MC Utils
== 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:
@@ -1,5 +1,14 @@
|
||||
--- a/net/minecraft/Util.java
|
||||
+++ b/net/minecraft/Util.java
|
||||
@@ -136,7 +136,7 @@
|
||||
}
|
||||
|
||||
public static long getNanos() {
|
||||
- return timeSource.getAsLong();
|
||||
+ return System.nanoTime(); // Paper
|
||||
}
|
||||
|
||||
public static long getEpochMillis() {
|
||||
@@ -537,7 +537,7 @@
|
||||
public static <K extends Enum<K>, V> EnumMap<K, V> makeEnumMap(Class<K> enumClass, Function<K, V> mapper) {
|
||||
EnumMap<K, V> enumMap = new EnumMap<>(enumClass);
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
--- a/net/minecraft/nbt/CompoundTag.java
|
||||
+++ b/net/minecraft/nbt/CompoundTag.java
|
||||
@@ -235,6 +235,10 @@
|
||||
this.tags.put(key, NbtUtils.createUUID(value));
|
||||
}
|
||||
|
||||
+
|
||||
+ /**
|
||||
+ * You must use {@link #hasUUID(String)} before or else it <b>will</b> throw an NPE.
|
||||
+ */
|
||||
public UUID getUUID(String key) {
|
||||
return NbtUtils.loadUUID(this.get(key));
|
||||
}
|
||||
@@ -12,15 +12,27 @@
|
||||
@Nullable
|
||||
private volatile PacketListener disconnectListener;
|
||||
@Nullable
|
||||
@@ -114,6 +119,7 @@
|
||||
@@ -114,6 +119,19 @@
|
||||
private volatile DisconnectionDetails delayedDisconnect;
|
||||
@Nullable
|
||||
BandwidthDebugMonitor bandwidthDebugMonitor;
|
||||
+ public String hostname = ""; // CraftBukkit - add field
|
||||
+
|
||||
+ // Paper start - add utility methods
|
||||
+ public final net.minecraft.server.level.ServerPlayer getPlayer() {
|
||||
+ if (this.packetListener instanceof net.minecraft.server.network.ServerGamePacketListenerImpl impl) {
|
||||
+ return impl.player;
|
||||
+ } else if (this.packetListener instanceof net.minecraft.server.network.ServerCommonPacketListenerImpl impl) {
|
||||
+ org.bukkit.craftbukkit.entity.CraftPlayer player = impl.getCraftPlayer();
|
||||
+ return player == null ? null : player.getHandle();
|
||||
+ }
|
||||
+ return null;
|
||||
+ }
|
||||
+ // Paper end - add utility methods
|
||||
|
||||
public Connection(PacketFlow side) {
|
||||
this.receiving = side;
|
||||
@@ -123,6 +129,9 @@
|
||||
@@ -123,6 +141,9 @@
|
||||
super.channelActive(channelhandlercontext);
|
||||
this.channel = channelhandlercontext.channel();
|
||||
this.address = this.channel.remoteAddress();
|
||||
@@ -30,7 +42,7 @@
|
||||
if (this.delayedDisconnect != null) {
|
||||
this.disconnect(this.delayedDisconnect);
|
||||
}
|
||||
@@ -176,6 +185,7 @@
|
||||
@@ -176,6 +197,7 @@
|
||||
|
||||
}
|
||||
}
|
||||
@@ -38,7 +50,7 @@
|
||||
}
|
||||
|
||||
protected void channelRead0(ChannelHandlerContext channelhandlercontext, Packet<?> packet) {
|
||||
@@ -205,7 +215,7 @@
|
||||
@@ -205,7 +227,7 @@
|
||||
}
|
||||
|
||||
private static <T extends PacketListener> void genericsFtw(Packet<T> packet, PacketListener listener) {
|
||||
@@ -47,7 +59,7 @@
|
||||
}
|
||||
|
||||
private void validateListener(ProtocolInfo<?> state, PacketListener listener) {
|
||||
@@ -464,12 +474,15 @@
|
||||
@@ -464,12 +486,15 @@
|
||||
}
|
||||
|
||||
public void disconnect(DisconnectionDetails disconnectionInfo) {
|
||||
@@ -64,7 +76,7 @@
|
||||
this.disconnectionDetails = disconnectionInfo;
|
||||
}
|
||||
|
||||
@@ -537,7 +550,7 @@
|
||||
@@ -537,7 +562,7 @@
|
||||
}
|
||||
|
||||
public void configurePacketHandler(ChannelPipeline pipeline) {
|
||||
@@ -73,7 +85,7 @@
|
||||
public void write(ChannelHandlerContext channelhandlercontext, Object object, ChannelPromise channelpromise) throws Exception {
|
||||
super.write(channelhandlercontext, object, channelpromise);
|
||||
}
|
||||
@@ -661,6 +674,7 @@
|
||||
@@ -661,6 +686,7 @@
|
||||
|
||||
packetlistener1.onDisconnect(disconnectiondetails);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/network/PacketEncoder.java
|
||||
+++ b/net/minecraft/network/PacketEncoder.java
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
JvmProfiler.INSTANCE.onPacketSent(this.protocolInfo.id(), packetType, channelHandlerContext.channel().remoteAddress(), i);
|
||||
} catch (Throwable var9) {
|
||||
- LOGGER.error("Error sending packet {}", packetType, var9);
|
||||
+ LOGGER.error("Error sending packet {} (skippable? {})", packetType, packet.isSkippable(), var9);
|
||||
if (packet.isSkippable()) {
|
||||
throw new SkipPacketException(var9);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
--- a/net/minecraft/network/protocol/login/ClientboundCustomQueryPacket.java
|
||||
+++ b/net/minecraft/network/protocol/login/ClientboundCustomQueryPacket.java
|
||||
@@ -47,4 +47,14 @@
|
||||
public void handle(ClientLoginPacketListener listener) {
|
||||
listener.handleCustomQuery(this);
|
||||
}
|
||||
+
|
||||
+ // Paper start - MC Utils - default query payloads
|
||||
+ public static record PlayerInfoChannelPayload(ResourceLocation id, FriendlyByteBuf buffer) implements CustomQueryPayload {
|
||||
+
|
||||
+ @Override
|
||||
+ public void write(final FriendlyByteBuf buf) {
|
||||
+ buf.writeBytes(this.buffer.copy());
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - MC Utils - default query payloads
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
--- a/net/minecraft/network/protocol/login/ServerboundCustomQueryAnswerPacket.java
|
||||
+++ b/net/minecraft/network/protocol/login/ServerboundCustomQueryAnswerPacket.java
|
||||
@@ -20,7 +20,17 @@
|
||||
}
|
||||
|
||||
private static CustomQueryAnswerPayload readPayload(int queryId, FriendlyByteBuf buf) {
|
||||
- return readUnknownPayload(buf);
|
||||
+ // Paper start - MC Utils - default query payloads
|
||||
+ FriendlyByteBuf buffer = buf.readNullable((buf2) -> {
|
||||
+ int i = buf2.readableBytes();
|
||||
+ if (i >= 0 && i <= MAX_PAYLOAD_SIZE) {
|
||||
+ return new FriendlyByteBuf(buf2.readBytes(i));
|
||||
+ } else {
|
||||
+ throw new IllegalArgumentException("Payload may not be larger than " + MAX_PAYLOAD_SIZE + " bytes");
|
||||
+ }
|
||||
+ });
|
||||
+ return buffer == null ? null : new net.minecraft.network.protocol.login.ServerboundCustomQueryAnswerPacket.QueryAnswerPayload(buffer);
|
||||
+ // Paper end - MC Utils - default query payloads
|
||||
}
|
||||
|
||||
private static CustomQueryAnswerPayload readUnknownPayload(FriendlyByteBuf buf) {
|
||||
@@ -47,4 +57,21 @@
|
||||
public void handle(ServerLoginPacketListener listener) {
|
||||
listener.handleCustomQueryPacket(this);
|
||||
}
|
||||
+
|
||||
+ // Paper start - MC Utils - default query payloads
|
||||
+ public static final class QueryAnswerPayload implements CustomQueryAnswerPayload {
|
||||
+
|
||||
+ public final FriendlyByteBuf buffer;
|
||||
+
|
||||
+ public QueryAnswerPayload(final net.minecraft.network.FriendlyByteBuf buffer) {
|
||||
+ this.buffer = buffer;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void write(final net.minecraft.network.FriendlyByteBuf buf) {
|
||||
+ buf.writeBytes(this.buffer.copy());
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - MC Utils - default query payloads
|
||||
+
|
||||
}
|
||||
@@ -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 @@
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
--- a/net/minecraft/util/thread/BlockableEventLoop.java
|
||||
+++ b/net/minecraft/util/thread/BlockableEventLoop.java
|
||||
@@ -82,6 +82,13 @@
|
||||
runnable.run();
|
||||
}
|
||||
}
|
||||
+ // Paper start
|
||||
+ public void scheduleOnMain(Runnable runnable) {
|
||||
+ // postToMainThread does not work the same as older versions of mc
|
||||
+ // This method is actually used to create a TickTask, which can then be posted onto main
|
||||
+ this.schedule(this.wrapRunnable(runnable));
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
@Override
|
||||
public void schedule(R runnable) {
|
||||
@@ -96,7 +96,7 @@
|
||||
private static final EntityDataAccessor<Integer> DATA_TICKS_FROZEN = SynchedEntityData.defineId(Entity.class, EntityDataSerializers.INT);
|
||||
private EntityInLevelCallback levelCallback;
|
||||
private final VecDeltaCodec packetPositionCodec;
|
||||
@@ -253,7 +312,38 @@
|
||||
@@ -253,6 +312,42 @@
|
||||
private final List<Entity.Movement> movementThisTick;
|
||||
private final Set<BlockState> blocksInside;
|
||||
private final LongSet visitedBlocks;
|
||||
@@ -122,7 +122,7 @@
|
||||
+ public long activatedTick = Integer.MIN_VALUE;
|
||||
+ public void inactiveTick() { }
|
||||
+ // Spigot end
|
||||
|
||||
+
|
||||
+ public float getBukkitYaw() {
|
||||
+ return this.yRot;
|
||||
+ }
|
||||
@@ -131,11 +131,15 @@
|
||||
+ return this.level.hasChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ // Paper start
|
||||
+ public final AABB getBoundingBoxAt(double x, double y, double z) {
|
||||
+ return this.dimensions.makeBoundingBox(x, y, z);
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
public Entity(EntityType<?> type, Level world) {
|
||||
this.id = Entity.ENTITY_COUNTER.incrementAndGet();
|
||||
this.passengers = ImmutableList.of();
|
||||
@@ -284,6 +374,13 @@
|
||||
@@ -284,6 +379,13 @@
|
||||
this.position = Vec3.ZERO;
|
||||
this.blockPosition = BlockPos.ZERO;
|
||||
this.chunkPosition = ChunkPos.ZERO;
|
||||
@@ -149,7 +153,7 @@
|
||||
SynchedEntityData.Builder datawatcher_a = new SynchedEntityData.Builder(this);
|
||||
|
||||
datawatcher_a.define(Entity.DATA_SHARED_FLAGS_ID, (byte) 0);
|
||||
@@ -292,7 +389,7 @@
|
||||
@@ -292,7 +394,7 @@
|
||||
datawatcher_a.define(Entity.DATA_CUSTOM_NAME, Optional.empty());
|
||||
datawatcher_a.define(Entity.DATA_SILENT, false);
|
||||
datawatcher_a.define(Entity.DATA_NO_GRAVITY, false);
|
||||
@@ -158,7 +162,7 @@
|
||||
datawatcher_a.define(Entity.DATA_TICKS_FROZEN, 0);
|
||||
this.defineSynchedData(datawatcher_a);
|
||||
this.entityData = datawatcher_a.build();
|
||||
@@ -362,20 +459,36 @@
|
||||
@@ -362,20 +464,36 @@
|
||||
}
|
||||
|
||||
public void kill(ServerLevel world) {
|
||||
@@ -197,7 +201,7 @@
|
||||
public boolean equals(Object object) {
|
||||
return object instanceof Entity ? ((Entity) object).id == this.id : false;
|
||||
}
|
||||
@@ -385,22 +498,34 @@
|
||||
@@ -385,22 +503,34 @@
|
||||
}
|
||||
|
||||
public void remove(Entity.RemovalReason reason) {
|
||||
@@ -237,7 +241,7 @@
|
||||
return this.getPose() == pose;
|
||||
}
|
||||
|
||||
@@ -417,6 +542,33 @@
|
||||
@@ -417,6 +547,33 @@
|
||||
}
|
||||
|
||||
public void setRot(float yaw, float pitch) {
|
||||
@@ -271,7 +275,7 @@
|
||||
this.setYRot(yaw % 360.0F);
|
||||
this.setXRot(pitch % 360.0F);
|
||||
}
|
||||
@@ -462,6 +614,15 @@
|
||||
@@ -462,6 +619,15 @@
|
||||
this.baseTick();
|
||||
}
|
||||
|
||||
@@ -287,7 +291,7 @@
|
||||
public void baseTick() {
|
||||
ProfilerFiller gameprofilerfiller = Profiler.get();
|
||||
|
||||
@@ -475,7 +636,7 @@
|
||||
@@ -475,7 +641,7 @@
|
||||
--this.boardingCooldown;
|
||||
}
|
||||
|
||||
@@ -296,7 +300,7 @@
|
||||
if (this.canSpawnSprintParticle()) {
|
||||
this.spawnSprintParticle();
|
||||
}
|
||||
@@ -514,6 +675,10 @@
|
||||
@@ -514,6 +680,10 @@
|
||||
if (this.isInLava()) {
|
||||
this.lavaHurt();
|
||||
this.fallDistance *= 0.5F;
|
||||
@@ -307,7 +311,7 @@
|
||||
}
|
||||
|
||||
this.checkBelowWorld();
|
||||
@@ -525,7 +690,7 @@
|
||||
@@ -525,7 +695,7 @@
|
||||
world = this.level();
|
||||
if (world instanceof ServerLevel worldserver) {
|
||||
if (this instanceof Leashable) {
|
||||
@@ -316,7 +320,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -568,15 +733,32 @@
|
||||
@@ -568,15 +738,32 @@
|
||||
|
||||
public void lavaHurt() {
|
||||
if (!this.fireImmune()) {
|
||||
@@ -351,7 +355,7 @@
|
||||
}
|
||||
|
||||
}
|
||||
@@ -587,9 +769,25 @@
|
||||
@@ -587,9 +774,25 @@
|
||||
}
|
||||
|
||||
public final void igniteForSeconds(float seconds) {
|
||||
@@ -378,7 +382,7 @@
|
||||
public void igniteForTicks(int ticks) {
|
||||
if (this.remainingFireTicks < ticks) {
|
||||
this.setRemainingFireTicks(ticks);
|
||||
@@ -610,7 +808,7 @@
|
||||
@@ -610,7 +813,7 @@
|
||||
}
|
||||
|
||||
protected void onBelowWorld() {
|
||||
@@ -387,7 +391,7 @@
|
||||
}
|
||||
|
||||
public boolean isFree(double offsetX, double offsetY, double offsetZ) {
|
||||
@@ -672,6 +870,7 @@
|
||||
@@ -672,6 +875,7 @@
|
||||
}
|
||||
|
||||
public void move(MoverType type, Vec3 movement) {
|
||||
@@ -395,10 +399,13 @@
|
||||
if (this.noPhysics) {
|
||||
this.setPos(this.getX() + movement.x, this.getY() + movement.y, this.getZ() + movement.z);
|
||||
} else {
|
||||
@@ -750,6 +949,28 @@
|
||||
}
|
||||
}
|
||||
@@ -747,8 +951,30 @@
|
||||
|
||||
if (movement.y != vec3d1.y) {
|
||||
block.updateEntityMovementAfterFallOn(this.level(), this);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // CraftBukkit start
|
||||
+ if (this.horizontalCollision && this.getBukkitEntity() instanceof Vehicle) {
|
||||
+ Vehicle vehicle = (Vehicle) this.getBukkitEntity();
|
||||
@@ -412,19 +419,18 @@
|
||||
+ bl = bl.getRelative(BlockFace.SOUTH);
|
||||
+ } else if (movement.z < vec3d1.z) {
|
||||
+ bl = bl.getRelative(BlockFace.NORTH);
|
||||
+ }
|
||||
}
|
||||
+
|
||||
+ if (!bl.getType().isAir()) {
|
||||
+ VehicleBlockCollisionEvent event = new VehicleBlockCollisionEvent(vehicle, bl);
|
||||
+ this.level.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
|
||||
if (!this.level().isClientSide() || this.isControlledByLocalInstance()) {
|
||||
Entity.MovementEmission entity_movementemission = this.getMovementEmission();
|
||||
|
||||
@@ -764,6 +985,7 @@
|
||||
@@ -764,6 +990,7 @@
|
||||
gameprofilerfiller.pop();
|
||||
}
|
||||
}
|
||||
@@ -432,7 +438,7 @@
|
||||
}
|
||||
|
||||
private void applyMovementEmissionAndPlaySound(Entity.MovementEmission moveEffect, Vec3 movement, BlockPos landingPos, BlockState landingState) {
|
||||
@@ -1133,6 +1355,20 @@
|
||||
@@ -1133,6 +1360,20 @@
|
||||
return SoundEvents.GENERIC_SPLASH;
|
||||
}
|
||||
|
||||
@@ -453,7 +459,7 @@
|
||||
public void recordMovementThroughBlocks(Vec3 oldPos, Vec3 newPos) {
|
||||
this.movementThisTick.add(new Entity.Movement(oldPos, newPos));
|
||||
}
|
||||
@@ -1609,6 +1845,7 @@
|
||||
@@ -1609,6 +1850,7 @@
|
||||
this.yo = y;
|
||||
this.zo = d4;
|
||||
this.setPos(d3, y, d4);
|
||||
@@ -461,7 +467,7 @@
|
||||
}
|
||||
|
||||
public void moveTo(Vec3 pos) {
|
||||
@@ -1861,6 +2098,12 @@
|
||||
@@ -1861,6 +2103,12 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -474,7 +480,7 @@
|
||||
public void awardKillScore(Entity entityKilled, DamageSource damageSource) {
|
||||
if (entityKilled instanceof ServerPlayer) {
|
||||
CriteriaTriggers.ENTITY_KILLED_PLAYER.trigger((ServerPlayer) entityKilled, this, damageSource);
|
||||
@@ -1889,16 +2132,22 @@
|
||||
@@ -1889,16 +2137,22 @@
|
||||
}
|
||||
|
||||
public boolean saveAsPassenger(CompoundTag nbt) {
|
||||
@@ -500,7 +506,7 @@
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1909,54 +2158,98 @@
|
||||
@@ -1909,54 +2163,98 @@
|
||||
}
|
||||
|
||||
public CompoundTag saveWithoutId(CompoundTag nbt) {
|
||||
@@ -619,7 +625,7 @@
|
||||
}
|
||||
|
||||
ListTag nbttaglist;
|
||||
@@ -1972,10 +2265,10 @@
|
||||
@@ -1972,10 +2270,10 @@
|
||||
nbttaglist.add(StringTag.valueOf(s));
|
||||
}
|
||||
|
||||
@@ -632,7 +638,7 @@
|
||||
if (this.isVehicle()) {
|
||||
nbttaglist = new ListTag();
|
||||
iterator = this.getPassengers().iterator();
|
||||
@@ -1984,17 +2277,22 @@
|
||||
@@ -1984,17 +2282,22 @@
|
||||
Entity entity = (Entity) iterator.next();
|
||||
CompoundTag nbttagcompound1 = new CompoundTag();
|
||||
|
||||
@@ -658,11 +664,10 @@
|
||||
} catch (Throwable throwable) {
|
||||
CrashReport crashreport = CrashReport.forThrowable(throwable, "Saving entity NBT");
|
||||
CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being saved");
|
||||
@@ -2079,7 +2377,51 @@
|
||||
}
|
||||
@@ -2080,6 +2383,50 @@
|
||||
} else {
|
||||
throw new IllegalStateException("Entity has invalid position");
|
||||
+ }
|
||||
}
|
||||
+
|
||||
+ // CraftBukkit start
|
||||
+ // Spigot start
|
||||
@@ -698,7 +703,7 @@
|
||||
+ }
|
||||
+
|
||||
+ ((ServerPlayer) this).setLevel(bworld == null ? null : ((CraftWorld) bworld).getHandle());
|
||||
}
|
||||
+ }
|
||||
+ this.getBukkitEntity().readBukkitValues(nbt);
|
||||
+ if (nbt.contains("Bukkit.invisible")) {
|
||||
+ boolean bukkitInvisible = nbt.getBoolean("Bukkit.invisible");
|
||||
@@ -710,7 +715,7 @@
|
||||
} catch (Throwable throwable) {
|
||||
CrashReport crashreport = CrashReport.forThrowable(throwable, "Loading entity NBT");
|
||||
CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being loaded");
|
||||
@@ -2101,6 +2443,12 @@
|
||||
@@ -2101,6 +2448,12 @@
|
||||
return entitytypes.canSerialize() && minecraftkey != null ? minecraftkey.toString() : null;
|
||||
}
|
||||
|
||||
@@ -723,7 +728,7 @@
|
||||
protected abstract void readAdditionalSaveData(CompoundTag nbt);
|
||||
|
||||
protected abstract void addAdditionalSaveData(CompoundTag nbt);
|
||||
@@ -2153,9 +2501,22 @@
|
||||
@@ -2153,9 +2506,22 @@
|
||||
if (stack.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
@@ -746,7 +751,7 @@
|
||||
world.addFreshEntity(entityitem);
|
||||
return entityitem;
|
||||
}
|
||||
@@ -2184,6 +2545,12 @@
|
||||
@@ -2184,6 +2550,12 @@
|
||||
if (this.isAlive() && this instanceof Leashable leashable) {
|
||||
if (leashable.getLeashHolder() == player) {
|
||||
if (!this.level().isClientSide()) {
|
||||
@@ -759,7 +764,7 @@
|
||||
if (player.hasInfiniteMaterials()) {
|
||||
leashable.removeLeash();
|
||||
} else {
|
||||
@@ -2200,6 +2567,13 @@
|
||||
@@ -2200,6 +2572,13 @@
|
||||
|
||||
if (itemstack.is(Items.LEAD) && leashable.canHaveALeashAttachedToIt()) {
|
||||
if (!this.level().isClientSide()) {
|
||||
@@ -773,7 +778,7 @@
|
||||
leashable.setLeashedTo(player, true);
|
||||
}
|
||||
|
||||
@@ -2265,7 +2639,7 @@
|
||||
@@ -2265,7 +2644,7 @@
|
||||
}
|
||||
|
||||
public boolean showVehicleHealth() {
|
||||
@@ -782,7 +787,7 @@
|
||||
}
|
||||
|
||||
public boolean startRiding(Entity entity, boolean force) {
|
||||
@@ -2273,7 +2647,7 @@
|
||||
@@ -2273,7 +2652,7 @@
|
||||
return false;
|
||||
} else if (!entity.couldAcceptPassenger()) {
|
||||
return false;
|
||||
@@ -791,7 +796,7 @@
|
||||
return false;
|
||||
} else {
|
||||
for (Entity entity1 = entity; entity1.vehicle != null; entity1 = entity1.vehicle) {
|
||||
@@ -2285,11 +2659,32 @@
|
||||
@@ -2285,11 +2664,32 @@
|
||||
if (!force && (!this.canRide(entity) || !entity.canAddPassenger(this))) {
|
||||
return false;
|
||||
} else {
|
||||
@@ -825,7 +830,7 @@
|
||||
this.vehicle = entity;
|
||||
this.vehicle.addPassenger(this);
|
||||
entity.getIndirectPassengersStream().filter((entity2) -> {
|
||||
@@ -2318,7 +2713,7 @@
|
||||
@@ -2318,7 +2718,7 @@
|
||||
Entity entity = this.vehicle;
|
||||
|
||||
this.vehicle = null;
|
||||
@@ -834,7 +839,7 @@
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2349,21 +2744,50 @@
|
||||
@@ -2349,21 +2749,50 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -891,7 +896,7 @@
|
||||
}
|
||||
|
||||
protected boolean canAddPassenger(Entity passenger) {
|
||||
@@ -2464,7 +2888,7 @@
|
||||
@@ -2464,7 +2893,7 @@
|
||||
if (teleporttransition != null) {
|
||||
ServerLevel worldserver1 = teleporttransition.newLevel();
|
||||
|
||||
@@ -900,7 +905,7 @@
|
||||
this.teleport(teleporttransition);
|
||||
}
|
||||
}
|
||||
@@ -2547,7 +2971,7 @@
|
||||
@@ -2547,7 +2976,7 @@
|
||||
}
|
||||
|
||||
public boolean isCrouching() {
|
||||
@@ -909,7 +914,7 @@
|
||||
}
|
||||
|
||||
public boolean isSprinting() {
|
||||
@@ -2563,7 +2987,7 @@
|
||||
@@ -2563,7 +2992,7 @@
|
||||
}
|
||||
|
||||
public boolean isVisuallySwimming() {
|
||||
@@ -918,7 +923,7 @@
|
||||
}
|
||||
|
||||
public boolean isVisuallyCrawling() {
|
||||
@@ -2571,6 +2995,13 @@
|
||||
@@ -2571,6 +3000,13 @@
|
||||
}
|
||||
|
||||
public void setSwimming(boolean swimming) {
|
||||
@@ -932,7 +937,7 @@
|
||||
this.setSharedFlag(4, swimming);
|
||||
}
|
||||
|
||||
@@ -2624,8 +3055,12 @@
|
||||
@@ -2624,8 +3060,12 @@
|
||||
return this.getTeam() != null ? this.getTeam().isAlliedTo(team) : false;
|
||||
}
|
||||
|
||||
@@ -946,7 +951,7 @@
|
||||
}
|
||||
|
||||
public boolean getSharedFlag(int index) {
|
||||
@@ -2644,7 +3079,7 @@
|
||||
@@ -2644,7 +3084,7 @@
|
||||
}
|
||||
|
||||
public int getMaxAirSupply() {
|
||||
@@ -955,7 +960,7 @@
|
||||
}
|
||||
|
||||
public int getAirSupply() {
|
||||
@@ -2652,7 +3087,18 @@
|
||||
@@ -2652,7 +3092,18 @@
|
||||
}
|
||||
|
||||
public void setAirSupply(int air) {
|
||||
@@ -975,7 +980,7 @@
|
||||
}
|
||||
|
||||
public int getTicksFrozen() {
|
||||
@@ -2679,11 +3125,40 @@
|
||||
@@ -2679,11 +3130,40 @@
|
||||
|
||||
public void thunderHit(ServerLevel world, LightningBolt lightning) {
|
||||
this.setRemainingFireTicks(this.remainingFireTicks + 1);
|
||||
@@ -1018,7 +1023,7 @@
|
||||
}
|
||||
|
||||
public void onAboveBubbleCol(boolean drag) {
|
||||
@@ -2713,7 +3188,7 @@
|
||||
@@ -2713,7 +3193,7 @@
|
||||
this.resetFallDistance();
|
||||
}
|
||||
|
||||
@@ -1027,7 +1032,7 @@
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2852,6 +3327,18 @@
|
||||
@@ -2852,6 +3332,18 @@
|
||||
|
||||
if (world instanceof ServerLevel worldserver) {
|
||||
if (!this.isRemoved()) {
|
||||
@@ -1046,7 +1051,7 @@
|
||||
ServerLevel worldserver1 = teleportTarget.newLevel();
|
||||
boolean flag = worldserver1.dimension() != worldserver.dimension();
|
||||
|
||||
@@ -2920,8 +3407,12 @@
|
||||
@@ -2920,8 +3412,12 @@
|
||||
} else {
|
||||
entity.restoreFrom(this);
|
||||
this.removeAfterChangingDimensions();
|
||||
@@ -1060,7 +1065,7 @@
|
||||
Iterator iterator1 = list1.iterator();
|
||||
|
||||
while (iterator1.hasNext()) {
|
||||
@@ -2947,7 +3438,7 @@
|
||||
@@ -2947,7 +3443,7 @@
|
||||
}
|
||||
|
||||
private void sendTeleportTransitionToRidingPlayers(TeleportTransition teleportTarget) {
|
||||
@@ -1069,7 +1074,7 @@
|
||||
Iterator iterator = this.getIndirectPassengers().iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
@@ -2995,8 +3486,9 @@
|
||||
@@ -2995,8 +3491,9 @@
|
||||
}
|
||||
|
||||
protected void removeAfterChangingDimensions() {
|
||||
@@ -1080,7 +1085,7 @@
|
||||
leashable.removeLeash();
|
||||
}
|
||||
|
||||
@@ -3006,6 +3498,20 @@
|
||||
@@ -3006,6 +3503,20 @@
|
||||
return PortalShape.getRelativePosition(portalRect, portalAxis, this.position(), this.getDimensions(this.getPose()));
|
||||
}
|
||||
|
||||
@@ -1101,7 +1106,7 @@
|
||||
public boolean canUsePortal(boolean allowVehicles) {
|
||||
return (allowVehicles || !this.isPassenger()) && this.isAlive();
|
||||
}
|
||||
@@ -3134,10 +3640,16 @@
|
||||
@@ -3134,9 +3645,15 @@
|
||||
return (Boolean) this.entityData.get(Entity.DATA_CUSTOM_NAME_VISIBLE);
|
||||
}
|
||||
|
||||
@@ -1112,16 +1117,15 @@
|
||||
+ public final boolean teleportTo(ServerLevel world, double destX, double destY, double destZ, Set<Relative> flags, float yaw, float pitch, boolean resetCamera) {
|
||||
+ return this.teleportTo(world, destX, destY, destZ, flags, yaw, pitch, resetCamera, PlayerTeleportEvent.TeleportCause.UNKNOWN);
|
||||
+ }
|
||||
|
||||
+
|
||||
+ public boolean teleportTo(ServerLevel worldserver, double d0, double d1, double d2, Set<Relative> set, float f, float f1, boolean flag, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause) {
|
||||
+ float f2 = Mth.clamp(f1, -90.0F, 90.0F);
|
||||
+ Entity entity = this.teleport(new TeleportTransition(worldserver, new Vec3(d0, d1, d2), Vec3.ZERO, f, f2, set, TeleportTransition.DO_NOTHING, cause));
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
|
||||
return entity != null;
|
||||
}
|
||||
|
||||
@@ -3187,7 +3699,7 @@
|
||||
@@ -3187,7 +3704,7 @@
|
||||
/** @deprecated */
|
||||
@Deprecated
|
||||
protected void fixupDimensions() {
|
||||
@@ -1130,7 +1134,7 @@
|
||||
EntityDimensions entitysize = this.getDimensions(entitypose);
|
||||
|
||||
this.dimensions = entitysize;
|
||||
@@ -3196,7 +3708,7 @@
|
||||
@@ -3196,7 +3713,7 @@
|
||||
|
||||
public void refreshDimensions() {
|
||||
EntityDimensions entitysize = this.dimensions;
|
||||
@@ -1139,7 +1143,7 @@
|
||||
EntityDimensions entitysize1 = this.getDimensions(entitypose);
|
||||
|
||||
this.dimensions = entitysize1;
|
||||
@@ -3258,10 +3770,29 @@
|
||||
@@ -3258,10 +3775,29 @@
|
||||
}
|
||||
|
||||
public final void setBoundingBox(AABB boundingBox) {
|
||||
@@ -1171,7 +1175,7 @@
|
||||
return this.getDimensions(pose).eyeHeight();
|
||||
}
|
||||
|
||||
@@ -3335,7 +3866,7 @@
|
||||
@@ -3335,7 +3871,7 @@
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -1180,7 +1184,7 @@
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -3435,7 +3966,7 @@
|
||||
@@ -3435,7 +3971,7 @@
|
||||
}
|
||||
|
||||
public boolean isControlledByLocalInstance() {
|
||||
@@ -1189,7 +1193,7 @@
|
||||
|
||||
if (entityliving instanceof Player entityhuman) {
|
||||
return entityhuman.isLocalPlayer();
|
||||
@@ -3445,7 +3976,7 @@
|
||||
@@ -3445,7 +3981,7 @@
|
||||
}
|
||||
|
||||
public boolean isControlledByClient() {
|
||||
@@ -1198,7 +1202,7 @@
|
||||
|
||||
return entityliving != null && entityliving.isControlledByClient();
|
||||
}
|
||||
@@ -3463,7 +3994,7 @@
|
||||
@@ -3463,7 +3999,7 @@
|
||||
return new Vec3((double) f1 * d2 / (double) f3, 0.0D, (double) f2 * d2 / (double) f3);
|
||||
}
|
||||
|
||||
@@ -1207,7 +1211,7 @@
|
||||
return new Vec3(this.getX(), this.getBoundingBox().maxY, this.getZ());
|
||||
}
|
||||
|
||||
@@ -3489,8 +4020,37 @@
|
||||
@@ -3489,8 +4025,37 @@
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1246,7 +1250,7 @@
|
||||
}
|
||||
|
||||
public void lookAt(EntityAnchorArgument.Anchor anchorPoint, Vec3 target) {
|
||||
@@ -3550,7 +4110,12 @@
|
||||
@@ -3550,7 +4115,12 @@
|
||||
|
||||
vec3d = vec3d.add(vec3d1);
|
||||
++k1;
|
||||
@@ -1259,7 +1263,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3613,7 +4178,7 @@
|
||||
@@ -3613,7 +4183,7 @@
|
||||
return new ClientboundAddEntityPacket(this, entityTrackerEntry);
|
||||
}
|
||||
|
||||
@@ -1268,7 +1272,7 @@
|
||||
return this.type.getDimensions();
|
||||
}
|
||||
|
||||
@@ -3818,8 +4383,16 @@
|
||||
@@ -3818,8 +4388,16 @@
|
||||
|
||||
@Override
|
||||
public final void setRemoved(Entity.RemovalReason reason) {
|
||||
@@ -1286,7 +1290,7 @@
|
||||
}
|
||||
|
||||
if (this.removalReason.shouldDestroy()) {
|
||||
@@ -3827,8 +4400,8 @@
|
||||
@@ -3827,8 +4405,8 @@
|
||||
}
|
||||
|
||||
this.getPassengers().forEach(Entity::stopRiding);
|
||||
@@ -1297,7 +1301,7 @@
|
||||
}
|
||||
|
||||
public void unsetRemoved() {
|
||||
@@ -3887,7 +4460,7 @@
|
||||
@@ -3887,7 +4465,7 @@
|
||||
}
|
||||
|
||||
public Vec3 getKnownMovement() {
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
public int lastHurtByPlayerTime;
|
||||
protected boolean dead;
|
||||
protected int noActionTime;
|
||||
@@ -260,7 +287,27 @@
|
||||
@@ -260,6 +287,27 @@
|
||||
protected boolean skipDropExperience;
|
||||
private final EnumMap<EquipmentSlot, Reference2ObjectMap<Enchantment, Set<EnchantmentLocationBasedEffect>>> activeLocationDependentEnchantments;
|
||||
protected float appliedScale;
|
||||
@@ -79,7 +79,8 @@
|
||||
+ public boolean collides = true;
|
||||
+ public Set<UUID> collidableExemptions = new HashSet<>();
|
||||
+ public boolean bukkitPickUpLoot;
|
||||
|
||||
+ public org.bukkit.craftbukkit.entity.CraftLivingEntity getBukkitLivingEntity() { return (org.bukkit.craftbukkit.entity.CraftLivingEntity) super.getBukkitEntity(); } // Paper
|
||||
+
|
||||
+ @Override
|
||||
+ public float getBukkitYaw() {
|
||||
+ return this.getYHeadRot();
|
||||
@@ -92,11 +93,10 @@
|
||||
+ ++this.noActionTime; // Above all the floats
|
||||
+ }
|
||||
+ // Spigot end
|
||||
+
|
||||
|
||||
protected LivingEntity(EntityType<? extends LivingEntity> type, Level world) {
|
||||
super(type, world);
|
||||
this.lastHandItemStacks = NonNullList.withSize(2, ItemStack.EMPTY);
|
||||
@@ -276,7 +323,9 @@
|
||||
@@ -276,7 +324,9 @@
|
||||
this.activeLocationDependentEnchantments = new EnumMap(EquipmentSlot.class);
|
||||
this.appliedScale = 1.0F;
|
||||
this.attributes = new AttributeMap(DefaultAttributes.getSupplier(type));
|
||||
@@ -107,7 +107,7 @@
|
||||
this.blocksBuilding = true;
|
||||
this.rotA = (float) ((Math.random() + 1.0D) * 0.009999999776482582D);
|
||||
this.reapplyPosition();
|
||||
@@ -356,7 +405,13 @@
|
||||
@@ -356,7 +406,13 @@
|
||||
double d8 = Math.min((double) (0.2F + f / 15.0F), 2.5D);
|
||||
int i = (int) (150.0D * d8);
|
||||
|
||||
@@ -122,7 +122,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -402,7 +457,7 @@
|
||||
@@ -402,7 +458,7 @@
|
||||
}
|
||||
|
||||
if (this.isAlive()) {
|
||||
@@ -131,7 +131,7 @@
|
||||
Level world1 = this.level();
|
||||
ServerLevel worldserver1;
|
||||
double d0;
|
||||
@@ -424,7 +479,7 @@
|
||||
@@ -424,7 +480,7 @@
|
||||
}
|
||||
|
||||
if (this.isEyeInFluid(FluidTags.WATER) && !this.level().getBlockState(BlockPos.containing(this.getX(), this.getEyeY(), this.getZ())).is(Blocks.BUBBLE_COLUMN)) {
|
||||
@@ -140,7 +140,7 @@
|
||||
|
||||
if (flag1) {
|
||||
this.setAirSupply(this.decreaseAirSupply(this.getAirSupply()));
|
||||
@@ -573,7 +628,7 @@
|
||||
@@ -573,7 +629,7 @@
|
||||
++this.deathTime;
|
||||
if (this.deathTime >= 20 && !this.level().isClientSide() && !this.isRemoved()) {
|
||||
this.level().broadcastEntityEvent(this, (byte) 60);
|
||||
@@ -149,7 +149,7 @@
|
||||
}
|
||||
|
||||
}
|
||||
@@ -629,7 +684,7 @@
|
||||
@@ -629,7 +685,7 @@
|
||||
return this.lastHurtByMobTimestamp;
|
||||
}
|
||||
|
||||
@@ -158,25 +158,26 @@
|
||||
this.lastHurtByPlayer = attacking;
|
||||
this.lastHurtByPlayerTime = this.tickCount;
|
||||
}
|
||||
@@ -679,17 +734,23 @@
|
||||
@@ -679,17 +735,23 @@
|
||||
}
|
||||
|
||||
public void onEquipItem(EquipmentSlot slot, ItemStack oldStack, ItemStack newStack) {
|
||||
- if (!this.level().isClientSide() && !this.isSpectator()) {
|
||||
- boolean flag = newStack.isEmpty() && oldStack.isEmpty();
|
||||
-
|
||||
- if (!flag && !ItemStack.isSameItemSameComponents(oldStack, newStack) && !this.firstTick) {
|
||||
- Equippable equippable = (Equippable) newStack.get(DataComponents.EQUIPPABLE);
|
||||
+ // CraftBukkit start
|
||||
+ this.onEquipItem(slot, oldStack, newStack, false);
|
||||
+ }
|
||||
|
||||
- if (!flag && !ItemStack.isSameItemSameComponents(oldStack, newStack) && !this.firstTick) {
|
||||
- Equippable equippable = (Equippable) newStack.get(DataComponents.EQUIPPABLE);
|
||||
- if (!this.isSilent() && equippable != null && slot == equippable.slot()) {
|
||||
- this.level().playSeededSound((Player) null, this.getX(), this.getY(), this.getZ(), equippable.equipSound(), this.getSoundSource(), 1.0F, 1.0F, this.random.nextLong());
|
||||
+ public void onEquipItem(EquipmentSlot enumitemslot, ItemStack itemstack, ItemStack itemstack1, boolean silent) {
|
||||
+ // CraftBukkit end
|
||||
+ if (!this.level().isClientSide() && !this.isSpectator()) {
|
||||
+ boolean flag = itemstack1.isEmpty() && itemstack.isEmpty();
|
||||
|
||||
- if (!this.isSilent() && equippable != null && slot == equippable.slot()) {
|
||||
- this.level().playSeededSound((Player) null, this.getX(), this.getY(), this.getZ(), equippable.equipSound(), this.getSoundSource(), 1.0F, 1.0F, this.random.nextLong());
|
||||
+
|
||||
+ if (!flag && !ItemStack.isSameItemSameComponents(itemstack, itemstack1) && !this.firstTick) {
|
||||
+ Equippable equippable = (Equippable) itemstack1.get(DataComponents.EQUIPPABLE);
|
||||
+
|
||||
@@ -189,7 +190,7 @@
|
||||
this.gameEvent(equippable != null ? GameEvent.EQUIP : GameEvent.UNEQUIP);
|
||||
}
|
||||
|
||||
@@ -699,17 +760,24 @@
|
||||
@@ -699,17 +761,24 @@
|
||||
|
||||
@Override
|
||||
public void remove(Entity.RemovalReason reason) {
|
||||
@@ -217,7 +218,7 @@
|
||||
this.brain.clearMemories();
|
||||
}
|
||||
|
||||
@@ -722,6 +790,7 @@
|
||||
@@ -722,6 +791,7 @@
|
||||
mobeffect.onMobRemoved(world, this, reason);
|
||||
}
|
||||
|
||||
@@ -225,7 +226,7 @@
|
||||
this.activeEffects.clear();
|
||||
}
|
||||
|
||||
@@ -781,6 +850,17 @@
|
||||
@@ -781,6 +851,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,7 +244,7 @@
|
||||
if (nbt.contains("Health", 99)) {
|
||||
this.setHealth(nbt.getFloat("Health"));
|
||||
}
|
||||
@@ -819,9 +899,32 @@
|
||||
@@ -819,9 +900,32 @@
|
||||
|
||||
}
|
||||
|
||||
@@ -276,7 +277,7 @@
|
||||
try {
|
||||
while (iterator.hasNext()) {
|
||||
Holder<MobEffect> holder = (Holder) iterator.next();
|
||||
@@ -831,6 +934,12 @@
|
||||
@@ -831,6 +935,12 @@
|
||||
this.onEffectUpdated(mobeffect, true, (Entity) null);
|
||||
})) {
|
||||
if (!this.level().isClientSide) {
|
||||
@@ -289,7 +290,7 @@
|
||||
iterator.remove();
|
||||
this.onEffectsRemoved(List.of(mobeffect));
|
||||
}
|
||||
@@ -841,6 +950,17 @@
|
||||
@@ -841,6 +951,17 @@
|
||||
} catch (ConcurrentModificationException concurrentmodificationexception) {
|
||||
;
|
||||
}
|
||||
@@ -307,7 +308,7 @@
|
||||
|
||||
if (this.effectsDirty) {
|
||||
if (!this.level().isClientSide) {
|
||||
@@ -921,7 +1041,7 @@
|
||||
@@ -921,7 +1042,7 @@
|
||||
}
|
||||
|
||||
public boolean canAttack(LivingEntity target) {
|
||||
@@ -316,7 +317,7 @@
|
||||
}
|
||||
|
||||
public boolean canBeSeenAsEnemy() {
|
||||
@@ -952,17 +1072,36 @@
|
||||
@@ -952,17 +1073,36 @@
|
||||
this.entityData.set(LivingEntity.DATA_EFFECT_PARTICLES, List.of());
|
||||
}
|
||||
|
||||
@@ -357,7 +358,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -987,24 +1126,55 @@
|
||||
@@ -987,24 +1127,55 @@
|
||||
return this.addEffect(effect, (Entity) null);
|
||||
}
|
||||
|
||||
@@ -421,7 +422,7 @@
|
||||
return flag;
|
||||
}
|
||||
}
|
||||
@@ -1031,14 +1201,40 @@
|
||||
@@ -1031,14 +1202,40 @@
|
||||
return this.getType().is(EntityTypeTags.INVERTED_HEALING_AND_HARM);
|
||||
}
|
||||
|
||||
@@ -464,7 +465,7 @@
|
||||
if (mobeffect != null) {
|
||||
this.onEffectsRemoved(List.of(mobeffect));
|
||||
return true;
|
||||
@@ -1142,20 +1338,55 @@
|
||||
@@ -1142,20 +1339,55 @@
|
||||
|
||||
}
|
||||
|
||||
@@ -521,7 +522,7 @@
|
||||
this.entityData.set(LivingEntity.DATA_HEALTH_ID, Mth.clamp(health, 0.0F, this.getMaxHealth()));
|
||||
}
|
||||
|
||||
@@ -1167,7 +1398,7 @@
|
||||
@@ -1167,7 +1399,7 @@
|
||||
public boolean hurtServer(ServerLevel world, DamageSource source, float amount) {
|
||||
if (this.isInvulnerableTo(world, source)) {
|
||||
return false;
|
||||
@@ -530,7 +531,7 @@
|
||||
return false;
|
||||
} else if (source.is(DamageTypeTags.IS_FIRE) && this.hasEffect(MobEffects.FIRE_RESISTANCE)) {
|
||||
return false;
|
||||
@@ -1182,10 +1413,11 @@
|
||||
@@ -1182,10 +1414,11 @@
|
||||
}
|
||||
|
||||
float f1 = amount;
|
||||
@@ -544,7 +545,7 @@
|
||||
this.hurtCurrentlyUsedShield(amount);
|
||||
f2 = amount;
|
||||
amount = 0.0F;
|
||||
@@ -1202,15 +1434,26 @@
|
||||
@@ -1202,15 +1435,26 @@
|
||||
flag = true;
|
||||
}
|
||||
|
||||
@@ -573,7 +574,7 @@
|
||||
this.walkAnimation.setSpeed(1.5F);
|
||||
if (Float.isNaN(amount) || Float.isInfinite(amount)) {
|
||||
amount = Float.MAX_VALUE;
|
||||
@@ -1218,18 +1461,27 @@
|
||||
@@ -1218,18 +1462,27 @@
|
||||
|
||||
boolean flag1 = true;
|
||||
|
||||
@@ -605,7 +606,7 @@
|
||||
this.hurtDuration = 10;
|
||||
this.hurtTime = this.hurtDuration;
|
||||
}
|
||||
@@ -1243,7 +1495,7 @@
|
||||
@@ -1243,7 +1496,7 @@
|
||||
world.broadcastDamageEvent(this, source);
|
||||
}
|
||||
|
||||
@@ -614,7 +615,7 @@
|
||||
this.markHurt();
|
||||
}
|
||||
|
||||
@@ -1263,7 +1515,7 @@
|
||||
@@ -1263,7 +1516,7 @@
|
||||
d1 = source.getSourcePosition().z() - this.getZ();
|
||||
}
|
||||
|
||||
@@ -623,7 +624,7 @@
|
||||
if (!flag) {
|
||||
this.indicateDamage(d0, d1);
|
||||
}
|
||||
@@ -1282,7 +1534,7 @@
|
||||
@@ -1282,7 +1535,7 @@
|
||||
this.playHurtSound(source);
|
||||
}
|
||||
|
||||
@@ -632,7 +633,7 @@
|
||||
|
||||
if (flag2) {
|
||||
this.lastDamageSource = source;
|
||||
@@ -1329,10 +1581,10 @@
|
||||
@@ -1329,10 +1582,10 @@
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -645,7 +646,7 @@
|
||||
this.lastHurtByPlayerTime = 100;
|
||||
this.lastHurtByPlayer = entityhuman;
|
||||
return entityhuman;
|
||||
@@ -1342,8 +1594,8 @@
|
||||
@@ -1342,8 +1595,8 @@
|
||||
this.lastHurtByPlayerTime = 100;
|
||||
LivingEntity entityliving = entitywolf.getOwner();
|
||||
|
||||
@@ -656,7 +657,7 @@
|
||||
|
||||
this.lastHurtByPlayer = entityhuman1;
|
||||
} else {
|
||||
@@ -1363,7 +1615,7 @@
|
||||
@@ -1363,7 +1616,7 @@
|
||||
}
|
||||
|
||||
protected void blockedByShield(LivingEntity target) {
|
||||
@@ -665,7 +666,7 @@
|
||||
}
|
||||
|
||||
private boolean checkTotemDeathProtection(DamageSource source) {
|
||||
@@ -1375,20 +1627,33 @@
|
||||
@@ -1375,20 +1628,33 @@
|
||||
InteractionHand[] aenumhand = InteractionHand.values();
|
||||
int i = aenumhand.length;
|
||||
|
||||
@@ -703,7 +704,7 @@
|
||||
ServerPlayer entityplayer = (ServerPlayer) this;
|
||||
|
||||
entityplayer.awardStat(Stats.ITEM_USED.get(itemstack.getItem()));
|
||||
@@ -1477,7 +1742,7 @@
|
||||
@@ -1477,7 +1743,7 @@
|
||||
}
|
||||
|
||||
if (!this.level().isClientSide && this.hasCustomName()) {
|
||||
@@ -712,7 +713,7 @@
|
||||
}
|
||||
|
||||
this.dead = true;
|
||||
@@ -1512,14 +1777,22 @@
|
||||
@@ -1512,14 +1778,22 @@
|
||||
BlockState iblockdata = Blocks.WITHER_ROSE.defaultBlockState();
|
||||
|
||||
if (this.level().getBlockState(blockposition).isAir() && iblockdata.canSurvive(this.level(), blockposition)) {
|
||||
@@ -737,7 +738,7 @@
|
||||
this.level().addFreshEntity(entityitem);
|
||||
}
|
||||
}
|
||||
@@ -1530,24 +1803,39 @@
|
||||
@@ -1530,22 +1804,37 @@
|
||||
protected void dropAllDeathLoot(ServerLevel world, DamageSource damageSource) {
|
||||
boolean flag = this.lastHurtByPlayerTime > 0;
|
||||
|
||||
@@ -767,8 +768,8 @@
|
||||
}
|
||||
|
||||
+ return 0; // CraftBukkit
|
||||
}
|
||||
|
||||
+ }
|
||||
+
|
||||
+ protected void dropExperience(ServerLevel world, @Nullable Entity attacker) {
|
||||
+ // CraftBukkit start - Update getExpReward() above if the removed if() changes!
|
||||
+ if (!(this instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon)) { // CraftBukkit - SPIGOT-2420: Special case ender dragon will drop the xp over time
|
||||
@@ -776,12 +777,10 @@
|
||||
+ this.expToDrop = 0;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ }
|
||||
+
|
||||
protected void dropCustomDeathLoot(ServerLevel world, DamageSource source, boolean causedByPlayer) {}
|
||||
}
|
||||
|
||||
public long getLootTableSeed() {
|
||||
@@ -1612,19 +1900,31 @@
|
||||
protected void dropCustomDeathLoot(ServerLevel world, DamageSource source, boolean causedByPlayer) {}
|
||||
@@ -1612,19 +1901,31 @@
|
||||
}
|
||||
|
||||
public void knockback(double strength, double x, double z) {
|
||||
@@ -820,7 +819,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1683,6 +1983,20 @@
|
||||
@@ -1683,6 +1984,20 @@
|
||||
return new LivingEntity.Fallsounds(SoundEvents.GENERIC_SMALL_FALL, SoundEvents.GENERIC_BIG_FALL);
|
||||
}
|
||||
|
||||
@@ -841,7 +840,7 @@
|
||||
public Optional<BlockPos> getLastClimbablePos() {
|
||||
return this.lastClimbablePos;
|
||||
}
|
||||
@@ -1757,9 +2071,14 @@
|
||||
@@ -1757,9 +2072,14 @@
|
||||
int i = this.calculateFallDamage(fallDistance, damageMultiplier);
|
||||
|
||||
if (i > 0) {
|
||||
@@ -857,7 +856,7 @@
|
||||
return true;
|
||||
} else {
|
||||
return flag;
|
||||
@@ -1830,7 +2149,7 @@
|
||||
@@ -1830,7 +2150,7 @@
|
||||
|
||||
protected float getDamageAfterArmorAbsorb(DamageSource source, float amount) {
|
||||
if (!source.is(DamageTypeTags.BYPASSES_ARMOR)) {
|
||||
@@ -866,7 +865,7 @@
|
||||
amount = CombatRules.getDamageAfterAbsorb(this, amount, source, (float) this.getArmorValue(), (float) this.getAttributeValue(Attributes.ARMOR_TOUGHNESS));
|
||||
}
|
||||
|
||||
@@ -1841,7 +2160,8 @@
|
||||
@@ -1841,7 +2161,8 @@
|
||||
if (source.is(DamageTypeTags.BYPASSES_EFFECTS)) {
|
||||
return amount;
|
||||
} else {
|
||||
@@ -876,7 +875,7 @@
|
||||
int i = (this.getEffect(MobEffects.DAMAGE_RESISTANCE).getAmplifier() + 1) * 5;
|
||||
int j = 25 - i;
|
||||
float f1 = amount * (float) j;
|
||||
@@ -1884,18 +2204,144 @@
|
||||
@@ -1884,18 +2205,144 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1030,7 +1029,7 @@
|
||||
|
||||
if (entity instanceof ServerPlayer) {
|
||||
ServerPlayer entityplayer = (ServerPlayer) entity;
|
||||
@@ -1904,13 +2350,48 @@
|
||||
@@ -1904,13 +2351,48 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1083,7 +1082,7 @@
|
||||
}
|
||||
|
||||
public CombatTracker getCombatTracker() {
|
||||
@@ -1935,8 +2416,18 @@
|
||||
@@ -1935,8 +2417,18 @@
|
||||
}
|
||||
|
||||
public final void setArrowCount(int stuckArrowCount) {
|
||||
@@ -1103,7 +1102,7 @@
|
||||
|
||||
public final int getStingerCount() {
|
||||
return (Integer) this.entityData.get(LivingEntity.DATA_STINGER_COUNT_ID);
|
||||
@@ -1999,7 +2490,7 @@
|
||||
@@ -1999,7 +2491,7 @@
|
||||
this.playSound(soundeffect, this.getSoundVolume(), (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F);
|
||||
}
|
||||
|
||||
@@ -1112,7 +1111,7 @@
|
||||
this.setHealth(0.0F);
|
||||
this.die(this.damageSources().generic());
|
||||
}
|
||||
@@ -2182,6 +2673,12 @@
|
||||
@@ -2182,6 +2674,12 @@
|
||||
|
||||
public abstract ItemStack getItemBySlot(EquipmentSlot slot);
|
||||
|
||||
@@ -1125,7 +1124,7 @@
|
||||
public abstract void setItemSlot(EquipmentSlot slot, ItemStack stack);
|
||||
|
||||
public Iterable<ItemStack> getHandSlots() {
|
||||
@@ -2494,7 +2991,7 @@
|
||||
@@ -2494,7 +2992,7 @@
|
||||
|
||||
}
|
||||
|
||||
@@ -1134,7 +1133,7 @@
|
||||
Vec3 vec3d1 = this.getRiddenInput(controllingPlayer, movementInput);
|
||||
|
||||
this.tickRidden(controllingPlayer, vec3d1);
|
||||
@@ -2507,13 +3004,13 @@
|
||||
@@ -2507,13 +3005,13 @@
|
||||
|
||||
}
|
||||
|
||||
@@ -1151,7 +1150,7 @@
|
||||
return this.getSpeed();
|
||||
}
|
||||
|
||||
@@ -2571,7 +3068,7 @@
|
||||
@@ -2571,7 +3069,7 @@
|
||||
double d1 = Mth.clamp(motion.z, -0.15000000596046448D, 0.15000000596046448D);
|
||||
double d2 = Math.max(motion.y, -0.15000000596046448D);
|
||||
|
||||
@@ -1160,7 +1159,7 @@
|
||||
d2 = 0.0D;
|
||||
}
|
||||
|
||||
@@ -2586,7 +3083,7 @@
|
||||
@@ -2586,7 +3084,7 @@
|
||||
}
|
||||
|
||||
protected float getFlyingSpeed() {
|
||||
@@ -1169,7 +1168,7 @@
|
||||
}
|
||||
|
||||
public float getSpeed() {
|
||||
@@ -2604,6 +3101,7 @@
|
||||
@@ -2604,6 +3102,7 @@
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
@@ -1177,7 +1176,7 @@
|
||||
super.tick();
|
||||
this.updatingUsingItem();
|
||||
this.updateSwimAmount();
|
||||
@@ -2634,7 +3132,7 @@
|
||||
@@ -2634,7 +3133,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1186,7 +1185,7 @@
|
||||
if (this.tickCount % 20 == 0) {
|
||||
this.getCombatTracker().recheckStatus();
|
||||
}
|
||||
@@ -2645,7 +3143,9 @@
|
||||
@@ -2645,7 +3144,9 @@
|
||||
}
|
||||
|
||||
if (!this.isRemoved()) {
|
||||
@@ -1196,7 +1195,7 @@
|
||||
}
|
||||
|
||||
double d0 = this.getX() - this.xo;
|
||||
@@ -2739,9 +3239,10 @@
|
||||
@@ -2739,9 +3240,10 @@
|
||||
}
|
||||
|
||||
this.elytraAnimationState.tick();
|
||||
@@ -1208,7 +1207,7 @@
|
||||
Map<EquipmentSlot, ItemStack> map = this.collectEquipmentChanges();
|
||||
|
||||
if (map != null) {
|
||||
@@ -2945,6 +3446,7 @@
|
||||
@@ -2945,6 +3447,7 @@
|
||||
ProfilerFiller gameprofilerfiller = Profiler.get();
|
||||
|
||||
gameprofilerfiller.push("ai");
|
||||
@@ -1216,7 +1215,7 @@
|
||||
if (this.isImmobile()) {
|
||||
this.jumping = false;
|
||||
this.xxa = 0.0F;
|
||||
@@ -2954,6 +3456,7 @@
|
||||
@@ -2954,6 +3457,7 @@
|
||||
this.serverAiStep();
|
||||
gameprofilerfiller.pop();
|
||||
}
|
||||
@@ -1224,7 +1223,7 @@
|
||||
|
||||
gameprofilerfiller.pop();
|
||||
gameprofilerfiller.push("jump");
|
||||
@@ -2996,11 +3499,12 @@
|
||||
@@ -2996,11 +3500,12 @@
|
||||
this.resetFallDistance();
|
||||
}
|
||||
|
||||
@@ -1238,7 +1237,7 @@
|
||||
if (this.isAlive()) {
|
||||
this.travelRidden(entityhuman, vec3d1);
|
||||
break label112;
|
||||
@@ -3009,6 +3513,7 @@
|
||||
@@ -3009,6 +3514,7 @@
|
||||
|
||||
this.travel(vec3d1);
|
||||
}
|
||||
@@ -1246,7 +1245,7 @@
|
||||
|
||||
if (!this.level().isClientSide() || this.isControlledByLocalInstance()) {
|
||||
this.applyEffectsFromBlocks();
|
||||
@@ -3044,7 +3549,9 @@
|
||||
@@ -3044,7 +3550,9 @@
|
||||
this.checkAutoSpinAttack(axisalignedbb, this.getBoundingBox());
|
||||
}
|
||||
|
||||
@@ -1256,7 +1255,7 @@
|
||||
gameprofilerfiller.pop();
|
||||
world = this.level();
|
||||
if (world instanceof ServerLevel worldserver) {
|
||||
@@ -3063,6 +3570,7 @@
|
||||
@@ -3063,6 +3571,7 @@
|
||||
this.checkSlowFallDistance();
|
||||
if (!this.level().isClientSide) {
|
||||
if (!this.canGlide()) {
|
||||
@@ -1264,7 +1263,7 @@
|
||||
this.setSharedFlag(7, false);
|
||||
return;
|
||||
}
|
||||
@@ -3113,7 +3621,7 @@
|
||||
@@ -3113,7 +3622,7 @@
|
||||
Level world = this.level();
|
||||
|
||||
if (!(world instanceof ServerLevel worldserver)) {
|
||||
@@ -1273,7 +1272,7 @@
|
||||
} else {
|
||||
List list = this.level().getEntities((Entity) this, this.getBoundingBox(), EntitySelector.pushableBy(this));
|
||||
|
||||
@@ -3305,15 +3813,22 @@
|
||||
@@ -3305,15 +3814,22 @@
|
||||
|
||||
@Override
|
||||
public boolean isPickable() {
|
||||
@@ -1298,7 +1297,7 @@
|
||||
public float getYHeadRot() {
|
||||
return this.yHeadRot;
|
||||
}
|
||||
@@ -3483,8 +3998,31 @@
|
||||
@@ -3483,8 +3999,31 @@
|
||||
this.releaseUsingItem();
|
||||
} else {
|
||||
if (!this.useItem.isEmpty() && this.isUsingItem()) {
|
||||
@@ -1331,7 +1330,7 @@
|
||||
if (itemstack != this.useItem) {
|
||||
this.setItemInHand(enumhand, itemstack);
|
||||
}
|
||||
@@ -3568,12 +4106,18 @@
|
||||
@@ -3568,12 +4107,18 @@
|
||||
}
|
||||
|
||||
public boolean randomTeleport(double x, double y, double z, boolean particleEffects) {
|
||||
@@ -1352,7 +1351,7 @@
|
||||
Level world = this.level();
|
||||
|
||||
if (world.hasChunkAt(blockposition)) {
|
||||
@@ -3592,18 +4136,43 @@
|
||||
@@ -3592,18 +4137,43 @@
|
||||
}
|
||||
|
||||
if (flag2) {
|
||||
@@ -1400,7 +1399,7 @@
|
||||
world.broadcastEntityEvent(this, (byte) 46);
|
||||
}
|
||||
|
||||
@@ -3613,7 +4182,7 @@
|
||||
@@ -3613,7 +4183,7 @@
|
||||
entitycreature.getNavigation().stop();
|
||||
}
|
||||
|
||||
@@ -1409,7 +1408,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3706,7 +4275,7 @@
|
||||
@@ -3706,7 +4276,7 @@
|
||||
}
|
||||
|
||||
public void stopSleeping() {
|
||||
@@ -1418,7 +1417,7 @@
|
||||
Level world = this.level();
|
||||
|
||||
java.util.Objects.requireNonNull(world);
|
||||
@@ -3718,9 +4287,9 @@
|
||||
@@ -3718,9 +4288,9 @@
|
||||
|
||||
this.level().setBlock(blockposition, (BlockState) iblockdata.setValue(BedBlock.OCCUPIED, false), 3);
|
||||
Vec3 vec3d = (Vec3) BedBlock.findStandUpPosition(this.getType(), this.level(), blockposition, enumdirection, this.getYRot()).orElseGet(() -> {
|
||||
@@ -1430,7 +1429,7 @@
|
||||
});
|
||||
Vec3 vec3d1 = Vec3.atBottomCenterOf(blockposition).subtract(vec3d).normalize();
|
||||
float f = (float) Mth.wrapDegrees(Mth.atan2(vec3d1.z, vec3d1.x) * 57.2957763671875D - 90.0D);
|
||||
@@ -3740,7 +4309,7 @@
|
||||
@@ -3740,7 +4310,7 @@
|
||||
|
||||
@Nullable
|
||||
public Direction getBedOrientation() {
|
||||
@@ -1439,7 +1438,7 @@
|
||||
|
||||
return blockposition != null ? BedBlock.getBedOrientation(this.level(), blockposition) : null;
|
||||
}
|
||||
@@ -3905,7 +4474,7 @@
|
||||
@@ -3905,7 +4475,7 @@
|
||||
public float maxUpStep() {
|
||||
float f = (float) this.getAttributeValue(Attributes.STEP_HEIGHT);
|
||||
|
||||
|
||||
@@ -454,7 +454,34 @@
|
||||
|
||||
@Nullable
|
||||
public <T> T set(DataComponentType<? super T> type, @Nullable T value) {
|
||||
@@ -858,7 +1082,7 @@
|
||||
@@ -804,7 +1028,26 @@
|
||||
} else {
|
||||
this.getItem().verifyComponentsAfterLoad(this);
|
||||
}
|
||||
+ }
|
||||
+
|
||||
+ // Paper start - (this is just a good no conflict location)
|
||||
+ public org.bukkit.inventory.ItemStack asBukkitMirror() {
|
||||
+ return CraftItemStack.asCraftMirror(this);
|
||||
+ }
|
||||
+ public org.bukkit.inventory.ItemStack asBukkitCopy() {
|
||||
+ return CraftItemStack.asCraftMirror(this.copy());
|
||||
+ }
|
||||
+ public static ItemStack fromBukkitCopy(org.bukkit.inventory.ItemStack itemstack) {
|
||||
+ return CraftItemStack.asNMSCopy(itemstack);
|
||||
+ }
|
||||
+ private org.bukkit.craftbukkit.inventory.CraftItemStack bukkitStack;
|
||||
+ public org.bukkit.inventory.ItemStack getBukkitStack() {
|
||||
+ if (bukkitStack == null || bukkitStack.handle != this) {
|
||||
+ bukkitStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(this);
|
||||
+ }
|
||||
+ return bukkitStack;
|
||||
}
|
||||
+ // Paper end
|
||||
|
||||
public void applyComponents(DataComponentPatch changes) {
|
||||
this.components.applyPatch(changes);
|
||||
@@ -858,7 +1101,7 @@
|
||||
}
|
||||
|
||||
private <T extends TooltipProvider> void addToTooltip(DataComponentType<T> componentType, Item.TooltipContext context, Consumer<Component> textConsumer, TooltipFlag type) {
|
||||
@@ -463,7 +490,7 @@
|
||||
|
||||
if (t0 != null) {
|
||||
t0.addToTooltip(context, textConsumer, type);
|
||||
@@ -866,7 +1090,7 @@
|
||||
@@ -866,7 +1109,7 @@
|
||||
|
||||
}
|
||||
|
||||
@@ -472,7 +499,7 @@
|
||||
boolean flag = this.getItem().shouldPrintOpWarning(this, player);
|
||||
|
||||
if (!type.isCreative() && this.has(DataComponents.HIDE_TOOLTIP)) {
|
||||
@@ -941,7 +1165,7 @@
|
||||
@@ -941,7 +1184,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -481,7 +508,7 @@
|
||||
ItemAttributeModifiers itemattributemodifiers = (ItemAttributeModifiers) this.getOrDefault(DataComponents.ATTRIBUTE_MODIFIERS, ItemAttributeModifiers.EMPTY);
|
||||
|
||||
if (itemattributemodifiers.showInTooltip()) {
|
||||
@@ -966,7 +1190,7 @@
|
||||
@@ -966,7 +1209,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -490,13 +517,14 @@
|
||||
double d0 = modifier.amount();
|
||||
boolean flag = false;
|
||||
|
||||
@@ -1091,6 +1315,13 @@
|
||||
@@ -1091,6 +1334,14 @@
|
||||
EnchantmentHelper.forEachModifier(this, slot, attributeModifierConsumer);
|
||||
}
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ @Deprecated
|
||||
+ public void setItem(Item item) {
|
||||
+ this.bukkitStack = null; // Paper
|
||||
+ this.item = item;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
@@ -504,7 +532,7 @@
|
||||
public Component getDisplayName() {
|
||||
MutableComponent ichatmutablecomponent = Component.empty().append(this.getHoverName());
|
||||
|
||||
@@ -1153,7 +1384,7 @@
|
||||
@@ -1153,7 +1404,7 @@
|
||||
}
|
||||
|
||||
public void consume(int amount, @Nullable LivingEntity entity) {
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
--- a/net/minecraft/world/level/BlockGetter.java
|
||||
+++ b/net/minecraft/world/level/BlockGetter.java
|
||||
@@ -31,7 +31,7 @@
|
||||
@@ -12,6 +12,7 @@
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.util.Mth;
|
||||
+import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
@@ -31,10 +32,19 @@
|
||||
default <T extends BlockEntity> Optional<T> getBlockEntity(BlockPos pos, BlockEntityType<T> type) {
|
||||
BlockEntity tileentity = this.getBlockEntity(pos);
|
||||
|
||||
@@ -9,7 +17,19 @@
|
||||
}
|
||||
|
||||
BlockState getBlockState(BlockPos pos);
|
||||
@@ -59,8 +59,8 @@
|
||||
+ // Paper start - if loaded util
|
||||
+ @Nullable BlockState getBlockStateIfLoaded(BlockPos blockposition);
|
||||
+
|
||||
+ default @Nullable Block getBlockIfLoaded(BlockPos blockposition) {
|
||||
+ BlockState type = this.getBlockStateIfLoaded(blockposition);
|
||||
+ return type == null ? null : type.getBlock();
|
||||
+ }
|
||||
+ @Nullable FluidState getFluidIfLoaded(BlockPos blockposition);
|
||||
+ // Paper end
|
||||
|
||||
FluidState getFluidState(BlockPos pos);
|
||||
|
||||
@@ -59,8 +69,8 @@
|
||||
});
|
||||
}
|
||||
|
||||
@@ -20,7 +40,7 @@
|
||||
BlockState iblockdata = this.getBlockState(blockposition);
|
||||
FluidState fluid = this.getFluidState(blockposition);
|
||||
Vec3 vec3d = raytrace1.getFrom();
|
||||
@@ -73,6 +73,12 @@
|
||||
@@ -73,6 +83,12 @@
|
||||
double d1 = movingobjectpositionblock1 == null ? Double.MAX_VALUE : raytrace1.getFrom().distanceToSqr(movingobjectpositionblock1.getLocation());
|
||||
|
||||
return d0 <= d1 ? movingobjectpositionblock : movingobjectpositionblock1;
|
||||
@@ -33,7 +53,7 @@
|
||||
}, (raytrace1) -> {
|
||||
Vec3 vec3d = raytrace1.getFrom().subtract(raytrace1.getTo());
|
||||
|
||||
@@ -145,7 +151,7 @@
|
||||
@@ -145,7 +161,7 @@
|
||||
double d13 = d10 * (i1 > 0 ? 1.0D - Mth.frac(d4) : Mth.frac(d4));
|
||||
double d14 = d11 * (j1 > 0 ? 1.0D - Mth.frac(d5) : Mth.frac(d5));
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
--- a/net/minecraft/world/level/ChunkPos.java
|
||||
+++ b/net/minecraft/world/level/ChunkPos.java
|
||||
@@ -46,6 +46,7 @@
|
||||
public static final int REGION_MAX_INDEX = 31;
|
||||
public final int x;
|
||||
public final int z;
|
||||
+ public final long longKey; // Paper
|
||||
private static final int HASH_A = 1664525;
|
||||
private static final int HASH_C = 1013904223;
|
||||
private static final int HASH_Z_XOR = -559038737;
|
||||
@@ -53,16 +54,19 @@
|
||||
public ChunkPos(int x, int z) {
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
+ this.longKey = asLong(this.x, this.z); // Paper
|
||||
}
|
||||
|
||||
public ChunkPos(BlockPos pos) {
|
||||
this.x = SectionPos.blockToSectionCoord(pos.getX());
|
||||
this.z = SectionPos.blockToSectionCoord(pos.getZ());
|
||||
+ this.longKey = asLong(this.x, this.z); // Paper
|
||||
}
|
||||
|
||||
public ChunkPos(long pos) {
|
||||
this.x = (int)pos;
|
||||
this.z = (int)(pos >> 32);
|
||||
+ this.longKey = asLong(this.x, this.z); // Paper
|
||||
}
|
||||
|
||||
public static ChunkPos minFromRegion(int x, int z) {
|
||||
@@ -74,7 +78,7 @@
|
||||
}
|
||||
|
||||
public long toLong() {
|
||||
- return asLong(this.x, this.z);
|
||||
+ return longKey; // Paper
|
||||
}
|
||||
|
||||
public static long asLong(int chunkX, int chunkZ) {
|
||||
@@ -0,0 +1,22 @@
|
||||
--- a/net/minecraft/world/level/EmptyBlockGetter.java
|
||||
+++ b/net/minecraft/world/level/EmptyBlockGetter.java
|
||||
@@ -17,7 +17,19 @@
|
||||
return null;
|
||||
}
|
||||
|
||||
+ // Paper start - If loaded util
|
||||
@Override
|
||||
+ public final FluidState getFluidIfLoaded(BlockPos blockposition) {
|
||||
+ return Fluids.EMPTY.defaultFluidState();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public final BlockState getBlockStateIfLoaded(BlockPos blockposition) {
|
||||
+ return Blocks.AIR.defaultBlockState();
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
+ @Override
|
||||
public BlockState getBlockState(BlockPos pos) {
|
||||
return Blocks.AIR.defaultBlockState();
|
||||
}
|
||||
@@ -31,7 +31,7 @@
|
||||
import net.minecraft.world.level.entity.EntityTypeTest;
|
||||
import net.minecraft.world.level.entity.LevelEntityGetter;
|
||||
import net.minecraft.world.level.gameevent.GameEvent;
|
||||
@@ -81,6 +85,25 @@
|
||||
@@ -81,6 +85,26 @@
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraft.world.scores.Scoreboard;
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
+import org.bukkit.craftbukkit.CraftWorld;
|
||||
+import org.bukkit.craftbukkit.SpigotTimings; // Spigot
|
||||
+import org.bukkit.craftbukkit.block.CapturedBlockState;
|
||||
+import org.bukkit.craftbukkit.block.CraftBlockState;
|
||||
+import org.bukkit.craftbukkit.block.data.CraftBlockData;
|
||||
+import org.bukkit.craftbukkit.util.CraftSpawnCategory;
|
||||
+import org.bukkit.entity.SpawnCategory;
|
||||
@@ -57,7 +58,7 @@
|
||||
public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
|
||||
public static final Codec<ResourceKey<Level>> RESOURCE_KEY_CODEC = ResourceKey.codec(Registries.DIMENSION);
|
||||
@@ -121,23 +144,73 @@
|
||||
@@ -121,23 +145,73 @@
|
||||
private final DamageSources damageSources;
|
||||
private long subTickCount;
|
||||
|
||||
@@ -140,7 +141,7 @@
|
||||
}
|
||||
};
|
||||
} else {
|
||||
@@ -145,11 +218,50 @@
|
||||
@@ -145,11 +219,50 @@
|
||||
}
|
||||
|
||||
this.thread = Thread.currentThread();
|
||||
@@ -196,7 +197,77 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -207,6 +319,18 @@
|
||||
@@ -163,6 +276,13 @@
|
||||
return null;
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ public net.minecraft.world.phys.BlockHitResult.Type clipDirect(Vec3 start, Vec3 end, net.minecraft.world.phys.shapes.CollisionContext context) {
|
||||
+ // To be patched over
|
||||
+ return this.clip(new ClipContext(start, end, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, context)).getType();
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
public boolean isInWorldBounds(BlockPos pos) {
|
||||
return !this.isOutsideBuildHeight(pos) && Level.isInWorldBoundsHorizontal(pos);
|
||||
}
|
||||
@@ -179,18 +299,52 @@
|
||||
return y < -20000000 || y >= 20000000;
|
||||
}
|
||||
|
||||
- public LevelChunk getChunkAt(BlockPos pos) {
|
||||
+ public final LevelChunk getChunkAt(BlockPos pos) { // Paper - help inline
|
||||
return this.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ()));
|
||||
}
|
||||
|
||||
@Override
|
||||
- public LevelChunk getChunk(int chunkX, int chunkZ) {
|
||||
- return (LevelChunk) this.getChunk(chunkX, chunkZ, ChunkStatus.FULL);
|
||||
+ public final LevelChunk getChunk(int chunkX, int chunkZ) { // Paper - final to help inline
|
||||
+ return (LevelChunk) this.getChunk(chunkX, chunkZ, ChunkStatus.FULL, true); // Paper - avoid a method jump
|
||||
}
|
||||
|
||||
+ // Paper start - if loaded
|
||||
@Nullable
|
||||
@Override
|
||||
+ public final ChunkAccess getChunkIfLoadedImmediately(int x, int z) {
|
||||
+ return ((ServerLevel)this).chunkSource.getChunkAtIfLoadedImmediately(x, z);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ @Nullable
|
||||
+ public final BlockState getBlockStateIfLoaded(BlockPos pos) {
|
||||
+ // CraftBukkit start - tree generation
|
||||
+ if (this.captureTreeGeneration) {
|
||||
+ CraftBlockState previous = this.capturedBlockStates.get(pos);
|
||||
+ if (previous != null) {
|
||||
+ return previous.getHandle();
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ if (this.isOutsideBuildHeight(pos)) {
|
||||
+ return Blocks.VOID_AIR.defaultBlockState();
|
||||
+ } else {
|
||||
+ ChunkAccess chunk = this.getChunkIfLoadedImmediately(pos.getX() >> 4, pos.getZ() >> 4);
|
||||
+
|
||||
+ return chunk == null ? null : chunk.getBlockState(pos);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public final FluidState getFluidIfLoaded(BlockPos blockposition) {
|
||||
+ ChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4);
|
||||
+
|
||||
+ return chunk == null ? null : chunk.getFluidState(blockposition);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
public ChunkAccess getChunk(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) {
|
||||
+ // Paper end
|
||||
ChunkAccess ichunkaccess = this.getChunkSource().getChunk(chunkX, chunkZ, leastStatus, create);
|
||||
|
||||
if (ichunkaccess == null && create) {
|
||||
@@ -207,6 +361,18 @@
|
||||
|
||||
@Override
|
||||
public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) {
|
||||
@@ -215,7 +286,7 @@
|
||||
if (this.isOutsideBuildHeight(pos)) {
|
||||
return false;
|
||||
} else if (!this.isClientSide && this.isDebug()) {
|
||||
@@ -214,45 +338,124 @@
|
||||
@@ -214,44 +380,123 @@
|
||||
} else {
|
||||
LevelChunk chunk = this.getChunkAt(pos);
|
||||
Block block = state.getBlock();
|
||||
@@ -299,10 +370,10 @@
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // CraftBukkit start - Split off from above in order to directly send client and physic updates
|
||||
+ public void notifyAndUpdatePhysics(BlockPos blockposition, LevelChunk chunk, BlockState oldBlock, BlockState newBlock, BlockState actualBlock, int i, int j) {
|
||||
+ BlockState iblockdata = newBlock;
|
||||
@@ -322,7 +393,7 @@
|
||||
+ if (!this.isClientSide && iblockdata.hasAnalogOutputSignal()) {
|
||||
+ this.updateNeighbourForOutputSignal(blockposition, newBlock.getBlock());
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
+
|
||||
+ if ((i & 16) == 0 && j > 0) {
|
||||
+ int k = i & -34;
|
||||
@@ -348,14 +419,13 @@
|
||||
+ this.onBlockStateChange(blockposition, iblockdata1, iblockdata2);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
}
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
|
||||
public void onBlockStateChange(BlockPos pos, BlockState oldBlock, BlockState newBlock) {}
|
||||
|
||||
@Override
|
||||
@@ -340,6 +543,14 @@
|
||||
@@ -340,10 +585,18 @@
|
||||
|
||||
@Override
|
||||
public BlockState getBlockState(BlockPos pos) {
|
||||
@@ -370,7 +440,12 @@
|
||||
if (this.isOutsideBuildHeight(pos)) {
|
||||
return Blocks.VOID_AIR.defaultBlockState();
|
||||
} else {
|
||||
@@ -440,32 +651,48 @@
|
||||
- LevelChunk chunk = this.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ()));
|
||||
+ ChunkAccess chunk = this.getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.FULL, true); // Paper - manually inline to reduce hops and avoid unnecessary null check to reduce total byte code size, this should never return null and if it does we will see it the next line but the real stack trace will matter in the chunk engine
|
||||
|
||||
return chunk.getBlockState(pos);
|
||||
}
|
||||
@@ -440,32 +693,48 @@
|
||||
ProfilerFiller gameprofilerfiller = Profiler.get();
|
||||
|
||||
gameprofilerfiller.push("blockEntities");
|
||||
@@ -423,7 +498,7 @@
|
||||
} catch (Throwable throwable) {
|
||||
CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking entity");
|
||||
CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being ticked");
|
||||
@@ -510,13 +737,29 @@
|
||||
@@ -510,13 +779,29 @@
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockEntity getBlockEntity(BlockPos pos) {
|
||||
@@ -454,7 +529,7 @@
|
||||
this.getChunkAt(blockposition).addAndRegisterBlockEntity(blockEntity);
|
||||
}
|
||||
}
|
||||
@@ -643,7 +886,7 @@
|
||||
@@ -643,7 +928,7 @@
|
||||
|
||||
for (int k = 0; k < j; ++k) {
|
||||
EnderDragonPart entitycomplexpart = aentitycomplexpart[k];
|
||||
@@ -463,7 +538,7 @@
|
||||
|
||||
if (t0 != null && predicate.test(t0)) {
|
||||
result.add(t0);
|
||||
@@ -912,7 +1155,7 @@
|
||||
@@ -912,7 +1197,7 @@
|
||||
|
||||
public static enum ExplosionInteraction implements StringRepresentable {
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
--- a/net/minecraft/world/level/LevelReader.java
|
||||
+++ b/net/minecraft/world/level/LevelReader.java
|
||||
@@ -26,6 +26,9 @@
|
||||
@Nullable
|
||||
ChunkAccess getChunk(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create);
|
||||
|
||||
+ @Nullable ChunkAccess getChunkIfLoadedImmediately(int x, int z); // Paper - ifLoaded api (we need this since current impl blocks if the chunk is loading)
|
||||
+ @Nullable default ChunkAccess getChunkIfLoadedImmediately(BlockPos pos) { return this.getChunkIfLoadedImmediately(pos.getX() >> 4, pos.getZ() >> 4);}
|
||||
+
|
||||
@Deprecated
|
||||
boolean hasChunk(int chunkX, int chunkZ);
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
--- a/net/minecraft/world/level/PathNavigationRegion.java
|
||||
+++ b/net/minecraft/world/level/PathNavigationRegion.java
|
||||
@@ -8,6 +8,7 @@
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.SectionPos;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
+import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.Biomes;
|
||||
@@ -66,7 +67,7 @@
|
||||
private ChunkAccess getChunk(int chunkX, int chunkZ) {
|
||||
int i = chunkX - this.centerX;
|
||||
int j = chunkZ - this.centerZ;
|
||||
- if (i >= 0 && i < this.chunks.length && j >= 0 && j < this.chunks[i].length) {
|
||||
+ if (i >= 0 && i < this.chunks.length && j >= 0 && j < this.chunks[i].length) { // Paper - if this changes, update getChunkIfLoaded below
|
||||
ChunkAccess chunkAccess = this.chunks[i][j];
|
||||
return (ChunkAccess)(chunkAccess != null ? chunkAccess : new EmptyLevelChunk(this.level, new ChunkPos(chunkX, chunkZ), this.plains.get()));
|
||||
} else {
|
||||
@@ -74,7 +75,31 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start - if loaded util
|
||||
+ private @Nullable ChunkAccess getChunkIfLoaded(int x, int z) {
|
||||
+ // Based on getChunk(int, int)
|
||||
+ int xx = x - this.centerX;
|
||||
+ int zz = z - this.centerZ;
|
||||
+
|
||||
+ if (xx >= 0 && xx < this.chunks.length && zz >= 0 && zz < this.chunks[xx].length) {
|
||||
+ return this.chunks[xx][zz];
|
||||
+ }
|
||||
+ return null;
|
||||
+ }
|
||||
@Override
|
||||
+ public final FluidState getFluidIfLoaded(BlockPos blockposition) {
|
||||
+ ChunkAccess chunk = getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4);
|
||||
+ return chunk == null ? null : chunk.getFluidState(blockposition);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public final BlockState getBlockStateIfLoaded(BlockPos blockposition) {
|
||||
+ ChunkAccess chunk = getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4);
|
||||
+ return chunk == null ? null : chunk.getBlockState(blockposition);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
+ @Override
|
||||
public WorldBorder getWorldBorder() {
|
||||
return this.level.getWorldBorder();
|
||||
}
|
||||
@@ -50,7 +50,33 @@
|
||||
}
|
||||
|
||||
state.spawnAfterBreak(world, pos, ItemStack.EMPTY, flag);
|
||||
@@ -1125,9 +1139,15 @@
|
||||
@@ -873,12 +887,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ protected boolean shapeExceedsCube = true; // Paper - moved from actual method to here
|
||||
public void initCache() {
|
||||
this.fluidState = ((Block) this.owner).getFluidState(this.asState());
|
||||
this.isRandomlyTicking = ((Block) this.owner).isRandomlyTicking(this.asState());
|
||||
if (!this.getBlock().hasDynamicShape()) {
|
||||
this.cache = new BlockBehaviour.BlockStateBase.Cache(this.asState());
|
||||
}
|
||||
+ this.shapeExceedsCube = this.cache == null || this.cache.largeCollisionShape; // Paper - moved from actual method to here
|
||||
|
||||
this.legacySolid = this.calculateSolid();
|
||||
this.occlusionShape = this.canOcclude ? ((Block) this.owner).getOcclusionShape(this.asState()) : Shapes.empty();
|
||||
@@ -945,8 +961,8 @@
|
||||
return this.occlusionShape;
|
||||
}
|
||||
|
||||
- public boolean hasLargeCollisionShape() {
|
||||
- return this.cache == null || this.cache.largeCollisionShape;
|
||||
+ public final boolean hasLargeCollisionShape() { // Paper
|
||||
+ return this.shapeExceedsCube; // Paper - moved into shape cache init
|
||||
}
|
||||
|
||||
public boolean useShapeForLightOcclusion() {
|
||||
@@ -1125,9 +1141,15 @@
|
||||
}
|
||||
|
||||
public void onPlace(Level world, BlockPos pos, BlockState state, boolean notify) {
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
--- a/net/minecraft/world/level/chunk/ChunkAccess.java
|
||||
+++ b/net/minecraft/world/level/chunk/ChunkAccess.java
|
||||
@@ -85,6 +85,11 @@
|
||||
@@ -65,7 +65,7 @@
|
||||
protected final ShortList[] postProcessing;
|
||||
private volatile boolean unsaved;
|
||||
private volatile boolean isLightCorrect;
|
||||
- protected final ChunkPos chunkPos;
|
||||
+ protected final ChunkPos chunkPos; public final long coordinateKey; public final int locX; public final int locZ; // Paper - cache coordinate key
|
||||
private long inhabitedTime;
|
||||
/** @deprecated */
|
||||
@Nullable
|
||||
@@ -85,8 +85,14 @@
|
||||
protected final LevelHeightAccessor levelHeightAccessor;
|
||||
protected final LevelChunkSection[] sections;
|
||||
|
||||
@@ -10,9 +19,13 @@
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
public ChunkAccess(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor heightLimitView, Registry<Biome> biomeRegistry, long inhabitedTime, @Nullable LevelChunkSection[] sectionArray, @Nullable BlendingData blendingData) {
|
||||
this.chunkPos = pos;
|
||||
- this.chunkPos = pos;
|
||||
+ this.locX = pos.x; this.locZ = pos.z; // Paper - reduce need for field lookups
|
||||
+ this.chunkPos = pos; this.coordinateKey = ChunkPos.asLong(locX, locZ); // Paper - cache long key
|
||||
this.upgradeData = upgradeData;
|
||||
@@ -103,7 +108,11 @@
|
||||
this.levelHeightAccessor = heightLimitView;
|
||||
this.sections = new LevelChunkSection[heightLimitView.getSectionsCount()];
|
||||
@@ -103,7 +109,11 @@
|
||||
}
|
||||
|
||||
ChunkAccess.replaceMissingSections(biomeRegistry, this.sections);
|
||||
@@ -24,7 +37,7 @@
|
||||
|
||||
private static void replaceMissingSections(Registry<Biome> biomeRegistry, LevelChunkSection[] sectionArray) {
|
||||
for (int i = 0; i < sectionArray.length; ++i) {
|
||||
@@ -275,6 +284,7 @@
|
||||
@@ -275,6 +285,7 @@
|
||||
public boolean tryMarkSaved() {
|
||||
if (this.unsaved) {
|
||||
this.unsaved = false;
|
||||
@@ -32,7 +45,7 @@
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -282,7 +292,7 @@
|
||||
@@ -282,7 +293,7 @@
|
||||
}
|
||||
|
||||
public boolean isUnsaved() {
|
||||
@@ -41,10 +54,15 @@
|
||||
}
|
||||
|
||||
public abstract ChunkStatus getPersistedStatus();
|
||||
@@ -463,6 +473,27 @@
|
||||
}
|
||||
}
|
||||
@@ -458,10 +469,31 @@
|
||||
|
||||
crashreportsystemdetails.setDetail("Location", () -> {
|
||||
return CrashReportCategory.formatLocation(this, biomeX, biomeY, biomeZ);
|
||||
+ });
|
||||
+ throw new ReportedException(crashreport);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // CraftBukkit start
|
||||
+ public void setBiome(int i, int j, int k, Holder<Biome> biome) {
|
||||
+ try {
|
||||
@@ -60,12 +78,11 @@
|
||||
+
|
||||
+ crashreportsystemdetails.setDetail("Location", () -> {
|
||||
+ return CrashReportCategory.formatLocation(this, i, j, k);
|
||||
+ });
|
||||
+ throw new ReportedException(crashreport);
|
||||
+ }
|
||||
+ }
|
||||
});
|
||||
throw new ReportedException(crashreport);
|
||||
}
|
||||
}
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
|
||||
public void fillBiomesFromNoise(BiomeResolver biomeSupplier, Climate.Sampler sampler) {
|
||||
ChunkPos chunkcoordintpair = this.getPos();
|
||||
int i = QuartPos.fromBlock(chunkcoordintpair.getMinBlockX());
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
--- a/net/minecraft/world/level/chunk/EmptyLevelChunk.java
|
||||
+++ b/net/minecraft/world/level/chunk/EmptyLevelChunk.java
|
||||
@@ -25,6 +25,12 @@
|
||||
public BlockState getBlockState(BlockPos pos) {
|
||||
return Blocks.VOID_AIR.defaultBlockState();
|
||||
}
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public BlockState getBlockState(final int x, final int y, final int z) {
|
||||
+ return Blocks.VOID_AIR.defaultBlockState();
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
@@ -18,7 +18,7 @@
|
||||
this.gameEventListenerRegistrySections = new Int2ObjectOpenHashMap();
|
||||
Heightmap.Types[] aheightmap_type = Heightmap.Types.values();
|
||||
int j = aheightmap_type.length;
|
||||
@@ -116,6 +116,11 @@
|
||||
@@ -116,6 +116,15 @@
|
||||
this.fluidTicks = fluidTickScheduler;
|
||||
}
|
||||
|
||||
@@ -26,11 +26,15 @@
|
||||
+ public boolean mustNotSave;
|
||||
+ public boolean needsDecoration;
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ // Paper start
|
||||
+ boolean loadedTicketLevel;
|
||||
+ // Paper end
|
||||
+
|
||||
public LevelChunk(ServerLevel world, ProtoChunk protoChunk, @Nullable LevelChunk.PostLoadProcessor entityLoader) {
|
||||
this(world, protoChunk.getPos(), protoChunk.getUpgradeData(), protoChunk.unpackBlockTicks(), protoChunk.unpackFluidTicks(), protoChunk.getInhabitedTime(), protoChunk.getSections(), entityLoader, protoChunk.getBlendingData());
|
||||
if (!Collections.disjoint(protoChunk.pendingBlockEntities.keySet(), protoChunk.blockEntities.keySet())) {
|
||||
@@ -151,6 +156,10 @@
|
||||
@@ -151,6 +160,10 @@
|
||||
this.skyLightSources = protoChunk.skyLightSources;
|
||||
this.setLightCorrect(protoChunk.isLightCorrect());
|
||||
this.markUnsaved();
|
||||
@@ -41,7 +45,53 @@
|
||||
}
|
||||
|
||||
public void setUnsavedListener(LevelChunk.UnsavedListener unsavedListener) {
|
||||
@@ -272,78 +281,86 @@
|
||||
@@ -200,8 +213,25 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start - Perf: Reduce instructions and provide final method
|
||||
+ public BlockState getBlockState(final int x, final int y, final int z) {
|
||||
+ return this.getBlockStateFinal(x, y, z);
|
||||
+ }
|
||||
+ public BlockState getBlockStateFinal(final int x, final int y, final int z) {
|
||||
+ // Copied and modified from below
|
||||
+ final int sectionIndex = this.getSectionIndex(y);
|
||||
+ if (sectionIndex < 0 || sectionIndex >= this.sections.length
|
||||
+ || this.sections[sectionIndex].nonEmptyBlockCount == 0) {
|
||||
+ return Blocks.AIR.defaultBlockState();
|
||||
+ }
|
||||
+ return this.sections[sectionIndex].states.get((y & 15) << 8 | (z & 15) << 4 | x & 15);
|
||||
+ }
|
||||
@Override
|
||||
public BlockState getBlockState(BlockPos pos) {
|
||||
+ if (true) {
|
||||
+ return this.getBlockStateFinal(pos.getX(), pos.getY(), pos.getZ());
|
||||
+ }
|
||||
+ // Paper end - Perf: Reduce instructions and provide final method
|
||||
int i = pos.getX();
|
||||
int j = pos.getY();
|
||||
int k = pos.getZ();
|
||||
@@ -243,7 +273,19 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start - If loaded util
|
||||
@Override
|
||||
+ public final FluidState getFluidIfLoaded(BlockPos blockposition) {
|
||||
+ return this.getFluidState(blockposition);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public final BlockState getBlockStateIfLoaded(BlockPos blockposition) {
|
||||
+ return this.getBlockState(blockposition);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
+ @Override
|
||||
public FluidState getFluidState(BlockPos pos) {
|
||||
return this.getFluidState(pos.getX(), pos.getY(), pos.getZ());
|
||||
}
|
||||
@@ -272,78 +314,86 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,7 +203,7 @@
|
||||
this.updateBlockEntityTicker(tileentity);
|
||||
}
|
||||
}
|
||||
@@ -375,7 +392,12 @@
|
||||
@@ -375,7 +425,12 @@
|
||||
|
||||
@Nullable
|
||||
public BlockEntity getBlockEntity(BlockPos pos, LevelChunk.EntityCreationType creationType) {
|
||||
@@ -167,7 +217,7 @@
|
||||
|
||||
if (tileentity == null) {
|
||||
CompoundTag nbttagcompound = (CompoundTag) this.pendingBlockEntities.remove(pos);
|
||||
@@ -447,6 +469,7 @@
|
||||
@@ -447,6 +502,7 @@
|
||||
|
||||
if (!iblockdata.hasBlockEntity()) {
|
||||
LevelChunk.LOGGER.warn("Trying to set block entity {} at position {}, but state {} does not allow it", new Object[]{blockEntity, blockposition, iblockdata});
|
||||
@@ -175,7 +225,7 @@
|
||||
} else {
|
||||
BlockState iblockdata1 = blockEntity.getBlockState();
|
||||
|
||||
@@ -500,6 +523,12 @@
|
||||
@@ -500,6 +556,12 @@
|
||||
if (this.isInLevel()) {
|
||||
BlockEntity tileentity = (BlockEntity) this.blockEntities.remove(pos);
|
||||
|
||||
@@ -188,7 +238,7 @@
|
||||
if (tileentity != null) {
|
||||
Level world = this.level;
|
||||
|
||||
@@ -549,10 +578,61 @@
|
||||
@@ -549,9 +611,68 @@
|
||||
if (this.postLoad != null) {
|
||||
this.postLoad.run(this);
|
||||
this.postLoad = null;
|
||||
@@ -198,7 +248,11 @@
|
||||
+
|
||||
+ // CraftBukkit start
|
||||
+ public void loadCallback() {
|
||||
+ // Paper start
|
||||
+ this.loadedTicketLevel = true;
|
||||
+ // Paper end
|
||||
+ org.bukkit.Server server = this.level.getCraftServer();
|
||||
+ this.level.getChunkSource().addLoadedChunk(this); // Paper
|
||||
+ if (server != null) {
|
||||
+ /*
|
||||
+ * If it's a new world, the first few chunks are generated inside
|
||||
@@ -239,18 +293,21 @@
|
||||
+ server.getPluginManager().callEvent(unloadEvent);
|
||||
+ // note: saving can be prevented, but not forced if no saving is actually required
|
||||
+ this.mustNotSave = !unloadEvent.isSaveChunk();
|
||||
}
|
||||
|
||||
+ this.level.getChunkSource().removeLoadedChunk(this); // Paper
|
||||
+ // Paper start
|
||||
+ this.loadedTicketLevel = false;
|
||||
+ // Paper end
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isUnsaved() {
|
||||
+ return super.isUnsaved() && !this.mustNotSave;
|
||||
+ }
|
||||
}
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
|
||||
public boolean isEmpty() {
|
||||
return false;
|
||||
}
|
||||
@@ -750,7 +830,7 @@
|
||||
@@ -750,7 +871,7 @@
|
||||
|
||||
private <T extends BlockEntity> void updateBlockEntityTicker(T blockEntity) {
|
||||
BlockState iblockdata = blockEntity.getBlockState();
|
||||
@@ -259,7 +316,7 @@
|
||||
|
||||
if (blockentityticker == null) {
|
||||
this.removeBlockEntityTicker(blockEntity.getBlockPos());
|
||||
@@ -841,7 +921,7 @@
|
||||
@@ -841,7 +962,7 @@
|
||||
private boolean loggedInvalidBlockState;
|
||||
|
||||
BoundTickingBlockEntity(final BlockEntity tileentity, final BlockEntityTicker blockentityticker) {
|
||||
@@ -268,7 +325,7 @@
|
||||
this.ticker = blockentityticker;
|
||||
}
|
||||
|
||||
@@ -855,6 +935,7 @@
|
||||
@@ -855,6 +976,7 @@
|
||||
ProfilerFiller gameprofilerfiller = Profiler.get();
|
||||
|
||||
gameprofilerfiller.push(this::getType);
|
||||
@@ -276,7 +333,7 @@
|
||||
BlockState iblockdata = LevelChunk.this.getBlockState(blockposition);
|
||||
|
||||
if (this.blockEntity.getType().isValid(iblockdata)) {
|
||||
@@ -872,6 +953,10 @@
|
||||
@@ -872,6 +994,10 @@
|
||||
|
||||
this.blockEntity.fillCrashReportCategory(crashreportsystemdetails);
|
||||
throw new ReportedException(crashreport);
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
--- a/net/minecraft/world/level/chunk/LevelChunkSection.java
|
||||
+++ b/net/minecraft/world/level/chunk/LevelChunkSection.java
|
||||
@@ -23,7 +23,7 @@
|
||||
@@ -19,11 +19,11 @@
|
||||
public static final int SECTION_HEIGHT = 16;
|
||||
public static final int SECTION_SIZE = 4096;
|
||||
public static final int BIOME_CONTAINER_BITS = 2;
|
||||
- private short nonEmptyBlockCount;
|
||||
+ short nonEmptyBlockCount; // Paper - package private
|
||||
private short tickingBlockCount;
|
||||
private short tickingFluidCount;
|
||||
public final PalettedContainer<BlockState> states;
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
--- a/net/minecraft/world/level/chunk/ProtoChunk.java
|
||||
+++ b/net/minecraft/world/level/chunk/ProtoChunk.java
|
||||
@@ -81,7 +81,19 @@
|
||||
@Override
|
||||
public ChunkAccess.PackedTicks getTicksForSerialization(long time) {
|
||||
return new ChunkAccess.PackedTicks(this.blockTicks.pack(time), this.fluidTicks.pack(time));
|
||||
+ }
|
||||
+
|
||||
+ // Paper start - If loaded util
|
||||
+ @Override
|
||||
+ public final FluidState getFluidIfLoaded(BlockPos blockposition) {
|
||||
+ return this.getFluidState(blockposition);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public final BlockState getBlockStateIfLoaded(BlockPos blockposition) {
|
||||
+ return this.getBlockState(blockposition);
|
||||
}
|
||||
+ // Paper end
|
||||
|
||||
@Override
|
||||
public BlockState getBlockState(BlockPos pos) {
|
||||
@@ -18,9 +18,12 @@
|
||||
ChunkStatusTasks.postLoadProtoChunk(worldserver, protochunk.getEntities());
|
||||
});
|
||||
generationchunkholder.replaceProtoChunk(new ImposterProtoChunk(chunk1, false));
|
||||
@@ -170,7 +170,17 @@
|
||||
@@ -168,9 +168,19 @@
|
||||
}, context.mainThreadExecutor());
|
||||
}
|
||||
|
||||
private static void postLoadProtoChunk(ServerLevel world, List<CompoundTag> entities) {
|
||||
- private static void postLoadProtoChunk(ServerLevel world, List<CompoundTag> entities) {
|
||||
+ public static void postLoadProtoChunk(ServerLevel world, List<CompoundTag> entities) { // Paper - public
|
||||
if (!entities.isEmpty()) {
|
||||
- world.addWorldGenChunkEntities(EntityType.loadEntitiesRecursive(entities, world, EntitySpawnReason.LOAD));
|
||||
+ // CraftBukkit start - these are spawned serialized (DefinedStructure) and we don't call an add event below at the moment due to ordering complexities
|
||||
|
||||
@@ -32,7 +32,24 @@
|
||||
void removeSectionIfEmpty(long sectionPos, EntitySection<T> section) {
|
||||
if (section.isEmpty()) {
|
||||
this.sectionStorage.remove(sectionPos);
|
||||
@@ -196,27 +211,35 @@
|
||||
@@ -76,6 +91,16 @@
|
||||
}
|
||||
|
||||
private boolean addEntity(T entity, boolean existing) {
|
||||
+ // Paper start - chunk system hooks
|
||||
+ // I don't want to know why this is a generic type.
|
||||
+ Entity entityCasted = (Entity)entity;
|
||||
+ boolean wasRemoved = entityCasted.isRemoved();
|
||||
+ boolean screened = ca.spottedleaf.moonrise.common.util.ChunkSystem.screenEntity((net.minecraft.server.level.ServerLevel)entityCasted.level(), entityCasted, existing, true);
|
||||
+ if ((!wasRemoved && entityCasted.isRemoved()) || !screened) {
|
||||
+ // removed by callback
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Paper end - chunk system hooks
|
||||
if (!this.addEntityUuid(entity)) {
|
||||
return false;
|
||||
} else {
|
||||
@@ -196,27 +221,35 @@
|
||||
}
|
||||
|
||||
private boolean storeChunkSections(long chunkPos, Consumer<T> action) {
|
||||
@@ -74,7 +91,7 @@
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -238,7 +261,7 @@
|
||||
@@ -238,7 +271,7 @@
|
||||
private boolean processChunkUnload(long chunkPos) {
|
||||
boolean flag = this.storeChunkSections(chunkPos, (entityaccess) -> {
|
||||
entityaccess.getPassengersAndSelf().forEach(this::unloadEntity);
|
||||
@@ -83,7 +100,7 @@
|
||||
|
||||
if (!flag) {
|
||||
return false;
|
||||
@@ -249,24 +272,28 @@
|
||||
@@ -249,24 +282,28 @@
|
||||
}
|
||||
|
||||
private void unloadEntity(EntityAccess entity) {
|
||||
@@ -115,7 +132,7 @@
|
||||
}
|
||||
|
||||
}
|
||||
@@ -292,7 +319,7 @@
|
||||
@@ -292,7 +329,7 @@
|
||||
}
|
||||
|
||||
public void autoSave() {
|
||||
@@ -124,7 +141,7 @@
|
||||
boolean flag = this.chunkVisibility.get(i) == Visibility.HIDDEN;
|
||||
|
||||
if (flag) {
|
||||
@@ -311,7 +338,7 @@
|
||||
@@ -311,7 +348,7 @@
|
||||
while (!longset.isEmpty()) {
|
||||
this.permanentStorage.flush(false);
|
||||
this.processPendingLoads();
|
||||
@@ -133,7 +150,7 @@
|
||||
boolean flag = this.chunkVisibility.get(i) == Visibility.HIDDEN;
|
||||
|
||||
return flag ? this.processChunkUnload(i) : this.storeChunkSections(i, (entityaccess) -> {
|
||||
@@ -323,7 +350,15 @@
|
||||
@@ -323,7 +360,15 @@
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
@@ -150,7 +167,7 @@
|
||||
this.permanentStorage.close();
|
||||
}
|
||||
|
||||
@@ -350,7 +385,7 @@
|
||||
@@ -350,7 +395,7 @@
|
||||
public void dumpSections(Writer writer) throws IOException {
|
||||
CsvOutput csvwriter = CsvOutput.builder().addColumn("x").addColumn("y").addColumn("z").addColumn("visibility").addColumn("load_status").addColumn("entity_count").build(writer);
|
||||
|
||||
@@ -159,7 +176,7 @@
|
||||
PersistentEntitySectionManager.ChunkLoadStatus persistententitysectionmanager_b = (PersistentEntitySectionManager.ChunkLoadStatus) this.chunkLoadStatuses.get(i);
|
||||
|
||||
this.sectionStorage.getExistingSectionPositionsInChunk(i).forEach((j) -> {
|
||||
@@ -394,7 +429,7 @@
|
||||
@@ -394,7 +439,7 @@
|
||||
private EntitySection<T> currentSection;
|
||||
|
||||
Callback(final EntityAccess entityaccess, final long i, final EntitySection entitysection) {
|
||||
|
||||
Reference in New Issue
Block a user