== AT ==
public net.minecraft.server.level.ServerChunkCache mainThread
public net.minecraft.server.level.ServerLevel chunkSource
public org.bukkit.craftbukkit.inventory.CraftItemStack handle
public net.minecraft.server.level.ChunkMap getVisibleChunkIfPresent(J)Lnet/minecraft/server/level/ChunkHolder;
public net.minecraft.server.level.ServerChunkCache mainThreadProcessor
public net.minecraft.server.level.ServerChunkCache$MainThreadExecutor
public net.minecraft.world.level.chunk.LevelChunkSection states
This commit is contained in:
Aikar
2016-03-28 20:55:47 -04:00
parent a82a09d198
commit b01c811c2f
81 changed files with 6261 additions and 473 deletions

View File

@@ -107,11 +107,10 @@
private static final int OVERLOADED_TICKS_THRESHOLD = 20;
private static final long OVERLOADED_WARNING_INTERVAL_NANOS = 10L * TimeUtil.NANOSECONDS_PER_SECOND;
private static final int OVERLOADED_TICKS_WARNING_INTERVAL = 100;
@@ -276,6 +301,26 @@
private static final AtomicReference<RuntimeException> fatalException = new AtomicReference();
@@ -277,6 +302,26 @@
private final SuppressedExceptionCollector suppressedExceptions;
private final DiscontinuousFrame tickFrame;
+
+ // CraftBukkit start
+ public final WorldLoader.DataLoadContext worldLoader;
+ public org.bukkit.craftbukkit.CraftServer server;
@@ -131,9 +130,10 @@
+ public final double[] recentTps = new double[ 3 ];
+ // Spigot end
+ public final io.papermc.paper.configuration.PaperConfigurations paperConfigurations; // Paper - add paper configuration files
+
public static <S extends MinecraftServer> S spin(Function<Thread, S> serverFactory) {
AtomicReference<S> atomicreference = new AtomicReference();
Thread thread = new Thread(() -> {
@@ -290,14 +335,14 @@
thread.setPriority(8);
}
@@ -513,8 +513,7 @@
- }
-
- worldborder.applySettings(iworlddataserver.getWorldBorder());
- }
+ }
}
+ // CraftBukkit end
private static void setInitialSpawn(ServerLevel world, ServerLevelData worldProperties, boolean bonusChest, boolean debugWorld) {
@@ -671,11 +670,14 @@
}
MinecraftServer.LOGGER.info("Saving worlds");
@@ -693,6 +987,12 @@
@@ -693,6 +987,15 @@
} catch (IOException ioexception1) {
MinecraftServer.LOGGER.error("Failed to unlock level {}", this.storageSource.getLevelId(), ioexception1);
}
+ // Spigot start
+ io.papermc.paper.util.MCUtil.ASYNC_EXECUTOR.shutdown(); // Paper
+ try { io.papermc.paper.util.MCUtil.ASYNC_EXECUTOR.awaitTermination(30, java.util.concurrent.TimeUnit.SECONDS); // Paper
+ } catch (java.lang.InterruptedException ignored) {} // Paper
+ if (org.spigotmc.SpigotConfig.saveUserCacheOnStopOnly) {
+ MinecraftServer.LOGGER.info("Saving usercache.json");
+ this.getProfileCache().save();
@@ -684,7 +686,7 @@
}
@@ -720,6 +1020,13 @@
@@ -720,6 +1023,13 @@
}
@@ -698,7 +700,7 @@
protected void runServer() {
try {
if (!this.initServer()) {
@@ -727,9 +1034,12 @@
@@ -727,9 +1037,12 @@
}
this.nextTickTimeNanos = Util.getNanos();
@@ -712,7 +714,7 @@
while (this.running) {
long i;
@@ -744,11 +1054,23 @@
@@ -744,11 +1057,23 @@
if (j > MinecraftServer.OVERLOADED_THRESHOLD_NANOS + 20L * i && this.nextTickTimeNanos - this.lastOverloadWarningNanos >= MinecraftServer.OVERLOADED_WARNING_INTERVAL_NANOS + 100L * i) {
long k = j / i;
@@ -736,7 +738,7 @@
boolean flag = i == 0L;
@@ -757,6 +1079,7 @@
@@ -757,6 +1082,7 @@
this.debugCommandProfiler = new MinecraftServer.TimeProfiler(Util.getNanos(), this.tickCount);
}
@@ -744,7 +746,7 @@
this.nextTickTimeNanos += i;
try {
@@ -830,6 +1153,13 @@
@@ -830,6 +1156,13 @@
this.services.profileCache().clearExecutor();
}
@@ -758,7 +760,7 @@
this.onServerExit();
}
@@ -889,9 +1219,16 @@
@@ -889,9 +1222,16 @@
}
private boolean haveTime() {
@@ -776,7 +778,7 @@
public static boolean throwIfFatalException() {
RuntimeException runtimeexception = (RuntimeException) MinecraftServer.fatalException.get();
@@ -903,7 +1240,7 @@
@@ -903,7 +1243,7 @@
}
public static void setFatalException(RuntimeException exception) {
@@ -785,7 +787,7 @@
}
@Override
@@ -977,7 +1314,7 @@
@@ -977,7 +1317,7 @@
}
}
@@ -794,7 +796,7 @@
Profiler.get().incrementCounter("runTask");
super.doRunTask(ticktask);
}
@@ -1025,6 +1362,7 @@
@@ -1025,6 +1365,7 @@
}
public void tickServer(BooleanSupplier shouldKeepTicking) {
@@ -802,7 +804,7 @@
long i = Util.getNanos();
int j = this.pauseWhileEmptySeconds() * 20;
@@ -1041,11 +1379,13 @@
@@ -1041,11 +1382,13 @@
this.autoSave();
}
@@ -816,7 +818,7 @@
++this.tickCount;
this.tickRateManager.tick();
this.tickChildren(shouldKeepTicking);
@@ -1055,7 +1395,7 @@
@@ -1055,7 +1398,7 @@
}
--this.ticksUntilAutosave;
@@ -825,7 +827,7 @@
this.autoSave();
}
@@ -1071,10 +1411,13 @@
@@ -1071,10 +1414,13 @@
this.smoothedTickTimeMillis = this.smoothedTickTimeMillis * 0.8F + (float) k / (float) TimeUtil.NANOSECONDS_PER_MILLISECOND * 0.19999999F;
this.logTickMethodTime(i);
gameprofilerfiller.pop();
@@ -840,7 +842,7 @@
MinecraftServer.LOGGER.debug("Autosave started");
ProfilerFiller gameprofilerfiller = Profiler.get();
@@ -1082,6 +1425,7 @@
@@ -1082,6 +1428,7 @@
this.saveEverything(true, false, false);
gameprofilerfiller.pop();
MinecraftServer.LOGGER.debug("Autosave finished");
@@ -848,7 +850,7 @@
}
private void logTickMethodTime(long tickStartTime) {
@@ -1154,11 +1498,34 @@
@@ -1154,11 +1501,34 @@
this.getPlayerList().getPlayers().forEach((entityplayer) -> {
entityplayer.connection.suspendFlushing();
});
@@ -883,7 +885,7 @@
while (iterator.hasNext()) {
ServerLevel worldserver = (ServerLevel) iterator.next();
@@ -1167,16 +1534,20 @@
@@ -1167,16 +1537,20 @@
return s + " " + String.valueOf(worldserver.dimension().location());
});
@@ -904,7 +906,7 @@
} catch (Throwable throwable) {
CrashReport crashreport = CrashReport.forThrowable(throwable, "Exception ticking world");
@@ -1189,18 +1560,24 @@
@@ -1189,18 +1563,24 @@
}
gameprofilerfiller.popPush("connection");
@@ -929,7 +931,7 @@
gameprofilerfiller.popPush("send chunks");
iterator = this.playerList.getPlayers().iterator();
@@ -1265,7 +1642,23 @@
@@ -1265,7 +1645,23 @@
@Nullable
public ServerLevel getLevel(ResourceKey<Level> key) {
return (ServerLevel) this.levels.get(key);
@@ -953,7 +955,7 @@
public Set<ResourceKey<Level>> levelKeys() {
return this.levels.keySet();
@@ -1296,7 +1689,7 @@
@@ -1296,7 +1692,7 @@
@DontObfuscate
public String getServerModName() {
@@ -962,7 +964,7 @@
}
public SystemReport fillSystemReport(SystemReport details) {
@@ -1507,7 +1900,7 @@
@@ -1507,7 +1903,7 @@
}
public ServerConnectionListener getConnection() {
@@ -971,7 +973,7 @@
}
public boolean isReady() {
@@ -1634,11 +2027,11 @@
@@ -1634,11 +2030,11 @@
public CompletableFuture<Void> reloadResources(Collection<String> dataPacks) {
CompletableFuture<Void> completablefuture = CompletableFuture.supplyAsync(() -> {
@@ -985,7 +987,7 @@
}, this).thenCompose((immutablelist) -> {
MultiPackResourceManager resourcemanager = new MultiPackResourceManager(PackType.SERVER_DATA, immutablelist);
List<Registry.PendingTags<?>> list = TagLoader.loadTagsForExistingRegistries(resourcemanager, this.registries.compositeAccess());
@@ -1654,6 +2047,7 @@
@@ -1654,6 +2050,7 @@
}).thenAcceptAsync((minecraftserver_reloadableresources) -> {
this.resources.close();
this.resources = minecraftserver_reloadableresources;
@@ -993,7 +995,7 @@
this.packRepository.setSelected(dataPacks);
WorldDataConfiguration worlddataconfiguration = new WorldDataConfiguration(MinecraftServer.getSelectedPacks(this.packRepository, true), this.worldData.enabledFeatures());
@@ -1952,7 +2346,7 @@
@@ -1952,7 +2349,7 @@
final List<String> list = Lists.newArrayList();
final GameRules gamerules = this.getGameRules();
@@ -1002,7 +1004,7 @@
@Override
public <T extends GameRules.Value<T>> void visit(GameRules.Key<T> key, GameRules.Type<T> type) {
list.add(String.format(Locale.ROOT, "%s=%s\n", key.getId(), gamerules.getRule(key)));
@@ -2058,7 +2452,7 @@
@@ -2058,7 +2455,7 @@
try {
label51:
{
@@ -1011,7 +1013,7 @@
try {
arraylist = Lists.newArrayList(NativeModuleLister.listModules());
@@ -2105,8 +2499,24 @@
@@ -2105,8 +2502,24 @@
if (bufferedwriter != null) {
bufferedwriter.close();
}
@@ -1036,7 +1038,7 @@
private ProfilerFiller createProfiler() {
if (this.willStartRecordingMetrics) {
@@ -2235,6 +2645,11 @@
@@ -2235,6 +2648,11 @@
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/server/level/ChunkHolder.java
+++ b/net/minecraft/server/level/ChunkHolder.java
@@ -28,6 +28,10 @@
@@ -28,14 +28,18 @@
import net.minecraft.world.level.chunk.status.ChunkStatus;
import net.minecraft.world.level.lighting.LevelLightEngine;
@@ -11,6 +11,17 @@
public class ChunkHolder extends GenerationChunkHolder {
public static final ChunkResult<LevelChunk> UNLOADED_LEVEL_CHUNK = ChunkResult.error("Unloaded level chunk");
private static final CompletableFuture<ChunkResult<LevelChunk>> UNLOADED_LEVEL_CHUNK_FUTURE = CompletableFuture.completedFuture(ChunkHolder.UNLOADED_LEVEL_CHUNK);
private final LevelHeightAccessor levelHeightAccessor;
- private volatile CompletableFuture<ChunkResult<LevelChunk>> fullChunkFuture;
- private volatile CompletableFuture<ChunkResult<LevelChunk>> tickingChunkFuture;
- private volatile CompletableFuture<ChunkResult<LevelChunk>> entityTickingChunkFuture;
+ private volatile CompletableFuture<ChunkResult<LevelChunk>> fullChunkFuture; private int fullChunkCreateCount; private volatile boolean isFullChunkReady; // Paper - cache chunk ticking stage
+ private volatile CompletableFuture<ChunkResult<LevelChunk>> tickingChunkFuture; private volatile boolean isTickingReady; // Paper - cache chunk ticking stage
+ private volatile CompletableFuture<ChunkResult<LevelChunk>> entityTickingChunkFuture; private volatile boolean isEntityTickingReady; // Paper - cache chunk ticking stage
public int oldTicketLevel;
private int ticketLevel;
private int queueLevel;
@@ -58,9 +62,9 @@
this.entityTickingChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE;
this.blockChangedLightSectionFilter = new BitSet();
@@ -24,12 +35,10 @@
this.levelHeightAccessor = world;
this.lightEngine = lightingProvider;
this.onLevelChange = levelUpdateListener;
@@ -70,7 +74,19 @@
this.queueLevel = this.oldTicketLevel;
this.setTicketLevel(level);
@@ -72,6 +76,18 @@
this.changedBlocksPerSection = new ShortSet[world.getSectionsCount()];
+ }
+
}
+ // CraftBukkit start
+ public LevelChunk getFullChunkNow() {
+ // Note: We use the oldTicketLevel for isLoaded checks.
@@ -39,16 +48,19 @@
+
+ public LevelChunk getFullChunkNowUnchecked() {
+ return (LevelChunk) this.getChunkIfPresentUnchecked(ChunkStatus.FULL);
}
+ }
+ // CraftBukkit end
+
public CompletableFuture<ChunkResult<LevelChunk>> getTickingChunkFuture() {
return this.tickingChunkFuture;
@@ -86,7 +102,7 @@
}
@@ -85,8 +101,8 @@
}
@Nullable
public LevelChunk getTickingChunk() {
- public LevelChunk getTickingChunk() {
- return (LevelChunk) ((ChunkResult) this.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).orElse((Object) null);
+ public final LevelChunk getTickingChunk() { // Paper - final for inline
+ return (LevelChunk) ((ChunkResult) this.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).orElse(null); // CraftBukkit - decompile error
}
@@ -83,12 +95,10 @@
});
});
}
@@ -299,7 +319,39 @@
private void demoteFullChunk(ChunkMap chunkLoadingManager, FullChunkStatus target) {
this.pendingFullStateConfirmation.cancel(false);
@@ -301,6 +321,38 @@
chunkLoadingManager.onFullChunkStatusChange(this.pos, target);
+ }
+
}
+ // CraftBukkit start
+ // ChunkUnloadEvent: Called before the chunk is unloaded: isChunkLoaded is still true and chunk can still be modified by plugins.
+ // SPIGOT-7780: Moved out of updateFutures to call all chunk unload events before calling updateHighestAllowedStatus for all chunks
@@ -118,12 +128,95 @@
+ // Run callback right away if the future was already done
+ playerchunkmap.callbackExecutor.run();
+ }
}
+ }
+ // CraftBukkit end
+
protected void updateFutures(ChunkMap chunkLoadingManager, Executor executor) {
FullChunkStatus fullchunkstatus = ChunkLevel.fullStatus(this.oldTicketLevel);
@@ -357,6 +409,26 @@
FullChunkStatus fullchunkstatus1 = ChunkLevel.fullStatus(this.ticketLevel);
@@ -309,12 +361,28 @@
this.wasAccessibleSinceLastSave |= flag1;
if (!flag && flag1) {
+ int expectCreateCount = ++this.fullChunkCreateCount; // Paper
this.fullChunkFuture = chunkLoadingManager.prepareAccessibleChunk(this);
this.scheduleFullChunkPromotion(chunkLoadingManager, this.fullChunkFuture, executor, FullChunkStatus.FULL);
+ // Paper start - cache ticking ready status
+ this.fullChunkFuture.thenAccept(chunkResult -> {
+ chunkResult.ifSuccess(chunk -> {
+ if (ChunkHolder.this.fullChunkCreateCount == expectCreateCount) {
+ ChunkHolder.this.isFullChunkReady = true;
+ ca.spottedleaf.moonrise.common.util.ChunkSystem.onChunkBorder(chunk, this);
+ }
+ });
+ });
+ // Paper end - cache ticking ready status
this.addSaveDependency(this.fullChunkFuture);
}
if (flag && !flag1) {
+ // Paper start
+ if (this.isFullChunkReady) {
+ ca.spottedleaf.moonrise.common.util.ChunkSystem.onChunkNotBorder(this.fullChunkFuture.join().orElseThrow(IllegalStateException::new), this); // Paper
+ }
+ // Paper end
this.fullChunkFuture.complete(ChunkHolder.UNLOADED_LEVEL_CHUNK);
this.fullChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE;
}
@@ -325,11 +393,25 @@
if (!flag2 && flag3) {
this.tickingChunkFuture = chunkLoadingManager.prepareTickingChunk(this);
this.scheduleFullChunkPromotion(chunkLoadingManager, this.tickingChunkFuture, executor, FullChunkStatus.BLOCK_TICKING);
+ // Paper start - cache ticking ready status
+ this.tickingChunkFuture.thenAccept(chunkResult -> {
+ chunkResult.ifSuccess(chunk -> {
+ // note: Here is a very good place to add callbacks to logic waiting on this.
+ ChunkHolder.this.isTickingReady = true;
+ ca.spottedleaf.moonrise.common.util.ChunkSystem.onChunkTicking(chunk, this);
+ });
+ });
+ // Paper end
this.addSaveDependency(this.tickingChunkFuture);
}
if (flag2 && !flag3) {
- this.tickingChunkFuture.complete(ChunkHolder.UNLOADED_LEVEL_CHUNK);
+ // Paper start
+ if (this.isTickingReady) {
+ ca.spottedleaf.moonrise.common.util.ChunkSystem.onChunkNotTicking(this.tickingChunkFuture.join().orElseThrow(IllegalStateException::new), this); // Paper
+ }
+ // Paper end
+ this.tickingChunkFuture.complete(ChunkHolder.UNLOADED_LEVEL_CHUNK); this.isTickingReady = false; // Paper - cache chunk ticking stage
this.tickingChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE;
}
@@ -343,11 +425,24 @@
this.entityTickingChunkFuture = chunkLoadingManager.prepareEntityTickingChunk(this);
this.scheduleFullChunkPromotion(chunkLoadingManager, this.entityTickingChunkFuture, executor, FullChunkStatus.ENTITY_TICKING);
+ // Paper start - cache ticking ready status
+ this.entityTickingChunkFuture.thenAccept(chunkResult -> {
+ chunkResult.ifSuccess(chunk -> {
+ ChunkHolder.this.isEntityTickingReady = true;
+ ca.spottedleaf.moonrise.common.util.ChunkSystem.onChunkEntityTicking(chunk, this);
+ });
+ });
+ // Paper end
this.addSaveDependency(this.entityTickingChunkFuture);
}
if (flag4 && !flag5) {
- this.entityTickingChunkFuture.complete(ChunkHolder.UNLOADED_LEVEL_CHUNK);
+ // Paper start
+ if (this.isEntityTickingReady) {
+ ca.spottedleaf.moonrise.common.util.ChunkSystem.onChunkNotEntityTicking(this.entityTickingChunkFuture.join().orElseThrow(IllegalStateException::new), this);
+ }
+ // Paper end
+ this.entityTickingChunkFuture.complete(ChunkHolder.UNLOADED_LEVEL_CHUNK); this.isEntityTickingReady = false; // Paper - cache chunk ticking stage
this.entityTickingChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE;
}
@@ -357,6 +452,26 @@
this.onLevelChange.onLevelChange(this.pos, this::getQueueLevel, this.ticketLevel, this::setQueueLevel);
this.oldTicketLevel = this.ticketLevel;

View File

@@ -11,11 +11,10 @@
public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider, GeneratingChunkMap {
private static final ChunkResult<List<ChunkAccess>> UNLOADED_CHUNK_LIST_RESULT = ChunkResult.error("Unloaded chunks found in range");
@@ -148,6 +152,27 @@
private final AtomicInteger activeChunkWrites;
@@ -149,6 +153,33 @@
public int serverViewDistance;
private final WorldGenContext worldGenContext;
+
+ // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback()
+ public final CallbackExecutor callbackExecutor = new CallbackExecutor();
+ public static final class CallbackExecutor implements java.util.concurrent.Executor, Runnable {
@@ -36,10 +35,17 @@
+ }
+ };
+ // CraftBukkit end
+
+ // Paper start
+ public final ChunkHolder getUnloadingChunkHolder(int chunkX, int chunkZ) {
+ return this.pendingUnloads.get(ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkKey(chunkX, chunkZ));
+ }
+ // Paper end
+
public ChunkMap(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureTemplateManager structureTemplateManager, Executor executor, BlockableEventLoop<Runnable> mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier<DimensionDataStorage> persistentStateManagerFactory, int viewDistance, boolean dsync) {
super(new RegionStorageInfo(session.getLevelId(), world.dimension(), "chunk"), session.getDimensionPath(world.dimension()).resolve("region"), dataFixer, dsync);
@@ -170,13 +195,19 @@
this.visibleChunkMap = this.updatingChunkMap.clone();
@@ -170,13 +201,19 @@
RegistryAccess iregistrycustom = world.registryAccess();
long j = world.getSeed();
@@ -61,7 +67,20 @@
this.mainThreadExecutor = mainThreadExecutor;
ConsecutiveExecutor consecutiveexecutor = new ConsecutiveExecutor(executor, "worldgen");
@@ -325,7 +356,7 @@
@@ -198,6 +235,12 @@
this.chunksToEagerlySave.add(pos.toLong());
}
+ // Paper start
+ public int getMobCountNear(final ServerPlayer player, final net.minecraft.world.entity.MobCategory mobCategory) {
+ return -1;
+ }
+ // Paper end
+
protected ChunkGenerator generator() {
return this.worldGenContext.generator();
}
@@ -325,7 +368,7 @@
throw this.debugFuturesAndCreateReportedException(new IllegalStateException("At least one of the chunk futures were null"), "n/a");
}
@@ -70,7 +89,131 @@
if (ichunkaccess == null) {
return ChunkMap.UNLOADED_CHUNK_LIST_RESULT;
@@ -977,7 +1008,8 @@
@@ -354,9 +397,9 @@
};
stringbuilder.append("Updating:").append(System.lineSeparator());
- this.updatingChunkMap.values().forEach(consumer);
+ ca.spottedleaf.moonrise.common.util.ChunkSystem.getUpdatingChunkHolders(this.level).forEach(consumer); // Paper
stringbuilder.append("Visible:").append(System.lineSeparator());
- this.visibleChunkMap.values().forEach(consumer);
+ ca.spottedleaf.moonrise.common.util.ChunkSystem.getVisibleChunkHolders(this.level).forEach(consumer); // Paper
CrashReport crashreport = CrashReport.forThrowable(exception, "Chunk loading");
CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Chunk loading");
@@ -398,6 +441,9 @@
holder.setTicketLevel(level);
} else {
holder = new ChunkHolder(new ChunkPos(pos), level, this.level, this.lightEngine, this::onLevelChange, this);
+ // Paper start
+ ca.spottedleaf.moonrise.common.util.ChunkSystem.onChunkHolderCreate(this.level, holder);
+ // Paper end
}
this.updatingChunkMap.put(pos, holder);
@@ -427,7 +473,7 @@
protected void saveAllChunks(boolean flush) {
if (flush) {
- List<ChunkHolder> list = this.visibleChunkMap.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).peek(ChunkHolder::refreshAccessibility).toList();
+ List<ChunkHolder> list = ca.spottedleaf.moonrise.common.util.ChunkSystem.getVisibleChunkHolders(this.level).stream().filter(ChunkHolder::wasAccessibleSinceLastSave).peek(ChunkHolder::refreshAccessibility).toList(); // Paper
MutableBoolean mutableboolean = new MutableBoolean();
do {
@@ -453,7 +499,7 @@
} else {
this.nextChunkSaveTime.clear();
long i = Util.getMillis();
- ObjectIterator objectiterator = this.visibleChunkMap.values().iterator();
+ Iterator<ChunkHolder> objectiterator = ca.spottedleaf.moonrise.common.util.ChunkSystem.getVisibleChunkHolders(this.level).iterator(); // Paper
while (objectiterator.hasNext()) {
ChunkHolder playerchunk = (ChunkHolder) objectiterator.next();
@@ -478,7 +524,7 @@
}
public boolean hasWork() {
- return this.lightEngine.hasLightWork() || !this.pendingUnloads.isEmpty() || !this.updatingChunkMap.isEmpty() || this.poiManager.hasWork() || !this.toDrop.isEmpty() || !this.unloadQueue.isEmpty() || this.worldgenTaskDispatcher.hasWork() || this.lightTaskDispatcher.hasWork() || this.distanceManager.hasTickets();
+ return this.lightEngine.hasLightWork() || !this.pendingUnloads.isEmpty() || ca.spottedleaf.moonrise.common.util.ChunkSystem.hasAnyChunkHolders(this.level) || !this.updatingChunkMap.isEmpty() || this.poiManager.hasWork() || !this.toDrop.isEmpty() || !this.unloadQueue.isEmpty() || this.worldgenTaskDispatcher.hasWork() || this.lightTaskDispatcher.hasWork() || this.distanceManager.hasTickets();
}
private void processUnloads(BooleanSupplier shouldKeepTicking) {
@@ -537,8 +583,11 @@
this.scheduleUnload(pos, chunk);
} else {
ChunkAccess ichunkaccess = chunk.getLatestChunk();
-
- if (this.pendingUnloads.remove(pos, chunk) && ichunkaccess != null) {
+ // Paper start
+ boolean removed;
+ if ((removed = this.pendingUnloads.remove(pos, chunk)) && ichunkaccess != null) {
+ ca.spottedleaf.moonrise.common.util.ChunkSystem.onChunkHolderDelete(this.level, chunk);
+ // Paper end
LevelChunk chunk1;
if (ichunkaccess instanceof LevelChunk) {
@@ -556,7 +605,9 @@
this.lightEngine.tryScheduleUpdate();
this.progressListener.onStatusChange(ichunkaccess.getPos(), (ChunkStatus) null);
this.nextChunkSaveTime.remove(ichunkaccess.getPos().toLong());
- }
+ } else if (removed) { // Paper start
+ ca.spottedleaf.moonrise.common.util.ChunkSystem.onChunkHolderDelete(this.level, chunk);
+ } // Paper end
}
};
@@ -905,7 +956,7 @@
}
}
- protected void setServerViewDistance(int watchDistance) {
+ public void setServerViewDistance(int watchDistance) { // Paper - public
int j = Mth.clamp(watchDistance, 2, 32);
if (j != this.serverViewDistance) {
@@ -922,7 +973,7 @@
}
- int getPlayerViewDistance(ServerPlayer player) {
+ public int getPlayerViewDistance(ServerPlayer player) { // Paper - public
return Mth.clamp(player.requestedViewDistance(), 2, this.serverViewDistance);
}
@@ -951,7 +1002,7 @@
}
public int size() {
- return this.visibleChunkMap.size();
+ return ca.spottedleaf.moonrise.common.util.ChunkSystem.getVisibleChunkHolderCount(this.level); // Paper
}
public DistanceManager getDistanceManager() {
@@ -959,25 +1010,26 @@
}
protected Iterable<ChunkHolder> getChunks() {
- return Iterables.unmodifiableIterable(this.visibleChunkMap.values());
+ return Iterables.unmodifiableIterable(ca.spottedleaf.moonrise.common.util.ChunkSystem.getVisibleChunkHolders(this.level)); // Paper
}
void dumpChunks(Writer writer) throws IOException {
CsvOutput csvwriter = CsvOutput.builder().addColumn("x").addColumn("z").addColumn("level").addColumn("in_memory").addColumn("status").addColumn("full_status").addColumn("accessible_ready").addColumn("ticking_ready").addColumn("entity_ticking_ready").addColumn("ticket").addColumn("spawning").addColumn("block_entity_count").addColumn("ticking_ticket").addColumn("ticking_level").addColumn("block_ticks").addColumn("fluid_ticks").build(writer);
TickingTracker tickingtracker = this.distanceManager.tickingTracker();
- ObjectBidirectionalIterator objectbidirectionaliterator = this.visibleChunkMap.long2ObjectEntrySet().iterator();
+ Iterator<ChunkHolder> objectbidirectionaliterator = ca.spottedleaf.moonrise.common.util.ChunkSystem.getVisibleChunkHolders(this.level).iterator(); // Paper
while (objectbidirectionaliterator.hasNext()) {
- Entry<ChunkHolder> entry = (Entry) objectbidirectionaliterator.next();
- long i = entry.getLongKey();
+ ChunkHolder playerchunk = objectbidirectionaliterator.next(); // Paper
+ long i = playerchunk.pos.toLong(); // Paper
ChunkPos chunkcoordintpair = new ChunkPos(i);
- ChunkHolder playerchunk = (ChunkHolder) entry.getValue();
+ // Paper - move up
Optional<ChunkAccess> optional = Optional.ofNullable(playerchunk.getLatestChunk());
Optional<LevelChunk> optional1 = optional.flatMap((ichunkaccess) -> {
return ichunkaccess instanceof LevelChunk ? Optional.of((LevelChunk) ichunkaccess) : Optional.empty();
});
@@ -80,7 +223,7 @@
return chunk.getBlockEntities().size();
}).orElse(0), tickingtracker.getTicketDebugString(i), tickingtracker.getLevel(i), optional1.map((chunk) -> {
return chunk.getBlockTicks().count();
@@ -990,7 +1022,7 @@
@@ -990,7 +1042,7 @@
private static String printFuture(CompletableFuture<ChunkResult<LevelChunk>> future) {
try {
@@ -89,7 +232,7 @@
return chunkresult != null ? (chunkresult.isSuccess() ? "done" : "unloaded") : "not completed";
} catch (CompletionException completionexception) {
@@ -1002,12 +1034,14 @@
@@ -1002,12 +1054,14 @@
private CompletableFuture<Optional<CompoundTag>> readChunk(ChunkPos chunkPos) {
return this.read(chunkPos).thenApplyAsync((optional) -> {
@@ -107,7 +250,7 @@
}
void forEachSpawnCandidateChunk(Consumer<ChunkHolder> callback) {
@@ -1025,10 +1059,27 @@
@@ -1025,10 +1079,27 @@
}
public boolean anyPlayerCloseEnoughForSpawning(ChunkPos pos) {
@@ -136,7 +279,7 @@
Iterator iterator = this.playerMap.getAllPlayers().iterator();
ServerPlayer entityplayer;
@@ -1039,7 +1090,7 @@
@@ -1039,7 +1110,7 @@
}
entityplayer = (ServerPlayer) iterator.next();
@@ -145,7 +288,7 @@
return true;
}
@@ -1056,7 +1107,7 @@
@@ -1056,7 +1127,7 @@
while (iterator.hasNext()) {
ServerPlayer entityplayer = (ServerPlayer) iterator.next();
@@ -154,7 +297,7 @@
builder.add(entityplayer);
}
}
@@ -1065,13 +1116,13 @@
@@ -1065,13 +1136,13 @@
}
}
@@ -172,7 +315,7 @@
}
}
@@ -1215,9 +1266,11 @@
@@ -1215,9 +1286,11 @@
}
public void addEntity(Entity entity) {
@@ -184,7 +327,7 @@
if (i != 0) {
int j = entitytypes.updateInterval();
@@ -1250,6 +1303,7 @@
@@ -1250,6 +1323,7 @@
}
protected void removeEntity(Entity entity) {
@@ -192,7 +335,16 @@
if (entity instanceof ServerPlayer entityplayer) {
this.updatePlayerStatus(entityplayer, false);
ObjectIterator objectiterator = this.entityMap.values().iterator();
@@ -1424,7 +1478,7 @@
@@ -1391,7 +1465,7 @@
});
}
- private class ChunkDistanceManager extends DistanceManager {
+ public class ChunkDistanceManager extends DistanceManager { // Paper - public
protected ChunkDistanceManager(final Executor workerExecutor, final Executor mainThreadExecutor) {
super(workerExecutor, mainThreadExecutor);
@@ -1424,7 +1498,7 @@
public final Set<ServerPlayerConnection> seenBy = Sets.newIdentityHashSet();
public TrackedEntity(final Entity entity, final int i, final int j, final boolean flag) {
@@ -201,7 +353,7 @@
this.entity = entity;
this.range = i;
this.lastSectionPos = SectionPos.of((EntityAccess) entity);
@@ -1469,6 +1523,7 @@
@@ -1469,6 +1543,7 @@
}
public void removePlayer(ServerPlayer player) {
@@ -209,7 +361,7 @@
if (this.seenBy.remove(player.connection)) {
this.serverEntity.removePairing(player);
}
@@ -1476,6 +1531,7 @@
@@ -1476,6 +1551,7 @@
}
public void updatePlayer(ServerPlayer player) {
@@ -217,7 +369,7 @@
if (player != this.entity) {
Vec3 vec3d = player.position().subtract(this.entity.position());
int i = ChunkMap.this.getPlayerViewDistance(player);
@@ -1484,6 +1540,11 @@
@@ -1484,6 +1560,11 @@
double d2 = d0 * d0;
boolean flag = d1 <= d2 && this.entity.broadcastToPlayer(player) && ChunkMap.this.isChunkTracked(player, this.entity.chunkPosition().x, this.entity.chunkPosition().z);

View File

@@ -108,10 +108,21 @@
objectset.remove(player);
if (objectset.isEmpty()) {
@@ -391,6 +418,26 @@
return !this.tickets.isEmpty();
@@ -358,7 +385,7 @@
}
public void removeTicketsOnClosing() {
- ImmutableSet<TicketType<?>> immutableset = ImmutableSet.of(TicketType.UNKNOWN);
+ ImmutableSet<TicketType<?>> immutableset = ImmutableSet.of(TicketType.UNKNOWN, TicketType.POST_TELEPORT, TicketType.FUTURE_AWAIT); // Paper - add additional tickets to preserve
ObjectIterator<Entry<SortedArraySet<Ticket<?>>>> objectiterator = this.tickets.long2ObjectEntrySet().fastIterator();
while (objectiterator.hasNext()) {
@@ -389,7 +416,27 @@
public boolean hasTickets() {
return !this.tickets.isEmpty();
+ }
+
+ // CraftBukkit start
+ public <T> void removeAllTicketsFor(TicketType<T> ticketType, int ticketLevel, T ticketIdentifier) {
+ Ticket<T> target = new Ticket<>(ticketType, ticketLevel, ticketIdentifier);
@@ -129,9 +140,8 @@
+ }
+ }
+ }
+ }
}
+ // CraftBukkit end
+
private class ChunkTicketTracker extends ChunkTracker {
private static final int MAX_LEVEL = ChunkLevel.MAX_LEVEL + 1;

View File

@@ -1,6 +1,20 @@
--- a/net/minecraft/server/level/ServerChunkCache.java
+++ b/net/minecraft/server/level/ServerChunkCache.java
@@ -95,6 +95,16 @@
@@ -74,6 +74,13 @@
@Nullable
@VisibleForDebug
private NaturalSpawner.SpawnState lastSpawnState;
+ // Paper start
+ private final ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable<net.minecraft.world.level.chunk.LevelChunk> fullChunks = new ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable<>();
+ public int getFullChunksCount() {
+ return this.fullChunks.size();
+ }
+ long chunkFutureAwaitCounter;
+ // Paper end
public ServerChunkCache(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureTemplateManager structureTemplateManager, Executor workerExecutor, ChunkGenerator chunkGenerator, int viewDistance, int simulationDistance, boolean dsync, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier<DimensionDataStorage> persistentStateManagerFactory) {
this.level = world;
@@ -95,6 +102,64 @@
this.clearCache();
}
@@ -13,11 +27,59 @@
+ return chunk.getFullChunkNow() != null;
+ }
+ // CraftBukkit end
+ // Paper start
+ public void addLoadedChunk(LevelChunk chunk) {
+ this.fullChunks.put(chunk.coordinateKey, chunk);
+ }
+
+ public void removeLoadedChunk(LevelChunk chunk) {
+ this.fullChunks.remove(chunk.coordinateKey);
+ }
+
+ @Nullable
+ public ChunkAccess getChunkAtImmediately(int x, int z) {
+ ChunkHolder holder = this.chunkMap.getVisibleChunkIfPresent(ChunkPos.asLong(x, z));
+ if (holder == null) {
+ return null;
+ }
+
+ return holder.getLatestChunk();
+ }
+
+ public <T> void addTicketAtLevel(TicketType<T> ticketType, ChunkPos chunkPos, int ticketLevel, T identifier) {
+ this.distanceManager.addTicket(ticketType, chunkPos, ticketLevel, identifier);
+ }
+
+ public <T> void removeTicketAtLevel(TicketType<T> ticketType, ChunkPos chunkPos, int ticketLevel, T identifier) {
+ this.distanceManager.removeTicket(ticketType, chunkPos, ticketLevel, identifier);
+ }
+
+ // "real" get chunk if loaded
+ // Note: Partially copied from the getChunkAt method below
+ @Nullable
+ public LevelChunk getChunkAtIfCachedImmediately(int x, int z) {
+ long k = ChunkPos.asLong(x, z);
+
+ // Note: Bypass cache since we need to check ticket level, and to make this MT-Safe
+
+ ChunkHolder playerChunk = this.getVisibleChunkIfPresent(k);
+ if (playerChunk == null) {
+ return null;
+ }
+
+ return playerChunk.getFullChunkNowUnchecked();
+ }
+
+ @Nullable
+ public LevelChunk getChunkAtIfLoadedImmediately(int x, int z) {
+ return this.fullChunks.get(ChunkPos.asLong(x, z));
+ }
+ // Paper end
+
@Override
public ThreadedLevelLightEngine getLightEngine() {
return this.lightEngine;
@@ -138,20 +148,22 @@
@@ -138,20 +203,22 @@
if (k == this.lastChunkPos[l] && leastStatus == this.lastChunkStatus[l]) {
ChunkAccess ichunkaccess = this.lastChunk[l];
@@ -42,7 +104,7 @@
if (ichunkaccess1 == null && create) {
throw (IllegalStateException) Util.pauseInIde(new IllegalStateException("Chunk not there when requested: " + chunkresult.getError()));
@@ -231,7 +243,15 @@
@@ -231,7 +298,15 @@
int l = ChunkLevel.byStatus(leastStatus);
ChunkHolder playerchunk = this.getVisibleChunkIfPresent(k);
@@ -59,7 +121,7 @@
this.distanceManager.addTicket(TicketType.UNKNOWN, chunkcoordintpair, l, chunkcoordintpair);
if (this.chunkAbsent(playerchunk, l)) {
ProfilerFiller gameprofilerfiller = Profiler.get();
@@ -250,7 +270,7 @@
@@ -250,7 +325,7 @@
}
private boolean chunkAbsent(@Nullable ChunkHolder holder, int maxLevel) {
@@ -68,7 +130,16 @@
}
@Override
@@ -309,30 +329,58 @@
@@ -279,7 +354,7 @@
return this.mainThreadProcessor.pollTask();
}
- boolean runDistanceManagerUpdates() {
+ public boolean runDistanceManagerUpdates() { // Paper - public
boolean flag = this.distanceManager.runAllUpdates(this.chunkMap);
boolean flag1 = this.chunkMap.promoteChunkMap();
@@ -309,30 +384,58 @@
@Override
public void close() throws IOException {
@@ -85,8 +156,8 @@
this.dataStorage.close();
this.lightEngine.close();
this.chunkMap.close();
+ }
+
}
+ // CraftBukkit start - modelled on below
+ public void purgeUnload() {
+ ProfilerFiller gameprofilerfiller = Profiler.get();
@@ -98,9 +169,9 @@
+ this.chunkMap.tick(() -> true);
+ gameprofilerfiller.pop();
+ this.clearCache();
}
+ }
+ // CraftBukkit end
+
@Override
public void tick(BooleanSupplier shouldKeepTicking, boolean tickChunks) {
ProfilerFiller gameprofilerfiller = Profiler.get();
@@ -129,7 +200,7 @@
gameprofilerfiller.pop();
this.clearCache();
}
@@ -401,14 +449,14 @@
@@ -401,14 +504,14 @@
this.lastSpawnState = spawnercreature_d;
profiler.popPush("spawnAndTick");
@@ -147,7 +218,7 @@
} else {
list1 = List.of();
}
@@ -420,12 +468,14 @@
@@ -420,12 +523,14 @@
ChunkPos chunkcoordintpair = chunk.getPos();
chunk.incrementInhabitedTime(timeDelta);
@@ -163,7 +234,7 @@
}
}
@@ -541,10 +591,16 @@
@@ -541,10 +646,16 @@
@Override
public void setSpawnSettings(boolean spawnMonsters) {
@@ -182,7 +253,7 @@
public String getChunkDebugData(ChunkPos pos) {
return this.chunkMap.getChunkDebugData(pos);
}
@@ -618,14 +674,20 @@
@@ -618,14 +729,20 @@
}
@Override

View File

@@ -62,7 +62,7 @@
private int lastSpawnChunkRadius;
final EntityTickList entityTickList = new EntityTickList();
public final PersistentEntitySectionManager<Entity> entityManager;
@@ -214,52 +227,87 @@
@@ -214,52 +227,184 @@
private final boolean tickTime;
private final RandomSequences randomSequences;
@@ -79,7 +79,7 @@
+ // CraftBukkit start
+ public final LevelStorageSource.LevelStorageAccess convertable;
+ public final UUID uuid;
+
+ public LevelChunk getChunkIfLoaded(int x, int z) {
+ return this.chunkSource.getChunk(x, z, false);
+ }
@@ -89,6 +89,103 @@
+ return this.convertable.dimensionType;
+ }
+
+ // Paper start
+ public final boolean areChunksLoadedForMove(AABB axisalignedbb) {
+ // copied code from collision methods, so that we can guarantee that they wont load chunks (we don't override
+ // ICollisionAccess methods for VoxelShapes)
+ // be more strict too, add a block (dumb plugins in move events?)
+ int minBlockX = Mth.floor(axisalignedbb.minX - 1.0E-7D) - 3;
+ int maxBlockX = Mth.floor(axisalignedbb.maxX + 1.0E-7D) + 3;
+
+ int minBlockZ = Mth.floor(axisalignedbb.minZ - 1.0E-7D) - 3;
+ int maxBlockZ = Mth.floor(axisalignedbb.maxZ + 1.0E-7D) + 3;
+
+ int minChunkX = minBlockX >> 4;
+ int maxChunkX = maxBlockX >> 4;
+
+ int minChunkZ = minBlockZ >> 4;
+ int maxChunkZ = maxBlockZ >> 4;
+
+ ServerChunkCache chunkProvider = this.getChunkSource();
+
+ for (int cx = minChunkX; cx <= maxChunkX; ++cx) {
+ for (int cz = minChunkZ; cz <= maxChunkZ; ++cz) {
+ if (chunkProvider.getChunkAtIfLoadedImmediately(cx, cz) == null) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ public final void loadChunksForMoveAsync(AABB axisalignedbb, ca.spottedleaf.concurrentutil.util.Priority priority,
+ java.util.function.Consumer<List<net.minecraft.world.level.chunk.ChunkAccess>> onLoad) {
+ if (Thread.currentThread() != this.thread) {
+ this.getChunkSource().mainThreadProcessor.execute(() -> {
+ this.loadChunksForMoveAsync(axisalignedbb, priority, onLoad);
+ });
+ return;
+ }
+ int minBlockX = Mth.floor(axisalignedbb.minX - 1.0E-7D) - 3;
+ int minBlockZ = Mth.floor(axisalignedbb.minZ - 1.0E-7D) - 3;
+
+ int maxBlockX = Mth.floor(axisalignedbb.maxX + 1.0E-7D) + 3;
+ int maxBlockZ = Mth.floor(axisalignedbb.maxZ + 1.0E-7D) + 3;
+
+ int minChunkX = minBlockX >> 4;
+ int minChunkZ = minBlockZ >> 4;
+
+ int maxChunkX = maxBlockX >> 4;
+ int maxChunkZ = maxBlockZ >> 4;
+
+ this.loadChunks(minChunkX, minChunkZ, maxChunkX, maxChunkZ, priority, onLoad);
+ }
+
+ public final void loadChunks(int minChunkX, int minChunkZ, int maxChunkX, int maxChunkZ,
+ ca.spottedleaf.concurrentutil.util.Priority priority,
+ java.util.function.Consumer<List<net.minecraft.world.level.chunk.ChunkAccess>> onLoad) {
+ List<net.minecraft.world.level.chunk.ChunkAccess> ret = new java.util.ArrayList<>();
+ it.unimi.dsi.fastutil.ints.IntArrayList ticketLevels = new it.unimi.dsi.fastutil.ints.IntArrayList();
+ ServerChunkCache chunkProvider = this.getChunkSource();
+
+ int requiredChunks = (maxChunkX - minChunkX + 1) * (maxChunkZ - minChunkZ + 1);
+ int[] loadedChunks = new int[1];
+
+ Long holderIdentifier = Long.valueOf(chunkProvider.chunkFutureAwaitCounter++);
+
+ java.util.function.Consumer<net.minecraft.world.level.chunk.ChunkAccess> consumer = (net.minecraft.world.level.chunk.ChunkAccess chunk) -> {
+ if (chunk != null) {
+ int ticketLevel = Math.max(33, chunkProvider.chunkMap.getUpdatingChunkIfPresent(chunk.getPos().toLong()).getTicketLevel());
+ ret.add(chunk);
+ ticketLevels.add(ticketLevel);
+ chunkProvider.addTicketAtLevel(TicketType.FUTURE_AWAIT, chunk.getPos(), ticketLevel, holderIdentifier);
+ }
+ if (++loadedChunks[0] == requiredChunks) {
+ try {
+ onLoad.accept(java.util.Collections.unmodifiableList(ret));
+ } finally {
+ for (int i = 0, len = ret.size(); i < len; ++i) {
+ ChunkPos chunkPos = ret.get(i).getPos();
+ int ticketLevel = ticketLevels.getInt(i);
+
+ chunkProvider.addTicketAtLevel(TicketType.UNKNOWN, chunkPos, ticketLevel, chunkPos);
+ chunkProvider.removeTicketAtLevel(TicketType.FUTURE_AWAIT, chunkPos, ticketLevel, holderIdentifier);
+ }
+ }
+ }
+ };
+
+ for (int cx = minChunkX; cx <= maxChunkX; ++cx) {
+ for (int cz = minChunkZ; cz <= maxChunkZ; ++cz) {
+ ca.spottedleaf.moonrise.common.util.ChunkSystem.scheduleChunkLoad(
+ this, cx, cz, net.minecraft.world.level.chunk.status.ChunkStatus.FULL, true, priority, consumer
+ );
+ }
+ }
+ }
+ // Paper end
+
+ // Add env and gen to constructor, IWorldDataServer -> WorldDataServer
+ public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PrimaryLevelData iworlddataserver, ResourceKey<Level> resourcekey, LevelStem worlddimension, ChunkProgressListener worldloadlistener, boolean flag, long i, List<CustomSpawner> list, boolean flag1, @Nullable RandomSequences randomsequences, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) {
+ super(iworlddataserver, resourcekey, minecraftserver.registryAccess(), worlddimension.type(), false, flag, i, minecraftserver.getMaxChainedNeighborUpdates(), gen, biomeProvider, env, spigotConfig -> minecraftserver.paperConfigurations.createWorldConfig(io.papermc.paper.configuration.PaperConfigurations.createWorldContextMap(convertable_conversionsession.levelDirectory.path(), iworlddataserver.getLevelName(), resourcekey.location(), spigotConfig, minecraftserver.registryAccess(), iworlddataserver.getGameRules()))); // Paper - create paper world configs
@@ -103,7 +200,7 @@
+ ChunkGenerator chunkgenerator = worlddimension.generator();
+ // CraftBukkit start
+ this.serverLevelData.setWorld(this);
+
+ if (biomeProvider != null) {
+ BiomeSource worldChunkManager = new CustomWorldChunkManager(this.getWorld(), biomeProvider, this.server.registryAccess().lookupOrThrow(Registries.BIOME));
+ if (chunkgenerator instanceof NoiseBasedChunkGenerator cga) {
@@ -174,7 +271,7 @@
}
/** @deprecated */
@@ -305,12 +353,20 @@
@@ -305,12 +450,20 @@
long j;
if (this.sleepStatus.areEnoughSleeping(i) && this.sleepStatus.areEnoughDeepSleeping(i, this.players)) {
@@ -198,7 +295,7 @@
if (this.getGameRules().getBoolean(GameRules.RULE_WEATHER_CYCLE) && this.isRaining()) {
this.resetWeatherCycle();
}
@@ -322,6 +378,7 @@
@@ -322,6 +475,7 @@
}
gameprofilerfiller.push("tickPending");
@@ -206,7 +303,7 @@
if (!this.isDebug() && flag) {
j = this.getGameTime();
gameprofilerfiller.push("blockTicks");
@@ -330,6 +387,7 @@
@@ -330,6 +484,7 @@
this.fluidTicks.tick(j, 65536, this::tickFluid);
gameprofilerfiller.pop();
}
@@ -214,7 +311,7 @@
gameprofilerfiller.popPush("raid");
if (flag) {
@@ -340,12 +398,14 @@
@@ -340,12 +495,14 @@
this.getChunkSource().tick(shouldKeepTicking, true);
gameprofilerfiller.popPush("blockEvents");
if (flag) {
@@ -230,7 +327,7 @@
if (flag1) {
this.resetEmptyTime();
@@ -353,12 +413,15 @@
@@ -353,12 +510,15 @@
if (flag1 || this.emptyTime++ < 300) {
gameprofilerfiller.push("entities");
@@ -246,7 +343,7 @@
this.entityTickList.forEach((entity) -> {
if (!entity.isRemoved()) {
if (!tickratemanager.isEntityFrozen(entity)) {
@@ -383,6 +446,8 @@
@@ -383,6 +543,8 @@
}
}
});
@@ -255,7 +352,7 @@
gameprofilerfiller.pop();
this.tickBlockEntities();
}
@@ -429,7 +494,7 @@
@@ -429,7 +591,7 @@
private void wakeUpAllPlayers() {
this.sleepStatus.removeAllSleepers();
@@ -264,7 +361,7 @@
entityplayer.stopSleepInBed(false, false);
});
}
@@ -442,7 +507,7 @@
@@ -442,7 +604,7 @@
ProfilerFiller gameprofilerfiller = Profiler.get();
gameprofilerfiller.push("thunder");
@@ -273,7 +370,7 @@
BlockPos blockposition = this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15));
if (this.isRainingAt(blockposition)) {
@@ -456,7 +521,7 @@
@@ -456,7 +618,7 @@
entityhorseskeleton.setTrap(true);
entityhorseskeleton.setAge(0);
entityhorseskeleton.setPos((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ());
@@ -282,7 +379,7 @@
}
}
@@ -465,7 +530,7 @@
@@ -465,7 +627,7 @@
if (entitylightning != null) {
entitylightning.moveTo(Vec3.atBottomCenterOf(blockposition));
entitylightning.setVisualOnly(flag1);
@@ -291,7 +388,7 @@
}
}
}
@@ -521,7 +586,7 @@
@@ -521,7 +683,7 @@
Biome biomebase = (Biome) this.getBiome(blockposition1).value();
if (biomebase.shouldFreeze(this, blockposition2)) {
@@ -300,7 +397,7 @@
}
if (this.isRaining()) {
@@ -537,10 +602,10 @@
@@ -537,10 +699,10 @@
BlockState iblockdata1 = (BlockState) iblockdata.setValue(SnowLayerBlock.LAYERS, j + 1);
Block.pushEntitiesUp(iblockdata, iblockdata1, this, blockposition1);
@@ -313,7 +410,7 @@
}
}
@@ -701,33 +766,67 @@
@@ -701,33 +863,67 @@
this.rainLevel = Mth.clamp(this.rainLevel, 0.0F, 1.0F);
}
@@ -331,9 +428,10 @@
if (flag != this.isRaining()) {
if (flag) {
- this.server.getPlayerList().broadcastAll(new ClientboundGameEventPacket(ClientboundGameEventPacket.STOP_RAINING, 0.0F));
+ this.server.getPlayerList().broadcastAll(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.STOP_RAINING, 0.0F));
} else {
- } else {
- this.server.getPlayerList().broadcastAll(new ClientboundGameEventPacket(ClientboundGameEventPacket.START_RAINING, 0.0F));
+ this.server.getPlayerList().broadcastAll(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.STOP_RAINING, 0.0F));
+ } else {
+ this.server.getPlayerList().broadcastAll(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.START_RAINING, 0.0F));
}
@@ -341,14 +439,14 @@
- this.server.getPlayerList().broadcastAll(new ClientboundGameEventPacket(ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, this.thunderLevel));
+ this.server.getPlayerList().broadcastAll(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.RAIN_LEVEL_CHANGE, this.rainLevel));
+ this.server.getPlayerList().broadcastAll(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.THUNDER_LEVEL_CHANGE, this.thunderLevel));
+ }
}
+ // */
+ for (int idx = 0; idx < this.players.size(); ++idx) {
+ if (((ServerPlayer) this.players.get(idx)).level() == this) {
+ ((ServerPlayer) this.players.get(idx)).tickWeather();
+ }
+ }
+
+ if (flag != this.isRaining()) {
+ // Only send weather packets to those affected
+ for (int idx = 0; idx < this.players.size(); ++idx) {
@@ -361,9 +459,9 @@
+ if (((ServerPlayer) this.players.get(idx)).level() == this) {
+ ((ServerPlayer) this.players.get(idx)).updateWeather(this.oRainLevel, this.rainLevel, this.oThunderLevel, this.thunderLevel);
+ }
}
+ }
+ // CraftBukkit end
+
}
@VisibleForTesting
@@ -389,7 +487,7 @@
}
public void resetEmptyTime() {
@@ -754,6 +853,14 @@
@@ -754,6 +950,14 @@
}
public void tickNonPassenger(Entity entity) {
@@ -404,7 +502,7 @@
entity.setOldPosAndRot();
ProfilerFiller gameprofilerfiller = Profiler.get();
@@ -763,6 +870,7 @@
@@ -763,6 +967,7 @@
});
gameprofilerfiller.incrementCounter("tickNonPassenger");
entity.tick();
@@ -412,7 +510,7 @@
gameprofilerfiller.pop();
Iterator iterator = entity.getPassengers().iterator();
@@ -771,6 +879,7 @@
@@ -771,6 +976,7 @@
this.tickPassenger(entity, entity1);
}
@@ -420,7 +518,7 @@
}
@@ -786,6 +895,7 @@
@@ -786,6 +992,7 @@
});
gameprofilerfiller.incrementCounter("tickPassenger");
passenger.rideTick();
@@ -428,7 +526,7 @@
gameprofilerfiller.pop();
Iterator iterator = passenger.getPassengers().iterator();
@@ -810,6 +920,7 @@
@@ -810,6 +1017,7 @@
ServerChunkCache chunkproviderserver = this.getChunkSource();
if (!savingDisabled) {
@@ -436,7 +534,7 @@
if (progressListener != null) {
progressListener.progressStartNoAbort(Component.translatable("menu.savingLevel"));
}
@@ -827,11 +938,19 @@
@@ -827,11 +1035,19 @@
}
}
@@ -457,21 +555,21 @@
}
DimensionDataStorage worldpersistentdata = this.getChunkSource().getDataStorage();
@@ -903,18 +1022,40 @@
@@ -903,18 +1119,40 @@
@Override
public boolean addFreshEntity(Entity entity) {
- return this.addEntity(entity);
+ // CraftBukkit start
+ return this.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.DEFAULT);
+ }
+
}
+ @Override
+ public boolean addFreshEntity(Entity entity, CreatureSpawnEvent.SpawnReason reason) {
+ return this.addEntity(entity, reason);
+ // CraftBukkit end
}
+ }
+
public boolean addWithUUID(Entity entity) {
- return this.addEntity(entity);
+ // CraftBukkit start
@@ -501,7 +599,7 @@
}
}
@@ -939,41 +1080,86 @@
@@ -939,41 +1177,86 @@
this.entityManager.addNewEntity(player);
}
@@ -593,20 +691,20 @@
while (iterator.hasNext()) {
ServerPlayer entityplayer = (ServerPlayer) iterator.next();
@@ -982,6 +1168,12 @@
@@ -981,6 +1264,12 @@
double d0 = (double) pos.getX() - entityplayer.getX();
double d1 = (double) pos.getY() - entityplayer.getY();
double d2 = (double) pos.getZ() - entityplayer.getZ();
+
+ // CraftBukkit start
+ if (entityhuman != null && !entityplayer.getBukkitEntity().canSee(entityhuman.getBukkitEntity())) {
+ continue;
+ }
+ // CraftBukkit end
+
if (d0 * d0 + d1 * d1 + d2 * d2 < 1024.0D) {
entityplayer.connection.send(new ClientboundBlockDestructionPacket(entityId, pos, progress));
}
@@ -1060,7 +1252,18 @@
@@ -1060,7 +1349,18 @@
Iterator iterator = this.navigatingMobs.iterator();
while (iterator.hasNext()) {
@@ -626,7 +724,7 @@
PathNavigation navigationabstract = entityinsentient.getNavigation();
if (navigationabstract.shouldRecomputePath(pos)) {
@@ -1126,9 +1329,15 @@
@@ -1126,9 +1426,15 @@
@Override
public void explode(@Nullable Entity entity, @Nullable DamageSource damageSource, @Nullable ExplosionDamageCalculator behavior, double x, double y, double z, float power, boolean createFire, Level.ExplosionInteraction explosionSourceType, ParticleOptions smallParticle, ParticleOptions largeParticle, Holder<SoundEvent> soundEvent) {
@@ -643,7 +741,7 @@
case NONE:
explosion_effect = Explosion.BlockInteraction.KEEP;
break;
@@ -1144,16 +1353,26 @@
@@ -1144,16 +1450,26 @@
case TRIGGER:
explosion_effect = Explosion.BlockInteraction.TRIGGER_BLOCK;
break;
@@ -673,7 +771,7 @@
Iterator iterator = this.players.iterator();
while (iterator.hasNext()) {
@@ -1162,10 +1381,11 @@
@@ -1162,10 +1478,11 @@
if (entityplayer.distanceToSqr(vec3d) < 4096.0D) {
Optional<Vec3> optional = Optional.ofNullable((Vec3) serverexplosion.getHitPlayers().get(entityplayer));
@@ -686,7 +784,7 @@
}
private Explosion.BlockInteraction getDestroyType(GameRules.Key<GameRules.BooleanValue> decayRule) {
@@ -1226,17 +1446,24 @@
@@ -1226,17 +1543,24 @@
}
public <T extends ParticleOptions> int sendParticles(T parameters, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double speed) {
@@ -714,7 +812,7 @@
++j;
}
}
@@ -1292,7 +1519,7 @@
@@ -1292,7 +1616,7 @@
@Nullable
public BlockPos findNearestMapStructure(TagKey<Structure> structureTag, BlockPos pos, int radius, boolean skipReferencedStructures) {
@@ -723,7 +821,7 @@
return null;
} else {
Optional<HolderSet.Named<Structure>> optional = this.registryAccess().lookupOrThrow(Registries.STRUCTURE).get(structureTag);
@@ -1334,11 +1561,22 @@
@@ -1334,11 +1658,22 @@
@Nullable
@Override
public MapItemSavedData getMapData(MapId id) {
@@ -747,7 +845,7 @@
this.getServer().overworld().getDataStorage().set(id.key(), state);
}
@@ -1649,6 +1887,11 @@
@@ -1649,6 +1984,11 @@
@Override
public void blockUpdated(BlockPos pos, Block block) {
if (!this.isDebug()) {
@@ -759,7 +857,7 @@
this.updateNeighborsAt(pos, block);
}
@@ -1668,12 +1911,12 @@
@@ -1668,12 +2008,12 @@
}
public boolean isFlat() {
@@ -774,7 +872,7 @@
}
@Nullable
@@ -1696,7 +1939,7 @@
@@ -1696,7 +2036,7 @@
private static <T> String getTypeCount(Iterable<T> items, Function<T, String> classifier) {
try {
Object2IntOpenHashMap<String> object2intopenhashmap = new Object2IntOpenHashMap();
@@ -783,7 +881,7 @@
while (iterator.hasNext()) {
T t0 = iterator.next();
@@ -1705,7 +1948,7 @@
@@ -1705,7 +2045,7 @@
object2intopenhashmap.addTo(s, 1);
}
@@ -792,7 +890,7 @@
String s1 = (String) entry.getKey();
return s1 + ":" + entry.getIntValue();
@@ -1717,6 +1960,7 @@
@@ -1717,6 +2057,7 @@
@Override
public LevelEntityGetter<Entity> getEntities() {
@@ -800,7 +898,7 @@
return this.entityManager.getEntityGetter();
}
@@ -1836,6 +2080,7 @@
@@ -1836,6 +2177,7 @@
}
public void onTrackingStart(Entity entity) {
@@ -808,7 +906,7 @@
ServerLevel.this.getChunkSource().addEntity(entity);
if (entity instanceof ServerPlayer entityplayer) {
ServerLevel.this.players.add(entityplayer);
@@ -1864,9 +2109,42 @@
@@ -1864,9 +2206,42 @@
}
entity.updateDynamicGameEventListener(DynamicGameEventListener::add);
@@ -851,7 +949,7 @@
ServerLevel.this.getChunkSource().removeEntity(entity);
if (entity instanceof ServerPlayer entityplayer) {
ServerLevel.this.players.remove(entityplayer);
@@ -1895,6 +2173,14 @@
@@ -1895,6 +2270,14 @@
}
entity.updateDynamicGameEventListener(DynamicGameEventListener::remove);

View File

@@ -112,7 +112,7 @@
@Nullable
private Vec3 startingToFallPosition;
@Nullable
@@ -258,6 +291,22 @@
@@ -258,6 +291,23 @@
private final CommandSource commandSource;
private int containerCounter;
public boolean wonGame;
@@ -132,10 +132,11 @@
+ public boolean sentListPacket = false;
+ public String kickLeaveMessage = null; // SPIGOT-3034: Forward leave message to PlayerQuitEvent
+ // CraftBukkit end
+ public boolean isRealPlayer; // Paper
public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ClientInformation clientOptions) {
super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile);
@@ -340,6 +389,13 @@
@@ -340,6 +390,13 @@
public void sendSystemMessage(Component message) {
ServerPlayer.this.sendSystemMessage(message);
}
@@ -149,7 +150,7 @@
};
this.textFilter = server.createTextFilterForPlayer(this);
this.gameMode = server.createGameModeForPlayer(this);
@@ -352,14 +408,67 @@
@@ -352,14 +409,67 @@
this.moveTo(this.adjustSpawnLocation(world, world.getSharedSpawnPos()).getBottomCenter(), 0.0F, 0.0F);
this.updateOptions(clientOptions);
this.object = null;
@@ -218,7 +219,7 @@
int i = Math.max(0, this.server.getSpawnRadius(world));
int j = Mth.floor(world.getWorldBorder().getDistanceToBorder((double) basePos.getX(), (double) basePos.getZ()));
@@ -395,14 +504,20 @@
@@ -395,14 +505,20 @@
Objects.requireNonNull(basePos);
crashreportsystemdetails.setDetail("Origin", basePos::toString);
@@ -241,7 +242,7 @@
});
throw new ReportedException(crashreport);
}
@@ -440,7 +555,7 @@
@@ -440,7 +556,7 @@
dataresult = WardenSpawnTracker.CODEC.parse(new Dynamic(NbtOps.INSTANCE, nbt.get("warden_spawn_tracker")));
logger = ServerPlayer.LOGGER;
Objects.requireNonNull(logger);
@@ -250,7 +251,7 @@
this.wardenSpawnTracker = wardenspawntracker;
});
}
@@ -457,17 +572,26 @@
@@ -457,17 +573,26 @@
return this.server.getRecipeManager().byKey(resourcekey).isPresent();
});
}
@@ -278,7 +279,7 @@
Logger logger1 = ServerPlayer.LOGGER;
Objects.requireNonNull(logger1);
@@ -482,7 +606,7 @@
@@ -482,7 +607,7 @@
dataresult = BlockPos.CODEC.parse(NbtOps.INSTANCE, nbtbase);
logger = ServerPlayer.LOGGER;
Objects.requireNonNull(logger);
@@ -287,7 +288,7 @@
this.raidOmenPosition = blockposition;
});
}
@@ -492,7 +616,7 @@
@@ -492,7 +617,7 @@
@Override
public void addAdditionalSaveData(CompoundTag nbt) {
super.addAdditionalSaveData(nbt);
@@ -296,7 +297,7 @@
Logger logger = ServerPlayer.LOGGER;
Objects.requireNonNull(logger);
@@ -526,6 +650,7 @@
@@ -526,6 +651,7 @@
nbt.put("SpawnDimension", nbtbase);
});
}
@@ -304,7 +305,7 @@
nbt.putBoolean("spawn_extra_particles_on_fall", this.spawnExtraParticlesOnFall);
if (this.raidOmenPosition != null) {
@@ -544,7 +669,20 @@
@@ -544,7 +670,20 @@
Entity entity = this.getRootVehicle();
Entity entity1 = this.getVehicle();
@@ -326,7 +327,7 @@
CompoundTag nbttagcompound1 = new CompoundTag();
CompoundTag nbttagcompound2 = new CompoundTag();
@@ -598,12 +736,12 @@
@@ -598,12 +737,12 @@
if (!this.isPassenger()) {
ServerPlayer.LOGGER.warn("Couldn't reattach entity to player");
@@ -341,7 +342,7 @@
}
}
}
@@ -625,7 +763,7 @@
@@ -625,7 +764,7 @@
CompoundTag nbttagcompound1 = new CompoundTag();
entityenderpearl.save(nbttagcompound1);
@@ -350,7 +351,7 @@
Logger logger = ServerPlayer.LOGGER;
Objects.requireNonNull(logger);
@@ -651,7 +789,7 @@
@@ -651,7 +790,7 @@
nbttaglist.forEach((nbtbase1) -> {
if (nbtbase1 instanceof CompoundTag nbttagcompound) {
if (nbttagcompound.contains("ender_pearl_dimension")) {
@@ -359,7 +360,7 @@
Logger logger = ServerPlayer.LOGGER;
Objects.requireNonNull(logger);
@@ -684,7 +822,30 @@
@@ -684,7 +823,30 @@
}
}
@@ -390,7 +391,7 @@
public void setExperiencePoints(int points) {
float f = (float) this.getXpNeededForNextLevel();
@@ -744,6 +905,11 @@
@@ -744,6 +906,11 @@
@Override
public void tick() {
@@ -402,7 +403,7 @@
this.tickClientLoadTimeout();
this.gameMode.tick();
this.wardenSpawnTracker.tick();
@@ -820,7 +986,7 @@
@@ -820,7 +987,7 @@
}
if (this.getHealth() != this.lastSentHealth || this.lastSentFood != this.foodData.getFoodLevel() || this.foodData.getSaturationLevel() == 0.0F != this.lastFoodSaturationZero) {
@@ -411,7 +412,7 @@
this.lastSentHealth = this.getHealth();
this.lastSentFood = this.foodData.getFoodLevel();
this.lastFoodSaturationZero = this.foodData.getSaturationLevel() == 0.0F;
@@ -851,6 +1017,12 @@
@@ -851,6 +1018,12 @@
this.updateScoreForCriteria(ObjectiveCriteria.EXPERIENCE, Mth.ceil((float) this.lastRecordedExperience));
}
@@ -424,17 +425,15 @@
if (this.experienceLevel != this.lastRecordedLevel) {
this.lastRecordedLevel = this.experienceLevel;
this.updateScoreForCriteria(ObjectiveCriteria.LEVEL, Mth.ceil((float) this.lastRecordedLevel));
@@ -863,8 +1035,22 @@
if (this.tickCount % 20 == 0) {
@@ -865,6 +1038,20 @@
CriteriaTriggers.LOCATION.trigger(this);
+ }
+
}
+ // CraftBukkit start - initialize oldLevel, fire PlayerLevelChangeEvent, and tick client-sided world border
+ if (this.oldLevel == -1) {
+ this.oldLevel = this.experienceLevel;
}
+ }
+
+ if (this.oldLevel != this.experienceLevel) {
+ CraftEventFactory.callPlayerLevelChangeEvent(this.getBukkitEntity(), this.oldLevel, this.experienceLevel);
+ this.oldLevel = this.experienceLevel;
@@ -447,7 +446,7 @@
} catch (Throwable throwable) {
CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking player");
CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Player being ticked");
@@ -893,7 +1079,7 @@
@@ -893,7 +1080,7 @@
if (this.level().getDifficulty() == Difficulty.PEACEFUL && this.serverLevel().getGameRules().getBoolean(GameRules.RULE_NATURAL_REGENERATION)) {
if (this.tickCount % 20 == 0) {
if (this.getHealth() < this.getMaxHealth()) {
@@ -456,7 +455,7 @@
}
float f = this.foodData.getSaturationLevel();
@@ -946,7 +1132,8 @@
@@ -946,7 +1133,8 @@
}
private void updateScoreForCriteria(ObjectiveCriteria criterion, int score) {
@@ -466,7 +465,7 @@
scoreaccess.set(score);
});
}
@@ -955,10 +1142,48 @@
@@ -955,9 +1143,47 @@
public void die(DamageSource damageSource) {
this.gameEvent(GameEvent.ENTITY_DIE);
boolean flag = this.serverLevel().getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES);
@@ -489,7 +488,7 @@
+ // SPIGOT-5071: manually add player loot tables (SPIGOT-5195 - ignores keepInventory rule)
+ this.dropFromLootTable(this.serverLevel(), damageSource, this.lastHurtByPlayerTime > 0);
+ this.dropCustomDeathLoot(this.serverLevel(), damageSource, flag);
+
+ loot.addAll(this.drops);
+ this.drops.clear(); // SPIGOT-5188: make sure to clear
+
@@ -513,11 +512,10 @@
+ } else {
+ ichatbasecomponent = org.bukkit.craftbukkit.util.CraftChatMessage.fromStringOrNull(deathMessage);
+ }
+
this.connection.send(new ClientboundPlayerCombatKillPacket(this.getId(), ichatbasecomponent), PacketSendListener.exceptionallySend(() -> {
boolean flag1 = true;
String s = ichatbasecomponent.getString(256);
@@ -988,12 +1213,18 @@
@@ -988,12 +1214,18 @@
if (this.serverLevel().getGameRules().getBoolean(GameRules.RULE_FORGIVE_DEAD_PLAYERS)) {
this.tellNeutralMobsThatIDied();
}
@@ -540,7 +538,7 @@
LivingEntity entityliving = this.getKillCredit();
if (entityliving != null) {
@@ -1028,10 +1259,12 @@
@@ -1028,10 +1260,12 @@
public void awardKillScore(Entity entityKilled, DamageSource damageSource) {
if (entityKilled != this) {
super.awardKillScore(entityKilled, damageSource);
@@ -556,7 +554,7 @@
} else {
this.awardStat(Stats.MOB_KILLS);
}
@@ -1049,7 +1282,8 @@
@@ -1049,7 +1283,8 @@
int i = scoreboardteam.getColor().getId();
if (i >= 0 && i < criterions.length) {
@@ -566,7 +564,7 @@
}
}
@@ -1062,8 +1296,8 @@
@@ -1062,8 +1297,8 @@
} else {
Entity entity = source.getEntity();
@@ -577,7 +575,7 @@
if (!this.canHarmPlayer(entityhuman)) {
return false;
@@ -1074,8 +1308,8 @@
@@ -1074,8 +1309,8 @@
AbstractArrow entityarrow = (AbstractArrow) entity;
Entity entity1 = entityarrow.getOwner();
@@ -588,7 +586,7 @@
if (!this.canHarmPlayer(entityhuman1)) {
return false;
@@ -1088,33 +1322,63 @@
@@ -1088,33 +1323,63 @@
}
@Override
@@ -659,7 +657,7 @@
}
public static Optional<ServerPlayer.RespawnPosAngle> findRespawnAndUseSpawnBlock(ServerLevel world, BlockPos pos, float spawnAngle, boolean spawnForced, boolean alive) {
@@ -1129,11 +1393,11 @@
@@ -1129,11 +1394,11 @@
}
return optional.map((vec3d) -> {
@@ -673,7 +671,7 @@
});
} else if (!spawnForced) {
return Optional.empty();
@@ -1142,7 +1406,7 @@
@@ -1142,7 +1407,7 @@
BlockState iblockdata1 = world.getBlockState(pos.above());
boolean flag3 = iblockdata1.getBlock().isPossibleToRespawnInThis(iblockdata1);
@@ -682,7 +680,7 @@
}
}
@@ -1160,6 +1424,7 @@
@@ -1160,6 +1425,7 @@
@Nullable
@Override
public ServerPlayer teleport(TeleportTransition teleportTarget) {
@@ -690,7 +688,7 @@
if (this.isRemoved()) {
return null;
} else {
@@ -1169,39 +1434,73 @@
@@ -1169,39 +1435,73 @@
ServerLevel worldserver = teleportTarget.newLevel();
ServerLevel worldserver1 = this.serverLevel();
@@ -772,7 +770,7 @@
this.connection.resetPosition();
worldserver.addDuringTeleport(this);
gameprofilerfiller.pop();
@@ -1215,12 +1514,30 @@
@@ -1215,12 +1515,30 @@
this.lastSentExp = -1;
this.lastSentHealth = -1.0F;
this.lastSentFood = -1;
@@ -803,7 +801,7 @@
public void forceSetRotation(float yaw, float pitch) {
this.connection.send(new ClientboundPlayerRotationPacket(yaw, pitch));
}
@@ -1228,13 +1545,21 @@
@@ -1228,13 +1546,21 @@
public void triggerDimensionChangeTriggers(ServerLevel origin) {
ResourceKey<Level> resourcekey = origin.dimension();
ResourceKey<Level> resourcekey1 = this.level().dimension();
@@ -828,7 +826,7 @@
this.enteredNetherPosition = null;
}
@@ -1251,36 +1576,63 @@
@@ -1251,36 +1577,63 @@
this.containerMenu.broadcastChanges();
}
@@ -907,7 +905,7 @@
this.awardStat(Stats.SLEEP_IN_BED);
CriteriaTriggers.SLEPT_IN_BED.trigger(this);
});
@@ -1293,9 +1645,8 @@
@@ -1293,9 +1646,8 @@
return either;
}
}
@@ -918,7 +916,7 @@
}
@Override
@@ -1322,13 +1673,31 @@
@@ -1322,13 +1674,31 @@
@Override
public void stopSleepInBed(boolean skipSleepTimer, boolean updateSleepingPlayers) {
@@ -951,7 +949,7 @@
}
}
@@ -1387,8 +1756,9 @@
@@ -1387,8 +1757,9 @@
this.connection.send(new ClientboundOpenSignEditorPacket(sign.getBlockPos(), front));
}
@@ -962,7 +960,7 @@
}
@Override
@@ -1396,13 +1766,35 @@
@@ -1396,13 +1767,35 @@
if (factory == null) {
return OptionalInt.empty();
} else {
@@ -998,7 +996,7 @@
if (container == null) {
if (this.isSpectator()) {
this.displayClientMessage(Component.translatable("container.spectatorCantOpen").withStyle(ChatFormatting.RED), true);
@@ -1410,9 +1802,11 @@
@@ -1410,9 +1803,11 @@
return OptionalInt.empty();
} else {
@@ -1012,7 +1010,7 @@
return OptionalInt.of(this.containerCounter);
}
}
@@ -1425,15 +1819,26 @@
@@ -1425,15 +1820,26 @@
@Override
public void openHorseInventory(AbstractHorse horse, Container inventory) {
@@ -1041,7 +1039,7 @@
this.initMenu(this.containerMenu);
}
@@ -1456,6 +1861,7 @@
@@ -1456,6 +1862,7 @@
@Override
public void closeContainer() {
@@ -1049,7 +1047,7 @@
this.connection.send(new ClientboundContainerClosePacket(this.containerMenu.containerId));
this.doCloseContainer();
}
@@ -1485,19 +1891,19 @@
@@ -1485,19 +1892,19 @@
i = Math.round((float) Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ) * 100.0F);
if (i > 0) {
this.awardStat(Stats.SWIM_ONE_CM, i);
@@ -1072,7 +1070,7 @@
}
} else if (this.onClimbable()) {
if (deltaY > 0.0D) {
@@ -1508,13 +1914,13 @@
@@ -1508,13 +1915,13 @@
if (i > 0) {
if (this.isSprinting()) {
this.awardStat(Stats.SPRINT_ONE_CM, i);
@@ -1089,7 +1087,7 @@
}
}
} else if (this.isFallFlying()) {
@@ -1557,7 +1963,7 @@
@@ -1557,7 +1964,7 @@
@Override
public void awardStat(Stat<?> stat, int amount) {
this.stats.increment(this, stat, amount);
@@ -1098,7 +1096,7 @@
scoreaccess.add(amount);
});
}
@@ -1565,7 +1971,7 @@
@@ -1565,7 +1972,7 @@
@Override
public void resetStat(Stat<?> stat) {
this.stats.setValue(this, stat, 0);
@@ -1107,7 +1105,7 @@
}
@Override
@@ -1597,9 +2003,9 @@
@@ -1597,9 +2004,9 @@
super.jumpFromGround();
this.awardStat(Stats.JUMP);
if (this.isSprinting()) {
@@ -1119,7 +1117,7 @@
}
}
@@ -1625,6 +2031,7 @@
@@ -1625,6 +2032,7 @@
public void resetSentInfo() {
this.lastSentHealth = -1.0E8F;
@@ -1127,7 +1125,7 @@
}
@Override
@@ -1661,7 +2068,7 @@
@@ -1661,7 +2069,7 @@
this.onUpdateAbilities();
if (alive) {
this.getAttributes().assignBaseValues(oldPlayer.getAttributes());
@@ -1136,7 +1134,7 @@
this.setHealth(oldPlayer.getHealth());
this.foodData = oldPlayer.foodData;
Iterator iterator = oldPlayer.getActiveEffects().iterator();
@@ -1669,7 +2076,7 @@
@@ -1669,7 +2077,7 @@
while (iterator.hasNext()) {
MobEffectInstance mobeffect = (MobEffectInstance) iterator.next();
@@ -1145,7 +1143,7 @@
}
this.getInventory().replaceWith(oldPlayer.getInventory());
@@ -1680,7 +2087,7 @@
@@ -1680,7 +2088,7 @@
this.portalProcess = oldPlayer.portalProcess;
} else {
this.getAttributes().assignBaseValues(oldPlayer.getAttributes());
@@ -1154,7 +1152,7 @@
if (this.serverLevel().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY) || oldPlayer.isSpectator()) {
this.getInventory().replaceWith(oldPlayer.getInventory());
this.experienceLevel = oldPlayer.experienceLevel;
@@ -1696,7 +2103,7 @@
@@ -1696,7 +2104,7 @@
this.lastSentExp = -1;
this.lastSentHealth = -1.0F;
this.lastSentFood = -1;
@@ -1163,7 +1161,7 @@
this.seenCredits = oldPlayer.seenCredits;
this.enteredNetherPosition = oldPlayer.enteredNetherPosition;
this.chunkTrackingView = oldPlayer.chunkTrackingView;
@@ -1752,19 +2159,19 @@
@@ -1752,19 +2160,19 @@
}
@Override
@@ -1187,7 +1185,7 @@
}
return flag1;
@@ -1878,6 +2285,16 @@
@@ -1878,6 +2286,16 @@
}
public void updateOptions(ClientInformation clientOptions) {
@@ -1204,7 +1202,7 @@
this.language = clientOptions.language();
this.requestedViewDistance = clientOptions.viewDistance();
this.chatVisibility = clientOptions.chatVisibility();
@@ -1962,7 +2379,7 @@
@@ -1962,7 +2380,7 @@
if (world instanceof ServerLevel) {
ServerLevel worldserver = (ServerLevel) world;
@@ -1213,7 +1211,7 @@
}
if (entity != null) {
@@ -1999,11 +2416,11 @@
@@ -1999,11 +2417,11 @@
@Nullable
public Component getTabListDisplayName() {
@@ -1227,7 +1225,7 @@
}
@Override
@@ -2046,17 +2463,43 @@
@@ -2046,17 +2464,43 @@
}
public void setRespawnPosition(ResourceKey<Level> dimension, @Nullable BlockPos pos, float angle, boolean forced, boolean sendMessage) {
@@ -1278,7 +1276,7 @@
} else {
this.respawnPosition = null;
this.respawnDimension = Level.OVERWORLD;
@@ -2088,18 +2531,44 @@
@@ -2088,18 +2532,44 @@
}
@Override
@@ -1327,7 +1325,7 @@
}
this.awardStat(Stats.DROP);
@@ -2375,16 +2844,160 @@
@@ -2375,16 +2845,160 @@
return TicketType.ENDER_PEARL.timeout();
}

View File

@@ -1,11 +1,20 @@
--- a/net/minecraft/server/level/TicketType.java
+++ b/net/minecraft/server/level/TicketType.java
@@ -22,6 +22,8 @@
@@ -7,6 +7,7 @@
import net.minecraft.world.level.ChunkPos;
public class TicketType<T> {
+ public static final TicketType<Long> FUTURE_AWAIT = create("future_await", Long::compareTo); // Paper
private final String name;
private final Comparator<T> comparator;
@@ -22,6 +23,9 @@
public static final TicketType<BlockPos> PORTAL = TicketType.create("portal", Vec3i::compareTo, 300);
public static final TicketType<ChunkPos> ENDER_PEARL = TicketType.create("ender_pearl", Comparator.comparingLong(ChunkPos::toLong), 40);
public static final TicketType<ChunkPos> UNKNOWN = TicketType.create("unknown", Comparator.comparingLong(ChunkPos::toLong), 1);
+ public static final TicketType<Unit> PLUGIN = TicketType.create("plugin", (a, b) -> 0); // CraftBukkit
+ public static final TicketType<org.bukkit.plugin.Plugin> PLUGIN_TICKET = TicketType.create("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit
+ public static final TicketType<Integer> POST_TELEPORT = TicketType.create("post_teleport", Integer::compare, 5); // Paper - post teleport ticket type
public static <T> TicketType<T> create(String name, Comparator<T> argumentComparator) {
return new TicketType<>(name, argumentComparator, 0L);

View File

@@ -1,6 +1,34 @@
--- a/net/minecraft/server/level/WorldGenRegion.java
+++ b/net/minecraft/server/level/WorldGenRegion.java
@@ -217,7 +217,7 @@
@@ -169,7 +169,27 @@
return k < this.generatingStep.directDependencies().size();
}
+ // Paper start - if loaded util
+ @Nullable
@Override
+ public ChunkAccess getChunkIfLoadedImmediately(int x, int z) {
+ return this.getChunk(x, z, ChunkStatus.FULL, false);
+ }
+
+ @Override
+ public final BlockState getBlockStateIfLoaded(BlockPos blockposition) {
+ ChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4);
+ return chunk == null ? null : chunk.getBlockState(blockposition);
+ }
+
+ @Override
+ public final FluidState getFluidIfLoaded(BlockPos blockposition) {
+ ChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4);
+ return chunk == null ? null : chunk.getFluidState(blockposition);
+ }
+ // Paper end
+
+ @Override
public BlockState getBlockState(BlockPos pos) {
return this.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ())).getBlockState(pos);
}
@@ -217,7 +237,7 @@
if (iblockdata.isAir()) {
return false;
} else {
@@ -9,7 +37,7 @@
BlockEntity tileentity = iblockdata.hasBlockEntity() ? this.getBlockEntity(pos) : null;
Block.dropResources(iblockdata, this.level, pos, tileentity, breakingEntity, ItemStack.EMPTY);
@@ -336,6 +336,13 @@
@@ -336,6 +356,13 @@
@Override
public boolean addFreshEntity(Entity entity) {

View File

@@ -90,8 +90,11 @@
this.server = server;
this.registries = registryManager;
this.maxPlayers = maxPlayers;
@@ -150,25 +183,34 @@
@@ -148,27 +181,37 @@
}
public void placeNewPlayer(Connection connection, ServerPlayer player, CommonListenerCookie clientData) {
+ player.isRealPlayer = true; // Paper
GameProfile gameprofile = player.getGameProfile();
GameProfileCache usercache = this.server.getProfileCache();
- Optional optional;
@@ -130,7 +133,7 @@
ServerLevel worldserver = this.server.getLevel(resourcekey);
ServerLevel worldserver1;
@@ -182,10 +224,24 @@
@@ -182,10 +225,24 @@
player.setServerLevel(worldserver1);
String s1 = connection.getLoggableAddress(this.server.logIPs());
@@ -157,7 +160,7 @@
ServerGamePacketListenerImpl playerconnection = new ServerGamePacketListenerImpl(this.server, connection, player, clientData);
connection.setupInboundProtocol(GameProtocols.SERVERBOUND_TEMPLATE.bind(RegistryFriendlyByteBuf.decorator(this.server.registryAccess())), playerconnection);
@@ -194,7 +250,9 @@
@@ -194,7 +251,9 @@
boolean flag1 = gamerules.getBoolean(GameRules.RULE_REDUCEDDEBUGINFO);
boolean flag2 = gamerules.getBoolean(GameRules.RULE_LIMITED_CRAFTING);
@@ -168,7 +171,7 @@
playerconnection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked()));
playerconnection.send(new ClientboundPlayerAbilitiesPacket(player.getAbilities()));
playerconnection.send(new ClientboundSetHeldSlotPacket(player.getInventory().selected));
@@ -213,8 +271,10 @@
@@ -213,8 +272,10 @@
} else {
ichatmutablecomponent = Component.translatable("multiplayer.player.joined.renamed", player.getDisplayName(), s);
}
@@ -180,7 +183,7 @@
playerconnection.teleport(player.getX(), player.getY(), player.getZ(), player.getYRot(), player.getXRot());
ServerStatus serverping = this.server.getStatus();
@@ -222,17 +282,71 @@
@@ -222,17 +283,71 @@
player.sendServerStatus(serverping);
}
@@ -256,7 +259,7 @@
}
public void updateEntireScoreboard(ServerScoreboard scoreboard, ServerPlayer player) {
@@ -269,30 +383,31 @@
@@ -269,30 +384,31 @@
}
public void addWorldborderListener(ServerLevel world) {
@@ -293,7 +296,7 @@
}
@Override
@@ -319,14 +434,15 @@
@@ -319,14 +435,15 @@
}
protected void save(ServerPlayer player) {
@@ -311,7 +314,7 @@
if (advancementdataplayer != null) {
advancementdataplayer.save();
@@ -334,95 +450,176 @@
@@ -334,95 +451,176 @@
}
@@ -527,7 +530,7 @@
if (entityplayer1 != null) {
set.add(entityplayer1);
@@ -431,30 +628,50 @@
@@ -431,30 +629,50 @@
Iterator iterator1 = set.iterator();
while (iterator1.hasNext()) {
@@ -591,7 +594,7 @@
while (iterator.hasNext()) {
String s = (String) iterator.next();
@@ -462,41 +679,87 @@
@@ -462,41 +680,88 @@
entityplayer1.addTag(s);
}
@@ -617,6 +620,7 @@
- entityplayer1.moveTo(vec3d.x, vec3d.y, vec3d.z, teleporttransition.yRot(), teleporttransition.xRot());
+ entityplayer1.forceSetPositionRotation(vec3d.x, vec3d.y, vec3d.z, teleporttransition.yRot(), teleporttransition.xRot());
+ worldserver.getChunkSource().addRegionTicket(net.minecraft.server.level.TicketType.POST_TELEPORT, new net.minecraft.world.level.ChunkPos(net.minecraft.util.Mth.floor(vec3d.x()) >> 4, net.minecraft.util.Mth.floor(vec3d.z()) >> 4), 1, entityplayer.getId()); // Paper - post teleport ticket type
+ // CraftBukkit end
if (teleporttransition.missingRespawnBlock()) {
entityplayer1.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.NO_RESPAWN_BLOCK_AVAILABLE, 0.0F));
@@ -687,7 +691,7 @@
return entityplayer1;
}
@@ -524,7 +787,18 @@
@@ -524,7 +789,18 @@
public void tick() {
if (++this.sendAllPlayerInfoIn > 600) {
@@ -707,7 +711,7 @@
this.sendAllPlayerInfoIn = 0;
}
@@ -541,6 +815,25 @@
@@ -541,6 +817,25 @@
}
@@ -733,7 +737,7 @@
public void broadcastAll(Packet<?> packet, ResourceKey<Level> dimension) {
Iterator iterator = this.players.iterator();
@@ -554,7 +847,7 @@
@@ -554,7 +849,7 @@
}
@@ -742,7 +746,7 @@
PlayerTeam scoreboardteam = source.getTeam();
if (scoreboardteam != null) {
@@ -573,7 +866,7 @@
@@ -573,7 +868,7 @@
}
}
@@ -751,7 +755,7 @@
PlayerTeam scoreboardteam = source.getTeam();
if (scoreboardteam == null) {
@@ -619,7 +912,7 @@
@@ -619,7 +914,7 @@
}
public void deop(GameProfile profile) {
@@ -760,7 +764,7 @@
ServerPlayer entityplayer = this.getPlayer(profile.getId());
if (entityplayer != null) {
@@ -643,6 +936,7 @@
@@ -643,6 +938,7 @@
player.connection.send(new ClientboundEntityEventPacket(player, b0));
}
@@ -768,7 +772,7 @@
this.server.getCommands().sendCommands(player);
}
@@ -656,23 +950,19 @@
@@ -656,23 +952,19 @@
@Nullable
public ServerPlayer getPlayerByName(String name) {
@@ -800,7 +804,7 @@
if (entityplayer != player && entityplayer.level().dimension() == worldKey) {
double d4 = x - entityplayer.getX();
double d5 = y - entityplayer.getY();
@@ -712,15 +1002,19 @@
@@ -712,15 +1004,19 @@
public void reloadWhiteList() {}
public void sendLevelInfo(ServerPlayer player, ServerLevel world) {
@@ -824,7 +828,7 @@
}
player.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.LEVEL_CHUNKS_LOAD_START, 0.0F));
@@ -729,8 +1023,16 @@
@@ -729,8 +1025,16 @@
public void sendAllPlayerInfo(ServerPlayer player) {
player.inventoryMenu.sendAllDataToRemote();
@@ -842,7 +846,7 @@
}
public int getPlayerCount() {
@@ -786,12 +1088,22 @@
@@ -786,12 +1090,22 @@
}
public void removeAll() {
@@ -867,7 +871,7 @@
public void broadcastSystemMessage(Component message, boolean overlay) {
this.broadcastSystemMessage(message, (entityplayer) -> {
return message;
@@ -849,16 +1161,23 @@
@@ -849,16 +1163,23 @@
return message.hasSignature() && !message.hasExpiredServer(Instant.now());
}
@@ -895,7 +899,7 @@
Path path = file2.toPath();
if (FileUtil.isPathNormalized(path) && FileUtil.isPathPortable(path) && path.startsWith(file.getPath()) && file2.isFile()) {
@@ -867,7 +1186,7 @@
@@ -867,7 +1188,7 @@
}
serverstatisticmanager = new ServerStatsCounter(this.server, file1);
@@ -904,7 +908,7 @@
}
return serverstatisticmanager;
@@ -875,13 +1194,13 @@
@@ -875,13 +1196,13 @@
public PlayerAdvancements getPlayerAdvancements(ServerPlayer player) {
UUID uuid = player.getUUID();
@@ -920,7 +924,7 @@
}
advancementdataplayer.setPlayer(player);
@@ -932,15 +1251,28 @@
@@ -932,15 +1253,28 @@
}
public void reloadResources() {