mirror of
https://github.com/PaperMC/Paper.git
synced 2025-07-31 04:02:06 -07:00
1.21.5
Co-authored-by: Bjarne Koll <git@lynxplay.dev> Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com> Co-authored-by: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com> Co-authored-by: MiniDigger | Martin <admin@minidigger.dev> Co-authored-by: Nassim Jahnke <nassim@njahnke.dev> Co-authored-by: Noah van der Aa <ndvdaa@gmail.com> Co-authored-by: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> Co-authored-by: Shane Freeder <theboyetronic@gmail.com> Co-authored-by: Spottedleaf <Spottedleaf@users.noreply.github.com> Co-authored-by: Tamion <70228790+notTamion@users.noreply.github.com> Co-authored-by: Warrior <50800980+Warriorrrr@users.noreply.github.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -145,6 +_,33 @@
|
||||
@@ -149,6 +_,33 @@
|
||||
public int serverViewDistance;
|
||||
private final WorldGenContext worldGenContext;
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
public ChunkMap(
|
||||
ServerLevel level,
|
||||
LevelStorageSource.LevelStorageAccess levelStorageAccess,
|
||||
@@ -171,13 +_,19 @@
|
||||
@@ -176,13 +_,19 @@
|
||||
this.level = level;
|
||||
RegistryAccess registryAccess = level.registryAccess();
|
||||
long seed = level.getSeed();
|
||||
@@ -56,7 +56,7 @@
|
||||
this.mainThreadExecutor = mainThreadExecutor;
|
||||
ConsecutiveExecutor consecutiveExecutor = new ConsecutiveExecutor(dispatcher, "worldgen");
|
||||
this.progressListener = progressListener;
|
||||
@@ -207,6 +_,12 @@
|
||||
@@ -213,6 +_,12 @@
|
||||
this.chunksToEagerlySave.add(chunkPos.toLong());
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
protected ChunkGenerator generator() {
|
||||
return this.worldGenContext.generator();
|
||||
}
|
||||
@@ -354,9 +_,9 @@
|
||||
@@ -352,9 +_,9 @@
|
||||
}
|
||||
);
|
||||
stringBuilder.append("Updating:").append(System.lineSeparator());
|
||||
@@ -81,17 +81,15 @@
|
||||
CrashReport crashReport = CrashReport.forThrowable(exception, "Chunk loading");
|
||||
CrashReportCategory crashReportCategory = crashReport.addCategory("Chunk loading");
|
||||
crashReportCategory.setDetail("Details", details);
|
||||
@@ -392,6 +_,9 @@
|
||||
@@ -390,6 +_,7 @@
|
||||
holder.setTicketLevel(newLevel);
|
||||
} else {
|
||||
holder = new ChunkHolder(new ChunkPos(chunkPos), newLevel, this.level, this.lightEngine, this::onLevelChange, this);
|
||||
+ // Paper start
|
||||
+ ca.spottedleaf.moonrise.common.PlatformHooks.get().onChunkHolderCreate(this.level, holder);
|
||||
+ // Paper end
|
||||
+ ca.spottedleaf.moonrise.common.PlatformHooks.get().onChunkHolderCreate(this.level, holder); // Paper
|
||||
}
|
||||
|
||||
this.updatingChunkMap.put(chunkPos, holder);
|
||||
@@ -420,8 +_,8 @@
|
||||
@@ -418,8 +_,8 @@
|
||||
|
||||
protected void saveAllChunks(boolean flush) {
|
||||
if (flush) {
|
||||
@@ -102,7 +100,7 @@
|
||||
.stream()
|
||||
.filter(ChunkHolder::wasAccessibleSinceLastSave)
|
||||
.peek(ChunkHolder::refreshAccessibility)
|
||||
@@ -447,7 +_,7 @@
|
||||
@@ -445,7 +_,7 @@
|
||||
this.nextChunkSaveTime.clear();
|
||||
long millis = Util.getMillis();
|
||||
|
||||
@@ -111,7 +109,7 @@
|
||||
this.saveChunkIfNeeded(chunkHolder, millis);
|
||||
}
|
||||
}
|
||||
@@ -468,6 +_,7 @@
|
||||
@@ -466,6 +_,7 @@
|
||||
public boolean hasWork() {
|
||||
return this.lightEngine.hasLightWork()
|
||||
|| !this.pendingUnloads.isEmpty()
|
||||
@@ -119,7 +117,7 @@
|
||||
|| !this.updatingChunkMap.isEmpty()
|
||||
|| this.poiManager.hasWork()
|
||||
|| !this.toDrop.isEmpty()
|
||||
@@ -526,7 +_,11 @@
|
||||
@@ -524,7 +_,11 @@
|
||||
this.scheduleUnload(chunkPos, chunkHolder);
|
||||
} else {
|
||||
ChunkAccess latestChunk = chunkHolder.getLatestChunk();
|
||||
@@ -132,7 +130,7 @@
|
||||
if (latestChunk instanceof LevelChunk levelChunk) {
|
||||
levelChunk.setLoaded(false);
|
||||
}
|
||||
@@ -540,7 +_,9 @@
|
||||
@@ -538,7 +_,9 @@
|
||||
this.lightEngine.tryScheduleUpdate();
|
||||
this.progressListener.onStatusChange(latestChunk.getPos(), null);
|
||||
this.nextChunkSaveTime.remove(latestChunk.getPos().toLong());
|
||||
@@ -143,7 +141,7 @@
|
||||
}
|
||||
}, this.unloadQueue::add).whenComplete((_void, error) -> {
|
||||
if (error != null) {
|
||||
@@ -856,7 +_,7 @@
|
||||
@@ -854,7 +_,7 @@
|
||||
}
|
||||
|
||||
public int size() {
|
||||
@@ -152,7 +150,7 @@
|
||||
}
|
||||
|
||||
public net.minecraft.server.level.DistanceManager getDistanceManager() {
|
||||
@@ -864,7 +_,7 @@
|
||||
@@ -862,7 +_,7 @@
|
||||
}
|
||||
|
||||
protected Iterable<ChunkHolder> getChunks() {
|
||||
@@ -161,9 +159,9 @@
|
||||
}
|
||||
|
||||
void dumpChunks(Writer writer) throws IOException {
|
||||
@@ -888,10 +_,10 @@
|
||||
@@ -885,10 +_,10 @@
|
||||
.addColumn("fluid_ticks")
|
||||
.build(writer);
|
||||
TickingTracker tickingTracker = this.distanceManager.tickingTracker();
|
||||
|
||||
- for (Entry<ChunkHolder> entry : this.visibleChunkMap.long2ObjectEntrySet()) {
|
||||
- long longKey = entry.getLongKey();
|
||||
@@ -175,7 +173,7 @@
|
||||
Optional<ChunkAccess> optional = Optional.ofNullable(chunkHolder.getLatestChunk());
|
||||
Optional<LevelChunk> optional1 = optional.flatMap(chunk -> chunk instanceof LevelChunk ? Optional.of((LevelChunk)chunk) : Optional.empty());
|
||||
csvOutput.writeRow(
|
||||
@@ -931,11 +_,13 @@
|
||||
@@ -928,11 +_,13 @@
|
||||
}
|
||||
|
||||
private CompletableFuture<Optional<CompoundTag>> readChunk(ChunkPos pos) {
|
||||
@@ -191,18 +189,28 @@
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
void forEachSpawnCandidateChunk(Consumer<ChunkHolder> action) {
|
||||
@@ -951,12 +_,34 @@
|
||||
void collectSpawningChunks(List<LevelChunk> output) {
|
||||
@@ -942,7 +_,7 @@
|
||||
ChunkHolder chunkHolder = this.visibleChunkMap.get(spawnCandidateChunks.nextLong());
|
||||
if (chunkHolder != null) {
|
||||
LevelChunk tickingChunk = chunkHolder.getTickingChunk();
|
||||
- if (tickingChunk != null && this.anyPlayerCloseEnoughForSpawningInternal(chunkHolder.getPos())) {
|
||||
+ if (tickingChunk != null && this.anyPlayerCloseEnoughForSpawningInternal(chunkHolder.getPos(), true)) { // Spigot
|
||||
output.add(tickingChunk);
|
||||
}
|
||||
}
|
||||
@@ -962,13 +_,35 @@
|
||||
}
|
||||
|
||||
public boolean anyPlayerCloseEnoughForSpawning(ChunkPos chunkPos) {
|
||||
- return this.distanceManager.hasPlayersNearby(chunkPos.toLong()) && this.anyPlayerCloseEnoughForSpawningInternal(chunkPos);
|
||||
+ // Spigot start
|
||||
+ return this.anyPlayerCloseEnoughForSpawning(chunkPos, false);
|
||||
+ }
|
||||
+
|
||||
+ boolean anyPlayerCloseEnoughForSpawning(ChunkPos chunkPos, boolean reducedRange) {
|
||||
+ return this.distanceManager.hasPlayersNearby(chunkPos.toLong()) && this.anyPlayerCloseEnoughForSpawningInternal(chunkPos, reducedRange);
|
||||
TriState triState = this.distanceManager.hasPlayersNearby(chunkPos.toLong());
|
||||
- return triState == TriState.DEFAULT ? this.anyPlayerCloseEnoughForSpawningInternal(chunkPos) : triState.toBoolean(true);
|
||||
+ return triState == TriState.DEFAULT ? this.anyPlayerCloseEnoughForSpawningInternal(chunkPos, reducedRange) : triState.toBoolean(true);
|
||||
+ // Spigot end
|
||||
}
|
||||
|
||||
@@ -224,12 +232,12 @@
|
||||
+ if (event == null || event.isCancelled()) continue;
|
||||
+ blockRange = (double) ((event.getSpawnRadius() << 4) * (event.getSpawnRadius() << 4));
|
||||
+ }
|
||||
+ // Paper end - PlayerNaturallySpawnCreaturesEvent
|
||||
+ if (this.playerIsCloseEnoughForSpawning(serverPlayer, chunkPos, blockRange)) {
|
||||
+ // Paper end - PlayerNaturallySpawnCreaturesEvent
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -972,7 +_,7 @@
|
||||
@@ -984,7 +_,7 @@
|
||||
Builder<ServerPlayer> builder = ImmutableList.builder();
|
||||
|
||||
for (ServerPlayer serverPlayer : this.playerMap.getAllPlayers()) {
|
||||
@@ -238,7 +246,7 @@
|
||||
builder.add(serverPlayer);
|
||||
}
|
||||
}
|
||||
@@ -981,12 +_,12 @@
|
||||
@@ -993,12 +_,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,13 +255,13 @@
|
||||
if (player.isSpectator()) {
|
||||
return false;
|
||||
} else {
|
||||
double d = euclideanDistanceSquared(chunkPos, player);
|
||||
double d = euclideanDistanceSquared(chunkPos, player.position());
|
||||
- return d < 16384.0;
|
||||
+ return d < range; // Spigot
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1100,9 +_,19 @@
|
||||
@@ -1120,9 +_,19 @@
|
||||
}
|
||||
|
||||
public void addEntity(Entity entity) {
|
||||
@@ -273,7 +281,7 @@
|
||||
if (i != 0) {
|
||||
int updateInterval = type.updateInterval();
|
||||
if (this.entityMap.containsKey(entity.getId())) {
|
||||
@@ -1126,6 +_,7 @@
|
||||
@@ -1146,6 +_,7 @@
|
||||
}
|
||||
|
||||
protected void removeEntity(Entity entity) {
|
||||
@@ -281,16 +289,7 @@
|
||||
if (entity instanceof ServerPlayer serverPlayer) {
|
||||
this.updatePlayerStatus(serverPlayer, false);
|
||||
|
||||
@@ -1230,7 +_,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
- class DistanceManager extends net.minecraft.server.level.DistanceManager {
|
||||
+ public class DistanceManager extends net.minecraft.server.level.DistanceManager { // Paper - public
|
||||
protected DistanceManager(final Executor dispatcher, final Executor mainThreadExecutor) {
|
||||
super(dispatcher, mainThreadExecutor);
|
||||
}
|
||||
@@ -1258,10 +_,10 @@
|
||||
@@ -1278,10 +_,10 @@
|
||||
final Entity entity;
|
||||
private final int range;
|
||||
SectionPos lastSectionPos;
|
||||
@@ -298,12 +297,12 @@
|
||||
+ public final Set<ServerPlayerConnection> seenBy = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(); // Paper - Perf: optimise map impl
|
||||
|
||||
public TrackedEntity(final Entity entity, final int range, final int updateInterval, final boolean trackDelta) {
|
||||
- this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, updateInterval, trackDelta, this::broadcast);
|
||||
+ this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, updateInterval, trackDelta, this::broadcast, this.seenBy); // CraftBukkit
|
||||
- this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, updateInterval, trackDelta, this::broadcast, this::broadcastIgnorePlayers);
|
||||
+ this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, updateInterval, trackDelta, this::broadcast, this::broadcastIgnorePlayers, this.seenBy); // Paper
|
||||
this.entity = entity;
|
||||
this.range = range;
|
||||
this.lastSectionPos = SectionPos.of(entity);
|
||||
@@ -1297,24 +_,47 @@
|
||||
@@ -1325,24 +_,47 @@
|
||||
}
|
||||
|
||||
public void removePlayer(ServerPlayer player) {
|
||||
@@ -356,7 +355,7 @@
|
||||
}
|
||||
} else if (this.seenBy.remove(player.connection)) {
|
||||
this.serverEntity.removePairing(player);
|
||||
@@ -1331,6 +_,7 @@
|
||||
@@ -1359,6 +_,7 @@
|
||||
|
||||
for (Entity entity : this.entity.getIndirectPassengers()) {
|
||||
int i1 = entity.getType().clientTrackingRange() * 16;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/server/level/DistanceManager.java
|
||||
+++ b/net/minecraft/server/level/DistanceManager.java
|
||||
@@ -107,6 +_,12 @@
|
||||
@@ -72,6 +_,12 @@
|
||||
}
|
||||
|
||||
if (!this.chunksToUpdateFutures.isEmpty()) {
|
||||
@@ -13,51 +13,7 @@
|
||||
for (ChunkHolder chunkHolder : this.chunksToUpdateFutures) {
|
||||
chunkHolder.updateHighestAllowedStatus(chunkMap);
|
||||
}
|
||||
@@ -177,16 +_,42 @@
|
||||
public <T> void addRegionTicket(TicketType<T> type, ChunkPos pos, int distance, T value) {
|
||||
Ticket<T> ticket = new Ticket<>(type, ChunkLevel.byStatus(FullChunkStatus.FULL) - distance, value);
|
||||
long packedChunkPos = pos.toLong();
|
||||
- this.addTicket(packedChunkPos, ticket);
|
||||
+ this.addTicket(packedChunkPos, ticket); // Paper - diff on change above
|
||||
this.tickingTicketsTracker.addTicket(packedChunkPos, ticket);
|
||||
}
|
||||
|
||||
public <T> void removeRegionTicket(TicketType<T> type, ChunkPos pos, int distance, T value) {
|
||||
Ticket<T> ticket = new Ticket<>(type, ChunkLevel.byStatus(FullChunkStatus.FULL) - distance, value);
|
||||
long packedChunkPos = pos.toLong();
|
||||
+ this.removeTicket(packedChunkPos, ticket); // Paper - diff on change above
|
||||
+ this.tickingTicketsTracker.removeTicket(packedChunkPos, ticket);
|
||||
+ }
|
||||
+
|
||||
+ // Paper start
|
||||
+ public boolean addPluginRegionTicket(final ChunkPos pos, final org.bukkit.plugin.Plugin value) {
|
||||
+ Ticket<org.bukkit.plugin.Plugin> ticket = new Ticket<>(TicketType.PLUGIN_TICKET, ChunkLevel.byStatus(FullChunkStatus.FULL) - 2, value); // Copied from below and keep in-line with force loading, add at level 31
|
||||
+ final long packedChunkPos = pos.toLong();
|
||||
+ final Set<Ticket<?>> tickets = this.getTickets(packedChunkPos);
|
||||
+ if (tickets.contains(ticket)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ this.addTicket(packedChunkPos, ticket);
|
||||
+ this.tickingTicketsTracker.addTicket(packedChunkPos, ticket);
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ public boolean removePluginRegionTicket(final ChunkPos pos, final org.bukkit.plugin.Plugin value) {
|
||||
+ Ticket<org.bukkit.plugin.Plugin> ticket = new Ticket<>(TicketType.PLUGIN_TICKET, ChunkLevel.byStatus(FullChunkStatus.FULL) - 2, value); // Copied from below and keep in-line with force loading, add at level 31
|
||||
+ final long packedChunkPos = pos.toLong();
|
||||
+ final Set<Ticket<?>> tickets = this.tickets.get(packedChunkPos); // Don't use getTickets, we don't want to create a new set
|
||||
+ if (tickets == null || !tickets.contains(ticket)) {
|
||||
+ return false;
|
||||
+ }
|
||||
this.removeTicket(packedChunkPos, ticket);
|
||||
this.tickingTicketsTracker.removeTicket(packedChunkPos, ticket);
|
||||
+ return true;
|
||||
}
|
||||
+ // Paper end
|
||||
|
||||
private SortedArraySet<Ticket<?>> getTickets(long chunkPos) {
|
||||
return this.tickets.computeIfAbsent(chunkPos, l -> SortedArraySet.create(4));
|
||||
@@ -217,8 +_,10 @@
|
||||
@@ -121,8 +_,10 @@
|
||||
ChunkPos chunkPos = sectionPos.chunk();
|
||||
long packedChunkPos = chunkPos.toLong();
|
||||
ObjectSet<ServerPlayer> set = this.playersPerChunk.get(packedChunkPos);
|
||||
@@ -70,39 +26,3 @@
|
||||
this.playersPerChunk.remove(packedChunkPos);
|
||||
this.naturalSpawnChunkCounter.update(packedChunkPos, Integer.MAX_VALUE, false);
|
||||
this.playerTicketManager.update(packedChunkPos, Integer.MAX_VALUE, false);
|
||||
@@ -299,7 +_,7 @@
|
||||
}
|
||||
|
||||
public void removeTicketsOnClosing() {
|
||||
- ImmutableSet<TicketType<?>> set = ImmutableSet.of(TicketType.UNKNOWN);
|
||||
+ ImmutableSet<TicketType<?>> set = 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()) {
|
||||
@@ -329,6 +_,26 @@
|
||||
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);
|
||||
+
|
||||
+ for (java.util.Iterator<Entry<SortedArraySet<Ticket<?>>>> iterator = this.tickets.long2ObjectEntrySet().fastIterator(); iterator.hasNext();) {
|
||||
+ Entry<SortedArraySet<Ticket<?>>> entry = iterator.next();
|
||||
+ SortedArraySet<Ticket<?>> tickets = entry.getValue();
|
||||
+ if (tickets.remove(target)) {
|
||||
+ // copied from removeTicket
|
||||
+ this.ticketTracker.update(entry.getLongKey(), DistanceManager.getTicketLevelAt(tickets), false);
|
||||
+
|
||||
+ // can't use entry after it's removed
|
||||
+ if (tickets.isEmpty()) {
|
||||
+ iterator.remove();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
|
||||
class ChunkTicketTracker extends ChunkTracker {
|
||||
private static final int MAX_LEVEL = ChunkLevel.MAX_LEVEL + 1;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -73,6 +_,13 @@
|
||||
@@ -77,6 +_,13 @@
|
||||
@Nullable
|
||||
@VisibleForDebug
|
||||
private NaturalSpawner.SpawnState lastSpawnState;
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
public ServerChunkCache(
|
||||
ServerLevel level,
|
||||
@@ -121,6 +_,64 @@
|
||||
@@ -127,6 +_,64 @@
|
||||
this.clearCache();
|
||||
}
|
||||
|
||||
@@ -46,12 +46,12 @@
|
||||
+ return holder.getLatestChunk();
|
||||
+ }
|
||||
+
|
||||
+ public <T> void addTicketAtLevel(TicketType<T> ticketType, ChunkPos chunkPos, int ticketLevel, T identifier) {
|
||||
+ this.distanceManager.addTicket(ticketType, chunkPos, ticketLevel, identifier);
|
||||
+ public void addTicketAtLevel(TicketType ticketType, ChunkPos chunkPos, int ticketLevel) {
|
||||
+ this.ticketStorage.addTicket(new Ticket(ticketType, ticketLevel), chunkPos);
|
||||
+ }
|
||||
+
|
||||
+ public <T> void removeTicketAtLevel(TicketType<T> ticketType, ChunkPos chunkPos, int ticketLevel, T identifier) {
|
||||
+ this.distanceManager.removeTicket(ticketType, chunkPos, ticketLevel, identifier);
|
||||
+ public void removeTicketAtLevel(TicketType ticketType, ChunkPos chunkPos, int ticketLevel) {
|
||||
+ this.ticketStorage.removeTicket(new Ticket(ticketType, ticketLevel), chunkPos);
|
||||
+ }
|
||||
+
|
||||
+ // "real" get chunk if loaded
|
||||
@@ -79,7 +79,7 @@
|
||||
@Override
|
||||
public ThreadedLevelLightEngine getLightEngine() {
|
||||
return this.lightEngine;
|
||||
@@ -160,7 +_,7 @@
|
||||
@@ -166,7 +_,7 @@
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (packedChunkPos == this.lastChunkPos[i] && chunkStatus == this.lastChunkStatus[i]) {
|
||||
ChunkAccess chunkAccess = this.lastChunk[i];
|
||||
@@ -88,7 +88,7 @@
|
||||
return chunkAccess;
|
||||
}
|
||||
}
|
||||
@@ -169,6 +_,7 @@
|
||||
@@ -175,6 +_,7 @@
|
||||
profilerFiller.incrementCounter("getChunkCacheMiss");
|
||||
CompletableFuture<ChunkResult<ChunkAccess>> chunkFutureMainThread = this.getChunkFutureMainThread(x, z, chunkStatus, requireChunk);
|
||||
this.mainThreadProcessor.managedBlock(chunkFutureMainThread::isDone);
|
||||
@@ -96,7 +96,7 @@
|
||||
ChunkResult<ChunkAccess> chunkResult = chunkFutureMainThread.join();
|
||||
ChunkAccess chunkAccess1 = chunkResult.orElse(null);
|
||||
if (chunkAccess1 == null && requireChunk) {
|
||||
@@ -240,7 +_,15 @@
|
||||
@@ -246,7 +_,15 @@
|
||||
long packedChunkPos = chunkPos.toLong();
|
||||
int i = ChunkLevel.byStatus(chunkStatus);
|
||||
ChunkHolder visibleChunkIfPresent = this.getVisibleChunkIfPresent(packedChunkPos);
|
||||
@@ -109,11 +109,11 @@
|
||||
+ currentlyUnloading = (oldChunkState.isOrAfter(FullChunkStatus.FULL) && !currentChunkState.isOrAfter(FullChunkStatus.FULL));
|
||||
+ }
|
||||
+ if (requireChunk && !currentlyUnloading) {
|
||||
+ // CraftBukkit end
|
||||
this.distanceManager.addTicket(TicketType.UNKNOWN, chunkPos, i, chunkPos);
|
||||
+ // CraftBukkit end
|
||||
this.addTicket(new Ticket(TicketType.UNKNOWN, i), chunkPos);
|
||||
if (this.chunkAbsent(visibleChunkIfPresent, i)) {
|
||||
ProfilerFiller profilerFiller = Profiler.get();
|
||||
@@ -260,7 +_,7 @@
|
||||
@@ -266,7 +_,7 @@
|
||||
}
|
||||
|
||||
private boolean chunkAbsent(@Nullable ChunkHolder chunkHolder, int status) {
|
||||
@@ -122,16 +122,7 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -287,7 +_,7 @@
|
||||
return this.mainThreadProcessor.pollTask();
|
||||
}
|
||||
|
||||
- boolean runDistanceManagerUpdates() {
|
||||
+ public boolean runDistanceManagerUpdates() { // Paper - public
|
||||
boolean flag = this.distanceManager.runAllUpdates(this.chunkMap);
|
||||
boolean flag1 = this.chunkMap.promoteChunkMap();
|
||||
this.chunkMap.runGenerationTasks();
|
||||
@@ -315,17 +_,39 @@
|
||||
@@ -321,17 +_,39 @@
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
@@ -155,7 +146,7 @@
|
||||
+ ProfilerFiller gameprofilerfiller = Profiler.get();
|
||||
+
|
||||
+ gameprofilerfiller.push("purge");
|
||||
+ this.distanceManager.purgeStaleTickets();
|
||||
+ this.ticketStorage.purgeStaleTickets();
|
||||
+ this.runDistanceManagerUpdates();
|
||||
+ gameprofilerfiller.popPush("unload");
|
||||
+ this.chunkMap.tick(() -> true);
|
||||
@@ -170,10 +161,10 @@
|
||||
profilerFiller.push("purge");
|
||||
- if (this.level.tickRateManager().runsNormally() || !tickChunks) {
|
||||
+ if (this.level.tickRateManager().runsNormally() || !tickChunks || this.level.spigotConfig.unloadFrozenChunks) { // Spigot
|
||||
this.distanceManager.purgeStaleTickets();
|
||||
this.ticketStorage.purgeStaleTickets();
|
||||
}
|
||||
|
||||
@@ -400,12 +_,20 @@
|
||||
@@ -388,12 +_,20 @@
|
||||
);
|
||||
this.lastSpawnState = spawnState;
|
||||
profiler.popPush("spawnAndTick");
|
||||
@@ -197,16 +188,7 @@
|
||||
} else {
|
||||
filteredSpawningCategories = List.of();
|
||||
}
|
||||
@@ -413,7 +_,7 @@
|
||||
for (LevelChunk levelChunk : chunks) {
|
||||
ChunkPos pos = levelChunk.getPos();
|
||||
levelChunk.incrementInhabitedTime(timeInhabited);
|
||||
- if (!filteredSpawningCategories.isEmpty() && this.level.getWorldBorder().isWithinBounds(pos)) {
|
||||
+ if (!filteredSpawningCategories.isEmpty() && this.level.getWorldBorder().isWithinBounds(pos) && this.chunkMap.anyPlayerCloseEnoughForSpawning(pos, true)) { // Spigot
|
||||
NaturalSpawner.spawnForChunk(this.level, levelChunk, spawnState, filteredSpawningCategories);
|
||||
}
|
||||
|
||||
@@ -526,8 +_,13 @@
|
||||
@@ -544,8 +_,13 @@
|
||||
|
||||
@Override
|
||||
public void setSpawnSettings(boolean spawnSettings) {
|
||||
@@ -221,7 +203,7 @@
|
||||
}
|
||||
|
||||
public String getChunkDebugData(ChunkPos chunkPos) {
|
||||
@@ -603,12 +_,18 @@
|
||||
@@ -618,12 +_,18 @@
|
||||
|
||||
@Override
|
||||
public boolean pollTask() {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/server/level/ServerEntity.java
|
||||
+++ b/net/minecraft/server/level/ServerEntity.java
|
||||
@@ -65,13 +_,17 @@
|
||||
@@ -69,11 +_,12 @@
|
||||
private Vec3 lastSentMovement;
|
||||
private int tickCount;
|
||||
private int teleportDelay;
|
||||
@@ -10,26 +10,25 @@
|
||||
private boolean wasOnGround;
|
||||
@Nullable
|
||||
private List<SynchedEntityData.DataValue<?>> trackedDataValues;
|
||||
+ private final Set<net.minecraft.server.network.ServerPlayerConnection> trackedPlayers; // Paper
|
||||
|
||||
- public ServerEntity(ServerLevel level, Entity entity, int updateInterval, boolean trackDelta, Consumer<Packet<?>> broadcast) {
|
||||
+ // CraftBukkit start
|
||||
+ private final Set<net.minecraft.server.network.ServerPlayerConnection> trackedPlayers;
|
||||
+ public ServerEntity(ServerLevel level, Entity entity, int updateInterval, boolean trackDelta, Consumer<Packet<?>> broadcast, final Set<net.minecraft.server.network.ServerPlayerConnection> trackedPlayers) {
|
||||
+ this.trackedPlayers = trackedPlayers;
|
||||
+ // CraftBukkit end
|
||||
public ServerEntity(
|
||||
ServerLevel level,
|
||||
@@ -81,8 +_,12 @@
|
||||
int updateInterval,
|
||||
boolean trackDelta,
|
||||
Consumer<Packet<?>> broadcast,
|
||||
- BiConsumer<Packet<?>, List<UUID>> broadcastWithIgnore
|
||||
+ // Paper start
|
||||
+ BiConsumer<Packet<?>, List<UUID>> broadcastWithIgnore,
|
||||
+ final Set<net.minecraft.server.network.ServerPlayerConnection> trackedPlayers
|
||||
+ // Paper end
|
||||
) {
|
||||
+ this.trackedPlayers = trackedPlayers; // Paper
|
||||
this.level = level;
|
||||
this.broadcast = broadcast;
|
||||
this.entity = entity;
|
||||
@@ -89,7 +_,7 @@
|
||||
public void sendChanges() {
|
||||
List<Entity> passengers = this.entity.getPassengers();
|
||||
if (!passengers.equals(this.lastPassengers)) {
|
||||
- this.broadcast.accept(new ClientboundSetPassengersPacket(this.entity));
|
||||
+ this.broadcastAndSend(new ClientboundSetPassengersPacket(this.entity)); // CraftBukkit
|
||||
removedPassengers(passengers, this.lastPassengers)
|
||||
.forEach(
|
||||
removedPassenger -> {
|
||||
@@ -102,13 +_,14 @@
|
||||
@@ -106,13 +_,14 @@
|
||||
this.lastPassengers = passengers;
|
||||
}
|
||||
|
||||
@@ -48,7 +47,7 @@
|
||||
savedData.tickCarriedBy(serverPlayer, item);
|
||||
Packet<?> updatePacket = savedData.getUpdatePacket(mapId, serverPlayer);
|
||||
if (updatePacket != null) {
|
||||
@@ -141,7 +_,13 @@
|
||||
@@ -145,7 +_,13 @@
|
||||
} else {
|
||||
this.teleportDelay++;
|
||||
Vec3 vec3 = this.entity.trackingPosition();
|
||||
@@ -63,7 +62,7 @@
|
||||
Packet<?> packet = null;
|
||||
boolean flag2 = flag1 || this.tickCount % 60 == 0;
|
||||
boolean flag3 = false;
|
||||
@@ -219,6 +_,25 @@
|
||||
@@ -223,6 +_,25 @@
|
||||
|
||||
this.tickCount++;
|
||||
if (this.entity.hurtMarked) {
|
||||
@@ -89,7 +88,7 @@
|
||||
this.entity.hurtMarked = false;
|
||||
this.broadcastAndSend(new ClientboundSetEntityMotionPacket(this.entity));
|
||||
}
|
||||
@@ -273,7 +_,10 @@
|
||||
@@ -280,7 +_,10 @@
|
||||
|
||||
public void sendPairingData(ServerPlayer player, Consumer<Packet<ClientGamePacketListener>> consumer) {
|
||||
if (this.entity.isRemoved()) {
|
||||
@@ -101,7 +100,7 @@
|
||||
}
|
||||
|
||||
Packet<ClientGamePacketListener> addEntityPacket = this.entity.getAddEntityPacket(this);
|
||||
@@ -285,6 +_,12 @@
|
||||
@@ -292,6 +_,12 @@
|
||||
boolean flag = this.trackDelta;
|
||||
if (this.entity instanceof LivingEntity) {
|
||||
Collection<AttributeInstance> syncableAttributes = ((LivingEntity)this.entity).getAttributes().getSyncableAttributes();
|
||||
@@ -114,18 +113,18 @@
|
||||
if (!syncableAttributes.isEmpty()) {
|
||||
consumer.accept(new ClientboundUpdateAttributesPacket(this.entity.getId(), syncableAttributes));
|
||||
}
|
||||
@@ -309,8 +_,9 @@
|
||||
@@ -316,8 +_,9 @@
|
||||
}
|
||||
|
||||
if (!list.isEmpty()) {
|
||||
- consumer.accept(new ClientboundSetEquipmentPacket(this.entity.getId(), list));
|
||||
+ consumer.accept(new ClientboundSetEquipmentPacket(this.entity.getId(), list, true)); // Paper - data sanitization
|
||||
}
|
||||
+ ((LivingEntity) this.entity).detectEquipmentUpdatesPublic(); // CraftBukkit - SPIGOT-3789: sync again immediately after sending
|
||||
+ ((LivingEntity) this.entity).detectEquipmentUpdates(); // CraftBukkit - SPIGOT-3789: sync again immediately after sending
|
||||
}
|
||||
|
||||
if (!this.entity.getPassengers().isEmpty()) {
|
||||
@@ -357,6 +_,11 @@
|
||||
@@ -364,6 +_,11 @@
|
||||
if (this.entity instanceof LivingEntity) {
|
||||
Set<AttributeInstance> attributesToSync = ((LivingEntity)this.entity).getAttributes().getAttributesToSync();
|
||||
if (!attributesToSync.isEmpty()) {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -182,7 +_,7 @@
|
||||
@@ -178,7 +_,7 @@
|
||||
final List<ServerPlayer> players = Lists.newArrayList();
|
||||
public final ServerChunkCache chunkSource;
|
||||
private final MinecraftServer server;
|
||||
@@ -9,17 +9,18 @@
|
||||
private int lastSpawnChunkRadius;
|
||||
final EntityTickList entityTickList = new EntityTickList();
|
||||
public final PersistentEntitySectionManager<Entity> entityManager;
|
||||
@@ -209,11 +_,132 @@
|
||||
@@ -205,11 +_,131 @@
|
||||
private final boolean tickTime;
|
||||
private final RandomSequences randomSequences;
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ public final LevelStorageSource.LevelStorageAccess levelStorageAccess;
|
||||
+ public final UUID uuid;
|
||||
+ public final java.util.UUID uuid;
|
||||
+ public boolean hasPhysicsEvent = true; // Paper - BlockPhysicsEvent
|
||||
+ public boolean hasEntityMoveEvent; // Paper - Add EntityMoveEvent
|
||||
+
|
||||
+ public LevelChunk getChunkIfLoaded(int x, int z) {
|
||||
+ @Override
|
||||
+ public @Nullable LevelChunk getChunkIfLoaded(int x, int z) {
|
||||
+ return this.chunkSource.getChunkAtIfLoadedImmediately(x, z); // Paper - Use getChunkIfLoadedImmediately
|
||||
+ }
|
||||
+
|
||||
@@ -91,14 +92,12 @@
|
||||
+ 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);
|
||||
+ chunkProvider.addTicketAtLevel(TicketType.FUTURE_AWAIT, chunk.getPos(), ticketLevel);
|
||||
+ }
|
||||
+ if (++loadedChunks[0] == requiredChunks) {
|
||||
+ try {
|
||||
@@ -108,8 +107,8 @@
|
||||
+ 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);
|
||||
+ chunkProvider.addTicketAtLevel(TicketType.UNKNOWN, chunkPos, ticketLevel);
|
||||
+ chunkProvider.removeTicketAtLevel(TicketType.FUTURE_AWAIT, chunkPos, ticketLevel);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
@@ -128,7 +127,7 @@
|
||||
+ // Paper start - optimise getPlayerByUUID
|
||||
+ @Nullable
|
||||
+ @Override
|
||||
+ public Player getPlayerByUUID(UUID uuid) {
|
||||
+ public Player getPlayerByUUID(java.util.UUID uuid) {
|
||||
+ final Player player = this.getServer().getPlayerList().getPlayer(uuid);
|
||||
+ return player != null && player.level() == this ? player : null;
|
||||
+ }
|
||||
@@ -143,7 +142,7 @@
|
||||
ResourceKey<Level> dimension,
|
||||
LevelStem levelStem,
|
||||
ChunkProgressListener progressListener,
|
||||
@@ -221,14 +_,38 @@
|
||||
@@ -217,14 +_,38 @@
|
||||
long biomeZoomSeed,
|
||||
List<CustomSpawner> customSpawners,
|
||||
boolean tickTime,
|
||||
@@ -158,7 +157,7 @@
|
||||
+ super(serverLevelData, dimension, server.registryAccess(), levelStem.type(), false, isDebug, biomeZoomSeed, server.getMaxChainedNeighborUpdates(), gen, biomeProvider, env, spigotConfig -> server.paperConfigurations.createWorldConfig(io.papermc.paper.configuration.PaperConfigurations.createWorldContextMap(levelStorageAccess.levelDirectory.path(), serverLevelData.getLevelName(), dimension.location(), spigotConfig, server.registryAccess(), serverLevelData.getGameRules()))); // Paper - create paper world configs
|
||||
+ this.pvpMode = server.isPvpAllowed();
|
||||
+ this.levelStorageAccess = levelStorageAccess;
|
||||
+ this.uuid = org.bukkit.craftbukkit.util.WorldUUID.getUUID(levelStorageAccess.levelDirectory.path().toFile());
|
||||
+ this.uuid = org.bukkit.craftbukkit.util.WorldUUID.getOrCreate(levelStorageAccess.levelDirectory.path().toFile());
|
||||
+ // CraftBukkit end
|
||||
this.tickTime = tickTime;
|
||||
this.server = server;
|
||||
@@ -184,7 +183,7 @@
|
||||
boolean flag = server.forceSynchronousWrites();
|
||||
DataFixer fixerUpper = server.getFixerUpper();
|
||||
EntityPersistentStorage<Entity> entityPersistentStorage = new EntityStorage(
|
||||
@@ -250,8 +_,8 @@
|
||||
@@ -246,8 +_,8 @@
|
||||
server.getStructureManager(),
|
||||
dispatcher,
|
||||
chunkGenerator,
|
||||
@@ -195,7 +194,7 @@
|
||||
flag,
|
||||
progressListener,
|
||||
this.entityManager::updateChunkStatus,
|
||||
@@ -272,7 +_,7 @@
|
||||
@@ -268,7 +_,7 @@
|
||||
this.chunkSource.chunkScanner(),
|
||||
this.registryAccess(),
|
||||
server.getStructureManager(),
|
||||
@@ -204,7 +203,7 @@
|
||||
chunkGenerator,
|
||||
this.chunkSource.randomState(),
|
||||
this,
|
||||
@@ -280,9 +_,9 @@
|
||||
@@ -276,9 +_,9 @@
|
||||
seed,
|
||||
fixerUpper
|
||||
);
|
||||
@@ -217,10 +216,10 @@
|
||||
} else {
|
||||
this.dragonFight = null;
|
||||
}
|
||||
@@ -292,7 +_,15 @@
|
||||
this.randomSequences = Objects.requireNonNullElseGet(
|
||||
randomSequences, () -> this.getDataStorage().computeIfAbsent(RandomSequences.factory(seed), "random_sequences")
|
||||
);
|
||||
@@ -286,7 +_,15 @@
|
||||
this.sleepStatus = new SleepStatus();
|
||||
this.gameEventDispatcher = new GameEventDispatcher(this);
|
||||
this.randomSequences = Objects.requireNonNullElseGet(randomSequences, () -> this.getDataStorage().computeIfAbsent(RandomSequences.TYPE));
|
||||
- }
|
||||
+ this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit
|
||||
+ }
|
||||
@@ -234,7 +233,7 @@
|
||||
|
||||
@Deprecated
|
||||
@VisibleForTesting
|
||||
@@ -304,8 +_,8 @@
|
||||
@@ -298,8 +_,8 @@
|
||||
this.serverLevelData.setClearWeatherTime(clearTime);
|
||||
this.serverLevelData.setRainTime(weatherTime);
|
||||
this.serverLevelData.setThunderTime(weatherTime);
|
||||
@@ -245,7 +244,7 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -332,12 +_,25 @@
|
||||
@@ -326,12 +_,25 @@
|
||||
|
||||
int _int = this.getGameRules().getInt(GameRules.RULE_PLAYERS_SLEEPING_PERCENTAGE);
|
||||
if (this.sleepStatus.areEnoughSleeping(_int) && this.sleepStatus.areEnoughDeepSleeping(_int, this.players)) {
|
||||
@@ -274,7 +273,7 @@
|
||||
if (this.getGameRules().getBoolean(GameRules.RULE_WEATHER_CYCLE) && this.isRaining()) {
|
||||
this.resetWeatherCycle();
|
||||
}
|
||||
@@ -352,9 +_,9 @@
|
||||
@@ -346,9 +_,9 @@
|
||||
if (!this.isDebug() && runsNormally) {
|
||||
long l = this.getGameTime();
|
||||
profilerFiller.push("blockTicks");
|
||||
@@ -286,16 +285,30 @@
|
||||
profilerFiller.pop();
|
||||
}
|
||||
|
||||
@@ -372,7 +_,7 @@
|
||||
@@ -366,7 +_,7 @@
|
||||
|
||||
this.handlingTick = false;
|
||||
profilerFiller.pop();
|
||||
- boolean flag = !this.players.isEmpty() || !this.getForcedChunks().isEmpty();
|
||||
+ boolean flag = !paperConfig().unsupportedSettings.disableWorldTickingWhenEmpty || !this.players.isEmpty() || !this.getForcedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players // Paper - restore this
|
||||
- boolean flag = !this.players.isEmpty() || !this.getForceLoadedChunks().isEmpty();
|
||||
+ boolean flag = !paperConfig().unsupportedSettings.disableWorldTickingWhenEmpty || !this.players.isEmpty() || !this.getForceLoadedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players // Paper - restore this
|
||||
if (flag) {
|
||||
this.resetEmptyTime();
|
||||
}
|
||||
@@ -461,12 +_,12 @@
|
||||
@@ -455,11 +_,13 @@
|
||||
ProfilerFiller profilerFiller = Profiler.get();
|
||||
profilerFiller.push("iceandsnow");
|
||||
|
||||
+ if (!this.paperConfig().environment.disableIceAndSnow) { // Paper - Option to disable ice and snow
|
||||
for (int i = 0; i < randomTickSpeed; i++) {
|
||||
if (this.random.nextInt(48) == 0) {
|
||||
this.tickPrecipitation(this.getBlockRandomPos(minBlockX, 0, minBlockZ, 15));
|
||||
}
|
||||
}
|
||||
+ } // Paper - Option to disable ice and snow
|
||||
|
||||
profilerFiller.popPush("tickBlocks");
|
||||
if (randomTickSpeed > 0) {
|
||||
@@ -502,12 +_,12 @@
|
||||
int minBlockZ = pos.getMinBlockZ();
|
||||
ProfilerFiller profilerFiller = Profiler.get();
|
||||
profilerFiller.push("thunder");
|
||||
@@ -310,7 +323,7 @@
|
||||
&& !this.getBlockState(blockPos.below()).is(Blocks.LIGHTNING_ROD);
|
||||
if (flag) {
|
||||
SkeletonHorse skeletonHorse = EntityType.SKELETON_HORSE.create(this, EntitySpawnReason.EVENT);
|
||||
@@ -474,7 +_,7 @@
|
||||
@@ -515,7 +_,7 @@
|
||||
skeletonHorse.setTrap(true);
|
||||
skeletonHorse.setAge(0);
|
||||
skeletonHorse.setPos(blockPos.getX(), blockPos.getY(), blockPos.getZ());
|
||||
@@ -319,63 +332,51 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -482,18 +_,20 @@
|
||||
@@ -523,7 +_,7 @@
|
||||
if (lightningBolt != null) {
|
||||
lightningBolt.moveTo(Vec3.atBottomCenterOf(blockPos));
|
||||
lightningBolt.snapTo(Vec3.atBottomCenterOf(blockPos));
|
||||
lightningBolt.setVisualOnly(flag);
|
||||
- this.addFreshEntity(lightningBolt);
|
||||
+ this.strikeLightning(lightningBolt, org.bukkit.event.weather.LightningStrikeEvent.Cause.WEATHER); // CraftBukkit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
profilerFiller.popPush("iceandsnow");
|
||||
|
||||
+ if (!this.paperConfig().environment.disableIceAndSnow) { // Paper - Option to disable ice and snow
|
||||
for (int i = 0; i < randomTickSpeed; i++) {
|
||||
if (this.random.nextInt(48) == 0) {
|
||||
this.tickPrecipitation(this.getBlockRandomPos(minBlockX, 0, minBlockZ, 15));
|
||||
}
|
||||
}
|
||||
+ } // Paper - Option to disable ice and snow
|
||||
|
||||
profilerFiller.popPush("tickBlocks");
|
||||
if (randomTickSpeed > 0) {
|
||||
@@ -535,7 +_,7 @@
|
||||
@@ -537,7 +_,7 @@
|
||||
BlockPos blockPos1 = heightmapPos.below();
|
||||
Biome biome = this.getBiome(heightmapPos).value();
|
||||
if (biome.shouldFreeze(this, blockPos1)) {
|
||||
- this.setBlockAndUpdate(blockPos1, Blocks.ICE.defaultBlockState());
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockPos1, Blocks.ICE.defaultBlockState(), null); // CraftBukkit
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockPos1, Blocks.ICE.defaultBlockState(), 3, null); // CraftBukkit
|
||||
}
|
||||
|
||||
if (this.isRaining()) {
|
||||
@@ -547,10 +_,10 @@
|
||||
@@ -549,10 +_,10 @@
|
||||
if (layersValue < Math.min(_int, 8)) {
|
||||
BlockState blockState1 = blockState.setValue(SnowLayerBlock.LAYERS, Integer.valueOf(layersValue + 1));
|
||||
BlockState blockState1 = blockState.setValue(SnowLayerBlock.LAYERS, layersValue + 1);
|
||||
Block.pushEntitiesUp(blockState, blockState1, this, heightmapPos);
|
||||
- this.setBlockAndUpdate(heightmapPos, blockState1);
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, heightmapPos, blockState1, null); // CraftBukkit
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, heightmapPos, blockState1, 3, null); // CraftBukkit
|
||||
}
|
||||
} else {
|
||||
- this.setBlockAndUpdate(heightmapPos, Blocks.SNOW.defaultBlockState());
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, heightmapPos, Blocks.SNOW.defaultBlockState(), null); // CraftBukkit
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, heightmapPos, Blocks.SNOW.defaultBlockState(), 3, null); // CraftBukkit
|
||||
}
|
||||
}
|
||||
|
||||
@@ -575,6 +_,11 @@
|
||||
@@ -577,6 +_,12 @@
|
||||
}
|
||||
|
||||
protected BlockPos findLightningTargetAround(BlockPos pos) {
|
||||
+ // Paper start - Add methods to find targets for lightning strikes
|
||||
+ return this.findLightningTargetAround(pos, false);
|
||||
+ }
|
||||
+
|
||||
+ public BlockPos findLightningTargetAround(BlockPos pos, boolean returnNullWhenNoTarget) {
|
||||
+ // Paper end - Add methods to find targets for lightning strikes
|
||||
BlockPos heightmapPos = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, pos);
|
||||
Optional<BlockPos> optional = this.findLightningRod(heightmapPos);
|
||||
if (optional.isPresent()) {
|
||||
@@ -582,11 +_,12 @@
|
||||
@@ -584,11 +_,12 @@
|
||||
} else {
|
||||
AABB aabb = AABB.encapsulatingFullBlocks(heightmapPos, heightmapPos.atY(this.getMaxY() + 1)).inflate(3.0);
|
||||
List<LivingEntity> entitiesOfClass = this.getEntitiesOfClass(
|
||||
@@ -389,7 +390,7 @@
|
||||
if (heightmapPos.getY() == this.getMinY() - 1) {
|
||||
heightmapPos = heightmapPos.above(2);
|
||||
}
|
||||
@@ -673,8 +_,8 @@
|
||||
@@ -675,8 +_,8 @@
|
||||
this.serverLevelData.setThunderTime(thunderTime);
|
||||
this.serverLevelData.setRainTime(rainTime);
|
||||
this.serverLevelData.setClearWeatherTime(clearWeatherTime);
|
||||
@@ -400,7 +401,7 @@
|
||||
}
|
||||
|
||||
this.oThunderLevel = this.thunderLevel;
|
||||
@@ -695,6 +_,7 @@
|
||||
@@ -697,6 +_,7 @@
|
||||
this.rainLevel = Mth.clamp(this.rainLevel, 0.0F, 1.0F);
|
||||
}
|
||||
|
||||
@@ -408,7 +409,7 @@
|
||||
if (this.oRainLevel != this.rainLevel) {
|
||||
this.server
|
||||
.getPlayerList()
|
||||
@@ -717,14 +_,47 @@
|
||||
@@ -719,14 +_,47 @@
|
||||
this.server.getPlayerList().broadcastAll(new ClientboundGameEventPacket(ClientboundGameEventPacket.RAIN_LEVEL_CHANGE, this.rainLevel));
|
||||
this.server.getPlayerList().broadcastAll(new ClientboundGameEventPacket(ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, this.thunderLevel));
|
||||
}
|
||||
@@ -460,7 +461,7 @@
|
||||
}
|
||||
|
||||
public void resetEmptyTime() {
|
||||
@@ -746,18 +_,46 @@
|
||||
@@ -748,18 +_,46 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -507,7 +508,7 @@
|
||||
}
|
||||
|
||||
private void tickPassenger(Entity ridingEntity, Entity passengerEntity) {
|
||||
@@ -766,10 +_,12 @@
|
||||
@@ -768,10 +_,12 @@
|
||||
} else if (passengerEntity instanceof Player || this.entityTickList.contains(passengerEntity)) {
|
||||
passengerEntity.setOldPosAndRot();
|
||||
passengerEntity.tickCount++;
|
||||
@@ -520,7 +521,7 @@
|
||||
profilerFiller.pop();
|
||||
|
||||
for (Entity entity : passengerEntity.getPassengers()) {
|
||||
@@ -786,6 +_,7 @@
|
||||
@@ -788,6 +_,7 @@
|
||||
public void save(@Nullable ProgressListener progress, boolean flush, boolean skipSave) {
|
||||
ServerChunkCache chunkSource = this.getChunkSource();
|
||||
if (!skipSave) {
|
||||
@@ -528,15 +529,15 @@
|
||||
if (progress != null) {
|
||||
progress.progressStartNoAbort(Component.translatable("menu.savingLevel"));
|
||||
}
|
||||
@@ -802,11 +_,19 @@
|
||||
@@ -804,11 +_,19 @@
|
||||
this.entityManager.autoSave();
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // CraftBukkit start - moved from MinecraftServer.saveChunks
|
||||
+ ServerLevel worldserver1 = this;
|
||||
+ // CraftBukkit start - moved from MinecraftServer#saveAllChunks
|
||||
+ ServerLevel serverLevel1 = this;
|
||||
+
|
||||
+ this.serverLevelData.setWorldBorder(worldserver1.getWorldBorder().createSettings());
|
||||
+ this.serverLevelData.setWorldBorder(serverLevel1.getWorldBorder().createSettings());
|
||||
+ this.serverLevelData.setCustomBossEvents(this.server.getCustomBossEvents().save(this.registryAccess()));
|
||||
+ this.levelStorageAccess.saveDataTag(this.server.registryAccess(), this.serverLevelData, this.server.getPlayerList().getSingleplayerData());
|
||||
+ // CraftBukkit end
|
||||
@@ -549,7 +550,7 @@
|
||||
}
|
||||
|
||||
DimensionDataStorage dataStorage = this.getChunkSource().getDataStorage();
|
||||
@@ -871,18 +_,40 @@
|
||||
@@ -873,18 +_,40 @@
|
||||
|
||||
@Override
|
||||
public boolean addFreshEntity(Entity entity) {
|
||||
@@ -559,7 +560,7 @@
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean addFreshEntity(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) {
|
||||
+ public boolean addFreshEntity(Entity entity, @Nullable org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) {
|
||||
+ return this.addEntity(entity, reason);
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
@@ -570,7 +571,7 @@
|
||||
+ return this.addWithUUID(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT);
|
||||
+ }
|
||||
+
|
||||
+ public boolean addWithUUID(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) {
|
||||
+ public boolean addWithUUID(Entity entity, @Nullable org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) {
|
||||
+ return this.addEntity(entity, reason);
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
@@ -583,7 +584,7 @@
|
||||
+ this.addDuringTeleport(entity, null);
|
||||
+ }
|
||||
+
|
||||
+ public void addDuringTeleport(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) {
|
||||
+ public void addDuringTeleport(Entity entity, @Nullable org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) {
|
||||
+ // CraftBukkit end
|
||||
if (entity instanceof ServerPlayer serverPlayer) {
|
||||
this.addPlayer(serverPlayer);
|
||||
@@ -593,13 +594,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -905,40 +_,119 @@
|
||||
@@ -907,40 +_,119 @@
|
||||
this.entityManager.addNewEntity(player);
|
||||
}
|
||||
|
||||
- private boolean addEntity(Entity entity) {
|
||||
+ // CraftBukkit start
|
||||
+ private boolean addEntity(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) {
|
||||
+ private boolean addEntity(Entity entity, @Nullable org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot
|
||||
+ entity.generation = false; // Paper - Don't fire sync event during generation; Reset flag if it was added during a ServerLevel generation process
|
||||
+ // Paper start - extra debug info
|
||||
@@ -718,16 +719,16 @@
|
||||
if (d * d + d1 * d1 + d2 * d2 < 1024.0) {
|
||||
serverPlayer.connection.send(new ClientboundBlockDestructionPacket(breakerId, pos, progress));
|
||||
}
|
||||
@@ -1000,7 +_,7 @@
|
||||
public void levelEvent(@Nullable Player player, int type, BlockPos pos, int data) {
|
||||
this.server
|
||||
.getPlayerList()
|
||||
- .broadcast(player, pos.getX(), pos.getY(), pos.getZ(), 64.0, this.dimension(), new ClientboundLevelEventPacket(type, pos, data, false));
|
||||
+ .broadcast(player, pos.getX(), pos.getY(), pos.getZ(), 64.0, this.dimension(), new ClientboundLevelEventPacket(type, pos, data, false)); // Paper - diff on change (the 64.0 distance is used as defaults for sound ranges in spigot config for ender dragon, end portal and wither)
|
||||
}
|
||||
|
||||
public int getLogicalHeight() {
|
||||
@@ -1009,6 +_,11 @@
|
||||
@@ -1015,7 +_,7 @@
|
||||
pos.getX(),
|
||||
pos.getY(),
|
||||
pos.getZ(),
|
||||
- 64.0,
|
||||
+ 64.0, // Paper - diff on change (the 64.0 distance is used as defaults for sound ranges in spigot config for ender dragon, end portal and wither)
|
||||
this.dimension(),
|
||||
new ClientboundLevelEventPacket(type, pos, data, false)
|
||||
);
|
||||
@@ -1027,6 +_,11 @@
|
||||
|
||||
@Override
|
||||
public void gameEvent(Holder<GameEvent> gameEvent, Vec3 pos, GameEvent.Context context) {
|
||||
@@ -739,7 +740,7 @@
|
||||
this.gameEventDispatcher.post(gameEvent, pos, context);
|
||||
}
|
||||
|
||||
@@ -1021,17 +_,28 @@
|
||||
@@ -1039,17 +_,28 @@
|
||||
|
||||
this.getChunkSource().blockChanged(pos);
|
||||
this.pathTypesByPosCache.invalidate(pos);
|
||||
@@ -768,7 +769,7 @@
|
||||
|
||||
try {
|
||||
this.isUpdatingNavigations = true;
|
||||
@@ -1043,15 +_,18 @@
|
||||
@@ -1061,15 +_,23 @@
|
||||
this.isUpdatingNavigations = false;
|
||||
}
|
||||
}
|
||||
@@ -777,6 +778,11 @@
|
||||
|
||||
@Override
|
||||
public void updateNeighborsAt(BlockPos pos, Block block) {
|
||||
+ // CraftBukkit start
|
||||
+ if (this.populating) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ if (captureBlockStates) { return; } // Paper - Cancel all physics during placement
|
||||
this.updateNeighborsAt(pos, block, ExperimentalRedstoneUtils.initialOrientation(this, null, null));
|
||||
}
|
||||
@@ -787,7 +793,7 @@
|
||||
this.neighborUpdater.updateNeighborsAtExceptFromFacing(pos, block, null, orientation);
|
||||
}
|
||||
|
||||
@@ -1100,6 +_,42 @@
|
||||
@@ -1118,6 +_,42 @@
|
||||
ParticleOptions largeExplosionParticles,
|
||||
Holder<SoundEvent> explosionSound
|
||||
) {
|
||||
@@ -830,7 +836,7 @@
|
||||
Explosion.BlockInteraction blockInteraction = switch (explosionInteraction) {
|
||||
case NONE -> Explosion.BlockInteraction.KEEP;
|
||||
case BLOCK -> this.getDestroyType(GameRules.RULE_BLOCK_EXPLOSION_DROP_DECAY);
|
||||
@@ -1108,10 +_,17 @@
|
||||
@@ -1126,10 +_,17 @@
|
||||
: Explosion.BlockInteraction.KEEP;
|
||||
case TNT -> this.getDestroyType(GameRules.RULE_TNT_EXPLOSION_DROP_DECAY);
|
||||
case TRIGGER -> Explosion.BlockInteraction.TRIGGER_BLOCK;
|
||||
@@ -848,7 +854,7 @@
|
||||
ParticleOptions particleOptions = serverExplosion.isSmall() ? smallExplosionParticles : largeExplosionParticles;
|
||||
|
||||
for (ServerPlayer serverPlayer : this.players) {
|
||||
@@ -1120,6 +_,8 @@
|
||||
@@ -1138,6 +_,8 @@
|
||||
serverPlayer.connection.send(new ClientboundExplodePacket(vec3, optional, particleOptions, explosionSound));
|
||||
}
|
||||
}
|
||||
@@ -857,7 +863,7 @@
|
||||
}
|
||||
|
||||
private Explosion.BlockInteraction getDestroyType(GameRules.Key<GameRules.BooleanValue> decayGameRule) {
|
||||
@@ -1190,7 +_,7 @@
|
||||
@@ -1208,7 +_,7 @@
|
||||
public <T extends ParticleOptions> int sendParticles(
|
||||
T type, double posX, double posY, double posZ, int particleCount, double xOffset, double yOffset, double zOffset, double speed
|
||||
) {
|
||||
@@ -866,7 +872,7 @@
|
||||
}
|
||||
|
||||
public <T extends ParticleOptions> int sendParticles(
|
||||
@@ -1206,13 +_,49 @@
|
||||
@@ -1224,13 +_,49 @@
|
||||
double zOffset,
|
||||
double speed
|
||||
) {
|
||||
@@ -874,7 +880,7 @@
|
||||
+ return this.sendParticlesSource(null, type, overrideLimiter, alwaysShow, posX, posY, posZ, particleCount, xOffset, yOffset, zOffset, speed);
|
||||
+ }
|
||||
+ public <T extends ParticleOptions> int sendParticlesSource(
|
||||
+ @javax.annotation.Nullable Entity sender,
|
||||
+ @Nullable Entity sender,
|
||||
+ T type,
|
||||
+ boolean overrideLimiter,
|
||||
+ boolean alwaysShow,
|
||||
@@ -891,7 +897,7 @@
|
||||
+ }
|
||||
+ public <T extends ParticleOptions> int sendParticlesSource(
|
||||
+ List<ServerPlayer> receivers,
|
||||
+ @javax.annotation.Nullable Entity sender,
|
||||
+ @Nullable Entity sender,
|
||||
+ T type,
|
||||
+ boolean overrideLimiter,
|
||||
+ boolean alwaysShow,
|
||||
@@ -918,7 +924,7 @@
|
||||
if (this.sendParticles(serverPlayer, overrideLimiter, posX, posY, posZ, clientboundLevelParticlesPacket)) {
|
||||
i++;
|
||||
}
|
||||
@@ -1280,7 +_,7 @@
|
||||
@@ -1293,7 +_,7 @@
|
||||
|
||||
@Nullable
|
||||
public BlockPos findNearestMapStructure(TagKey<Structure> structureTag, BlockPos pos, int radius, boolean skipExistingChunks) {
|
||||
@@ -927,17 +933,17 @@
|
||||
return null;
|
||||
} else {
|
||||
Optional<HolderSet.Named<Structure>> optional = this.registryAccess().lookupOrThrow(Registries.STRUCTURE).get(structureTag);
|
||||
@@ -1327,11 +_,38 @@
|
||||
@@ -1340,10 +_,36 @@
|
||||
@Nullable
|
||||
@Override
|
||||
public MapItemSavedData getMapData(MapId mapId) {
|
||||
- return this.getServer().overworld().getDataStorage().get(MapItemSavedData.factory(), mapId.key());
|
||||
- return this.getServer().overworld().getDataStorage().get(MapItemSavedData.type(mapId));
|
||||
+ // Paper start - Call missing map initialize event and set id
|
||||
+ final DimensionDataStorage storage = this.getServer().overworld().getDataStorage();
|
||||
+
|
||||
+ final Optional<net.minecraft.world.level.saveddata.SavedData> cacheEntry = storage.cache.get(mapId.key());
|
||||
+ if (cacheEntry == null) { // Cache did not contain, try to load and may init
|
||||
+ final MapItemSavedData mapData = storage.get(MapItemSavedData.factory(), mapId.key()); // get populates the cache
|
||||
+ final MapItemSavedData mapData = storage.get(MapItemSavedData.type(mapId)); // get populates the cache
|
||||
+ if (mapData != null) { // map was read, init it and return
|
||||
+ mapData.id = mapId;
|
||||
+ new org.bukkit.event.server.MapInitializeEvent(mapData.mapView).callEvent();
|
||||
@@ -946,7 +952,6 @@
|
||||
+
|
||||
+ return null; // Map does not exist, reading failed.
|
||||
+ }
|
||||
+
|
||||
+ // Cache entry exists, update it with the id ref and return.
|
||||
+ if (cacheEntry.orElse(null) instanceof final MapItemSavedData mapItemSavedData) {
|
||||
+ mapItemSavedData.id = mapId;
|
||||
@@ -957,17 +962,16 @@
|
||||
+ // Paper end - Call missing map initialize event and set id
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMapData(MapId mapId, MapItemSavedData mapData) {
|
||||
public void setMapData(MapId mapId, MapItemSavedData data) {
|
||||
+ // CraftBukkit start
|
||||
+ mapData.id = mapId;
|
||||
+ org.bukkit.event.server.MapInitializeEvent event = new org.bukkit.event.server.MapInitializeEvent(mapData.mapView);
|
||||
+ data.id = mapId;
|
||||
+ org.bukkit.event.server.MapInitializeEvent event = new org.bukkit.event.server.MapInitializeEvent(data.mapView);
|
||||
+ event.callEvent();
|
||||
+ // CraftBukkit end
|
||||
this.getServer().overworld().getDataStorage().set(mapId.key(), mapData);
|
||||
this.getServer().overworld().getDataStorage().set(MapItemSavedData.type(mapId), data);
|
||||
}
|
||||
|
||||
@@ -1344,17 +_,27 @@
|
||||
@@ -1355,17 +_,27 @@
|
||||
BlockPos spawnPos = this.levelData.getSpawnPos();
|
||||
float spawnAngle = this.levelData.getSpawnAngle();
|
||||
if (!spawnPos.equals(pos) || spawnAngle != angle) {
|
||||
@@ -978,50 +982,38 @@
|
||||
}
|
||||
|
||||
if (this.lastSpawnChunkRadius > 1) {
|
||||
- this.getChunkSource().removeRegionTicket(TicketType.START, new ChunkPos(spawnPos), this.lastSpawnChunkRadius, Unit.INSTANCE);
|
||||
- this.getChunkSource().removeTicketWithRadius(TicketType.START, new ChunkPos(spawnPos), this.lastSpawnChunkRadius);
|
||||
+ // Paper start - allow disabling gamerule limits
|
||||
+ for (ChunkPos chunkPos : io.papermc.paper.util.MCUtil.getSpiralOutChunks(spawnPos, this.lastSpawnChunkRadius - 2)) {
|
||||
+ this.getChunkSource().removeTicketAtLevel(TicketType.START, chunkPos, net.minecraft.server.level.ChunkLevel.ENTITY_TICKING_LEVEL, Unit.INSTANCE);
|
||||
+ this.getChunkSource().removeTicketAtLevel(TicketType.START, chunkPos, ChunkLevel.ENTITY_TICKING_LEVEL);
|
||||
+ }
|
||||
+ // Paper end - allow disabling gamerule limits
|
||||
}
|
||||
|
||||
int i = this.getGameRules().getInt(GameRules.RULE_SPAWN_CHUNK_RADIUS) + 1;
|
||||
if (i > 1) {
|
||||
- this.getChunkSource().addRegionTicket(TicketType.START, new ChunkPos(pos), i, Unit.INSTANCE);
|
||||
- this.getChunkSource().addTicketWithRadius(TicketType.START, new ChunkPos(pos), i);
|
||||
+ // Paper start - allow disabling gamerule limits
|
||||
+ for (ChunkPos chunkPos : io.papermc.paper.util.MCUtil.getSpiralOutChunks(pos, i - 2)) {
|
||||
+ this.getChunkSource().addTicketAtLevel(TicketType.START, chunkPos, net.minecraft.server.level.ChunkLevel.ENTITY_TICKING_LEVEL, Unit.INSTANCE);
|
||||
+ this.getChunkSource().addTicketAtLevel(TicketType.START, chunkPos, ChunkLevel.ENTITY_TICKING_LEVEL);
|
||||
+ }
|
||||
+ // Paper end - allow disabling gamerule limits
|
||||
}
|
||||
|
||||
this.lastSpawnChunkRadius = i;
|
||||
@@ -1403,6 +_,11 @@
|
||||
@@ -1400,6 +_,11 @@
|
||||
DebugPackets.sendPoiRemovedPacket(this, blockPos);
|
||||
}));
|
||||
optional1.ifPresent(poiType -> this.getServer().execute(() -> {
|
||||
optional1.ifPresent(holder -> this.getServer().execute(() -> {
|
||||
+ // Paper start - Remove stale POIs
|
||||
+ if (optional.isEmpty() && this.getPoiManager().exists(blockPos, ignored -> true)) {
|
||||
+ this.getPoiManager().remove(blockPos);
|
||||
+ }
|
||||
+ // Paper end - Remove stale POIs
|
||||
this.getPoiManager().add(blockPos, (Holder<PoiType>)poiType);
|
||||
this.getPoiManager().add(blockPos, (Holder<PoiType>)holder);
|
||||
DebugPackets.sendPoiAddedPacket(this, blockPos);
|
||||
}));
|
||||
@@ -1543,6 +_,11 @@
|
||||
@Override
|
||||
public void blockUpdated(BlockPos pos, Block block) {
|
||||
if (!this.isDebug()) {
|
||||
+ // CraftBukkit start
|
||||
+ if (this.populating) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
this.updateNeighborsAt(pos, block);
|
||||
}
|
||||
}
|
||||
@@ -1562,12 +_,12 @@
|
||||
@@ -1552,12 +_,12 @@
|
||||
}
|
||||
|
||||
public boolean isFlat() {
|
||||
@@ -1036,7 +1028,7 @@
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -1618,6 +_,7 @@
|
||||
@@ -1608,6 +_,7 @@
|
||||
|
||||
@Override
|
||||
public LevelEntityGetter<Entity> getEntities() {
|
||||
@@ -1044,7 +1036,7 @@
|
||||
return this.entityManager.getEntityGetter();
|
||||
}
|
||||
|
||||
@@ -1699,6 +_,27 @@
|
||||
@@ -1697,6 +_,28 @@
|
||||
return this.serverLevelData.getGameRules();
|
||||
}
|
||||
|
||||
@@ -1059,12 +1051,13 @@
|
||||
+ }
|
||||
+ // Paper end - respect global sound events gamerule
|
||||
+ // Paper start - notify observers even if grow failed
|
||||
+ @Deprecated
|
||||
+ public void checkCapturedTreeStateForObserverNotify(final BlockPos pos, final org.bukkit.craftbukkit.block.CraftBlockState craftBlockState) {
|
||||
+ // notify observers if the block state is the same and the Y level equals the original y level (for mega trees)
|
||||
+ // blocks at the same Y level with the same state can be assumed to be saplings which trigger observers regardless of if the
|
||||
+ // tree grew or not
|
||||
+ if (craftBlockState.getPosition().getY() == pos.getY() && this.getBlockState(craftBlockState.getPosition()) == craftBlockState.getHandle()) {
|
||||
+ this.notifyAndUpdatePhysics(craftBlockState.getPosition(), null, craftBlockState.getHandle(), craftBlockState.getHandle(), craftBlockState.getHandle(), craftBlockState.getFlag(), 512);
|
||||
+ this.notifyAndUpdatePhysics(craftBlockState.getPosition(), null, craftBlockState.getHandle(), craftBlockState.getHandle(), craftBlockState.getHandle(), craftBlockState.getFlags(), 512);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - notify observers even if grow failed
|
||||
@@ -1072,7 +1065,7 @@
|
||||
@Override
|
||||
public CrashReportCategory fillReportDetails(CrashReport report) {
|
||||
CrashReportCategory crashReportCategory = super.fillReportDetails(report);
|
||||
@@ -1714,6 +_,7 @@
|
||||
@@ -1712,6 +_,7 @@
|
||||
final class EntityCallbacks implements LevelCallback<Entity> {
|
||||
@Override
|
||||
public void onCreated(Entity entity) {
|
||||
@@ -1080,7 +1073,7 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1723,24 +_,32 @@
|
||||
@@ -1721,24 +_,32 @@
|
||||
|
||||
@Override
|
||||
public void onTickingStart(Entity entity) {
|
||||
@@ -1115,7 +1108,7 @@
|
||||
String string = "onTrackingStart called during navigation iteration";
|
||||
Util.logAndPauseIfInIde(
|
||||
"onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration")
|
||||
@@ -1757,10 +_,52 @@
|
||||
@@ -1755,10 +_,52 @@
|
||||
}
|
||||
|
||||
entity.updateDynamicGameEventListener(DynamicGameEventListener::add);
|
||||
@@ -1123,12 +1116,12 @@
|
||||
+ entity.valid = true; // CraftBukkit
|
||||
+ ServerLevel.this.getChunkSource().addEntity(entity); // Paper - ignore and warn about illegal addEntity calls instead of crashing server
|
||||
+ // Paper start - Entity origin API
|
||||
+ if (entity.getOriginVector() == null) {
|
||||
+ entity.setOrigin(entity.getBukkitEntity().getLocation());
|
||||
+ if (entity.origin == null) {
|
||||
+ entity.origin = entity.position();
|
||||
+ }
|
||||
+ // Default to current world if unknown, gross assumption but entities rarely change world
|
||||
+ if (entity.getOriginWorld() == null) {
|
||||
+ entity.setOrigin(entity.getOriginVector().toLocation(getWorld()));
|
||||
+ if (entity.originWorld == null) {
|
||||
+ entity.originWorld = ServerLevel.this.getWorld().getUID();
|
||||
+ }
|
||||
+ // Paper end - Entity origin API
|
||||
+ new com.destroystokyo.paper.event.entity.EntityAddToWorldEvent(entity.getBukkitEntity(), ServerLevel.this.getWorld()).callEvent(); // Paper - fire while valid
|
||||
@@ -1168,7 +1161,7 @@
|
||||
ServerLevel.this.getChunkSource().removeEntity(entity);
|
||||
if (entity instanceof ServerPlayer serverPlayer) {
|
||||
ServerLevel.this.players.remove(serverPlayer);
|
||||
@@ -1768,7 +_,7 @@
|
||||
@@ -1766,7 +_,7 @@
|
||||
}
|
||||
|
||||
if (entity instanceof Mob mob) {
|
||||
@@ -1177,7 +1170,7 @@
|
||||
String string = "onTrackingStart called during navigation iteration";
|
||||
Util.logAndPauseIfInIde(
|
||||
"onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration")
|
||||
@@ -1785,6 +_,15 @@
|
||||
@@ -1783,6 +_,15 @@
|
||||
}
|
||||
|
||||
entity.updateDynamicGameEventListener(DynamicGameEventListener::remove);
|
||||
@@ -1193,7 +1186,7 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1792,4 +_,24 @@
|
||||
@@ -1790,4 +_,24 @@
|
||||
entity.updateDynamicGameEventListener(DynamicGameEventListener::move);
|
||||
}
|
||||
}
|
||||
@@ -1201,7 +1194,7 @@
|
||||
+ // Paper start - check global player list where appropriate
|
||||
+ @Override
|
||||
+ @Nullable
|
||||
+ public Player getGlobalPlayerByUUID(UUID uuid) {
|
||||
+ public Player getGlobalPlayerByUUID(java.util.UUID uuid) {
|
||||
+ return this.server.getPlayerList().getPlayer(uuid);
|
||||
+ }
|
||||
+ // Paper end - check global player list where appropriate
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
@@ -41,28 +_,49 @@
|
||||
@@ -41,28 +_,50 @@
|
||||
private BlockPos delayedDestroyPos = BlockPos.ZERO;
|
||||
private int delayedTickStart;
|
||||
private int lastSentState = -1;
|
||||
@@ -18,6 +18,7 @@
|
||||
+ org.bukkit.event.player.PlayerGameModeChangeEvent event = this.changeGameModeForPlayer(gameModeForPlayer, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.UNKNOWN, null);
|
||||
+ return event != null && event.isCancelled();
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ public org.bukkit.event.player.PlayerGameModeChangeEvent changeGameModeForPlayer(GameType gameModeForPlayer, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause playerGameModeChangeCause, @Nullable net.kyori.adventure.text.Component cancelMessage) {
|
||||
+ // Paper end - Expand PlayerGameModeChangeEvent
|
||||
@@ -92,34 +93,30 @@
|
||||
this.debugLogging(pos, false, sequence, "too far");
|
||||
} else if (pos.getY() > maxBuildHeight) {
|
||||
this.player.connection.send(new ClientboundBlockUpdatePacket(pos, this.level.getBlockState(pos)));
|
||||
@@ -138,16 +_,39 @@
|
||||
@@ -138,16 +_,35 @@
|
||||
} else {
|
||||
if (action == ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK) {
|
||||
if (!this.level.mayInteract(this.player, pos)) {
|
||||
+ // CraftBukkit start - fire PlayerInteractEvent
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent(this.player, org.bukkit.event.block.Action.LEFT_CLICK_BLOCK, pos, face, this.player.getInventory().getSelected(), InteractionHand.MAIN_HAND);
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent(this.player, org.bukkit.event.block.Action.LEFT_CLICK_BLOCK, pos, face, this.player.getInventory().getSelectedItem(), InteractionHand.MAIN_HAND);
|
||||
this.player.connection.send(new ClientboundBlockUpdatePacket(pos, this.level.getBlockState(pos)));
|
||||
this.debugLogging(pos, false, sequence, "may not interact");
|
||||
- return;
|
||||
- }
|
||||
+ // Update any tile entity data for this block
|
||||
+ this.capturedBlockEntity = true; // Paper - Send block entities after destroy prediction
|
||||
+ // CraftBukkit end
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.event.player.PlayerInteractEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent(this.player, org.bukkit.event.block.Action.LEFT_CLICK_BLOCK, pos, face, this.player.getInventory().getSelected(), InteractionHand.MAIN_HAND);
|
||||
+ org.bukkit.event.player.PlayerInteractEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent(this.player, org.bukkit.event.block.Action.LEFT_CLICK_BLOCK, pos, face, this.player.getInventory().getSelectedItem(), InteractionHand.MAIN_HAND);
|
||||
+ if (event.isCancelled()) {
|
||||
+ // Let the client know the block still exists
|
||||
+ // this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); // Paper - Don't resync blocks
|
||||
+ // Update any tile entity data for this block
|
||||
+ this.capturedBlockEntity = true; // Paper - Send block entities after destroy prediction
|
||||
+ return;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
|
||||
if (this.isCreative()) {
|
||||
if (this.player.getAbilities().instabuild) {
|
||||
this.destroyAndAck(pos, sequence, "creative destroy");
|
||||
return;
|
||||
}
|
||||
@@ -153,7 +150,7 @@
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDamageEvent blockEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockDamageEvent(this.player, pos, face, this.player.getInventory().getSelected(), f >= 1.0f); // Paper - Add BlockFace to BlockDamageEvent
|
||||
+ org.bukkit.event.block.BlockDamageEvent blockEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockDamageEvent(this.player, pos, face, this.player.getInventory().getSelectedItem(), f >= 1.0f); // Paper - Add BlockFace to BlockDamageEvent
|
||||
+
|
||||
+ if (blockEvent.isCancelled()) {
|
||||
+ return;
|
||||
@@ -188,7 +185,7 @@
|
||||
this.level.destroyBlockProgress(this.player.getId(), pos, -1);
|
||||
this.debugLogging(pos, true, sequence, "aborted destroying");
|
||||
+
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.callBlockDamageAbortEvent(this.player, pos, this.player.getInventory().getSelected()); // CraftBukkit
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.callBlockDamageAbortEvent(this.player, pos, this.player.getInventory().getSelectedItem()); // CraftBukkit
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -196,13 +193,13 @@
|
||||
|
||||
public boolean destroyBlock(BlockPos pos) {
|
||||
BlockState blockState = this.level.getBlockState(pos);
|
||||
- if (!this.player.getMainHandItem().getItem().canAttackBlock(blockState, this.level, pos, this.player)) {
|
||||
- if (!this.player.getMainHandItem().canDestroyBlock(blockState, this.level, pos, this.player)) {
|
||||
+ // CraftBukkit start - fire BlockBreakEvent
|
||||
+ org.bukkit.block.Block bblock = org.bukkit.craftbukkit.block.CraftBlock.at(this.level, pos);
|
||||
+ org.bukkit.event.block.BlockBreakEvent event = null;
|
||||
+ if (this.player instanceof ServerPlayer) {
|
||||
+ // Sword + Creative mode pre-cancel
|
||||
+ boolean canAttackBlock = !this.player.getMainHandItem().getItem().canAttackBlock(blockState, this.level, pos, this.player);
|
||||
+ boolean canAttackBlock = !this.player.getMainHandItem().canDestroyBlock(blockState, this.level, pos, this.player);
|
||||
+ event = new org.bukkit.event.block.BlockBreakEvent(bblock, this.player.getBukkitEntity());
|
||||
+
|
||||
+ // Sword + Creative mode pre-cancel
|
||||
@@ -238,7 +235,7 @@
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ if (false && !this.player.getMainHandItem().getItem().canAttackBlock(blockState, this.level, pos, this.player)) { // CraftBukkit - false
|
||||
+ if (false && !this.player.getMainHandItem().canDestroyBlock(blockState, this.level, pos, this.player)) { // CraftBukkit - false
|
||||
return false;
|
||||
} else {
|
||||
+ blockState = this.level.getBlockState(pos); // CraftBukkit - update state from plugins
|
||||
@@ -264,7 +261,7 @@
|
||||
|
||||
+ ItemStack mainHandStack = null; // Paper - Trigger bee_nest_destroyed trigger in the correct place
|
||||
+ boolean isCorrectTool = false; // Paper - Trigger bee_nest_destroyed trigger in the correct place
|
||||
if (this.isCreative()) {
|
||||
if (this.player.preventsBlockDrops()) {
|
||||
- return true;
|
||||
+ // return true; // CraftBukkit
|
||||
} else {
|
||||
@@ -368,7 +365,7 @@
|
||||
+ if (!stack.isEmpty() && !this.interactResult) { // add !interactResult SPIGOT-764
|
||||
UseOnContext useOnContext = new UseOnContext(player, hand, hitResult);
|
||||
InteractionResult interactionResult1;
|
||||
if (this.isCreative()) {
|
||||
if (player.hasInfiniteMaterials()) {
|
||||
@@ -357,6 +_,11 @@
|
||||
|
||||
return interactionResult1;
|
||||
|
@@ -0,0 +1,41 @@
|
||||
--- a/net/minecraft/server/level/Ticket.java
|
||||
+++ b/net/minecraft/server/level/Ticket.java
|
||||
@@ -14,17 +_,36 @@
|
||||
ExtraCodecs.NON_NEGATIVE_INT.fieldOf("level").forGetter(Ticket::getTicketLevel),
|
||||
Codec.LONG.optionalFieldOf("ticks_left", 0L).forGetter(ticket -> ticket.ticksLeft)
|
||||
)
|
||||
- .apply(instance, Ticket::new)
|
||||
+ .apply(instance, (type, level, ticks) -> new Ticket(type, level.intValue(), ticks.longValue())) // Paper - add identifier
|
||||
);
|
||||
private final TicketType type;
|
||||
private final int ticketLevel;
|
||||
private long ticksLeft;
|
||||
+ // Paper start - add identifier
|
||||
+ private Object identifier;
|
||||
+
|
||||
+ public Object getIdentifier() {
|
||||
+ return this.identifier;
|
||||
+ }
|
||||
+ // Paper end - add identifier
|
||||
+
|
||||
|
||||
public Ticket(TicketType type, int ticketLevel) {
|
||||
- this(type, ticketLevel, type.timeout());
|
||||
+ // Paper start - add identifier
|
||||
+ this(type, ticketLevel, null);
|
||||
+ }
|
||||
+ public Ticket(TicketType type, int ticketLevel, Object identifier) {
|
||||
+ this(type, ticketLevel, type.timeout(), identifier);
|
||||
+ // Paper end - add identifier
|
||||
}
|
||||
|
||||
private Ticket(TicketType type, int ticketLevel, long ticksLeft) {
|
||||
+ // Paper start - add identifier
|
||||
+ this(type, ticketLevel, ticksLeft, null);
|
||||
+ }
|
||||
+ private Ticket(TicketType type, int ticketLevel, long ticksLeft, Object identifier) {
|
||||
+ this.identifier = identifier;
|
||||
+ // Paper end - add identifier
|
||||
this.type = type;
|
||||
this.ticketLevel = ticketLevel;
|
||||
this.ticksLeft = ticksLeft;
|
@@ -1,20 +1,36 @@
|
||||
--- a/net/minecraft/server/level/TicketType.java
|
||||
+++ b/net/minecraft/server/level/TicketType.java
|
||||
@@ -7,6 +_,7 @@
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
@@ -13,11 +_,24 @@
|
||||
public static final TicketType PORTAL = register("portal", 300L, true, TicketType.TicketUse.LOADING_AND_SIMULATION);
|
||||
public static final TicketType ENDER_PEARL = register("ender_pearl", 40L, false, TicketType.TicketUse.LOADING_AND_SIMULATION);
|
||||
public static final TicketType UNKNOWN = register("unknown", 1L, false, TicketType.TicketUse.LOADING);
|
||||
+ public static final TicketType PLUGIN = register("plugin", 0L, false, TicketType.TicketUse.LOADING_AND_SIMULATION); // CraftBukkit
|
||||
+ public static final TicketType POST_TELEPORT = register("post_teleport", 5L, false, TicketType.TicketUse.LOADING_AND_SIMULATION); // Paper
|
||||
+ public static final TicketType PLUGIN_TICKET = register("plugin_ticket", TicketType.NO_TIMEOUT, false, TicketType.TicketUse.LOADING_AND_SIMULATION); // Paper
|
||||
+ public static final TicketType FUTURE_AWAIT = register("future_await", TicketType.NO_TIMEOUT, false, TicketType.TicketUse.LOADING_AND_SIMULATION); // Paper
|
||||
+ public static final TicketType CHUNK_LOAD = register("chunk_load", TicketType.NO_TIMEOUT, false, TicketType.TicketUse.LOADING); // Paper - moonrise
|
||||
|
||||
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;
|
||||
public long timeout;
|
||||
@@ -17,6 +_,9 @@
|
||||
public static final TicketType<BlockPos> PORTAL = create("portal", Vec3i::compareTo, 300);
|
||||
public static final TicketType<ChunkPos> ENDER_PEARL = create("ender_pearl", Comparator.comparingLong(ChunkPos::toLong), 40);
|
||||
public static final TicketType<ChunkPos> UNKNOWN = 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 TicketType register(String name, long timeout, boolean persist, TicketType.TicketUse use) {
|
||||
return Registry.register(BuiltInRegistries.TICKET_TYPE, name, new TicketType(timeout, persist, use));
|
||||
}
|
||||
|
||||
public static <T> TicketType<T> create(String name, Comparator<T> comparator) {
|
||||
return new TicketType<>(name, comparator, 0L);
|
||||
+ // Paper start - chunk-gc config
|
||||
+ public static int PLUGIN_TYPE_TIMEOUT = 600;
|
||||
+ @Override
|
||||
+ public long timeout() {
|
||||
+ return this == PLUGIN ? PLUGIN_TYPE_TIMEOUT : this.timeout;
|
||||
+ }
|
||||
+ // Paper end - chunk-gc config
|
||||
+
|
||||
public boolean doesLoad() {
|
||||
return this.use == TicketType.TicketUse.LOADING || this.use == TicketType.TicketUse.LOADING_AND_SIMULATION;
|
||||
}
|
||||
@@ -27,7 +_,7 @@
|
||||
}
|
||||
|
||||
public boolean hasTimeout() {
|
||||
- return this.timeout != 0L;
|
||||
+ return this.timeout() != 0L; // Paper - chunk-gc config
|
||||
}
|
||||
|
||||
public static enum TicketUse {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/server/level/WorldGenRegion.java
|
||||
+++ b/net/minecraft/server/level/WorldGenRegion.java
|
||||
@@ -151,6 +_,26 @@
|
||||
@@ -151,6 +_,28 @@
|
||||
return chessboardDistance < this.generatingStep.directDependencies().size();
|
||||
}
|
||||
|
||||
@@ -11,16 +11,18 @@
|
||||
+ return this.getChunk(x, z, ChunkStatus.FULL, false);
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ @Override
|
||||
+ public final BlockState getBlockStateIfLoaded(BlockPos blockposition) {
|
||||
+ ChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4);
|
||||
+ return chunk == null ? null : chunk.getBlockState(blockposition);
|
||||
+ public final BlockState getBlockStateIfLoaded(BlockPos pos) {
|
||||
+ ChunkAccess chunk = this.getChunkIfLoadedImmediately(pos.getX() >> 4, pos.getZ() >> 4);
|
||||
+ return chunk == null ? null : chunk.getBlockState(pos);
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ @Override
|
||||
+ public final FluidState getFluidIfLoaded(BlockPos blockposition) {
|
||||
+ ChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4);
|
||||
+ return chunk == null ? null : chunk.getFluidState(blockposition);
|
||||
+ public final FluidState getFluidIfLoaded(BlockPos pos) {
|
||||
+ ChunkAccess chunk = this.getChunkIfLoadedImmediately(pos.getX() >> 4, pos.getZ() >> 4);
|
||||
+ return chunk == null ? null : chunk.getFluidState(pos);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@@ -71,10 +73,10 @@
|
||||
return false;
|
||||
} else {
|
||||
ChunkAccess chunk = this.getChunk(pos);
|
||||
- BlockState blockState = chunk.setBlockState(pos, state, false);
|
||||
+ BlockState blockState = chunk.setBlockState(pos, state, false); final BlockState previousBlockState = blockState; // Paper - Clear block entity before setting up a DUMMY block entity - obfhelper
|
||||
- BlockState blockState = chunk.setBlockState(pos, state, flags);
|
||||
+ BlockState blockState = chunk.setBlockState(pos, state, flags); final BlockState previousBlockState = blockState; // Paper - Clear block entity before setting up a DUMMY block entity - obfhelper
|
||||
if (blockState != null) {
|
||||
this.level.onBlockStateChange(pos, blockState, state);
|
||||
this.level.updatePOIOnBlockStateChange(pos, blockState, state);
|
||||
}
|
||||
@@ -294,6 +_,17 @@
|
||||
chunk.removeBlockEntity(pos);
|
||||
|
Reference in New Issue
Block a user