moooore
This commit is contained in:
parent
6456b5dea8
commit
cb79de80c4
59 changed files with 373 additions and 380 deletions
42
patches/server/0634-Entity-powdered-snow-API.patch
Normal file
42
patches/server/0634-Entity-powdered-snow-API.patch
Normal file
|
@ -0,0 +1,42 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sun, 24 Oct 2021 20:58:43 -0700
|
||||
Subject: [PATCH] Entity powdered snow API
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.entity.monster.Skeleton inPowderSnowTime
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
index 1ed01978611cddb2558e441863dadc468bc07c3d..9693656418210957000add9b6670c4bee67f8462 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
@@ -1100,6 +1100,13 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
||||
}
|
||||
// Paper end - raw entity serialization API
|
||||
|
||||
+ // Paper start - entity powdered snow API
|
||||
+ @Override
|
||||
+ public boolean isInPowderedSnow() {
|
||||
+ return getHandle().isInPowderSnow || getHandle().wasInPowderSnow; // depending on the location in the entity "tick" either could be needed.
|
||||
+ }
|
||||
+ // Paper end - entity powdered snow API
|
||||
+
|
||||
// Paper start - missing entity api
|
||||
@Override
|
||||
public boolean isInvisible() { // Paper - moved up from LivingEntity
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java
|
||||
index a0ea54181de6c6685deef265cbe9f66aabbca42b..6f98da9be6aef35e3b5c940188b872459a383c8e 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java
|
||||
@@ -45,4 +45,11 @@ public class CraftSkeleton extends CraftAbstractSkeleton implements Skeleton {
|
||||
public SkeletonType getSkeletonType() {
|
||||
return SkeletonType.NORMAL;
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public int inPowderedSnowTime() {
|
||||
+ return getHandle().inPowderSnowTime;
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
34
patches/server/0635-Add-API-for-item-entity-health.patch
Normal file
34
patches/server/0635-Add-API-for-item-entity-health.patch
Normal file
|
@ -0,0 +1,34 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sat, 28 Aug 2021 09:00:45 -0700
|
||||
Subject: [PATCH] Add API for item entity health
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.entity.item.ItemEntity health
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java
|
||||
index 4a15c3786edbfeae3367c0b20fb6aee11d62aea6..1a291dd8a287db30e71dcb315599fc4b038764c4 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java
|
||||
@@ -98,6 +98,21 @@ public class CraftItem extends CraftEntity implements Item {
|
||||
public void setWillAge(boolean willAge) {
|
||||
this.getHandle().age = willAge ? 0 : NO_AGE_TIME;
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public int getHealth() {
|
||||
+ return this.getHandle().health;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setHealth(int health) {
|
||||
+ if (health <= 0) {
|
||||
+ this.getHandle().getItem().onDestroyed(this.getHandle());
|
||||
+ this.getHandle().discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.PLUGIN);
|
||||
+ } else {
|
||||
+ this.getHandle().health = health;
|
||||
+ }
|
||||
+ }
|
||||
// Paper end
|
||||
|
||||
@Override
|
|
@ -0,0 +1,19 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Nassim Jahnke <nassim@njahnke.dev>
|
||||
Date: Thu, 16 Dec 2021 09:40:39 +0100
|
||||
Subject: [PATCH] Configurable max block light for monster spawning
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/Monster.java b/src/main/java/net/minecraft/world/entity/monster/Monster.java
|
||||
index c49853f25bdf1fbc7ec9700d421c6ddccabae05f..e2de074bbe7bab0e5a7aecc1fae4c5914a203dd4 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Monster.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Monster.java
|
||||
@@ -92,7 +92,7 @@ public abstract class Monster extends PathfinderMob implements Enemy {
|
||||
return false;
|
||||
} else {
|
||||
DimensionType dimensionType = world.dimensionType();
|
||||
- int i = dimensionType.monsterSpawnBlockLightLimit();
|
||||
+ int i = world.getLevel().paperConfig().entities.spawning.monsterSpawnMaxLightLevel.or(dimensionType.monsterSpawnBlockLightLimit()); // Paper - Configurable max block light for monster spawning
|
||||
if (i < 15 && world.getBrightness(LightLayer.BLOCK, pos) > i) {
|
||||
return false;
|
||||
} else {
|
|
@ -0,0 +1,85 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Wed, 22 Dec 2021 09:51:48 -0800
|
||||
Subject: [PATCH] Fix sticky pistons and BlockPistonRetractEvent
|
||||
|
||||
There is an explicit check in the handling code for empty pistons that
|
||||
prevents sticky pistons from firing the event. However when we look back
|
||||
at the history we see that this check was originally added so that ONLY
|
||||
sticky pistons would fire the retract event. I'm not sure why.
|
||||
https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/commits/1092acbddf07edfa4100bc6824504ac75088e913
|
||||
|
||||
Over the course of several updates, the meaning of that field appears to
|
||||
have changed from "is NOT sticky" to "is sticky". So now its having the
|
||||
opposite effect. Only normal pistons fire the retraction event. And like
|
||||
all things in CB, it's just been carried around since.
|
||||
|
||||
If we are to believe the history, the correct fix for this issue is to
|
||||
flip it so it only fires for sticky pistons, but that puts us in a
|
||||
bind. It's already firing for non-sticky pistons, changing it now would
|
||||
likely result in breakage. Furthermore, there is little documentation as
|
||||
to WHY that was ever intended to be the case.
|
||||
|
||||
Instead we opt to remove the check entirely so that the event fires for
|
||||
all piston types.
|
||||
|
||||
Co-authored-by: Zach Brown <zach@zachbr.io>
|
||||
Co-authored-by: Madeline Miller <mnmiller1@me.com>
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java
|
||||
index 560797552799f7874133fd4aaf6e421609a54dbf..b27cf7d27672ba9ff8ade84b5a8454b19b935607 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java
|
||||
@@ -163,15 +163,15 @@ public class PistonBaseBlock extends DirectionalBlock {
|
||||
}
|
||||
|
||||
// CraftBukkit start
|
||||
- if (!this.isSticky) {
|
||||
- org.bukkit.block.Block block = world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ());
|
||||
- BlockPistonRetractEvent event = new BlockPistonRetractEvent(block, ImmutableList.<org.bukkit.block.Block>of(), CraftBlock.notchToBlockFace(enumdirection));
|
||||
- world.getCraftServer().getPluginManager().callEvent(event);
|
||||
-
|
||||
- if (event.isCancelled()) {
|
||||
- return;
|
||||
- }
|
||||
- }
|
||||
+ // if (!this.isSticky) { // Paper - Fix sticky pistons and BlockPistonRetractEvent; Move further down
|
||||
+ // org.bukkit.block.Block block = world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ());
|
||||
+ // BlockPistonRetractEvent event = new BlockPistonRetractEvent(block, ImmutableList.<org.bukkit.block.Block>of(), CraftBlock.notchToBlockFace(enumdirection));
|
||||
+ // world.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ //
|
||||
+ // if (event.isCancelled()) {
|
||||
+ // return;
|
||||
+ // }
|
||||
+ // }
|
||||
// PAIL: checkME - what happened to setTypeAndData?
|
||||
// CraftBukkit end
|
||||
world.blockEvent(pos, this, b0, enumdirection.get3DDataValue());
|
||||
@@ -248,6 +248,13 @@ public class PistonBaseBlock extends DirectionalBlock {
|
||||
|
||||
BlockState iblockdata2 = (BlockState) ((BlockState) Blocks.MOVING_PISTON.defaultBlockState().setValue(MovingPistonBlock.FACING, enumdirection)).setValue(MovingPistonBlock.TYPE, this.isSticky ? PistonType.STICKY : PistonType.DEFAULT);
|
||||
|
||||
+ // Paper start - Fix sticky pistons and BlockPistonRetractEvent; Move empty piston retract call to fix multiple event fires
|
||||
+ if (!this.isSticky) {
|
||||
+ if (!new BlockPistonRetractEvent(CraftBlock.at(world, pos), java.util.Collections.emptyList(), CraftBlock.notchToBlockFace(enumdirection)).callEvent()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Fix sticky pistons and BlockPistonRetractEvent
|
||||
world.setBlock(pos, iblockdata2, 20);
|
||||
world.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(pos, iblockdata2, (BlockState) this.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.from3DDataValue(data & 7)), enumdirection, false, true));
|
||||
world.blockUpdated(pos, iblockdata2.getBlock());
|
||||
@@ -274,6 +281,13 @@ public class PistonBaseBlock extends DirectionalBlock {
|
||||
if (type == 1 && !iblockdata3.isAir() && PistonBaseBlock.isPushable(iblockdata3, world, blockposition1, enumdirection.getOpposite(), false, enumdirection) && (iblockdata3.getPistonPushReaction() == PushReaction.NORMAL || iblockdata3.is(Blocks.PISTON) || iblockdata3.is(Blocks.STICKY_PISTON))) {
|
||||
this.moveBlocks(world, pos, enumdirection, false);
|
||||
} else {
|
||||
+ // Paper start - Fix sticky pistons and BlockPistonRetractEvent; fire BlockPistonRetractEvent for sticky pistons retracting nothing (air)
|
||||
+ if (type == TRIGGER_CONTRACT && iblockdata2.isAir()) {
|
||||
+ if (!new BlockPistonRetractEvent(CraftBlock.at(world, pos), java.util.Collections.emptyList(), CraftBlock.notchToBlockFace(enumdirection)).callEvent()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Fix sticky pistons and BlockPistonRetractEvent
|
||||
world.removeBlock(pos.relative(enumdirection), false);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <blake.galbreath@gmail.com>
|
||||
Date: Thu, 23 Dec 2021 15:32:50 -0600
|
||||
Subject: [PATCH] Expose isFuel and canSmelt methods to FurnaceInventory
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryFurnace.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryFurnace.java
|
||||
index 29a8cd7667860c4598a556e6ef3af39c731683db..bd370f5c856d75b7210ef26036aedaa859c570be 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryFurnace.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryFurnace.java
|
||||
@@ -40,6 +40,20 @@ public class CraftInventoryFurnace extends CraftInventory implements FurnaceInve
|
||||
this.setItem(0, stack);
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public boolean isFuel(ItemStack stack) {
|
||||
+ return stack != null && !stack.getType().isEmpty() && AbstractFurnaceBlockEntity.isFuel(CraftItemStack.asNMSCopy(stack));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean canSmelt(ItemStack stack) {
|
||||
+ // data packs are always loaded in the main world
|
||||
+ net.minecraft.server.level.ServerLevel world = ((org.bukkit.craftbukkit.CraftWorld) org.bukkit.Bukkit.getWorlds().get(0)).getHandle();
|
||||
+ return stack != null && !stack.getType().isEmpty() && world.getRecipeManager().getRecipeFor(((AbstractFurnaceBlockEntity) this.inventory).recipeType, new net.minecraft.world.item.crafting.SingleRecipeInput(CraftItemStack.asNMSCopy(stack)), world).isPresent();
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public Furnace getHolder() {
|
||||
return (Furnace) this.inventory.getOwner();
|
69
patches/server/0639-Bucketable-API.patch
Normal file
69
patches/server/0639-Bucketable-API.patch
Normal file
|
@ -0,0 +1,69 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
|
||||
Date: Sun, 26 Dec 2021 14:03:17 -0500
|
||||
Subject: [PATCH] Bucketable API
|
||||
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/entity/PaperBucketable.java b/src/main/java/io/papermc/paper/entity/PaperBucketable.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..d3fc2e5db9f3c20120b403bf03c3c340b9956cbd
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/entity/PaperBucketable.java
|
||||
@@ -0,0 +1,31 @@
|
||||
+package io.papermc.paper.entity;
|
||||
+
|
||||
+import org.bukkit.Sound;
|
||||
+import org.bukkit.craftbukkit.CraftSound;
|
||||
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
+import org.bukkit.inventory.ItemStack;
|
||||
+
|
||||
+public interface PaperBucketable extends Bucketable {
|
||||
+
|
||||
+ net.minecraft.world.entity.animal.Bucketable getHandle();
|
||||
+
|
||||
+ @Override
|
||||
+ default boolean isFromBucket() {
|
||||
+ return this.getHandle().fromBucket();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default void setFromBucket(boolean fromBucket) {
|
||||
+ this.getHandle().setFromBucket(fromBucket);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default ItemStack getBaseBucketItem() {
|
||||
+ return CraftItemStack.asBukkitCopy(this.getHandle().getBucketItemStack());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default Sound getPickupSound() {
|
||||
+ return CraftSound.minecraftToBukkit(this.getHandle().getPickupSound());
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAxolotl.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAxolotl.java
|
||||
index e730292edca4624400bdb89d555922c5f61db7a5..cbfca242f820d238b112f8ce64e9de8398c48a1c 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAxolotl.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAxolotl.java
|
||||
@@ -4,7 +4,7 @@ import com.google.common.base.Preconditions;
|
||||
import org.bukkit.craftbukkit.CraftServer;
|
||||
import org.bukkit.entity.Axolotl;
|
||||
|
||||
-public class CraftAxolotl extends CraftAnimals implements Axolotl {
|
||||
+public class CraftAxolotl extends CraftAnimals implements Axolotl, io.papermc.paper.entity.PaperBucketable { // Paper - Bucketable API
|
||||
|
||||
public CraftAxolotl(CraftServer server, net.minecraft.world.entity.animal.axolotl.Axolotl entity) {
|
||||
super(server, entity);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFish.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFish.java
|
||||
index da5150f4ca0397bf10053aab0c3ff18af5bc3f3c..eb10f94d5ed8ca89d3786138647dd43357609a6c 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFish.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFish.java
|
||||
@@ -4,7 +4,7 @@ import net.minecraft.world.entity.animal.AbstractFish;
|
||||
import org.bukkit.craftbukkit.CraftServer;
|
||||
import org.bukkit.entity.Fish;
|
||||
|
||||
-public class CraftFish extends CraftWaterMob implements Fish {
|
||||
+public class CraftFish extends CraftWaterMob implements Fish, io.papermc.paper.entity.PaperBucketable { // Paper - Bucketable API
|
||||
|
||||
public CraftFish(CraftServer server, AbstractFish entity) {
|
||||
super(server, entity);
|
76
patches/server/0640-Validate-usernames.patch
Normal file
76
patches/server/0640-Validate-usernames.patch
Normal file
|
@ -0,0 +1,76 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Sat, 1 Jan 2022 05:19:37 -0800
|
||||
Subject: [PATCH] Validate usernames
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
index 1e4b288f20153ce0c91fabf164c5c8320c90ba7d..cb5dd77892283a1aaec45434fb99bb7f08ee5394 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
@@ -90,6 +90,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
|
||||
private final String serverId;
|
||||
private final boolean transferred;
|
||||
private ServerPlayer player; // CraftBukkit
|
||||
+ public boolean iKnowThisMayNotBeTheBestIdeaButPleaseDisableUsernameValidation = false; // Paper - username validation overriding
|
||||
|
||||
public ServerLoginPacketListenerImpl(MinecraftServer server, Connection connection, boolean transferred) {
|
||||
this.state = ServerLoginPacketListenerImpl.State.HELLO;
|
||||
@@ -171,7 +172,13 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
|
||||
@Override
|
||||
public void handleHello(ServerboundHelloPacket packet) {
|
||||
Validate.validState(this.state == ServerLoginPacketListenerImpl.State.HELLO, "Unexpected hello packet", new Object[0]);
|
||||
- Validate.validState(StringUtil.isValidPlayerName(packet.name()), "Invalid characters in username", new Object[0]);
|
||||
+ // Paper start - Validate usernames
|
||||
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode()
|
||||
+ && io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.performUsernameValidation
|
||||
+ && !this.iKnowThisMayNotBeTheBestIdeaButPleaseDisableUsernameValidation) {
|
||||
+ Validate.validState(StringUtil.isReasonablePlayerName(packet.name()), "Invalid characters in username", new Object[0]);
|
||||
+ }
|
||||
+ // Paper end - Validate usernames
|
||||
this.requestedUsername = packet.name();
|
||||
GameProfile gameprofile = this.server.getSingleplayerProfile();
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
index 1b6540ae28d73501c59581b1864f0e01ab53e365..f34cad30c982f2bb563f0deab030111720858fa8 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
@@ -628,7 +628,7 @@ public abstract class PlayerList {
|
||||
|
||||
for (int i = 0; i < this.players.size(); ++i) {
|
||||
entityplayer = (ServerPlayer) this.players.get(i);
|
||||
- if (entityplayer.getUUID().equals(uuid)) {
|
||||
+ if (entityplayer.getUUID().equals(uuid) || (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode() && entityplayer.getGameProfile().getName().equalsIgnoreCase(gameprofile.getName()))) { // Paper - validate usernames
|
||||
list.add(entityplayer);
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/util/StringUtil.java b/src/main/java/net/minecraft/util/StringUtil.java
|
||||
index e588bd7ef0616dc88ce4c0feeeabadc29dcaa550..6c33002dc8bbb3759c3156302ab7d1f26ce5e8ee 100644
|
||||
--- a/src/main/java/net/minecraft/util/StringUtil.java
|
||||
+++ b/src/main/java/net/minecraft/util/StringUtil.java
|
||||
@@ -67,6 +67,25 @@ public class StringUtil {
|
||||
return name.length() <= 16 && name.chars().filter(c -> c <= 32 || c >= 127).findAny().isEmpty();
|
||||
}
|
||||
|
||||
+ // Paper start - Username validation
|
||||
+ public static boolean isReasonablePlayerName(final String name) {
|
||||
+ if (name.isEmpty() || name.length() > 16) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ for (int i = 0, len = name.length(); i < len; ++i) {
|
||||
+ final char c = name.charAt(i);
|
||||
+ if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || (c == '_' || c == '.')) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+ }
|
||||
+ // Paper end - Username validation
|
||||
+
|
||||
public static String filterText(String string) {
|
||||
return filterText(string, false);
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Brokkonaut <hannos17@gmx.de>
|
||||
Date: Sat, 18 Dec 2021 08:26:55 +0100
|
||||
Subject: [PATCH] Make water animal spawn height configurable
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/WaterAnimal.java b/src/main/java/net/minecraft/world/entity/animal/WaterAnimal.java
|
||||
index 6a8a90059dcc524a0724264c8d604bf39228a650..8c4532a250f8679d729a35c17e9b5bd339264450 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/WaterAnimal.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/WaterAnimal.java
|
||||
@@ -70,6 +70,10 @@ public abstract class WaterAnimal extends PathfinderMob {
|
||||
) {
|
||||
int i = world.getSeaLevel();
|
||||
int j = i - 13;
|
||||
+ // Paper start - Make water animal spawn height configurable
|
||||
+ i = world.getMinecraftWorld().paperConfig().entities.spawning.wateranimalSpawnHeight.maximum.or(i);
|
||||
+ j = world.getMinecraftWorld().paperConfig().entities.spawning.wateranimalSpawnHeight.minimum.or(j);
|
||||
+ // Paper end - Make water animal spawn height configurable
|
||||
return pos.getY() >= j && pos.getY() <= i && world.getFluidState(pos.below()).is(FluidTags.WATER) && world.getBlockState(pos.above()).is(Blocks.WATER);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,177 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
|
||||
Date: Thu, 6 Jan 2022 15:59:06 -0800
|
||||
Subject: [PATCH] Expose vanilla BiomeProvider from WorldInfo
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 7e1b74547c691de5fa2fac6e515394e267c57036..15382d7da69967c50007f136e9d17dd2f81166e3 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -627,7 +627,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
List<CustomSpawner> list = ImmutableList.of(new PhantomSpawner(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(iworlddataserver));
|
||||
LevelStem worlddimension = (LevelStem) dimensions.getValue(dimensionKey);
|
||||
|
||||
- org.bukkit.generator.WorldInfo worldInfo = new org.bukkit.craftbukkit.generator.CraftWorldInfo(iworlddataserver, worldSession, org.bukkit.World.Environment.getEnvironment(dimension), worlddimension.type().value());
|
||||
+ org.bukkit.generator.WorldInfo worldInfo = new org.bukkit.craftbukkit.generator.CraftWorldInfo(iworlddataserver, worldSession, org.bukkit.World.Environment.getEnvironment(dimension), worlddimension.type().value(), worlddimension.generator(), this.registryAccess()); // Paper - Expose vanilla BiomeProvider from WorldInfo
|
||||
if (biomeProvider == null && gen != null) {
|
||||
biomeProvider = gen.getDefaultBiomeProvider(worldInfo);
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 0fbd077c1d3dddc97c8c99effa936470562b02a4..f46393f68ce7ff45302d6aef78b33b18fd10339b 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -359,7 +359,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
this.serverLevelData.setWorld(this);
|
||||
|
||||
if (biomeProvider != null) {
|
||||
- BiomeSource worldChunkManager = new CustomWorldChunkManager(this.getWorld(), biomeProvider, this.server.registryAccess().lookupOrThrow(Registries.BIOME));
|
||||
+ BiomeSource worldChunkManager = new CustomWorldChunkManager(this.getWorld(), biomeProvider, this.server.registryAccess().lookupOrThrow(Registries.BIOME), chunkgenerator.getBiomeSource()); // Paper - add vanillaBiomeProvider
|
||||
if (chunkgenerator instanceof NoiseBasedChunkGenerator cga) {
|
||||
chunkgenerator = new NoiseBasedChunkGenerator(worldChunkManager, cga.settings);
|
||||
} else if (chunkgenerator instanceof FlatLevelSource cpf) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index f69504676d2f48f3778f489ec1e08e2b3dec85cc..d30c1e853bb2e27922a00d890dffca153cdcbe97 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -1311,7 +1311,7 @@ public final class CraftServer implements Server {
|
||||
List<CustomSpawner> list = ImmutableList.of(new PhantomSpawner(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(worlddata));
|
||||
LevelStem worlddimension = iregistry.getValue(actualDimension);
|
||||
|
||||
- WorldInfo worldInfo = new CraftWorldInfo(worlddata, worldSession, creator.environment(), worlddimension.type().value());
|
||||
+ WorldInfo worldInfo = new CraftWorldInfo(worlddata, worldSession, creator.environment(), worlddimension.type().value(), worlddimension.generator(), this.getHandle().getServer().registryAccess()); // Paper - Expose vanilla BiomeProvider from WorldInfo
|
||||
if (biomeProvider == null && generator != null) {
|
||||
biomeProvider = generator.getDefaultBiomeProvider(worldInfo);
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
index 0e5b673cee93525c1ba87d5b5e48def351ce8db8..7dc167950021371b5cf8a7e1e38f013220e1c8a6 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
@@ -216,6 +216,39 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
public int getPlayerCount() {
|
||||
return world.players().size();
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public BiomeProvider vanillaBiomeProvider() {
|
||||
+ net.minecraft.server.level.ServerChunkCache serverCache = this.getHandle().chunkSource;
|
||||
+
|
||||
+ final net.minecraft.world.level.chunk.ChunkGenerator gen = serverCache.getGenerator();
|
||||
+ net.minecraft.world.level.biome.BiomeSource biomeSource;
|
||||
+ if (gen instanceof org.bukkit.craftbukkit.generator.CustomChunkGenerator custom) {
|
||||
+ biomeSource = custom.getDelegate().getBiomeSource();
|
||||
+ } else {
|
||||
+ biomeSource = gen.getBiomeSource();
|
||||
+ }
|
||||
+ if (biomeSource instanceof org.bukkit.craftbukkit.generator.CustomWorldChunkManager customBiomeSource) {
|
||||
+ biomeSource = customBiomeSource.vanillaBiomeSource;
|
||||
+ }
|
||||
+ final net.minecraft.world.level.biome.BiomeSource finalBiomeSource = biomeSource;
|
||||
+ final net.minecraft.world.level.biome.Climate.Sampler sampler = serverCache.randomState().sampler();
|
||||
+
|
||||
+ final List<Biome> possibleBiomes = finalBiomeSource.possibleBiomes().stream()
|
||||
+ .map(CraftBiome::minecraftHolderToBukkit)
|
||||
+ .toList();
|
||||
+ return new BiomeProvider() {
|
||||
+ @Override
|
||||
+ public Biome getBiome(final org.bukkit.generator.WorldInfo worldInfo, final int x, final int y, final int z) {
|
||||
+ return CraftBiome.minecraftHolderToBukkit(finalBiomeSource.getNoiseBiome(x >> 2, y >> 2, z >> 2, sampler));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public List<Biome> getBiomes(final org.bukkit.generator.WorldInfo worldInfo) {
|
||||
+ return possibleBiomes;
|
||||
+ }
|
||||
+ };
|
||||
+ }
|
||||
// Paper end
|
||||
|
||||
private static final Random rand = new Random();
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftWorldInfo.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftWorldInfo.java
|
||||
index 5d655d6cd3e23e0287069f8bdf77601487e862fd..c81455a4ee9a3185f125ebf8cec325f4ed2e501d 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/generator/CraftWorldInfo.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftWorldInfo.java
|
||||
@@ -17,8 +17,14 @@ public class CraftWorldInfo implements WorldInfo {
|
||||
private final long seed;
|
||||
private final int minHeight;
|
||||
private final int maxHeight;
|
||||
+ // Paper start
|
||||
+ private final net.minecraft.world.level.chunk.ChunkGenerator vanillaChunkGenerator;
|
||||
+ private final net.minecraft.core.RegistryAccess.Frozen registryAccess;
|
||||
|
||||
- public CraftWorldInfo(ServerLevelData worldDataServer, LevelStorageSource.LevelStorageAccess session, World.Environment environment, DimensionType dimensionManager) {
|
||||
+ public CraftWorldInfo(PrimaryLevelData worldDataServer, LevelStorageSource.LevelStorageAccess session, World.Environment environment, DimensionType dimensionManager, net.minecraft.world.level.chunk.ChunkGenerator chunkGenerator, net.minecraft.core.RegistryAccess.Frozen registryAccess) {
|
||||
+ this.registryAccess = registryAccess;
|
||||
+ this.vanillaChunkGenerator = chunkGenerator;
|
||||
+ // Paper end
|
||||
this.name = worldDataServer.getLevelName();
|
||||
this.uuid = WorldUUID.getUUID(session.levelDirectory.path().toFile());
|
||||
this.environment = environment;
|
||||
@@ -27,15 +33,6 @@ public class CraftWorldInfo implements WorldInfo {
|
||||
this.maxHeight = dimensionManager.minY() + dimensionManager.height();
|
||||
}
|
||||
|
||||
- public CraftWorldInfo(String name, UUID uuid, World.Environment environment, long seed, int minHeight, int maxHeight) {
|
||||
- this.name = name;
|
||||
- this.uuid = uuid;
|
||||
- this.environment = environment;
|
||||
- this.seed = seed;
|
||||
- this.minHeight = minHeight;
|
||||
- this.maxHeight = maxHeight;
|
||||
- }
|
||||
-
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.name;
|
||||
@@ -65,4 +62,34 @@ public class CraftWorldInfo implements WorldInfo {
|
||||
public int getMaxHeight() {
|
||||
return this.maxHeight;
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public org.bukkit.generator.BiomeProvider vanillaBiomeProvider() {
|
||||
+ final net.minecraft.world.level.levelgen.RandomState randomState;
|
||||
+ if (vanillaChunkGenerator instanceof net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator noiseBasedChunkGenerator) {
|
||||
+ randomState = net.minecraft.world.level.levelgen.RandomState.create(noiseBasedChunkGenerator.generatorSettings().value(),
|
||||
+ registryAccess.lookupOrThrow(net.minecraft.core.registries.Registries.NOISE), getSeed());
|
||||
+ } else {
|
||||
+ randomState = net.minecraft.world.level.levelgen.RandomState.create(net.minecraft.world.level.levelgen.NoiseGeneratorSettings.dummy(),
|
||||
+ registryAccess.lookupOrThrow(net.minecraft.core.registries.Registries.NOISE), getSeed());
|
||||
+ }
|
||||
+
|
||||
+ final java.util.List<org.bukkit.block.Biome> possibleBiomes = CraftWorldInfo.this.vanillaChunkGenerator.getBiomeSource().possibleBiomes().stream()
|
||||
+ .map(biome -> org.bukkit.craftbukkit.block.CraftBiome.minecraftHolderToBukkit(biome))
|
||||
+ .toList();
|
||||
+ return new org.bukkit.generator.BiomeProvider() {
|
||||
+ @Override
|
||||
+ public org.bukkit.block.Biome getBiome(final WorldInfo worldInfo, final int x, final int y, final int z) {
|
||||
+ return org.bukkit.craftbukkit.block.CraftBiome.minecraftHolderToBukkit(
|
||||
+ CraftWorldInfo.this.vanillaChunkGenerator.getBiomeSource().getNoiseBiome(x >> 2, y >> 2, z >> 2, randomState.sampler()));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public java.util.List<org.bukkit.block.Biome> getBiomes(final org.bukkit.generator.WorldInfo worldInfo) {
|
||||
+ return possibleBiomes;
|
||||
+ }
|
||||
+ };
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CustomWorldChunkManager.java b/src/main/java/org/bukkit/craftbukkit/generator/CustomWorldChunkManager.java
|
||||
index 0063c4c17d05a77adf81164fb9307a29860cbe12..0bac128d6faff0063b03f595b82deea78d1ae161 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/generator/CustomWorldChunkManager.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/generator/CustomWorldChunkManager.java
|
||||
@@ -31,7 +31,11 @@ public class CustomWorldChunkManager extends BiomeSource {
|
||||
return biomeBases;
|
||||
}
|
||||
|
||||
- public CustomWorldChunkManager(WorldInfo worldInfo, BiomeProvider biomeProvider, Registry<net.minecraft.world.level.biome.Biome> registry) {
|
||||
+ // Paper start - add vanillaBiomeProvider
|
||||
+ public final BiomeSource vanillaBiomeSource;
|
||||
+ public CustomWorldChunkManager(WorldInfo worldInfo, BiomeProvider biomeProvider, Registry<net.minecraft.world.level.biome.Biome> registry, BiomeSource vanillaBiomeSource) {
|
||||
+ this.vanillaBiomeSource = vanillaBiomeSource;
|
||||
+ // Paper end - add vanillaBiomeProvider
|
||||
this.worldInfo = worldInfo;
|
||||
this.biomeProvider = biomeProvider;
|
||||
this.registry = registry;
|
|
@ -0,0 +1,28 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sun, 2 Jan 2022 22:34:51 -0800
|
||||
Subject: [PATCH] Add config option for worlds affected by time cmd
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/commands/TimeCommand.java b/src/main/java/net/minecraft/server/commands/TimeCommand.java
|
||||
index db9317f813244c3cd895bdf9c4eb2218f68c4f1d..44fcd43a466fb47d31ab05e44bafbef3c4cae63f 100644
|
||||
--- a/src/main/java/net/minecraft/server/commands/TimeCommand.java
|
||||
+++ b/src/main/java/net/minecraft/server/commands/TimeCommand.java
|
||||
@@ -53,7 +53,7 @@ public class TimeCommand {
|
||||
}
|
||||
|
||||
public static int setTime(CommandSourceStack source, int time) {
|
||||
- Iterator iterator = com.google.common.collect.Iterators.singletonIterator(source.getLevel()); // CraftBukkit - SPIGOT-6496: Only set the time for the world the command originates in
|
||||
+ Iterator iterator = io.papermc.paper.configuration.GlobalConfiguration.get().commands.timeCommandAffectsAllWorlds ? source.getServer().getAllLevels().iterator() : com.google.common.collect.Iterators.singletonIterator(source.getLevel()); // CraftBukkit - SPIGOT-6496: Only set the time for the world the command originates in // Paper - add config option for spigot's change
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
ServerLevel worldserver = (ServerLevel) iterator.next();
|
||||
@@ -74,7 +74,7 @@ public class TimeCommand {
|
||||
}
|
||||
|
||||
public static int addTime(CommandSourceStack source, int time) {
|
||||
- Iterator iterator = com.google.common.collect.Iterators.singletonIterator(source.getLevel()); // CraftBukkit - SPIGOT-6496: Only set the time for the world the command originates in
|
||||
+ Iterator iterator = io.papermc.paper.configuration.GlobalConfiguration.get().commands.timeCommandAffectsAllWorlds ? source.getServer().getAllLevels().iterator() : com.google.common.collect.Iterators.singletonIterator(source.getLevel()); // CraftBukkit - SPIGOT-6496: Only set the time for the world the command originates in // Paper - add config option for spigot's change
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
ServerLevel worldserver = (ServerLevel) iterator.next();
|
|
@ -0,0 +1,18 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: u9g <winworkswow@gmail.com>
|
||||
Date: Mon, 3 Jan 2022 23:32:42 -0500
|
||||
Subject: [PATCH] Add missing IAE check for PersistentDataContainer#has
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java
|
||||
index 3001bb0e3d4af9b16645a0136093db594b89ab01..984e988a47aa55a3fd92198e379d0f92f511daef 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java
|
||||
@@ -57,6 +57,7 @@ public class CraftPersistentDataContainer implements PersistentDataContainer {
|
||||
|
||||
@Override
|
||||
public boolean has(NamespacedKey key) {
|
||||
+ Preconditions.checkArgument(key != null, "The provided key for the custom value was null"); // Paper
|
||||
return this.customDataTags.get(key.toString()) != null;
|
||||
}
|
||||
|
125
patches/server/0645-Multiple-Entries-with-Scoreboards.patch
Normal file
125
patches/server/0645-Multiple-Entries-with-Scoreboards.patch
Normal file
|
@ -0,0 +1,125 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Cryptite <cryptite@gmail.com>
|
||||
Date: Tue, 21 Sep 2021 18:17:33 -0500
|
||||
Subject: [PATCH] Multiple Entries with Scoreboards
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java
|
||||
index 1d0c473442b5c72245c356054440323e3c5d4711..f8fe125f12a6a00899d1d6acfa448be882b81557 100644
|
||||
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java
|
||||
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java
|
||||
@@ -58,6 +58,11 @@ public class ClientboundSetPlayerTeamPacket implements Packet<ClientGamePacketLi
|
||||
);
|
||||
}
|
||||
|
||||
+ // Paper start - Multiple Entries with Scoreboards
|
||||
+ public static ClientboundSetPlayerTeamPacket createMultiplePlayerPacket(PlayerTeam team, Collection<String> players, ClientboundSetPlayerTeamPacket.Action operation) {
|
||||
+ return new ClientboundSetPlayerTeamPacket(team.getName(), operation == ClientboundSetPlayerTeamPacket.Action.ADD ? 3 : 4, Optional.empty(), players);
|
||||
+ }
|
||||
+ // Paper end - Multiple Entries with Scoreboards
|
||||
private ClientboundSetPlayerTeamPacket(RegistryFriendlyByteBuf buf) {
|
||||
this.name = buf.readUtf();
|
||||
this.method = buf.readByte();
|
||||
diff --git a/src/main/java/net/minecraft/server/ServerScoreboard.java b/src/main/java/net/minecraft/server/ServerScoreboard.java
|
||||
index f1e72463ca11658390f662efbaf3e551c05fe799..8fd4d8ffcc9e1a0fcf83730d26c3bb9bef0f73f2 100644
|
||||
--- a/src/main/java/net/minecraft/server/ServerScoreboard.java
|
||||
+++ b/src/main/java/net/minecraft/server/ServerScoreboard.java
|
||||
@@ -106,6 +106,25 @@ public class ServerScoreboard extends Scoreboard {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start - Multiple Entries with Scoreboards
|
||||
+ public boolean addPlayersToTeam(java.util.Collection<String> players, PlayerTeam team) {
|
||||
+ boolean anyAdded = false;
|
||||
+ for (String playerName : players) {
|
||||
+ if (super.addPlayerToTeam(playerName, team)) {
|
||||
+ anyAdded = true;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (anyAdded) {
|
||||
+ this.broadcastAll(ClientboundSetPlayerTeamPacket.createMultiplePlayerPacket(team, players, ClientboundSetPlayerTeamPacket.Action.ADD));
|
||||
+ this.setDirty();
|
||||
+ return true;
|
||||
+ } else {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Multiple Entries with Scoreboards
|
||||
+
|
||||
@Override
|
||||
public void removePlayerFromTeam(String scoreHolderName, PlayerTeam team) {
|
||||
super.removePlayerFromTeam(scoreHolderName, team);
|
||||
@@ -113,6 +132,17 @@ public class ServerScoreboard extends Scoreboard {
|
||||
this.setDirty();
|
||||
}
|
||||
|
||||
+ // Paper start - Multiple Entries with Scoreboards
|
||||
+ public void removePlayersFromTeam(java.util.Collection<String> players, PlayerTeam team) {
|
||||
+ for (String playerName : players) {
|
||||
+ super.removePlayerFromTeam(playerName, team);
|
||||
+ }
|
||||
+
|
||||
+ this.broadcastAll(ClientboundSetPlayerTeamPacket.createMultiplePlayerPacket(team, players, ClientboundSetPlayerTeamPacket.Action.REMOVE));
|
||||
+ this.setDirty();
|
||||
+ }
|
||||
+ // Paper end - Multiple Entries with Scoreboards
|
||||
+
|
||||
@Override
|
||||
public void onObjectiveAdded(Objective objective) {
|
||||
super.onObjectiveAdded(objective);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java
|
||||
index 27219bf2f16aed64c78623d44c3cc84aa9f47065..2b335c750ce5f9ccc2651a8701497ca9b8f46704 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java
|
||||
@@ -229,6 +229,21 @@ final class CraftTeam extends CraftScoreboardComponent implements Team {
|
||||
scoreboard.board.addPlayerToTeam(entry, this.team);
|
||||
}
|
||||
|
||||
+ // Paper start - Multiple Entries with Scoreboards
|
||||
+ @Override
|
||||
+ public void addEntities(java.util.Collection<org.bukkit.entity.Entity> entities) throws IllegalStateException, IllegalArgumentException {
|
||||
+ this.addEntries(entities.stream().map(entity -> ((org.bukkit.craftbukkit.entity.CraftEntity) entity).getHandle().getScoreboardName()).toList());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void addEntries(java.util.Collection<String> entries) throws IllegalStateException, IllegalArgumentException {
|
||||
+ Preconditions.checkArgument(entries != null, "Entries cannot be null");
|
||||
+ CraftScoreboard scoreboard = this.checkState();
|
||||
+
|
||||
+ ((net.minecraft.server.ServerScoreboard) scoreboard.board).addPlayersToTeam(entries, this.team);
|
||||
+ }
|
||||
+ // Paper end - Multiple Entries with Scoreboards
|
||||
+
|
||||
@Override
|
||||
public boolean removePlayer(OfflinePlayer player) {
|
||||
Preconditions.checkArgument(player != null, "OfflinePlayer cannot be null");
|
||||
@@ -248,6 +263,28 @@ final class CraftTeam extends CraftScoreboardComponent implements Team {
|
||||
return true;
|
||||
}
|
||||
|
||||
+ // Paper start - Multiple Entries with Scoreboards
|
||||
+ @Override
|
||||
+ public boolean removeEntities(java.util.Collection<org.bukkit.entity.Entity> entities) throws IllegalStateException, IllegalArgumentException {
|
||||
+ return this.removeEntries(entities.stream().map(entity -> ((org.bukkit.craftbukkit.entity.CraftEntity) entity).getHandle().getScoreboardName()).toList());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean removeEntries(java.util.Collection<String> entries) throws IllegalStateException, IllegalArgumentException {
|
||||
+ Preconditions.checkArgument(entries != null, "Entry cannot be null");
|
||||
+ CraftScoreboard scoreboard = this.checkState();
|
||||
+
|
||||
+ for (String entry : entries) {
|
||||
+ if (this.team.getPlayers().contains(entry)) {
|
||||
+ ((net.minecraft.server.ServerScoreboard) scoreboard.board).removePlayersFromTeam(entries, this.team);
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Paper end - Multiple Entries with Scoreboards
|
||||
+
|
||||
@Override
|
||||
public boolean hasPlayer(OfflinePlayer player) throws IllegalArgumentException, IllegalStateException {
|
||||
Preconditions.checkArgument(player != null, "OfflinePlayer cannot be null");
|
39
patches/server/0646-Reset-placed-block-on-exception.patch
Normal file
39
patches/server/0646-Reset-placed-block-on-exception.patch
Normal file
|
@ -0,0 +1,39 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Nassim Jahnke <nassim@njahnke.dev>
|
||||
Date: Fri, 7 Jan 2022 11:45:15 +0100
|
||||
Subject: [PATCH] Reset placed block on exception
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/item/BlockItem.java b/src/main/java/net/minecraft/world/item/BlockItem.java
|
||||
index 407f5db0a4b3884440bc49bf4f00d9c035899e86..44cc12a3338b5f0448c88192c8674cd36531db34 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/BlockItem.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/BlockItem.java
|
||||
@@ -71,6 +71,7 @@ public class BlockItem extends Item {
|
||||
if (this instanceof PlaceOnWaterBlockItem || this instanceof SolidBucketItem) {
|
||||
blockstate = org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockactioncontext1.getLevel(), blockactioncontext1.getClickedPos());
|
||||
}
|
||||
+ final org.bukkit.block.BlockState oldBlockstate = blockstate != null ? blockstate : org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockactioncontext1.getLevel(), blockactioncontext1.getClickedPos()); // Paper - Reset placed block on exception
|
||||
// CraftBukkit end
|
||||
|
||||
if (iblockdata == null) {
|
||||
@@ -86,8 +87,20 @@ public class BlockItem extends Item {
|
||||
|
||||
if (iblockdata1.is(iblockdata.getBlock())) {
|
||||
iblockdata1 = this.updateBlockStateFromTag(blockposition, world, itemstack, iblockdata1);
|
||||
+ // Paper start - Reset placed block on exception
|
||||
+ try {
|
||||
this.updateCustomBlockEntityTag(blockposition, world, entityhuman, itemstack, iblockdata1);
|
||||
BlockItem.updateBlockEntityComponents(world, blockposition, itemstack);
|
||||
+ } catch (Exception e) {
|
||||
+ oldBlockstate.update(true, false);
|
||||
+ if (entityhuman instanceof ServerPlayer player) {
|
||||
+ org.apache.logging.log4j.LogManager.getLogger().error("Player {} tried placing invalid block", player.getScoreboardName(), e);
|
||||
+ player.getBukkitEntity().kickPlayer("Packet processing error");
|
||||
+ return InteractionResult.FAIL;
|
||||
+ }
|
||||
+ throw e; // Rethrow exception if not placed by a player
|
||||
+ }
|
||||
+ // Paper end - Reset placed block on exception
|
||||
iblockdata1.getBlock().setPlacedBy(world, blockposition, iblockdata1, entityhuman, itemstack);
|
||||
// CraftBukkit start
|
||||
if (blockstate != null) {
|
|
@ -0,0 +1,35 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Doc <nachito94@msn.com>
|
||||
Date: Mon, 2 Aug 2021 11:24:39 -0400
|
||||
Subject: [PATCH] Add configurable height for slime spawn
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/Slime.java b/src/main/java/net/minecraft/world/entity/monster/Slime.java
|
||||
index 129f0cbc0469cb2804db6088b53347d88d91f4eb..72346a7e5269c91e3143933ac37e65ad9639b791 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Slime.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Slime.java
|
||||
@@ -340,7 +340,11 @@ public class Slime extends Mob implements Enemy {
|
||||
return checkMobSpawnRules(type, world, spawnReason, pos, random);
|
||||
}
|
||||
|
||||
- if (world.getBiome(pos).is(BiomeTags.ALLOWS_SURFACE_SLIME_SPAWNS) && pos.getY() > 50 && pos.getY() < 70 && random.nextFloat() < 0.5F && random.nextFloat() < world.getMoonBrightness() && world.getMaxLocalRawBrightness(pos) <= random.nextInt(8)) {
|
||||
+ // Paper start - Replace rules for Height in Swamp Biome
|
||||
+ final double maxHeightSwamp = world.getMinecraftWorld().paperConfig().entities.spawning.slimeSpawnHeight.surfaceBiome.maximum;
|
||||
+ final double minHeightSwamp = world.getMinecraftWorld().paperConfig().entities.spawning.slimeSpawnHeight.surfaceBiome.minimum;
|
||||
+ if (world.getBiome(pos).is(BiomeTags.ALLOWS_SURFACE_SLIME_SPAWNS) && pos.getY() > minHeightSwamp && pos.getY() < maxHeightSwamp && random.nextFloat() < 0.5F && random.nextFloat() < world.getMoonBrightness() && world.getMaxLocalRawBrightness(pos) <= random.nextInt(8)) {
|
||||
+ // Paper end - Replace rules for Height in Swamp Biome
|
||||
return checkMobSpawnRules(type, world, spawnReason, pos, random);
|
||||
}
|
||||
|
||||
@@ -351,7 +355,10 @@ public class Slime extends Mob implements Enemy {
|
||||
ChunkPos chunkcoordintpair = new ChunkPos(pos);
|
||||
boolean flag = world.getMinecraftWorld().paperConfig().entities.spawning.allChunksAreSlimeChunks || WorldgenRandom.seedSlimeChunk(chunkcoordintpair.x, chunkcoordintpair.z, ((WorldGenLevel) world).getSeed(), world.getMinecraftWorld().spigotConfig.slimeSeed).nextInt(10) == 0; // Spigot // Paper
|
||||
|
||||
- if (random.nextInt(10) == 0 && flag && pos.getY() < 40) {
|
||||
+ // Paper start - Replace rules for Height in Slime Chunks
|
||||
+ final double maxHeightSlimeChunk = world.getMinecraftWorld().paperConfig().entities.spawning.slimeSpawnHeight.slimeChunk.maximum;
|
||||
+ if (random.nextInt(10) == 0 && flag && pos.getY() < maxHeightSlimeChunk) {
|
||||
+ // Paper end - Replace rules for Height in Slime Chunks
|
||||
return checkMobSpawnRules(type, world, spawnReason, pos, random);
|
||||
}
|
||||
}
|
32
patches/server/0648-Fix-xp-reward-for-baby-zombies.patch
Normal file
32
patches/server/0648-Fix-xp-reward-for-baby-zombies.patch
Normal file
|
@ -0,0 +1,32 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sun, 16 Jan 2022 10:34:02 -0800
|
||||
Subject: [PATCH] Fix xp reward for baby zombies
|
||||
|
||||
The field that tracks the xpReward was not
|
||||
getting reset if the death was cancelled
|
||||
so this resets it after each call to
|
||||
Zombie#getExperienceReward
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
|
||||
index 6dc9fc3451edec01f11f526c05d84138c46a3a8e..17974f85d3c1db549ea11e8809954cd9d2af063e 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
|
||||
@@ -174,11 +174,16 @@ public class Zombie extends Monster {
|
||||
|
||||
@Override
|
||||
protected int getBaseExperienceReward(ServerLevel world) {
|
||||
+ final int previousReward = this.xpReward; // Paper - store previous value to reset after calculating XP reward
|
||||
if (this.isBaby()) {
|
||||
this.xpReward = (int) ((double) this.xpReward * 2.5D);
|
||||
}
|
||||
|
||||
- return super.getBaseExperienceReward(world);
|
||||
+ // Paper start - store previous value to reset after calculating XP reward
|
||||
+ int reward = super.getBaseExperienceReward(world);
|
||||
+ this.xpReward = previousReward;
|
||||
+ return reward;
|
||||
+ // Paper end - store previous value to reset after calculating XP reward
|
||||
}
|
||||
|
||||
@Override
|
|
@ -0,0 +1,62 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Brody Beckwith <brody@beckwith.dev>
|
||||
Date: Fri, 14 Jan 2022 00:41:11 -0500
|
||||
Subject: [PATCH] Multi Block Change API Implementation
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java
|
||||
index 926ff9be3d9e3f5d620e4c7ccb22b9f64865ff8c..1a37654aff9a9c86c9f7af10a1cf721371f0c5ec 100644
|
||||
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java
|
||||
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java
|
||||
@@ -62,6 +62,14 @@ public class ClientboundSectionBlocksUpdatePacket implements Packet<ClientGamePa
|
||||
|
||||
}
|
||||
|
||||
+ // Paper start - Multi Block Change API
|
||||
+ public ClientboundSectionBlocksUpdatePacket(SectionPos sectionPos, it.unimi.dsi.fastutil.shorts.Short2ObjectMap<BlockState> blockChanges) {
|
||||
+ this.sectionPos = sectionPos;
|
||||
+ this.positions = blockChanges.keySet().toShortArray();
|
||||
+ this.states = blockChanges.values().toArray(new BlockState[0]);
|
||||
+ }
|
||||
+ // Paper end - Multi Block Change API
|
||||
+
|
||||
private void write(FriendlyByteBuf buf) {
|
||||
buf.writeLong(this.sectionPos.asLong());
|
||||
buf.writeVarInt(this.positions.length);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index b3efe7391b7e43327bcca419efe72811574c0664..2347e260780d4703cff01b84a7971861fd924b20 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -943,6 +943,32 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
this.getHandle().connection.send(packet);
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public void sendMultiBlockChange(final Map<? extends io.papermc.paper.math.Position, BlockData> blockChanges) {
|
||||
+ if (this.getHandle().connection == null) return;
|
||||
+
|
||||
+ Map<SectionPos, it.unimi.dsi.fastutil.shorts.Short2ObjectMap<net.minecraft.world.level.block.state.BlockState>> sectionMap = new HashMap<>();
|
||||
+
|
||||
+ for (Map.Entry<? extends io.papermc.paper.math.Position, BlockData> entry : blockChanges.entrySet()) {
|
||||
+ BlockData blockData = entry.getValue();
|
||||
+ BlockPos blockPos = io.papermc.paper.util.MCUtil.toBlockPos(entry.getKey());
|
||||
+ SectionPos sectionPos = SectionPos.of(blockPos);
|
||||
+
|
||||
+ it.unimi.dsi.fastutil.shorts.Short2ObjectMap<net.minecraft.world.level.block.state.BlockState> sectionData = sectionMap.computeIfAbsent(sectionPos, key -> new it.unimi.dsi.fastutil.shorts.Short2ObjectArrayMap<>());
|
||||
+ sectionData.put(SectionPos.sectionRelativePos(blockPos), ((CraftBlockData) blockData).getState());
|
||||
+ }
|
||||
+
|
||||
+ for (Map.Entry<SectionPos, it.unimi.dsi.fastutil.shorts.Short2ObjectMap<net.minecraft.world.level.block.state.BlockState>> entry : sectionMap.entrySet()) {
|
||||
+ SectionPos sectionPos = entry.getKey();
|
||||
+ it.unimi.dsi.fastutil.shorts.Short2ObjectMap<net.minecraft.world.level.block.state.BlockState> blockData = entry.getValue();
|
||||
+
|
||||
+ net.minecraft.network.protocol.game.ClientboundSectionBlocksUpdatePacket packet = new net.minecraft.network.protocol.game.ClientboundSectionBlocksUpdatePacket(sectionPos, blockData);
|
||||
+ this.getHandle().connection.send(packet);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public void sendBlockChanges(Collection<BlockState> blocks) {
|
||||
Preconditions.checkArgument(blocks != null, "blocks must not be null");
|
54
patches/server/0650-Fix-NotePlayEvent.patch
Normal file
54
patches/server/0650-Fix-NotePlayEvent.patch
Normal file
|
@ -0,0 +1,54 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Kieran Wallbanks <kieran.wallbanks@gmail.com>
|
||||
Date: Mon, 21 Jun 2021 14:23:50 +0100
|
||||
Subject: [PATCH] Fix NotePlayEvent
|
||||
|
||||
== AT ==
|
||||
public org.bukkit.craftbukkit.block.data.CraftBlockData toNMS(Ljava/lang/Enum;Ljava/lang/Class;)Ljava/lang/Enum;
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/NoteBlock.java b/src/main/java/net/minecraft/world/level/block/NoteBlock.java
|
||||
index 57e13269367a82ec39c2298b20d7595f61326f47..71fd7a467a4cb89cad8d2541366fd4add9115e04 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/NoteBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/NoteBlock.java
|
||||
@@ -96,11 +96,12 @@ public class NoteBlock extends Block {
|
||||
private void playNote(@Nullable Entity entity, BlockState state, Level world, BlockPos pos) {
|
||||
if (((NoteBlockInstrument) state.getValue(NoteBlock.INSTRUMENT)).worksAboveNoteBlock() || world.getBlockState(pos.above()).isAir()) {
|
||||
// CraftBukkit start
|
||||
- org.bukkit.event.block.NotePlayEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callNotePlayEvent(world, pos, state.getValue(NoteBlock.INSTRUMENT), state.getValue(NoteBlock.NOTE));
|
||||
- if (event.isCancelled()) {
|
||||
- return;
|
||||
- }
|
||||
+ // org.bukkit.event.block.NotePlayEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callNotePlayEvent(world, pos, state.getValue(NoteBlock.INSTRUMENT), state.getValue(NoteBlock.NOTE));
|
||||
+ // if (event.isCancelled()) {
|
||||
+ // return;
|
||||
+ // }
|
||||
// CraftBukkit end
|
||||
+ // Paper - move NotePlayEvent call to fix instrument/note changes; TODO any way to cancel the game event?
|
||||
world.blockEvent(pos, this, 0, 0);
|
||||
world.gameEvent(entity, (Holder) GameEvent.NOTE_BLOCK_PLAY, pos);
|
||||
}
|
||||
@@ -139,10 +140,14 @@ public class NoteBlock extends Block {
|
||||
@Override
|
||||
protected boolean triggerEvent(BlockState state, Level world, BlockPos pos, int type, int data) {
|
||||
NoteBlockInstrument blockpropertyinstrument = (NoteBlockInstrument) state.getValue(NoteBlock.INSTRUMENT);
|
||||
+ // Paper start - move NotePlayEvent call to fix instrument/note changes
|
||||
+ org.bukkit.event.block.NotePlayEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callNotePlayEvent(world, pos, blockpropertyinstrument, state.getValue(NOTE));
|
||||
+ if (event.isCancelled()) return false;
|
||||
+ // Paper end - move NotePlayEvent call to fix instrument/note changes
|
||||
float f;
|
||||
|
||||
if (blockpropertyinstrument.isTunable()) {
|
||||
- int k = (Integer) state.getValue(NoteBlock.NOTE);
|
||||
+ int k = event.getNote().getId(); // Paper - move NotePlayEvent call to fix instrument/note changes
|
||||
|
||||
f = NoteBlock.getPitchFromNote(k);
|
||||
world.addParticle(ParticleTypes.NOTE, (double) pos.getX() + 0.5D, (double) pos.getY() + 1.2D, (double) pos.getZ() + 0.5D, (double) k / 24.0D, 0.0D, 0.0D);
|
||||
@@ -161,7 +166,7 @@ public class NoteBlock extends Block {
|
||||
|
||||
holder = Holder.direct(SoundEvent.createVariableRangeEvent(minecraftkey));
|
||||
} else {
|
||||
- holder = blockpropertyinstrument.getSoundEvent();
|
||||
+ holder = org.bukkit.craftbukkit.block.data.CraftBlockData.toNMS(event.getInstrument(), NoteBlockInstrument.class).getSoundEvent(); // Paper - move NotePlayEvent call to fix instrument/note changes
|
||||
}
|
||||
|
||||
world.playSeededSound((Player) null, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, holder, SoundSource.RECORDS, 3.0F, f, world.random.nextLong());
|
82
patches/server/0651-Freeze-Tick-Lock-API.patch
Normal file
82
patches/server/0651-Freeze-Tick-Lock-API.patch
Normal file
|
@ -0,0 +1,82 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
|
||||
Date: Sun, 26 Dec 2021 20:27:43 -0500
|
||||
Subject: [PATCH] Freeze Tick Lock API
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index 1497c3b79e6dc9ecc270c0fd2003e606f967a56e..a41bb1d80a84f487a8fb6fdefd7ccc7631902d04 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -414,6 +414,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
private org.bukkit.util.Vector origin;
|
||||
@javax.annotation.Nullable
|
||||
private UUID originWorld;
|
||||
+ public boolean freezeLocked = false; // Paper - Freeze Tick Lock API
|
||||
|
||||
public void setOrigin(@javax.annotation.Nonnull Location location) {
|
||||
this.origin = location.toVector();
|
||||
@@ -759,7 +760,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
this.setRemainingFireTicks(this.remainingFireTicks - 1);
|
||||
}
|
||||
|
||||
- if (this.getTicksFrozen() > 0) {
|
||||
+ if (this.getTicksFrozen() > 0 && !freezeLocked) { // Paper - Freeze Tick Lock API
|
||||
this.setTicksFrozen(0);
|
||||
this.level().levelEvent((Player) null, 1009, this.blockPosition, 1);
|
||||
}
|
||||
@@ -2428,6 +2429,9 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
if (fromNetherPortal) {
|
||||
nbttagcompound.putBoolean("Paper.FromNetherPortal", true);
|
||||
}
|
||||
+ if (freezeLocked) {
|
||||
+ nbttagcompound.putBoolean("Paper.FreezeLock", true);
|
||||
+ }
|
||||
// Paper end
|
||||
return nbttagcompound;
|
||||
} catch (Throwable throwable) {
|
||||
@@ -2573,6 +2577,9 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
if (spawnReason == null) {
|
||||
spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT;
|
||||
}
|
||||
+ if (nbt.contains("Paper.FreezeLock")) {
|
||||
+ freezeLocked = nbt.getBoolean("Paper.FreezeLock");
|
||||
+ }
|
||||
// Paper end
|
||||
|
||||
} catch (Throwable throwable) {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index 4db8ac288e59c5f14b260686e55a7d48e2f2791d..6598f119edc5d890dcc9d065478e7c52ac5a5183 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -3611,7 +3611,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
this.calculateEntityAnimation(this instanceof FlyingAnimal);
|
||||
gameprofilerfiller.pop();
|
||||
gameprofilerfiller.push("freezing");
|
||||
- if (!this.level().isClientSide && !this.isDeadOrDying()) {
|
||||
+ if (!this.level().isClientSide && !this.isDeadOrDying() && !this.freezeLocked) { // Paper - Freeze Tick Lock API
|
||||
int i = this.getTicksFrozen();
|
||||
|
||||
if (this.isInPowderSnow && this.canFreeze()) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
index 9693656418210957000add9b6670c4bee67f8462..4e6afa243d6108cb946a8a7cf96c4036a3c2ac0c 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
@@ -324,6 +324,17 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
||||
return this.getHandle().isFullyFrozen();
|
||||
}
|
||||
|
||||
+ // Paper start - Freeze Tick Lock API
|
||||
+ @Override
|
||||
+ public boolean isFreezeTickingLocked() {
|
||||
+ return this.entity.freezeLocked;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void lockFreezeTicks(boolean locked) {
|
||||
+ this.entity.freezeLocked = locked;
|
||||
+ }
|
||||
+ // Paper end - Freeze Tick Lock API
|
||||
@Override
|
||||
public void remove() {
|
||||
this.entity.pluginRemoved = true;
|
98
patches/server/0652-More-PotionEffectType-API.patch
Normal file
98
patches/server/0652-More-PotionEffectType-API.patch
Normal file
|
@ -0,0 +1,98 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Thu, 27 May 2021 21:58:24 -0700
|
||||
Subject: [PATCH] More PotionEffectType API
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.effect.MobEffect attributeModifiers
|
||||
public net.minecraft.world.effect.MobEffect$AttributeTemplate
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionEffectType.java b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionEffectType.java
|
||||
index 21d4224c8993f521d6004d708ecbf71fa6d09306..6cf790c9fa23ea313423fdaeb7c181bf530828c6 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionEffectType.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionEffectType.java
|
||||
@@ -129,6 +129,48 @@ public class CraftPotionEffectType extends PotionEffectType implements Handleabl
|
||||
return this.handle.getDescriptionId();
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public java.util.Map<org.bukkit.attribute.Attribute, org.bukkit.attribute.AttributeModifier> getEffectAttributes() {
|
||||
+ // re-create map each time because a nms MobEffect can have its attributes modified
|
||||
+ final java.util.Map<org.bukkit.attribute.Attribute, org.bukkit.attribute.AttributeModifier> attributeMap = new java.util.HashMap<>();
|
||||
+ this.handle.attributeModifiers.forEach((attribute, attributeModifier) -> {
|
||||
+ attributeMap.put(
|
||||
+ org.bukkit.craftbukkit.attribute.CraftAttribute.minecraftHolderToBukkit(attribute),
|
||||
+ // use zero as amplifier to get the base amount, as it is amount = base * (amplifier + 1)
|
||||
+ org.bukkit.craftbukkit.attribute.CraftAttributeInstance.convert(attributeModifier.create(0))
|
||||
+ );
|
||||
+ });
|
||||
+ return java.util.Map.copyOf(attributeMap);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public double getAttributeModifierAmount(org.bukkit.attribute.Attribute attribute, int effectAmplifier) {
|
||||
+ com.google.common.base.Preconditions.checkArgument(effectAmplifier >= 0, "effectAmplifier must be greater than or equal to 0");
|
||||
+ Holder<net.minecraft.world.entity.ai.attributes.Attribute> nmsAttribute = org.bukkit.craftbukkit.attribute.CraftAttribute.bukkitToMinecraftHolder(attribute);
|
||||
+ com.google.common.base.Preconditions.checkArgument(this.handle.attributeModifiers.containsKey(nmsAttribute), attribute + " is not present on " + this.getKey());
|
||||
+ return this.handle.attributeModifiers.get(nmsAttribute).create(effectAmplifier).amount();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public PotionEffectType.Category getEffectCategory() {
|
||||
+ return fromNMS(handle.getCategory());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public String translationKey() {
|
||||
+ return this.handle.getDescriptionId();
|
||||
+ }
|
||||
+
|
||||
+ public static PotionEffectType.Category fromNMS(net.minecraft.world.effect.MobEffectCategory mobEffectInfo) {
|
||||
+ return switch (mobEffectInfo) {
|
||||
+ case BENEFICIAL -> PotionEffectType.Category.BENEFICIAL;
|
||||
+ case HARMFUL -> PotionEffectType.Category.HARMFUL;
|
||||
+ case NEUTRAL -> PotionEffectType.Category.NEUTRAL;
|
||||
+ };
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
diff --git a/src/test/java/io/papermc/paper/effects/EffectCategoryTest.java b/src/test/java/io/papermc/paper/effects/EffectCategoryTest.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..a57e8fdc35efc7e0353d4f36c91578390ee4572e
|
||||
--- /dev/null
|
||||
+++ b/src/test/java/io/papermc/paper/effects/EffectCategoryTest.java
|
||||
@@ -0,0 +1,30 @@
|
||||
+package io.papermc.paper.effects;
|
||||
+
|
||||
+import io.papermc.paper.adventure.PaperAdventure;
|
||||
+import net.minecraft.world.effect.MobEffectCategory;
|
||||
+import org.bukkit.craftbukkit.potion.CraftPotionEffectType;
|
||||
+import org.bukkit.potion.PotionEffectType;
|
||||
+import org.bukkit.support.environment.AllFeatures;
|
||||
+import org.junit.jupiter.api.Test;
|
||||
+
|
||||
+import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
+import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
+
|
||||
+@AllFeatures
|
||||
+public class EffectCategoryTest {
|
||||
+
|
||||
+ @Test
|
||||
+ public void testEffectCategoriesExist() {
|
||||
+ for (MobEffectCategory mobEffectInfo : MobEffectCategory.values()) {
|
||||
+ assertNotNull(CraftPotionEffectType.fromNMS(mobEffectInfo), mobEffectInfo + " is missing a bukkit equivalent");
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void testCategoryHasEquivalentColors() {
|
||||
+ for (MobEffectCategory mobEffectInfo : MobEffectCategory.values()) {
|
||||
+ PotionEffectType.Category bukkitEffectCategory = CraftPotionEffectType.fromNMS(mobEffectInfo);
|
||||
+ assertEquals(bukkitEffectCategory.getColor(), PaperAdventure.asAdventure(mobEffectInfo.getTooltipFormatting()), mobEffectInfo.getTooltipFormatting().name() + " doesn't equal " + bukkitEffectCategory.getColor());
|
||||
+ }
|
||||
+ }
|
||||
+}
|
|
@ -0,0 +1,20 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Mon, 12 Jul 2021 12:28:29 +0100
|
||||
Subject: [PATCH] Use a CHM for StructureTemplate.Pallete cache
|
||||
|
||||
fixes a CME due to this collection being shared across threads
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java
|
||||
index e7900e7e8263cae131dad2427fb2bfdadf5b8d14..b120949667ae0169a667b329b3cabbd79a0a5bda 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java
|
||||
@@ -889,7 +889,7 @@ public class StructureTemplate {
|
||||
public static final class Palette {
|
||||
|
||||
private final List<StructureTemplate.StructureBlockInfo> blocks;
|
||||
- private final Map<Block, List<StructureTemplate.StructureBlockInfo>> cache = Maps.newHashMap();
|
||||
+ private final Map<Block, List<StructureTemplate.StructureBlockInfo>> cache = Maps.newConcurrentMap(); // Paper - Fix CME due to this collection being shared across threads
|
||||
@Nullable
|
||||
private List<StructureTemplate.JigsawBlockInfo> cachedJigsaws;
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
|
||||
Date: Tue, 1 Feb 2022 15:51:55 -0700
|
||||
Subject: [PATCH] API for creating command sender which forwards feedback
|
||||
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/commands/FeedbackForwardingSender.java b/src/main/java/io/papermc/paper/commands/FeedbackForwardingSender.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..e3a5f1ec376319bdfda87fa27ae217bff3914292
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/commands/FeedbackForwardingSender.java
|
||||
@@ -0,0 +1,111 @@
|
||||
+package io.papermc.paper.commands;
|
||||
+
|
||||
+import io.papermc.paper.adventure.PaperAdventure;
|
||||
+import java.util.UUID;
|
||||
+import java.util.function.Consumer;
|
||||
+import net.kyori.adventure.audience.MessageType;
|
||||
+import net.kyori.adventure.identity.Identity;
|
||||
+import net.kyori.adventure.text.Component;
|
||||
+import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
+import net.minecraft.commands.CommandSource;
|
||||
+import net.minecraft.commands.CommandSourceStack;
|
||||
+import net.minecraft.server.level.ServerLevel;
|
||||
+import net.minecraft.world.phys.Vec2;
|
||||
+import net.minecraft.world.phys.Vec3;
|
||||
+import org.bukkit.command.CommandSender;
|
||||
+import org.bukkit.craftbukkit.CraftServer;
|
||||
+import org.bukkit.craftbukkit.command.ServerCommandSender;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public final class FeedbackForwardingSender extends ServerCommandSender {
|
||||
+ private final Consumer<? super Component> feedback;
|
||||
+ private final CraftServer server;
|
||||
+
|
||||
+ public FeedbackForwardingSender(final Consumer<? super Component> feedback, final CraftServer server) {
|
||||
+ super(((ServerCommandSender) server.getConsoleSender()).perm);
|
||||
+ this.server = server;
|
||||
+ this.feedback = feedback;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void sendMessage(final String message) {
|
||||
+ this.sendMessage(LegacyComponentSerializer.legacySection().deserialize(message));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void sendMessage(final String... messages) {
|
||||
+ for (final String message : messages) {
|
||||
+ this.sendMessage(message);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void sendMessage(final Identity identity, final Component message, final MessageType type) {
|
||||
+ this.feedback.accept(message);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public String getName() {
|
||||
+ return "FeedbackForwardingSender";
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Component name() {
|
||||
+ return Component.text(this.getName());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isOp() {
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setOp(final boolean value) {
|
||||
+ throw new UnsupportedOperationException("Cannot change operator status of " + this.getClass().getName());
|
||||
+ }
|
||||
+
|
||||
+ public CommandSourceStack asVanilla() {
|
||||
+ final @Nullable ServerLevel overworld = this.server.getServer().overworld();
|
||||
+ return new CommandSourceStack(
|
||||
+ new Source(this),
|
||||
+ overworld == null ? Vec3.ZERO : Vec3.atLowerCornerOf(overworld.getSharedSpawnPos()),
|
||||
+ Vec2.ZERO,
|
||||
+ overworld,
|
||||
+ 4,
|
||||
+ this.getName(),
|
||||
+ net.minecraft.network.chat.Component.literal(this.getName()),
|
||||
+ this.server.getServer(),
|
||||
+ null
|
||||
+ );
|
||||
+ }
|
||||
+
|
||||
+ private record Source(FeedbackForwardingSender sender) implements CommandSource {
|
||||
+ @Override
|
||||
+ public void sendSystemMessage(final net.minecraft.network.chat.Component message) {
|
||||
+ this.sender.sendMessage(Identity.nil(), PaperAdventure.asAdventure(message));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean acceptsSuccess() {
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean acceptsFailure() {
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean shouldInformAdmins() {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public CommandSender getBukkitSender(final CommandSourceStack stack) {
|
||||
+ return this.sender;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index d30c1e853bb2e27922a00d890dffca153cdcbe97..93811e7770546c202085487642699e0c74b9f498 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -2166,6 +2166,13 @@ public final class CraftServer implements Server {
|
||||
return this.console.console;
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public CommandSender createCommandSender(final java.util.function.Consumer<? super net.kyori.adventure.text.Component> feedback) {
|
||||
+ return new io.papermc.paper.commands.FeedbackForwardingSender(feedback, this);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
public EntityMetadataStore getEntityMetadata() {
|
||||
return this.entityMetadata;
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/command/ServerCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/ServerCommandSender.java
|
||||
index 7f22950ae61436e91a59cd29a345809c42bbe739..1e3091687735b461d3b6a313ab8761127981d3e8 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/command/ServerCommandSender.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/command/ServerCommandSender.java
|
||||
@@ -12,7 +12,7 @@ import org.bukkit.permissions.PermissionAttachmentInfo;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
public abstract class ServerCommandSender implements CommandSender {
|
||||
- private final PermissibleBase perm;
|
||||
+ public final PermissibleBase perm; // Paper
|
||||
private net.kyori.adventure.pointer.Pointers adventure$pointers; // Paper - implement pointers
|
||||
|
||||
protected ServerCommandSender() {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java b/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java
|
||||
index 4e81c26fdbd089961b2577168c716bf29d504d40..a35e2d2f53e8308d51e5a07b34c56d05a707bc14 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java
|
||||
@@ -81,6 +81,11 @@ public final class VanillaCommandWrapper extends BukkitCommand {
|
||||
if (sender instanceof ProxiedCommandSender) {
|
||||
return ((ProxiedNativeCommandSender) sender).getHandle();
|
||||
}
|
||||
+ // Paper start
|
||||
+ if (sender instanceof io.papermc.paper.commands.FeedbackForwardingSender feedback) {
|
||||
+ return feedback.asVanilla();
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
throw new IllegalArgumentException("Cannot make " + sender + " a vanilla command listener");
|
||||
}
|
399
patches/server/0655-Add-missing-structure-set-seed-configs.patch
Normal file
399
patches/server/0655-Add-missing-structure-set-seed-configs.patch
Normal file
|
@ -0,0 +1,399 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Thu, 13 Jan 2022 23:05:53 -0800
|
||||
Subject: [PATCH] Add missing structure set seed configs
|
||||
|
||||
The 4 missing structure set seed configs are strongholds, mineshafts,
|
||||
buried treasure, and ancient cities.
|
||||
|
||||
Strongholds use a ring placement scheme which isn't random so they
|
||||
utilize the world seed by default, this adds a config to override it
|
||||
for just generating the ring positions.
|
||||
|
||||
Mineshafts and Buried Treasure structure sets are special cases
|
||||
where the "salt" that can be defined for them via datapacks has 0
|
||||
effect because the difference between the spacing and separation is 1
|
||||
which is used as the upper bound in the random with salt. So the random
|
||||
always returns the same int (0) so the salt has no effect. This adds
|
||||
seeds/salts to the frequency reducer which has a similar effect.
|
||||
|
||||
Co-authored-by: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
|
||||
index 575fa665ff9c8f52056a0e7305540ec5c3da4785..906f56d07c26ef3c2dc1a3b62e9349dd91a37742 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
|
||||
@@ -573,7 +573,7 @@ public abstract class ChunkGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
- if (structureplacement.isStructureChunk(placementCalculator, chunkcoordintpair.x, chunkcoordintpair.z)) {
|
||||
+ if (structureplacement.isStructureChunk(placementCalculator, chunkcoordintpair.x, chunkcoordintpair.z, structureplacement instanceof net.minecraft.world.level.chunk.ChunkGeneratorStructureState.KeyedRandomSpreadStructurePlacement keyed ? keyed.key : null)) { // Paper - Add missing structure set seed configs
|
||||
if (list.size() == 1) {
|
||||
this.tryGenerateStructure((StructureSet.StructureSelectionEntry) list.get(0), structureAccessor, registryManager, randomstate, structureTemplateManager, placementCalculator.getLevelSeed(), chunk, chunkcoordintpair, sectionposition);
|
||||
} else {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java
|
||||
index ed779a03e2ce7684428600dac4f2e92ab002f29f..a20520a6bd28bae1cee82258ac49d9753faba2bd 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java
|
||||
@@ -50,13 +50,14 @@ public class ChunkGeneratorStructureState {
|
||||
private final Map<ConcentricRingsStructurePlacement, CompletableFuture<List<ChunkPos>>> ringPositions = new Object2ObjectArrayMap();
|
||||
private boolean hasGeneratedPositions;
|
||||
private final List<Holder<StructureSet>> possibleStructureSets;
|
||||
+ public final SpigotWorldConfig conf; // Paper - Add missing structure set seed configs
|
||||
|
||||
public static ChunkGeneratorStructureState createForFlat(RandomState randomstate, long i, BiomeSource worldchunkmanager, Stream<Holder<StructureSet>> stream, SpigotWorldConfig conf) { // Spigot
|
||||
List<Holder<StructureSet>> list = stream.filter((holder) -> {
|
||||
return ChunkGeneratorStructureState.hasBiomesForStructureSet((StructureSet) holder.value(), worldchunkmanager);
|
||||
}).toList();
|
||||
|
||||
- return new ChunkGeneratorStructureState(randomstate, worldchunkmanager, i, 0L, ChunkGeneratorStructureState.injectSpigot(list, conf)); // Spigot
|
||||
+ return new ChunkGeneratorStructureState(randomstate, worldchunkmanager, i, 0L, ChunkGeneratorStructureState.injectSpigot(list, conf), conf); // Spigot
|
||||
}
|
||||
|
||||
public static ChunkGeneratorStructureState createForNormal(RandomState randomstate, long i, BiomeSource worldchunkmanager, HolderLookup<StructureSet> holderlookup, SpigotWorldConfig conf) { // Spigot
|
||||
@@ -64,14 +65,24 @@ public class ChunkGeneratorStructureState {
|
||||
return ChunkGeneratorStructureState.hasBiomesForStructureSet((StructureSet) holder_c.value(), worldchunkmanager);
|
||||
}).collect(Collectors.toUnmodifiableList());
|
||||
|
||||
- return new ChunkGeneratorStructureState(randomstate, worldchunkmanager, i, i, ChunkGeneratorStructureState.injectSpigot(list, conf)); // Spigot
|
||||
+ return new ChunkGeneratorStructureState(randomstate, worldchunkmanager, i, i, ChunkGeneratorStructureState.injectSpigot(list, conf), conf); // Spigot
|
||||
}
|
||||
+ // Paper start - Add missing structure set seed configs; horrible hack because spigot creates a ton of direct Holders which lose track of the identifying key
|
||||
+ public static final class KeyedRandomSpreadStructurePlacement extends RandomSpreadStructurePlacement {
|
||||
+ public final net.minecraft.resources.ResourceKey<StructureSet> key;
|
||||
+ public KeyedRandomSpreadStructurePlacement(net.minecraft.resources.ResourceKey<StructureSet> key, net.minecraft.core.Vec3i locateOffset, FrequencyReductionMethod frequencyReductionMethod, float frequency, int salt, java.util.Optional<StructurePlacement.ExclusionZone> exclusionZone, int spacing, int separation, net.minecraft.world.level.levelgen.structure.placement.RandomSpreadType spreadType) {
|
||||
+ super(locateOffset, frequencyReductionMethod, frequency, salt, exclusionZone, spacing, separation, spreadType);
|
||||
+ this.key = key;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Add missing structure set seed configs
|
||||
|
||||
// Spigot start
|
||||
private static List<Holder<StructureSet>> injectSpigot(List<Holder<StructureSet>> list, SpigotWorldConfig conf) {
|
||||
return list.stream().map((holder) -> {
|
||||
StructureSet structureset = holder.value();
|
||||
- if (structureset.placement() instanceof RandomSpreadStructurePlacement randomConfig) {
|
||||
+ final Holder<StructureSet> newHolder; // Paper - Add missing structure set seed configs
|
||||
+ if (structureset.placement() instanceof RandomSpreadStructurePlacement randomConfig && holder.unwrapKey().orElseThrow().location().getNamespace().equals(net.minecraft.resources.ResourceLocation.DEFAULT_NAMESPACE)) { // Paper - Add missing structure set seed configs; check namespace cause datapacks could add structure sets with the same path
|
||||
String name = holder.unwrapKey().orElseThrow().location().getPath();
|
||||
int seed = randomConfig.salt;
|
||||
|
||||
@@ -118,11 +129,27 @@ public class ChunkGeneratorStructureState {
|
||||
case "villages":
|
||||
seed = conf.villageSeed;
|
||||
break;
|
||||
+ // Paper start - Add missing structure set seed configs
|
||||
+ case "ancient_cities":
|
||||
+ seed = conf.ancientCitySeed;
|
||||
+ break;
|
||||
+ case "trail_ruins":
|
||||
+ seed = conf.trailRuinsSeed;
|
||||
+ break;
|
||||
+ case "trial_chambers":
|
||||
+ seed = conf.trialChambersSeed;
|
||||
+ break;
|
||||
+ // Paper end - Add missing structure set seed configs
|
||||
}
|
||||
|
||||
- structureset = new StructureSet(structureset.structures(), new RandomSpreadStructurePlacement(randomConfig.locateOffset, randomConfig.frequencyReductionMethod, randomConfig.frequency, seed, randomConfig.exclusionZone, randomConfig.spacing(), randomConfig.separation(), randomConfig.spreadType()));
|
||||
+ // Paper start - Add missing structure set seed configs
|
||||
+ structureset = new StructureSet(structureset.structures(), new KeyedRandomSpreadStructurePlacement(holder.unwrapKey().orElseThrow(), randomConfig.locateOffset, randomConfig.frequencyReductionMethod, randomConfig.frequency, seed, randomConfig.exclusionZone, randomConfig.spacing(), randomConfig.separation(), randomConfig.spreadType()));
|
||||
+ newHolder = Holder.direct(structureset); // I really wish we didn't have to do this here
|
||||
+ } else {
|
||||
+ newHolder = holder;
|
||||
}
|
||||
- return Holder.direct(structureset);
|
||||
+ return newHolder;
|
||||
+ // Paper end - Add missing structure set seed configs
|
||||
}).collect(Collectors.toUnmodifiableList());
|
||||
}
|
||||
// Spigot end
|
||||
@@ -139,12 +166,13 @@ public class ChunkGeneratorStructureState {
|
||||
return stream.anyMatch(set::contains);
|
||||
}
|
||||
|
||||
- private ChunkGeneratorStructureState(RandomState noiseConfig, BiomeSource biomeSource, long structureSeed, long concentricRingSeed, List<Holder<StructureSet>> structureSets) {
|
||||
+ private ChunkGeneratorStructureState(RandomState noiseConfig, BiomeSource biomeSource, long structureSeed, long concentricRingSeed, List<Holder<StructureSet>> structureSets, SpigotWorldConfig conf) { // Paper - Add missing structure set seed configs
|
||||
this.randomState = noiseConfig;
|
||||
this.levelSeed = structureSeed;
|
||||
this.biomeSource = biomeSource;
|
||||
this.concentricRingsSeed = concentricRingSeed;
|
||||
this.possibleStructureSets = structureSets;
|
||||
+ this.conf = conf; // Paper - Add missing structure set seed configs
|
||||
}
|
||||
|
||||
public List<Holder<StructureSet>> possibleStructureSets() {
|
||||
@@ -198,7 +226,13 @@ public class ChunkGeneratorStructureState {
|
||||
HolderSet<Biome> holderset = placement.preferredBiomes();
|
||||
RandomSource randomsource = RandomSource.create();
|
||||
|
||||
+ // Paper start - Add missing structure set seed configs
|
||||
+ if (this.conf.strongholdSeed != null && structureSetEntry.is(net.minecraft.world.level.levelgen.structure.BuiltinStructureSets.STRONGHOLDS)) {
|
||||
+ randomsource.setSeed(this.conf.strongholdSeed);
|
||||
+ } else {
|
||||
+ // Paper end - Add missing structure set seed configs
|
||||
randomsource.setSeed(this.concentricRingsSeed);
|
||||
+ } // Paper - Add missing structure set seed configs
|
||||
double d0 = randomsource.nextDouble() * Math.PI * 2.0D;
|
||||
int l = 0;
|
||||
int i1 = 0;
|
||||
@@ -275,7 +309,7 @@ public class ChunkGeneratorStructureState {
|
||||
|
||||
for (int l = centerChunkX - chunkCount; l <= centerChunkX + chunkCount; ++l) {
|
||||
for (int i1 = centerChunkZ - chunkCount; i1 <= centerChunkZ + chunkCount; ++i1) {
|
||||
- if (structureplacement.isStructureChunk(this, l, i1)) {
|
||||
+ if (structureplacement.isStructureChunk(this, l, i1, structureplacement instanceof KeyedRandomSpreadStructurePlacement keyed ? keyed.key : null)) { // Paper - Add missing structure set seed configs
|
||||
return true;
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/StructureCheck.java b/src/main/java/net/minecraft/world/level/levelgen/structure/StructureCheck.java
|
||||
index 953ab7638f7242b5a11dd1de8786172443a0558c..5f354b333a39b873915bedd57b647355ae5bdf56 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/levelgen/structure/StructureCheck.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/StructureCheck.java
|
||||
@@ -74,6 +74,20 @@ public class StructureCheck {
|
||||
this.fixerUpper = dataFixer;
|
||||
}
|
||||
|
||||
+ // Paper start - add missing structure salt configs
|
||||
+ @Nullable
|
||||
+ private Integer getSaltOverride(Structure type) {
|
||||
+ if (this.heightAccessor instanceof net.minecraft.server.level.ServerLevel serverLevel) {
|
||||
+ if (type instanceof net.minecraft.world.level.levelgen.structure.structures.MineshaftStructure) {
|
||||
+ return serverLevel.spigotConfig.mineshaftSeed;
|
||||
+ } else if (type instanceof net.minecraft.world.level.levelgen.structure.structures.BuriedTreasureStructure) {
|
||||
+ return serverLevel.spigotConfig.buriedTreasureSeed;
|
||||
+ }
|
||||
+ }
|
||||
+ return null;
|
||||
+ }
|
||||
+ // Paper end - add missing structure seed configs
|
||||
+
|
||||
public StructureCheckResult checkStart(ChunkPos pos, Structure type, StructurePlacement placement, boolean skipReferencedStructures) {
|
||||
long l = pos.toLong();
|
||||
Object2IntMap<Structure> object2IntMap = this.loadedChunks.get(l);
|
||||
@@ -83,7 +97,7 @@ public class StructureCheck {
|
||||
StructureCheckResult structureCheckResult = this.tryLoadFromStorage(pos, type, skipReferencedStructures, l);
|
||||
if (structureCheckResult != null) {
|
||||
return structureCheckResult;
|
||||
- } else if (!placement.applyAdditionalChunkRestrictions(pos.x, pos.z, this.seed)) {
|
||||
+ } else if (!placement.applyAdditionalChunkRestrictions(pos.x, pos.z, this.seed, this.getSaltOverride(type))) { // Paper - add missing structure seed configs
|
||||
return StructureCheckResult.START_NOT_PRESENT;
|
||||
} else {
|
||||
boolean bl = this.featureChecks
|
||||
diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/placement/StructurePlacement.java b/src/main/java/net/minecraft/world/level/levelgen/structure/placement/StructurePlacement.java
|
||||
index a4c34e9415632354d33668a38d06453ada4d3c77..cbf13e4f2da6a27619e9bc9a7cd73bb6e69cad2a 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/levelgen/structure/placement/StructurePlacement.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/placement/StructurePlacement.java
|
||||
@@ -79,14 +79,30 @@ public abstract class StructurePlacement {
|
||||
return this.exclusionZone;
|
||||
}
|
||||
|
||||
+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper - Add missing structure set seed configs
|
||||
public boolean isStructureChunk(ChunkGeneratorStructureState calculator, int chunkX, int chunkZ) {
|
||||
+ // Paper start - Add missing structure set seed configs
|
||||
+ return this.isStructureChunk(calculator, chunkX, chunkZ, null);
|
||||
+ }
|
||||
+ public boolean isStructureChunk(ChunkGeneratorStructureState calculator, int chunkX, int chunkZ, @org.jetbrains.annotations.Nullable net.minecraft.resources.ResourceKey<StructureSet> structureSetKey) {
|
||||
+ Integer saltOverride = null;
|
||||
+ if (structureSetKey != null) {
|
||||
+ if (structureSetKey == net.minecraft.world.level.levelgen.structure.BuiltinStructureSets.MINESHAFTS) {
|
||||
+ saltOverride = calculator.conf.mineshaftSeed;
|
||||
+ } else if (structureSetKey == net.minecraft.world.level.levelgen.structure.BuiltinStructureSets.BURIED_TREASURES) {
|
||||
+ saltOverride = calculator.conf.buriedTreasureSeed;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Add missing structure set seed configs
|
||||
return this.isPlacementChunk(calculator, chunkX, chunkZ)
|
||||
- && this.applyAdditionalChunkRestrictions(chunkX, chunkZ, calculator.getLevelSeed())
|
||||
+ && this.applyAdditionalChunkRestrictions(chunkX, chunkZ, calculator.getLevelSeed(), saltOverride) // Paper - Add missing structure set seed configs
|
||||
&& this.applyInteractionsWithOtherStructures(calculator, chunkX, chunkZ);
|
||||
}
|
||||
|
||||
- public boolean applyAdditionalChunkRestrictions(int chunkX, int chunkZ, long seed) {
|
||||
- return !(this.frequency < 1.0F) || this.frequencyReductionMethod.shouldGenerate(seed, this.salt, chunkX, chunkZ, this.frequency);
|
||||
+ // Paper start - Add missing structure set seed configs
|
||||
+ public boolean applyAdditionalChunkRestrictions(int chunkX, int chunkZ, long seed, @org.jetbrains.annotations.Nullable Integer saltOverride) {
|
||||
+ return !(this.frequency < 1.0F) || this.frequencyReductionMethod.shouldGenerate(seed, this.salt, chunkX, chunkZ, this.frequency, saltOverride);
|
||||
+ // Paper end - Add missing structure set seed configs
|
||||
}
|
||||
|
||||
public boolean applyInteractionsWithOtherStructures(ChunkGeneratorStructureState calculator, int centerChunkX, int centerChunkZ) {
|
||||
@@ -101,25 +117,31 @@ public abstract class StructurePlacement {
|
||||
|
||||
public abstract StructurePlacementType<?> type();
|
||||
|
||||
- private static boolean probabilityReducer(long seed, int salt, int chunkX, int chunkZ, float frequency) {
|
||||
+ private static boolean probabilityReducer(long seed, int salt, int chunkX, int chunkZ, float frequency, @org.jetbrains.annotations.Nullable Integer saltOverride) { // Paper - Add missing structure set seed configs; ignore here
|
||||
WorldgenRandom worldgenRandom = new WorldgenRandom(new LegacyRandomSource(0L));
|
||||
worldgenRandom.setLargeFeatureWithSalt(seed, salt, chunkX, chunkZ);
|
||||
return worldgenRandom.nextFloat() < frequency;
|
||||
}
|
||||
|
||||
- private static boolean legacyProbabilityReducerWithDouble(long seed, int salt, int chunkX, int chunkZ, float frequency) {
|
||||
+ private static boolean legacyProbabilityReducerWithDouble(long seed, int salt, int chunkX, int chunkZ, float frequency, @org.jetbrains.annotations.Nullable Integer saltOverride) { // Paper - Add missing structure set seed configs
|
||||
WorldgenRandom worldgenRandom = new WorldgenRandom(new LegacyRandomSource(0L));
|
||||
+ if (saltOverride == null) { // Paper - Add missing structure set seed configs
|
||||
worldgenRandom.setLargeFeatureSeed(seed, chunkX, chunkZ);
|
||||
+ // Paper start - Add missing structure set seed configs
|
||||
+ } else {
|
||||
+ worldgenRandom.setLargeFeatureWithSalt(seed, chunkX, chunkZ, saltOverride);
|
||||
+ }
|
||||
+ // Paper end - Add missing structure set seed configs
|
||||
return worldgenRandom.nextDouble() < (double)frequency;
|
||||
}
|
||||
|
||||
- private static boolean legacyArbitrarySaltProbabilityReducer(long seed, int salt, int chunkX, int chunkZ, float frequency) {
|
||||
+ private static boolean legacyArbitrarySaltProbabilityReducer(long seed, int salt, int chunkX, int chunkZ, float frequency, @org.jetbrains.annotations.Nullable Integer saltOverride) { // Paper - Add missing structure set seed configs
|
||||
WorldgenRandom worldgenRandom = new WorldgenRandom(new LegacyRandomSource(0L));
|
||||
- worldgenRandom.setLargeFeatureWithSalt(seed, chunkX, chunkZ, 10387320);
|
||||
+ worldgenRandom.setLargeFeatureWithSalt(seed, chunkX, chunkZ, saltOverride != null ? saltOverride : HIGHLY_ARBITRARY_RANDOM_SALT); // Paper - Add missing structure set seed configs
|
||||
return worldgenRandom.nextFloat() < frequency;
|
||||
}
|
||||
|
||||
- private static boolean legacyPillagerOutpostReducer(long seed, int salt, int chunkX, int chunkZ, float frequency) {
|
||||
+ private static boolean legacyPillagerOutpostReducer(long seed, int salt, int chunkX, int chunkZ, float frequency, @org.jetbrains.annotations.Nullable Integer saltOverride) { // Paper - Add missing structure set seed configs; ignore here
|
||||
int i = chunkX >> 4;
|
||||
int j = chunkZ >> 4;
|
||||
WorldgenRandom worldgenRandom = new WorldgenRandom(new LegacyRandomSource(0L));
|
||||
@@ -147,7 +169,7 @@ public abstract class StructurePlacement {
|
||||
|
||||
@FunctionalInterface
|
||||
public interface FrequencyReducer {
|
||||
- boolean shouldGenerate(long seed, int salt, int chunkX, int chunkZ, float chance);
|
||||
+ boolean shouldGenerate(long seed, int salt, int chunkX, int chunkZ, float chance, @org.jetbrains.annotations.Nullable Integer saltOverride); // Paper - Add missing structure set seed configs
|
||||
}
|
||||
|
||||
public static enum FrequencyReductionMethod implements StringRepresentable {
|
||||
@@ -167,8 +189,8 @@ public abstract class StructurePlacement {
|
||||
this.reducer = generationPredicate;
|
||||
}
|
||||
|
||||
- public boolean shouldGenerate(long seed, int salt, int chunkX, int chunkZ, float chance) {
|
||||
- return this.reducer.shouldGenerate(seed, salt, chunkX, chunkZ, chance);
|
||||
+ public boolean shouldGenerate(long seed, int salt, int chunkX, int chunkZ, float chance, @org.jetbrains.annotations.Nullable Integer saltOverride) { // Paper - Add missing structure set seed configs
|
||||
+ return this.reducer.shouldGenerate(seed, salt, chunkX, chunkZ, chance, saltOverride); // Paper - Add missing structure set seed configs
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java
|
||||
index e76f96a5c48d1eda2f9bbb3e11dd79f23f9ab75c..2b263246135c85aa225120519e9702a628773935 100644
|
||||
--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java
|
||||
+++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java
|
||||
@@ -322,6 +322,18 @@ public class SpigotWorldConfig
|
||||
public int mansionSeed;
|
||||
public int fossilSeed;
|
||||
public int portalSeed;
|
||||
+ // Paper start - add missing structure set configs
|
||||
+ public int ancientCitySeed;
|
||||
+ public int trailRuinsSeed;
|
||||
+ public int trialChambersSeed;
|
||||
+ public int buriedTreasureSeed;
|
||||
+ public Integer mineshaftSeed;
|
||||
+ public Long strongholdSeed;
|
||||
+ private <N extends Number> N getSeed(String path, java.util.function.Function<String, N> toNumberFunc) {
|
||||
+ final String value = this.getString(path, "default");
|
||||
+ return org.apache.commons.lang3.math.NumberUtils.isParsable(value) ? toNumberFunc.apply(value) : null;
|
||||
+ }
|
||||
+ // Paper end
|
||||
private void initWorldGenSeeds()
|
||||
{
|
||||
this.villageSeed = this.getInt( "seed-village", 10387312 );
|
||||
@@ -339,6 +351,14 @@ public class SpigotWorldConfig
|
||||
this.mansionSeed = this.getInt( "seed-mansion", 10387319 );
|
||||
this.fossilSeed = this.getInt( "seed-fossil", 14357921 );
|
||||
this.portalSeed = this.getInt( "seed-portal", 34222645 );
|
||||
+ // Paper start - add missing structure set configs
|
||||
+ this.ancientCitySeed = this.getInt("seed-ancientcity", 20083232);
|
||||
+ this.trailRuinsSeed = this.getInt("seed-trailruins", 83469867);
|
||||
+ this.trialChambersSeed = this.getInt("seed-trialchambers", 94251327);
|
||||
+ this.buriedTreasureSeed = this.getInt("seed-buriedtreasure", 10387320); // StructurePlacement#HIGHLY_ARBITRARY_RANDOM_SALT
|
||||
+ this.mineshaftSeed = this.getSeed("seed-mineshaft", Integer::parseInt);
|
||||
+ this.strongholdSeed = this.getSeed("seed-stronghold", Long::parseLong);
|
||||
+ // Paper end
|
||||
this.log( "Custom Map Seeds: Village: " + this.villageSeed + " Desert: " + this.desertSeed + " Igloo: " + this.iglooSeed + " Jungle: " + this.jungleSeed + " Swamp: " + this.swampSeed + " Monument: " + this.monumentSeed
|
||||
+ " Ocean: " + this.oceanSeed + " Shipwreck: " + this.shipwreckSeed + " End City: " + this.endCitySeed + " Slime: " + this.slimeSeed + " Nether: " + this.netherSeed + " Mansion: " + this.mansionSeed + " Fossil: " + this.fossilSeed + " Portal: " + this.portalSeed );
|
||||
}
|
||||
diff --git a/src/test/java/io/papermc/paper/world/structure/StructureSeedConfigTest.java b/src/test/java/io/papermc/paper/world/structure/StructureSeedConfigTest.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..c77345f7e0c9bf179b8b35a8b300085f31fd45af
|
||||
--- /dev/null
|
||||
+++ b/src/test/java/io/papermc/paper/world/structure/StructureSeedConfigTest.java
|
||||
@@ -0,0 +1,77 @@
|
||||
+package io.papermc.paper.world.structure;
|
||||
+
|
||||
+import io.papermc.paper.configuration.PaperConfigurations;
|
||||
+import java.io.File;
|
||||
+import java.lang.reflect.Field;
|
||||
+import net.minecraft.core.Registry;
|
||||
+import net.minecraft.core.registries.Registries;
|
||||
+import net.minecraft.resources.ResourceKey;
|
||||
+import net.minecraft.resources.ResourceLocation;
|
||||
+import net.minecraft.world.level.levelgen.structure.BuiltinStructureSets;
|
||||
+import net.minecraft.world.level.levelgen.structure.StructureSet;
|
||||
+import net.minecraft.world.level.levelgen.structure.placement.StructurePlacement;
|
||||
+import org.bukkit.configuration.file.YamlConfiguration;
|
||||
+import org.bukkit.support.RegistryHelper;
|
||||
+import org.bukkit.support.environment.AllFeatures;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.junit.jupiter.api.Test;
|
||||
+import org.spigotmc.SpigotConfig;
|
||||
+import org.spigotmc.SpigotWorldConfig;
|
||||
+
|
||||
+import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
+
|
||||
+@AllFeatures
|
||||
+public class StructureSeedConfigTest {
|
||||
+
|
||||
+ @Test
|
||||
+ public void checkStructureSeedDefaults() throws ReflectiveOperationException {
|
||||
+ SpigotConfig.config = new YamlConfiguration() {
|
||||
+ @Override
|
||||
+ public void save(final @NotNull File file) {
|
||||
+ // no-op
|
||||
+ }
|
||||
+ };
|
||||
+ final SpigotWorldConfig config = PaperConfigurations.SPIGOT_WORLD_DEFAULTS.get();
|
||||
+
|
||||
+
|
||||
+ final Registry<StructureSet> structureSets = RegistryHelper.getRegistry().registryOrThrow(Registries.STRUCTURE_SET);
|
||||
+ for (final ResourceKey<StructureSet> setKey : structureSets.registryKeySet()) {
|
||||
+ assertEquals(ResourceLocation.DEFAULT_NAMESPACE, setKey.location().getNamespace());
|
||||
+ final StructureSet set = structureSets.getOrThrow(setKey);
|
||||
+ if (setKey == BuiltinStructureSets.STRONGHOLDS) { // special case due to seed matching world seed
|
||||
+ assertEquals(0, set.placement().salt);
|
||||
+ continue;
|
||||
+ }
|
||||
+ int salt = switch (setKey.location().getPath()) {
|
||||
+ case "villages" -> config.villageSeed;
|
||||
+ case "desert_pyramids" -> config.desertSeed;
|
||||
+ case "igloos" -> config.iglooSeed;
|
||||
+ case "jungle_temples" -> config.jungleSeed;
|
||||
+ case "swamp_huts" -> config.swampSeed;
|
||||
+ case "pillager_outposts" -> config.outpostSeed;
|
||||
+ case "ocean_monuments" -> config.monumentSeed;
|
||||
+ case "woodland_mansions" -> config.mansionSeed;
|
||||
+ case "buried_treasures" -> config.buriedTreasureSeed;
|
||||
+ case "mineshafts" -> config.mineshaftSeed == null ? 0 : config.mineshaftSeed; // mineshaft seed is set differently
|
||||
+ case "ruined_portals" -> config.portalSeed;
|
||||
+ case "shipwrecks" -> config.shipwreckSeed;
|
||||
+ case "ocean_ruins" -> config.oceanSeed;
|
||||
+ case "nether_complexes" -> config.netherSeed;
|
||||
+ case "nether_fossils" -> config.fossilSeed;
|
||||
+ case "end_cities" -> config.endCitySeed;
|
||||
+ case "ancient_cities" -> config.ancientCitySeed;
|
||||
+ case "trail_ruins" -> config.trailRuinsSeed;
|
||||
+ case "trial_chambers" -> config.trialChambersSeed;
|
||||
+ default -> throw new AssertionError("Missing structure set seed in SpigotWorldConfig for " + setKey);
|
||||
+ };
|
||||
+ if (setKey == BuiltinStructureSets.BURIED_TREASURES) {
|
||||
+ final Field field = StructurePlacement.class.getDeclaredField("HIGHLY_ARBITRARY_RANDOM_SALT");
|
||||
+ field.trySetAccessible();
|
||||
+ assertEquals(0, set.placement().salt);
|
||||
+ assertEquals(field.get(null), salt, "Mismatched default seed for " + setKey + ". Should be " + field.get(null));
|
||||
+ continue;
|
||||
+ }
|
||||
+ assertEquals(set.placement().salt, salt, "Mismatched default seed for " + setKey + ". Should be " + set.placement().salt);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
|
@ -0,0 +1,31 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Fri, 8 Oct 2021 13:12:58 -0700
|
||||
Subject: [PATCH] Fix cancelled powdered snow bucket placement
|
||||
|
||||
Cancelling the placement of powdered snow from the powdered
|
||||
snow bucket didn't revert grass that became snowy because of the
|
||||
placement.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
index 8c9ae9ac38def29ae4cd8944395e566e434d46d0..9289faebce6b1546af71aeadc6569d2595b486e0 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
@@ -425,7 +425,7 @@ public final class ItemStack implements DataComponentHolder {
|
||||
int oldCount = this.getCount();
|
||||
ServerLevel world = (ServerLevel) context.getLevel();
|
||||
|
||||
- if (!(item instanceof BucketItem || item instanceof SolidBucketItem)) { // if not bucket
|
||||
+ if (!(item instanceof BucketItem/* || item instanceof SolidBucketItem*/)) { // if not bucket // Paper - Fix cancelled powdered snow bucket placement
|
||||
world.captureBlockStates = true;
|
||||
// special case bonemeal
|
||||
if (item == Items.BONE_MEAL) {
|
||||
@@ -488,7 +488,7 @@ public final class ItemStack implements DataComponentHolder {
|
||||
world.capturedBlockStates.clear();
|
||||
if (blocks.size() > 1) {
|
||||
placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockMultiPlaceEvent(world, entityhuman, enumhand, blocks, blockposition.getX(), blockposition.getY(), blockposition.getZ());
|
||||
- } else if (blocks.size() == 1) {
|
||||
+ } else if (blocks.size() == 1 && item != Items.POWDER_SNOW_BUCKET) { // Paper - Fix cancelled powdered snow bucket placement
|
||||
placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPlaceEvent(world, entityhuman, enumhand, blocks.get(0), blockposition.getX(), blockposition.getY(), blockposition.getZ());
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
|
||||
Date: Sat, 12 Feb 2022 12:40:50 -0700
|
||||
Subject: [PATCH] Add missing Validate calls to CraftServer#getSpawnLimit
|
||||
|
||||
Copies appropriate checks from CraftWorld#getSpawnLimit
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index 93811e7770546c202085487642699e0c74b9f498..8d9816f84e551f1257972f467352e9c9ee09473e 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -2343,6 +2343,8 @@ public final class CraftServer implements Server {
|
||||
@Override
|
||||
public int getSpawnLimit(SpawnCategory spawnCategory) {
|
||||
// Paper start - Add mobcaps commands
|
||||
+ Preconditions.checkArgument(spawnCategory != null, "SpawnCategory cannot be null");
|
||||
+ Preconditions.checkArgument(CraftSpawnCategory.isValidForLimits(spawnCategory), "SpawnCategory." + spawnCategory + " does not have a spawn limit.");
|
||||
return this.getSpawnLimitUnsafe(spawnCategory);
|
||||
}
|
||||
public int getSpawnLimitUnsafe(final SpawnCategory spawnCategory) {
|
81
patches/server/0658-Add-GameEvent-tags.patch
Normal file
81
patches/server/0658-Add-GameEvent-tags.patch
Normal file
|
@ -0,0 +1,81 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sun, 3 Jan 2021 20:03:35 -0800
|
||||
Subject: [PATCH] Add GameEvent tags
|
||||
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/CraftGameEventTag.java b/src/main/java/io/papermc/paper/CraftGameEventTag.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..e7d9fd2702a1ce96596580fff8f5ee4fd3d22b5b
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/CraftGameEventTag.java
|
||||
@@ -0,0 +1,35 @@
|
||||
+package io.papermc.paper;
|
||||
+
|
||||
+import net.minecraft.core.registries.BuiltInRegistries;
|
||||
+import net.minecraft.core.registries.Registries;
|
||||
+import net.minecraft.resources.ResourceKey;
|
||||
+import net.minecraft.tags.TagKey;
|
||||
+import org.bukkit.GameEvent;
|
||||
+import org.bukkit.craftbukkit.tag.CraftTag;
|
||||
+import org.bukkit.craftbukkit.util.CraftNamespacedKey;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+import java.util.Collections;
|
||||
+import java.util.IdentityHashMap;
|
||||
+import java.util.Map;
|
||||
+import java.util.Objects;
|
||||
+import java.util.Set;
|
||||
+import java.util.stream.Collectors;
|
||||
+
|
||||
+public class CraftGameEventTag extends CraftTag<net.minecraft.world.level.gameevent.GameEvent, GameEvent> {
|
||||
+
|
||||
+ public CraftGameEventTag(net.minecraft.core.Registry<net.minecraft.world.level.gameevent.GameEvent> registry, TagKey<net.minecraft.world.level.gameevent.GameEvent> tag) {
|
||||
+ super(registry, tag);
|
||||
+ }
|
||||
+
|
||||
+ private static final Map<GameEvent, ResourceKey<net.minecraft.world.level.gameevent.GameEvent>> KEY_CACHE = Collections.synchronizedMap(new IdentityHashMap<>());
|
||||
+ @Override
|
||||
+ public boolean isTagged(@NotNull GameEvent gameEvent) {
|
||||
+ return registry.getHolderOrThrow(KEY_CACHE.computeIfAbsent(gameEvent, event -> ResourceKey.create(Registries.GAME_EVENT, CraftNamespacedKey.toMinecraft(event.getKey())))).is(tag);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull Set<GameEvent> getValues() {
|
||||
+ return getHandle().stream().map((nms) -> Objects.requireNonNull(GameEvent.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.GAME_EVENT.getKey(nms.value()))), nms + " is not a recognized game event")).collect(Collectors.toUnmodifiableSet());
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index 8d9816f84e551f1257972f467352e9c9ee09473e..b18ad8abb5e3c53b0e13544a6833198a670c1f34 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -2700,6 +2700,15 @@ public final class CraftServer implements Server {
|
||||
return (org.bukkit.Tag<T>) new CraftDamageTag(damageRegistry, damageTagKey);
|
||||
}
|
||||
}
|
||||
+ // Paper start
|
||||
+ case org.bukkit.Tag.REGISTRY_GAME_EVENTS -> {
|
||||
+ Preconditions.checkArgument(clazz == org.bukkit.GameEvent.class, "Game Event namespace must have GameEvent type");
|
||||
+ TagKey<net.minecraft.world.level.gameevent.GameEvent> gameEventTagKey = TagKey.create(net.minecraft.core.registries.Registries.GAME_EVENT, key);
|
||||
+ if (net.minecraft.core.registries.BuiltInRegistries.GAME_EVENT.getTag(gameEventTagKey).isPresent()) {
|
||||
+ return (org.bukkit.Tag<T>) new io.papermc.paper.CraftGameEventTag(net.minecraft.core.registries.BuiltInRegistries.GAME_EVENT, gameEventTagKey);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
default -> throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
@@ -2737,6 +2746,13 @@ public final class CraftServer implements Server {
|
||||
net.minecraft.core.Registry<DamageType> damageTags = CraftRegistry.getMinecraftRegistry(Registries.DAMAGE_TYPE);
|
||||
return damageTags.getTags().map(pair -> (org.bukkit.Tag<T>) new CraftDamageTag(damageTags, pair.key())).collect(ImmutableList.toImmutableList());
|
||||
}
|
||||
+ // Paper start
|
||||
+ case org.bukkit.Tag.REGISTRY_GAME_EVENTS -> {
|
||||
+ Preconditions.checkArgument(clazz == org.bukkit.GameEvent.class);
|
||||
+ net.minecraft.core.Registry<net.minecraft.world.level.gameevent.GameEvent> gameEvents = net.minecraft.core.registries.BuiltInRegistries.GAME_EVENT;
|
||||
+ return gameEvents.getTags().map(pair -> (org.bukkit.Tag<T>) new io.papermc.paper.CraftGameEventTag(gameEvents, pair.getFirst())).collect(ImmutableList.toImmutableList());
|
||||
+ }
|
||||
+ // Paper end
|
||||
default -> throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Tue, 28 Dec 2021 07:19:01 -0800
|
||||
Subject: [PATCH] Execute chunk tasks fairly for worlds while waiting for next
|
||||
tick
|
||||
|
||||
Currently, only the first world would have had tasks executed.
|
||||
This might result in chunks loading far slower in the nether,
|
||||
for example.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 15382d7da69967c50007f136e9d17dd2f81166e3..af392711da61a1921be1f82396c2a04dc897d563 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1419,6 +1419,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
if (super.pollTask()) {
|
||||
return true;
|
||||
} else {
|
||||
+ boolean ret = false; // Paper - force execution of all worlds, do not just bias the first
|
||||
if (this.tickRateManager.isSprinting() || this.haveTime()) {
|
||||
Iterator iterator = this.getAllLevels().iterator();
|
||||
|
||||
@@ -1426,12 +1427,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
ServerLevel worldserver = (ServerLevel) iterator.next();
|
||||
|
||||
if (worldserver.getChunkSource().pollTask()) {
|
||||
- return true;
|
||||
+ ret = true; // Paper - force execution of all worlds, do not just bias the first
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- return false;
|
||||
+ return ret; // Paper - force execution of all worlds, do not just bias the first
|
||||
}
|
||||
}
|
||||
|
48
patches/server/0660-Furnace-RecipesUsed-API.patch
Normal file
48
patches/server/0660-Furnace-RecipesUsed-API.patch
Normal file
|
@ -0,0 +1,48 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Thu, 13 Jan 2022 15:20:47 -0800
|
||||
Subject: [PATCH] Furnace RecipesUsed API
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java b/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java
|
||||
index 0ec30feb68efc1747e489ee4bb60e6a503cb31c4..e39fe3c848657bb75ffa510926c5d9109e523db9 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java
|
||||
@@ -103,5 +103,37 @@ public abstract class CraftFurnace<T extends AbstractFurnaceBlockEntity> extends
|
||||
snapshot.cookSpeedMultiplier = multiplier;
|
||||
snapshot.cookingTotalTime = AbstractFurnaceBlockEntity.getTotalCookTime(this.isPlaced() ? this.world.getHandle() : null, snapshot.recipeType, snapshot, snapshot.cookSpeedMultiplier); // Update the snapshot's current total cook time to scale with the newly set multiplier
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public int getRecipeUsedCount(org.bukkit.NamespacedKey furnaceRecipe) {
|
||||
+ return this.getSnapshot().getRecipesUsed().getInt(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(furnaceRecipe));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean hasRecipeUsedCount(org.bukkit.NamespacedKey furnaceRecipe) {
|
||||
+ return this.getSnapshot().getRecipesUsed().containsKey(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(furnaceRecipe));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setRecipeUsedCount(org.bukkit.inventory.CookingRecipe<?> furnaceRecipe, int count) {
|
||||
+ final net.minecraft.resources.ResourceLocation location = org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(furnaceRecipe.getKey());
|
||||
+ java.util.Optional<net.minecraft.world.item.crafting.RecipeHolder<?>> nmsRecipe = (this.isPlaced() ? this.world.getHandle().getRecipeManager() : net.minecraft.server.MinecraftServer.getServer().getRecipeManager()).byKey(location);
|
||||
+ com.google.common.base.Preconditions.checkArgument(nmsRecipe.isPresent() && nmsRecipe.get().value() instanceof net.minecraft.world.item.crafting.AbstractCookingRecipe, furnaceRecipe.getKey() + " is not recognized as a valid and registered furnace recipe");
|
||||
+ if (count > 0) {
|
||||
+ this.getSnapshot().getRecipesUsed().put(location, count);
|
||||
+ } else {
|
||||
+ this.getSnapshot().getRecipesUsed().removeInt(location);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setRecipesUsed(java.util.Map<org.bukkit.inventory.CookingRecipe<?>, Integer> recipesUsed) {
|
||||
+ this.getSnapshot().getRecipesUsed().clear();
|
||||
+ recipesUsed.forEach((recipe, integer) -> {
|
||||
+ if (integer != null) {
|
||||
+ this.setRecipeUsedCount(recipe, integer);
|
||||
+ }
|
||||
+ });
|
||||
+ }
|
||||
// Paper end
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Thu, 19 Aug 2021 18:45:42 -0700
|
||||
Subject: [PATCH] Configurable sculk sensor listener range
|
||||
|
||||
== AT ==
|
||||
public-f net.minecraft.world.level.gameevent.vibrations.VibrationListener listenerRange
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/CalibratedSculkSensorBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/CalibratedSculkSensorBlockEntity.java
|
||||
index 41ccbee5fc7767a7d5e1cdca0ec7d9a17ee80a90..1d28f117965da22694b12018923a5f1347905085 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/CalibratedSculkSensorBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/CalibratedSculkSensorBlockEntity.java
|
||||
@@ -20,6 +20,12 @@ public class CalibratedSculkSensorBlockEntity extends SculkSensorBlockEntity {
|
||||
public VibrationSystem.User createVibrationUser() {
|
||||
return new CalibratedSculkSensorBlockEntity.VibrationUser(this.getBlockPos());
|
||||
}
|
||||
+ // Paper start - Configurable sculk sensor listener range
|
||||
+ @Override
|
||||
+ protected void saveRangeOverride(final net.minecraft.nbt.CompoundTag nbt) {
|
||||
+ if (this.rangeOverride != null && this.rangeOverride != 16) nbt.putInt(PAPER_LISTENER_RANGE_NBT_KEY, this.rangeOverride); // only save if it's different from the default
|
||||
+ }
|
||||
+ // Paper end - Configurable sculk sensor listener range
|
||||
|
||||
protected class VibrationUser extends SculkSensorBlockEntity.VibrationUser {
|
||||
public VibrationUser(final BlockPos pos) {
|
||||
@@ -28,6 +34,7 @@ public class CalibratedSculkSensorBlockEntity extends SculkSensorBlockEntity {
|
||||
|
||||
@Override
|
||||
public int getListenerRadius() {
|
||||
+ if (CalibratedSculkSensorBlockEntity.this.rangeOverride != null) return CalibratedSculkSensorBlockEntity.this.rangeOverride; // Paper - Configurable sculk sensor listener range
|
||||
return 16;
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/SculkSensorBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SculkSensorBlockEntity.java
|
||||
index 070814eb011ab8e02218c91e1cf75be5501c1a0a..28849cf84afcdc0d9fc245fac1a8d769a2db3b68 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/SculkSensorBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/SculkSensorBlockEntity.java
|
||||
@@ -26,6 +26,7 @@ public class SculkSensorBlockEntity extends BlockEntity implements GameEventList
|
||||
private final VibrationSystem.Listener vibrationListener;
|
||||
private final VibrationSystem.User vibrationUser = this.createVibrationUser();
|
||||
public int lastVibrationFrequency;
|
||||
+ @Nullable public Integer rangeOverride = null; // Paper - Configurable sculk sensor listener range
|
||||
|
||||
protected SculkSensorBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
||||
super(type, pos, state);
|
||||
@@ -52,8 +53,16 @@ public class SculkSensorBlockEntity extends BlockEntity implements GameEventList
|
||||
.resultOrPartial(string -> LOGGER.error("Failed to parse vibration listener for Sculk Sensor: '{}'", string))
|
||||
.ifPresent(listener -> this.vibrationData = listener);
|
||||
}
|
||||
+ // Paper start - Configurable sculk sensor listener range
|
||||
+ if (nbt.contains(PAPER_LISTENER_RANGE_NBT_KEY)) {
|
||||
+ this.rangeOverride = nbt.getInt(PAPER_LISTENER_RANGE_NBT_KEY);
|
||||
+ } else {
|
||||
+ this.rangeOverride = null;
|
||||
+ }
|
||||
+ // Paper end - Configurable sculk sensor listener range
|
||||
}
|
||||
|
||||
+ protected static final String PAPER_LISTENER_RANGE_NBT_KEY = "Paper.ListenerRange"; // Paper - Configurable sculk sensor listener range
|
||||
@Override
|
||||
protected void saveAdditional(CompoundTag nbt, HolderLookup.Provider registries) {
|
||||
super.saveAdditional(nbt, registries);
|
||||
@@ -63,7 +72,13 @@ public class SculkSensorBlockEntity extends BlockEntity implements GameEventList
|
||||
.encodeStart(registryOps, this.vibrationData)
|
||||
.resultOrPartial(string -> LOGGER.error("Failed to encode vibration listener for Sculk Sensor: '{}'", string))
|
||||
.ifPresent(listenerNbt -> nbt.put("listener", listenerNbt));
|
||||
+ this.saveRangeOverride(nbt); // Paper - Configurable sculk sensor listener range
|
||||
+ }
|
||||
+ // Paper start - Configurable sculk sensor listener range
|
||||
+ protected void saveRangeOverride(CompoundTag nbt) {
|
||||
+ if (this.rangeOverride != null && this.rangeOverride != VibrationUser.LISTENER_RANGE) nbt.putInt(PAPER_LISTENER_RANGE_NBT_KEY, this.rangeOverride); // only save if it's different from the default
|
||||
}
|
||||
+ // Paper end - Configurable sculk sensor listener range
|
||||
|
||||
@Override
|
||||
public VibrationSystem.Data getVibrationData() {
|
||||
@@ -100,6 +115,7 @@ public class SculkSensorBlockEntity extends BlockEntity implements GameEventList
|
||||
|
||||
@Override
|
||||
public int getListenerRadius() {
|
||||
+ if (SculkSensorBlockEntity.this.rangeOverride != null) return SculkSensorBlockEntity.this.rangeOverride; // Paper - Configurable sculk sensor listener range
|
||||
return 8;
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftSculkSensor.java b/src/main/java/org/bukkit/craftbukkit/block/CraftSculkSensor.java
|
||||
index 70d85dbfcaae7ee632a4f541334302b46615a254..6ba229afb0219ff229fd794c59d7585f010742ee 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftSculkSensor.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftSculkSensor.java
|
||||
@@ -36,4 +36,17 @@ public class CraftSculkSensor<T extends SculkSensorBlockEntity> extends CraftBlo
|
||||
public CraftSculkSensor<T> copy(Location location) {
|
||||
return new CraftSculkSensor<>(this, location);
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public int getListenerRange() {
|
||||
+ return this.getSnapshot().getListener().getListenerRadius();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setListenerRange(int range) {
|
||||
+ Preconditions.checkArgument(range > 0, "Vibration listener range must be greater than 0");
|
||||
+ this.getSnapshot().rangeOverride = range;
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
214
patches/server/0662-Add-missing-block-data-API.patch
Normal file
214
patches/server/0662-Add-missing-block-data-API.patch
Normal file
|
@ -0,0 +1,214 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sat, 16 Oct 2021 22:57:31 -0700
|
||||
Subject: [PATCH] Add missing block data API
|
||||
|
||||
General purpose patch adding missing getters/setters to BlockData and
|
||||
its child types.
|
||||
|
||||
Co-authored-by: SoSeDiK <mrsosedik@gmail.com>
|
||||
Co-authored-by: Fabrizio La Rosa <lr.fabrizio@gmail.com>
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftBed.java b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftBed.java
|
||||
index 2ccf3fbe3f991b7a014cff3bcd424e6a81bc310a..e5450d3511389bf3bd6461fb6ec65ea82e4ae9f0 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftBed.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftBed.java
|
||||
@@ -51,4 +51,11 @@ public final class CraftBed extends org.bukkit.craftbukkit.block.data.CraftBlock
|
||||
public java.util.Set<org.bukkit.block.BlockFace> getFaces() {
|
||||
return this.getValues(CraftBed.FACING, org.bukkit.block.BlockFace.class);
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public void setOccupied(boolean occupied) {
|
||||
+ set(CraftBed.OCCUPIED, occupied);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftCandle.java b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftCandle.java
|
||||
index 2230160d5e04e979467a56346600436c1e5dd70c..08436bfeba2f35fb11b16c4f71f76e13c0d44b1a 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftCandle.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftCandle.java
|
||||
@@ -31,6 +31,12 @@ public final class CraftCandle extends org.bukkit.craftbukkit.block.data.CraftBl
|
||||
public int getMaximumCandles() {
|
||||
return getMax(CraftCandle.CANDLES);
|
||||
}
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public int getMinimumCandles() {
|
||||
+ return getMin(CraftCandle.CANDLES);
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
// org.bukkit.craftbukkit.block.data.CraftLightable
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftCherryLeaves.java b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftCherryLeaves.java
|
||||
index af29ff861eb2c504ef31cc3236adf1e7f6b46049..bc32c5d4c7568ed4392e4bdb5872066846aa62b6 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftCherryLeaves.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftCherryLeaves.java
|
||||
@@ -51,4 +51,16 @@ public final class CraftCherryLeaves extends org.bukkit.craftbukkit.block.data.C
|
||||
public void setWaterlogged(boolean waterlogged) {
|
||||
this.set(CraftCherryLeaves.WATERLOGGED, waterlogged);
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public int getMaximumDistance() {
|
||||
+ return getMax(DISTANCE);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getMinimumDistance() {
|
||||
+ return getMin(DISTANCE);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftComposter.java b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftComposter.java
|
||||
index 7ce2e8b733bcd496dcfccb1ddfcb7c5c1b64052e..5ae27fc8f9d18bae949d335ea53e7e70917f0e80 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftComposter.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftComposter.java
|
||||
@@ -31,4 +31,11 @@ public final class CraftComposter extends org.bukkit.craftbukkit.block.data.Craf
|
||||
public int getMaximumLevel() {
|
||||
return getMax(CraftComposter.LEVEL);
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public int getMinimumLevel() {
|
||||
+ return getMin(CraftComposter.LEVEL);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftDecoratedPot.java b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftDecoratedPot.java
|
||||
index 356230b9b266974e36d0508f8c239714d673504d..b7ea9a6fba6b4fc157dfcc4bee099871b8ad7380 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftDecoratedPot.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftDecoratedPot.java
|
||||
@@ -45,4 +45,18 @@ public final class CraftDecoratedPot extends org.bukkit.craftbukkit.block.data.C
|
||||
public void setWaterlogged(boolean waterlogged) {
|
||||
this.set(CraftDecoratedPot.WATERLOGGED, waterlogged);
|
||||
}
|
||||
+
|
||||
+ // Paper start - add missing block data api
|
||||
+ private static final net.minecraft.world.level.block.state.properties.BooleanProperty CRACKED = getBoolean(net.minecraft.world.level.block.DecoratedPotBlock.class, "cracked");
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isCracked() {
|
||||
+ return this.get(CraftDecoratedPot.CRACKED);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setCracked(final boolean cracked) {
|
||||
+ this.set(CraftDecoratedPot.CRACKED, cracked);
|
||||
+ }
|
||||
+ // Paper end - add missing block data api
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftFluids.java b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftFluids.java
|
||||
index 70d734fc71a4499bbf569b3908aa5fbbdf19e6a0..1af5fe48c5861077555e6bdeb6312859b7b37eb2 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftFluids.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftFluids.java
|
||||
@@ -31,4 +31,11 @@ public final class CraftFluids extends org.bukkit.craftbukkit.block.data.CraftBl
|
||||
public int getMaximumLevel() {
|
||||
return getMax(CraftFluids.LEVEL);
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public int getMinimumLevel() {
|
||||
+ return getMin(CraftFluids.LEVEL);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftLayeredCauldron.java b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftLayeredCauldron.java
|
||||
index bf0d53f65f8a672c385b2e798b109a9662725f9e..c0e0cbceb0b5c36f4ac4672f217027a5898900a6 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftLayeredCauldron.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftLayeredCauldron.java
|
||||
@@ -31,4 +31,11 @@ public final class CraftLayeredCauldron extends org.bukkit.craftbukkit.block.dat
|
||||
public int getMaximumLevel() {
|
||||
return getMax(CraftLayeredCauldron.LEVEL);
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public int getMinimumLevel() {
|
||||
+ return getMin(CraftLayeredCauldron.LEVEL);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftLeaves.java b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftLeaves.java
|
||||
index 33d9a950ed678595fe2573e9f89a8d1716040503..ab336b400c1937ff86b681b27b1550e4b7f1ab79 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftLeaves.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftLeaves.java
|
||||
@@ -51,4 +51,16 @@ public final class CraftLeaves extends org.bukkit.craftbukkit.block.data.CraftBl
|
||||
public void setWaterlogged(boolean waterlogged) {
|
||||
this.set(CraftLeaves.WATERLOGGED, waterlogged);
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public int getMaximumDistance() {
|
||||
+ return getMax(CraftLeaves.DISTANCE);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getMinimumDistance() {
|
||||
+ return getMin(CraftLeaves.DISTANCE);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftLight.java b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftLight.java
|
||||
index 49f314b1447212a1a5a7623d2302b5960a44ce6e..8c936a95effa84ba0337d2aaf880cc561591fb33 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftLight.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftLight.java
|
||||
@@ -32,6 +32,13 @@ public final class CraftLight extends org.bukkit.craftbukkit.block.data.CraftBlo
|
||||
return getMax(CraftLight.LEVEL);
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public int getMinimumLevel() {
|
||||
+ return getMin(CraftLight.LEVEL);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
// org.bukkit.craftbukkit.block.data.CraftWaterlogged
|
||||
|
||||
private static final net.minecraft.world.level.block.state.properties.BooleanProperty WATERLOGGED = getBoolean(net.minecraft.world.level.block.LightBlock.class, "waterlogged");
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftMangroveLeaves.java b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftMangroveLeaves.java
|
||||
index 7a1f2fd2f7f8f1b46352fe2c4d0cdf23a88020fd..8b621aaeadcf2cc6e2ccdbab92f4ae2b89a6ca08 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftMangroveLeaves.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftMangroveLeaves.java
|
||||
@@ -51,4 +51,16 @@ public final class CraftMangroveLeaves extends org.bukkit.craftbukkit.block.data
|
||||
public void setWaterlogged(boolean waterlogged) {
|
||||
this.set(CraftMangroveLeaves.WATERLOGGED, waterlogged);
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public int getMinimumDistance() {
|
||||
+ return getMin(CraftMangroveLeaves.DISTANCE);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getMaximumDistance() {
|
||||
+ return getMax(CraftMangroveLeaves.DISTANCE);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftPinkPetals.java b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftPinkPetals.java
|
||||
index 78b220a6f460cd91ad1574c0d32f3e4288eaf431..0f7df1b4c58ba731832958043ba345ec77737e54 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftPinkPetals.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftPinkPetals.java
|
||||
@@ -27,6 +27,13 @@ public final class CraftPinkPetals extends org.bukkit.craftbukkit.block.data.Cra
|
||||
this.set(CraftPinkPetals.FLOWER_AMOUNT, flower_amount);
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public int getMinimumFlowerAmount() {
|
||||
+ return getMin(CraftPinkPetals.FLOWER_AMOUNT);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public int getMaximumFlowerAmount() {
|
||||
return getMax(CraftPinkPetals.FLOWER_AMOUNT);
|
|
@ -0,0 +1,32 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sat, 19 Feb 2022 20:15:41 -0800
|
||||
Subject: [PATCH] Option to have default CustomSpawners in custom worlds
|
||||
|
||||
By default, only LevelStem's that specifically match the ResourceKey for
|
||||
OVERWORLD will have the 5 (currently) impls of CustomSpawner (for
|
||||
phantoms, wandering traders, etc.). This adds an option to instead of
|
||||
just looking at the LevelStem key, look at the DimensionType key which
|
||||
is one level below that. Defaults to off to keep vanilla behavior.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index af392711da61a1921be1f82396c2a04dc897d563..7841421f00a3408e52b8d060674e6a686681210e 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -647,7 +647,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
this.commandStorage = new CommandStorage(worldpersistentdata);
|
||||
} else {
|
||||
ChunkProgressListener worldloadlistener = this.progressListenerFactory.create(this.worldData.getGameRules().getInt(GameRules.RULE_SPAWN_CHUNK_RADIUS));
|
||||
- world = new ServerLevel(this, this.executor, worldSession, iworlddataserver, worldKey, worlddimension, worldloadlistener, flag, j, ImmutableList.of(), true, this.overworld().getRandomSequences(), org.bukkit.World.Environment.getEnvironment(dimension), gen, biomeProvider);
|
||||
+ // Paper start - option to use the dimension_type to check if spawners should be added. I imagine mojang will add some datapack-y way of managing this in the future.
|
||||
+ final List<CustomSpawner> spawners;
|
||||
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().misc.useDimensionTypeForCustomSpawners && this.registryAccess().registryOrThrow(Registries.DIMENSION_TYPE).getResourceKey(worlddimension.type().value()).orElseThrow() == net.minecraft.world.level.dimension.BuiltinDimensionTypes.OVERWORLD) {
|
||||
+ spawners = list;
|
||||
+ } else {
|
||||
+ spawners = Collections.emptyList();
|
||||
+ }
|
||||
+ world = new ServerLevel(this, this.executor, worldSession, iworlddataserver, worldKey, worlddimension, worldloadlistener, flag, j, spawners, true, this.overworld().getRandomSequences(), org.bukkit.World.Environment.getEnvironment(dimension), gen, biomeProvider);
|
||||
+ // Paper end - option to use the dimension_type to check if spawners should be added
|
||||
}
|
||||
|
||||
worlddata.setModdedInfo(this.getServerModName(), this.getModdedStatus().shouldReportAsModified());
|
|
@ -0,0 +1,41 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Tue, 22 Feb 2022 14:21:35 -0800
|
||||
Subject: [PATCH] Put world into worldlist before initing the world
|
||||
|
||||
Some parts of legacy conversion will need the overworld
|
||||
to get the legacy structure data storage
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 7841421f00a3408e52b8d060674e6a686681210e..cc162b2046c7d39d9a85bcb69fc45e53d15fe5ef 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -659,9 +659,10 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
}
|
||||
|
||||
worlddata.setModdedInfo(this.getServerModName(), this.getModdedStatus().shouldReportAsModified());
|
||||
+ this.addLevel(world); // Paper - Put world into worldlist before initing the world; move up
|
||||
this.initWorld(world, worlddata, this.worldData, worldoptions);
|
||||
|
||||
- this.addLevel(world);
|
||||
+ // Paper - Put world into worldlist before initing the world; move up
|
||||
this.getPlayerList().addWorldborderListener(world);
|
||||
|
||||
if (worlddata.getCustomBossEvents() != null) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index b18ad8abb5e3c53b0e13544a6833198a670c1f34..29a71a050e49f1131ce9945c4275a33909ea3091 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -1337,10 +1337,11 @@ public final class CraftServer implements Server {
|
||||
return null;
|
||||
}
|
||||
|
||||
+ this.console.addLevel(internal); // Paper - Put world into worldlist before initing the world; move up
|
||||
this.console.initWorld(internal, worlddata, worlddata, worlddata.worldGenOptions());
|
||||
|
||||
internal.setSpawnSettings(true);
|
||||
- this.console.addLevel(internal);
|
||||
+ // Paper - Put world into worldlist before initing the world; move up
|
||||
|
||||
this.getServer().prepareLevels(internal.getChunkSource().chunkMap.progressListener, internal);
|
||||
internal.entityManager.tick(); // SPIGOT-6526: Load pending entities so they are available to the API
|
329
patches/server/0665-Custom-Potion-Mixes.patch
Normal file
329
patches/server/0665-Custom-Potion-Mixes.patch
Normal file
|
@ -0,0 +1,329 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Thu, 7 Oct 2021 14:34:55 -0700
|
||||
Subject: [PATCH] Custom Potion Mixes
|
||||
|
||||
== AT ==
|
||||
public-f net.minecraft.server.MinecraftServer potionBrewing
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/potion/PaperPotionBrewer.java b/src/main/java/io/papermc/paper/potion/PaperPotionBrewer.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..d9390227a2bba4e03aa9ee592ca157127633c41b
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/potion/PaperPotionBrewer.java
|
||||
@@ -0,0 +1,56 @@
|
||||
+package io.papermc.paper.potion;
|
||||
+
|
||||
+import com.google.common.base.Preconditions;
|
||||
+import java.util.Collection;
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
+import org.bukkit.NamespacedKey;
|
||||
+import org.bukkit.potion.PotionBrewer;
|
||||
+import org.bukkit.potion.PotionEffect;
|
||||
+import org.bukkit.potion.PotionType;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public class PaperPotionBrewer implements PotionBrewer {
|
||||
+
|
||||
+ private final MinecraftServer minecraftServer;
|
||||
+
|
||||
+ public PaperPotionBrewer(final MinecraftServer minecraftServer) {
|
||||
+ this.minecraftServer = minecraftServer;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ @Deprecated(forRemoval = true)
|
||||
+ public Collection<PotionEffect> getEffects(PotionType type, boolean upgraded, boolean extended) {
|
||||
+ final org.bukkit.NamespacedKey key = type.getKey();
|
||||
+
|
||||
+ Preconditions.checkArgument(!key.getKey().startsWith("strong_"), "Strong potion type cannot be used directly, got %s", key);
|
||||
+ Preconditions.checkArgument(!key.getKey().startsWith("long_"), "Extended potion type cannot be used directly, got %s", key);
|
||||
+
|
||||
+ org.bukkit.NamespacedKey effectiveKey = key;
|
||||
+ if (upgraded) {
|
||||
+ effectiveKey = new org.bukkit.NamespacedKey(key.namespace(), "strong_" + key.key());
|
||||
+ } else if (extended) {
|
||||
+ effectiveKey = new org.bukkit.NamespacedKey(key.namespace(), "long_" + key.key());
|
||||
+ }
|
||||
+
|
||||
+ final org.bukkit.potion.PotionType effectivePotionType = org.bukkit.Registry.POTION.get(effectiveKey);
|
||||
+ Preconditions.checkNotNull(type, "Unknown potion type from data " + effectiveKey.asMinimalString()); // Legacy error message in 1.20.4
|
||||
+ return effectivePotionType.getPotionEffects();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void addPotionMix(final PotionMix potionMix) {
|
||||
+ this.minecraftServer.potionBrewing().addPotionMix(potionMix);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void removePotionMix(final NamespacedKey key) {
|
||||
+ this.minecraftServer.potionBrewing.removePotionMix(key);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void resetPotionMixes() {
|
||||
+ this.minecraftServer.potionBrewing = this.minecraftServer.potionBrewing().reload(this.minecraftServer.getWorldData().enabledFeatures());
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/potion/PaperPotionMix.java b/src/main/java/io/papermc/paper/potion/PaperPotionMix.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..7ea357ac2f3a93db4ebdf24b5072be7d1cad3e33
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/potion/PaperPotionMix.java
|
||||
@@ -0,0 +1,21 @@
|
||||
+package io.papermc.paper.potion;
|
||||
+
|
||||
+import java.util.function.Predicate;
|
||||
+import net.minecraft.world.item.ItemStack;
|
||||
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
+import org.bukkit.craftbukkit.inventory.CraftRecipe;
|
||||
+import org.bukkit.inventory.RecipeChoice;
|
||||
+
|
||||
+public record PaperPotionMix(ItemStack result, Predicate<ItemStack> input, Predicate<ItemStack> ingredient) {
|
||||
+
|
||||
+ public PaperPotionMix(PotionMix potionMix) {
|
||||
+ this(CraftItemStack.asNMSCopy(potionMix.getResult()), convert(potionMix.getInput()), convert(potionMix.getIngredient()));
|
||||
+ }
|
||||
+
|
||||
+ static Predicate<ItemStack> convert(final RecipeChoice choice) {
|
||||
+ if (choice instanceof PredicateRecipeChoice predicateRecipeChoice) {
|
||||
+ return stack -> predicateRecipeChoice.test(CraftItemStack.asBukkitCopy(stack));
|
||||
+ }
|
||||
+ return CraftRecipe.toIngredient(choice, true);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index cc162b2046c7d39d9a85bcb69fc45e53d15fe5ef..0b9f4541cc0d0f27e811c1a6798d6758a2687b0c 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -2239,6 +2239,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
this.worldData.setDataConfiguration(worlddataconfiguration);
|
||||
this.resources.managers.updateStaticRegistryTags();
|
||||
this.resources.managers.getRecipeManager().finalizeRecipeLoading(this.worldData.enabledFeatures());
|
||||
+ this.potionBrewing = this.potionBrewing.reload(this.worldData.enabledFeatures()); // Paper - Custom Potion Mixes
|
||||
this.getPlayerList().saveAll();
|
||||
this.getPlayerList().reloadResources();
|
||||
this.functionManager.replaceLibrary(this.resources.managers.getFunctionLibrary());
|
||||
diff --git a/src/main/java/net/minecraft/world/inventory/BrewingStandMenu.java b/src/main/java/net/minecraft/world/inventory/BrewingStandMenu.java
|
||||
index b6ae648d1fa6382bc1fa5d21e45b09ec8c4c22ca..182c87a0b7081f6a777c4c7969961c30438b0d86 100644
|
||||
--- a/src/main/java/net/minecraft/world/inventory/BrewingStandMenu.java
|
||||
+++ b/src/main/java/net/minecraft/world/inventory/BrewingStandMenu.java
|
||||
@@ -54,9 +54,11 @@ public class BrewingStandMenu extends AbstractContainerMenu {
|
||||
this.brewingStandData = propertyDelegate;
|
||||
PotionBrewing potionbrewer = playerInventory.player.level().potionBrewing();
|
||||
|
||||
- this.addSlot(new BrewingStandMenu.PotionSlot(inventory, 0, 56, 51));
|
||||
- this.addSlot(new BrewingStandMenu.PotionSlot(inventory, 1, 79, 58));
|
||||
- this.addSlot(new BrewingStandMenu.PotionSlot(inventory, 2, 102, 51));
|
||||
+ // Paper start - custom potion mixes
|
||||
+ this.addSlot(new BrewingStandMenu.PotionSlot(inventory, 0, 56, 51, potionbrewer));
|
||||
+ this.addSlot(new BrewingStandMenu.PotionSlot(inventory, 1, 79, 58, potionbrewer));
|
||||
+ this.addSlot(new BrewingStandMenu.PotionSlot(inventory, 2, 102, 51, potionbrewer));
|
||||
+ // Paper end - custom potion mixes
|
||||
this.ingredientSlot = this.addSlot(new BrewingStandMenu.IngredientsSlot(potionbrewer, inventory, 3, 79, 17));
|
||||
this.addSlot(new BrewingStandMenu.FuelSlot(inventory, 4, 17, 17));
|
||||
this.addDataSlots(propertyDelegate);
|
||||
@@ -87,7 +89,7 @@ public class BrewingStandMenu extends AbstractContainerMenu {
|
||||
if (!this.moveItemStackTo(itemstack1, 3, 4, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
- } else if (BrewingStandMenu.PotionSlot.mayPlaceItem(itemstack)) {
|
||||
+ } else if (BrewingStandMenu.PotionSlot.mayPlaceItem(itemstack, this.player.player.level().potionBrewing())) { // Paper - custom potion mixes
|
||||
if (!this.moveItemStackTo(itemstack1, 0, 3, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
@@ -136,13 +138,15 @@ public class BrewingStandMenu extends AbstractContainerMenu {
|
||||
|
||||
private static class PotionSlot extends Slot {
|
||||
|
||||
- public PotionSlot(Container inventory, int index, int x, int y) {
|
||||
+ private final PotionBrewing potionBrewing; // Paper - custom potion mixes
|
||||
+ public PotionSlot(Container inventory, int index, int x, int y, PotionBrewing potionBrewing) { // Paper - custom potion mixes
|
||||
super(inventory, index, x, y);
|
||||
+ this.potionBrewing = potionBrewing; // Paper - custom potion mixes
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mayPlace(ItemStack stack) {
|
||||
- return PotionSlot.mayPlaceItem(stack);
|
||||
+ return PotionSlot.mayPlaceItem(stack, this.potionBrewing); // Paper - custom potion mixes
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -161,8 +165,8 @@ public class BrewingStandMenu extends AbstractContainerMenu {
|
||||
super.onTake(player, stack);
|
||||
}
|
||||
|
||||
- public static boolean mayPlaceItem(ItemStack stack) {
|
||||
- return stack.is(Items.POTION) || stack.is(Items.SPLASH_POTION) || stack.is(Items.LINGERING_POTION) || stack.is(Items.GLASS_BOTTLE);
|
||||
+ public static boolean mayPlaceItem(ItemStack stack, PotionBrewing potionBrewing) { // Paper - custom potion mixes
|
||||
+ return stack.is(Items.POTION) || stack.is(Items.SPLASH_POTION) || stack.is(Items.LINGERING_POTION) || stack.is(Items.GLASS_BOTTLE) || potionBrewing.isCustomInput(stack); // Paper - Custom Potion Mixes
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/item/alchemy/PotionBrewing.java b/src/main/java/net/minecraft/world/item/alchemy/PotionBrewing.java
|
||||
index 50e81e3babd331077eda8daa769eb2b3f99e8ca2..ca01f3344005b295c7ae98f6d5b03f79513b12a4 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/alchemy/PotionBrewing.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/alchemy/PotionBrewing.java
|
||||
@@ -19,6 +19,7 @@ public class PotionBrewing {
|
||||
private final List<Ingredient> containers;
|
||||
private final List<PotionBrewing.Mix<Potion>> potionMixes;
|
||||
private final List<PotionBrewing.Mix<Item>> containerMixes;
|
||||
+ private final it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap<org.bukkit.NamespacedKey, io.papermc.paper.potion.PaperPotionMix> customMixes = new it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap<>(); // Paper - Custom Potion Mixes
|
||||
|
||||
PotionBrewing(List<Ingredient> potionTypes, List<PotionBrewing.Mix<Potion>> potionRecipes, List<PotionBrewing.Mix<Item>> itemRecipes) {
|
||||
this.containers = potionTypes;
|
||||
@@ -27,7 +28,7 @@ public class PotionBrewing {
|
||||
}
|
||||
|
||||
public boolean isIngredient(ItemStack stack) {
|
||||
- return this.isContainerIngredient(stack) || this.isPotionIngredient(stack);
|
||||
+ return this.isContainerIngredient(stack) || this.isPotionIngredient(stack) || this.isCustomIngredient(stack); // Paper - Custom Potion Mixes
|
||||
}
|
||||
|
||||
private boolean isContainer(ItemStack stack) {
|
||||
@@ -71,6 +72,11 @@ public class PotionBrewing {
|
||||
}
|
||||
|
||||
public boolean hasMix(ItemStack input, ItemStack ingredient) {
|
||||
+ // Paper start - Custom Potion Mixes
|
||||
+ if (this.hasCustomMix(input, ingredient)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ // Paper end - Custom Potion Mixes
|
||||
return this.isContainer(input) && (this.hasContainerMix(input, ingredient) || this.hasPotionMix(input, ingredient));
|
||||
}
|
||||
|
||||
@@ -103,6 +109,13 @@ public class PotionBrewing {
|
||||
if (input.isEmpty()) {
|
||||
return input;
|
||||
} else {
|
||||
+ // Paper start - Custom Potion Mixes
|
||||
+ for (io.papermc.paper.potion.PaperPotionMix mix : this.customMixes.values()) {
|
||||
+ if (mix.input().test(input) && mix.ingredient().test(ingredient)) {
|
||||
+ return mix.result().copy();
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Custom Potion Mixes
|
||||
Optional<Holder<Potion>> optional = input.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY).potion();
|
||||
if (optional.isEmpty()) {
|
||||
return input;
|
||||
@@ -190,6 +203,50 @@ public class PotionBrewing {
|
||||
builder.addMix(Potions.SLOW_FALLING, Items.REDSTONE, Potions.LONG_SLOW_FALLING);
|
||||
}
|
||||
|
||||
+ // Paper start - Custom Potion Mixes
|
||||
+ public boolean isCustomIngredient(ItemStack stack) {
|
||||
+ for (io.papermc.paper.potion.PaperPotionMix mix : this.customMixes.values()) {
|
||||
+ if (mix.ingredient().test(stack)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ public boolean isCustomInput(ItemStack stack) {
|
||||
+ for (io.papermc.paper.potion.PaperPotionMix mix : this.customMixes.values()) {
|
||||
+ if (mix.input().test(stack)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ private boolean hasCustomMix(ItemStack input, ItemStack ingredient) {
|
||||
+ for (io.papermc.paper.potion.PaperPotionMix mix : this.customMixes.values()) {
|
||||
+ if (mix.input().test(input) && mix.ingredient().test(ingredient)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ public void addPotionMix(io.papermc.paper.potion.PotionMix mix) {
|
||||
+ if (this.customMixes.containsKey(mix.getKey())) {
|
||||
+ throw new IllegalArgumentException("Duplicate recipe ignored with ID " + mix.getKey());
|
||||
+ }
|
||||
+ this.customMixes.putAndMoveToFirst(mix.getKey(), new io.papermc.paper.potion.PaperPotionMix(mix));
|
||||
+ }
|
||||
+
|
||||
+ public boolean removePotionMix(org.bukkit.NamespacedKey key) {
|
||||
+ return this.customMixes.remove(key) != null;
|
||||
+ }
|
||||
+
|
||||
+ public PotionBrewing reload(FeatureFlagSet flags) {
|
||||
+ return bootstrap(flags);
|
||||
+ }
|
||||
+ // Paper end - Custom Potion Mixes
|
||||
+
|
||||
public static class Builder {
|
||||
private final List<Ingredient> containers = new ArrayList<>();
|
||||
private final List<PotionBrewing.Mix<Potion>> potionMixes = new ArrayList<>();
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java
|
||||
index e167c2834f1b7899a7d11cef782940deeb739a9c..2bafacd7bc56186d9105d2031180f8c4a6940018 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java
|
||||
@@ -316,12 +316,12 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements
|
||||
|
||||
@Override
|
||||
public boolean canPlaceItem(int slot, ItemStack stack) {
|
||||
+ PotionBrewing potionbrewer = this.level != null ? this.level.potionBrewing() : PotionBrewing.EMPTY; // Paper - move up
|
||||
if (slot == 3) {
|
||||
- PotionBrewing potionbrewer = this.level != null ? this.level.potionBrewing() : PotionBrewing.EMPTY;
|
||||
|
||||
return potionbrewer.isIngredient(stack);
|
||||
} else {
|
||||
- return slot == 4 ? stack.is(ItemTags.BREWING_FUEL) : (stack.is(Items.POTION) || stack.is(Items.SPLASH_POTION) || stack.is(Items.LINGERING_POTION) || stack.is(Items.GLASS_BOTTLE)) && this.getItem(slot).isEmpty();
|
||||
+ return slot == 4 ? stack.is(ItemTags.BREWING_FUEL) : (stack.is(Items.POTION) || stack.is(Items.SPLASH_POTION) || stack.is(Items.LINGERING_POTION) || stack.is(Items.GLASS_BOTTLE) || potionbrewer.isCustomInput(stack)) && this.getItem(slot).isEmpty(); // Paper - Custom Potion Mixes
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index 29a71a050e49f1131ce9945c4275a33909ea3091..f0eb8284b537014b591e45f034f1498e7e687e54 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -311,6 +311,7 @@ public final class CraftServer implements Server {
|
||||
private final io.papermc.paper.datapack.PaperDatapackManager datapackManager; // Paper
|
||||
public static Exception excessiveVelEx; // Paper - Velocity warnings
|
||||
private final io.papermc.paper.logging.SysoutCatcher sysoutCatcher = new io.papermc.paper.logging.SysoutCatcher(); // Paper
|
||||
+ private final io.papermc.paper.potion.PaperPotionBrewer potionBrewer; // Paper - Custom Potion Mixes
|
||||
|
||||
static {
|
||||
ConfigurationSerialization.registerClass(CraftOfflinePlayer.class);
|
||||
@@ -395,6 +396,7 @@ public final class CraftServer implements Server {
|
||||
if (this.configuration.getBoolean("settings.use-map-color-cache")) {
|
||||
MapPalette.setMapColorCache(new CraftMapColorCache(this.logger));
|
||||
}
|
||||
+ this.potionBrewer = new io.papermc.paper.potion.PaperPotionBrewer(console); // Paper - custom potion mixes
|
||||
datapackManager = new io.papermc.paper.datapack.PaperDatapackManager(console.getPackRepository()); // Paper
|
||||
}
|
||||
|
||||
@@ -3067,5 +3069,9 @@ public final class CraftServer implements Server {
|
||||
return datapackManager;
|
||||
}
|
||||
|
||||
+ @Override
|
||||
+ public io.papermc.paper.potion.PaperPotionBrewer getPotionBrewer() {
|
||||
+ return this.potionBrewer;
|
||||
+ }
|
||||
// Paper end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java
|
||||
index 6f1da5aa8714d64b8454dc79258f941ead986e46..a68e036a12b354c4f04b6596dfb9cd6e7663718b 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java
|
||||
@@ -25,6 +25,11 @@ public interface CraftRecipe extends Recipe {
|
||||
}
|
||||
|
||||
default Ingredient toNMS(RecipeChoice bukkit, boolean requireNotEmpty) {
|
||||
+ // Paper start
|
||||
+ return toIngredient(bukkit, requireNotEmpty);
|
||||
+ }
|
||||
+ static Ingredient toIngredient(RecipeChoice bukkit, boolean requireNotEmpty) {
|
||||
+ // Paper end
|
||||
Ingredient stack;
|
||||
|
||||
if (bukkit == null) {
|
32
patches/server/0666-Force-close-world-loading-screen.patch
Normal file
32
patches/server/0666-Force-close-world-loading-screen.patch
Normal file
|
@ -0,0 +1,32 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Nassim Jahnke <nassim@njahnke.dev>
|
||||
Date: Wed, 2 Mar 2022 09:45:56 +0100
|
||||
Subject: [PATCH] Force close world loading screen
|
||||
|
||||
Dead players would be stuck in the world loading screen and other players may
|
||||
miss messages and similar sent in the join event if chunk loading is slow.
|
||||
Paper already circumvents falling through the world before chunks are loaded,
|
||||
so we do not need that. The client only needs the chunk it is currently in to
|
||||
be loaded to close the loading screen, so we just send an empty one.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
index f34cad30c982f2bb563f0deab030111720858fa8..f65b583057d37ec64a7cd9ed3ec09448064576db 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
@@ -179,6 +179,16 @@ public abstract class PlayerList {
|
||||
this.registries = registryManager;
|
||||
this.maxPlayers = maxPlayers;
|
||||
this.playerIo = saveHandler;
|
||||
+ // Paper start - Send empty chunk, so players aren't stuck in the world loading screen with our chunk system not sending chunks when dead
|
||||
+ if (player.isDeadOrDying()) {
|
||||
+ net.minecraft.core.Holder<net.minecraft.world.level.biome.Biome> plains = worldserver1.registryAccess().registryOrThrow(net.minecraft.core.registries.Registries.BIOME)
|
||||
+ .getHolderOrThrow(net.minecraft.world.level.biome.Biomes.PLAINS);
|
||||
+ player.connection.send(new net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket(
|
||||
+ new net.minecraft.world.level.chunk.EmptyLevelChunk(worldserver1, player.chunkPosition(), plains),
|
||||
+ worldserver1.getLightEngine(), (java.util.BitSet)null, (java.util.BitSet) null)
|
||||
+ );
|
||||
+ }
|
||||
+ // Paper end - Send empty chunk
|
||||
}
|
||||
abstract public void loadAndSaveFiles(); // Paper - fix converting txt to json file; moved from DedicatedPlayerList constructor
|
||||
|
57
patches/server/0667-Fix-falling-block-spawn-methods.patch
Normal file
57
patches/server/0667-Fix-falling-block-spawn-methods.patch
Normal file
|
@ -0,0 +1,57 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Nassim Jahnke <nassim@njahnke.dev>
|
||||
Date: Fri, 4 Mar 2022 20:35:19 +0100
|
||||
Subject: [PATCH] Fix falling block spawn methods
|
||||
|
||||
Restores the API behavior from previous versions of the server
|
||||
- Do not call API events
|
||||
- Do not replace the existing block in the world
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.entity.item.FallingBlockEntity <init>(Lnet/minecraft/world/level/Level;DDDLnet/minecraft/world/level/block/state/BlockState;)V
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
index 7dc167950021371b5cf8a7e1e38f013220e1c8a6..9ea74d52112ab4feea3f4bafd82351a72088cbc5 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
@@ -1405,7 +1405,12 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
Preconditions.checkArgument(material != null, "Material cannot be null");
|
||||
Preconditions.checkArgument(material.isBlock(), "Material.%s must be a block", material);
|
||||
|
||||
- FallingBlockEntity entity = FallingBlockEntity.fall(this.world, BlockPos.containing(location.getX(), location.getY(), location.getZ()), CraftBlockType.bukkitToMinecraft(material).defaultBlockState(), SpawnReason.CUSTOM);
|
||||
+ // Paper start - restore API behavior for spawning falling blocks
|
||||
+ FallingBlockEntity entity = new FallingBlockEntity(this.world, location.getX(), location.getY(), location.getZ(), CraftBlockType.bukkitToMinecraft(material).defaultBlockState()); // Paper
|
||||
+ entity.time = 1;
|
||||
+
|
||||
+ this.world.addFreshEntity(entity, SpawnReason.CUSTOM);
|
||||
+ // Paper end - restore API behavior for spawning falling blocks
|
||||
return (FallingBlock) entity.getBukkitEntity();
|
||||
}
|
||||
|
||||
@@ -1414,7 +1419,12 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
Preconditions.checkArgument(location != null, "Location cannot be null");
|
||||
Preconditions.checkArgument(data != null, "BlockData cannot be null");
|
||||
|
||||
- FallingBlockEntity entity = FallingBlockEntity.fall(this.world, BlockPos.containing(location.getX(), location.getY(), location.getZ()), ((CraftBlockData) data).getState(), SpawnReason.CUSTOM);
|
||||
+ // Paper start - restore API behavior for spawning falling blocks
|
||||
+ FallingBlockEntity entity = new FallingBlockEntity(this.world, location.getX(), location.getY(), location.getZ(), ((CraftBlockData) data).getState());
|
||||
+ entity.time = 1;
|
||||
+
|
||||
+ this.world.addFreshEntity(entity, SpawnReason.CUSTOM);
|
||||
+ // Paper end - restore API behavior for spawning falling blocks
|
||||
return (FallingBlock) entity.getBukkitEntity();
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java
|
||||
index 42ecef3dbb888ba716b6f63335efca6fb0f27457..b79e72a77178f755957ef391b6444a357bdefbd0 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java
|
||||
@@ -440,7 +440,7 @@ public final class CraftEntityTypes {
|
||||
register(new EntityTypeData<>(EntityType.TNT, TNTPrimed.class, CraftTNTPrimed::new, spawnData -> new PrimedTnt(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), null)));
|
||||
register(new EntityTypeData<>(EntityType.FALLING_BLOCK, FallingBlock.class, CraftFallingBlock::new, spawnData -> {
|
||||
BlockPos pos = BlockPos.containing(spawnData.x(), spawnData.y(), spawnData.z());
|
||||
- return FallingBlockEntity.fall(spawnData.minecraftWorld(), pos, spawnData.world().getBlockState(pos));
|
||||
+ return new FallingBlockEntity(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), spawnData.world().getBlockState(pos)); // Paper - create falling block entities correctly
|
||||
}));
|
||||
register(new EntityTypeData<>(EntityType.FIREWORK_ROCKET, Firework.class, CraftFirework::new, spawnData -> new FireworkRocketEntity(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), net.minecraft.world.item.ItemStack.EMPTY)));
|
||||
register(new EntityTypeData<>(EntityType.EVOKER_FANGS, EvokerFangs.class, CraftEvokerFangs::new, spawnData -> new net.minecraft.world.entity.projectile.EvokerFangs(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), (float) Math.toRadians(spawnData.yaw()), 0, null)));
|
|
@ -0,0 +1,40 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: EpicKnarvik97 <kristian.knarvik@knett.no>
|
||||
Date: Sat, 5 Mar 2022 20:58:46 +0100
|
||||
Subject: [PATCH] Expose furnace minecart push values
|
||||
|
||||
Adds methods for getting and setting a furnace minecart's push values
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartFurnace.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartFurnace.java
|
||||
index 53042b75b45093535d6572239b34c3ff9a72f648..1b41026ab638bb2764b19429706eb0aded5aad12 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartFurnace.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartFurnace.java
|
||||
@@ -27,6 +27,28 @@ public class CraftMinecartFurnace extends CraftMinecart implements PoweredMineca
|
||||
this.getHandle().fuel = fuel;
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public double getPushX() {
|
||||
+ return getHandle().xPush;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public double getPushZ() {
|
||||
+ return getHandle().zPush;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setPushX(double xPush) {
|
||||
+ getHandle().xPush = xPush;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setPushZ(double zPush) {
|
||||
+ getHandle().zPush = zPush;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CraftMinecartFurnace";
|
|
@ -0,0 +1,40 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sat, 19 Feb 2022 19:05:59 -0800
|
||||
Subject: [PATCH] Fix cancelling ProjectileHitEvent for piercing arrows
|
||||
|
||||
Piercing arrows search for multiple entities inside a while
|
||||
loop that is checking the projectile entity's removed state.
|
||||
If the hit event is cancelled on the first entity, the event will
|
||||
be called over and over again inside that while loop until the event
|
||||
is not cancelled. The solution here, is to make use of an
|
||||
already-existing field on AbstractArrow for tracking entities hit by
|
||||
piercing arrows to avoid duplicate damage being applied.
|
||||
|
||||
== AT ==
|
||||
protected net.minecraft.world.entity.projectile.Projectile hitCancelled
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
|
||||
index 44bcb1117cfa4d66c500011489ae193a0d1e7d78..75cc3db39c974abab8510af4a633fc6812efc647 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
|
||||
@@ -344,6 +344,19 @@ public abstract class AbstractArrow extends Projectile {
|
||||
|
||||
}
|
||||
|
||||
+ // Paper start - Fix cancelling ProjectileHitEvent for piercing arrows
|
||||
+ @Override
|
||||
+ public ProjectileDeflection preHitTargetOrDeflectSelf(HitResult hitResult) {
|
||||
+ if (hitResult instanceof EntityHitResult entityHitResult && this.hitCancelled && this.getPierceLevel() > 0) {
|
||||
+ if (this.piercingIgnoreEntityIds == null) {
|
||||
+ this.piercingIgnoreEntityIds = new IntOpenHashSet(5);
|
||||
+ }
|
||||
+ this.piercingIgnoreEntityIds.add(entityHitResult.getEntity().getId());
|
||||
+ }
|
||||
+ return super.preHitTargetOrDeflectSelf(hitResult);
|
||||
+ }
|
||||
+ // Paper end - Fix cancelling ProjectileHitEvent for piercing arrows
|
||||
+
|
||||
@Override
|
||||
protected double getDefaultGravity() {
|
||||
return 0.05D;
|
931
patches/server/0670-More-Projectile-API.patch
Normal file
931
patches/server/0670-More-Projectile-API.patch
Normal file
|
@ -0,0 +1,931 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
|
||||
Date: Tue, 22 Jun 2021 23:41:11 -0400
|
||||
Subject: [PATCH] More Projectile API
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.entity.projectile.FishingHook timeUntilLured
|
||||
public net.minecraft.world.entity.projectile.FishingHook fishAngle
|
||||
public net.minecraft.world.entity.projectile.ShulkerBullet targetDeltaX
|
||||
public net.minecraft.world.entity.projectile.ShulkerBullet targetDeltaY
|
||||
public net.minecraft.world.entity.projectile.ShulkerBullet targetDeltaZ
|
||||
public net.minecraft.world.entity.projectile.ShulkerBullet currentMoveDirection
|
||||
public net.minecraft.world.entity.projectile.ShulkerBullet flightSteps
|
||||
public net.minecraft.world.entity.projectile.AbstractArrow soundEvent
|
||||
public net.minecraft.world.entity.projectile.AbstractArrow setPickupItemStack(Lnet/minecraft/world/item/ItemStack;)V
|
||||
public net.minecraft.world.entity.projectile.ThrownTrident dealtDamage
|
||||
public net.minecraft.world.entity.projectile.Arrow NO_EFFECT_COLOR
|
||||
public net.minecraft.world.entity.projectile.Projectile hasBeenShot
|
||||
public net.minecraft.world.entity.projectile.Projectile leftOwner
|
||||
public net.minecraft.world.entity.projectile.Projectile preOnHit(Lnet/minecraft/world/phys/HitResult;)V
|
||||
public net.minecraft.world.entity.projectile.Projectile canHitEntity(Lnet/minecraft/world/entity/Entity;)Z
|
||||
public net.minecraft.world.entity.projectile.FireworkRocketEntity getDefaultItem()Lnet/minecraft/world/item/ItemStack;
|
||||
public net.minecraft.world.item.CrossbowItem FIREWORK_POWER
|
||||
|
||||
Co-authored-by: Nassim Jahnke <nassim@njahnke.dev>
|
||||
Co-authored-by: SoSeDiK <mrsosedik@gmail.com>
|
||||
Co-authored-by: MelnCat <melncatuwu@gmail.com>
|
||||
Co-authored-by: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
|
||||
index 536196a740f607adda2a5ae7f644981ac26bef98..1f95234c0a1457050574aa0f6c4b2a8c91b1f272 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
|
||||
@@ -419,13 +419,18 @@ public class FishingHook extends Projectile {
|
||||
}
|
||||
} else {
|
||||
// CraftBukkit start - logic to modify fishing wait time
|
||||
- this.timeUntilLured = Mth.nextInt(this.random, this.minWaitTime, this.maxWaitTime);
|
||||
- this.timeUntilLured -= (this.applyLure) ? (this.lureSpeed >= this.maxWaitTime ? this.timeUntilLured - 1 : this.lureSpeed ) : 0; // Paper - Fix Lure infinite loop
|
||||
+ this.resetTimeUntilLured(); // Paper - more projectile api - extract time until lured reset logic
|
||||
// CraftBukkit end
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+ // Paper start - more projectile api - extract time until lured reset logic
|
||||
+ public void resetTimeUntilLured() {
|
||||
+ this.timeUntilLured = Mth.nextInt(this.random, this.minWaitTime, this.maxWaitTime);
|
||||
+ this.timeUntilLured -= (this.applyLure) ? (this.lureSpeed >= this.maxWaitTime ? this.timeUntilLured - 1 : this.lureSpeed ) : 0; // Paper - Fix Lure infinite loop
|
||||
+ }
|
||||
+ // Paper end - more projectile api - extract time until lured reset logic
|
||||
|
||||
public boolean calculateOpenWater(BlockPos pos) {
|
||||
FishingHook.OpenWaterType entityfishinghook_waterposition = FishingHook.OpenWaterType.INVALID;
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
|
||||
index 2cb77d0b6e6ba880a2a76488a870a20ed883b15a..846a108af8bacdcaf3a17db9fb808965ce2581bb 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
|
||||
@@ -288,7 +288,7 @@ public abstract class Projectile extends Entity implements TraceableEntity {
|
||||
}
|
||||
|
||||
// CraftBukkit start - call projectile hit event
|
||||
- protected ProjectileDeflection preHitTargetOrDeflectSelf(HitResult movingobjectposition) {
|
||||
+ public ProjectileDeflection preHitTargetOrDeflectSelf(HitResult movingobjectposition) { // Paper - protected -> public
|
||||
org.bukkit.event.entity.ProjectileHitEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileHitEvent(this, movingobjectposition);
|
||||
this.hitCancelled = event != null && event.isCancelled();
|
||||
if (movingobjectposition.getType() == HitResult.Type.BLOCK || !this.hitCancelled) {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java
|
||||
index d6ac07d9d5ee0430a1d91b7084b378aac1d047e5..a486466040a646b8a5a5ff2430cdd25b95b7e20f 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java
|
||||
@@ -103,8 +103,12 @@ public class ThrownPotion extends ThrowableItemProjectile {
|
||||
@Override
|
||||
protected void onHit(HitResult hitResult) {
|
||||
super.onHit(hitResult);
|
||||
+ // Paper start - More projectile API
|
||||
+ this.splash(hitResult);
|
||||
+ }
|
||||
+ public void splash(@Nullable HitResult hitResult) {
|
||||
+ // Paper end - More projectile API
|
||||
Level world = this.level();
|
||||
-
|
||||
if (world instanceof ServerLevel worldserver) {
|
||||
ItemStack itemstack = this.getItem();
|
||||
PotionContents potioncontents = (PotionContents) itemstack.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY);
|
||||
@@ -116,7 +120,7 @@ public class ThrownPotion extends ThrowableItemProjectile {
|
||||
if (this.isLingering()) {
|
||||
showParticles = this.makeAreaOfEffectCloud(potioncontents, hitResult); // CraftBukkit - Pass MovingObjectPosition // Paper
|
||||
} else {
|
||||
- showParticles = this.applySplash(worldserver, potioncontents.getAllEffects(), hitResult.getType() == HitResult.Type.ENTITY ? ((EntityHitResult) hitResult).getEntity() : null, hitResult); // CraftBukkit - Pass MovingObjectPosition // Paper
|
||||
+ showParticles = this.applySplash(worldserver, potioncontents.getAllEffects(), hitResult != null && hitResult.getType() == HitResult.Type.ENTITY ? ((EntityHitResult) hitResult).getEntity() : null, hitResult); // CraftBukkit - Pass MovingObjectPosition // Paper - More projectile API
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,7 +182,7 @@ public class ThrownPotion extends ThrowableItemProjectile {
|
||||
|
||||
}
|
||||
|
||||
- private boolean applySplash(ServerLevel worldserver, Iterable<MobEffectInstance> iterable, @Nullable Entity entity, HitResult position) { // CraftBukkit - Pass MovingObjectPosition // Paper - Fix potions splash events
|
||||
+ private boolean applySplash(ServerLevel worldserver, Iterable<MobEffectInstance> iterable, @Nullable Entity entity, @Nullable HitResult position) { // CraftBukkit - Pass MovingObjectPosition // Paper - Fix potions splash events & More projectile API
|
||||
AABB axisalignedbb = this.getBoundingBox().inflate(4.0D, 2.0D, 4.0D);
|
||||
List<net.minecraft.world.entity.LivingEntity> list = worldserver.getEntitiesOfClass(net.minecraft.world.entity.LivingEntity.class, axisalignedbb);
|
||||
Map<LivingEntity, Double> affected = new HashMap<LivingEntity, Double>(); // CraftBukkit
|
||||
@@ -256,7 +260,7 @@ public class ThrownPotion extends ThrowableItemProjectile {
|
||||
|
||||
}
|
||||
|
||||
- private boolean makeAreaOfEffectCloud(PotionContents potioncontents, HitResult position) { // CraftBukkit - Pass MovingObjectPosition
|
||||
+ private boolean makeAreaOfEffectCloud(PotionContents potioncontents, @Nullable HitResult position) { // CraftBukkit - Pass MovingObjectPosition // Paper - More projectile API
|
||||
AreaEffectCloud entityareaeffectcloud = new AreaEffectCloud(this.level(), this.getX(), this.getY(), this.getZ());
|
||||
Entity entity = this.getOwner();
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/AbstractProjectile.java b/src/main/java/org/bukkit/craftbukkit/entity/AbstractProjectile.java
|
||||
index 91c2d0b40d3fca86938cd454e1415a4eea3df7c7..de4fb2654c7895cfd83ad694455ee56cb708c2f2 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/AbstractProjectile.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/AbstractProjectile.java
|
||||
@@ -17,4 +17,65 @@ public abstract class AbstractProjectile extends CraftEntity implements Projecti
|
||||
@Override
|
||||
public void setBounce(boolean doesBounce) {}
|
||||
|
||||
+ // Paper start - More projectile API
|
||||
+ @Override
|
||||
+ public boolean hasLeftShooter() {
|
||||
+ return this.getHandle().leftOwner;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setHasLeftShooter(boolean leftShooter) {
|
||||
+ this.getHandle().leftOwner = leftShooter;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean hasBeenShot() {
|
||||
+ return this.getHandle().hasBeenShot;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setHasBeenShot(boolean beenShot) {
|
||||
+ this.getHandle().hasBeenShot = beenShot;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean canHitEntity(org.bukkit.entity.Entity entity) {
|
||||
+ return this.getHandle().canHitEntity(((CraftEntity) entity).getHandle());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void hitEntity(org.bukkit.entity.Entity entity) {
|
||||
+ this.getHandle().preHitTargetOrDeflectSelf(new net.minecraft.world.phys.EntityHitResult(((CraftEntity) entity).getHandle()));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void hitEntity(org.bukkit.entity.Entity entity, org.bukkit.util.Vector vector) {
|
||||
+ this.getHandle().preHitTargetOrDeflectSelf(new net.minecraft.world.phys.EntityHitResult(((CraftEntity) entity).getHandle(), new net.minecraft.world.phys.Vec3(vector.getX(), vector.getY(), vector.getZ())));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public net.minecraft.world.entity.projectile.Projectile getHandle() {
|
||||
+ return (net.minecraft.world.entity.projectile.Projectile) entity;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public final org.bukkit.projectiles.ProjectileSource getShooter() {
|
||||
+ return this.getHandle().projectileSource;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public final void setShooter(org.bukkit.projectiles.ProjectileSource shooter) {
|
||||
+ if (shooter instanceof CraftEntity craftEntity) {
|
||||
+ this.getHandle().setOwner(craftEntity.getHandle());
|
||||
+ } else {
|
||||
+ this.getHandle().setOwner(null);
|
||||
+ }
|
||||
+ this.getHandle().projectileSource = shooter;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public java.util.UUID getOwnerUniqueId() {
|
||||
+ return this.getHandle().ownerUUID;
|
||||
+ }
|
||||
+ // Paper end - More projectile API
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractArrow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractArrow.java
|
||||
index 0f85c1f991469b277bba8b40b087f7224b4b3a85..1f30109abd86b76af343eb5eb75ec3db83ef9417 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractArrow.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractArrow.java
|
||||
@@ -59,20 +59,7 @@ public class CraftAbstractArrow extends AbstractProjectile implements AbstractAr
|
||||
this.getHandle().setCritArrow(critical);
|
||||
}
|
||||
|
||||
- @Override
|
||||
- public ProjectileSource getShooter() {
|
||||
- return this.getHandle().projectileSource;
|
||||
- }
|
||||
-
|
||||
- @Override
|
||||
- public void setShooter(ProjectileSource shooter) {
|
||||
- if (shooter instanceof Entity) {
|
||||
- this.getHandle().setOwner(((CraftEntity) shooter).getHandle());
|
||||
- } else {
|
||||
- this.getHandle().setOwner(null);
|
||||
- }
|
||||
- this.getHandle().projectileSource = shooter;
|
||||
- }
|
||||
+ // Paper - moved to AbstractProjectile
|
||||
|
||||
@Override
|
||||
public boolean isInBlock() {
|
||||
@@ -133,6 +120,7 @@ public class CraftAbstractArrow extends AbstractProjectile implements AbstractAr
|
||||
|
||||
@Override
|
||||
public ItemStack getWeapon() {
|
||||
+ if (this.getHandle().getWeaponItem() == null) return null; // Paper - fix NPE
|
||||
return CraftItemStack.asBukkitCopy(this.getHandle().getWeaponItem());
|
||||
}
|
||||
|
||||
@@ -152,4 +140,37 @@ public class CraftAbstractArrow extends AbstractProjectile implements AbstractAr
|
||||
public String toString() {
|
||||
return "CraftArrow";
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public CraftItemStack getItemStack() {
|
||||
+ return CraftItemStack.asCraftMirror(this.getHandle().getPickupItem());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setItemStack(final ItemStack stack) {
|
||||
+ Preconditions.checkArgument(stack != null, "ItemStack cannot be null");
|
||||
+ this.getHandle().setPickupItemStack(CraftItemStack.asNMSCopy(stack));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setLifetimeTicks(int ticks) {
|
||||
+ this.getHandle().life = ticks;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getLifetimeTicks() {
|
||||
+ return this.getHandle().life;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public org.bukkit.Sound getHitSound() {
|
||||
+ return org.bukkit.craftbukkit.CraftSound.minecraftToBukkit(this.getHandle().soundEvent);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setHitSound(org.bukkit.Sound sound) {
|
||||
+ this.getHandle().setSoundEvent(org.bukkit.craftbukkit.CraftSound.bukkitToMinecraft(sound));
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAreaEffectCloud.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAreaEffectCloud.java
|
||||
index 6591513bb62226b6f85fd2ef9f6ebe376f0f7362..f9c113dc018702159345240d6d0de85767afa0c3 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAreaEffectCloud.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAreaEffectCloud.java
|
||||
@@ -125,7 +125,7 @@ public class CraftAreaEffectCloud extends CraftEntity implements AreaEffectCloud
|
||||
|
||||
@Override
|
||||
public Color getColor() {
|
||||
- return Color.fromRGB(this.getHandle().potionContents.getColor());
|
||||
+ return Color.fromRGB(this.getHandle().potionContents.getColor() & 0x00FFFFFF); // Paper - skip alpha channel
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -143,7 +143,7 @@ public class CraftAreaEffectCloud extends CraftEntity implements AreaEffectCloud
|
||||
this.removeCustomEffect(effect.getType());
|
||||
}
|
||||
this.getHandle().addEffect(CraftPotionUtil.fromBukkit(effect));
|
||||
- this.getHandle().updateColor();
|
||||
+ // this.getHandle().updateColor(); // Paper - already done above
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@ public class CraftAreaEffectCloud extends CraftEntity implements AreaEffectCloud
|
||||
public void clearCustomEffects() {
|
||||
PotionContents old = this.getHandle().potionContents;
|
||||
this.getHandle().setPotionContents(new PotionContents(old.potion(), old.customColor(), List.of(), old.customName()));
|
||||
- this.getHandle().updateColor();
|
||||
+ // this.getHandle().updateColor(); // Paper - already done above
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java
|
||||
index 199d5836dc787cca54c6b653a4e67573f2f758a2..15d50a284cafc2eb59239ca00926836526f09e06 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java
|
||||
@@ -43,7 +43,7 @@ public class CraftArrow extends CraftAbstractArrow implements Arrow {
|
||||
this.removeCustomEffect(effect.getType());
|
||||
}
|
||||
this.getHandle().addEffect(CraftPotionUtil.fromBukkit(effect));
|
||||
- this.getHandle().updateColor();
|
||||
+ // this.getHandle().updateColor(); // Paper - already done above
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ public class CraftArrow extends CraftAbstractArrow implements Arrow {
|
||||
public void clearCustomEffects() {
|
||||
PotionContents old = this.getHandle().getPotionContents();
|
||||
this.getHandle().setPotionContents(new PotionContents(old.potion(), old.customColor(), List.of(), old.customName()));
|
||||
- this.getHandle().updateColor();
|
||||
+ // this.getHandle().updateColor(); // Paper - already done above
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -117,16 +117,17 @@ public class CraftArrow extends CraftAbstractArrow implements Arrow {
|
||||
|
||||
@Override
|
||||
public void setColor(Color color) {
|
||||
- int colorRGB = (color == null) ? -1 : color.asRGB();
|
||||
+ int colorRGB = (color == null) ? net.minecraft.world.entity.projectile.Arrow.NO_EFFECT_COLOR : color.asARGB(); // Paper
|
||||
PotionContents old = this.getHandle().getPotionContents();
|
||||
this.getHandle().setPotionContents(new PotionContents(old.potion(), Optional.of(colorRGB), old.customEffects(), old.customName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getColor() {
|
||||
- if (this.getHandle().getColor() <= -1) {
|
||||
+ int color = this.getHandle().getColor(); // Paper
|
||||
+ if (color == net.minecraft.world.entity.projectile.Arrow.NO_EFFECT_COLOR) { // Paper
|
||||
return null;
|
||||
}
|
||||
- return Color.fromRGB(this.getHandle().getColor());
|
||||
+ return Color.fromARGB(color); // Paper
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java
|
||||
index b79e72a77178f755957ef391b6444a357bdefbd0..39ea25d2145acaa7c7b458800adc674a3e73e7c1 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java
|
||||
@@ -442,7 +442,7 @@ public final class CraftEntityTypes {
|
||||
BlockPos pos = BlockPos.containing(spawnData.x(), spawnData.y(), spawnData.z());
|
||||
return new FallingBlockEntity(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), spawnData.world().getBlockState(pos)); // Paper - create falling block entities correctly
|
||||
}));
|
||||
- register(new EntityTypeData<>(EntityType.FIREWORK_ROCKET, Firework.class, CraftFirework::new, spawnData -> new FireworkRocketEntity(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), net.minecraft.world.item.ItemStack.EMPTY)));
|
||||
+ register(new EntityTypeData<>(EntityType.FIREWORK_ROCKET, Firework.class, CraftFirework::new, spawnData -> new FireworkRocketEntity(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), FireworkRocketEntity.getDefaultItem()))); // Paper - pass correct default to rocket for data storage
|
||||
register(new EntityTypeData<>(EntityType.EVOKER_FANGS, EvokerFangs.class, CraftEvokerFangs::new, spawnData -> new net.minecraft.world.entity.projectile.EvokerFangs(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), (float) Math.toRadians(spawnData.yaw()), 0, null)));
|
||||
register(new EntityTypeData<>(EntityType.COMMAND_BLOCK_MINECART, CommandMinecart.class, CraftMinecartCommand::new, createMinecart(net.minecraft.world.entity.EntityType.COMMAND_BLOCK_MINECART)));
|
||||
register(new EntityTypeData<>(EntityType.MINECART, RideableMinecart.class, CraftMinecartRideable::new, createMinecart(net.minecraft.world.entity.EntityType.MINECART)));
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFireball.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFireball.java
|
||||
index 1b084d63bdbb24dad45d28eed1693eb6e26e24dc..43d7bea201a52cfeacf60c75caa28dfd2c4ff164 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFireball.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFireball.java
|
||||
@@ -34,20 +34,7 @@ public class CraftFireball extends AbstractProjectile implements Fireball {
|
||||
this.getHandle().bukkitYield = yield;
|
||||
}
|
||||
|
||||
- @Override
|
||||
- public ProjectileSource getShooter() {
|
||||
- return this.getHandle().projectileSource;
|
||||
- }
|
||||
-
|
||||
- @Override
|
||||
- public void setShooter(ProjectileSource shooter) {
|
||||
- if (shooter instanceof CraftLivingEntity) {
|
||||
- this.getHandle().setOwner(((CraftLivingEntity) shooter).getHandle());
|
||||
- } else {
|
||||
- this.getHandle().setOwner(null);
|
||||
- }
|
||||
- this.getHandle().projectileSource = shooter;
|
||||
- }
|
||||
+ // Paper - moved to AbstractProjectile
|
||||
|
||||
@Override
|
||||
public Vector getDirection() {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java
|
||||
index c9e15a9d82dee935293b2e7e233f5b9b2d822448..2d54cf6f3d9696c55335f0a2057025e2034d4e13 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java
|
||||
@@ -15,24 +15,26 @@ import org.bukkit.inventory.meta.FireworkMeta;
|
||||
public class CraftFirework extends CraftProjectile implements Firework {
|
||||
|
||||
private final Random random = new Random();
|
||||
- private final CraftItemStack item;
|
||||
+ //private CraftItemStack item; // Paper - Remove usage, not accurate representation of current item.
|
||||
|
||||
public CraftFirework(CraftServer server, FireworkRocketEntity entity) {
|
||||
super(server, entity);
|
||||
|
||||
- ItemStack item = this.getHandle().getEntityData().get(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM);
|
||||
-
|
||||
- if (item.isEmpty()) {
|
||||
- item = new ItemStack(Items.FIREWORK_ROCKET);
|
||||
- this.getHandle().getEntityData().set(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM, item);
|
||||
- }
|
||||
-
|
||||
- this.item = CraftItemStack.asCraftMirror(item);
|
||||
-
|
||||
- // Ensure the item is a firework...
|
||||
- if (this.item.getType() != Material.FIREWORK_ROCKET) {
|
||||
- this.item.setType(Material.FIREWORK_ROCKET);
|
||||
- }
|
||||
+ // Paper start - Expose firework item directly
|
||||
+// ItemStack item = this.getHandle().getEntityData().get(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM);
|
||||
+//
|
||||
+// if (item.isEmpty()) {
|
||||
+// item = new ItemStack(Items.FIREWORK_ROCKET);
|
||||
+// this.getHandle().getEntityData().set(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM, item);
|
||||
+// }
|
||||
+//
|
||||
+// this.item = CraftItemStack.asCraftMirror(item);
|
||||
+//
|
||||
+// // Ensure the item is a firework...
|
||||
+// if (this.item.getType() != Material.FIREWORK_ROCKET) {
|
||||
+// this.item.setType(Material.FIREWORK_ROCKET);
|
||||
+// }
|
||||
+ // Paper end - Expose firework item directly
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -47,12 +49,12 @@ public class CraftFirework extends CraftProjectile implements Firework {
|
||||
|
||||
@Override
|
||||
public FireworkMeta getFireworkMeta() {
|
||||
- return (FireworkMeta) this.item.getItemMeta();
|
||||
+ return (FireworkMeta) CraftItemStack.getItemMeta(this.getHandle().getEntityData().get(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM), org.bukkit.inventory.ItemType.FIREWORK_ROCKET); // Paper - Expose firework item directly
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFireworkMeta(FireworkMeta meta) {
|
||||
- this.item.setItemMeta(meta);
|
||||
+ applyFireworkEffect(meta); // Paper - Expose firework item directly
|
||||
|
||||
// Copied from EntityFireworks constructor, update firework lifetime/power
|
||||
this.getHandle().lifetime = 10 * (1 + meta.getPower()) + this.random.nextInt(6) + this.random.nextInt(7);
|
||||
@@ -136,4 +138,46 @@ public class CraftFirework extends CraftProjectile implements Firework {
|
||||
return getHandle().spawningEntity;
|
||||
}
|
||||
// Paper end
|
||||
+ // Paper start - Expose firework item directly + manually setting flight
|
||||
+ @Override
|
||||
+ public org.bukkit.inventory.ItemStack getItem() {
|
||||
+ return CraftItemStack.asBukkitCopy(this.getHandle().getItem());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setItem(org.bukkit.inventory.ItemStack itemStack) {
|
||||
+ FireworkMeta meta = getFireworkMeta();
|
||||
+ ItemStack nmsItem = itemStack == null ? FireworkRocketEntity.getDefaultItem() : CraftItemStack.asNMSCopy(itemStack);
|
||||
+ this.getHandle().getEntityData().set(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM, nmsItem);
|
||||
+
|
||||
+ applyFireworkEffect(meta);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getTicksFlown() {
|
||||
+ return this.getHandle().life;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setTicksFlown(int ticks) {
|
||||
+ this.getHandle().life = ticks;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getTicksToDetonate() {
|
||||
+ return this.getHandle().lifetime;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setTicksToDetonate(int ticks) {
|
||||
+ this.getHandle().lifetime = ticks;
|
||||
+ }
|
||||
+
|
||||
+ void applyFireworkEffect(FireworkMeta meta) {
|
||||
+ ItemStack item = this.getHandle().getItem();
|
||||
+ CraftItemStack.applyMetaToItem(item, meta);
|
||||
+
|
||||
+ this.getHandle().getEntityData().set(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM, item);
|
||||
+ }
|
||||
+ // Paper end - Expose firework item directly + manually setting flight
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java
|
||||
index 6e2f91423371ead9890095cf4b1e2299c4dcba28..9d8f4b7176e60180565e3134a14ecf19060f2621 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java
|
||||
@@ -196,4 +196,42 @@ public class CraftFishHook extends CraftProjectile implements FishHook {
|
||||
public HookState getState() {
|
||||
return HookState.values()[this.getHandle().currentState.ordinal()];
|
||||
}
|
||||
+ // Paper start - More FishHook API
|
||||
+ @Override
|
||||
+ public int getWaitTime() {
|
||||
+ return this.getHandle().timeUntilLured;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setWaitTime(int ticks) {
|
||||
+ this.getHandle().timeUntilLured = ticks;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getTimeUntilBite() {
|
||||
+ return this.getHandle().timeUntilHooked;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setTimeUntilBite(final int ticks) {
|
||||
+ com.google.common.base.Preconditions.checkArgument(ticks >= 1, "Cannot set time until bite to less than 1 (%s<1)", ticks);
|
||||
+ final FishingHook hook = this.getHandle();
|
||||
+
|
||||
+ // Reset the fish angle hook only when this call "enters" the fish into the lure stage.
|
||||
+ final boolean alreadyInLuringPhase = hook.timeUntilHooked > 0 && hook.timeUntilLured <= 0;
|
||||
+ if (!alreadyInLuringPhase) {
|
||||
+ hook.fishAngle = net.minecraft.util.Mth.nextFloat(hook.random, hook.minLureAngle, hook.maxLureAngle);
|
||||
+ hook.timeUntilLured = 0;
|
||||
+ }
|
||||
+
|
||||
+ hook.timeUntilHooked = ticks;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void resetFishingState() {
|
||||
+ final FishingHook hook = this.getHandle();
|
||||
+ hook.resetTimeUntilLured();
|
||||
+ hook.timeUntilHooked = 0; // Reset time until hooked, will be repopulated once lured time is ticked down.
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
|
||||
index e148239d4930e5cbb000beed4de386f992f28d88..14b4c3835388d957653ba34444968bb718ce7f68 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
|
||||
@@ -579,8 +579,15 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
|
||||
}
|
||||
|
||||
@Override
|
||||
- @SuppressWarnings("unchecked")
|
||||
public <T extends Projectile> T launchProjectile(Class<? extends T> projectile, Vector velocity) {
|
||||
+ // Paper start - launchProjectile consumer
|
||||
+ return this.launchProjectile(projectile, velocity, null);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ @SuppressWarnings("unchecked")
|
||||
+ public <T extends Projectile> T launchProjectile(Class<? extends T> projectile, Vector velocity, java.util.function.Consumer<? super T> function) {
|
||||
+ // Paper end - launchProjectile consumer
|
||||
Preconditions.checkState(!this.getHandle().generation, "Cannot launch projectile during world generation");
|
||||
|
||||
net.minecraft.world.level.Level world = ((CraftWorld) this.getWorld()).getHandle();
|
||||
@@ -606,7 +613,7 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
|
||||
} else {
|
||||
launch = new net.minecraft.world.entity.projectile.Arrow(world, this.getHandle(), new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Items.ARROW), null);
|
||||
}
|
||||
- ((net.minecraft.world.entity.projectile.AbstractArrow) launch).shootFromRotation(this.getHandle(), this.getHandle().getXRot(), this.getHandle().getYRot(), 0.0F, 3.0F, 1.0F); // ItemBow
|
||||
+ ((net.minecraft.world.entity.projectile.AbstractArrow) launch).shootFromRotation(this.getHandle(), this.getHandle().getXRot(), this.getHandle().getYRot(), 0.0F, Trident.class.isAssignableFrom(projectile) ? net.minecraft.world.item.TridentItem.SHOOT_POWER : 3.0F, 1.0F); // ItemBow // Paper - see TridentItem
|
||||
} else if (ThrownPotion.class.isAssignableFrom(projectile)) {
|
||||
if (LingeringPotion.class.isAssignableFrom(projectile)) {
|
||||
launch = new net.minecraft.world.entity.projectile.ThrownPotion(world, this.getHandle(), new net.minecraft.world.item.ItemStack(Items.LINGERING_POTION));
|
||||
@@ -663,8 +670,26 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
|
||||
} else if (Firework.class.isAssignableFrom(projectile)) {
|
||||
Location location = this.getEyeLocation();
|
||||
|
||||
- launch = new FireworkRocketEntity(world, net.minecraft.world.item.ItemStack.EMPTY, this.getHandle());
|
||||
- launch.moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
|
||||
+ // Paper start - see CrossbowItem
|
||||
+ launch = new FireworkRocketEntity(world, FireworkRocketEntity.getDefaultItem(), this.getHandle(), location.getX(), location.getY() - 0.15F, location.getZ(), true); // Paper - pass correct default to rocket for data storage & see CrossbowItem for regular launch without elytra boost
|
||||
+
|
||||
+ // Lifted from net.minecraft.world.item.ProjectileWeaponItem.shoot
|
||||
+ float f2 = /* net.minecraft.world.item.enchantment.EnchantmentHelper.processProjectileSpread((ServerLevel) world, new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Items.CROSSBOW), this.getHandle(), 0.0F); */ 0; // Just shortcut this to 0, no need to do any calculations on a non existing stack
|
||||
+ int projectileSize = 1;
|
||||
+ int i = 0;
|
||||
+
|
||||
+ float f3 = projectileSize == 1 ? 0.0F : 2.0F * f2 / (float) (projectileSize - 1);
|
||||
+ float f4 = (float) ((projectileSize - 1) % 2) * f3 / 2.0F;
|
||||
+ float f5 = 1.0F;
|
||||
+ float yaw = f4 + f5 * (float) ((i + 1) / 2) * f3;
|
||||
+
|
||||
+ // Lifted from net.minecraft.world.item.CrossbowItem.shootProjectile
|
||||
+ Vec3 vec3 = this.getHandle().getUpVector(1.0F);
|
||||
+ org.joml.Quaternionf quaternionf = new org.joml.Quaternionf().setAngleAxis((double)(yaw * (float) (Math.PI / 180.0)), vec3.x, vec3.y, vec3.z);
|
||||
+ Vec3 vec32 = this.getHandle().getViewVector(1.0F);
|
||||
+ org.joml.Vector3f vector3f = vec32.toVector3f().rotate(quaternionf);
|
||||
+ ((FireworkRocketEntity) launch).shoot((double)vector3f.x(), (double)vector3f.y(), (double)vector3f.z(), net.minecraft.world.item.CrossbowItem.FIREWORK_POWER, 1.0F);
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
Preconditions.checkArgument(launch != null, "Projectile (%s) not supported", projectile.getName());
|
||||
@@ -672,6 +697,11 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
|
||||
if (velocity != null) {
|
||||
((T) launch.getBukkitEntity()).setVelocity(velocity);
|
||||
}
|
||||
+ // Paper start - launchProjectile consumer
|
||||
+ if (function != null) {
|
||||
+ function.accept((T) launch.getBukkitEntity());
|
||||
+ }
|
||||
+ // Paper end - launchProjectile consumer
|
||||
|
||||
world.addFreshEntity(launch);
|
||||
return (T) launch.getBukkitEntity();
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLlamaSpit.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLlamaSpit.java
|
||||
index 70cbc6c668c60e9d608ca7013b72f9b916c05c2d..47633f05b4fab1dcabc2117e7645fe6d6949622a 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLlamaSpit.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLlamaSpit.java
|
||||
@@ -20,13 +20,5 @@ public class CraftLlamaSpit extends AbstractProjectile implements LlamaSpit {
|
||||
return "CraftLlamaSpit";
|
||||
}
|
||||
|
||||
- @Override
|
||||
- public ProjectileSource getShooter() {
|
||||
- return (this.getHandle().getOwner() != null) ? (ProjectileSource) this.getHandle().getOwner().getBukkitEntity() : null;
|
||||
- }
|
||||
-
|
||||
- @Override
|
||||
- public void setShooter(ProjectileSource source) {
|
||||
- this.getHandle().setOwner((source != null) ? ((CraftLivingEntity) source).getHandle() : null);
|
||||
- }
|
||||
+ // Paper - moved to AbstractProjectile
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftProjectile.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftProjectile.java
|
||||
index 696fdfa723aa896a67946f862d7c6890f7f7ab17..4f1fa7dec78970bdfc184d3c1f1632dc9d75a574 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftProjectile.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftProjectile.java
|
||||
@@ -10,20 +10,7 @@ public abstract class CraftProjectile extends AbstractProjectile implements Proj
|
||||
super(server, entity);
|
||||
}
|
||||
|
||||
- @Override
|
||||
- public ProjectileSource getShooter() {
|
||||
- return this.getHandle().projectileSource;
|
||||
- }
|
||||
-
|
||||
- @Override
|
||||
- public void setShooter(ProjectileSource shooter) {
|
||||
- if (shooter instanceof CraftLivingEntity) {
|
||||
- this.getHandle().setOwner((LivingEntity) ((CraftLivingEntity) shooter).entity);
|
||||
- } else {
|
||||
- this.getHandle().setOwner(null);
|
||||
- }
|
||||
- this.getHandle().projectileSource = shooter;
|
||||
- }
|
||||
+ // Paper - moved to AbstractProjectile
|
||||
|
||||
@Override
|
||||
public net.minecraft.world.entity.projectile.Projectile getHandle() {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftShulkerBullet.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftShulkerBullet.java
|
||||
index d685d09cae5f862c0004f148298c800736d2139e..b3797a43eeee11cb7ae0774d61bd5f195d0aa3ad 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftShulkerBullet.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftShulkerBullet.java
|
||||
@@ -12,31 +12,56 @@ public class CraftShulkerBullet extends AbstractProjectile implements ShulkerBul
|
||||
super(server, entity);
|
||||
}
|
||||
|
||||
+ // Paper - moved to AbstractProjectile
|
||||
+
|
||||
+ @Override
|
||||
+ public org.bukkit.entity.Entity getTarget() {
|
||||
+ return this.getHandle().getTarget() != null ? this.getHandle().getTarget().getBukkitEntity() : null;
|
||||
+ }
|
||||
+
|
||||
@Override
|
||||
- public ProjectileSource getShooter() {
|
||||
- return this.getHandle().projectileSource;
|
||||
+ public void setTarget(org.bukkit.entity.Entity target) {
|
||||
+ Preconditions.checkState(!this.getHandle().generation, "Cannot set target during world generation");
|
||||
+
|
||||
+ this.getHandle().setTarget(target == null ? null : ((CraftEntity) target).getHandle());
|
||||
}
|
||||
|
||||
@Override
|
||||
- public void setShooter(ProjectileSource shooter) {
|
||||
- if (shooter instanceof Entity) {
|
||||
- this.getHandle().setOwner(((CraftEntity) shooter).getHandle());
|
||||
- } else {
|
||||
- this.getHandle().setOwner(null);
|
||||
+ public org.bukkit.util.Vector getTargetDelta() {
|
||||
+ net.minecraft.world.entity.projectile.ShulkerBullet bullet = this.getHandle();
|
||||
+ return new org.bukkit.util.Vector(bullet.targetDeltaX, bullet.targetDeltaY, bullet.targetDeltaZ);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setTargetDelta(org.bukkit.util.Vector vector) {
|
||||
+ net.minecraft.world.entity.projectile.ShulkerBullet bullet = this.getHandle();
|
||||
+ bullet.targetDeltaX = vector.getX();
|
||||
+ bullet.targetDeltaY = vector.getY();
|
||||
+ bullet.targetDeltaZ = vector.getZ();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public org.bukkit.block.BlockFace getCurrentMovementDirection() {
|
||||
+ net.minecraft.core.Direction dir = this.getHandle().currentMoveDirection;
|
||||
+ if (dir == null) {
|
||||
+ return null; // random dir
|
||||
}
|
||||
- this.getHandle().projectileSource = shooter;
|
||||
+ return org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(dir);
|
||||
}
|
||||
|
||||
@Override
|
||||
- public org.bukkit.entity.Entity getTarget() {
|
||||
- return this.getHandle().getTarget() != null ? this.getHandle().getTarget().getBukkitEntity() : null;
|
||||
+ public void setCurrentMovementDirection(org.bukkit.block.BlockFace movementDirection) {
|
||||
+ this.getHandle().currentMoveDirection = org.bukkit.craftbukkit.block.CraftBlock.blockFaceToNotch(movementDirection);
|
||||
}
|
||||
|
||||
@Override
|
||||
- public void setTarget(org.bukkit.entity.Entity target) {
|
||||
- Preconditions.checkState(!this.getHandle().generation, "Cannot set target during world generation");
|
||||
+ public int getFlightSteps() {
|
||||
+ return this.getHandle().flightSteps;
|
||||
+ }
|
||||
|
||||
- this.getHandle().setTarget(target == null ? null : ((CraftEntity) target).getHandle());
|
||||
+ @Override
|
||||
+ public void setFlightSteps(int steps) {
|
||||
+ this.getHandle().flightSteps = steps;
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java
|
||||
index d67a80161b3e7c1fe02a6ed9d341c00dc7c2847a..f6fa6f1ac50b757dd3bc9a8dee9f6085446182c8 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java
|
||||
@@ -36,11 +36,31 @@ public class CraftThrownPotion extends CraftThrowableProjectile implements Throw
|
||||
@Override
|
||||
public void setItem(ItemStack item) {
|
||||
Preconditions.checkArgument(item != null, "ItemStack cannot be null");
|
||||
- Preconditions.checkArgument(item.getType() == Material.LINGERING_POTION || item.getType() == Material.SPLASH_POTION, "ItemStack material must be Material.LINGERING_POTION or Material.SPLASH_POTION but was Material.%s", item.getType());
|
||||
+ // Preconditions.checkArgument(item.getType() == Material.LINGERING_POTION || item.getType() == Material.SPLASH_POTION, "ItemStack material must be Material.LINGERING_POTION or Material.SPLASH_POTION but was Material.%s", item.getType()); // Paper - Projectile API
|
||||
+ org.bukkit.inventory.meta.PotionMeta meta = (item.getType() == Material.LINGERING_POTION || item.getType() == Material.SPLASH_POTION) ? null : this.getPotionMeta(); // Paper - Projectile API
|
||||
|
||||
this.getHandle().setItem(CraftItemStack.asNMSCopy(item));
|
||||
+ if (meta != null) this.setPotionMeta(meta); // Paper - Projectile API
|
||||
}
|
||||
|
||||
+ // Paper start - Projectile API
|
||||
+ @Override
|
||||
+ public org.bukkit.inventory.meta.PotionMeta getPotionMeta() {
|
||||
+ return (org.bukkit.inventory.meta.PotionMeta) CraftItemStack.getItemMeta(this.getHandle().getItem(), org.bukkit.inventory.ItemType.SPLASH_POTION);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setPotionMeta(org.bukkit.inventory.meta.PotionMeta meta) {
|
||||
+ net.minecraft.world.item.ItemStack item = this.getHandle().getItem();
|
||||
+ CraftItemStack.applyMetaToItem(item, meta);
|
||||
+ this.getHandle().setItem(item); // Reset item
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void splash() {
|
||||
+ this.getHandle().splash(null);
|
||||
+ }
|
||||
+ // Paper end
|
||||
@Override
|
||||
public net.minecraft.world.entity.projectile.ThrownPotion getHandle() {
|
||||
return (net.minecraft.world.entity.projectile.ThrownPotion) this.entity;
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTrident.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTrident.java
|
||||
index e374b9f40eddca13b30855d25a2030f8df98138f..4fc893378fb0568ddcffc7593d66df6bfe23f659 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTrident.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTrident.java
|
||||
@@ -53,5 +53,15 @@ public class CraftTrident extends CraftAbstractArrow implements Trident {
|
||||
com.google.common.base.Preconditions.checkArgument(loyaltyLevel >= 0 && loyaltyLevel <= 127, "The loyalty level has to be between 0 and 127");
|
||||
this.getHandle().setLoyalty((byte) loyaltyLevel);
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean hasDealtDamage() {
|
||||
+ return this.getHandle().dealtDamage;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setHasDealtDamage(boolean hasDealtDamage) {
|
||||
+ this.getHandle().dealtDamage = hasDealtDamage;
|
||||
+ }
|
||||
// Paper end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
index 376563ea6990aef558a34e4f5889125412b734df..412f5e414745123535a275d5670b35fff5b1aaec 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
@@ -841,19 +841,19 @@ public class CraftEventFactory {
|
||||
/**
|
||||
* PotionSplashEvent
|
||||
*/
|
||||
- public static PotionSplashEvent callPotionSplashEvent(net.minecraft.world.entity.projectile.ThrownPotion potion, HitResult position, Map<LivingEntity, Double> affectedEntities) {
|
||||
+ public static PotionSplashEvent callPotionSplashEvent(net.minecraft.world.entity.projectile.ThrownPotion potion, @Nullable HitResult position, Map<LivingEntity, Double> affectedEntities) { // Paper - nullable hitResult
|
||||
ThrownPotion thrownPotion = (ThrownPotion) potion.getBukkitEntity();
|
||||
|
||||
Block hitBlock = null;
|
||||
BlockFace hitFace = null;
|
||||
- if (position.getType() == HitResult.Type.BLOCK) {
|
||||
+ if (position != null && position.getType() == HitResult.Type.BLOCK) { // Paper - nullable hitResult
|
||||
BlockHitResult positionBlock = (BlockHitResult) position;
|
||||
hitBlock = CraftBlock.at(potion.level(), positionBlock.getBlockPos());
|
||||
hitFace = CraftBlock.notchToBlockFace(positionBlock.getDirection());
|
||||
}
|
||||
|
||||
org.bukkit.entity.Entity hitEntity = null;
|
||||
- if (position.getType() == HitResult.Type.ENTITY) {
|
||||
+ if (position != null && position.getType() == HitResult.Type.ENTITY) { // Paper - nullable hitResult
|
||||
hitEntity = ((EntityHitResult) position).getEntity().getBukkitEntity();
|
||||
}
|
||||
|
||||
@@ -862,20 +862,20 @@ public class CraftEventFactory {
|
||||
return event;
|
||||
}
|
||||
|
||||
- public static LingeringPotionSplashEvent callLingeringPotionSplashEvent(net.minecraft.world.entity.projectile.ThrownPotion potion, HitResult position, net.minecraft.world.entity.AreaEffectCloud cloud) {
|
||||
+ public static LingeringPotionSplashEvent callLingeringPotionSplashEvent(net.minecraft.world.entity.projectile.ThrownPotion potion, @Nullable HitResult position, net.minecraft.world.entity.AreaEffectCloud cloud) { // Paper - nullable hitResult
|
||||
ThrownPotion thrownPotion = (ThrownPotion) potion.getBukkitEntity();
|
||||
AreaEffectCloud effectCloud = (AreaEffectCloud) cloud.getBukkitEntity();
|
||||
|
||||
Block hitBlock = null;
|
||||
BlockFace hitFace = null;
|
||||
- if (position.getType() == HitResult.Type.BLOCK) {
|
||||
+ if (position != null && position.getType() == HitResult.Type.BLOCK) { // Paper
|
||||
BlockHitResult positionBlock = (BlockHitResult) position;
|
||||
hitBlock = CraftBlock.at(potion.level(), positionBlock.getBlockPos());
|
||||
hitFace = CraftBlock.notchToBlockFace(positionBlock.getDirection());
|
||||
}
|
||||
|
||||
org.bukkit.entity.Entity hitEntity = null;
|
||||
- if (position.getType() == HitResult.Type.ENTITY) {
|
||||
+ if (position != null && position.getType() == HitResult.Type.ENTITY) { // Paper
|
||||
hitEntity = ((EntityHitResult) position).getEntity().getBukkitEntity();
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
|
||||
index 60062ea5b18b95a14c459f2f3a0743c1e1ac0f12..502be683e8b04a9966043c9bee9d9fe793b12ef5 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
|
||||
@@ -341,12 +341,23 @@ public final class CraftItemStack extends ItemStack {
|
||||
public ItemMeta getItemMeta() {
|
||||
return CraftItemStack.getItemMeta(this.handle);
|
||||
}
|
||||
+ // Paper start
|
||||
+ public static void applyMetaToItem(net.minecraft.world.item.ItemStack itemStack, ItemMeta itemMeta) {
|
||||
+ final CraftMetaItem.Applicator tag = new CraftMetaItem.Applicator();
|
||||
+ ((CraftMetaItem) itemMeta).applyToItem(tag);
|
||||
+ itemStack.applyComponents(tag.build());
|
||||
+ }
|
||||
|
||||
public static ItemMeta getItemMeta(net.minecraft.world.item.ItemStack item) {
|
||||
+ return getItemMeta(item, null);
|
||||
+ }
|
||||
+ public static ItemMeta getItemMeta(net.minecraft.world.item.ItemStack item, org.bukkit.inventory.ItemType metaForType) {
|
||||
+ // Paper end
|
||||
if (!CraftItemStack.hasItemMeta(item)) {
|
||||
return CraftItemFactory.instance().getItemMeta(CraftItemStack.getType(item));
|
||||
}
|
||||
|
||||
+ if (metaForType != null) { return ((CraftItemType<?>) metaForType).getItemMeta(item); } // Paper
|
||||
return ((CraftItemType<?>) CraftItemType.minecraftToBukkitNew(item.getItem())).getItemMeta(item);
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/projectiles/CraftBlockProjectileSource.java b/src/main/java/org/bukkit/craftbukkit/projectiles/CraftBlockProjectileSource.java
|
||||
index 642f5bf75661eb485558bc227f668e84416f3b5f..76fd4d27730d9139caa67099a6757ea33d681be9 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/projectiles/CraftBlockProjectileSource.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/projectiles/CraftBlockProjectileSource.java
|
||||
@@ -56,7 +56,15 @@ public class CraftBlockProjectileSource implements BlockProjectileSource {
|
||||
|
||||
@Override
|
||||
public <T extends Projectile> T launchProjectile(Class<? extends T> projectile, Vector velocity) {
|
||||
+ // Paper start - launchProjectile consumer
|
||||
+ return this.launchProjectile(projectile, velocity, null);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public <T extends Projectile> T launchProjectile(Class<? extends T> projectile, Vector velocity, java.util.function.Consumer<? super T> function) {
|
||||
+ // Paper end - launchProjectile consumer
|
||||
Preconditions.checkArgument(this.getBlock().getType() == Material.DISPENSER, "Block is no longer dispenser");
|
||||
+
|
||||
// Copied from BlockDispenser.dispense()
|
||||
BlockSource sourceblock = new BlockSource((ServerLevel) this.dispenserBlock.getLevel(), this.dispenserBlock.getBlockPos(), this.dispenserBlock.getBlockState(), this.dispenserBlock);
|
||||
// Copied from DispenseBehaviorProjectile
|
||||
@@ -68,7 +76,7 @@ public class CraftBlockProjectileSource implements BlockProjectileSource {
|
||||
item = Items.SNOWBALL;
|
||||
} else if (Egg.class.isAssignableFrom(projectile)) {
|
||||
item = Items.EGG;
|
||||
- } else if (EnderPearl.class.isAssignableFrom(projectile)) {
|
||||
+ } else if (false && EnderPearl.class.isAssignableFrom(projectile)) { // Paper - more projectile API - disallow enderpearl, it is not a projectile item
|
||||
item = Items.ENDER_PEARL;
|
||||
} else if (ThrownExpBottle.class.isAssignableFrom(projectile)) {
|
||||
item = Items.EXPERIENCE_BOTTLE;
|
||||
@@ -83,20 +91,20 @@ public class CraftBlockProjectileSource implements BlockProjectileSource {
|
||||
item = Items.TIPPED_ARROW;
|
||||
} else if (SpectralArrow.class.isAssignableFrom(projectile)) {
|
||||
item = Items.SPECTRAL_ARROW;
|
||||
- } else {
|
||||
+ } else if (org.bukkit.entity.Arrow.class.isAssignableFrom(projectile)) { // Paper - more projectile API - disallow trident
|
||||
item = Items.ARROW;
|
||||
}
|
||||
} else if (Fireball.class.isAssignableFrom(projectile)) {
|
||||
- if (AbstractWindCharge.class.isAssignableFrom(projectile)) {
|
||||
+ if (org.bukkit.entity.WindCharge.class.isAssignableFrom(projectile)) { // Paper - more projectile API - only allow wind charge not breeze wind charge
|
||||
item = Items.WIND_CHARGE;
|
||||
- } else {
|
||||
+ } else if (org.bukkit.entity.SmallFireball.class.isAssignableFrom(projectile)) { // Paper - more projectile API - only allow firing fire charges.
|
||||
item = Items.FIRE_CHARGE;
|
||||
}
|
||||
} else if (Firework.class.isAssignableFrom(projectile)) {
|
||||
item = Items.FIREWORK_ROCKET;
|
||||
}
|
||||
|
||||
- Preconditions.checkArgument(item instanceof ProjectileItem, "Projectile not supported");
|
||||
+ Preconditions.checkArgument(item instanceof ProjectileItem, "Projectile '%s' not supported", projectile.getSimpleName()); // Paper - more projectile API - include simple name in exception
|
||||
|
||||
ItemStack itemstack = new ItemStack(item);
|
||||
ProjectileItem projectileItem = (ProjectileItem) item;
|
||||
@@ -105,7 +113,7 @@ public class CraftBlockProjectileSource implements BlockProjectileSource {
|
||||
Position iposition = dispenseConfig.positionFunction().getDispensePosition(sourceblock, enumdirection);
|
||||
net.minecraft.world.entity.projectile.Projectile launch = projectileItem.asProjectile(world, iposition, itemstack, enumdirection);
|
||||
|
||||
- if (Fireball.class.isAssignableFrom(projectile)) {
|
||||
+ if (false && Fireball.class.isAssignableFrom(projectile)) { // Paper - more project API - dispensers cannot launch anything but fire charges.
|
||||
AbstractHurtingProjectile customFireball = null;
|
||||
if (WitherSkull.class.isAssignableFrom(projectile)) {
|
||||
launch = customFireball = EntityType.WITHER_SKULL.create(world, EntitySpawnReason.TRIGGERED);
|
||||
@@ -130,7 +138,7 @@ public class CraftBlockProjectileSource implements BlockProjectileSource {
|
||||
}
|
||||
}
|
||||
|
||||
- if (launch instanceof net.minecraft.world.entity.projectile.AbstractArrow arrow) {
|
||||
+ if (false && launch instanceof net.minecraft.world.entity.projectile.AbstractArrow arrow) { // Paper - more projectile API - this is set by the respective ArrowItem when constructing the projectile
|
||||
arrow.pickup = net.minecraft.world.entity.projectile.AbstractArrow.Pickup.ALLOWED;
|
||||
}
|
||||
launch.projectileSource = this;
|
||||
@@ -139,6 +147,11 @@ public class CraftBlockProjectileSource implements BlockProjectileSource {
|
||||
if (velocity != null) {
|
||||
((T) launch.getBukkitEntity()).setVelocity(velocity);
|
||||
}
|
||||
+ // Paper start
|
||||
+ if (function != null) {
|
||||
+ function.accept((T) launch.getBukkitEntity());
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
world.addFreshEntity(launch);
|
||||
return (T) launch.getBukkitEntity();
|
|
@ -0,0 +1,64 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Sat, 12 Mar 2022 06:31:13 -0800
|
||||
Subject: [PATCH] Fix swamp hut cat generation deadlock
|
||||
|
||||
The worldgen thread will attempt to get structure references
|
||||
via the world's getChunkAt method, which is fine if the gen is
|
||||
not cancelled - but if the chunk was unloaded, the call will block
|
||||
indefinitely. Instead of using the world state, we use the already
|
||||
supplied ServerLevelAccessor which will always have the chunk available.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/Cat.java b/src/main/java/net/minecraft/world/entity/animal/Cat.java
|
||||
index f3a991aa878f3b29fdc525ecdde6766efb5e129c..5a86530c65d7d83e4608600a04ffd931bf59dc4a 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/Cat.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/Cat.java
|
||||
@@ -366,7 +366,7 @@ public class Cat extends TamableAnimal implements VariantHolder<Holder<CatVarian
|
||||
BuiltInRegistries.CAT_VARIANT.getRandomElementOf(tagkey, world.getRandom()).ifPresent(this::setVariant);
|
||||
ServerLevel worldserver = world.getLevel();
|
||||
|
||||
- if (worldserver.structureManager().getStructureWithPieceAt(this.blockPosition(), StructureTags.CATS_SPAWN_AS_BLACK).isValid()) {
|
||||
+ if (worldserver.structureManager().getStructureWithPieceAt(this.blockPosition(), StructureTags.CATS_SPAWN_AS_BLACK, world).isValid()) { // Paper - Fix swamp hut cat generation deadlock
|
||||
this.setVariant((Holder) BuiltInRegistries.CAT_VARIANT.getOrThrow(CatVariant.ALL_BLACK));
|
||||
this.setPersistenceRequired();
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/StructureManager.java b/src/main/java/net/minecraft/world/level/StructureManager.java
|
||||
index 3d607ac74de4bc051ab68269dbab0bbd3a52dc54..03adb02297911e5a5051edac14453d7e3eeac29c 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/StructureManager.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/StructureManager.java
|
||||
@@ -48,7 +48,12 @@ public class StructureManager {
|
||||
}
|
||||
|
||||
public List<StructureStart> startsForStructure(ChunkPos pos, Predicate<Structure> predicate) {
|
||||
- Map<Structure, LongSet> map = this.level.getChunk(pos.x, pos.z, ChunkStatus.STRUCTURE_REFERENCES).getAllReferences();
|
||||
+ // Paper start - Fix swamp hut cat generation deadlock
|
||||
+ return this.startsForStructure(pos, predicate, null);
|
||||
+ }
|
||||
+ public List<StructureStart> startsForStructure(ChunkPos pos, Predicate<Structure> predicate, @Nullable ServerLevelAccessor levelAccessor) {
|
||||
+ Map<Structure, LongSet> map = (levelAccessor == null ? this.level : levelAccessor).getChunk(pos.x, pos.z, ChunkStatus.STRUCTURE_REFERENCES).getAllReferences();
|
||||
+ // Paper end - Fix swamp hut cat generation deadlock
|
||||
Builder<StructureStart> builder = ImmutableList.builder();
|
||||
|
||||
for (Entry<Structure, LongSet> entry : map.entrySet()) {
|
||||
@@ -116,10 +121,20 @@ public class StructureManager {
|
||||
}
|
||||
|
||||
public StructureStart getStructureWithPieceAt(BlockPos pos, Predicate<Holder<Structure>> predicate) {
|
||||
+ // Paper start - Fix swamp hut cat generation deadlock
|
||||
+ return this.getStructureWithPieceAt(pos, predicate, null);
|
||||
+ }
|
||||
+
|
||||
+ public StructureStart getStructureWithPieceAt(BlockPos pos, TagKey<Structure> tag, @Nullable ServerLevelAccessor levelAccessor) {
|
||||
+ return this.getStructureWithPieceAt(pos, structure -> structure.is(tag), levelAccessor);
|
||||
+ }
|
||||
+
|
||||
+ public StructureStart getStructureWithPieceAt(BlockPos pos, Predicate<Holder<Structure>> predicate, @Nullable ServerLevelAccessor levelAccessor) {
|
||||
+ // Paper end - Fix swamp hut cat generation deadlock
|
||||
Registry<Structure> registry = this.registryAccess().lookupOrThrow(Registries.STRUCTURE);
|
||||
|
||||
for (StructureStart structureStart : this.startsForStructure(
|
||||
- new ChunkPos(pos), structure -> registry.get(registry.getId(structure)).map(predicate::test).orElse(false)
|
||||
+ new ChunkPos(pos), structure -> registry.get(registry.getId(structure)).map(predicate::test).orElse(false), levelAccessor // Paper - Fix swamp hut cat generation deadlock
|
||||
)) {
|
||||
if (this.structureHasPieceAt(pos, structureStart)) {
|
||||
return structureStart;
|
|
@ -0,0 +1,24 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Mon, 14 Mar 2022 12:35:37 -0700
|
||||
Subject: [PATCH] Don't allow vehicle movement from players while teleporting
|
||||
|
||||
Bring the vehicle move packet behavior in line with the
|
||||
regular player move packet.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 7b858178ce7d0e33fec17311f1710bead5f0837d..33f76a6df7997ecdc789004bf0b230e74ad07f5a 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -481,6 +481,11 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
this.disconnect((Component) Component.translatable("multiplayer.disconnect.invalid_vehicle_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_VEHICLE_MOVEMENT); // Paper - kick event cause
|
||||
} else if (!this.updateAwaitingTeleport()) {
|
||||
Entity entity = this.player.getRootVehicle();
|
||||
+ // Paper start - Don't allow vehicle movement from players while teleporting
|
||||
+ if (this.awaitingPositionFromClient != null || this.player.isImmobile() || entity.isRemoved()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end - Don't allow vehicle movement from players while teleporting
|
||||
|
||||
if (entity != this.player && entity.getControllingPassenger() == this.player && entity == this.lastVehicle) {
|
||||
ServerLevel worldserver = this.player.serverLevel();
|
61
patches/server/0673-Implement-getComputedBiome-API.patch
Normal file
61
patches/server/0673-Implement-getComputedBiome-API.patch
Normal file
|
@ -0,0 +1,61 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
|
||||
Date: Mon, 14 Mar 2022 22:46:05 -0700
|
||||
Subject: [PATCH] Implement getComputedBiome API
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
|
||||
index 123824f6b8306900ed5c0b3addb884301dbcab7e..244cff4f84792fd0efe146e6faf47db0b0a0dc87 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
|
||||
@@ -77,6 +77,13 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
|
||||
return CraftBiome.minecraftHolderToBukkit(this.getHandle().getNoiseBiome(x >> 2, y >> 2, z >> 2));
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public Biome getComputedBiome(int x, int y, int z) {
|
||||
+ return CraftBiome.minecraftHolderToBukkit(this.getHandle().getBiome(new BlockPos(x, y, z)));
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public void setBiome(Location location, Biome biome) {
|
||||
this.setBiome(location.getBlockX(), location.getBlockY(), location.getBlockZ(), biome);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
|
||||
index d5b495b5a3ca7f4411d1a700f7149042a16509f1..68fcec085334383808b2117a49220f4d8239220b 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
|
||||
@@ -340,6 +340,13 @@ public class CraftBlock implements Block {
|
||||
return this.getWorld().getBiome(this.getX(), this.getY(), this.getZ());
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public Biome getComputedBiome() {
|
||||
+ return this.getWorld().getComputedBiome(this.getX(), this.getY(), this.getZ());
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public void setBiome(Biome bio) {
|
||||
this.getWorld().setBiome(this.getX(), this.getY(), this.getZ(), bio);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftLimitedRegion.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftLimitedRegion.java
|
||||
index 2c7b64bd7071cb803a042152d497982d753e0b5d..a23269e3bdb83f85a1d08d5f7b54742025223ada 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/generator/CraftLimitedRegion.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftLimitedRegion.java
|
||||
@@ -166,6 +166,14 @@ public class CraftLimitedRegion extends CraftRegionAccessor implements LimitedRe
|
||||
return super.getBiome(x, y, z);
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public Biome getComputedBiome(int x, int y, int z) {
|
||||
+ Preconditions.checkArgument(this.isInRegion(x, y, z), "Coordinates %s, %s, %s are not in the region", x, y, z);
|
||||
+ return super.getComputedBiome(x, y, z);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public void setBiome(int x, int y, int z, Holder<net.minecraft.world.level.biome.Biome> biomeBase) {
|
||||
Preconditions.checkArgument(this.isInRegion(x, y, z), "Coordinates %s, %s, %s are not in the region", x, y, z);
|
28
patches/server/0674-Make-some-itemstacks-nonnull.patch
Normal file
28
patches/server/0674-Make-some-itemstacks-nonnull.patch
Normal file
|
@ -0,0 +1,28 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Tue, 15 Mar 2022 01:38:15 -0700
|
||||
Subject: [PATCH] Make some itemstacks nonnull
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java
|
||||
index 5e40faa88c51b0ebd76493fd1731d16ca1051f4a..46d0b324498510c73a8439611f44269edee62313 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java
|
||||
@@ -155,13 +155,13 @@ public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.i
|
||||
case OFF_HAND:
|
||||
return this.getItemInOffHand();
|
||||
case FEET:
|
||||
- return this.getBoots();
|
||||
+ return java.util.Objects.requireNonNullElseGet(this.getBoots(), () -> new ItemStack(org.bukkit.Material.AIR)); // Paper - make nonnull
|
||||
case LEGS:
|
||||
- return this.getLeggings();
|
||||
+ return java.util.Objects.requireNonNullElseGet(this.getLeggings(), () -> new ItemStack(org.bukkit.Material.AIR)); // Paper - make nonnull
|
||||
case CHEST:
|
||||
- return this.getChestplate();
|
||||
+ return java.util.Objects.requireNonNullElseGet(this.getChestplate(), () -> new ItemStack(org.bukkit.Material.AIR)); // Paper - make nonnull
|
||||
case HEAD:
|
||||
- return this.getHelmet();
|
||||
+ return java.util.Objects.requireNonNullElseGet(this.getHelmet(), () -> new ItemStack(org.bukkit.Material.AIR)); // Paper - make nonnull
|
||||
default:
|
||||
throw new IllegalArgumentException("Not implemented. This is a bug");
|
||||
}
|
58
patches/server/0675-Implement-enchantWithLevels-API.patch
Normal file
58
patches/server/0675-Implement-enchantWithLevels-API.patch
Normal file
|
@ -0,0 +1,58 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
|
||||
Date: Wed, 16 Mar 2022 20:35:21 -0700
|
||||
Subject: [PATCH] Implement enchantWithLevels API
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
|
||||
index 237df8b37ee8cf5b15e8e6d30fa3b51ef394434d..944dcc1126c947b4c8c3b4fdd174eb57320abbba 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
|
||||
@@ -305,4 +305,47 @@ public final class CraftItemFactory implements ItemFactory {
|
||||
return eggItem == null ? null : new net.minecraft.world.item.ItemStack(eggItem).asBukkitMirror();
|
||||
}
|
||||
// Paper end - old getSpawnEgg API
|
||||
+ // Paper start - enchantWithLevels API
|
||||
+ @Override
|
||||
+ public ItemStack enchantWithLevels(ItemStack itemStack, int levels, boolean allowTreasure, java.util.Random random) {
|
||||
+ return enchantWithLevels(
|
||||
+ itemStack,
|
||||
+ levels,
|
||||
+ allowTreasure
|
||||
+ ? Optional.empty()
|
||||
+ // While IN_ENCHANTING_TABLE is not logically the same as all but TREASURE, the tag is defined as
|
||||
+ // NON_TREASURE, which does contain all enchantments not in the treasure tag.
|
||||
+ // Additionally, the allowTreasure boolean is more intended to configure this method to behave like
|
||||
+ // an enchanting table.
|
||||
+ : net.minecraft.server.MinecraftServer.getServer().registryAccess().registryOrThrow(Registries.ENCHANTMENT).getTag(EnchantmentTags.IN_ENCHANTING_TABLE),
|
||||
+ random
|
||||
+ );
|
||||
+ }
|
||||
+
|
||||
+ @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
||||
+ private ItemStack enchantWithLevels(
|
||||
+ ItemStack itemStack,
|
||||
+ int levels,
|
||||
+ Optional<? extends net.minecraft.core.HolderSet<net.minecraft.world.item.enchantment.Enchantment>> possibleEnchantments,
|
||||
+ java.util.Random random
|
||||
+ ) {
|
||||
+ Preconditions.checkArgument(itemStack != null, "Argument 'itemStack' must not be null");
|
||||
+ Preconditions.checkArgument(!itemStack.isEmpty(), "Argument 'itemStack' cannot be empty");
|
||||
+ Preconditions.checkArgument(levels > 0 && levels <= 30, "Argument 'levels' must be in range [1, 30] (attempted " + levels + ")");
|
||||
+ Preconditions.checkArgument(random != null, "Argument 'random' must not be null");
|
||||
+ final net.minecraft.world.item.ItemStack internalStack = CraftItemStack.asNMSCopy(itemStack);
|
||||
+ if (internalStack.isEnchanted()) {
|
||||
+ internalStack.set(net.minecraft.core.component.DataComponents.ENCHANTMENTS, net.minecraft.world.item.enchantment.ItemEnchantments.EMPTY);
|
||||
+ }
|
||||
+ final net.minecraft.core.RegistryAccess registryAccess = net.minecraft.server.MinecraftServer.getServer().registryAccess();
|
||||
+ final net.minecraft.world.item.ItemStack enchanted = net.minecraft.world.item.enchantment.EnchantmentHelper.enchantItem(
|
||||
+ new org.bukkit.craftbukkit.util.RandomSourceWrapper(random),
|
||||
+ internalStack,
|
||||
+ levels,
|
||||
+ registryAccess,
|
||||
+ possibleEnchantments
|
||||
+ );
|
||||
+ return CraftItemStack.asCraftMirror(enchanted);
|
||||
+ }
|
||||
+ // Paper end - enchantWithLevels API
|
||||
}
|
20
patches/server/0676-Fix-saving-in-unloadWorld.patch
Normal file
20
patches/server/0676-Fix-saving-in-unloadWorld.patch
Normal file
|
@ -0,0 +1,20 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Philip Kelley <philip@thoriumcube.org>
|
||||
Date: Wed, 16 Mar 2022 12:05:59 +0000
|
||||
Subject: [PATCH] Fix saving in unloadWorld
|
||||
|
||||
Change savingDisabled to false to ensure ServerLevel's saving logic gets called when unloadWorld is called with save = true
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index f0eb8284b537014b591e45f034f1498e7e687e54..cc08b56da8a276202da3e85315fdb2ad530c2545 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -1386,7 +1386,7 @@ public final class CraftServer implements Server {
|
||||
|
||||
try {
|
||||
if (save) {
|
||||
- handle.save(null, true, true);
|
||||
+ handle.save(null, true, false); // Paper - Fix saving in unloadWorld
|
||||
}
|
||||
|
||||
handle.getChunkSource().close(save);
|
42
patches/server/0677-Buffer-OOB-setBlock-calls.patch
Normal file
42
patches/server/0677-Buffer-OOB-setBlock-calls.patch
Normal file
|
@ -0,0 +1,42 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Sat, 19 Mar 2022 12:12:22 +0000
|
||||
Subject: [PATCH] Buffer OOB setBlock calls
|
||||
|
||||
lets debug mode throw a trace in order to potentially see where
|
||||
such calls are cascading from easier, but, generally, if you see one setBlock
|
||||
call, you're gonna see more, and this just potentially causes a flood of logs
|
||||
which can cause issues for slower terminals, etc.
|
||||
|
||||
We can limit the flood by just allowing one for a single gen region,
|
||||
we'll also only gen a trace for the first one, I see no real pressing need
|
||||
to generate more, given that that would *massively* negate this patch otherwise
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/WorldGenRegion.java b/src/main/java/net/minecraft/server/level/WorldGenRegion.java
|
||||
index f1725ef766c35aa623ace58fe8bf31fc9b2bb6b3..5bf438bb58833c1df3620e82d3d2b90207366372 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/WorldGenRegion.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/WorldGenRegion.java
|
||||
@@ -284,6 +284,7 @@ public class WorldGenRegion implements WorldGenLevel {
|
||||
}
|
||||
}
|
||||
|
||||
+ private boolean hasSetFarWarned = false; // Paper - Buffer OOB setBlock calls
|
||||
@Override
|
||||
public boolean ensureCanWrite(BlockPos pos) {
|
||||
int i = SectionPos.blockToSectionCoord(pos.getX());
|
||||
@@ -303,7 +304,15 @@ public class WorldGenRegion implements WorldGenLevel {
|
||||
|
||||
return true;
|
||||
} else {
|
||||
+ // Paper start - Buffer OOB setBlock calls
|
||||
+ if (!hasSetFarWarned) {
|
||||
Util.logAndPauseIfInIde("Detected setBlock in a far chunk [" + i + ", " + j + "], pos: " + String.valueOf(pos) + ", status: " + String.valueOf(this.generatingStep.targetStatus()) + (this.currentlyGenerating == null ? "" : ", currently generating: " + (String) this.currentlyGenerating.get()));
|
||||
+ hasSetFarWarned = true;
|
||||
+ if (this.getServer() != null && this.getServer().isDebugging()) {
|
||||
+ io.papermc.paper.util.TraceUtil.dumpTraceForThread("far setBlock call");
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Buffer OOB setBlock calls
|
||||
return false;
|
||||
}
|
||||
}
|
24
patches/server/0678-Add-TameableDeathMessageEvent.patch
Normal file
24
patches/server/0678-Add-TameableDeathMessageEvent.patch
Normal file
|
@ -0,0 +1,24 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
|
||||
Date: Mon, 21 Jun 2021 21:24:45 -0400
|
||||
Subject: [PATCH] Add TameableDeathMessageEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/TamableAnimal.java b/src/main/java/net/minecraft/world/entity/TamableAnimal.java
|
||||
index cd565d1a8dab8d45196e4d29cab3d93a3ca619eb..550c7f3435cc6c3180769e47f05bf693bdc380e3 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/TamableAnimal.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/TamableAnimal.java
|
||||
@@ -250,7 +250,12 @@ public abstract class TamableAnimal extends Animal implements OwnableEntity {
|
||||
if (entityliving instanceof ServerPlayer) {
|
||||
ServerPlayer entityplayer = (ServerPlayer) entityliving;
|
||||
|
||||
- entityplayer.sendSystemMessage(this.getCombatTracker().getDeathMessage());
|
||||
+ // Paper start - Add TameableDeathMessageEvent
|
||||
+ io.papermc.paper.event.entity.TameableDeathMessageEvent event = new io.papermc.paper.event.entity.TameableDeathMessageEvent((org.bukkit.entity.Tameable) getBukkitEntity(), io.papermc.paper.adventure.PaperAdventure.asAdventure(this.getCombatTracker().getDeathMessage()));
|
||||
+ if (event.callEvent()) {
|
||||
+ entityplayer.sendSystemMessage(this.getCombatTracker().getDeathMessage());
|
||||
+ }
|
||||
+ // Paper end - Add TameableDeathMessageEvent
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,215 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: SoSeDiK <mrsosedik@gmail.com>
|
||||
Date: Mon, 21 Mar 2022 20:00:53 +0200
|
||||
Subject: [PATCH] Fix new block data for EntityChangeBlockEvent
|
||||
|
||||
Also standardizes how to handle EntityChangeBlockEvent before a removeBlock or destroyBlock
|
||||
call. Always use 'state.getFluidState().createLegacyBlock()' to get the new state instead of
|
||||
just using the 'air' state.
|
||||
|
||||
Also fixes the new block data for EntityBreakDoorEvent (a sub-event from
|
||||
EntityChangeBlockEvent)
|
||||
|
||||
Co-authored-by: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
|
||||
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java b/src/main/java/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java
|
||||
index 6a7052cd6ec88ed4aaea2fef0ebc750060d1dec0..2ade08d1466660ee1787fa97908002ef56389712 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java
|
||||
@@ -108,7 +108,7 @@ public class HarvestFarmland extends Behavior<Villager> {
|
||||
Block block1 = world.getBlockState(this.aboveFarmlandPos.below()).getBlock();
|
||||
|
||||
if (block instanceof CropBlock && ((CropBlock) block).isMaxAge(iblockdata)) {
|
||||
- if (CraftEventFactory.callEntityChangeBlockEvent(entity, this.aboveFarmlandPos, Blocks.AIR.defaultBlockState())) { // CraftBukkit
|
||||
+ if (CraftEventFactory.callEntityChangeBlockEvent(entity, this.aboveFarmlandPos, iblockdata.getFluidState().createLegacyBlock())) { // CraftBukkit // Paper - fix wrong block state
|
||||
world.destroyBlock(this.aboveFarmlandPos, true, entity);
|
||||
} // CraftBukkit
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java
|
||||
index e2aa6d46375cbc4f4b694888c4f9750eb26e4940..6827426e6e9706909265f84bf97b5fa7105a7fea 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java
|
||||
@@ -73,7 +73,7 @@ public class BreakDoorGoal extends DoorInteractGoal {
|
||||
|
||||
if (this.breakTime == this.getDoorBreakTime() && this.isValidDifficulty(this.mob.level().getDifficulty())) {
|
||||
// CraftBukkit start
|
||||
- if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityBreakDoorEvent(this.mob, this.doorPos).isCancelled()) {
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityBreakDoorEvent(this.mob, this.doorPos, this.mob.level().getFluidState(this.doorPos).createLegacyBlock()).isCancelled()) { // Paper - fix wrong block state
|
||||
this.start();
|
||||
return;
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/EatBlockGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/EatBlockGoal.java
|
||||
index dc3602002e60d64cbbe9504c22282a9e65da2c9d..9e6f946e6d2878aa3fa8abe0f6fa4770d18676d3 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/ai/goal/EatBlockGoal.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/EatBlockGoal.java
|
||||
@@ -67,8 +67,9 @@ public class EatBlockGoal extends Goal {
|
||||
if (this.eatAnimationTick == this.adjustedTickDelay(4)) {
|
||||
BlockPos blockposition = this.mob.blockPosition();
|
||||
|
||||
- if (EatBlockGoal.IS_TALL_GRASS.test(this.level.getBlockState(blockposition))) {
|
||||
- if (CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockposition, Blocks.AIR.defaultBlockState(), !getServerLevel(this.level).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit
|
||||
+ final BlockState blockState = this.level.getBlockState(blockposition); // Paper - fix wrong block state
|
||||
+ if (EatBlockGoal.IS_TALL_GRASS.test(blockState)) { // Paper - fix wrong block state
|
||||
+ if (CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockposition, blockState.getFluidState().createLegacyBlock(), !getServerLevel(this.level).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit // Paper - fix wrong block state
|
||||
this.level.destroyBlock(blockposition, false);
|
||||
}
|
||||
|
||||
@@ -77,7 +78,7 @@ public class EatBlockGoal extends Goal {
|
||||
BlockPos blockposition1 = blockposition.below();
|
||||
|
||||
if (this.level.getBlockState(blockposition1).is(Blocks.GRASS_BLOCK)) {
|
||||
- if (CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockposition1, Blocks.AIR.defaultBlockState(), !getServerLevel(this.level).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit
|
||||
+ if (CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockposition1, Blocks.DIRT.defaultBlockState(), !getServerLevel(this.level).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit // Paper - Fix wrong block state
|
||||
this.level.levelEvent(2001, blockposition1, Block.getId(Blocks.GRASS_BLOCK.defaultBlockState()));
|
||||
this.level.setBlock(blockposition1, Blocks.DIRT.defaultBlockState(), 2);
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/Rabbit.java b/src/main/java/net/minecraft/world/entity/animal/Rabbit.java
|
||||
index a2bbb79f2999e719b8c80d33e530391ec3d1d2d2..8cc6022507c97af62fb2b4455198bc35744137c9 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/Rabbit.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/Rabbit.java
|
||||
@@ -580,7 +580,7 @@ public class Rabbit extends Animal implements VariantHolder<Rabbit.Variant> {
|
||||
|
||||
if (i == 0) {
|
||||
// CraftBukkit start
|
||||
- if (!CraftEventFactory.callEntityChangeBlockEvent(this.rabbit, blockposition, Blocks.AIR.defaultBlockState())) {
|
||||
+ if (!CraftEventFactory.callEntityChangeBlockEvent(this.rabbit, blockposition, iblockdata.getFluidState().createLegacyBlock())) { // Paper - fix wrong block state
|
||||
return;
|
||||
}
|
||||
// CraftBukkit end
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java
|
||||
index b145023308e6a2823d83db97ff2d79c38b709ef9..e6b18d7f8922cb42acb9e40bef2f71a56aea8646 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java
|
||||
@@ -375,7 +375,7 @@ public class WitherBoss extends Monster implements RangedAttackMob {
|
||||
|
||||
if (WitherBoss.canDestroy(iblockdata)) {
|
||||
// CraftBukkit start
|
||||
- if (!CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.defaultBlockState())) {
|
||||
+ if (!CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, iblockdata.getFluidState().createLegacyBlock())) { // Paper - fix wrong block state
|
||||
continue;
|
||||
}
|
||||
// CraftBukkit end
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java
|
||||
index 0e8349aa6cb23860a4dd884e730ac8f22d422205..48dcd2bc12ce1d08cc5195bff5460dc0dd9902d3 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java
|
||||
@@ -552,7 +552,7 @@ public class EnderMan extends Monster implements NeutralMob {
|
||||
boolean flag = movingobjectpositionblock.getBlockPos().equals(blockposition);
|
||||
|
||||
if (iblockdata.is(BlockTags.ENDERMAN_HOLDABLE) && flag) {
|
||||
- if (CraftEventFactory.callEntityChangeBlockEvent(this.enderman, blockposition, Blocks.AIR.defaultBlockState())) { // CraftBukkit - Place event
|
||||
+ if (CraftEventFactory.callEntityChangeBlockEvent(this.enderman, blockposition, iblockdata.getFluidState().createLegacyBlock())) { // CraftBukkit - Place event // Paper - fix wrong block state
|
||||
world.removeBlock(blockposition, false);
|
||||
world.gameEvent((Holder) GameEvent.BLOCK_DESTROY, blockposition, GameEvent.Context.of(this.enderman, iblockdata));
|
||||
this.enderman.setCarriedBlock(iblockdata.getBlock().defaultBlockState());
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/Ravager.java b/src/main/java/net/minecraft/world/entity/monster/Ravager.java
|
||||
index c661ae4e5c07494c7de852cc8d01f0f9839c1590..c96fbfe448b3e7b722a8db0e1688276776abd94e 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Ravager.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Ravager.java
|
||||
@@ -165,7 +165,7 @@ public class Ravager extends Raider {
|
||||
|
||||
if (block instanceof LeavesBlock) {
|
||||
// CraftBukkit start
|
||||
- if (!CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, net.minecraft.world.level.block.Blocks.AIR.defaultBlockState())) {
|
||||
+ if (!CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, iblockdata.getFluidState().createLegacyBlock())) { // Paper - fix wrong block state
|
||||
continue;
|
||||
}
|
||||
// CraftBukkit end
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/Silverfish.java b/src/main/java/net/minecraft/world/entity/monster/Silverfish.java
|
||||
index 52d8ea3e40cdb01eab428f5d3d945c0c9f6088ce..1580c8b93a4ea1a9f2d7bf9c589ef64e070e3f53 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Silverfish.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Silverfish.java
|
||||
@@ -165,7 +165,8 @@ public class Silverfish extends Monster {
|
||||
|
||||
if (block instanceof InfestedBlock) {
|
||||
// CraftBukkit start
|
||||
- if (!CraftEventFactory.callEntityChangeBlockEvent(this.silverfish, blockposition1, net.minecraft.world.level.block.Blocks.AIR.defaultBlockState())) {
|
||||
+ BlockState afterState = world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? iblockdata.getFluidState().createLegacyBlock() : ((InfestedBlock) block).hostStateByInfested(world.getBlockState(blockposition1)); // Paper - fix wrong block state
|
||||
+ if (!CraftEventFactory.callEntityChangeBlockEvent(this.silverfish, blockposition1, afterState)) { // Paper - fix wrong block state
|
||||
continue;
|
||||
}
|
||||
// CraftBukkit end
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java
|
||||
index a486466040a646b8a5a5ff2430cdd25b95b7e20f..e78eef3b6fbcd657f9dd180df4cb2eeb55d0814f 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java
|
||||
@@ -294,7 +294,7 @@ public class ThrownPotion extends ThrowableItemProjectile {
|
||||
|
||||
if (iblockdata.is(BlockTags.FIRE)) {
|
||||
// CraftBukkit start
|
||||
- if (CraftEventFactory.callEntityChangeBlockEvent(this, pos, Blocks.AIR.defaultBlockState())) {
|
||||
+ if (CraftEventFactory.callEntityChangeBlockEvent(this, pos, iblockdata.getFluidState().createLegacyBlock())) { // Paper - fix wrong block state
|
||||
this.level().destroyBlock(pos, false, this);
|
||||
}
|
||||
// CraftBukkit end
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/ChorusFlowerBlock.java b/src/main/java/net/minecraft/world/level/block/ChorusFlowerBlock.java
|
||||
index fae574f8617bada96469a2eb1349eaa061f0450f..6d0d13e70a82c4db7848e1007f5b6d670dd5acad 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/ChorusFlowerBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/ChorusFlowerBlock.java
|
||||
@@ -286,7 +286,7 @@ public class ChorusFlowerBlock extends Block {
|
||||
if (world instanceof ServerLevel worldserver) {
|
||||
if (projectile.mayInteract(worldserver, blockposition) && projectile.mayBreak(worldserver)) {
|
||||
// CraftBukkit
|
||||
- if (!CraftEventFactory.callEntityChangeBlockEvent(projectile, blockposition, Blocks.AIR.defaultBlockState())) {
|
||||
+ if (!CraftEventFactory.callEntityChangeBlockEvent(projectile, blockposition, state.getFluidState().createLegacyBlock())) { // Paper - fix wrong block state
|
||||
return;
|
||||
}
|
||||
// CraftBukkit end
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/PointedDripstoneBlock.java b/src/main/java/net/minecraft/world/level/block/PointedDripstoneBlock.java
|
||||
index 48503f5ba8bccb42ae3b5324a5f65f6c23a8e479..bd38a0a73d543a85bb5c6d50219f5438ce194df3 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/PointedDripstoneBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/PointedDripstoneBlock.java
|
||||
@@ -137,7 +137,7 @@ public class PointedDripstoneBlock extends Block implements Fallable, SimpleWate
|
||||
|
||||
if (projectile.mayInteract(worldserver, blockposition) && projectile.mayBreak(worldserver) && projectile instanceof ThrownTrident && projectile.getDeltaMovement().length() > 0.6D) {
|
||||
// CraftBukkit start
|
||||
- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(projectile, blockposition, Blocks.AIR.defaultBlockState())) {
|
||||
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(projectile, blockposition, state.getFluidState().createLegacyBlock())) { // Paper - fix wrong block state
|
||||
return;
|
||||
}
|
||||
// CraftBukkit end
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/TntBlock.java b/src/main/java/net/minecraft/world/level/block/TntBlock.java
|
||||
index d256b0f3998028709334dd6c394d184f2c36efce..2cbe2053dd5d0bcdcd89de69762c77b400b8697a 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/TntBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/TntBlock.java
|
||||
@@ -158,7 +158,7 @@ public class TntBlock extends Block {
|
||||
|
||||
if (projectile.isOnFire() && projectile.mayInteract(worldserver, blockposition)) {
|
||||
// CraftBukkit start
|
||||
- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(projectile, blockposition, Blocks.AIR.defaultBlockState()) || !CraftEventFactory.callTNTPrimeEvent(world, blockposition, PrimeCause.PROJECTILE, projectile, null)) {
|
||||
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(projectile, blockposition, state.getFluidState().createLegacyBlock()) || !CraftEventFactory.callTNTPrimeEvent(world, blockposition, PrimeCause.PROJECTILE, projectile, null)) { // Paper - fix wrong block state
|
||||
return;
|
||||
}
|
||||
// CraftBukkit end
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/WaterlilyBlock.java b/src/main/java/net/minecraft/world/level/block/WaterlilyBlock.java
|
||||
index 674d710ff88db5eced9e017284d1b7ec7a4fe7cd..72320c6099a4b26235bab68570e7b7efad84740f 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/WaterlilyBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/WaterlilyBlock.java
|
||||
@@ -37,7 +37,7 @@ public class WaterlilyBlock extends BushBlock {
|
||||
super.entityInside(state, world, pos, entity);
|
||||
if (world instanceof ServerLevel && entity instanceof AbstractBoat) {
|
||||
// CraftBukkit start
|
||||
- if (!CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState())) {
|
||||
+ if (!CraftEventFactory.callEntityChangeBlockEvent(entity, pos, state.getFluidState().createLegacyBlock())) { // Paper - fix wrong block state
|
||||
return;
|
||||
}
|
||||
// CraftBukkit end
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
index 412f5e414745123535a275d5670b35fff5b1aaec..f7e26e381c2a2fec70cc2df01a12e7dbeeab48cd 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
@@ -1378,11 +1378,11 @@ populateFields(victim, event); // Paper - make cancellable
|
||||
return event;
|
||||
}
|
||||
|
||||
- public static EntityBreakDoorEvent callEntityBreakDoorEvent(Entity entity, BlockPos pos) {
|
||||
+ public static EntityBreakDoorEvent callEntityBreakDoorEvent(Entity entity, BlockPos pos, net.minecraft.world.level.block.state.BlockState newState) { // Paper
|
||||
org.bukkit.entity.Entity entity1 = entity.getBukkitEntity();
|
||||
Block block = CraftBlock.at(entity.level(), pos);
|
||||
|
||||
- EntityBreakDoorEvent event = new EntityBreakDoorEvent((LivingEntity) entity1, block);
|
||||
+ EntityBreakDoorEvent event = new EntityBreakDoorEvent((LivingEntity) entity1, block, newState.createCraftBlockData()); // Paper
|
||||
entity1.getServer().getPluginManager().callEvent(event);
|
||||
|
||||
return event;
|
|
@ -0,0 +1,25 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Tue, 22 Mar 2022 09:50:40 -0700
|
||||
Subject: [PATCH] fix player loottables running when mob loot gamerule is false
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index f72ab5e4e743cb0758ebca28e81f97c143c91b42..84f4913c06bf9068a3a4d7400055031c474a4f7e 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -1218,12 +1218,14 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player {
|
||||
}
|
||||
}
|
||||
}
|
||||
+ if (this.shouldDropLoot() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { // Paper - fix player loottables running when mob loot gamerule is false
|
||||
// SPIGOT-5071: manually add player loot tables (SPIGOT-5195 - ignores keepInventory rule)
|
||||
this.dropFromLootTable(this.serverLevel(), damageSource, this.lastHurtByPlayerTime > 0);
|
||||
this.dropCustomDeathLoot(this.serverLevel(), damageSource, flag);
|
||||
|
||||
loot.addAll(this.drops);
|
||||
this.drops.clear(); // SPIGOT-5188: make sure to clear
|
||||
+ } // Paper - fix player loottables running when mob loot gamerule is false
|
||||
|
||||
Component defaultMessage = this.getCombatTracker().getDeathMessage();
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Thu, 31 Mar 2022 05:11:37 -0700
|
||||
Subject: [PATCH] Ensure entity passenger world matches ridden entity
|
||||
|
||||
Bad plugins doing this would cause some obvious problems...
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index a41bb1d80a84f487a8fb6fdefd7ccc7631902d04..325c8b178dfb39727107190e74663113ebb4ab54 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -2802,7 +2802,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
}
|
||||
|
||||
public boolean startRiding(Entity entity, boolean force) {
|
||||
- if (entity == this.vehicle) {
|
||||
+ if (entity == this.vehicle || entity.level != this.level) { // Paper - Ensure entity passenger world matches ridden entity (bad plugins)
|
||||
return false;
|
||||
} else if (!entity.couldAcceptPassenger()) {
|
||||
return false;
|
|
@ -0,0 +1,66 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sun, 20 Mar 2022 22:06:47 -0700
|
||||
Subject: [PATCH] Cache resource keys and optimize reference Holder tags set
|
||||
|
||||
TagKeys are always interned, so we can use a reference hash set for them
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/core/Holder.java b/src/main/java/net/minecraft/core/Holder.java
|
||||
index 94671ea227b59a8f820425c401712e6aeb8b2b10..e91c4e26c25980645941ca8fbdcc3a9d02e31063 100644
|
||||
--- a/src/main/java/net/minecraft/core/Holder.java
|
||||
+++ b/src/main/java/net/minecraft/core/Holder.java
|
||||
@@ -230,7 +230,7 @@ public interface Holder<T> {
|
||||
}
|
||||
|
||||
void bindTags(Collection<TagKey<T>> tags) {
|
||||
- this.tags = Set.copyOf(tags);
|
||||
+ this.tags = java.util.Collections.unmodifiableSet(new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(tags)); // Paper
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBiome.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBiome.java
|
||||
index 95b956802f83b583a823fcd24808363775a56842..33d2e89ac40465b0c4633f9c51378b80f7c397a9 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBiome.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBiome.java
|
||||
@@ -3,6 +3,7 @@ package org.bukkit.craftbukkit.block;
|
||||
import com.google.common.base.Preconditions;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
+import net.minecraft.resources.ResourceKey;
|
||||
import org.bukkit.Registry;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.craftbukkit.CraftRegistry;
|
||||
@@ -27,13 +28,14 @@ public class CraftBiome {
|
||||
return CraftBiome.minecraftToBukkit(minecraft.value());
|
||||
}
|
||||
|
||||
+ private static final java.util.Map<org.bukkit.block.Biome, ResourceKey<net.minecraft.world.level.biome.Biome>> BIOME_KEY_CACHE = java.util.Collections.synchronizedMap(new java.util.EnumMap<>(Biome.class)); // Paper
|
||||
public static net.minecraft.world.level.biome.Biome bukkitToMinecraft(Biome bukkit) {
|
||||
if (bukkit == null || bukkit == Biome.CUSTOM) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return CraftRegistry.getMinecraftRegistry(Registries.BIOME)
|
||||
- .getOptional(CraftNamespacedKey.toMinecraft(bukkit.getKey())).orElseThrow();
|
||||
+ .getOptional(BIOME_KEY_CACHE.computeIfAbsent(bukkit, b -> ResourceKey.create(Registries.BIOME, CraftNamespacedKey.toMinecraft(b.getKey())))).orElseThrow();
|
||||
}
|
||||
|
||||
public static Holder<net.minecraft.world.level.biome.Biome> bukkitToMinecraftHolder(Biome bukkit) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityType.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityType.java
|
||||
index 6cf8af0c85231de9955282d4abaa0607ec9a195c..d230cbc26f61d8ac5880825aca4dfab197c20401 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityType.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityType.java
|
||||
@@ -25,11 +25,11 @@ public class CraftEntityType {
|
||||
return bukkit;
|
||||
}
|
||||
|
||||
+ private static final java.util.Map<EntityType, net.minecraft.resources.ResourceKey<net.minecraft.world.entity.EntityType<?>>> KEY_CACHE = java.util.Collections.synchronizedMap(new java.util.EnumMap<>(EntityType.class)); // Paper
|
||||
public static net.minecraft.world.entity.EntityType<?> bukkitToMinecraft(EntityType bukkit) {
|
||||
Preconditions.checkArgument(bukkit != null);
|
||||
-
|
||||
return CraftRegistry.getMinecraftRegistry(Registries.ENTITY_TYPE)
|
||||
- .getOptional(CraftNamespacedKey.toMinecraft(bukkit.getKey())).orElseThrow();
|
||||
+ .getOptional(KEY_CACHE.computeIfAbsent(bukkit, type -> net.minecraft.resources.ResourceKey.create(Registries.ENTITY_TYPE, CraftNamespacedKey.toMinecraft(type.getKey())))).orElseThrow();
|
||||
}
|
||||
|
||||
public static Holder<net.minecraft.world.entity.EntityType<?>> bukkitToMinecraftHolder(EntityType bukkit) {
|
142
patches/server/0683-Allow-changing-the-EnderDragon-podium.patch
Normal file
142
patches/server/0683-Allow-changing-the-EnderDragon-podium.patch
Normal file
|
@ -0,0 +1,142 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Doc <nachito94@msn.com>
|
||||
Date: Sun, 3 Apr 2022 11:31:42 -0400
|
||||
Subject: [PATCH] Allow changing the EnderDragon podium
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
||||
index 25d2226c2a5dda411a9e35f7a0e3ab183110c227..38456d3901e495e4c401cff0de7ae38544c1b2a7 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
||||
@@ -104,6 +104,10 @@ public class EnderDragon extends Mob implements Enemy {
|
||||
private final int[] nodeAdjacency;
|
||||
private final BinaryHeap openSet;
|
||||
private final Explosion explosionSource; // CraftBukkit - reusable source for CraftTNTPrimed.getSource()
|
||||
+ // Paper start - Allow changing the EnderDragon podium
|
||||
+ @Nullable
|
||||
+ private BlockPos podium;
|
||||
+ // Paper end - Allow changing the EnderDragon podium
|
||||
|
||||
public EnderDragon(EntityType<? extends EnderDragon> entitytypes, Level world) {
|
||||
super(EntityType.ENDER_DRAGON, world);
|
||||
@@ -143,6 +147,19 @@ public class EnderDragon extends Mob implements Enemy {
|
||||
return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 200.0D);
|
||||
}
|
||||
|
||||
+ // Paper start - Allow changing the EnderDragon podium
|
||||
+ public BlockPos getPodium() {
|
||||
+ if (this.podium == null) {
|
||||
+ return EndPodiumFeature.getLocation(this.getFightOrigin());
|
||||
+ }
|
||||
+ return this.podium;
|
||||
+ }
|
||||
+
|
||||
+ public void setPodium(@Nullable BlockPos blockPos) {
|
||||
+ this.podium = blockPos;
|
||||
+ }
|
||||
+ // Paper end - Allow changing the EnderDragon podium
|
||||
+
|
||||
@Override
|
||||
public boolean isFlapping() {
|
||||
float f = Mth.cos(this.flapTime * 6.2831855F);
|
||||
@@ -988,7 +1005,7 @@ public class EnderDragon extends Mob implements Enemy {
|
||||
vec3d = this.getViewVector(tickDelta);
|
||||
}
|
||||
} else {
|
||||
- BlockPos blockposition = this.level().getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, EndPodiumFeature.getLocation(this.fightOrigin));
|
||||
+ BlockPos blockposition = this.level().getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, this.getPodium()); // Paper - Allow changing the EnderDragon podium
|
||||
|
||||
f1 = Math.max((float) Math.sqrt(blockposition.distToCenterSqr(this.position())) / 4.0F, 1.0F);
|
||||
float f3 = 6.0F / f1;
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonDeathPhase.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonDeathPhase.java
|
||||
index a897c994423d7d624df6ff3a67789cc2436f0417..29f4acc2943ce009088c61bb32aed330f6e2c051 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonDeathPhase.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonDeathPhase.java
|
||||
@@ -42,7 +42,7 @@ public class DragonDeathPhase extends AbstractDragonPhaseInstance {
|
||||
public void doServerTick(ServerLevel world) {
|
||||
this.time++;
|
||||
if (this.targetLocation == null) {
|
||||
- BlockPos blockPos = world.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, EndPodiumFeature.getLocation(this.dragon.getFightOrigin()));
|
||||
+ BlockPos blockPos = world.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, this.dragon.getPodium()); // Paper - Allow changing the EnderDragon podium
|
||||
this.targetLocation = Vec3.atBottomCenterOf(blockPos);
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonHoldingPatternPhase.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonHoldingPatternPhase.java
|
||||
index 2db996f3528c65f5d719cbcfb8ae587ff59c14c1..b8730a0fc759dbacc9b2e737c3e48d3ff9c5d824 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonHoldingPatternPhase.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonHoldingPatternPhase.java
|
||||
@@ -53,7 +53,7 @@ public class DragonHoldingPatternPhase extends AbstractDragonPhaseInstance {
|
||||
|
||||
private void findNewTarget(ServerLevel world) {
|
||||
if (this.currentPath != null && this.currentPath.isDone()) {
|
||||
- BlockPos blockPos = world.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, EndPodiumFeature.getLocation(this.dragon.getFightOrigin()));
|
||||
+ BlockPos blockPos = world.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, new BlockPos(this.dragon.getPodium())); // Paper - Allow changing the EnderDragon podium
|
||||
int i = this.dragon.getDragonFight() == null ? 0 : this.dragon.getDragonFight().getCrystalsAlive();
|
||||
if (this.dragon.getRandom().nextInt(i + 3) == 0) {
|
||||
this.dragon.getPhaseManager().setPhase(EnderDragonPhase.LANDING_APPROACH);
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonLandingApproachPhase.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonLandingApproachPhase.java
|
||||
index 4c28d3c3d601b5316d79c8474d106800abc8e95b..1c4250cc61b770707ad25c0e93caeacbcb0a80b0 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonLandingApproachPhase.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonLandingApproachPhase.java
|
||||
@@ -52,7 +52,7 @@ public class DragonLandingApproachPhase extends AbstractDragonPhaseInstance {
|
||||
private void findNewTarget(ServerLevel world) {
|
||||
if (this.currentPath == null || this.currentPath.isDone()) {
|
||||
int i = this.dragon.findClosestNode();
|
||||
- BlockPos blockPos = world.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, EndPodiumFeature.getLocation(this.dragon.getFightOrigin()));
|
||||
+ BlockPos blockPos = world.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, this.dragon.getPodium()); // Paper - Allow changing the EnderDragon podium
|
||||
Player player = world.getNearestPlayer(NEAR_EGG_TARGETING, this.dragon, (double)blockPos.getX(), (double)blockPos.getY(), (double)blockPos.getZ());
|
||||
int j;
|
||||
if (player != null) {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonLandingPhase.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonLandingPhase.java
|
||||
index 789df0e05d0cf0df0f66bffc98f587a31770ebea..cfcd3f91517832d26c1177c3715cfa8ebe675193 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonLandingPhase.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonLandingPhase.java
|
||||
@@ -42,7 +42,7 @@ public class DragonLandingPhase extends AbstractDragonPhaseInstance {
|
||||
public void doServerTick(ServerLevel world) {
|
||||
if (this.targetLocation == null) {
|
||||
this.targetLocation = Vec3.atBottomCenterOf(
|
||||
- world.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, EndPodiumFeature.getLocation(this.dragon.getFightOrigin()))
|
||||
+ world.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, this.dragon.getPodium()) // Paper - Allow changing the EnderDragon podium
|
||||
);
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonTakeoffPhase.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonTakeoffPhase.java
|
||||
index f942ea2ad87d4ae12921578f7b869f064c8db7b0..5c5b03f612621ec4efd92b78601032b84e6f3c28 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonTakeoffPhase.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonTakeoffPhase.java
|
||||
@@ -24,7 +24,7 @@ public class DragonTakeoffPhase extends AbstractDragonPhaseInstance {
|
||||
@Override
|
||||
public void doServerTick(ServerLevel world) {
|
||||
if (!this.firstTick && this.currentPath != null) {
|
||||
- BlockPos blockPos = world.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, EndPodiumFeature.getLocation(this.dragon.getFightOrigin()));
|
||||
+ BlockPos blockPos = world.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, this.dragon.getPodium()); // Paper - Allow changing the EnderDragon podium
|
||||
if (!blockPos.closerToCenterThan(this.dragon.position(), 10.0)) {
|
||||
this.dragon.getPhaseManager().setPhase(EnderDragonPhase.HOLDING_PATTERN);
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderDragon.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderDragon.java
|
||||
index 25b3d889a1742c347e60725df8d6f6c1cee264c7..7b7b89e67d53ed70efae714192c5fa32977f3d9c 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderDragon.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderDragon.java
|
||||
@@ -73,4 +73,22 @@ public class CraftEnderDragon extends CraftMob implements EnderDragon, CraftEnem
|
||||
public int getDeathAnimationTicks() {
|
||||
return this.getHandle().dragonDeathTime;
|
||||
}
|
||||
+
|
||||
+ // Paper start - Allow changing the EnderDragon podium
|
||||
+ @Override
|
||||
+ public org.bukkit.Location getPodium() {
|
||||
+ net.minecraft.core.BlockPos blockPosOrigin = this.getHandle().getPodium();
|
||||
+ return new org.bukkit.Location(getWorld(), blockPosOrigin.getX(), blockPosOrigin.getY(), blockPosOrigin.getZ());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setPodium(org.bukkit.Location location) {
|
||||
+ if (location == null) {
|
||||
+ this.getHandle().setPodium(null);
|
||||
+ } else {
|
||||
+ org.apache.commons.lang.Validate.isTrue(location.getWorld() == null || location.getWorld().equals(getWorld()), "You cannot set a podium in a different world to where the dragon is");
|
||||
+ this.getHandle().setPodium(io.papermc.paper.util.MCUtil.toBlockPos(location));
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Allow changing the EnderDragon podium
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: etil2jz <blanchot.arthur@protonmail.ch>
|
||||
Date: Sat, 2 Apr 2022 23:29:24 +0200
|
||||
Subject: [PATCH] Fix NBT pieces overriding a block entity during worldgen
|
||||
deadlock
|
||||
|
||||
By checking if the world passed into StructureTemplate's placeInWorld
|
||||
is not a WorldGenRegion, we can bypass the deadlock entirely.
|
||||
See https://bugs.mojang.com/browse/MC-246262
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java
|
||||
index b120949667ae0169a667b329b3cabbd79a0a5bda..734f511d197bc6bf2b02588069eb02c0224781f5 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java
|
||||
@@ -303,7 +303,11 @@ public class StructureTemplate {
|
||||
|
||||
if (definedstructure_blockinfo.nbt != null) {
|
||||
tileentity = world.getBlockEntity(blockposition2);
|
||||
- Clearable.tryClear(tileentity);
|
||||
+ // Paper start - Fix NBT pieces overriding a block entity during worldgen deadlock
|
||||
+ if (!(world instanceof net.minecraft.world.level.WorldGenLevel)) {
|
||||
+ Clearable.tryClear(tileentity);
|
||||
+ }
|
||||
+ // Paper end - Fix NBT pieces overriding a block entity during worldgen deadlock
|
||||
world.setBlock(blockposition2, Blocks.BARRIER.defaultBlockState(), 20);
|
||||
}
|
||||
// CraftBukkit start
|
||||
@@ -430,7 +434,11 @@ public class StructureTemplate {
|
||||
if (pair1.getSecond() != null) {
|
||||
tileentity = world.getBlockEntity(blockposition6);
|
||||
if (tileentity != null) {
|
||||
- tileentity.setChanged();
|
||||
+ // Paper start - Fix NBT pieces overriding a block entity during worldgen deadlock
|
||||
+ if (!(world instanceof net.minecraft.world.level.WorldGenLevel)) {
|
||||
+ tileentity.setChanged();
|
||||
+ }
|
||||
+ // Paper end - Fix NBT pieces overriding a block entity during worldgen deadlock
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Wed, 13 Apr 2022 08:25:42 +0100
|
||||
Subject: [PATCH] Prevent tile entity copies loading chunks
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 33f76a6df7997ecdc789004bf0b230e74ad07f5a..ffd8e7a537fd8c6276674f5e0034412bb93ca82c 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -3240,7 +3240,12 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
BlockPos blockposition = BlockEntity.getPosFromTag(customdata.getUnsafe());
|
||||
|
||||
if (this.player.level().isLoaded(blockposition)) {
|
||||
- BlockEntity tileentity = this.player.level().getBlockEntity(blockposition);
|
||||
+ // Paper start - Prevent tile entity copies loading chunks
|
||||
+ BlockEntity tileentity = null;
|
||||
+ if (this.player.distanceToSqr(blockposition.getX(), blockposition.getY(), blockposition.getZ()) < 32 * 32 && this.player.serverLevel().isLoadedAndInBounds(blockposition)) {
|
||||
+ tileentity = this.player.level().getBlockEntity(blockposition);
|
||||
+ }
|
||||
+ // Paper end - Prevent tile entity copies loading chunks
|
||||
|
||||
if (tileentity != null) {
|
||||
tileentity.saveToItem(itemstack, this.player.level().registryAccess());
|
|
@ -0,0 +1,20 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Doc <nachito94@msn.com>
|
||||
Date: Fri, 15 Apr 2022 17:40:30 -0400
|
||||
Subject: [PATCH] Use username instead of display name in
|
||||
PlayerList#getPlayerStats
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
index f65b583057d37ec64a7cd9ed3ec09448064576db..b36edfa81b504107c4225234e3a1d48984e1d241 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
@@ -1354,7 +1354,7 @@ public abstract class PlayerList {
|
||||
// CraftBukkit start
|
||||
public ServerStatsCounter getPlayerStats(ServerPlayer entityhuman) {
|
||||
ServerStatsCounter serverstatisticmanager = entityhuman.getStats();
|
||||
- return serverstatisticmanager == null ? this.getPlayerStats(entityhuman.getUUID(), entityhuman.getDisplayName().getString()) : serverstatisticmanager;
|
||||
+ return serverstatisticmanager == null ? this.getPlayerStats(entityhuman.getUUID(), entityhuman.getGameProfile().getName()) : serverstatisticmanager; // Paper - use username and not display name
|
||||
}
|
||||
|
||||
public ServerStatsCounter getPlayerStats(UUID uuid, String displayName) {
|
23
patches/server/0687-Expand-PlayerItemDamageEvent.patch
Normal file
23
patches/server/0687-Expand-PlayerItemDamageEvent.patch
Normal file
|
@ -0,0 +1,23 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: HexedHero <6012891+HexedHero@users.noreply.github.com>
|
||||
Date: Sun, 10 Apr 2022 06:26:32 +0100
|
||||
Subject: [PATCH] Expand PlayerItemDamageEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
index 9289faebce6b1546af71aeadc6569d2595b486e0..fd49ff4ec22e4bdd3cd1aff0a6a2d2178d773bf2 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
@@ -693,10 +693,11 @@ public final class ItemStack implements DataComponentHolder {
|
||||
}
|
||||
|
||||
public void hurtAndBreak(int amount, ServerLevel world, @Nullable LivingEntity player, Consumer<Item> breakCallback) { // Paper - Add EntityDamageItemEvent
|
||||
+ int originalDamage = amount; // Paper - Expand PlayerItemDamageEvent
|
||||
int j = this.processDurabilityChange(amount, world, player);
|
||||
// CraftBukkit start
|
||||
if (player instanceof final ServerPlayer serverPlayer) { // Paper - Add EntityDamageItemEvent
|
||||
- PlayerItemDamageEvent event = new PlayerItemDamageEvent(serverPlayer.getBukkitEntity(), CraftItemStack.asCraftMirror(this), j); // Paper - Add EntityDamageItemEvent
|
||||
+ PlayerItemDamageEvent event = new PlayerItemDamageEvent(serverPlayer.getBukkitEntity(), CraftItemStack.asCraftMirror(this), j, originalDamage); // Paper - Add EntityDamageItemEvent
|
||||
event.getPlayer().getServer().getPluginManager().callEvent(event);
|
||||
|
||||
if (j != event.getDamage() || event.isCancelled()) {
|
19
patches/server/0688-WorldCreator-keepSpawnLoaded.patch
Normal file
19
patches/server/0688-WorldCreator-keepSpawnLoaded.patch
Normal file
|
@ -0,0 +1,19 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Sat, 3 Jul 2021 21:18:28 +0100
|
||||
Subject: [PATCH] WorldCreator#keepSpawnLoaded
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index cc08b56da8a276202da3e85315fdb2ad530c2545..b31f3013ff63bb6ece80a9d10e51641a7e93f3df 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -1329,7 +1329,7 @@ public final class CraftServer implements Server {
|
||||
}
|
||||
|
||||
// If set to not keep spawn in memory (changed from default) then adjust rule accordingly
|
||||
- if (!creator.keepSpawnInMemory()) {
|
||||
+ if (creator.keepSpawnLoaded() == net.kyori.adventure.util.TriState.FALSE) { // Paper
|
||||
worlddata.getGameRules().getRule(GameRules.RULE_SPAWN_CHUNK_RADIUS).set(0, null);
|
||||
}
|
||||
ServerLevel internal = (ServerLevel) new ServerLevel(this.console, this.console.executor, worldSession, worlddata, worldKey, worlddimension, this.getServer().progressListenerFactory.create(worlddata.getGameRules().getInt(GameRules.RULE_SPAWN_CHUNK_RADIUS)),
|
|
@ -0,0 +1,19 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Gero <gecam59@gmail.com>
|
||||
Date: Sat, 2 Oct 2021 20:08:30 +0200
|
||||
Subject: [PATCH] Fix CME in CraftPersistentDataTypeRegistry
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataTypeRegistry.java b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataTypeRegistry.java
|
||||
index 71dc4a2285ddc86e7aa65ba1a211997ffa8fcce4..20c53aac0aef180ee12de919a8000e4b4bc619ff 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataTypeRegistry.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataTypeRegistry.java
|
||||
@@ -121,7 +121,7 @@ public final class CraftPersistentDataTypeRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
- private final Map<Class, TagAdapter> adapters = new HashMap<>();
|
||||
+ private final Map<Class, TagAdapter> adapters = new java.util.concurrent.ConcurrentHashMap<>(); // Paper - Replace HashMap with ConcurrentHashMap to avoid CME
|
||||
|
||||
/**
|
||||
* Creates a suitable adapter instance for the primitive class type.
|
Loading…
Add table
Add a link
Reference in a new issue