More more more more more more more more more more more more more work

This commit is contained in:
Nassim Jahnke 2021-11-24 16:07:19 +01:00 committed by MiniDigger | Martin
parent 4e81c1fe78
commit 45c36e5d0c
29 changed files with 247 additions and 269 deletions

View file

@ -1,93 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MiniDigger <admin@minidigger.me>
Date: Sat, 6 Jun 2020 18:13:16 +0200
Subject: [PATCH] Support components in ItemMeta
diff --git a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java
index 01b462fccce71cef3398dd43944046f322b8e57e..f093f991f1fedd20fcef041b093398250b7fb286 100644
--- a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java
+++ b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java
@@ -5,6 +5,7 @@ import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import net.kyori.adventure.text.Component;
import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeModifier;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
@@ -62,6 +63,20 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste
@NotNull
String getDisplayName();
+ // Paper start
+ /**
+ * Gets the display name that is set.
+ * <p>
+ * Plugins should check that hasDisplayName() returns <code>true</code>
+ * before calling this method.
+ *
+ * @return the display name that is set
+ * @deprecated use {@link #displayName()}
+ */
+ @NotNull
+ @Deprecated
+ net.md_5.bungee.api.chat.BaseComponent[] getDisplayNameComponent();
+ // Paper end
/**
* Sets the display name.
*
@@ -71,6 +86,16 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste
@Deprecated // Paper
void setDisplayName(@Nullable String name);
+ // Paper start
+ /**
+ * Sets the display name.
+ *
+ * @param component the name component to set
+ * @deprecated use {@link #displayName(Component)}
+ */
+ @Deprecated
+ void setDisplayNameComponent(@Nullable net.md_5.bungee.api.chat.BaseComponent[] component);
+ // Paper end
/**
* Checks for existence of a localized name.
*
@@ -134,6 +159,19 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste
@Nullable
List<String> getLore();
+ /**
+ * Gets the lore that is set.
+ * <p>
+ * Plugins should check if hasLore() returns <code>true</code> before
+ * calling this method.
+ *
+ * @return a list of lore that is set
+ * @deprecated use {@link #lore()}
+ */
+ @Nullable
+ @Deprecated
+ List<net.md_5.bungee.api.chat.BaseComponent[]> getLoreComponents();
+
/**
* Sets the lore for this item.
* Removes lore when given null.
@@ -144,6 +182,16 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste
@Deprecated // Paper
void setLore(@Nullable List<String> lore);
+ /**
+ * Sets the lore for this item.
+ * Removes lore when given null.
+ *
+ * @param lore the lore that will be set
+ * @deprecated use {@link #lore(List)}
+ */
+ @Deprecated
+ void setLoreComponents(@Nullable List<net.md_5.bungee.api.chat.BaseComponent[]> lore);
+
/**
* Checks for existence of custom model data.
* <p>

View file

@ -1,25 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Fri, 3 Jul 2020 15:05:54 -0700
Subject: [PATCH] added 2 new TargetReasons for 1.16 mob behavior
diff --git a/src/main/java/org/bukkit/event/entity/EntityTargetEvent.java b/src/main/java/org/bukkit/event/entity/EntityTargetEvent.java
index dee186e99463a56394bbc2039d1e763d109125b9..601904150156d475c18286b485f3409307a75950 100644
--- a/src/main/java/org/bukkit/event/entity/EntityTargetEvent.java
+++ b/src/main/java/org/bukkit/event/entity/EntityTargetEvent.java
@@ -159,6 +159,14 @@ public class EntityTargetEvent extends EntityEvent implements Cancellable {
* as wheat in it's hand.
*/
TEMPT,
+ /**
+ * When the target is in a different dimension
+ */
+ TARGET_OTHER_LEVEL, // Paper
+ /**
+ * When the target is in creative or spectator mode, or the gamemode is peaceful, or other reasons
+ */
+ TARGET_INVALID, // Paper
/**
* A currently unknown reason for the entity changing target.
*/

View file

@ -1,46 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Thu, 2 Jul 2020 18:11:33 -0500
Subject: [PATCH] Add entity liquid API
diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java
index 3bb7154a5be37e1943e4f94b5496019c07ca6937..c729cb44290cd719e7684fd919bf74300484b883 100644
--- a/src/main/java/org/bukkit/entity/Entity.java
+++ b/src/main/java/org/bukkit/entity/Entity.java
@@ -725,5 +725,35 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent
*/
@NotNull
org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason();
+
+ /**
+ * Check if entity is in rain
+ */
+ public boolean isInRain();
+
+ /**
+ * Check if entity is in bubble column
+ */
+ public boolean isInBubbleColumn();
+
+ /**
+ * Check if entity is in water or rain
+ */
+ public boolean isInWaterOrRain();
+
+ /**
+ * Check if entity is in water or bubble column
+ */
+ public boolean isInWaterOrBubbleColumn();
+
+ /**
+ * Check if entity is in water or rain or bubble column
+ */
+ public boolean isInWaterOrRainOrBubbleColumn();
+
+ /**
+ * Check if entity is in lava
+ */
+ public boolean isInLava();
// Paper end
}

View file

@ -1,211 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Fri, 3 Jul 2020 11:58:56 -0500
Subject: [PATCH] Add PrepareResultEvent / PrepareGrindstoneEvent
Adds a new event for all crafting stations that generate a result slot item
Anvil, Grindstone and Smithing now extend this event
Grindstone is a backwards compat from a previous PrepareGrindstoneEvent
diff --git a/src/main/java/com/destroystokyo/paper/event/inventory/PrepareGrindstoneEvent.java b/src/main/java/com/destroystokyo/paper/event/inventory/PrepareGrindstoneEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..449e8c06f8434b59d49a76481fa60c5c49e80579
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/inventory/PrepareGrindstoneEvent.java
@@ -0,0 +1,28 @@
+package com.destroystokyo.paper.event.inventory;
+
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.inventory.InventoryEvent;
+import org.bukkit.inventory.GrindstoneInventory;
+import org.bukkit.inventory.InventoryView;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Called when an item is put in a slot for grinding in a Grindstone
+ * @see com.destroystokyo.paper.event.inventory.PrepareResultEvent
+ */
+@Deprecated
+public class PrepareGrindstoneEvent extends PrepareResultEvent {
+
+ public PrepareGrindstoneEvent(@NotNull InventoryView inventory, @Nullable ItemStack result) {
+ super(inventory, result);
+ }
+
+ @NotNull
+ @Override
+ public GrindstoneInventory getInventory() {
+ return (GrindstoneInventory) super.getInventory();
+ }
+
+}
diff --git a/src/main/java/com/destroystokyo/paper/event/inventory/PrepareResultEvent.java b/src/main/java/com/destroystokyo/paper/event/inventory/PrepareResultEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..045ce9ec3c9134aced5f5235b760ac85599d16c6
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/inventory/PrepareResultEvent.java
@@ -0,0 +1,48 @@
+package com.destroystokyo.paper.event.inventory;
+
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.inventory.InventoryEvent;
+import org.bukkit.event.inventory.InventoryType;
+import org.bukkit.inventory.InventoryView;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Called when an item is put in an inventory containing a result slot
+ */
+public class PrepareResultEvent extends InventoryEvent {
+
+ private static final HandlerList handlers = new HandlerList();
+ private ItemStack result;
+
+ public PrepareResultEvent(@NotNull InventoryView inventory, @Nullable ItemStack result) {
+ super(inventory);
+ this.result = result;
+ }
+
+ /**
+ * Get result item, may be null.
+ *
+ * @return result item
+ */
+ @Nullable
+ public ItemStack getResult() {
+ return result;
+ }
+
+ public void setResult(@Nullable ItemStack result) {
+ this.result = result;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+}
diff --git a/src/main/java/org/bukkit/event/inventory/PrepareAnvilEvent.java b/src/main/java/org/bukkit/event/inventory/PrepareAnvilEvent.java
index 77109a07f07aa6985106dc1a9ad5218f6c7f360f..f1f6f4ab4f81a3f21e757fef4a30b00e94371f8d 100644
--- a/src/main/java/org/bukkit/event/inventory/PrepareAnvilEvent.java
+++ b/src/main/java/org/bukkit/event/inventory/PrepareAnvilEvent.java
@@ -1,5 +1,6 @@
package org.bukkit.event.inventory;
+import com.destroystokyo.paper.event.inventory.PrepareResultEvent;
import org.bukkit.event.HandlerList;
import org.bukkit.inventory.AnvilInventory;
import org.bukkit.inventory.InventoryView;
@@ -10,14 +11,16 @@ import org.jetbrains.annotations.Nullable;
/**
* Called when an item is put in a slot for repair by an anvil.
*/
-public class PrepareAnvilEvent extends InventoryEvent {
+// Paper start - extend PrepareResultEvent
+public class PrepareAnvilEvent extends PrepareResultEvent {
- private static final HandlerList handlers = new HandlerList();
- private ItemStack result;
+ //private static final HandlerList handlers = new HandlerList();
+ //private ItemStack result;
public PrepareAnvilEvent(@NotNull InventoryView inventory, @Nullable ItemStack result) {
- super(inventory);
- this.result = result;
+ super(inventory, result);
+ //this.result = result;
+ // Paper end
}
@NotNull
@@ -33,13 +36,14 @@ public class PrepareAnvilEvent extends InventoryEvent {
*/
@Nullable
public ItemStack getResult() {
- return result;
+ return super.getResult(); // Paper
}
public void setResult(@Nullable ItemStack result) {
- this.result = result;
+ super.setResult(result); // Paper
}
+ /* // Paper - comment out
@NotNull
@Override
public HandlerList getHandlers() {
@@ -50,4 +54,5 @@ public class PrepareAnvilEvent extends InventoryEvent {
public static HandlerList getHandlerList() {
return handlers;
}
+ */ // Paper
}
diff --git a/src/main/java/org/bukkit/event/inventory/PrepareSmithingEvent.java b/src/main/java/org/bukkit/event/inventory/PrepareSmithingEvent.java
index 99af1540324c4d68c5890ac40b591c5cbdd2e870..0bc0ca4f96c800e9c46c61710f44446691d8b93f 100644
--- a/src/main/java/org/bukkit/event/inventory/PrepareSmithingEvent.java
+++ b/src/main/java/org/bukkit/event/inventory/PrepareSmithingEvent.java
@@ -1,5 +1,6 @@
package org.bukkit.event.inventory;
+import com.destroystokyo.paper.event.inventory.PrepareResultEvent;
import org.bukkit.event.HandlerList;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.ItemStack;
@@ -10,14 +11,16 @@ import org.jetbrains.annotations.Nullable;
/**
* Called when an item is put in a slot for upgrade by a Smithing Table.
*/
-public class PrepareSmithingEvent extends InventoryEvent {
+// Paper start - extend PrepareResultEvent
+public class PrepareSmithingEvent extends PrepareResultEvent {
- private static final HandlerList handlers = new HandlerList();
- private ItemStack result;
+ //private static final HandlerList handlers = new HandlerList();
+ //private ItemStack result;
public PrepareSmithingEvent(@NotNull InventoryView inventory, @Nullable ItemStack result) {
- super(inventory);
- this.result = result;
+ super(inventory, result);
+ //this.result = result;
+ // Paper end
}
@NotNull
@@ -33,13 +36,14 @@ public class PrepareSmithingEvent extends InventoryEvent {
*/
@Nullable
public ItemStack getResult() {
- return result;
+ return super.getResult(); // Paper
}
public void setResult(@Nullable ItemStack result) {
- this.result = result;
+ super.setResult(result); // Paper
}
+ /* // Paper - comment out
@NotNull
@Override
public HandlerList getHandlers() {
@@ -50,4 +54,5 @@ public class PrepareSmithingEvent extends InventoryEvent {
public static HandlerList getHandlerList() {
return handlers;
}
+ */ // Paper
}

View file

@ -1,85 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MiniDigger <admin@minidigger.me>
Date: Wed, 29 Apr 2020 02:09:17 +0200
Subject: [PATCH] Allow delegation to vanilla chunk gen
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
index 474b7a7d14d1b4ef8146c7b23883651ff776e41b..2bcae78ec0016b465b611041b8397fee5a04baaf 100644
--- a/src/main/java/org/bukkit/Bukkit.java
+++ b/src/main/java/org/bukkit/Bukkit.java
@@ -1620,6 +1620,22 @@ public final class Bukkit {
return server.createChunkData(world);
}
+ // Paper start
+ /**
+ * Create a ChunkData for use in a generator, that is populated by the vanilla generator for that world
+ *
+ * @param world the world to create the ChunkData for
+ * @param x the x coordinate of the chunk
+ * @param z the z coordinate of the chunk
+ * @return a new ChunkData for the world
+ *
+ */
+ @NotNull
+ public static ChunkGenerator.ChunkData createVanillaChunkData(@NotNull World world, int x, int z) {
+ return server.createVanillaChunkData(world, x, z);
+ }
+ // Paper stop
+
/**
* Creates a boss bar instance to display to players. The progress
* defaults to 1.0
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
index 4800e1e0f127cc159bcc75c856aee9102462b01a..2a2f009a957c19a6d1ef1e284b27fe2f954f13e0 100644
--- a/src/main/java/org/bukkit/Server.java
+++ b/src/main/java/org/bukkit/Server.java
@@ -1371,6 +1371,20 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
@NotNull
public ChunkGenerator.ChunkData createChunkData(@NotNull World world);
+ // Paper start
+ /**
+ * Create a ChunkData for use in a generator, that is populated by the vanilla generator for that world
+ *
+ * @param world the world to create the ChunkData for
+ * @param x the x coordinate of the chunk
+ * @param z the z coordinate of the chunk
+ * @return a new ChunkData for the world
+ *
+ */
+ @NotNull
+ ChunkGenerator.ChunkData createVanillaChunkData(@NotNull World world, int x, int z);
+ // Paper end
+
/**
* Creates a boss bar instance to display to players. The progress
* defaults to 1.0
diff --git a/src/main/java/org/bukkit/generator/ChunkGenerator.java b/src/main/java/org/bukkit/generator/ChunkGenerator.java
index 80fcd02e9cb5f432f21b1f68fd8266f296becaa0..0667315e2bd10254aef59c2a6bcceee9d927b6d5 100644
--- a/src/main/java/org/bukkit/generator/ChunkGenerator.java
+++ b/src/main/java/org/bukkit/generator/ChunkGenerator.java
@@ -454,6 +454,22 @@ public abstract class ChunkGenerator {
return false;
}
+ // Paper start
+ /**
+ * Create a ChunkData for use in a generator, that is populated by the vanilla generator for that world
+ *
+ * @param world the world to create the ChunkData for
+ * @param x the x coordinate of the chunk
+ * @param z the z coordinate of the chunk
+ * @return a new ChunkData for the world
+ *
+ */
+ @NotNull
+ public ChunkData createVanillaChunkData(@NotNull World world, int x, int z) {
+ return Bukkit.getServer().createVanillaChunkData(world, x, z);
+ }
+ // Paper end
+
/**
* Data for a Chunk.
*/

View file

@ -1,213 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Thu, 4 Jun 2020 02:24:49 -0400
Subject: [PATCH] Optimize Bit Operations by inlining
Inline bit operations and reduce instruction count to make these hot
operations faster
diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java
index 80d8873bc2512ecde6a531e974b14e9b48402d64..b70aa66732fb5e957aed0901f4c76358b2c56f8e 100644
--- a/src/main/java/net/minecraft/core/BlockPos.java
+++ b/src/main/java/net/minecraft/core/BlockPos.java
@@ -30,15 +30,16 @@ public class BlockPos extends Vec3i {
}).stable();
private static final Logger LOGGER = LogManager.getLogger();
public static final BlockPos ZERO = new BlockPos(0, 0, 0);
- private static final int PACKED_X_LENGTH = 1 + Mth.log2(Mth.smallestEncompassingPowerOfTwo(30000000));
- private static final int PACKED_Z_LENGTH = PACKED_X_LENGTH;
- public static final int PACKED_Y_LENGTH = 64 - PACKED_X_LENGTH - PACKED_Z_LENGTH;
- private static final long PACKED_X_MASK = (1L << PACKED_X_LENGTH) - 1L;
- private static final long PACKED_Y_MASK = (1L << PACKED_Y_LENGTH) - 1L;
- private static final long PACKED_Z_MASK = (1L << PACKED_Z_LENGTH) - 1L;
- private static final int Y_OFFSET = 0;
- private static final int Z_OFFSET = PACKED_Y_LENGTH;
- private static final int X_OFFSET = PACKED_Y_LENGTH + PACKED_Z_LENGTH;
+ // Paper start - static constants
+ private static final int PACKED_X_LENGTH = 26;
+ private static final int PACKED_Z_LENGTH = 26;
+ public static final int PACKED_Y_LENGTH = 12;
+ private static final long PACKED_X_MASK = 67108863;
+ private static final long PACKED_Y_MASK = 4095;
+ private static final long PACKED_Z_MASK = 67108863;
+ private static final int Z_OFFSET = 12;
+ private static final int X_OFFSET = 38;
+ // Paper end
public BlockPos(int x, int y, int z) {
super(x, y, z);
@@ -60,28 +61,29 @@ public class BlockPos extends Vec3i {
this(pos.getX(), pos.getY(), pos.getZ());
}
+ public static long getAdjacent(int baseX, int baseY, int baseZ, Direction enumdirection) { return asLong(baseX + enumdirection.getStepX(), baseY + enumdirection.getStepY(), baseZ + enumdirection.getStepZ()); } // Paper
public static long offset(long value, Direction direction) {
return offset(value, direction.getStepX(), direction.getStepY(), direction.getStepZ());
}
public static long offset(long value, int x, int y, int z) {
- return asLong(getX(value) + x, getY(value) + y, getZ(value) + z);
+ return asLong((int) (value >> 38) + x, (int) ((value << 52) >> 52) + y, (int) ((value << 26) >> 38) + z); // Paper - simplify/inline
}
public static int getX(long packedPos) {
- return (int)(packedPos << 64 - X_OFFSET - PACKED_X_LENGTH >> 64 - PACKED_X_LENGTH);
+ return (int) (packedPos >> 38); // Paper - simplify/inline
}
public static int getY(long packedPos) {
- return (int)(packedPos << 64 - PACKED_Y_LENGTH >> 64 - PACKED_Y_LENGTH);
+ return (int) ((packedPos << 52) >> 52); // Paper - simplify/inline
}
public static int getZ(long packedPos) {
- return (int)(packedPos << 64 - Z_OFFSET - PACKED_Z_LENGTH >> 64 - PACKED_Z_LENGTH);
+ return (int) ((packedPos << 26) >> 38); // Paper - simplify/inline
}
public static BlockPos of(long packedPos) {
- return new BlockPos(getX(packedPos), getY(packedPos), getZ(packedPos));
+ return new BlockPos((int) (packedPos >> 38), (int) ((packedPos << 52) >> 52), (int) ((packedPos << 26) >> 38)); // Paper - simplify/inline
}
public long asLong() {
@@ -89,10 +91,7 @@ public class BlockPos extends Vec3i {
}
public static long asLong(int x, int y, int z) {
- long l = 0L;
- l = l | ((long)x & PACKED_X_MASK) << X_OFFSET;
- l = l | ((long)y & PACKED_Y_MASK) << 0;
- return l | ((long)z & PACKED_Z_MASK) << Z_OFFSET;
+ return (((long) x & (long) 67108863) << 38) | (((long) y & (long) 4095)) | (((long) z & (long) 67108863) << 12); // Paper - inline constants and simplify
}
public static long getFlatIndex(long y) {
diff --git a/src/main/java/net/minecraft/core/SectionPos.java b/src/main/java/net/minecraft/core/SectionPos.java
index 4ea92289304bdad469e67164442bc0b837183e8a..b0c39895e10fab5acc609128d34aafdebc5520f9 100644
--- a/src/main/java/net/minecraft/core/SectionPos.java
+++ b/src/main/java/net/minecraft/core/SectionPos.java
@@ -37,7 +37,7 @@ public class SectionPos extends Vec3i {
}
public static SectionPos of(BlockPos pos) {
- return new SectionPos(blockToSectionCoord(pos.getX()), blockToSectionCoord(pos.getY()), blockToSectionCoord(pos.getZ()));
+ return new SectionPos(pos.getX() >> 4, pos.getY() >> 4, pos.getZ() >> 4); // Paper
}
public static SectionPos of(ChunkPos chunkPos, int y) {
@@ -49,7 +49,7 @@ public class SectionPos extends Vec3i {
}
public static SectionPos of(long packed) {
- return new SectionPos(x(packed), y(packed), z(packed));
+ return new SectionPos((int) (packed >> 42), (int) (packed << 44 >> 44), (int) (packed << 22 >> 42)); // Paper
}
public static SectionPos bottomOf(ChunkAccess chunk) {
@@ -60,8 +60,16 @@ public class SectionPos extends Vec3i {
return offset(packed, direction.getStepX(), direction.getStepY(), direction.getStepZ());
}
+ // Paper start
+ public static long getAdjacentFromBlockPos(int x, int y, int z, Direction enumdirection) {
+ return (((long) ((x >> 4) + enumdirection.getStepX()) & 4194303L) << 42) | (((long) ((y >> 4) + enumdirection.getStepY()) & 1048575L)) | (((long) ((z >> 4) + enumdirection.getStepZ()) & 4194303L) << 20);
+ }
+ public static long getAdjacentFromSectionPos(int x, int y, int z, Direction enumdirection) {
+ return (((long) (x + enumdirection.getStepX()) & 4194303L) << 42) | (((long) ((y) + enumdirection.getStepY()) & 1048575L)) | (((long) (z + enumdirection.getStepZ()) & 4194303L) << 20);
+ }
+ // Paper end
public static long offset(long packed, int x, int y, int z) {
- return asLong(x(packed) + x, y(packed) + y, z(packed) + z);
+ return (((long) ((int) (packed >> 42) + x) & 4194303L) << 42) | (((long) ((int) (packed << 44 >> 44) + y) & 1048575L)) | (((long) ((int) (packed << 22 >> 42) + z) & 4194303L) << 20); // Simplify to reduce instruction count
}
public static int posToSectionCoord(double coord) {
@@ -77,10 +85,7 @@ public class SectionPos extends Vec3i {
}
public static short sectionRelativePos(BlockPos pos) {
- int i = sectionRelative(pos.getX());
- int j = sectionRelative(pos.getY());
- int k = sectionRelative(pos.getZ());
- return (short)(i << 8 | k << 4 | j << 0);
+ return (short) ((pos.getX() & 15) << 8 | (pos.getZ() & 15) << 4 | pos.getY() & 15); // Paper - simplify/inline
}
public static int sectionRelativeX(short packedLocalPos) {
@@ -143,16 +148,16 @@ public class SectionPos extends Vec3i {
return this.getZ();
}
- public int minBlockX() {
- return sectionToBlockCoord(this.x());
+ public final int minBlockX() { // Paper - make final
+ return this.getX() << 4; // Paper - inline
}
- public int minBlockY() {
- return sectionToBlockCoord(this.y());
+ public final int minBlockY() { // Paper - make final
+ return this.getY() << 4; // Paper - inline
}
- public int minBlockZ() {
- return sectionToBlockCoord(this.z());
+ public int minBlockZ() { // Paper - make final
+ return this.getZ() << 4; // Paper - inline
}
public int maxBlockX() {
@@ -168,7 +173,8 @@ public class SectionPos extends Vec3i {
}
public static long blockToSection(long blockPos) {
- return asLong(blockToSectionCoord(BlockPos.getX(blockPos)), blockToSectionCoord(BlockPos.getY(blockPos)), blockToSectionCoord(BlockPos.getZ(blockPos)));
+ // b(a(BlockPosition.b(i)), a(BlockPosition.c(i)), a(BlockPosition.d(i)));
+ return (((long) (int) (blockPos >> 42) & 4194303L) << 42) | (((long) (int) ((blockPos << 52) >> 56) & 1048575L)) | (((long) (int) ((blockPos << 26) >> 42) & 4194303L) << 20); // Simplify to reduce instruction count
}
public static long getZeroNode(long pos) {
@@ -192,15 +198,18 @@ public class SectionPos extends Vec3i {
return asLong(blockToSectionCoord(pos.getX()), blockToSectionCoord(pos.getY()), blockToSectionCoord(pos.getZ()));
}
+ // Paper start
+ public static long blockPosAsSectionLong(int i, int j, int k) {
+ return (((long) (i >> 4) & 4194303L) << 42) | (((long) (j >> 4) & 1048575L)) | (((long) (k >> 4) & 4194303L) << 20);
+ }
+ // Paper end
+
public static long asLong(int x, int y, int z) {
- long l = 0L;
- l = l | ((long)x & 4194303L) << 42;
- l = l | ((long)y & 1048575L) << 0;
- return l | ((long)z & 4194303L) << 20;
+ return (((long) x & 4194303L) << 42) | (((long) y & 1048575L)) | (((long) z & 4194303L) << 20); // Paper - Simplify to reduce instruction count
}
public long asLong() {
- return asLong(this.x(), this.y(), this.z());
+ return (((long) getX() & 4194303L) << 42) | (((long) getY() & 1048575L)) | (((long) getZ() & 4194303L) << 20); // Paper - Simplify to reduce instruction count
}
@Override
@@ -213,16 +222,11 @@ public class SectionPos extends Vec3i {
}
public static Stream<SectionPos> cube(SectionPos center, int radius) {
- int i = center.x();
- int j = center.y();
- int k = center.z();
- return betweenClosedStream(i - radius, j - radius, k - radius, i + radius, j + radius, k + radius);
+ return betweenClosedStream(center.getX() - radius, center.getY() - radius, center.getZ() - radius, center.getX() + radius, center.getY() + radius, center.getZ() + radius); // Paper - simplify/inline
}
public static Stream<SectionPos> aroundChunk(ChunkPos center, int radius, int minY, int maxY) {
- int i = center.x;
- int j = center.z;
- return betweenClosedStream(i - radius, minY, j - radius, i + radius, maxY - 1, j + radius);
+ return betweenClosedStream(center.x - radius, 0, center.z - radius, center.x + radius, 15, center.z + radius); // Paper - simplify/inline
}
public static Stream<SectionPos> betweenClosedStream(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) {

View file

@ -1,121 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Tue, 9 Jun 2020 03:33:03 -0400
Subject: [PATCH] Add Plugin Tickets to API Chunk Methods
Like previous versions, plugins loading chunks kept them loaded until
they garbage collected to avoid constant spamming of chunk loads
This adds tickets to a few more places so that they can be unloaded.
Additionally, this drops their ticket level to BORDER so they wont be ticking
so they will just sit inactive instead.
Using .loadChunk to keep a chunk ticking was a horrible idea for upstream
when we have TWO methods that are able to do that already in the API.
Also reduce their collection count down to a maximum of 1 second. Barely
anyone knows what chunk-gc is in bukkit.yml as its less relevant now, and
since this wasn't spigot behavior, this is safe to mostly ignore (unless someone
wants it to collect even faster, they can restore that setting back to 1 instead of 20+)
Not adding it to .getType() though to keep behavior consistent with vanilla for performance reasons.
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index acae4ffc1e97ba54056b7b30679404de6ff54fca..cb08173bdfe52c8a0d5de70f0421cabaa476647a 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -369,7 +369,7 @@ public final class CraftServer implements Server {
this.ambientSpawn = this.configuration.getInt("spawn-limits.ambient");
console.autosavePeriod = this.configuration.getInt("ticks-per.autosave");
this.warningState = WarningState.value(this.configuration.getString("settings.deprecated-verbose"));
- TicketType.PLUGIN.timeout = this.configuration.getInt("chunk-gc.period-in-ticks");
+ TicketType.PLUGIN.timeout = Math.min(20, this.configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second
this.minimumAPI = this.configuration.getString("settings.minimum-api");
this.loadIcon();
}
@@ -860,7 +860,7 @@ public final class CraftServer implements Server {
this.waterUndergroundCreatureSpawn = this.configuration.getInt("spawn-limits.water-underground-creature");
this.ambientSpawn = this.configuration.getInt("spawn-limits.ambient");
this.warningState = WarningState.value(this.configuration.getString("settings.deprecated-verbose"));
- TicketType.PLUGIN.timeout = this.configuration.getInt("chunk-gc.period-in-ticks");
+ TicketType.PLUGIN.timeout = Math.min(20, configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second
this.minimumAPI = this.configuration.getString("settings.minimum-api");
this.printSaveWarning = false;
console.autosavePeriod = this.configuration.getInt("ticks-per.autosave");
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 01ac6e7e7b4b6c61d01684c77ecc2238afcaa8f1..20d956c9a4e3b598ffebbe481a190158566343d9 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -264,8 +264,21 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@Override
public Chunk getChunkAt(int x, int z) {
- return this.world.getChunkSource().getChunk(x, z, true).bukkitChunk;
+ // Paper start - add ticket to hold chunk for a little while longer if plugin accesses it
+ net.minecraft.world.level.chunk.LevelChunk chunk = world.getChunkSource().getChunkAtIfLoadedImmediately(x, z);
+ if (chunk == null) {
+ addTicket(x, z);
+ chunk = this.world.getChunkSource().getChunk(x, z, true);
+ }
+ return chunk.bukkitChunk;
+ // Paper end
+ }
+
+ // Paper start
+ private void addTicket(int x, int z) {
+ net.minecraft.server.MCUtil.MAIN_EXECUTOR.execute(() -> world.getChunkSource().addRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 0, Unit.INSTANCE)); // Paper
}
+ // Paper end
@Override
public Chunk getChunkAt(Block block) {
@@ -332,7 +345,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
public boolean unloadChunkRequest(int x, int z) {
org.spigotmc.AsyncCatcher.catchOp("chunk unload"); // Spigot
if (this.isChunkLoaded(x, z)) {
- this.world.getChunkSource().removeRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 1, Unit.INSTANCE);
+ this.world.getChunkSource().removeRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 0, Unit.INSTANCE); // Paper
}
return true;
@@ -409,9 +422,12 @@ public class CraftWorld extends CraftRegionAccessor implements World {
org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot
// Paper start - Optimize this method
ChunkPos chunkPos = new ChunkPos(x, z);
+ ChunkAccess immediate = world.getChunkSource().getChunkAtIfLoadedImmediately(x, z); // Paper
+ if (immediate != null) return true; // Paper
if (!generate) {
- ChunkAccess immediate = world.getChunkSource().getChunkAtImmediately(x, z);
+
+ //IChunkAccess immediate = world.getChunkProvider().getChunkAtImmediately(x, z); // Paper
if (immediate == null) {
immediate = world.getChunkSource().chunkMap.getUnloadingChunk(x, z);
}
@@ -419,7 +435,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
if (!(immediate instanceof ImposterProtoChunk) && !(immediate instanceof net.minecraft.world.level.chunk.LevelChunk)) {
return false; // not full status
}
- world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE);
+ world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 0, Unit.INSTANCE); // Paper
world.getChunk(x, z); // make sure we're at ticket level 32 or lower
return true;
}
@@ -445,7 +461,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
// we do this so we do not re-read the chunk data on disk
}
- world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE);
+ world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 0, Unit.INSTANCE); // Paper
world.getChunkSource().getChunk(x, z, ChunkStatus.FULL, true);
return true;
// Paper end
@@ -1914,6 +1930,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
return this.world.getChunkSource().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> {
net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk) either.left().orElse(null);
+ if (chunk != null) addTicket(x, z); // Paper
return java.util.concurrent.CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk());
}, net.minecraft.server.MinecraftServer.getServer());
}

View file

@ -1,297 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <spottedleaf@spottedleaf.dev>
Date: Mon, 27 Apr 2020 04:05:38 -0700
Subject: [PATCH] Stop copy-on-write operations for updating light data
Causes huge memory allocations + gc issues
diff --git a/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java
index 573cdb0897978eef8f5fc906ed4928293f4b2ab9..314b46f0becd088d26956b45981217b128d539cb 100644
--- a/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java
+++ b/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java
@@ -9,7 +9,7 @@ import net.minecraft.world.level.chunk.LightChunkGetter;
public class BlockLightSectionStorage extends LayerLightSectionStorage<BlockLightSectionStorage.BlockDataLayerStorageMap> {
protected BlockLightSectionStorage(LightChunkGetter chunkProvider) {
- super(LightLayer.BLOCK, chunkProvider, new BlockLightSectionStorage.BlockDataLayerStorageMap(new Long2ObjectOpenHashMap<>()));
+ super(LightLayer.BLOCK, chunkProvider, new BlockLightSectionStorage.BlockDataLayerStorageMap(new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<>(), false)); // Paper - avoid copying light data
}
@Override
@@ -20,13 +20,13 @@ public class BlockLightSectionStorage extends LayerLightSectionStorage<BlockLigh
}
protected static final class BlockDataLayerStorageMap extends DataLayerStorageMap<BlockLightSectionStorage.BlockDataLayerStorageMap> {
- public BlockDataLayerStorageMap(Long2ObjectOpenHashMap<DataLayer> arrays) {
- super(arrays);
+ public BlockDataLayerStorageMap(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<DataLayer> long2objectopenhashmap, boolean isVisible) { // Paper - avoid copying light data
+ super(long2objectopenhashmap, isVisible); // Paper - avoid copying light data
}
@Override
public BlockLightSectionStorage.BlockDataLayerStorageMap copy() {
- return new BlockLightSectionStorage.BlockDataLayerStorageMap(this.map.clone());
+ return new BlockDataLayerStorageMap(this.data, true); // Paper - avoid copying light data
}
}
}
diff --git a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java
index 67ff66e232592203cf8dad605ad01eabc4dded89..f357a3473682c2d37a20fb862522c67b9979402a 100644
--- a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java
+++ b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java
@@ -9,10 +9,23 @@ public abstract class DataLayerStorageMap<M extends DataLayerStorageMap<M>> {
private final long[] lastSectionKeys = new long[2];
private final DataLayer[] lastSections = new DataLayer[2];
private boolean cacheEnabled;
- protected final Long2ObjectOpenHashMap<DataLayer> map;
+ protected final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<DataLayer> data; // Paper - avoid copying light data
+ protected final boolean isVisible; // Paper - avoid copying light data
+ java.util.function.Function<Long, DataLayer> lookup; // Paper - faster branchless lookup
- protected DataLayerStorageMap(Long2ObjectOpenHashMap<DataLayer> arrays) {
- this.map = arrays;
+ // Paper start - avoid copying light data
+ protected DataLayerStorageMap(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<DataLayer> data, boolean isVisible) {
+ if (isVisible) {
+ data.performUpdatesLockMap();
+ }
+ this.data = data;
+ this.isVisible = isVisible;
+ if (isVisible) {
+ lookup = data::getVisibleAsync;
+ } else {
+ lookup = data::getUpdating;
+ }
+ // Paper end - avoid copying light data
this.clearCache();
this.cacheEnabled = true;
}
@@ -20,16 +33,17 @@ public abstract class DataLayerStorageMap<M extends DataLayerStorageMap<M>> {
public abstract M copy();
public void copyDataLayer(long pos) {
- this.map.put(pos, this.map.get(pos).copy());
+ if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data
+ this.data.queueUpdate(pos, ((DataLayer) this.data.getUpdating(pos)).copy()); // Paper - avoid copying light data
this.clearCache();
}
public boolean hasLayer(long chunkPos) {
- return this.map.containsKey(chunkPos);
+ return lookup.apply(chunkPos) != null; // Paper - avoid copying light data
}
@Nullable
- public DataLayer getLayer(long chunkPos) {
+ public final DataLayer getLayer(long chunkPos) { // Paper - final
if (this.cacheEnabled) {
for(int i = 0; i < 2; ++i) {
if (chunkPos == this.lastSectionKeys[i]) {
@@ -38,7 +52,7 @@ public abstract class DataLayerStorageMap<M extends DataLayerStorageMap<M>> {
}
}
- DataLayer dataLayer = this.map.get(chunkPos);
+ DataLayer dataLayer = lookup.apply(chunkPos); // Paper - avoid copying light data
if (dataLayer == null) {
return null;
} else {
@@ -58,11 +72,13 @@ public abstract class DataLayerStorageMap<M extends DataLayerStorageMap<M>> {
@Nullable
public DataLayer removeLayer(long chunkPos) {
- return this.map.remove(chunkPos);
+ if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data
+ return (DataLayer) this.data.queueRemove(chunkPos); // Paper - avoid copying light data
}
public void setLayer(long pos, DataLayer data) {
- this.map.put(pos, data);
+ if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data
+ this.data.queueUpdate(pos, data); // Paper - avoid copying light data
}
public void clearCache() {
diff --git a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java
index ee32aba07aad4a3f101a6a57f7aa6c07f74dd0c3..cc9eb8273d5157fb649d84a3ec589b0b923b5bc9 100644
--- a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java
+++ b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java
@@ -28,7 +28,7 @@ public abstract class LayerLightSectionStorage<M extends DataLayerStorageMap<M>>
protected final LongSet dataSectionSet = new LongOpenHashSet();
protected final LongSet toMarkNoData = new LongOpenHashSet();
protected final LongSet toMarkData = new LongOpenHashSet();
- protected volatile M visibleSectionData;
+ protected volatile M e_visible; protected final Object visibleUpdateLock = new Object(); // Paper - diff on change, should be "visible" - force compile fail on usage change
protected final M updatingSectionData;
protected final LongSet changedSections = new LongOpenHashSet();
protected final LongSet sectionsAffectedByLightUpdates = new LongOpenHashSet();
@@ -43,8 +43,8 @@ public abstract class LayerLightSectionStorage<M extends DataLayerStorageMap<M>>
this.layer = lightType;
this.chunkSource = chunkProvider;
this.updatingSectionData = lightData;
- this.visibleSectionData = lightData.copy();
- this.visibleSectionData.disableCache();
+ this.e_visible = lightData.copy(); // Paper - avoid copying light dat
+ this.e_visible.disableCache(); // Paper - avoid copying light dat
}
protected boolean storingLightForSection(long sectionPos) {
@@ -53,7 +53,15 @@ public abstract class LayerLightSectionStorage<M extends DataLayerStorageMap<M>>
@Nullable
protected DataLayer getDataLayer(long sectionPos, boolean cached) {
- return this.getDataLayer((M)(cached ? this.updatingSectionData : this.visibleSectionData), sectionPos);
+ // Paper start - avoid copying light data
+ if (cached) {
+ return this.getDataLayer(this.updatingSectionData, sectionPos);
+ } else {
+ synchronized (this.visibleUpdateLock) {
+ return this.getDataLayer(this.e_visible, sectionPos);
+ }
+ }
+ // Paper end - avoid copying light data
}
@Nullable
@@ -346,9 +354,11 @@ public abstract class LayerLightSectionStorage<M extends DataLayerStorageMap<M>>
protected void swapSectionMap() {
if (!this.changedSections.isEmpty()) {
+ synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data
M dataLayerStorageMap = this.updatingSectionData.copy();
dataLayerStorageMap.disableCache();
- this.visibleSectionData = dataLayerStorageMap;
+ this.e_visible = dataLayerStorageMap; // Paper - avoid copying light data
+ } // Paper - avoid copying light data
this.changedSections.clear();
}
diff --git a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java
index c436ba1f09f6034679dc3dc7af28c00776e165f2..24030bcb3303d0419c7859ded7613608c5f82308 100644
--- a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java
+++ b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java
@@ -21,7 +21,7 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage<SkyLightSec
private volatile boolean hasSourceInconsistencies;
protected SkyLightSectionStorage(LightChunkGetter chunkProvider) {
- super(LightLayer.SKY, chunkProvider, new SkyLightSectionStorage.SkyDataLayerStorageMap(new Long2ObjectOpenHashMap<>(), new Long2IntOpenHashMap(), Integer.MAX_VALUE));
+ super(LightLayer.SKY, chunkProvider, new SkyLightSectionStorage.SkyDataLayerStorageMap(new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<>(), new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int(), Integer.MAX_VALUE, false)); // Paper - avoid copying light data
}
@Override
@@ -32,8 +32,9 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage<SkyLightSec
protected int getLightValue(long l, boolean bl) {
long m = SectionPos.blockToSection(l);
int i = SectionPos.y(m);
- SkyLightSectionStorage.SkyDataLayerStorageMap skyDataLayerStorageMap = bl ? this.updatingSectionData : this.visibleSectionData;
- int j = skyDataLayerStorageMap.topSections.get(SectionPos.getZeroNode(m));
+ synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data
+ SkyLightSectionStorage.SkyDataLayerStorageMap skyDataLayerStorageMap = (SkyLightSectionStorage.SkyDataLayerStorageMap) this.e_visible; // Paper - avoid copying light data - must be after lock acquire
+ int j = skyDataLayerStorageMap.otherData.getVisibleAsync(SectionPos.getZeroNode(m)); // Paper - avoid copying light data
if (j != skyDataLayerStorageMap.currentLowestY && i < j) {
DataLayer dataLayer = this.getDataLayer(skyDataLayerStorageMap, m);
if (dataLayer == null) {
@@ -52,6 +53,7 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage<SkyLightSec
} else {
return bl && !this.lightOnInSection(m) ? 0 : 15;
}
+ } // Paper - avoid copying light data
}
@Override
@@ -59,13 +61,13 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage<SkyLightSec
int i = SectionPos.y(sectionPos);
if ((this.updatingSectionData).currentLowestY > i) {
(this.updatingSectionData).currentLowestY = i;
- (this.updatingSectionData).topSections.defaultReturnValue((this.updatingSectionData).currentLowestY);
+ (this.updatingSectionData).otherData.queueDefaultReturnValue((this.updatingSectionData).currentLowestY); // Paper - avoid copying light data
}
long l = SectionPos.getZeroNode(sectionPos);
- int j = (this.updatingSectionData).topSections.get(l);
+ int j = (this.updatingSectionData).otherData.getUpdating(l); // Paper - avoid copying light data
if (j < i + 1) {
- (this.updatingSectionData).topSections.put(l, i + 1);
+ (this.updatingSectionData).otherData.queueUpdate(l, i + 1); // Paper - avoid copying light data
if (this.columnsWithSkySources.contains(l)) {
this.queueAddSource(sectionPos);
if (j > (this.updatingSectionData).currentLowestY) {
@@ -102,19 +104,19 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage<SkyLightSec
}
int i = SectionPos.y(sectionPos);
- if ((this.updatingSectionData).topSections.get(l) == i + 1) {
+ if ((this.updatingSectionData).otherData.getUpdating(l) == i + 1) { // Paper - avoid copying light data
long m;
for(m = sectionPos; !this.storingLightForSection(m) && this.hasSectionsBelow(i); m = SectionPos.offset(m, Direction.DOWN)) {
--i;
}
if (this.storingLightForSection(m)) {
- (this.updatingSectionData).topSections.put(l, i + 1);
+ (this.updatingSectionData).otherData.queueUpdate(l, i + 1); // Paper - avoid copying light data
if (bl) {
this.queueAddSource(m);
}
} else {
- (this.updatingSectionData).topSections.remove(l);
+ (this.updatingSectionData).otherData.queueRemove(l); // Paper - avoid copying light data
}
}
@@ -128,7 +130,7 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage<SkyLightSec
protected void enableLightSources(long columnPos, boolean enabled) {
this.runAllUpdates();
if (enabled && this.columnsWithSkySources.add(columnPos)) {
- int i = (this.updatingSectionData).topSections.get(columnPos);
+ int i = (this.updatingSectionData).otherData.getUpdating(columnPos); // Paper - avoid copying light data
if (i != (this.updatingSectionData).currentLowestY) {
long l = SectionPos.asLong(SectionPos.x(columnPos), i - 1, SectionPos.z(columnPos));
this.queueAddSource(l);
@@ -152,7 +154,7 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage<SkyLightSec
return dataLayer;
} else {
long l = SectionPos.offset(sectionPos, Direction.UP);
- int i = (this.updatingSectionData).topSections.get(SectionPos.getZeroNode(sectionPos));
+ int i = (this.updatingSectionData).otherData.getUpdating(SectionPos.getZeroNode(sectionPos)); // Paper - avoid copying light data
if (i != (this.updatingSectionData).currentLowestY && SectionPos.y(l) < i) {
DataLayer dataLayer2;
while((dataLayer2 = this.getDataLayer(l, true)) == null) {
@@ -275,7 +277,7 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage<SkyLightSec
protected boolean isAboveData(long sectionPos) {
long l = SectionPos.getZeroNode(sectionPos);
- int i = (this.updatingSectionData).topSections.get(l);
+ int i = (this.updatingSectionData).otherData.getUpdating(l); // Paper - avoid copying light data
return i == (this.updatingSectionData).currentLowestY || SectionPos.y(sectionPos) >= i;
}
@@ -286,18 +288,21 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage<SkyLightSec
protected static final class SkyDataLayerStorageMap extends DataLayerStorageMap<SkyLightSectionStorage.SkyDataLayerStorageMap> {
int currentLowestY;
- final Long2IntOpenHashMap topSections;
-
- public SkyDataLayerStorageMap(Long2ObjectOpenHashMap<DataLayer> arrays, Long2IntOpenHashMap columnToTopSection, int minSectionY) {
- super(arrays);
- this.topSections = columnToTopSection;
- columnToTopSection.defaultReturnValue(minSectionY);
+ private final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int otherData; // Paper - avoid copying light data
+
+ // Paper start - avoid copying light data
+ public SkyDataLayerStorageMap(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<DataLayer> arrays, com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int columnToTopSection, int minSectionY, boolean isVisible) {
+ super(arrays, isVisible);
+ this.otherData = columnToTopSection;
+ otherData.queueDefaultReturnValue(minSectionY);
+ // Paper end
this.currentLowestY = minSectionY;
}
@Override
public SkyLightSectionStorage.SkyDataLayerStorageMap copy() {
- return new SkyLightSectionStorage.SkyDataLayerStorageMap(this.map.clone(), this.topSections.clone(), this.currentLowestY);
+ this.otherData.performUpdatesLockMap(); // Paper - avoid copying light data
+ return new SkyLightSectionStorage.SkyDataLayerStorageMap(this.data, this.otherData, this.currentLowestY, true); // Paper - avoid copying light data
}
}
}

View file

@ -1,100 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Mon, 29 Jun 2020 03:26:17 -0400
Subject: [PATCH] Support old UUID format for NBT
We have stored UUID in plenty of places that did not get DFU'd
So just look for old format and load it if it exists.
diff --git a/src/main/java/net/minecraft/nbt/CompoundTag.java b/src/main/java/net/minecraft/nbt/CompoundTag.java
index 5456387ade8932fb0d9804abe0fd66f1c565e1ae..7199be3b9c00c66f452e92ad35795017112f1658 100644
--- a/src/main/java/net/minecraft/nbt/CompoundTag.java
+++ b/src/main/java/net/minecraft/nbt/CompoundTag.java
@@ -120,6 +120,12 @@ public class CompoundTag implements Tag {
}
public void putUUID(String key, UUID value) {
+ // Paper start - support old format
+ if (this.contains(key + "Most", 99) && this.contains(key + "Least", 99)) {
+ this.tags.remove(key + "Most");
+ this.tags.remove(key + "Least");
+ }
+ // Paper end
this.tags.put(key, NbtUtils.createUUID(value));
}
@@ -128,10 +134,20 @@ public class CompoundTag implements Tag {
* You must use {@link #hasUUID(String)} before or else it <b>will</b> throw an NPE.
*/
public UUID getUUID(String key) {
+ // Paper start - support old format
+ if (!contains(key, 11) && this.contains(key + "Most", 99) && this.contains(key + "Least", 99)) {
+ return new UUID(this.getLong(key + "Most"), this.getLong(key + "Least"));
+ }
+ // Paper end
return NbtUtils.loadUUID(this.get(key));
}
public boolean hasUUID(String key) {
+ // Paper start - support old format
+ if (this.contains(key + "Most", 99) && this.contains(key + "Least", 99)) {
+ return true;
+ }
+ // Paper end
Tag tag = this.get(key);
return tag != null && tag.getType() == IntArrayTag.TYPE && ((IntArrayTag)tag).getAsIntArray().length == 4;
}
diff --git a/src/main/java/net/minecraft/nbt/NbtUtils.java b/src/main/java/net/minecraft/nbt/NbtUtils.java
index 57c9575a9714acb95d9dced672955a96d71dfd1e..06fe97e05608fc21f90c9884d745d910beb6883d 100644
--- a/src/main/java/net/minecraft/nbt/NbtUtils.java
+++ b/src/main/java/net/minecraft/nbt/NbtUtils.java
@@ -40,14 +40,14 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public final class NbtUtils {
- private static final Comparator<ListTag> YXZ_LISTTAG_INT_COMPARATOR = Comparator.comparingInt((listTag) -> {
+ private static final Comparator<ListTag> YXZ_LISTTAG_INT_COMPARATOR = Comparator.<ListTag>comparingInt((listTag) -> { // Paper - decompile fix
return listTag.getInt(1);
}).thenComparingInt((listTag) -> {
return listTag.getInt(0);
}).thenComparingInt((listTag) -> {
return listTag.getInt(2);
});
- private static final Comparator<ListTag> YXZ_LISTTAG_DOUBLE_COMPARATOR = Comparator.comparingDouble((listTag) -> {
+ private static final Comparator<ListTag> YXZ_LISTTAG_DOUBLE_COMPARATOR = Comparator.<ListTag>comparingDouble((listTag) -> { // Paper - decompile fix
return listTag.getDouble(1);
}).thenComparingDouble((listTag) -> {
return listTag.getDouble(0);
@@ -76,6 +76,11 @@ public final class NbtUtils {
string = compound.getString("Name");
}
+ // Paper start - support string UUID's
+ if (compound.contains("Id", 8)) {
+ uUID = UUID.fromString(compound.getString("Id"));
+ }
+ // Paper end
if (compound.hasUUID("Id")) {
uUID = compound.getUUID("Id");
}
@@ -495,7 +500,7 @@ public final class NbtUtils {
}
public static CompoundTag update(DataFixer fixer, DataFixTypes fixTypes, CompoundTag compound, int oldVersion, int targetVersion) {
- return fixer.update(fixTypes.getType(), new Dynamic<>(NbtOps.INSTANCE, compound), oldVersion, targetVersion).getValue();
+ return (CompoundTag) fixer.update(fixTypes.getType(), new com.mojang.serialization.Dynamic<>(NbtOps.INSTANCE, compound), oldVersion, targetVersion).getValue(); // Paper - decompile fix
}
public static Component toPrettyComponent(Tag element) {
@@ -620,8 +625,8 @@ public final class NbtUtils {
CompoundTag compoundTag2 = new CompoundTag();
if (i + 2 <= string.length()) {
String string3 = string.substring(i + 1, string.indexOf(125, i));
- COMMA_SPLITTER.split(string3).forEach((string2) -> {
- List<String> list = COLON_SPLITTER.splitToList(string2);
+ COMMA_SPLITTER.split(string3).forEach(it -> { // Paper - decompile fix
+ List<String> list = COLON_SPLITTER.splitToList(it); // Paper - decompile fix
if (list.size() == 2) {
compoundTag2.putString(list.get(0), list.get(1));
} else {

View file

@ -1,47 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Wed, 1 Jul 2020 03:12:06 -0400
Subject: [PATCH] Clean up duplicated GameProfile Properties
We had a bug where we accidently cloned properties resulting in skulls
growing to large sizes and preventing login.
This now automatically cleans up the extra properties.
diff --git a/src/main/java/net/minecraft/nbt/NbtUtils.java b/src/main/java/net/minecraft/nbt/NbtUtils.java
index 06fe97e05608fc21f90c9884d745d910beb6883d..dca8853944832e8fc5a291aa6b46d84b24181ea7 100644
--- a/src/main/java/net/minecraft/nbt/NbtUtils.java
+++ b/src/main/java/net/minecraft/nbt/NbtUtils.java
@@ -93,7 +93,8 @@ public final class NbtUtils {
for(String string2 : compoundTag.getAllKeys()) {
ListTag listTag = compoundTag.getList(string2, 10);
- for(int i = 0; i < listTag.size(); ++i) {
+ if (listTag.size() == 0) continue; // Paper - remove duplicate properties
+ for (int i = listTag.size() - 1; i < listTag.size(); ++i) { // Paper - remove duplicate properties
CompoundTag compoundTag2 = listTag.getCompound(i);
String string3 = compoundTag2.getString("Value");
if (compoundTag2.contains("Signature", 8)) {
diff --git a/src/main/java/net/minecraft/world/item/PlayerHeadItem.java b/src/main/java/net/minecraft/world/item/PlayerHeadItem.java
index 7fb2cc8d49a2d8f256f625cb99b66ef8efc3fc0e..f9980110a4614bb0206dce3dc796d9459069b750 100644
--- a/src/main/java/net/minecraft/world/item/PlayerHeadItem.java
+++ b/src/main/java/net/minecraft/world/item/PlayerHeadItem.java
@@ -53,6 +53,18 @@ public class PlayerHeadItem extends StandingAndWallBlockItem {
});
// CraftBukkit start
} else {
+ // Paper start - clean up old duplicated properties
+ CompoundTag properties = nbt.getCompound("SkullOwner").getCompound("Properties");
+ for (String key : properties.getAllKeys()) {
+ net.minecraft.nbt.ListTag values = properties.getList(key, 10);
+ if (values.size() > 1) {
+ net.minecraft.nbt.Tag texture = values.get(values.size() - 1);
+ values = new net.minecraft.nbt.ListTag();
+ values.add(texture);
+ properties.put(key, values);
+ }
+ }
+ // Paper end
net.minecraft.nbt.ListTag textures = nbt.getCompound("SkullOwner").getCompound("Properties").getList("textures", 10); // Safe due to method contracts
for (int i = 0; i < textures.size(); i++) {
if (textures.get(i) instanceof CompoundTag && !((CompoundTag) textures.get(i)).contains("Signature", 8) && ((CompoundTag) textures.get(i)).getString("Value").trim().isEmpty()) {

View file

@ -1,44 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Wed, 1 Jul 2020 04:50:22 -0400
Subject: [PATCH] Convert legacy attributes in Item Meta
diff --git a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java
index 0520c45197629cbdc2777d9ae11eef572e793160..46c313d581b9af6aa0a48f97ae3cc800a88535f2 100644
--- a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java
+++ b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java
@@ -11,6 +11,20 @@ import org.bukkit.craftbukkit.util.CraftNamespacedKey;
public class CraftAttributeMap implements Attributable {
private final AttributeMap handle;
+ // Paper start - convert legacy attributes
+ private static final com.google.common.collect.ImmutableMap<String, String> legacyNMS = com.google.common.collect.ImmutableMap.<String, String>builder().put("generic.maxHealth", "generic.max_health").put("Max Health", "generic.max_health").put("zombie.spawnReinforcements", "zombie.spawn_reinforcements").put("Spawn Reinforcements Chance", "zombie.spawn_reinforcements").put("horse.jumpStrength", "horse.jump_strength").put("Jump Strength", "horse.jump_strength").put("generic.followRange", "generic.follow_range").put("Follow Range", "generic.follow_range").put("generic.knockbackResistance", "generic.knockback_resistance").put("Knockback Resistance", "generic.knockback_resistance").put("generic.movementSpeed", "generic.movement_speed").put("Movement Speed", "generic.movement_speed").put("generic.flyingSpeed", "generic.flying_speed").put("Flying Speed", "generic.flying_speed").put("generic.attackDamage", "generic.attack_damage").put("generic.attackKnockback", "generic.attack_knockback").put("generic.attackSpeed", "generic.attack_speed").put("generic.armorToughness", "generic.armor_toughness").build();
+
+ public static String convertIfNeeded(String nms) {
+ if (nms == null) {
+ return null;
+ }
+ nms = legacyNMS.getOrDefault(nms, nms);
+ if (!nms.toLowerCase().equals(nms) || nms.indexOf(' ') != -1) {
+ return null;
+ }
+ return nms;
+ }
+ // Paper end
public CraftAttributeMap(AttributeMap handle) {
this.handle = handle;
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
index 0aa7854119ab876f0e46bb7667282d79d2a57e3d..3a125e7018b57aa6a802e99662fa784493fec5fc 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
@@ -480,7 +480,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
AttributeModifier attribMod = CraftAttributeInstance.convert(nmsModifier);
- String attributeName = entry.getString(ATTRIBUTES_IDENTIFIER.NBT);
+ String attributeName = CraftAttributeMap.convertIfNeeded(entry.getString(ATTRIBUTES_IDENTIFIER.NBT)); // Paper
if (attributeName == null || attributeName.isEmpty()) {
continue;
}

View file

@ -1,106 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: JRoy <joshroy126@gmail.com>
Date: Mon, 29 Jun 2020 17:03:06 -0400
Subject: [PATCH] Remove some streams from structures
This showed up a lot in the spark profiler, should have a low-medium performance improvement.
diff --git a/src/main/java/net/minecraft/world/level/StructureFeatureManager.java b/src/main/java/net/minecraft/world/level/StructureFeatureManager.java
index 21f67cf20dede30a056a7807a0e7338e858da142..9a8e44fb3b1cffec3f70c9812c80175bd07f10e2 100644
--- a/src/main/java/net/minecraft/world/level/StructureFeatureManager.java
+++ b/src/main/java/net/minecraft/world/level/StructureFeatureManager.java
@@ -45,6 +45,20 @@ public class StructureFeatureManager {
});
}
+ // Paper start - remove structure streams - based on method above
+ public java.util.List<StructureStart<?>> streamlessStartsForFeature(SectionPos sectionPosition, StructureFeature<?> structureGenerator) {
+ java.util.List<StructureStart<?>> list = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>();
+ for (Long curLong : this.level.getChunk(sectionPosition.x(), sectionPosition.z(), ChunkStatus.STRUCTURE_REFERENCES).getReferencesForFeature(structureGenerator)) {
+ SectionPos sectionPosition1 = SectionPos.of(new ChunkPos(curLong), 0);
+ StructureStart<?> structurestart = getStartForFeature(sectionPosition1, structureGenerator, this.level.getChunk(sectionPosition1.x(), sectionPosition1.z(), ChunkStatus.STRUCTURE_STARTS));
+ if (structurestart != null && structurestart.isValid()) {
+ list.add(structurestart);
+ }
+ }
+ return list;
+ }
+ // Paper end
+
@Nullable
public StructureStart<?> getStartForFeature(SectionPos pos, StructureFeature<?> feature, FeatureAccess holder) {
return holder.getStartForFeature(feature);
@@ -63,11 +77,20 @@ public class StructureFeatureManager {
}
public StructureStart<?> getStructureAt(BlockPos pos, boolean matchChildren, StructureFeature<?> feature) {
- return (StructureStart) DataFixUtils.orElse(this.startsForFeature(SectionPos.of(pos), feature).filter((structurestart) -> {
- return matchChildren ? structurestart.getPieces().stream().anyMatch((structurepiece) -> {
- return structurepiece.getBoundingBox().isInside((Vec3i) pos);
- }) : structurestart.getBoundingBox().isInside((Vec3i) pos);
- }).findFirst(), StructureStart.INVALID_START);
+ // Paper start - remove structure streams
+ for (StructureStart<?> structureStart : streamlessStartsForFeature(SectionPos.of(pos), feature)) {
+ if (matchChildren) {
+ for (net.minecraft.world.level.levelgen.structure.StructurePiece piece : structureStart.getPieces()) {
+ if (piece.getBoundingBox().isInside(pos)) {
+ return structureStart;
+ }
+ }
+ } else if (structureStart.getBoundingBox().isInside(pos)) {
+ return structureStart;
+ }
+ }
+ return StructureStart.INVALID_START;
+ // Paper end
}
// Spigot start
diff --git a/src/main/java/net/minecraft/world/level/biome/Biome.java b/src/main/java/net/minecraft/world/level/biome/Biome.java
index 3f3b4e4ea8231fdcc799bd9de3e20747a5634603..a7a7e6cd87270e64a92448f03f8b0b0c7e375ec7 100644
--- a/src/main/java/net/minecraft/world/level/biome/Biome.java
+++ b/src/main/java/net/minecraft/world/level/biome/Biome.java
@@ -44,6 +44,7 @@ import net.minecraft.world.level.levelgen.WorldgenRandom;
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
import net.minecraft.world.level.levelgen.feature.StructureFeature;
import net.minecraft.world.level.levelgen.structure.BoundingBox;
+import net.minecraft.world.level.levelgen.structure.StructureStart;
import net.minecraft.world.level.levelgen.surfacebuilders.ConfiguredSurfaceBuilder;
import net.minecraft.world.level.levelgen.synth.PerlinSimplexNoise;
import net.minecraft.world.level.material.FluidState;
@@ -241,9 +242,11 @@ public final class Biome {
int p = region.getMinBuildHeight() + 1;
int q = region.getMaxBuildHeight() - 1;
region.setCurrentlyGenerating(supplier);
- structureAccessor.startsForFeature(SectionPos.of(origin), structureFeature).forEach((structureStart) -> {
+ // Paper start - remove structure streams
+ for (StructureStart<?> structureStart : structureAccessor.streamlessStartsForFeature(SectionPos.of(origin), structureFeature)) {
structureStart.placeInChunk(region, structureAccessor, chunkGenerator, random, new BoundingBox(n, p, o, n + 15, q, o + 15), new ChunkPos(l, m));
- });
+ }
+ // Paper end
} catch (Exception var24) {
CrashReport crashReport = CrashReport.forThrowable(var24, "Feature placement");
crashReport.addCategory("Feature").setDetail("Description", supplier::get);
diff --git a/src/main/java/net/minecraft/world/level/levelgen/Beardifier.java b/src/main/java/net/minecraft/world/level/levelgen/Beardifier.java
index ed3bfe13d0e3835ce0dbe3ae5af8cd22a7ea25e6..c52d1a23a0f0bdde062f73a435bc6b9cef51c437 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/Beardifier.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/Beardifier.java
@@ -44,7 +44,7 @@ public class Beardifier {
this.rigids = new ObjectArrayList<>(10);
for(StructureFeature<?> structureFeature : StructureFeature.NOISE_AFFECTING_FEATURES) {
- accessor.startsForFeature(SectionPos.bottomOf(chunk), structureFeature).forEach((start) -> {
+ for (net.minecraft.world.level.levelgen.structure.StructureStart<?> start : accessor.streamlessStartsForFeature(SectionPos.of(chunkPos, 0), structureFeature)) { // Paper - remove structure streams
for(StructurePiece structurePiece : start.getPieces()) {
if (structurePiece.isCloseToChunk(chunkPos, 12)) {
if (structurePiece instanceof PoolElementStructurePiece) {
@@ -67,7 +67,7 @@ public class Beardifier {
}
}
- });
+ } // Paper - remove structure streams
}
this.pieceIterator = this.rigids.iterator();

View file

@ -1,83 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: JRoy <joshroy126@gmail.com>
Date: Wed, 1 Jul 2020 18:01:49 -0400
Subject: [PATCH] Remove streams from classes related villager gossip
diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java
index 01df536b3b61281828ca2be03ac1bbb6a1096423..2d124ff784b943f5a9d164ee7cdc001465502ce4 100644
--- a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java
+++ b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java
@@ -8,6 +8,7 @@ import com.mojang.serialization.Dynamic;
import com.mojang.serialization.DynamicOps;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
+import it.unimi.dsi.fastutil.objects.ObjectArrayList; // Paper
import it.unimi.dsi.fastutil.objects.ObjectIterator;
import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry;
import java.util.Arrays;
@@ -60,8 +61,21 @@ public class GossipContainer {
});
}
+ // Paper start - Remove streams from reputation
+ private List<GossipContainer.GossipEntry> decompress() {
+ List<GossipContainer.GossipEntry> list = new ObjectArrayList<>();
+ for (Map.Entry<UUID, GossipContainer.EntityGossips> entry : getReputations().entrySet()) {
+ for (GossipContainer.GossipEntry cur : entry.getValue().decompress(entry.getKey())) {
+ if (cur.weightedValue() != 0)
+ list.add(cur);
+ }
+ }
+ return list;
+ }
+ // Paper end
+
private Collection<GossipContainer.GossipEntry> selectGossipsForTransfer(Random random, int count) {
- List<GossipContainer.GossipEntry> list = this.unpack().collect(Collectors.toList());
+ List<GossipContainer.GossipEntry> list = decompress(); // Paper - Remove streams from reputation
if (list.isEmpty()) {
return Collections.emptyList();
} else {
@@ -154,9 +168,9 @@ public class GossipContainer {
}
- public <T> Dynamic<T> store(DynamicOps<T> dynamicOps) {
- return new Dynamic<>(dynamicOps, dynamicOps.createList(this.unpack().map((gossipEntry) -> {
- return gossipEntry.store(dynamicOps);
+ public <T> Dynamic<T> store(DynamicOps<T> dynamicops) {
+ return new Dynamic(dynamicops, dynamicops.createList(this.decompress().stream().map((reputation_b) -> {
+ return reputation_b.store(dynamicops);
}).map(Dynamic::getValue)));
}
@@ -181,11 +195,23 @@ public class GossipContainer {
final Object2IntMap<GossipType> entries = new Object2IntOpenHashMap<>();
public int weightedValue(Predicate<GossipType> gossipTypeFilter) {
- return this.entries.object2IntEntrySet().stream().filter((entry) -> {
- return gossipTypeFilter.test(entry.getKey());
- }).mapToInt((entry) -> {
- return entry.getIntValue() * (entry.getKey()).weight;
- }).sum();
+ // Paper start - Remove streams from reputation
+ int weight = 0;
+ for (Object2IntMap.Entry<GossipType> entry : entries.object2IntEntrySet()) {
+ if (gossipTypeFilter.test(entry.getKey())) {
+ weight += entry.getIntValue() * entry.getKey().weight;
+ }
+ }
+ return weight;
+ }
+
+ public List<GossipContainer.GossipEntry> decompress(UUID uuid) {
+ List<GossipContainer.GossipEntry> list = new ObjectArrayList<>();
+ for (Object2IntMap.Entry<GossipType> entry : entries.object2IntEntrySet()) {
+ list.add(new GossipContainer.GossipEntry(uuid, entry.getKey(), entry.getIntValue()));
+ }
+ return list;
+ // Paper - end
}
public Stream<GossipContainer.GossipEntry> unpack(UUID target) {

View file

@ -1,321 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Wed, 6 May 2020 23:30:30 -0400
Subject: [PATCH] Optimize NibbleArray to use pooled buffers
Massively reduces memory allocation of 2048 byte buffers by using
an object pool for these.
Uses lots of advanced new capabilities of the Paper codebase :)
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacket.java
index 24d5a44cb81ec5f10bfcce002a193f4566de88fc..d8be2ad889f46491e50404916fb4ae0de5f42098 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacket.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacket.java
@@ -2,11 +2,14 @@ package net.minecraft.network.protocol.game;
import com.google.common.collect.Lists;
import java.util.BitSet;
+import io.netty.channel.ChannelFuture; // Paper
import java.util.List;
import javax.annotation.Nullable;
import net.minecraft.core.SectionPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.protocol.Packet;
+import net.minecraft.server.MCUtil;
+import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.LightLayer;
import net.minecraft.world.level.chunk.DataLayer;
@@ -22,6 +25,35 @@ public class ClientboundLightUpdatePacket implements Packet<ClientGamePacketList
private final List<byte[]> skyUpdates;
private final List<byte[]> blockUpdates;
private final boolean trustEdges;
+ // Paper start
+ java.lang.Runnable cleaner1;
+ java.lang.Runnable cleaner2;
+ java.util.concurrent.atomic.AtomicInteger remainingSends = new java.util.concurrent.atomic.AtomicInteger(0);
+
+ @Override
+ public void onPacketDispatch(ServerPlayer player) {
+ remainingSends.incrementAndGet();
+ }
+
+ @Override
+ public void onPacketDispatchFinish(ServerPlayer player, ChannelFuture future) {
+ if (remainingSends.decrementAndGet() <= 0) {
+ // incase of any race conditions, schedule this delayed
+ MCUtil.scheduleTask(5, () -> {
+ if (remainingSends.get() == 0) {
+ cleaner1.run();
+ cleaner2.run();
+ }
+ }, "Light Packet Release");
+ }
+ }
+
+ @Override
+ public boolean hasFinishListener() {
+ return true;
+ }
+
+ // Paper end
public ClientboundLightUpdatePacket(ChunkPos chunkPos, LevelLightEngine lightProvider, @Nullable BitSet bitSet, @Nullable BitSet bitSet2, boolean nonEdge) {
this.x = chunkPos.x;
@@ -31,8 +63,8 @@ public class ClientboundLightUpdatePacket implements Packet<ClientGamePacketList
this.blockYMask = new BitSet();
this.emptySkyYMask = new BitSet();
this.emptyBlockYMask = new BitSet();
- this.skyUpdates = Lists.newArrayList();
- this.blockUpdates = Lists.newArrayList();
+ this.skyUpdates = Lists.newArrayList();this.cleaner1 = MCUtil.registerListCleaner(this, this.skyUpdates, DataLayer::releaseBytes); // Paper
+ this.blockUpdates = Lists.newArrayList();this.cleaner2 = MCUtil.registerListCleaner(this, this.blockUpdates, DataLayer::releaseBytes); // Paper
for(int i = 0; i < lightProvider.getLightSectionCount(); ++i) {
if (bitSet == null || bitSet.get(i)) {
@@ -53,7 +85,7 @@ public class ClientboundLightUpdatePacket implements Packet<ClientGamePacketList
bitSet2.set(i);
} else {
bitSet.set(i);
- list.add((byte[])dataLayer.getData().clone());
+ list.add((byte[])dataLayer.getCloneIfSet()); // Paper
}
}
diff --git a/src/main/java/net/minecraft/world/level/chunk/DataLayer.java b/src/main/java/net/minecraft/world/level/chunk/DataLayer.java
index 4ddcdb3881f616f922cb539bf9d00a1ac89f051f..68a6c4db5980e733d81ef9a34cf32950f0983de6 100644
--- a/src/main/java/net/minecraft/world/level/chunk/DataLayer.java
+++ b/src/main/java/net/minecraft/world/level/chunk/DataLayer.java
@@ -13,11 +13,65 @@ public final class DataLayer {
private static final int NIBBLE_SIZE = 4;
@Nullable
protected byte[] data;
+ // Paper start
+ public static byte[] EMPTY_NIBBLE = new byte[2048];
+ private static final int nibbleBucketSizeMultiplier = Integer.getInteger("Paper.nibbleBucketSize", 3072);
+ private static final int maxPoolSize = Integer.getInteger("Paper.maxNibblePoolSize", (int) Math.min(6, Math.max(1, Runtime.getRuntime().maxMemory() / 1024 / 1024 / 1024)) * (nibbleBucketSizeMultiplier * 8));
+ public static final com.destroystokyo.paper.util.pooled.PooledObjects<byte[]> BYTE_2048 = new com.destroystokyo.paper.util.pooled.PooledObjects<>(() -> new byte[2048], maxPoolSize);
+ public static void releaseBytes(byte[] bytes) {
+ if (bytes != null && bytes != EMPTY_NIBBLE && bytes.length == 2048) {
+ System.arraycopy(EMPTY_NIBBLE, 0, bytes, 0, 2048);
+ BYTE_2048.release(bytes);
+ }
+ }
+ public DataLayer markPoolSafe(byte[] bytes) {
+ if (bytes != EMPTY_NIBBLE) this.data = bytes;
+ return markPoolSafe();
+ }
+ public DataLayer markPoolSafe() {
+ poolSafe = true;
+ return this;
+ }
+ public byte[] getIfSet() {
+ return this.data != null ? this.data : EMPTY_NIBBLE;
+ }
+ public byte[] getCloneIfSet() {
+ if (data == null) {
+ return EMPTY_NIBBLE;
+ }
+ byte[] ret = BYTE_2048.acquire();
+ System.arraycopy(getIfSet(), 0, ret, 0, 2048);
+ return ret;
+ }
+
+ public DataLayer cloneAndSet(byte[] bytes) {
+ if (bytes != null && bytes != EMPTY_NIBBLE) {
+ this.data = BYTE_2048.acquire();
+ System.arraycopy(bytes, 0, this.data, 0, 2048);
+ }
+ return this;
+ }
+ boolean poolSafe = false;
+ public java.lang.Runnable cleaner;
+ private void registerCleaner() {
+ if (!poolSafe) {
+ cleaner = net.minecraft.server.MCUtil.registerCleaner(this, this.data, DataLayer::releaseBytes);
+ } else {
+ cleaner = net.minecraft.server.MCUtil.once(() -> DataLayer.releaseBytes(this.data));
+ }
+ }
public DataLayer() {}
public DataLayer(byte[] bytes) {
+ // Paper start
+ this(bytes, false);
+ }
+ public DataLayer(byte[] bytes, boolean isSafe) {
this.data = bytes;
+ if (!isSafe) this.data = getCloneIfSet(); // Paper - clone for safety
+ registerCleaner();
+ // Paper end
if (bytes.length != 2048) {
throw (IllegalArgumentException) Util.pauseInIde((Throwable) (new IllegalArgumentException("DataLayer should be 2048 bytes not: " + bytes.length)));
}
@@ -52,7 +106,8 @@ public final class DataLayer {
private void set(int index, int value) {
if (this.data == null) {
- this.data = new byte[2048];
+ this.data = BYTE_2048.acquire(); // Paper
+ registerCleaner();// Paper
}
int k = DataLayer.getByteIndex(index);
@@ -74,13 +129,33 @@ public final class DataLayer {
public byte[] getData() {
if (this.data == null) {
this.data = new byte[2048];
+ } else { // Paper start
+ // Accessor may need this object past garbage collection so need to clone it and return pooled value
+ // If we know its safe for pre GC access, use asBytesPoolSafe(). If you just need read, use getIfSet()
+ Runnable cleaner = this.cleaner;
+ if (cleaner != null) {
+ this.data = this.data.clone();
+ cleaner.run(); // release the previously pooled value
+ this.cleaner = null;
+ }
}
+ // Paper end
return this.data;
}
+ @javax.annotation.Nonnull
+ public byte[] asBytesPoolSafe() {
+ if (this.data == null) {
+ this.data = BYTE_2048.acquire(); // Paper
+ registerCleaner(); // Paper
+ }
+
+ return this.data;
+ }
+ // Paper end
public DataLayer copy() {
- return this.data == null ? new DataLayer() : new DataLayer((byte[]) this.data.clone());
+ return this.data == null ? new DataLayer() : new DataLayer(this.data); // Paper - clone in ctor
}
public String toString() {
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
index d113b4835e86a789c0ba124eb839e1c56a5437d2..ed05a11f5038fdac90576ca33a0b710c83ab39a1 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
@@ -488,11 +488,11 @@ public class ChunkSerializer {
}
if (nibblearray != null && !nibblearray.isEmpty()) {
- nbttagcompound2.putByteArray("BlockLight", nibblearray.getData());
+ nbttagcompound2.putByteArray("BlockLight", nibblearray.asBytesPoolSafe().clone()); // Paper
}
if (nibblearray1 != null && !nibblearray1.isEmpty()) {
- nbttagcompound2.putByteArray("SkyLight", nibblearray1.getData());
+ nbttagcompound2.putByteArray("SkyLight", nibblearray1.asBytesPoolSafe().clone()); // Paper
}
nbttaglist.add(nbttagcompound2);
diff --git a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java
index f357a3473682c2d37a20fb862522c67b9979402a..52682471adc13dffc0383fc4abacbd3397f3bb10 100644
--- a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java
+++ b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java
@@ -34,7 +34,9 @@ public abstract class DataLayerStorageMap<M extends DataLayerStorageMap<M>> {
public void copyDataLayer(long pos) {
if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data
- this.data.queueUpdate(pos, ((DataLayer) this.data.getUpdating(pos)).copy()); // Paper - avoid copying light data
+ DataLayer updating = this.data.getUpdating(pos); // Paper - pool nibbles
+ this.data.queueUpdate(pos, new DataLayer().markPoolSafe(updating.getCloneIfSet())); // Paper - avoid copying light data - pool safe clone
+ if (updating.cleaner != null) net.minecraft.server.MCUtil.scheduleTask(2, updating.cleaner, "Light Engine Release"); // Paper - delay clean incase anything holding ref was still using it
this.clearCache();
}
diff --git a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java
index cc9eb8273d5157fb649d84a3ec589b0b923b5bc9..fd1cdb6e2023713f947b9497c605cf6f4bae8994 100644
--- a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java
+++ b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java
@@ -162,7 +162,7 @@ public abstract class LayerLightSectionStorage<M extends DataLayerStorageMap<M>>
protected DataLayer createDataLayer(long sectionPos) {
DataLayer dataLayer = this.queuedSections.get(sectionPos);
- return dataLayer != null ? dataLayer : new DataLayer();
+ return dataLayer != null ? dataLayer : new DataLayer().markPoolSafe(); // Paper
}
protected void clearQueuedSectionBlocks(LayerLightEngine<?, ?> storage, long sectionPos) {
@@ -321,12 +321,12 @@ public abstract class LayerLightSectionStorage<M extends DataLayerStorageMap<M>>
protected void queueSectionData(long sectionPos, @Nullable DataLayer array, boolean bl) {
if (array != null) {
- this.queuedSections.put(sectionPos, array);
+ DataLayer remove = this.queuedSections.put(sectionPos, array); if (remove != null && remove.cleaner != null) remove.cleaner.run(); // Paper - clean up when removed
if (!bl) {
this.untrustedSections.add(sectionPos);
}
} else {
- this.queuedSections.remove(sectionPos);
+ DataLayer remove = this.queuedSections.remove(sectionPos); if (remove != null && remove.cleaner != null) remove.cleaner.run(); // Paper - clean up when removed
}
}
diff --git a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java
index 24030bcb3303d0419c7859ded7613608c5f82308..ec3837a64e8ac6892028611d57a111a7fd5c58f7 100644
--- a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java
+++ b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java
@@ -163,14 +163,14 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage<SkyLightSec
return repeatFirstLayer(dataLayer2);
} else {
- return new DataLayer();
+ return new DataLayer().markPoolSafe(); // Paper - mark pool use as safe (no auto cleaner)
}
}
}
private static DataLayer repeatFirstLayer(DataLayer source) {
if (source.isEmpty()) {
- return new DataLayer();
+ return new DataLayer().markPoolSafe(); // Paper - mark pool use as safe (no auto cleaner)
} else {
byte[] bs = source.getData();
byte[] cs = new byte[2048];
@@ -179,7 +179,7 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage<SkyLightSec
System.arraycopy(bs, 0, cs, i * 128, 128);
}
- return new DataLayer(cs);
+ return new DataLayer(cs).markPoolSafe(cs); // Paper - mark pool use as safe (no auto cleaner)
}
}
@@ -197,7 +197,7 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage<SkyLightSec
this.updatingSectionData.copyDataLayer(l);
}
- Arrays.fill(this.getDataLayer(l, true).getData(), (byte)-1);
+ Arrays.fill(this.getDataLayer(l, true).asBytesPoolSafe(), (byte)-1); // Paper
int j = SectionPos.sectionToBlockCoord(SectionPos.x(l));
int k = SectionPos.sectionToBlockCoord(SectionPos.y(l));
int m = SectionPos.sectionToBlockCoord(SectionPos.z(l));
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
index 46136c5daa1b4ea9103c736cc4b035195177368e..5088c84f6518cb686241b1db54faa8d813cb3eaa 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
@@ -343,14 +343,14 @@ public class CraftChunk implements Chunk {
sectionSkyLights[i] = CraftChunk.emptyLight;
} else {
sectionSkyLights[i] = new byte[2048];
- System.arraycopy(skyLightArray.getData(), 0, sectionSkyLights[i], 0, 2048);
+ System.arraycopy(skyLightArray.getIfSet(), 0, sectionSkyLights[i], 0, 2048); // Paper
}
DataLayer emitLightArray = lightengine.getLayerListener(LightLayer.BLOCK).getDataLayerData(SectionPos.of(x, i, z));
if (emitLightArray == null) {
sectionEmitLights[i] = CraftChunk.emptyLight;
} else {
sectionEmitLights[i] = new byte[2048];
- System.arraycopy(emitLightArray.getData(), 0, sectionEmitLights[i], 0, 2048);
+ System.arraycopy(emitLightArray.getIfSet(), 0, sectionEmitLights[i], 0, 2048); // Paper
}
}
}

View file

@ -1,83 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MiniDigger <admin@minidigger.me>
Date: Sat, 6 Jun 2020 18:13:42 +0200
Subject: [PATCH] Support components in ItemMeta
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
index 3a125e7018b57aa6a802e99662fa784493fec5fc..808eb6b9ec535b1179a1d7b88877c9ce1755c45b 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
@@ -874,11 +874,23 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
return CraftChatMessage.fromJSONComponent(displayName);
}
+ // Paper start
+ @Override
+ public net.md_5.bungee.api.chat.BaseComponent[] getDisplayNameComponent() {
+ return displayName == null ? new net.md_5.bungee.api.chat.BaseComponent[0] : net.md_5.bungee.chat.ComponentSerializer.parse(displayName);
+ }
+ // Paper end
@Override
public final void setDisplayName(String name) {
this.displayName = CraftChatMessage.fromStringOrNullToJSON(name);
}
+ // Paper start
+ @Override
+ public void setDisplayNameComponent(net.md_5.bungee.api.chat.BaseComponent[] component) {
+ this.displayName = net.md_5.bungee.chat.ComponentSerializer.toString(component);
+ }
+ // Paper end
@Override
public boolean hasDisplayName() {
return this.displayName != null;
@@ -1021,6 +1033,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
return this.lore == null ? null : new ArrayList<String>(Lists.transform(this.lore, CraftChatMessage::fromJSONComponent));
}
+ // Paper start
+ @Override
+ public List<net.md_5.bungee.api.chat.BaseComponent[]> getLoreComponents() {
+ return this.lore == null ? null : new ArrayList<>(this.lore.stream().map(entry ->
+ net.md_5.bungee.chat.ComponentSerializer.parse(entry)
+ ).collect(java.util.stream.Collectors.toList()));
+ }
+ // Paper end
@Override
public void setLore(List<String> lore) {
if (lore == null || lore.isEmpty()) {
@@ -1035,6 +1055,21 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
}
}
+ // Paper start
+ @Override
+ public void setLoreComponents(List<net.md_5.bungee.api.chat.BaseComponent[]> lore) {
+ if (lore == null) {
+ this.lore = null;
+ } else {
+ if (this.lore == null) {
+ safelyAdd(lore, this.lore = new ArrayList<>(lore.size()), false);
+ } else {
+ this.lore.clear();
+ safelyAdd(lore, this.lore, false);
+ }
+ }
+ }
+ // Paper end
@Override
public boolean hasCustomModelData() {
return this.customModelData != null;
@@ -1495,6 +1530,11 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
}
for (Object object : addFrom) {
+ // Paper start - support components
+ if(object instanceof net.md_5.bungee.api.chat.BaseComponent[]) {
+ addTo.add(net.md_5.bungee.chat.ComponentSerializer.toString((net.md_5.bungee.api.chat.BaseComponent[]) object));
+ } else
+ // Paper end
if (!(object instanceof String)) {
if (object != null) {
throw new IllegalArgumentException(addFrom + " cannot contain non-string " + object.getClass().getName());

View file

@ -1,60 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Fri, 3 Jul 2020 15:03:33 -0700
Subject: [PATCH] Improve EntityTargetLivingEntityEvent for 1.16 mobs
CraftBukkit has a bug in their implementation and is incorrectly handling forget
Also adds more target reasons for why it forgot target.
diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java b/src/main/java/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java
index 6ee0098de2b55a437f914869643adbd1ddbe7faf..4b2e0379d9bbeb12c104e52817bb2005ed627a78 100644
--- a/src/main/java/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java
+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java
@@ -50,15 +50,15 @@ public class StopAttackingIfTargetInvalid<E extends Mob> extends Behavior<E> {
LivingEntity entityliving = this.getAttackTarget(entity);
if (!entity.canAttack(entityliving)) {
- this.clearAttackTarget(entity);
+ this.clearAttackTarget(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_INVALID); // Paper
} else if (StopAttackingIfTargetInvalid.isTiredOfTryingToReachTarget((LivingEntity) entity)) {
- this.clearAttackTarget(entity);
+ this.clearAttackTarget(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.FORGOT_TARGET); // Paper
} else if (this.isCurrentTargetDeadOrRemoved(entity)) {
- this.clearAttackTarget(entity);
+ this.clearAttackTarget(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_DIED); // Paper
} else if (this.isCurrentTargetInDifferentLevel(entity)) {
- this.clearAttackTarget(entity);
+ this.clearAttackTarget(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_OTHER_LEVEL); // Paper
} else if (this.stopAttackingWhen.test(this.getAttackTarget(entity))) {
- this.clearAttackTarget(entity);
+ this.clearAttackTarget(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_INVALID); // Paper
}
}
@@ -82,17 +82,20 @@ public class StopAttackingIfTargetInvalid<E extends Mob> extends Behavior<E> {
return optional.isPresent() && !((LivingEntity) optional.get()).isAlive();
}
- protected void clearAttackTarget(E entity) {
+ protected void clearAttackTarget(E entity, EntityTargetEvent.TargetReason reason) {
// CraftBukkit start
- LivingEntity old = entity.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null);
- EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(entity, null, (old != null && !old.isAlive()) ? EntityTargetEvent.TargetReason.TARGET_DIED : EntityTargetEvent.TargetReason.FORGOT_TARGET);
+ // Paper start - fix this event
+ //EntityLiving old = e0.getBehaviorController().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null);
+ EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(entity, null, reason);
if (event.isCancelled()) {
return;
}
- if (event.getTarget() != null) {
- entity.getBrain().setMemory(MemoryModuleType.ATTACK_TARGET, ((CraftLivingEntity) event.getTarget()).getHandle());
+ // comment out, bad logic - bad
+ /*if (event.getTarget() != null) {
+ e0.getBehaviorController().setMemory(MemoryModuleType.ATTACK_TARGET, ((CraftLivingEntity) event.getTarget()).getHandle());
return;
- }
+ }*/
+ // Paper end
// CraftBukkit end
this.onTargetErased.accept(entity);
entity.getBrain().eraseMemory(MemoryModuleType.ATTACK_TARGET);

View file

@ -1,52 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Thu, 2 Jul 2020 18:11:43 -0500
Subject: [PATCH] Add entity liquid API
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 19a6b2c686e6421624282d0536dfdd3320da4ec6..3e1f34ed8c3b4bd4f6c3624332a5f2be62e196fe 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -1365,7 +1365,6 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
return this.isInWater() || this.isInRain();
}
- @Deprecated public final boolean isInWaterOrRainOrBubble() { return isInWaterRainOrBubble(); } // Paper - OBFHELPER
public boolean isInWaterRainOrBubble() {
return this.isInWater() || this.isInRain() || this.isInBubbleColumn();
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index c9e716900d88d025be1f09b6fe0156cf0dac2d33..f28f857d6218db1634348e8a57e7b275b9115bfc 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -1235,5 +1235,29 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason() {
return getHandle().spawnReason;
}
+
+ public boolean isInRain() {
+ return getHandle().isInRain();
+ }
+
+ public boolean isInBubbleColumn() {
+ return getHandle().isInBubbleColumn();
+ }
+
+ public boolean isInWaterOrRain() {
+ return getHandle().isInWaterOrRain();
+ }
+
+ public boolean isInWaterOrBubbleColumn() {
+ return getHandle().isInWaterOrBubble();
+ }
+
+ public boolean isInWaterOrRainOrBubbleColumn() {
+ return getHandle().isInWaterRainOrBubble();
+ }
+
+ public boolean isInLava() {
+ return getHandle().isInLava();
+ }
// Paper end
}

View file

@ -1,63 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Wed, 1 Jul 2020 11:57:40 -0500
Subject: [PATCH] Update itemstack legacy name and lore
diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java
index 1f93ad93701339418b554eb3e1e3f74e62468f3f..e643f925623820ffa67217eb3615582c0d0ca3a5 100644
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
@@ -168,6 +168,44 @@ public final class ItemStack {
list.sort((Comparator<? super net.minecraft.nbt.Tag>) enchantSorter); // Paper
} catch (Exception ignored) {}
}
+
+ private void processText() {
+ CompoundTag display = getTagElement("display");
+ if (display != null) {
+ if (display.contains("Name", 8)) {
+ String json = display.getString("Name");
+ if (json != null && json.contains("\u00A7")) {
+ try {
+ display.put("Name", convert(json));
+ } catch (JsonParseException jsonparseexception) {
+ display.remove("Name");
+ }
+ }
+ }
+ if (display.contains("Lore", 9)) {
+ ListTag list = display.getList("Lore", 8);
+ for (int index = 0; index < list.size(); index++) {
+ String json = list.getString(index);
+ if (json != null && json.contains("\u00A7")) { // Only try if it has legacy in the unparsed json
+ try {
+ list.set(index, convert(json));
+ } catch (JsonParseException e) {
+ list.set(index, net.minecraft.nbt.StringTag.valueOf(org.bukkit.craftbukkit.util.CraftChatMessage.toJSON(new TextComponent(""))));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private net.minecraft.nbt.StringTag convert(String json) {
+ Component component = Component.Serializer.fromJson(json);
+ if (component instanceof TextComponent && component.getContents().contains("\u00A7") && component.getSiblings().isEmpty()) {
+ // Only convert if the root component is a single comp with legacy in it, don't convert already normal components
+ component = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(component.getContents())[0];
+ }
+ return net.minecraft.nbt.StringTag.valueOf(org.bukkit.craftbukkit.util.CraftChatMessage.toJSON(component));
+ }
// Paper end
public ItemStack(ItemLike item) {
@@ -214,6 +252,7 @@ public final class ItemStack {
this.tag = (CompoundTag) nbttagcompound.getCompound("tag").copy();
// CraftBukkit end
this.processEnchantOrder(this.tag); // Paper
+ this.processText(); // Paper
this.getItem().verifyTagAfterLoad(this.tag);
}

View file

@ -1,30 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Wyatt Childers <wchilders@nearce.com>
Date: Fri, 3 Jul 2020 14:57:05 -0400
Subject: [PATCH] Spawn player in correct world on login
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index f5334be5d9c799da16198ecb0f69f17a2bf4a1eb..e0c9857a922d8a3f421d7df0f056b82c4775390e 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -196,7 +196,18 @@ public abstract class PlayerList {
}String lastKnownName = s; // Paper
// CraftBukkit end
- if (nbttagcompound != null) {
+ // Paper start - move logic in Entity to here, to use bukkit supplied world UUID.
+ if (nbttagcompound != null && nbttagcompound.contains("WorldUUIDMost") && nbttagcompound.contains("WorldUUIDLeast")) {
+ UUID uid = new UUID(nbttagcompound.getLong("WorldUUIDMost"), nbttagcompound.getLong("WorldUUIDLeast"));
+ org.bukkit.World bWorld = org.bukkit.Bukkit.getServer().getWorld(uid);
+ if (bWorld != null) {
+ resourcekey = ((CraftWorld) bWorld).getHandle().dimension();
+ } else {
+ resourcekey = Level.OVERWORLD;
+ }
+ } else if (nbttagcompound != null) {
+ // Vanilla migration support
+ // Paper end
DataResult dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, nbttagcompound.get("Dimension")));
Logger logger = PlayerList.LOGGER;

View file

@ -1,152 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Fri, 3 Jul 2020 11:58:56 -0500
Subject: [PATCH] Add PrepareResultEvent
Adds a new event for all crafting stations that generate a result slot item
Anvil, Grindstone and Smithing now extend this event
diff --git a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java b/src/main/java/net/minecraft/world/inventory/AnvilMenu.java
index 2ed4930648411ccd52fc970b069e57eba9bceef8..593e23c10f2b1616db7256158dfe564b2d289df1 100644
--- a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/AnvilMenu.java
@@ -317,6 +317,7 @@ public class AnvilMenu extends ItemCombinerMenu {
}
this.createResult();
+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper
}
public int getCost() {
diff --git a/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java b/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java
index 93ebd73b94efac5f671b0459e0075959f5ce8bdf..aaf67ac2a73fa3b4420ec99ee185bceda2cb4c2b 100644
--- a/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java
@@ -150,6 +150,7 @@ public class CartographyTableMenu extends AbstractContainerMenu {
this.setupResultSlot(itemstack, itemstack1, itemstack2);
}
+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper
}
private void setupResultSlot(ItemStack map, ItemStack item, ItemStack oldResult) {
diff --git a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java
index b268645827b7a57b906fd925d694f802a75da25d..dda6c4948b903221fa8020c76d109216d2dd82bf 100644
--- a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java
@@ -160,6 +160,7 @@ public class GrindstoneMenu extends AbstractContainerMenu {
super.slotsChanged(inventory);
if (inventory == this.repairSlots) {
this.createResult();
+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper
}
}
diff --git a/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java b/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java
index 8819347987a8072eede52a57fec763711d9bab92..9cc246f43230e87c6bd2377ef77ab2dcb9509a5c 100644
--- a/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java
@@ -78,6 +78,7 @@ public abstract class ItemCombinerMenu extends AbstractContainerMenu {
super.slotsChanged(inventory);
if (inventory == this.inputSlots) {
this.createResult();
+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper
}
}
diff --git a/src/main/java/net/minecraft/world/inventory/LoomMenu.java b/src/main/java/net/minecraft/world/inventory/LoomMenu.java
index b490e87d95c3a140323aa9da95b90381392f64f8..9bcab01324612a905b21623a09109d404f8dadf7 100644
--- a/src/main/java/net/minecraft/world/inventory/LoomMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/LoomMenu.java
@@ -196,7 +196,8 @@ public class LoomMenu extends AbstractContainerMenu {
}
this.setupResultSlot();
- this.broadcastChanges();
+ //this.c(); // Paper - done below
+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 3); // Paper
}
public void registerUpdateListener(Runnable inventoryChangeListener) {
diff --git a/src/main/java/net/minecraft/world/inventory/SmithingMenu.java b/src/main/java/net/minecraft/world/inventory/SmithingMenu.java
index 92dd2ea23185bba311e184b2ac9744a423c102ea..cb3f522a586b841056c35378a49dd50bfa673f61 100644
--- a/src/main/java/net/minecraft/world/inventory/SmithingMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/SmithingMenu.java
@@ -76,6 +76,7 @@ public class SmithingMenu extends ItemCombinerMenu {
// CraftBukkit end
}
+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper
}
@Override
diff --git a/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java b/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java
index 3df5031ec2c50dc6eb2533318cf8a98f21b03d2a..c971a534ded962e3be92c71059c75cc1d54970b5 100644
--- a/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java
@@ -176,6 +176,7 @@ public class StonecutterMenu extends AbstractContainerMenu {
this.setupRecipeList(inventory, itemstack);
}
+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 1); // Paper
}
private void setupRecipeList(Container input, ItemStack stack) {
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index ff2149572a82d6605a0b28f2fdd0dadb86af25a1..869990c181403a025d219dbd0e1201005973ffe9 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -1556,19 +1556,44 @@ public class CraftEventFactory {
return event;
}
- public static PrepareAnvilEvent callPrepareAnvilEvent(InventoryView view, ItemStack item) {
- PrepareAnvilEvent event = new PrepareAnvilEvent(view, CraftItemStack.asCraftMirror(item).clone());
- event.getView().getPlayer().getServer().getPluginManager().callEvent(event);
+ // Paper start - disable this method, handled below
+ public static void callPrepareAnvilEvent(InventoryView view, ItemStack item) { // Paper - verify nothing uses return - handled below in PrepareResult
+ PrepareAnvilEvent event = new PrepareAnvilEvent(view, CraftItemStack.asCraftMirror(item)); // Paper - remove clone
+ //event.getView().getPlayer().getServer().getPluginManager().callEvent(event); // disable event
event.getInventory().setItem(2, event.getResult());
- return event;
+ //return event; // Paper
}
+ // Paper end
- public static PrepareSmithingEvent callPrepareSmithingEvent(InventoryView view, ItemStack item) {
- PrepareSmithingEvent event = new PrepareSmithingEvent(view, CraftItemStack.asCraftMirror(item).clone());
- event.getView().getPlayer().getServer().getPluginManager().callEvent(event);
+ // Paper start - disable this method, handled in callPrepareResultEvent
+ public static void callPrepareSmithingEvent(InventoryView view, ItemStack item) { // Paper - verify nothing uses return - handled below in PrepareResult
+ PrepareSmithingEvent event = new PrepareSmithingEvent(view, CraftItemStack.asCraftMirror(item)); // Paper - remove clone
+ //event.getView().getPlayer().getServer().getPluginManager().callEvent(event); // Paper - disable event
event.getInventory().setItem(2, event.getResult());
- return event;
+ //return event; // Paper
}
+ // Paper end
+
+ // Paper start - support specific overrides for prepare result
+ public static void callPrepareResultEvent(AbstractContainerMenu container, int resultSlot) {
+ com.destroystokyo.paper.event.inventory.PrepareResultEvent event;
+ InventoryView view = container.getBukkitView();
+ org.bukkit.inventory.ItemStack origItem = view.getTopInventory().getItem(resultSlot);
+ CraftItemStack result = origItem != null ? CraftItemStack.asCraftCopy(origItem) : null;
+ if (view.getTopInventory() instanceof org.bukkit.inventory.AnvilInventory) {
+ event = new PrepareAnvilEvent(view, result);
+ } else if (view.getTopInventory() instanceof org.bukkit.inventory.GrindstoneInventory) {
+ event = new com.destroystokyo.paper.event.inventory.PrepareGrindstoneEvent(view, result);
+ } else if (view.getTopInventory() instanceof org.bukkit.inventory.SmithingInventory) {
+ event = new PrepareSmithingEvent(view, result);
+ } else {
+ event = new com.destroystokyo.paper.event.inventory.PrepareResultEvent(view, result);
+ }
+ event.callEvent();
+ event.getInventory().setItem(resultSlot, event.getResult());
+ container.broadcastChanges();;
+ }
+ // Paper end
/**
* Mob spawner event.

View file

@ -1,67 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MiniDigger <admin@minidigger.me>
Date: Wed, 29 Apr 2020 02:10:32 +0200
Subject: [PATCH] Allow delegation to vanilla chunk gen
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index da9fc8a99576f13a52ab4830cb09b69b1e406fae..81effb4bc34d3cb4325510c1b0de39956961c427 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -2198,6 +2198,32 @@ public final class CraftServer implements Server {
return new OldCraftChunkData(world);
}
+ // Paper start
+ @Override
+ public ChunkGenerator.ChunkData createVanillaChunkData(World world, int x, int z) {
+ // get empty object
+ OldCraftChunkData data = (OldCraftChunkData) createChunkData(world);
+ // do bunch of vanilla shit
+ net.minecraft.server.level.ServerLevel nmsWorld = ((CraftWorld) world).getHandle();
+ net.minecraft.world.level.chunk.ProtoChunk protoChunk = new net.minecraft.world.level.chunk.ProtoChunk(new net.minecraft.world.level.ChunkPos(x, z), null, nmsWorld, nmsWorld);
+ List<net.minecraft.world.level.chunk.ChunkAccess> list = new ArrayList<>();
+ list.add(protoChunk);
+ net.minecraft.server.level.WorldGenRegion genRegion = new net.minecraft.server.level.WorldGenRegion(nmsWorld, list, net.minecraft.world.level.chunk.ChunkStatus.EMPTY, -1);
+ // call vanilla generator, one feature after another. Order here is important!
+ net.minecraft.world.level.chunk.ChunkGenerator chunkGenerator = nmsWorld.getChunkSource().generator;
+ if (chunkGenerator instanceof org.bukkit.craftbukkit.generator.CustomChunkGenerator) {
+ chunkGenerator = ((org.bukkit.craftbukkit.generator.CustomChunkGenerator) chunkGenerator).delegate;
+ }
+ chunkGenerator.createBiomes(nmsWorld.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), protoChunk);
+ chunkGenerator.fillFromNoise((runnable) -> {}, nmsWorld.structureFeatureManager(), protoChunk);
+ chunkGenerator.buildSurfaceAndBedrock(genRegion, protoChunk);
+ // copy over generated sections
+ data.setRawChunkData(protoChunk.getSections());
+ // hooray!
+ return data;
+ }
+ // Paper end
+
@Override
public BossBar createBossBar(String title, BarColor color, BarStyle style, BarFlag... flags) {
return new CraftBossBar(title, color, style, flags);
diff --git a/src/main/java/org/bukkit/craftbukkit/generator/OldCraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/OldCraftChunkData.java
index a48c659c02c6c33a8efdac6daf9c9a0708f05071..932bd3334b5852c8f209678b1444fc0e43a637f0 100644
--- a/src/main/java/org/bukkit/craftbukkit/generator/OldCraftChunkData.java
+++ b/src/main/java/org/bukkit/craftbukkit/generator/OldCraftChunkData.java
@@ -22,7 +22,7 @@ import org.bukkit.material.MaterialData;
public final class OldCraftChunkData implements ChunkGenerator.ChunkData {
private final int minHeight;
private final int maxHeight;
- private final LevelChunkSection[] sections;
+ private LevelChunkSection[] sections;
private Set<BlockPos> tiles;
private final Set<BlockPos> lights = new HashSet<>();
private World world; // Paper - Anti-Xray - Add parameters
@@ -195,4 +195,10 @@ public final class OldCraftChunkData implements ChunkGenerator.ChunkData {
Set<BlockPos> getLights() {
return this.lights;
}
+
+ // Paper start
+ public void setRawChunkData(LevelChunkSection[] sections) {
+ this.sections = sections;
+ }
+ // Paper end
}

View file

@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Sun, 5 Jul 2020 14:59:31 -0400
Subject: [PATCH] Don't check chunk for portal on world gen entity add
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index fab8098ce72feb9b08960e55ab1a4aebaae22276..2e7d7bd60ac340568b1bc0f3052affcf445090f7 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -3359,7 +3359,7 @@ public abstract class LivingEntity extends Entity {
Entity entity = this.getVehicle();
super.stopRiding(suppressCancellation); // Paper - suppress
- if (entity != null && entity != this.getVehicle() && !this.level.isClientSide) {
+ if (entity != null && entity != this.getVehicle() && !this.level.isClientSide && entity.valid) { // Paper - don't process on world gen
this.dismountVehicle(entity);
}