666 plus 1
This commit is contained in:
parent
21afc0a2e2
commit
1de0dc8828
58 changed files with 265 additions and 264 deletions
|
@ -1,118 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: underscore11code <minecrafter11mrt@gmail.com>
|
||||
Date: Fri, 23 Jul 2021 23:01:42 -0700
|
||||
Subject: [PATCH] Add System.out/err catcher
|
||||
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/logging/SysoutCatcher.java b/src/main/java/io/papermc/paper/logging/SysoutCatcher.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..a8e813ca89b033f061e695288b3383bdcf128531
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/logging/SysoutCatcher.java
|
||||
@@ -0,0 +1,94 @@
|
||||
+package io.papermc.paper.logging;
|
||||
+
|
||||
+import org.bukkit.Bukkit;
|
||||
+import org.bukkit.plugin.java.JavaPlugin;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+import java.io.OutputStream;
|
||||
+import java.io.PrintStream;
|
||||
+import java.util.Objects;
|
||||
+import java.util.concurrent.ConcurrentHashMap;
|
||||
+import java.util.concurrent.ConcurrentMap;
|
||||
+import java.util.concurrent.TimeUnit;
|
||||
+import java.util.logging.Level;
|
||||
+
|
||||
+public final class SysoutCatcher {
|
||||
+ private static final boolean SUPPRESS_NAGS = Boolean.getBoolean("io.papermc.paper.suppress.sout.nags");
|
||||
+ // Nanoseconds between nag at most; if interval is caught first, this is reset.
|
||||
+ // <= 0 for disabling.
|
||||
+ private static final long NAG_TIMEOUT = TimeUnit.MILLISECONDS.toNanos(
|
||||
+ Long.getLong("io.papermc.paper.sout.nags.timeout", TimeUnit.MINUTES.toMillis(5L)));
|
||||
+ // Count since last nag; if timeout is first, this is reset.
|
||||
+ // <= 0 for disabling.
|
||||
+ private static final long NAG_INTERVAL = Long.getLong("io.papermc.paper.sout.nags.interval", 200L);
|
||||
+
|
||||
+ // We don't particularly care about how correct this is at any given moment; let's do it on a best attempt basis.
|
||||
+ // The records are also pretty small, so let's just go for a size of 64 to start...
|
||||
+ //
|
||||
+ // Content: Plugin name => nag object
|
||||
+ // Why plugin name?: This doesn't store a reference to the plugin; keeps the reload ability.
|
||||
+ // Why not clean on reload?: Effort.
|
||||
+ private final ConcurrentMap<String, PluginNag> nagRecords = new ConcurrentHashMap<>(64);
|
||||
+
|
||||
+ public SysoutCatcher() {
|
||||
+ System.setOut(new WrappedOutStream(System.out, Level.INFO, "[STDOUT] "));
|
||||
+ System.setErr(new WrappedOutStream(System.err, Level.SEVERE, "[STDERR] "));
|
||||
+ }
|
||||
+
|
||||
+ private final class WrappedOutStream extends PrintStream {
|
||||
+ private static final StackWalker STACK_WALKER = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
|
||||
+ private final Level level;
|
||||
+ private final String prefix;
|
||||
+
|
||||
+ public WrappedOutStream(@NotNull final OutputStream out, final Level level, final String prefix) {
|
||||
+ super(out);
|
||||
+ this.level = level;
|
||||
+ this.prefix = prefix;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void println(@Nullable final String line) {
|
||||
+ final Class<?> clazz = STACK_WALKER.getCallerClass();
|
||||
+ try {
|
||||
+ final JavaPlugin plugin = JavaPlugin.getProvidingPlugin(clazz);
|
||||
+
|
||||
+ // Instead of just printing the message, send it to the plugin's logger
|
||||
+ plugin.getLogger().log(this.level, this.prefix + line);
|
||||
+
|
||||
+ if (SysoutCatcher.SUPPRESS_NAGS) {
|
||||
+ return;
|
||||
+ }
|
||||
+ if (SysoutCatcher.NAG_INTERVAL > 0 || SysoutCatcher.NAG_TIMEOUT > 0) {
|
||||
+ final PluginNag nagRecord = SysoutCatcher.this.nagRecords.computeIfAbsent(plugin.getName(), k -> new PluginNag());
|
||||
+ final boolean hasTimePassed = SysoutCatcher.NAG_TIMEOUT > 0
|
||||
+ && (nagRecord.lastNagTimestamp == Long.MIN_VALUE
|
||||
+ || nagRecord.lastNagTimestamp + SysoutCatcher.NAG_TIMEOUT <= System.nanoTime());
|
||||
+ final boolean hasMessagesPassed = SysoutCatcher.NAG_INTERVAL > 0
|
||||
+ && (nagRecord.messagesSinceNag == Long.MIN_VALUE
|
||||
+ || ++nagRecord.messagesSinceNag >= SysoutCatcher.NAG_INTERVAL);
|
||||
+ if (!hasMessagesPassed && !hasTimePassed) {
|
||||
+ return;
|
||||
+ }
|
||||
+ nagRecord.lastNagTimestamp = System.nanoTime();
|
||||
+ nagRecord.messagesSinceNag = 0;
|
||||
+ }
|
||||
+ Bukkit.getLogger().warning(
|
||||
+ String.format("Nag author(s): '%s' of '%s' about their usage of System.out/err.print. "
|
||||
+ + "Please use your plugin's logger instead (JavaPlugin#getLogger).",
|
||||
+ plugin.getPluginMeta().getAuthors(),
|
||||
+ plugin.getPluginMeta().getDisplayName())
|
||||
+ );
|
||||
+ } catch (final IllegalArgumentException | IllegalStateException e) {
|
||||
+ // If anything happens, the calling class doesn't exist, there is no JavaPlugin that "owns" the calling class, etc
|
||||
+ // Just print out normally, with some added information
|
||||
+ Bukkit.getLogger().log(this.level, String.format("%s[%s] %s", this.prefix, clazz.getName(), line));
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private static class PluginNag {
|
||||
+ private long lastNagTimestamp = Long.MIN_VALUE;
|
||||
+ private long messagesSinceNag = Long.MIN_VALUE;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index 236e73eed6caac7f98236ca418185a143f78c5fa..51337b1b2e74a67ad54c5d594004b649cb6af4ed 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -305,6 +305,7 @@ public final class CraftServer implements Server {
|
||||
public int reloadCount;
|
||||
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
|
||||
|
||||
static {
|
||||
ConfigurationSerialization.registerClass(CraftOfflinePlayer.class);
|
|
@ -1,19 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Noah van der Aa <ndvdaa@gmail.com>
|
||||
Date: Sat, 24 Jul 2021 16:54:11 +0200
|
||||
Subject: [PATCH] Prevent AFK kick while watching end credits
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index cb7d038b902c326d2ebec61f1dc40849c3cfbc63..574efd531199332a36fb26c70cc44bd5a05ff37d 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -389,7 +389,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
--this.dropSpamTickCount;
|
||||
}
|
||||
|
||||
- if (this.player.getLastActionTime() > 0L && this.server.getPlayerIdleTimeout() > 0 && Util.getMillis() - this.player.getLastActionTime() > (long) this.server.getPlayerIdleTimeout() * 1000L * 60L) {
|
||||
+ if (this.player.getLastActionTime() > 0L && this.server.getPlayerIdleTimeout() > 0 && Util.getMillis() - this.player.getLastActionTime() > (long) this.server.getPlayerIdleTimeout() * 1000L * 60L && !this.player.wonGame) { // Paper - Prevent AFK kick while watching end credits
|
||||
this.player.resetLastActionTime(); // CraftBukkit - SPIGOT-854
|
||||
this.disconnect(Component.translatable("multiplayer.disconnect.idling"), org.bukkit.event.player.PlayerKickEvent.Cause.IDLING); // Paper - kick event cause
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Professor Bloodstone <git@bloodstone.dev>
|
||||
Date: Fri, 23 Jul 2021 02:32:04 +0200
|
||||
Subject: [PATCH] Allow skipping writing of comments to server.properties
|
||||
|
||||
Makes less git noise, as it won't update the date every single time
|
||||
|
||||
Use -DPaper.skipServerPropertiesComments=true flag to disable writing it
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/dedicated/Settings.java b/src/main/java/net/minecraft/server/dedicated/Settings.java
|
||||
index fc45c2c4ecdf3906df6bceaf3e019c462fe62186..61bf3ccf998bcb9ebd80e983566e7181a73f0e30 100644
|
||||
--- a/src/main/java/net/minecraft/server/dedicated/Settings.java
|
||||
+++ b/src/main/java/net/minecraft/server/dedicated/Settings.java
|
||||
@@ -29,6 +29,7 @@ public abstract class Settings<T extends Settings<T>> {
|
||||
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
public final Properties properties;
|
||||
+ private static final boolean skipComments = Boolean.getBoolean("Paper.skipServerPropertiesComments"); // Paper - allow skipping server.properties comments
|
||||
// CraftBukkit start
|
||||
private OptionSet options = null;
|
||||
|
||||
@@ -123,7 +124,46 @@ public abstract class Settings<T extends Settings<T>> {
|
||||
return;
|
||||
}
|
||||
// CraftBukkit end
|
||||
- BufferedWriter bufferedwriter = Files.newBufferedWriter(path, StandardCharsets.UTF_8);
|
||||
+ // Paper start - allow skipping server.properties comments
|
||||
+ java.io.OutputStream outputstream = Files.newOutputStream(path);
|
||||
+ java.io.BufferedOutputStream bufferedOutputStream = !skipComments ? new java.io.BufferedOutputStream(outputstream) : new java.io.BufferedOutputStream(outputstream) {
|
||||
+ private boolean isRightAfterNewline = true; // If last written char was newline
|
||||
+ private boolean isComment = false; // Are we writing comment currently?
|
||||
+
|
||||
+ @Override
|
||||
+ public void write(@org.jetbrains.annotations.NotNull byte[] b) throws IOException {
|
||||
+ this.write(b, 0, b.length);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void write(@org.jetbrains.annotations.NotNull byte[] bbuf, int off, int len) throws IOException {
|
||||
+ int latest_offset = off; // The latest offset, updated when comment ends
|
||||
+ for (int index = off; index < off + len; ++index ) {
|
||||
+ byte c = bbuf[index];
|
||||
+ boolean isNewline = (c == '\n' || c == '\r');
|
||||
+ if (isNewline && this.isComment) {
|
||||
+ // Comment has ended
|
||||
+ this.isComment = false;
|
||||
+ latest_offset = index+1;
|
||||
+ }
|
||||
+ if (c == '#' && this.isRightAfterNewline) {
|
||||
+ this.isComment = true;
|
||||
+ if (index != latest_offset) {
|
||||
+ // We got some non-comment data earlier
|
||||
+ super.write(bbuf, latest_offset, index-latest_offset);
|
||||
+ }
|
||||
+ }
|
||||
+ this.isRightAfterNewline = isNewline; // Store for next iteration
|
||||
+
|
||||
+ }
|
||||
+ if (latest_offset < off+len && !this.isComment) {
|
||||
+ // We have some unwritten data, that isn't part of a comment
|
||||
+ super.write(bbuf, latest_offset, (off + len) - latest_offset);
|
||||
+ }
|
||||
+ }
|
||||
+ };
|
||||
+ BufferedWriter bufferedwriter = new BufferedWriter(new java.io.OutputStreamWriter(bufferedOutputStream, java.nio.charset.StandardCharsets.UTF_8.newEncoder()));
|
||||
+ // Paper end - allow skipping server.properties comments
|
||||
|
||||
try {
|
||||
this.properties.store(bufferedwriter, "Minecraft server properties");
|
|
@ -1,204 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Wed, 19 May 2021 18:59:10 -0700
|
||||
Subject: [PATCH] Add PlayerSetSpawnEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/commands/SetSpawnCommand.java b/src/main/java/net/minecraft/server/commands/SetSpawnCommand.java
|
||||
index a2d0699e8427b2262a2396495111125eccafbb66..15db9368227dbc29d07d74e85bd126b345b526b6 100644
|
||||
--- a/src/main/java/net/minecraft/server/commands/SetSpawnCommand.java
|
||||
+++ b/src/main/java/net/minecraft/server/commands/SetSpawnCommand.java
|
||||
@@ -38,24 +38,34 @@ public class SetSpawnCommand {
|
||||
ResourceKey<Level> resourcekey = source.getLevel().dimension();
|
||||
Iterator iterator = targets.iterator();
|
||||
|
||||
+ final Collection<ServerPlayer> actualTargets = new java.util.ArrayList<>(); // Paper - Add PlayerSetSpawnEvent
|
||||
while (iterator.hasNext()) {
|
||||
ServerPlayer entityplayer = (ServerPlayer) iterator.next();
|
||||
|
||||
- entityplayer.setRespawnPosition(resourcekey, pos, angle, true, false, org.bukkit.event.player.PlayerSpawnChangeEvent.Cause.COMMAND); // CraftBukkit
|
||||
+ // Paper start - Add PlayerSetSpawnEvent
|
||||
+ if (entityplayer.setRespawnPosition(resourcekey, pos, angle, true, false, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.COMMAND)) {
|
||||
+ actualTargets.add(entityplayer);
|
||||
+ }
|
||||
+ // Paper end - Add PlayerSetSpawnEvent
|
||||
}
|
||||
+ // Paper start - Add PlayerSetSpawnEvent
|
||||
+ if (actualTargets.isEmpty()) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+ // Paper end - Add PlayerSetSpawnEvent
|
||||
|
||||
String s = resourcekey.location().toString();
|
||||
|
||||
- if (targets.size() == 1) {
|
||||
+ if (actualTargets.size() == 1) { // Paper - Add PlayerSetSpawnEvent
|
||||
source.sendSuccess(() -> {
|
||||
- return Component.translatable("commands.spawnpoint.success.single", pos.getX(), pos.getY(), pos.getZ(), angle, s, ((ServerPlayer) targets.iterator().next()).getDisplayName());
|
||||
+ return Component.translatable("commands.spawnpoint.success.single", pos.getX(), pos.getY(), pos.getZ(), angle, s, ((ServerPlayer) actualTargets.iterator().next()).getDisplayName()); // Paper - Add PlayerSetSpawnEvent
|
||||
}, true);
|
||||
} else {
|
||||
source.sendSuccess(() -> {
|
||||
- return Component.translatable("commands.spawnpoint.success.multiple", pos.getX(), pos.getY(), pos.getZ(), angle, s, targets.size());
|
||||
+ return Component.translatable("commands.spawnpoint.success.multiple", pos.getX(), pos.getY(), pos.getZ(), angle, s, actualTargets.size()); // Paper - Add PlayerSetSpawnEvent
|
||||
}, true);
|
||||
}
|
||||
|
||||
- return targets.size();
|
||||
+ return actualTargets.size(); // Paper - Add PlayerSetSpawnEvent
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index bb0a5e3cdfec18a71c30fde98d21affcd95a9885..3f4950e0c0525346a89c7402ea85edebc6b36698 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -1307,7 +1307,7 @@ public class ServerPlayer extends Player {
|
||||
} else if (this.bedBlocked(blockposition, enumdirection)) {
|
||||
return Either.left(Player.BedSleepingProblem.OBSTRUCTED);
|
||||
} else {
|
||||
- this.setRespawnPosition(this.level().dimension(), blockposition, this.getYRot(), false, true, PlayerSpawnChangeEvent.Cause.BED); // CraftBukkit
|
||||
+ this.setRespawnPosition(this.level().dimension(), blockposition, this.getYRot(), false, true, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.BED); // Paper - Add PlayerSetSpawnEvent
|
||||
if (this.level().isDay()) {
|
||||
return Either.left(Player.BedSleepingProblem.NOT_POSSIBLE_NOW);
|
||||
} else {
|
||||
@@ -2262,44 +2262,50 @@ public class ServerPlayer extends Player {
|
||||
return this.respawnForced;
|
||||
}
|
||||
|
||||
+ @Deprecated // Paper - Add PlayerSetSpawnEvent
|
||||
public void setRespawnPosition(ResourceKey<Level> dimension, @Nullable BlockPos pos, float angle, boolean forced, boolean sendMessage) {
|
||||
- // CraftBukkit start
|
||||
- this.setRespawnPosition(dimension, pos, angle, forced, sendMessage, PlayerSpawnChangeEvent.Cause.UNKNOWN);
|
||||
- }
|
||||
-
|
||||
- public void setRespawnPosition(ResourceKey<Level> resourcekey, @Nullable BlockPos blockposition, float f, boolean flag, boolean flag1, PlayerSpawnChangeEvent.Cause cause) {
|
||||
- ServerLevel newWorld = this.server.getLevel(resourcekey);
|
||||
- Location newSpawn = (blockposition != null) ? CraftLocation.toBukkit(blockposition, newWorld.getWorld(), f, 0) : null;
|
||||
-
|
||||
- PlayerSpawnChangeEvent event = new PlayerSpawnChangeEvent(this.getBukkitEntity(), newSpawn, flag, cause);
|
||||
- Bukkit.getServer().getPluginManager().callEvent(event);
|
||||
- if (event.isCancelled()) {
|
||||
- return;
|
||||
- }
|
||||
- newSpawn = event.getNewSpawn();
|
||||
- flag = event.isForced();
|
||||
-
|
||||
- if (newSpawn != null) {
|
||||
- resourcekey = ((CraftWorld) newSpawn.getWorld()).getHandle().dimension();
|
||||
- blockposition = BlockPos.containing(newSpawn.getX(), newSpawn.getY(), newSpawn.getZ());
|
||||
- f = newSpawn.getYaw();
|
||||
- } else {
|
||||
- resourcekey = Level.OVERWORLD;
|
||||
- blockposition = null;
|
||||
- f = 0.0F;
|
||||
+ // Paper start - Add PlayerSetSpawnEvent
|
||||
+ this.setRespawnPosition(dimension, pos, angle, forced, sendMessage, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.UNKNOWN);
|
||||
+ }
|
||||
+ @Deprecated
|
||||
+ public boolean setRespawnPosition(ResourceKey<Level> dimension, @Nullable BlockPos pos, float angle, boolean forced, boolean sendMessage, PlayerSpawnChangeEvent.Cause cause) {
|
||||
+ return this.setRespawnPosition(dimension, pos, angle, forced, sendMessage, cause == PlayerSpawnChangeEvent.Cause.RESET ?
|
||||
+ com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.PLAYER_RESPAWN : com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.valueOf(cause.name()));
|
||||
+ }
|
||||
+ public boolean setRespawnPosition(ResourceKey<Level> dimension, @Nullable BlockPos pos, float angle, boolean forced, boolean sendMessage, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause cause) {
|
||||
+ Location spawnLoc = null;
|
||||
+ boolean willNotify = false;
|
||||
+ if (pos != null) {
|
||||
+ boolean flag2 = pos.equals(this.respawnPosition) && dimension.equals(this.respawnDimension);
|
||||
+ spawnLoc = io.papermc.paper.util.MCUtil.toLocation(this.getServer().getLevel(dimension), pos);
|
||||
+ spawnLoc.setYaw(angle);
|
||||
+ willNotify = sendMessage && !flag2;
|
||||
+ }
|
||||
+
|
||||
+ PlayerSpawnChangeEvent dumbEvent = new PlayerSpawnChangeEvent(this.getBukkitEntity(), spawnLoc, forced,
|
||||
+ cause == com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.PLAYER_RESPAWN ? PlayerSpawnChangeEvent.Cause.RESET : PlayerSpawnChangeEvent.Cause.valueOf(cause.name()));
|
||||
+ dumbEvent.callEvent();
|
||||
+
|
||||
+ com.destroystokyo.paper.event.player.PlayerSetSpawnEvent event = new com.destroystokyo.paper.event.player.PlayerSetSpawnEvent(this.getBukkitEntity(), cause, dumbEvent.getNewSpawn(), dumbEvent.isForced(), willNotify, willNotify ? net.kyori.adventure.text.Component.translatable("block.minecraft.set_spawn") : null);
|
||||
+ event.setCancelled(dumbEvent.isCancelled());
|
||||
+ if (!event.callEvent()) {
|
||||
+ return false;
|
||||
}
|
||||
- // CraftBukkit end
|
||||
- if (blockposition != null) {
|
||||
- boolean flag2 = blockposition.equals(this.respawnPosition) && resourcekey.equals(this.respawnDimension);
|
||||
+ if (event.getLocation() != null) {
|
||||
+ dimension = event.getLocation().getWorld() != null ? ((CraftWorld) event.getLocation().getWorld()).getHandle().dimension() : dimension;
|
||||
+ pos = io.papermc.paper.util.MCUtil.toBlockPosition(event.getLocation());
|
||||
+ angle = event.getLocation().getYaw();
|
||||
+ forced = event.isForced();
|
||||
+ // Paper end - Add PlayerSetSpawnEvent
|
||||
|
||||
- if (flag1 && !flag2) {
|
||||
- this.sendSystemMessage(Component.translatable("block.minecraft.set_spawn"));
|
||||
+ if (event.willNotifyPlayer() && event.getNotification() != null) { // Paper - Add PlayerSetSpawnEvent
|
||||
+ this.sendSystemMessage(PaperAdventure.asVanilla(event.getNotification())); // Paper - Add PlayerSetSpawnEvent
|
||||
}
|
||||
|
||||
- this.respawnPosition = blockposition;
|
||||
- this.respawnDimension = resourcekey;
|
||||
- this.respawnAngle = f;
|
||||
- this.respawnForced = flag;
|
||||
+ this.respawnPosition = pos;
|
||||
+ this.respawnDimension = dimension;
|
||||
+ this.respawnAngle = angle;
|
||||
+ this.respawnForced = forced;
|
||||
} else {
|
||||
this.respawnPosition = null;
|
||||
this.respawnDimension = Level.OVERWORLD;
|
||||
@@ -2307,6 +2313,7 @@ public class ServerPlayer extends Player {
|
||||
this.respawnForced = false;
|
||||
}
|
||||
|
||||
+ return true; // Paper - Add PlayerSetSpawnEvent
|
||||
}
|
||||
|
||||
public SectionPos getLastSectionPos() {
|
||||
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
index 57e7ce227666a2e273c9e61a102152efd2c0ebd9..7cd6d91fe154d29ec0b0fc0a5a50713bbc2c1c83 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
@@ -871,7 +871,7 @@ public abstract class PlayerList {
|
||||
location = CraftLocation.toBukkit(vec3d, worldserver1.getWorld(), f1, 0.0F);
|
||||
} else if (blockposition != null) {
|
||||
entityplayer1.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.NO_RESPAWN_BLOCK_AVAILABLE, 0.0F));
|
||||
- entityplayer1.setRespawnPosition(null, null, 0f, false, false, PlayerSpawnChangeEvent.Cause.RESET); // CraftBukkit - SPIGOT-5988: Clear respawn location when obstructed
|
||||
+ entityplayer1.setRespawnPosition(null, null, 0f, false, false, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.PLAYER_RESPAWN); // CraftBukkit - SPIGOT-5988: Clear respawn location when obstructed // Paper - Add PlayerSetSpawnEvent
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/RespawnAnchorBlock.java b/src/main/java/net/minecraft/world/level/block/RespawnAnchorBlock.java
|
||||
index ecaa7f0b2bf795f16187f11fa27f6d5d435ccbfe..acd5ec218b8d4c096f44ae2eec1379eeaf30ddc5 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/RespawnAnchorBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/RespawnAnchorBlock.java
|
||||
@@ -87,9 +87,14 @@ public class RespawnAnchorBlock extends Block {
|
||||
ServerPlayer entityplayer = (ServerPlayer) player;
|
||||
|
||||
if (entityplayer.getRespawnDimension() != world.dimension() || !pos.equals(entityplayer.getRespawnPosition())) {
|
||||
- entityplayer.setRespawnPosition(world.dimension(), pos, 0.0F, false, true, org.bukkit.event.player.PlayerSpawnChangeEvent.Cause.RESPAWN_ANCHOR); // CraftBukkit
|
||||
+ if (entityplayer.setRespawnPosition(world.dimension(), pos, 0.0F, false, true, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.RESPAWN_ANCHOR)) { // Paper - Add PlayerSetSpawnEvent
|
||||
world.playSound((Player) null, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, SoundEvents.RESPAWN_ANCHOR_SET_SPAWN, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
return InteractionResult.SUCCESS;
|
||||
+ // Paper start - Add PlayerSetSpawnEvent
|
||||
+ } else {
|
||||
+ return InteractionResult.FAIL;
|
||||
+ }
|
||||
+ // Paper end - Add PlayerSetSpawnEvent
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index 423e599e703723ce038c85c5d42e18a633e130f5..b522a5353cef252fa9040b81c9f012228d334e8f 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -1323,9 +1323,9 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
@Override
|
||||
public void setRespawnLocation(Location location, boolean override) {
|
||||
if (location == null) {
|
||||
- this.getHandle().setRespawnPosition(null, null, 0.0F, override, false, PlayerSpawnChangeEvent.Cause.PLUGIN);
|
||||
+ this.getHandle().setRespawnPosition(null, null, 0.0F, override, false, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.PLUGIN); // Paper - Add PlayerSetSpawnEvent
|
||||
} else {
|
||||
- this.getHandle().setRespawnPosition(((CraftWorld) location.getWorld()).getHandle().dimension(), CraftLocation.toBlockPosition(location), location.getYaw(), override, false, PlayerSpawnChangeEvent.Cause.PLUGIN);
|
||||
+ this.getHandle().setRespawnPosition(((CraftWorld) location.getWorld()).getHandle().dimension(), CraftLocation.toBlockPosition(location), location.getYaw(), override, false, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.PLUGIN); // Paper - Add PlayerSetSpawnEvent
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Wed, 7 Jul 2021 16:30:17 -0700
|
||||
Subject: [PATCH] Make hoppers respect inventory max stack size
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
index f0b4b8eb5d2740cd73b4338fd0c2acc3b06df1f6..e3b6f2bf93710ea695b0c25c0b6968a8f24f0829 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
@@ -438,15 +438,17 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
|
||||
if (itemstack1.isEmpty()) {
|
||||
// Spigot start - SPIGOT-6693, InventorySubcontainer#setItem
|
||||
+ ItemStack leftover = ItemStack.EMPTY; // Paper - Make hoppers respect inventory max stack size
|
||||
if (!stack.isEmpty() && stack.getCount() > to.getMaxStackSize()) {
|
||||
+ leftover = stack; // Paper - Make hoppers respect inventory max stack size
|
||||
stack = stack.split(to.getMaxStackSize());
|
||||
}
|
||||
// Spigot end
|
||||
to.setItem(slot, stack);
|
||||
- stack = ItemStack.EMPTY;
|
||||
+ stack = leftover; // Paper - Make hoppers respect inventory max stack size
|
||||
flag = true;
|
||||
} else if (HopperBlockEntity.canMergeItems(itemstack1, stack)) {
|
||||
- int j = stack.getMaxStackSize() - itemstack1.getCount();
|
||||
+ int j = Math.min(stack.getMaxStackSize(), to.getMaxStackSize()) - itemstack1.getCount(); // Paper - Make hoppers respect inventory max stack size
|
||||
int k = Math.min(stack.getCount(), j);
|
||||
|
||||
stack.shrink(k);
|
|
@ -1,19 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Steinborn <git@steinborn.me>
|
||||
Date: Sun, 8 Aug 2021 00:52:54 -0400
|
||||
Subject: [PATCH] Optimize entity tracker passenger checks
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java
|
||||
index e324c41947b823bba04e3da157e5be7a74d9f099..36e87e8650bef90fab47c4156ce12315f45b2241 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerEntity.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
|
||||
@@ -79,7 +79,7 @@ public class ServerEntity {
|
||||
this.trackedPlayers = trackedPlayers;
|
||||
// CraftBukkit end
|
||||
this.ap = Vec3.ZERO;
|
||||
- this.lastPassengers = Collections.emptyList();
|
||||
+ this.lastPassengers = com.google.common.collect.ImmutableList.of(); // Paper - optimize passenger checks
|
||||
this.level = worldserver;
|
||||
this.broadcast = consumer;
|
||||
this.entity = entity;
|
|
@ -1,18 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
|
||||
Date: Wed, 2 Dec 2020 03:07:58 -0800
|
||||
Subject: [PATCH] Config option for Piglins guarding chests
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAi.java b/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAi.java
|
||||
index 4a071dea48e86a962fd41a6ebecc5dfdaf9df78a..9d905ba5c306409ff846f93e3569d1e4c3c6bbf7 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAi.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAi.java
|
||||
@@ -478,6 +478,7 @@ public class PiglinAi {
|
||||
}
|
||||
|
||||
public static void angerNearbyPiglins(Player player, boolean blockOpen) {
|
||||
+ if (!player.level().paperConfig().entities.behavior.piglinsGuardChests) return; // Paper - Config option for Piglins guarding chests
|
||||
List<Piglin> list = player.level().getEntitiesOfClass(Piglin.class, player.getBoundingBox().inflate(16.0D));
|
||||
|
||||
list.stream().filter(PiglinAi::isIdle).filter((entitypiglin) -> {
|
|
@ -1,65 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Tue, 22 Dec 2020 13:52:48 -0800
|
||||
Subject: [PATCH] Add EntityDamageItemEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
index 9d2d305a5e66b9f3d94f6464736f5bb40adae591..d5ee83e6538fbd067388272fa9895e17859be642 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
@@ -624,7 +624,7 @@ public final class ItemStack {
|
||||
return this.getItem().getMaxDamage();
|
||||
}
|
||||
|
||||
- public boolean hurt(int amount, RandomSource random, @Nullable ServerPlayer player) {
|
||||
+ public boolean hurt(int amount, RandomSource random, @Nullable LivingEntity player) { // Paper - Add EntityDamageItemEvent
|
||||
if (!this.isDamageableItem()) {
|
||||
return false;
|
||||
} else {
|
||||
@@ -642,8 +642,8 @@ public final class ItemStack {
|
||||
|
||||
amount -= k;
|
||||
// CraftBukkit start
|
||||
- if (player != null) {
|
||||
- PlayerItemDamageEvent event = new PlayerItemDamageEvent(player.getBukkitEntity(), CraftItemStack.asCraftMirror(this), amount);
|
||||
+ if (player instanceof ServerPlayer serverPlayer) { // Paper - Add EntityDamageItemEvent
|
||||
+ PlayerItemDamageEvent event = new PlayerItemDamageEvent(serverPlayer.getBukkitEntity(), CraftItemStack.asCraftMirror(this), amount); // Paper - Add EntityDamageItemEvent
|
||||
event.getPlayer().getServer().getPluginManager().callEvent(event);
|
||||
|
||||
if (amount != event.getDamage() || event.isCancelled()) {
|
||||
@@ -654,6 +654,14 @@ public final class ItemStack {
|
||||
}
|
||||
|
||||
amount = event.getDamage();
|
||||
+ // Paper start - Add EntityDamageItemEvent
|
||||
+ } else if (player != null) {
|
||||
+ io.papermc.paper.event.entity.EntityDamageItemEvent event = new io.papermc.paper.event.entity.EntityDamageItemEvent(player.getBukkitLivingEntity(), CraftItemStack.asCraftMirror(this), amount);
|
||||
+ if (!event.callEvent()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ amount = event.getDamage();
|
||||
+ // Paper end - Add EntityDamageItemEvent
|
||||
}
|
||||
// CraftBukkit end
|
||||
if (amount <= 0) {
|
||||
@@ -661,8 +669,8 @@ public final class ItemStack {
|
||||
}
|
||||
}
|
||||
|
||||
- if (player != null && amount != 0) {
|
||||
- CriteriaTriggers.ITEM_DURABILITY_CHANGED.trigger(player, this, this.getDamageValue() + amount);
|
||||
+ if (player instanceof ServerPlayer serverPlayer && amount != 0) { // Paper - Add EntityDamageItemEvent
|
||||
+ CriteriaTriggers.ITEM_DURABILITY_CHANGED.trigger(serverPlayer, this, this.getDamageValue() + amount); // Paper - Add EntityDamageItemEvent
|
||||
}
|
||||
|
||||
j = this.getDamageValue() + amount;
|
||||
@@ -674,7 +682,7 @@ public final class ItemStack {
|
||||
public <T extends LivingEntity> void hurtAndBreak(int amount, T entity, Consumer<T> breakCallback) {
|
||||
if (!entity.level().isClientSide && (!(entity instanceof net.minecraft.world.entity.player.Player) || !((net.minecraft.world.entity.player.Player) entity).getAbilities().instabuild)) {
|
||||
if (this.isDamageableItem()) {
|
||||
- if (this.hurt(amount, entity.getRandom(), entity instanceof ServerPlayer ? (ServerPlayer) entity : null)) {
|
||||
+ if (this.hurt(amount, entity.getRandom(), entity /*instanceof ServerPlayer ? (ServerPlayer) entity : null*/)) { // Paper - Add EntityDamageItemEvent
|
||||
breakCallback.accept(entity);
|
||||
Item item = this.getItem();
|
||||
// CraftBukkit start - Check for item breaking
|
|
@ -1,53 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Steinborn <git@steinborn.me>
|
||||
Date: Mon, 9 Aug 2021 00:38:37 -0400
|
||||
Subject: [PATCH] Optimize indirect passenger iteration
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index 53e2ca6ddba4936a7387e07a2aae4c282a305222..04f901236a5b9ca59ba45a5bac69ba89fc767679 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -3842,20 +3842,34 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
|
||||
}
|
||||
|
||||
private Stream<Entity> getIndirectPassengersStream() {
|
||||
+ if (this.passengers.isEmpty()) { return Stream.of(); } // Paper - Optimize indirect passenger iteration
|
||||
return this.passengers.stream().flatMap(Entity::getSelfAndPassengers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Entity> getSelfAndPassengers() {
|
||||
+ if (this.passengers.isEmpty()) { return Stream.of(this); } // Paper - Optimize indirect passenger iteration
|
||||
return Stream.concat(Stream.of(this), this.getIndirectPassengersStream());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Entity> getPassengersAndSelf() {
|
||||
+ if (this.passengers.isEmpty()) { return Stream.of(this); } // Paper - Optimize indirect passenger iteration
|
||||
return Stream.concat(this.passengers.stream().flatMap(Entity::getPassengersAndSelf), Stream.of(this));
|
||||
}
|
||||
|
||||
public Iterable<Entity> getIndirectPassengers() {
|
||||
+ // Paper start - Optimize indirect passenger iteration
|
||||
+ if (this.passengers.isEmpty()) { return ImmutableList.of(); }
|
||||
+ ImmutableList.Builder<Entity> indirectPassengers = ImmutableList.builder();
|
||||
+ for (Entity passenger : this.passengers) {
|
||||
+ indirectPassengers.add(passenger);
|
||||
+ indirectPassengers.addAll(passenger.getIndirectPassengers());
|
||||
+ }
|
||||
+ return indirectPassengers.build();
|
||||
+ }
|
||||
+ private Iterable<Entity> getIndirectPassengers_old() {
|
||||
+ // Paper end - Optimize indirect passenger iteration
|
||||
return () -> {
|
||||
return this.getIndirectPassengersStream().iterator();
|
||||
};
|
||||
@@ -3868,6 +3882,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
|
||||
}
|
||||
|
||||
public boolean hasExactlyOnePlayerPassenger() {
|
||||
+ if (this.passengers.isEmpty()) { return false; } // Paper - Optimize indirect passenger iteration
|
||||
return this.countPlayerPassengers() == 1;
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Warrior <50800980+Warriorrrr@users.noreply.github.com>
|
||||
Date: Fri, 13 Aug 2021 01:14:38 +0200
|
||||
Subject: [PATCH] Configurable item frame map cursor update interval
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java
|
||||
index 36e87e8650bef90fab47c4156ce12315f45b2241..91563f903834c1a0636dc087f8c6376815165b6c 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerEntity.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
|
||||
@@ -117,7 +117,7 @@ public class ServerEntity {
|
||||
if (true || this.tickCount % 10 == 0) { // CraftBukkit - Moved below, should always enter this block
|
||||
ItemStack itemstack = entityitemframe.getItem();
|
||||
|
||||
- if (this.tickCount % 10 == 0 && itemstack.getItem() instanceof MapItem) { // CraftBukkit - Moved this.tickCounter % 10 logic here so item frames do not enter the other blocks
|
||||
+ if (this.level.paperConfig().maps.itemFrameCursorUpdateInterval > 0 && this.tickCount % this.level.paperConfig().maps.itemFrameCursorUpdateInterval == 0 && itemstack.getItem() instanceof MapItem) { // CraftBukkit - Moved this.tickCounter % 10 logic here so item frames do not enter the other blocks // Paper - Make item frame map cursor update interval configurable
|
||||
Integer integer = MapItem.getMapId(itemstack);
|
||||
MapItemSavedData worldmap = MapItem.getSavedData(integer, this.level);
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Fri, 13 Aug 2021 15:00:06 -0700
|
||||
Subject: [PATCH] Clear bucket NBT after dispense
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
||||
index c1c57f24ccfa7bd17541f53d02293db0bce8dc5c..829c72333664da0c06ce04af93ea39bb90ce0b67 100644
|
||||
--- a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
||||
+++ b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
||||
@@ -656,8 +656,7 @@ public interface DispenseItemBehavior {
|
||||
Item item = Items.BUCKET;
|
||||
stack.shrink(1);
|
||||
if (stack.isEmpty()) {
|
||||
- stack.setItem(Items.BUCKET);
|
||||
- stack.setCount(1);
|
||||
+ stack = new ItemStack(item); // Paper - Clear bucket NBT after dispense
|
||||
} else if (pointer.blockEntity().addItem(new ItemStack(item)) < 0) {
|
||||
this.defaultDispenseItemBehavior.dispense(pointer, new ItemStack(item));
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sat, 21 Aug 2021 12:13:53 -0700
|
||||
Subject: [PATCH] Change EnderEye target without changing other things
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/projectile/EyeOfEnder.java b/src/main/java/net/minecraft/world/entity/projectile/EyeOfEnder.java
|
||||
index 305e92007fa2466f9aa7be8b9224dcc04d20120f..d06a02f1868b911721477c149f1b321979d8d178 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/projectile/EyeOfEnder.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/projectile/EyeOfEnder.java
|
||||
@@ -73,6 +73,11 @@ public class EyeOfEnder extends Entity implements ItemSupplier {
|
||||
}
|
||||
|
||||
public void signalTo(BlockPos pos) {
|
||||
+ // Paper start - Change EnderEye target without changing other things
|
||||
+ this.signalTo(pos, true);
|
||||
+ }
|
||||
+ public void signalTo(BlockPos pos, boolean update) {
|
||||
+ // Paper end - Change EnderEye target without changing other things
|
||||
double d0 = (double) pos.getX();
|
||||
int i = pos.getY();
|
||||
double d1 = (double) pos.getZ();
|
||||
@@ -90,8 +95,10 @@ public class EyeOfEnder extends Entity implements ItemSupplier {
|
||||
this.tz = d1;
|
||||
}
|
||||
|
||||
+ if (update) { // Paper - Change EnderEye target without changing other things
|
||||
this.life = 0;
|
||||
this.surviveAfterDeath = this.random.nextInt(5) > 0;
|
||||
+ } // Paper - Change EnderEye target without changing other things
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderSignal.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderSignal.java
|
||||
index d4dfc7a0266086b9bf2c3966c6e149453d0583ba..27f56fa4b7ef92a9a4dfa6b782350424b88210f2 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderSignal.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderSignal.java
|
||||
@@ -32,8 +32,15 @@ public class CraftEnderSignal extends CraftEntity implements EnderSignal {
|
||||
|
||||
@Override
|
||||
public void setTargetLocation(Location location) {
|
||||
+ // Paper start - Change EnderEye target without changing other things
|
||||
+ this.setTargetLocation(location, true);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setTargetLocation(Location location, boolean update) {
|
||||
+ // Paper end - Change EnderEye target without changing other things
|
||||
Preconditions.checkArgument(this.getWorld().equals(location.getWorld()), "Cannot target EnderSignal across worlds");
|
||||
- this.getHandle().signalTo(CraftLocation.toBlockPosition(location));
|
||||
+ this.getHandle().signalTo(CraftLocation.toBlockPosition(location), update); // Paper - Change EnderEye target without changing other things
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,87 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sun, 3 Jan 2021 17:58:11 -0800
|
||||
Subject: [PATCH] Add BlockBreakBlockEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java
|
||||
index 89a62fbeeb78c864938a1cea84178478c6dc1b34..57d92c1785586dfab2b3934733d8ba253e042e2e 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/Block.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/Block.java
|
||||
@@ -314,6 +314,24 @@ public class Block extends BlockBehaviour implements ItemLike {
|
||||
|
||||
}
|
||||
|
||||
+ // Paper start - Add BlockBreakBlockEvent
|
||||
+ public static boolean dropResources(BlockState state, LevelAccessor levelAccessor, BlockPos pos, @Nullable BlockEntity blockEntity, BlockPos source) {
|
||||
+ if (levelAccessor instanceof ServerLevel serverLevel) {
|
||||
+ List<org.bukkit.inventory.ItemStack> items = new java.util.ArrayList<>();
|
||||
+ for (ItemStack drop : Block.getDrops(state, serverLevel, pos, blockEntity)) {
|
||||
+ items.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(drop));
|
||||
+ }
|
||||
+ io.papermc.paper.event.block.BlockBreakBlockEvent event = new io.papermc.paper.event.block.BlockBreakBlockEvent(org.bukkit.craftbukkit.block.CraftBlock.at(levelAccessor, pos), org.bukkit.craftbukkit.block.CraftBlock.at(levelAccessor, source), items);
|
||||
+ event.callEvent();
|
||||
+ for (org.bukkit.inventory.ItemStack drop : event.getDrops()) {
|
||||
+ popResource(serverLevel, pos, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(drop));
|
||||
+ }
|
||||
+ state.spawnAfterBreak(serverLevel, pos, ItemStack.EMPTY, true);
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+ // Paper end - Add BlockBreakBlockEvent
|
||||
+
|
||||
public static void dropResources(BlockState state, Level world, BlockPos pos, @Nullable BlockEntity blockEntity, @Nullable Entity entity, ItemStack tool) {
|
||||
if (world instanceof ServerLevel) {
|
||||
Block.getDrops(state, (ServerLevel) world, pos, blockEntity, entity, tool).forEach((itemstack1) -> {
|
||||
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 3ae61e7b50bfc440c597f88843f92903f8a66801..0dbdcd443fe8a299119ea5ba3acb1a0412856184 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
|
||||
@@ -402,7 +402,7 @@ public class PistonBaseBlock extends DirectionalBlock {
|
||||
iblockdata1 = world.getBlockState(blockposition3);
|
||||
BlockEntity tileentity = iblockdata1.hasBlockEntity() ? world.getBlockEntity(blockposition3) : null;
|
||||
|
||||
- dropResources(iblockdata1, world, blockposition3, tileentity);
|
||||
+ dropResources(iblockdata1, world, blockposition3, tileentity, pos); // Paper - Add BlockBreakBlockEvent
|
||||
world.setBlock(blockposition3, Blocks.AIR.defaultBlockState(), 18);
|
||||
world.gameEvent(GameEvent.BLOCK_DESTROY, blockposition3, GameEvent.Context.of(iblockdata1));
|
||||
if (!iblockdata1.is(BlockTags.FIRE)) {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/material/FlowingFluid.java b/src/main/java/net/minecraft/world/level/material/FlowingFluid.java
|
||||
index 0aeb9faa1ce22359361741a591aa3d465d955970..a98ab20814cc29a25e9d29adfbb7e70d46768df2 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/material/FlowingFluid.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/material/FlowingFluid.java
|
||||
@@ -295,7 +295,7 @@ public abstract class FlowingFluid extends Fluid {
|
||||
((LiquidBlockContainer) state.getBlock()).placeLiquid(world, pos, state, fluidState);
|
||||
} else {
|
||||
if (!state.isAir()) {
|
||||
- this.beforeDestroyingBlock(world, pos, state);
|
||||
+ this.beforeDestroyingBlock(world, pos, state, pos.relative(direction.getOpposite())); // Paper - Add BlockBreakBlockEvent
|
||||
}
|
||||
|
||||
world.setBlock(pos, fluidState.createLegacyBlock(), 3);
|
||||
@@ -303,6 +303,7 @@ public abstract class FlowingFluid extends Fluid {
|
||||
|
||||
}
|
||||
|
||||
+ protected void beforeDestroyingBlock(LevelAccessor world, BlockPos pos, BlockState state, BlockPos source) { beforeDestroyingBlock(world, pos, state); } // Paper - Add BlockBreakBlockEvent
|
||||
protected abstract void beforeDestroyingBlock(LevelAccessor world, BlockPos pos, BlockState state);
|
||||
|
||||
private static short getCacheKey(BlockPos from, BlockPos to) {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/material/WaterFluid.java b/src/main/java/net/minecraft/world/level/material/WaterFluid.java
|
||||
index 7f40e8196cb966424ae63043d1f54e661dbce715..21b4afd053e01073eb514264d4960f0f3b1ee3d8 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/material/WaterFluid.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/material/WaterFluid.java
|
||||
@@ -80,6 +80,13 @@ public abstract class WaterFluid extends FlowingFluid {
|
||||
return world.getGameRules().getBoolean(GameRules.RULE_WATER_SOURCE_CONVERSION);
|
||||
}
|
||||
|
||||
+ // Paper start - Add BlockBreakBlockEvent
|
||||
+ @Override
|
||||
+ protected void beforeDestroyingBlock(LevelAccessor world, BlockPos pos, BlockState state, BlockPos source) {
|
||||
+ BlockEntity tileentity = state.hasBlockEntity() ? world.getBlockEntity(pos) : null;
|
||||
+ Block.dropResources(state, world, pos, tileentity, source);
|
||||
+ }
|
||||
+ // Paper end - Add BlockBreakBlockEvent
|
||||
@Override
|
||||
protected void beforeDestroyingBlock(LevelAccessor world, BlockPos pos, BlockState state) {
|
||||
BlockEntity blockEntity = state.hasBlockEntity() ? world.getBlockEntity(pos) : null;
|
|
@ -1,147 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sun, 26 Sep 2021 12:57:28 -0700
|
||||
Subject: [PATCH] Option to prevent NBT copy in smithing recipes
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/item/crafting/SmithingTransformRecipe.java b/src/main/java/net/minecraft/world/item/crafting/SmithingTransformRecipe.java
|
||||
index 566b588006da2b46ec1727be85560ccd59c42c6f..67f7eb89570934b73ff5b894ae3e89fdb874b923 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/crafting/SmithingTransformRecipe.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/crafting/SmithingTransformRecipe.java
|
||||
@@ -23,8 +23,15 @@ public class SmithingTransformRecipe implements SmithingRecipe {
|
||||
final Ingredient base;
|
||||
final Ingredient addition;
|
||||
final ItemStack result;
|
||||
+ final boolean copyNBT; // Paper - Option to prevent NBT copy
|
||||
|
||||
public SmithingTransformRecipe(Ingredient template, Ingredient base, Ingredient addition, ItemStack result) {
|
||||
+ // Paper start - Option to prevent NBT copy
|
||||
+ this(template, base, addition, result, true);
|
||||
+ }
|
||||
+ public SmithingTransformRecipe(Ingredient template, Ingredient base, Ingredient addition, ItemStack result, boolean copyNBT) {
|
||||
+ this.copyNBT = copyNBT;
|
||||
+ // Paper end - Option to prevent NBT copy
|
||||
this.template = template;
|
||||
this.base = base;
|
||||
this.addition = addition;
|
||||
@@ -39,11 +46,13 @@ public class SmithingTransformRecipe implements SmithingRecipe {
|
||||
@Override
|
||||
public ItemStack assemble(Container inventory, RegistryAccess registryManager) {
|
||||
ItemStack itemstack = this.result.copy();
|
||||
+ if (this.copyNBT) { // Paper - Option to prevent NBT copy
|
||||
CompoundTag nbttagcompound = inventory.getItem(1).getTag();
|
||||
|
||||
if (nbttagcompound != null) {
|
||||
itemstack.setTag(nbttagcompound.copy());
|
||||
}
|
||||
+ } // Paper - Option to prevent NBT copy
|
||||
|
||||
return itemstack;
|
||||
}
|
||||
@@ -83,7 +92,7 @@ public class SmithingTransformRecipe implements SmithingRecipe {
|
||||
public Recipe toBukkitRecipe(NamespacedKey id) {
|
||||
CraftItemStack result = CraftItemStack.asCraftMirror(this.result);
|
||||
|
||||
- CraftSmithingTransformRecipe recipe = new CraftSmithingTransformRecipe(id, result, CraftRecipe.toBukkit(this.template), CraftRecipe.toBukkit(this.base), CraftRecipe.toBukkit(this.addition));
|
||||
+ CraftSmithingTransformRecipe recipe = new CraftSmithingTransformRecipe(id, result, CraftRecipe.toBukkit(this.template), CraftRecipe.toBukkit(this.base), CraftRecipe.toBukkit(this.addition), this.copyNBT); // Paper - Option to prevent NBT copy
|
||||
|
||||
return recipe;
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/item/crafting/SmithingTrimRecipe.java b/src/main/java/net/minecraft/world/item/crafting/SmithingTrimRecipe.java
|
||||
index e0b24c140e04a159a7b8aaef64ab94e19fc03dfd..a3686cede266c0205247abcec3ce082ae4a048a0 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/crafting/SmithingTrimRecipe.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/crafting/SmithingTrimRecipe.java
|
||||
@@ -29,8 +29,15 @@ public class SmithingTrimRecipe implements SmithingRecipe {
|
||||
final Ingredient template;
|
||||
final Ingredient base;
|
||||
final Ingredient addition;
|
||||
+ final boolean copyNbt; // Paper - Option to prevent NBT copy
|
||||
|
||||
public SmithingTrimRecipe(Ingredient template, Ingredient base, Ingredient addition) {
|
||||
+ // Paper start - Option to prevent NBT copy
|
||||
+ this(template, base, addition, true);
|
||||
+ }
|
||||
+ public SmithingTrimRecipe(Ingredient template, Ingredient base, Ingredient addition, boolean copyNbt) {
|
||||
+ this.copyNbt = copyNbt;
|
||||
+ // Paper end - Option to prevent NBT copy
|
||||
this.template = template;
|
||||
this.base = base;
|
||||
this.addition = addition;
|
||||
@@ -56,7 +63,7 @@ public class SmithingTrimRecipe implements SmithingRecipe {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
- ItemStack itemstack1 = itemstack.copy();
|
||||
+ ItemStack itemstack1 = this.copyNbt ? itemstack.copy() : new ItemStack(itemstack.getItem(), itemstack.getCount()); // Paper - Option to prevent NBT copy
|
||||
|
||||
itemstack1.setCount(1);
|
||||
ArmorTrim armortrim = new ArmorTrim((Holder) optional.get(), (Holder) optional1.get());
|
||||
@@ -116,7 +123,7 @@ public class SmithingTrimRecipe implements SmithingRecipe {
|
||||
// CraftBukkit start
|
||||
@Override
|
||||
public Recipe toBukkitRecipe(NamespacedKey id) {
|
||||
- return new CraftSmithingTrimRecipe(id, CraftRecipe.toBukkit(this.template), CraftRecipe.toBukkit(this.base), CraftRecipe.toBukkit(this.addition));
|
||||
+ return new CraftSmithingTrimRecipe(id, CraftRecipe.toBukkit(this.template), CraftRecipe.toBukkit(this.base), CraftRecipe.toBukkit(this.addition), this.copyNbt); // Paper - Option to prevent NBT copy
|
||||
}
|
||||
// CraftBukkit end
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftSmithingTransformRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftSmithingTransformRecipe.java
|
||||
index 8c381e2745e7d5b63e72a60c5541b549f0d1b9bf..3301711afbcf39a5db15d9a7b37bbd95a63dd375 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftSmithingTransformRecipe.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftSmithingTransformRecipe.java
|
||||
@@ -12,12 +12,17 @@ public class CraftSmithingTransformRecipe extends SmithingTransformRecipe implem
|
||||
public CraftSmithingTransformRecipe(NamespacedKey key, ItemStack result, RecipeChoice template, RecipeChoice base, RecipeChoice addition) {
|
||||
super(key, result, template, base, addition);
|
||||
}
|
||||
+ // Paper start - Option to prevent NBT copy
|
||||
+ public CraftSmithingTransformRecipe(NamespacedKey key, ItemStack result, RecipeChoice template, RecipeChoice base, RecipeChoice addition, boolean copyNbt) {
|
||||
+ super(key, result, template, base, addition, copyNbt);
|
||||
+ }
|
||||
+ // Paper end - Option to prevent NBT copy
|
||||
|
||||
public static CraftSmithingTransformRecipe fromBukkitRecipe(SmithingTransformRecipe recipe) {
|
||||
if (recipe instanceof CraftSmithingTransformRecipe) {
|
||||
return (CraftSmithingTransformRecipe) recipe;
|
||||
}
|
||||
- CraftSmithingTransformRecipe ret = new CraftSmithingTransformRecipe(recipe.getKey(), recipe.getResult(), recipe.getTemplate(), recipe.getBase(), recipe.getAddition());
|
||||
+ CraftSmithingTransformRecipe ret = new CraftSmithingTransformRecipe(recipe.getKey(), recipe.getResult(), recipe.getTemplate(), recipe.getBase(), recipe.getAddition(), recipe.willCopyNbt()); // Paper - Option to prevent NBT copy
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -25,6 +30,6 @@ public class CraftSmithingTransformRecipe extends SmithingTransformRecipe implem
|
||||
public void addToCraftingManager() {
|
||||
ItemStack result = this.getResult();
|
||||
|
||||
- MinecraftServer.getServer().getRecipeManager().addRecipe(new RecipeHolder<>(CraftNamespacedKey.toMinecraft(this.getKey()), new net.minecraft.world.item.crafting.SmithingTransformRecipe(this.toNMS(this.getTemplate(), true), this.toNMS(this.getBase(), true), this.toNMS(this.getAddition(), true), CraftItemStack.asNMSCopy(result))));
|
||||
+ MinecraftServer.getServer().getRecipeManager().addRecipe(new RecipeHolder<>(CraftNamespacedKey.toMinecraft(this.getKey()), new net.minecraft.world.item.crafting.SmithingTransformRecipe(this.toNMS(this.getTemplate(), true), this.toNMS(this.getBase(), true), this.toNMS(this.getAddition(), true), CraftItemStack.asNMSCopy(result), this.willCopyNbt()))); // Paper - Option to prevent NBT copy
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftSmithingTrimRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftSmithingTrimRecipe.java
|
||||
index 87f20a4811d082f217638768417c1c0feb84f741..2217e7ed9533c52a3b7d27d4dfff23ada6f2cef1 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftSmithingTrimRecipe.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftSmithingTrimRecipe.java
|
||||
@@ -12,17 +12,22 @@ public class CraftSmithingTrimRecipe extends SmithingTrimRecipe implements Craft
|
||||
public CraftSmithingTrimRecipe(NamespacedKey key, RecipeChoice template, RecipeChoice base, RecipeChoice addition) {
|
||||
super(key, template, base, addition);
|
||||
}
|
||||
+ // Paper start - Option to prevent NBT copy
|
||||
+ public CraftSmithingTrimRecipe(NamespacedKey key, RecipeChoice template, RecipeChoice base, RecipeChoice addition, boolean copyNbt) {
|
||||
+ super(key, template, base, addition, copyNbt);
|
||||
+ }
|
||||
+ // Paper end - Option to prevent NBT copy
|
||||
|
||||
public static CraftSmithingTrimRecipe fromBukkitRecipe(SmithingTrimRecipe recipe) {
|
||||
if (recipe instanceof CraftSmithingTrimRecipe) {
|
||||
return (CraftSmithingTrimRecipe) recipe;
|
||||
}
|
||||
- CraftSmithingTrimRecipe ret = new CraftSmithingTrimRecipe(recipe.getKey(), recipe.getTemplate(), recipe.getBase(), recipe.getAddition());
|
||||
+ CraftSmithingTrimRecipe ret = new CraftSmithingTrimRecipe(recipe.getKey(), recipe.getTemplate(), recipe.getBase(), recipe.getAddition(), recipe.willCopyNbt()); // Paper - Option to prevent NBT copy
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addToCraftingManager() {
|
||||
- MinecraftServer.getServer().getRecipeManager().addRecipe(new RecipeHolder<>(CraftNamespacedKey.toMinecraft(this.getKey()), new net.minecraft.world.item.crafting.SmithingTrimRecipe(this.toNMS(this.getTemplate(), true), this.toNMS(this.getBase(), true), this.toNMS(this.getAddition(), true))));
|
||||
+ MinecraftServer.getServer().getRecipeManager().addRecipe(new RecipeHolder<>(CraftNamespacedKey.toMinecraft(this.getKey()), new net.minecraft.world.item.crafting.SmithingTrimRecipe(this.toNMS(this.getTemplate(), true), this.toNMS(this.getBase(), true), this.toNMS(this.getAddition(), true), this.willCopyNbt()))); // Paper - Option to prevent NBT copy
|
||||
}
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Thu, 23 Sep 2021 10:40:09 -0700
|
||||
Subject: [PATCH] More CommandBlock API
|
||||
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/commands/PaperCommandBlockHolder.java b/src/main/java/io/papermc/paper/commands/PaperCommandBlockHolder.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0b42306f17bf8850a13a51067c2d19e7583187e5
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/commands/PaperCommandBlockHolder.java
|
||||
@@ -0,0 +1,33 @@
|
||||
+package io.papermc.paper.commands;
|
||||
+
|
||||
+import io.papermc.paper.adventure.PaperAdventure;
|
||||
+import io.papermc.paper.command.CommandBlockHolder;
|
||||
+import net.kyori.adventure.text.Component;
|
||||
+import net.minecraft.world.level.BaseCommandBlock;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+public interface PaperCommandBlockHolder extends CommandBlockHolder {
|
||||
+
|
||||
+ BaseCommandBlock getCommandBlockHandle();
|
||||
+
|
||||
+ @Override
|
||||
+ default @NotNull Component lastOutput() {
|
||||
+ return PaperAdventure.asAdventure(getCommandBlockHandle().getLastOutput());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default void lastOutput(@Nullable Component lastOutput) {
|
||||
+ getCommandBlockHandle().setLastOutput(PaperAdventure.asVanilla(lastOutput));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default int getSuccessCount() {
|
||||
+ return getCommandBlockHandle().getSuccessCount();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default void setSuccessCount(int successCount) {
|
||||
+ getCommandBlockHandle().setSuccessCount(successCount);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftCommandBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftCommandBlock.java
|
||||
index 7f5d930b6bfaf9a0042f9be4be68f2cc111b304e..63f6b97d82c8b98eb1379b5c30f6c75eb22f7c23 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftCommandBlock.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftCommandBlock.java
|
||||
@@ -5,7 +5,7 @@ import org.bukkit.World;
|
||||
import org.bukkit.block.CommandBlock;
|
||||
import org.bukkit.craftbukkit.util.CraftChatMessage;
|
||||
|
||||
-public class CraftCommandBlock extends CraftBlockEntityState<CommandBlockEntity> implements CommandBlock {
|
||||
+public class CraftCommandBlock extends CraftBlockEntityState<CommandBlockEntity> implements CommandBlock, io.papermc.paper.commands.PaperCommandBlockHolder {
|
||||
|
||||
public CraftCommandBlock(World world, CommandBlockEntity tileEntity) {
|
||||
super(world, tileEntity);
|
||||
@@ -50,5 +50,10 @@ public class CraftCommandBlock extends CraftBlockEntityState<CommandBlockEntity>
|
||||
public void name(net.kyori.adventure.text.Component name) {
|
||||
getSnapshot().getCommandBlock().setName(name == null ? net.minecraft.network.chat.Component.literal("@") : io.papermc.paper.adventure.PaperAdventure.asVanilla(name));
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public net.minecraft.world.level.BaseCommandBlock getCommandBlockHandle() {
|
||||
+ return getSnapshot().getCommandBlock();
|
||||
+ }
|
||||
// Paper end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartCommand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartCommand.java
|
||||
index 92e21126a9347f1ee2279ab09bb6abf2344ad2e2..0ee159d488b15e571f9b19ec852fe279755696fa 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartCommand.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartCommand.java
|
||||
@@ -13,7 +13,7 @@ import org.bukkit.permissions.PermissionAttachment;
|
||||
import org.bukkit.permissions.PermissionAttachmentInfo;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
-public class CraftMinecartCommand extends CraftMinecart implements CommandMinecart {
|
||||
+public class CraftMinecartCommand extends CraftMinecart implements CommandMinecart, io.papermc.paper.commands.PaperCommandBlockHolder {
|
||||
private final PermissibleBase perm = new PermissibleBase(this);
|
||||
|
||||
public CraftMinecartCommand(CraftServer server, MinecartCommandBlock entity) {
|
||||
@@ -64,6 +64,17 @@ public class CraftMinecartCommand extends CraftMinecart implements CommandMineca
|
||||
public net.kyori.adventure.text.@org.jetbrains.annotations.NotNull Component name() {
|
||||
return io.papermc.paper.adventure.PaperAdventure.asAdventure(this.getHandle().getCommandBlock().getName());
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public net.minecraft.world.level.BaseCommandBlock getCommandBlockHandle() {
|
||||
+ return getHandle().getCommandBlock();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void lastOutput(net.kyori.adventure.text.Component lastOutput) {
|
||||
+ io.papermc.paper.commands.PaperCommandBlockHolder.super.lastOutput(lastOutput);
|
||||
+ getCommandBlockHandle().onUpdated();
|
||||
+ }
|
||||
// Paper end
|
||||
|
||||
@Override
|
|
@ -1,103 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Fri, 1 Oct 2021 08:04:39 -0700
|
||||
Subject: [PATCH] Add missing team sidebar display slots
|
||||
|
||||
== AT ==
|
||||
public org.bukkit.craftbukkit.scoreboard.CraftScoreboardTranslations
|
||||
public org.bukkit.craftbukkit.scoreboard.CraftScoreboardTranslations toBukkitSlot(Lnet/minecraft/world/scores/DisplaySlot;)Lorg/bukkit/scoreboard/DisplaySlot;
|
||||
public org.bukkit.craftbukkit.scoreboard.CraftScoreboardTranslations fromBukkitSlot(Lorg/bukkit/scoreboard/DisplaySlot;)Lnet/minecraft/world/scores/DisplaySlot;
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardTranslations.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardTranslations.java
|
||||
index 73c5ffff70605b32188a9bb5fb6c0ee04cb66efe..711d227f5ee6d63356a94a0567968da48e9f284c 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardTranslations.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardTranslations.java
|
||||
@@ -7,35 +7,22 @@ import org.bukkit.scoreboard.RenderType;
|
||||
|
||||
public final class CraftScoreboardTranslations {
|
||||
static final int MAX_DISPLAY_SLOT = 19;
|
||||
+ @Deprecated // Paper
|
||||
static final ImmutableBiMap<DisplaySlot, String> SLOTS = ImmutableBiMap.<DisplaySlot, String>builder()
|
||||
.put(DisplaySlot.BELOW_NAME, "below_name")
|
||||
.put(DisplaySlot.PLAYER_LIST, "list")
|
||||
.put(DisplaySlot.SIDEBAR, "sidebar")
|
||||
- .put(DisplaySlot.SIDEBAR_BLACK, "sidebar.team.black")
|
||||
- .put(DisplaySlot.SIDEBAR_DARK_BLUE, "sidebar.team.dark_blue")
|
||||
- .put(DisplaySlot.SIDEBAR_DARK_GREEN, "sidebar.team.dark_green")
|
||||
- .put(DisplaySlot.SIDEBAR_DARK_AQUA, "sidebar.team.dark_aqua")
|
||||
- .put(DisplaySlot.SIDEBAR_DARK_RED, "sidebar.team.dark_red")
|
||||
- .put(DisplaySlot.SIDEBAR_DARK_PURPLE, "sidebar.team.dark_purple")
|
||||
- .put(DisplaySlot.SIDEBAR_GOLD, "sidebar.team.gold")
|
||||
- .put(DisplaySlot.SIDEBAR_GRAY, "sidebar.team.gray")
|
||||
- .put(DisplaySlot.SIDEBAR_DARK_GRAY, "sidebar.team.dark_gray")
|
||||
- .put(DisplaySlot.SIDEBAR_BLUE, "sidebar.team.blue")
|
||||
- .put(DisplaySlot.SIDEBAR_GREEN, "sidebar.team.green")
|
||||
- .put(DisplaySlot.SIDEBAR_AQUA, "sidebar.team.aqua")
|
||||
- .put(DisplaySlot.SIDEBAR_RED, "sidebar.team.red")
|
||||
- .put(DisplaySlot.SIDEBAR_LIGHT_PURPLE, "sidebar.team.light_purple")
|
||||
- .put(DisplaySlot.SIDEBAR_YELLOW, "sidebar.team.yellow")
|
||||
- .put(DisplaySlot.SIDEBAR_WHITE, "sidebar.team.white")
|
||||
.buildOrThrow();
|
||||
|
||||
private CraftScoreboardTranslations() {}
|
||||
|
||||
public static DisplaySlot toBukkitSlot(net.minecraft.world.scores.DisplaySlot minecraft) {
|
||||
+ if (true) return DisplaySlot.NAMES.value(minecraft.getSerializedName()); // Paper
|
||||
return CraftScoreboardTranslations.SLOTS.inverse().get(minecraft.getSerializedName());
|
||||
}
|
||||
|
||||
public static net.minecraft.world.scores.DisplaySlot fromBukkitSlot(DisplaySlot slot) {
|
||||
+ if (true) return net.minecraft.world.scores.DisplaySlot.CODEC.byName(slot.getId()); // Paper
|
||||
return net.minecraft.world.scores.DisplaySlot.CODEC.byName(CraftScoreboardTranslations.SLOTS.get(slot));
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java
|
||||
index 31714ce05b1023b82e96b36ba52254b4e3e948f2..a06352499b9f2c6fb84e585459077b4aa1886d6f 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java
|
||||
@@ -217,6 +217,15 @@ public class Commodore {
|
||||
desc = getOriginalOrRewrite(desc);
|
||||
}
|
||||
// Paper end
|
||||
+
|
||||
+ // Paper start - DisplaySlot
|
||||
+ if (owner.equals("org/bukkit/scoreboard/DisplaySlot")) {
|
||||
+ if (name.startsWith("SIDEBAR_") && !name.startsWith("SIDEBAR_TEAM_")) {
|
||||
+ super.visitFieldInsn(opcode, owner, name.replace("SIDEBAR_", "SIDEBAR_TEAM_"), desc);
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - DisplaySlot
|
||||
if (owner.equals("org/bukkit/block/Biome")) {
|
||||
switch (name) {
|
||||
case "NETHER":
|
||||
diff --git a/src/test/java/io/papermc/paper/scoreboard/DisplaySlotTest.java b/src/test/java/io/papermc/paper/scoreboard/DisplaySlotTest.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..69c9678f8218c240be1044eeabe1c6bef7747b1e
|
||||
--- /dev/null
|
||||
+++ b/src/test/java/io/papermc/paper/scoreboard/DisplaySlotTest.java
|
||||
@@ -0,0 +1,24 @@
|
||||
+package io.papermc.paper.scoreboard;
|
||||
+
|
||||
+import org.bukkit.craftbukkit.scoreboard.CraftScoreboardTranslations;
|
||||
+import org.bukkit.scoreboard.DisplaySlot;
|
||||
+import org.junit.jupiter.api.Test;
|
||||
+
|
||||
+import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
+
|
||||
+public class DisplaySlotTest {
|
||||
+
|
||||
+ @Test
|
||||
+ public void testBukkitToMinecraftDisplaySlots() {
|
||||
+ for (DisplaySlot bukkitSlot : DisplaySlot.values()) {
|
||||
+ assertNotNull(CraftScoreboardTranslations.fromBukkitSlot(bukkitSlot));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void testMinecraftToBukkitDisplaySlots() {
|
||||
+ for (net.minecraft.world.scores.DisplaySlot nmsSlot : net.minecraft.world.scores.DisplaySlot.values()) {
|
||||
+ assertNotNull(CraftScoreboardTranslations.toBukkitSlot(nmsSlot));
|
||||
+ }
|
||||
+ }
|
||||
+}
|
|
@ -1,50 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sun, 16 May 2021 09:39:46 -0700
|
||||
Subject: [PATCH] Add back EntityPortalExitEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index 04f901236a5b9ca59ba45a5bac69ba89fc767679..11985b5c0e48178a7f995dfc35dd27a172261f1c 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -3291,6 +3291,28 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
|
||||
} else {
|
||||
// CraftBukkit start
|
||||
worldserver = shapedetectorshape.world;
|
||||
+ // Paper start - Call EntityPortalExitEvent
|
||||
+ Vec3 position = shapedetectorshape.pos;
|
||||
+ float yaw = shapedetectorshape.yRot;
|
||||
+ float pitch = this.getXRot(); // Keep entity pitch as per moveTo line below
|
||||
+ Vec3 velocity = shapedetectorshape.speed;
|
||||
+ CraftEntity bukkitEntity = this.getBukkitEntity();
|
||||
+ org.bukkit.event.entity.EntityPortalExitEvent event = new org.bukkit.event.entity.EntityPortalExitEvent(bukkitEntity,
|
||||
+ bukkitEntity.getLocation(), new Location(worldserver.getWorld(), position.x, position.y, position.z, yaw, pitch),
|
||||
+ bukkitEntity.getVelocity(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(shapedetectorshape.speed));
|
||||
+ event.callEvent();
|
||||
+ if (this.isRemoved()) {
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.isCancelled() && event.getTo() != null) {
|
||||
+ worldserver = ((CraftWorld) event.getTo().getWorld()).getHandle();
|
||||
+ position = CraftLocation.toVec3D(event.getTo());
|
||||
+ yaw = event.getTo().getYaw();
|
||||
+ pitch = event.getTo().getPitch();
|
||||
+ velocity = org.bukkit.craftbukkit.util.CraftVector.toNMS(event.getAfter());
|
||||
+ }
|
||||
+ // Paper end - Call EntityPortalExitEvent
|
||||
if (worldserver == this.level) {
|
||||
// SPIGOT-6782: Just move the entity if a plugin changed the world to the one the entity is already in
|
||||
this.moveTo(shapedetectorshape.pos.x, shapedetectorshape.pos.y, shapedetectorshape.pos.z, shapedetectorshape.yRot, shapedetectorshape.xRot);
|
||||
@@ -3310,8 +3332,8 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
|
||||
|
||||
if (entity != null) {
|
||||
entity.restoreFrom(this);
|
||||
- entity.moveTo(shapedetectorshape.pos.x, shapedetectorshape.pos.y, shapedetectorshape.pos.z, shapedetectorshape.yRot, entity.getXRot());
|
||||
- entity.setDeltaMovement(shapedetectorshape.speed);
|
||||
+ entity.moveTo(position.x, position.y, position.z, yaw, pitch); // Paper - EntityPortalExitEvent
|
||||
+ entity.setDeltaMovement(velocity); // Paper - EntityPortalExitEvent
|
||||
// CraftBukkit start - Don't spawn the new entity if the current entity isn't spawned
|
||||
if (this.inWorld) {
|
||||
worldserver.addDuringTeleport(entity);
|
|
@ -1,60 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jakub Zacek <dawon@dawon.eu>
|
||||
Date: Mon, 4 Oct 2021 10:16:44 +0200
|
||||
Subject: [PATCH] Add methods to find targets for lightning strikes
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.server.level.ServerLevel findLightningRod(Lnet/minecraft/core/BlockPos;)Ljava/util/Optional;
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 60590ee30d2ff3b94c796bae2d7e9d9bc145fc0d..14b3edc05a04f5049f994df5be68e4f01e8cf1ef 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -757,6 +757,11 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
}
|
||||
|
||||
protected BlockPos findLightningTargetAround(BlockPos pos) {
|
||||
+ // Paper start - Add methods to find targets for lightning strikes
|
||||
+ return this.findLightningTargetAround(pos, false);
|
||||
+ }
|
||||
+ public BlockPos findLightningTargetAround(BlockPos pos, boolean returnNullWhenNoTarget) {
|
||||
+ // Paper end - Add methods to find targets for lightning strikes
|
||||
BlockPos blockposition1 = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, pos);
|
||||
Optional<BlockPos> optional = this.findLightningRod(blockposition1);
|
||||
|
||||
@@ -771,6 +776,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
if (!list.isEmpty()) {
|
||||
return ((LivingEntity) list.get(this.random.nextInt(list.size()))).blockPosition();
|
||||
} else {
|
||||
+ if (returnNullWhenNoTarget) return null; // Paper - Add methods to find targets for lightning strikes
|
||||
if (blockposition1.getY() == this.getMinBuildHeight() - 1) {
|
||||
blockposition1 = blockposition1.above(2);
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
index 95a5f2ef87252ab3fb684d1e04e2a3d05a3aa4bb..6d74a3a43aee0f7ba4c109bd2443c5fcd950fa54 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
@@ -687,6 +687,23 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
return (LightningStrike) lightning.getBukkitEntity();
|
||||
}
|
||||
|
||||
+ // Paper start - Add methods to find targets for lightning strikes
|
||||
+ @Override
|
||||
+ public Location findLightningRod(Location location) {
|
||||
+ return this.world.findLightningRod(io.papermc.paper.util.MCUtil.toBlockPosition(location))
|
||||
+ .map(blockPos -> io.papermc.paper.util.MCUtil.toLocation(this.world, blockPos)
|
||||
+ // get the actual rod pos
|
||||
+ .subtract(0, 1, 0))
|
||||
+ .orElse(null);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Location findLightningTarget(Location location) {
|
||||
+ final BlockPos pos = this.world.findLightningTargetAround(io.papermc.paper.util.MCUtil.toBlockPosition(location), true);
|
||||
+ return pos == null ? null : io.papermc.paper.util.MCUtil.toLocation(this.world, pos);
|
||||
+ }
|
||||
+ // Paper end - Add methods to find targets for lightning strikes
|
||||
+
|
||||
@Override
|
||||
public boolean generateTree(Location loc, TreeType type) {
|
||||
return this.generateTree(loc, CraftWorld.rand, type);
|
|
@ -1,150 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Fri, 20 Aug 2021 13:03:21 -0700
|
||||
Subject: [PATCH] Get entity default attributes
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.entity.ai.attributes.AttributeSupplier getAttributeInstance(Lnet/minecraft/world/entity/ai/attributes/Attribute;)Lnet/minecraft/world/entity/ai/attributes/AttributeInstance;
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/attribute/UnmodifiableAttributeInstance.java b/src/main/java/io/papermc/paper/attribute/UnmodifiableAttributeInstance.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..12135ffeacd648f6bc4d7d327059ea1a7e8c79c4
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/attribute/UnmodifiableAttributeInstance.java
|
||||
@@ -0,0 +1,30 @@
|
||||
+package io.papermc.paper.attribute;
|
||||
+
|
||||
+import net.minecraft.world.entity.ai.attributes.AttributeInstance;
|
||||
+import org.bukkit.attribute.Attribute;
|
||||
+import org.bukkit.attribute.AttributeModifier;
|
||||
+import org.bukkit.craftbukkit.attribute.CraftAttributeInstance;
|
||||
+
|
||||
+import java.util.Collection;
|
||||
+
|
||||
+public class UnmodifiableAttributeInstance extends CraftAttributeInstance {
|
||||
+
|
||||
+ public UnmodifiableAttributeInstance(AttributeInstance handle, Attribute attribute) {
|
||||
+ super(handle, attribute);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setBaseValue(double d) {
|
||||
+ throw new UnsupportedOperationException("Cannot modify default attributes");
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void addModifier(AttributeModifier modifier) {
|
||||
+ throw new UnsupportedOperationException("Cannot modify default attributes");
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void removeModifier(AttributeModifier modifier) {
|
||||
+ throw new UnsupportedOperationException("Cannot modify default attributes");
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/attribute/UnmodifiableAttributeMap.java b/src/main/java/io/papermc/paper/attribute/UnmodifiableAttributeMap.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..68044b8439c302114240d0ae4da93ab3e0789cd2
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/attribute/UnmodifiableAttributeMap.java
|
||||
@@ -0,0 +1,32 @@
|
||||
+package io.papermc.paper.attribute;
|
||||
+
|
||||
+import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
|
||||
+import org.bukkit.attribute.Attributable;
|
||||
+import org.bukkit.attribute.Attribute;
|
||||
+import org.bukkit.attribute.AttributeInstance;
|
||||
+import org.bukkit.craftbukkit.attribute.CraftAttribute;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+public class UnmodifiableAttributeMap implements Attributable {
|
||||
+
|
||||
+ private final AttributeSupplier handle;
|
||||
+
|
||||
+ public UnmodifiableAttributeMap(@NotNull AttributeSupplier handle) {
|
||||
+ this.handle = handle;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @Nullable AttributeInstance getAttribute(@NotNull Attribute attribute) {
|
||||
+ net.minecraft.world.entity.ai.attributes.Attribute nmsAttribute = CraftAttribute.bukkitToMinecraft(attribute);
|
||||
+ if (!this.handle.hasAttribute(nmsAttribute)) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ return new UnmodifiableAttributeInstance(this.handle.getAttributeInstance(nmsAttribute), attribute);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void registerAttribute(@NotNull Attribute attribute) {
|
||||
+ throw new UnsupportedOperationException("Cannot register new attributes here");
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
index 31898e8425c524277bd07b139a898fe5f9fe344d..445e87a4cc7a1b6c38a4cbf2212ebddbc3496d12 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
@@ -581,6 +581,18 @@ public final class CraftMagicNumbers implements UnsafeValues {
|
||||
public int getProtocolVersion() {
|
||||
return net.minecraft.SharedConstants.getCurrentVersion().getProtocolVersion();
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean hasDefaultEntityAttributes(NamespacedKey bukkitEntityKey) {
|
||||
+ return net.minecraft.world.entity.ai.attributes.DefaultAttributes.hasSupplier(net.minecraft.core.registries.BuiltInRegistries.ENTITY_TYPE.get(CraftNamespacedKey.toMinecraft(bukkitEntityKey)));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public org.bukkit.attribute.Attributable getDefaultEntityAttributes(NamespacedKey bukkitEntityKey) {
|
||||
+ Preconditions.checkArgument(hasDefaultEntityAttributes(bukkitEntityKey), bukkitEntityKey + " doesn't have default attributes");
|
||||
+ var supplier = net.minecraft.world.entity.ai.attributes.DefaultAttributes.getSupplier((net.minecraft.world.entity.EntityType<? extends net.minecraft.world.entity.LivingEntity>) net.minecraft.core.registries.BuiltInRegistries.ENTITY_TYPE.get(CraftNamespacedKey.toMinecraft(bukkitEntityKey)));
|
||||
+ return new io.papermc.paper.attribute.UnmodifiableAttributeMap(supplier);
|
||||
+ }
|
||||
// Paper end
|
||||
|
||||
/**
|
||||
diff --git a/src/test/java/io/papermc/paper/attribute/EntityTypeAttributesTest.java b/src/test/java/io/papermc/paper/attribute/EntityTypeAttributesTest.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..e8cdfa385230d3de202122e4df5e07f61f80ce75
|
||||
--- /dev/null
|
||||
+++ b/src/test/java/io/papermc/paper/attribute/EntityTypeAttributesTest.java
|
||||
@@ -0,0 +1,39 @@
|
||||
+package io.papermc.paper.attribute;
|
||||
+
|
||||
+import org.bukkit.attribute.Attributable;
|
||||
+import org.bukkit.attribute.Attribute;
|
||||
+import org.bukkit.attribute.AttributeInstance;
|
||||
+import org.bukkit.attribute.AttributeModifier;
|
||||
+import org.bukkit.entity.EntityType;
|
||||
+import org.bukkit.support.AbstractTestingBase;
|
||||
+import org.junit.jupiter.api.Test;
|
||||
+
|
||||
+import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
+import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
+import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
+import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
+
|
||||
+public class EntityTypeAttributesTest extends AbstractTestingBase {
|
||||
+
|
||||
+ @Test
|
||||
+ public void testIllegalEntity() {
|
||||
+ assertFalse(EntityType.EGG.hasDefaultAttributes());
|
||||
+ assertThrows(IllegalArgumentException.class, () -> EntityType.EGG.getDefaultAttributes());
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void testLegalEntity() {
|
||||
+ assertTrue(EntityType.ZOMBIE.hasDefaultAttributes());
|
||||
+ EntityType.ZOMBIE.getDefaultAttributes();
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void testUnmodifiabilityOfAttributable() {
|
||||
+ Attributable attributable = EntityType.ZOMBIE.getDefaultAttributes();
|
||||
+ assertThrows(UnsupportedOperationException.class, () -> attributable.registerAttribute(Attribute.GENERIC_ATTACK_DAMAGE));
|
||||
+ AttributeInstance instance = attributable.getAttribute(Attribute.GENERIC_FOLLOW_RANGE);
|
||||
+ assertNotNull(instance);
|
||||
+ assertThrows(UnsupportedOperationException.class, () -> instance.addModifier(new AttributeModifier("test", 3, AttributeModifier.Operation.ADD_NUMBER)));
|
||||
+ assertThrows(UnsupportedOperationException.class, () -> instance.setBaseValue(3.2));
|
||||
+ }
|
||||
+}
|
|
@ -1,27 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||
Date: Thu, 14 Oct 2021 12:36:58 -0500
|
||||
Subject: [PATCH] Left handed API
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java
|
||||
index ae430c36ed433e337dd92f197f1717fbf00ac0e1..ad293ad9d5dcd7836a4fa29b4b687346e3ae516c 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java
|
||||
@@ -147,6 +147,16 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob {
|
||||
public int getMaxHeadPitch() {
|
||||
return getHandle().getMaxHeadXRot();
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isLeftHanded() {
|
||||
+ return getHandle().isLeftHanded();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setLeftHanded(boolean leftHanded) {
|
||||
+ getHandle().setLeftHanded(leftHanded);
|
||||
+ }
|
||||
// Paper end
|
||||
|
||||
// Paper start
|
|
@ -1,219 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: syldium <syldium@mailo.com>
|
||||
Date: Fri, 9 Jul 2021 18:50:40 +0200
|
||||
Subject: [PATCH] Add more advancement API
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.advancements.Advancement decorateName(Lnet/minecraft/advancements/DisplayInfo;)Lnet/minecraft/network/chat/Component;
|
||||
|
||||
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/advancement/PaperAdvancementDisplay.java b/src/main/java/io/papermc/paper/advancement/PaperAdvancementDisplay.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..adac21ce6db3ff7a56dbcd6bffc02143c2db4046
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/advancement/PaperAdvancementDisplay.java
|
||||
@@ -0,0 +1,69 @@
|
||||
+package io.papermc.paper.advancement;
|
||||
+
|
||||
+import io.papermc.paper.adventure.PaperAdventure;
|
||||
+import net.kyori.adventure.text.Component;
|
||||
+import net.minecraft.advancements.Advancement;
|
||||
+import net.minecraft.advancements.AdvancementType;
|
||||
+import net.minecraft.advancements.DisplayInfo;
|
||||
+import org.bukkit.NamespacedKey;
|
||||
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
+import org.bukkit.craftbukkit.util.CraftNamespacedKey;
|
||||
+import org.bukkit.inventory.ItemStack;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+public record PaperAdvancementDisplay(DisplayInfo handle) implements AdvancementDisplay {
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull Frame frame() {
|
||||
+ return asPaperFrame(this.handle.getType());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull Component title() {
|
||||
+ return PaperAdventure.asAdventure(this.handle.getTitle());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull Component description() {
|
||||
+ return PaperAdventure.asAdventure(this.handle.getDescription());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull ItemStack icon() {
|
||||
+ return CraftItemStack.asBukkitCopy(this.handle.getIcon());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean doesShowToast() {
|
||||
+ return this.handle.shouldShowToast();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean doesAnnounceToChat() {
|
||||
+ return this.handle.shouldAnnounceChat();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isHidden() {
|
||||
+ return this.handle.isHidden();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @Nullable NamespacedKey backgroundPath() {
|
||||
+ return this.handle.getBackground().map(CraftNamespacedKey::fromMinecraft).orElse(null);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull Component displayName() {
|
||||
+ return PaperAdventure.asAdventure(Advancement.decorateName(java.util.Objects.requireNonNull(this.handle, "cannot build display name for null handle, invalid state")));
|
||||
+ }
|
||||
+
|
||||
+ public static @NotNull Frame asPaperFrame(final @NotNull AdvancementType frameType) {
|
||||
+ return switch (frameType) {
|
||||
+ case TASK -> Frame.TASK;
|
||||
+ case CHALLENGE -> Frame.CHALLENGE;
|
||||
+ case GOAL -> Frame.GOAL;
|
||||
+ };
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/advancements/DisplayInfo.java b/src/main/java/net/minecraft/advancements/DisplayInfo.java
|
||||
index 3751b43469e92b8a3d70ec3d5413bc1571147e6e..8057d42f2484bca8e5555e3010c27b898c4245b5 100644
|
||||
--- a/src/main/java/net/minecraft/advancements/DisplayInfo.java
|
||||
+++ b/src/main/java/net/minecraft/advancements/DisplayInfo.java
|
||||
@@ -34,6 +34,7 @@ public class DisplayInfo {
|
||||
private final boolean hidden;
|
||||
private float x;
|
||||
private float y;
|
||||
+ public final io.papermc.paper.advancement.AdvancementDisplay paper = new io.papermc.paper.advancement.PaperAdvancementDisplay(this); // Paper - Add more advancement API
|
||||
|
||||
public DisplayInfo(
|
||||
ItemStack icon,
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancement.java b/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancement.java
|
||||
index 52baf818579a6841b77ff80e42f4f1b9f635ea08..8dfaca2efa0b0bdc97b75aaa83158a2e46361e4e 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancement.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancement.java
|
||||
@@ -29,12 +29,47 @@ public class CraftAdvancement implements org.bukkit.advancement.Advancement {
|
||||
return Collections.unmodifiableCollection(this.handle.value().criteria().keySet());
|
||||
}
|
||||
|
||||
+ // Paper start - Add more advancement API
|
||||
@Override
|
||||
- public AdvancementDisplay getDisplay() {
|
||||
- if (this.handle.value().display().isEmpty()) {
|
||||
- return null;
|
||||
+ public io.papermc.paper.advancement.AdvancementDisplay getDisplay() {
|
||||
+ return this.handle.value().display().map(d -> d.paper).orElse(null);
|
||||
+ }
|
||||
+
|
||||
+ @Deprecated
|
||||
+ @io.papermc.paper.annotation.DoNotUse
|
||||
+ public AdvancementDisplay getDisplay0() { // May be called by plugins via Commodore
|
||||
+ return this.handle.value().display().map(CraftAdvancementDisplay::new).orElse(null);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public net.kyori.adventure.text.Component displayName() {
|
||||
+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(net.minecraft.advancements.Advancement.name(this.handle));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public org.bukkit.advancement.Advancement getParent() {
|
||||
+ return this.handle.value().parent()
|
||||
+ .map(net.minecraft.server.MinecraftServer.getServer().getAdvancements()::get)
|
||||
+ .map(AdvancementHolder::toBukkit)
|
||||
+ .orElse(null);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Collection<org.bukkit.advancement.Advancement> getChildren() {
|
||||
+ final com.google.common.collect.ImmutableList.Builder<org.bukkit.advancement.Advancement> children = com.google.common.collect.ImmutableList.<org.bukkit.advancement.Advancement>builder();
|
||||
+ final net.minecraft.advancements.AdvancementNode advancementNode = net.minecraft.server.MinecraftServer.getServer().getAdvancements().tree().get(this.handle);
|
||||
+ if (advancementNode != null) {
|
||||
+ for (final net.minecraft.advancements.AdvancementNode child : advancementNode.children()) {
|
||||
+ children.add(child.holder().toBukkit());
|
||||
+ }
|
||||
}
|
||||
+ return children.build();
|
||||
+ }
|
||||
|
||||
- return new CraftAdvancementDisplay(this.handle.value().display().get());
|
||||
+ @Override
|
||||
+ public org.bukkit.advancement.Advancement getRoot() {
|
||||
+ final net.minecraft.advancements.AdvancementNode advancementNode = net.minecraft.server.MinecraftServer.getServer().getAdvancements().tree().get(this.handle);
|
||||
+ return java.util.Objects.requireNonNull(advancementNode, "could not find internal advancement node for advancement " + this.handle.id()).root().holder().toBukkit();
|
||||
}
|
||||
+ // Paper end - Add more advancement API
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancementDisplay.java b/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancementDisplay.java
|
||||
index 8ca86852319d7463f60832bc98b825b0b4325995..62ada73302c6b3ce3fb2dcc8c31a1d9c0ac4fd09 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancementDisplay.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancementDisplay.java
|
||||
@@ -6,6 +6,7 @@ import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
import org.bukkit.craftbukkit.util.CraftChatMessage;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
+@Deprecated // Paper
|
||||
public class CraftAdvancementDisplay implements org.bukkit.advancement.AdvancementDisplay {
|
||||
|
||||
private final DisplayInfo handle;
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java
|
||||
index a06352499b9f2c6fb84e585459077b4aa1886d6f..6d6a7abe1aa39a2e4ecf3ac5f55b1f227e1a9db9 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java
|
||||
@@ -56,6 +56,7 @@ public class Commodore {
|
||||
);
|
||||
|
||||
// Paper start - Plugin rewrites
|
||||
+ private static final String CB_PACKAGE = org.bukkit.Bukkit.getServer().getClass().getPackageName().replace('.', '/');
|
||||
private static final Map<String, String> SEARCH_AND_REMOVE = initReplacementsMap();
|
||||
private static Map<String, String> initReplacementsMap() {
|
||||
Map<String, String> getAndRemove = new HashMap<>();
|
||||
@@ -388,6 +389,11 @@ public class Commodore {
|
||||
super.visitMethodInsn(opcode, owner, name, "()Lcom/destroystokyo/paper/profile/PlayerProfile;", itf);
|
||||
return;
|
||||
}
|
||||
+ if (owner.equals("org/bukkit/advancement/Advancement") && name.equals("getDisplay") && desc.endsWith(")Lorg/bukkit/advancement/AdvancementDisplay;")) {
|
||||
+ super.visitTypeInsn(Opcodes.CHECKCAST, CB_PACKAGE + "/advancement/CraftAdvancement");
|
||||
+ super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, CB_PACKAGE + "/advancement/CraftAdvancement", "getDisplay0", desc, false);
|
||||
+ return;
|
||||
+ }
|
||||
// Paper end
|
||||
|
||||
if (modern) {
|
||||
diff --git a/src/test/java/io/papermc/paper/advancement/AdvancementFrameTest.java b/src/test/java/io/papermc/paper/advancement/AdvancementFrameTest.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..47535c27d7cffc4b5ee6cc9e145b1087477eef79
|
||||
--- /dev/null
|
||||
+++ b/src/test/java/io/papermc/paper/advancement/AdvancementFrameTest.java
|
||||
@@ -0,0 +1,24 @@
|
||||
+package io.papermc.paper.advancement;
|
||||
+
|
||||
+import io.papermc.paper.adventure.PaperAdventure;
|
||||
+import net.kyori.adventure.text.format.TextColor;
|
||||
+import net.minecraft.advancements.AdvancementType;
|
||||
+import net.minecraft.network.chat.contents.TranslatableContents;
|
||||
+import org.junit.jupiter.api.Test;
|
||||
+
|
||||
+import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
+
|
||||
+public class AdvancementFrameTest {
|
||||
+
|
||||
+ @Test
|
||||
+ public void test() {
|
||||
+ for (final AdvancementType advancementType : AdvancementType.values()) {
|
||||
+ final TextColor expectedColor = PaperAdventure.asAdventure(advancementType.getChatColor());
|
||||
+ final String expectedTranslationKey = ((TranslatableContents) advancementType.getDisplayName().getContents()).getKey();
|
||||
+ final var frame = PaperAdvancementDisplay.asPaperFrame(advancementType);
|
||||
+ assertEquals(expectedTranslationKey, frame.translationKey(), "The translation keys should be the same");
|
||||
+ assertEquals(expectedColor, frame.color(), "The frame colors should be the same");
|
||||
+ assertEquals(advancementType.getSerializedName(), AdvancementDisplay.Frame.NAMES.key(frame));
|
||||
+ }
|
||||
+ }
|
||||
+}
|
|
@ -1,50 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||
Date: Thu, 14 Oct 2021 12:09:39 -0500
|
||||
Subject: [PATCH] Add ItemFactory#getSpawnEgg API
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
|
||||
index 12f90520e4d6d5fcea0c2f8e19dad9102970cd99..ef0c6e04a89704688f7b5461b27c0036abbf647d 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
|
||||
@@ -564,4 +564,19 @@ public final class CraftItemFactory implements ItemFactory {
|
||||
new net.md_5.bungee.api.chat.TextComponent(customName));
|
||||
}
|
||||
// Paper end - bungee hover events
|
||||
+
|
||||
+ // Paper start - old getSpawnEgg API
|
||||
+ // @Override // used to override, upstream added conflicting method, is called via Commodore now
|
||||
+ @Deprecated
|
||||
+ public ItemStack getSpawnEgg0(org.bukkit.entity.EntityType type) {
|
||||
+ if (type == null) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ String typeId = type.getKey().toString();
|
||||
+ net.minecraft.resources.ResourceLocation typeKey = new net.minecraft.resources.ResourceLocation(typeId);
|
||||
+ net.minecraft.world.entity.EntityType<?> nmsType = net.minecraft.core.registries.BuiltInRegistries.ENTITY_TYPE.get(typeKey);
|
||||
+ net.minecraft.world.item.SpawnEggItem eggItem = net.minecraft.world.item.SpawnEggItem.byId(nmsType);
|
||||
+ return eggItem == null ? null : new net.minecraft.world.item.ItemStack(eggItem).asBukkitMirror();
|
||||
+ }
|
||||
+ // Paper end - old getSpawnEgg API
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java
|
||||
index 6d6a7abe1aa39a2e4ecf3ac5f55b1f227e1a9db9..010014c06fcea7d603160928f124f54d6e5e63d8 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java
|
||||
@@ -396,6 +396,15 @@ public class Commodore {
|
||||
}
|
||||
// Paper end
|
||||
|
||||
+ // Paper start - ItemFactory#getSpawnEgg (paper had original method that returned ItemStack, upstream added identical but returned Material)
|
||||
+ if (owner.equals("org/bukkit/inventory/ItemFactory") && name.equals("getSpawnEgg") && desc.equals("(Lorg/bukkit/entity/EntityType;)Lorg/bukkit/inventory/ItemStack;")) {
|
||||
+ super.visitInsn(Opcodes.SWAP); // has 1 param, this moves the owner instance to the top for the checkcast
|
||||
+ super.visitTypeInsn(Opcodes.CHECKCAST, CB_PACKAGE + "/inventory/CraftItemFactory");
|
||||
+ super.visitInsn(Opcodes.SWAP); // moves param back to the the top of stack
|
||||
+ super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, CB_PACKAGE + "/inventory/CraftItemFactory", "getSpawnEgg0", desc, false);
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end - ItemFactory#getSpawnEgg
|
||||
if (modern) {
|
||||
if (owner.equals("org/bukkit/Material") || (instantiatedMethodType != null && instantiatedMethodType.getDescriptor().startsWith("(Lorg/bukkit/Material;)"))) {
|
||||
switch (name) {
|
|
@ -1,111 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: dodison <kacpik@mapik.eu>
|
||||
Date: Mon, 26 Jul 2021 17:32:36 +0200
|
||||
Subject: [PATCH] Add critical damage API
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSource.java b/src/main/java/net/minecraft/world/damagesource/DamageSource.java
|
||||
index e055106c50944c9a23bc59fe23f58a62c5deb7e4..8187feffe52efa5c887f1910e581a37c6e439401 100644
|
||||
--- a/src/main/java/net/minecraft/world/damagesource/DamageSource.java
|
||||
+++ b/src/main/java/net/minecraft/world/damagesource/DamageSource.java
|
||||
@@ -234,4 +234,18 @@ public class DamageSource {
|
||||
public Holder<DamageType> typeHolder() {
|
||||
return this.type;
|
||||
}
|
||||
+
|
||||
+ // Paper start - add critical damage API
|
||||
+ private boolean critical;
|
||||
+ public boolean isCritical() {
|
||||
+ return this.critical;
|
||||
+ }
|
||||
+ public DamageSource critical() {
|
||||
+ return this.critical(true);
|
||||
+ }
|
||||
+ public DamageSource critical(boolean critical) {
|
||||
+ this.critical = critical;
|
||||
+ return this;
|
||||
+ }
|
||||
+ // Paper end - add critical damage API
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
index 4d967016ac34d21161f10217db494f5bb537bd07..cb91111c1ae1cfbf256ba09f76ce0b0c8fc91f32 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
@@ -1257,7 +1257,7 @@ public abstract class Player extends LivingEntity {
|
||||
flag1 = true;
|
||||
}
|
||||
|
||||
- boolean flag2 = flag && this.fallDistance > 0.0F && !this.onGround() && !this.onClimbable() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && target instanceof LivingEntity;
|
||||
+ boolean flag2 = flag && this.fallDistance > 0.0F && !this.onGround() && !this.onClimbable() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && target instanceof LivingEntity; // Paper - Add critical damage API; diff on change
|
||||
|
||||
flag2 = flag2 && !this.level().paperConfig().entities.behavior.disablePlayerCrits; // Paper - Toggleable player crits
|
||||
flag2 = flag2 && !this.isSprinting();
|
||||
@@ -1297,7 +1297,7 @@ public abstract class Player extends LivingEntity {
|
||||
}
|
||||
|
||||
Vec3 vec3d = target.getDeltaMovement();
|
||||
- boolean flag5 = target.hurt(this.damageSources().playerAttack(this), f);
|
||||
+ boolean flag5 = target.hurt(this.damageSources().playerAttack(this).critical(flag2), f); // Paper - add critical damage API
|
||||
|
||||
if (flag5) {
|
||||
if (i > 0) {
|
||||
@@ -1325,7 +1325,7 @@ public abstract class Player extends LivingEntity {
|
||||
|
||||
if (entityliving != this && entityliving != target && !this.isAlliedTo((Entity) entityliving) && (!(entityliving instanceof ArmorStand) || !((ArmorStand) entityliving).isMarker()) && this.distanceToSqr((Entity) entityliving) < 9.0D) {
|
||||
// CraftBukkit start - Only apply knockback if the damage hits
|
||||
- if (entityliving.hurt(this.damageSources().playerAttack(this).sweep(), f4)) {
|
||||
+ if (entityliving.hurt(this.damageSources().playerAttack(this).sweep().critical(flag2), f4)) { // Paper - add critical damage API
|
||||
entityliving.knockback(0.4000000059604645D, (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F)), this, EntityKnockbackEvent.KnockbackCause.SWEEP_ATTACK); // CraftBukkit
|
||||
}
|
||||
// CraftBukkit end
|
||||
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 913f0eb1d9081cd224b54df401ff4a0af2989f1f..b3972c0aececb1d7170a47bbe8f1d6ce02d11331 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
|
||||
@@ -380,6 +380,7 @@ public abstract class AbstractArrow extends Projectile {
|
||||
}
|
||||
}
|
||||
|
||||
+ if (this.isCritArrow()) damagesource = damagesource.critical(); // Paper - add critical damage API
|
||||
boolean flag = entity.getType() == EntityType.ENDERMAN;
|
||||
int k = entity.getRemainingFireTicks();
|
||||
boolean flag1 = entity.getType().is(EntityTypeTags.DEFLECTS_ARROWS);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
index 74df21363c96dbf82337550ae2d8525e82eaface..7d72ccdd82daa6afe85859f5bc6ec7b187622384 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
@@ -1063,7 +1063,7 @@ public class CraftEventFactory {
|
||||
return CraftEventFactory.callEntityDamageEvent(source.getDirectBlock(), entity, DamageCause.BLOCK_EXPLOSION, bukkitDamageSource, modifiers, modifierFunctions, cancelled);
|
||||
}
|
||||
DamageCause damageCause = (damager.getBukkitEntity() instanceof org.bukkit.entity.TNTPrimed) ? DamageCause.BLOCK_EXPLOSION : DamageCause.ENTITY_EXPLOSION;
|
||||
- return CraftEventFactory.callEntityDamageEvent(damager, entity, damageCause, bukkitDamageSource, modifiers, modifierFunctions, cancelled);
|
||||
+ return CraftEventFactory.callEntityDamageEvent(damager, entity, damageCause, bukkitDamageSource, modifiers, modifierFunctions, cancelled, source.isCritical()); // Paper - add critical damage API
|
||||
} else if (damager != null || source.getDirectEntity() != null) {
|
||||
DamageCause cause = (source.isSweep()) ? DamageCause.ENTITY_SWEEP_ATTACK : DamageCause.ENTITY_ATTACK;
|
||||
|
||||
@@ -1093,7 +1093,7 @@ public class CraftEventFactory {
|
||||
cause = DamageCause.MAGIC;
|
||||
}
|
||||
|
||||
- return CraftEventFactory.callEntityDamageEvent(damager, entity, cause, bukkitDamageSource, modifiers, modifierFunctions, cancelled);
|
||||
+ return CraftEventFactory.callEntityDamageEvent(damager, entity, cause, bukkitDamageSource, modifiers, modifierFunctions, cancelled, source.isCritical()); // Paper - add critical damage API
|
||||
} else if (source.is(DamageTypes.FELL_OUT_OF_WORLD)) {
|
||||
return CraftEventFactory.callEntityDamageEvent(source.getDirectBlock(), entity, DamageCause.VOID, bukkitDamageSource, modifiers, modifierFunctions, cancelled);
|
||||
} else if (source.is(DamageTypes.LAVA)) {
|
||||
@@ -1151,13 +1151,13 @@ public class CraftEventFactory {
|
||||
cause = DamageCause.CUSTOM;
|
||||
}
|
||||
|
||||
- return CraftEventFactory.callEntityDamageEvent((Entity) null, entity, cause, bukkitDamageSource, modifiers, modifierFunctions, cancelled);
|
||||
+ return CraftEventFactory.callEntityDamageEvent((Entity) null, entity, cause, bukkitDamageSource, modifiers, modifierFunctions, cancelled, source.isCritical()); // Paper - add critical damage API
|
||||
}
|
||||
|
||||
- private static EntityDamageEvent callEntityDamageEvent(Entity damager, Entity damagee, DamageCause cause, org.bukkit.damage.DamageSource bukkitDamageSource, Map<DamageModifier, Double> modifiers, Map<DamageModifier, Function<? super Double, Double>> modifierFunctions, boolean cancelled) {
|
||||
+ private static EntityDamageEvent callEntityDamageEvent(Entity damager, Entity damagee, DamageCause cause, org.bukkit.damage.DamageSource bukkitDamageSource, Map<DamageModifier, Double> modifiers, Map<DamageModifier, Function<? super Double, Double>> modifierFunctions, boolean cancelled, boolean critical) { // Paper - add critical damage API
|
||||
EntityDamageEvent event;
|
||||
if (damager != null) {
|
||||
- event = new EntityDamageByEntityEvent(damager.getBukkitEntity(), damagee.getBukkitEntity(), cause, bukkitDamageSource, modifiers, modifierFunctions);
|
||||
+ event = new EntityDamageByEntityEvent(damager.getBukkitEntity(), damagee.getBukkitEntity(), cause, bukkitDamageSource, modifiers, modifierFunctions, critical);
|
||||
} else {
|
||||
event = new EntityDamageEvent(damagee.getBukkitEntity(), cause, bukkitDamageSource, modifiers, modifierFunctions);
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sun, 24 Oct 2021 20:29:45 -0700
|
||||
Subject: [PATCH] Fix issues with mob conversion
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/Skeleton.java b/src/main/java/net/minecraft/world/entity/monster/Skeleton.java
|
||||
index e88af2dcc0f7fc5190654e2640f67d706e6c8c81..92974452d8f63fde8524cfac305ee2ef5212f840 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Skeleton.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Skeleton.java
|
||||
@@ -90,10 +90,15 @@ public class Skeleton extends AbstractSkeleton {
|
||||
}
|
||||
|
||||
protected void doFreezeConversion() {
|
||||
- this.convertTo(EntityType.STRAY, true, org.bukkit.event.entity.EntityTransformEvent.TransformReason.FROZEN, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.FROZEN); // CraftBukkit - add spawn and transform reasons
|
||||
+ Stray stray = this.convertTo(EntityType.STRAY, true, org.bukkit.event.entity.EntityTransformEvent.TransformReason.FROZEN, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.FROZEN); // CraftBukkit - add spawn and transform reasons // Paper - Fix issues with mob conversion
|
||||
if (!this.isSilent()) {
|
||||
this.level().levelEvent((Player) null, 1048, this.blockPosition(), 0);
|
||||
}
|
||||
+ // Paper start - Fix issues with mob conversion; reset conversion time to prevent event spam
|
||||
+ if (stray == null) {
|
||||
+ this.conversionTime = 300;
|
||||
+ }
|
||||
+ // Paper end - Fix issues with mob conversion
|
||||
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java b/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java
|
||||
index 2025599c337759d8856e15b606cde604d6c64a88..050ffa4a23feba29fdf4c6a175cdff4e5009027d 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java
|
||||
@@ -271,6 +271,11 @@ public class Hoglin extends Animal implements Enemy, HoglinBase {
|
||||
if (zoglin != null) {
|
||||
zoglin.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200, 0));
|
||||
}
|
||||
+ // Paper start - Fix issues with mob conversion; reset to prevent event spam
|
||||
+ else {
|
||||
+ this.timeInOverworld = 0;
|
||||
+ }
|
||||
+ // Paper end - Fix issues with mob conversion
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java b/src/main/java/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java
|
||||
index 22c8d6233be5e4f7fb4f03176e83dbee02256b1f..c575a86ca5c1bbdd6d2faf6e4a609af8ba03cab6 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java
|
||||
@@ -120,6 +120,11 @@ public abstract class AbstractPiglin extends Monster {
|
||||
if (entitypigzombie != null) {
|
||||
entitypigzombie.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200, 0));
|
||||
}
|
||||
+ // Paper start - Fix issues with mob conversion; reset to prevent event spam
|
||||
+ else {
|
||||
+ this.timeInOverworld = 0;
|
||||
+ }
|
||||
+ // Paper end - Fix issues with mob conversion
|
||||
|
||||
}
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Thu, 4 Nov 2021 11:50:40 -0700
|
||||
Subject: [PATCH] Add isCollidable methods to various places
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.level.block.state.BlockBehaviour hasCollision
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
|
||||
index ce297420f695404356655b1df2847a32fb98ec59..068b3735b6c50a7a2053c7dc39856f728fb7218a 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
|
||||
@@ -457,6 +457,11 @@ public class CraftBlock implements Block {
|
||||
public boolean isSolid() {
|
||||
return this.getNMS().blocksMotion();
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isCollidable() {
|
||||
+ return getNMS().getBlock().hasCollision;
|
||||
+ }
|
||||
// Paper end
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java
|
||||
index 928a301627134b49915b0ceaeabb7dc350605dc2..08716e757b2e100f7bc47a046f02db664d882aba 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java
|
||||
@@ -331,4 +331,11 @@ public class CraftBlockState implements BlockState {
|
||||
public CraftBlockState copy() {
|
||||
return new CraftBlockState(this);
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public boolean isCollidable() {
|
||||
+ return this.data.getBlock().hasCollision;
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
index 445e87a4cc7a1b6c38a4cbf2212ebddbc3496d12..2734f4187a4b92ef461e1f2fdae9139c6f54d8fc 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
@@ -593,6 +593,12 @@ public final class CraftMagicNumbers implements UnsafeValues {
|
||||
var supplier = net.minecraft.world.entity.ai.attributes.DefaultAttributes.getSupplier((net.minecraft.world.entity.EntityType<? extends net.minecraft.world.entity.LivingEntity>) net.minecraft.core.registries.BuiltInRegistries.ENTITY_TYPE.get(CraftNamespacedKey.toMinecraft(bukkitEntityKey)));
|
||||
return new io.papermc.paper.attribute.UnmodifiableAttributeMap(supplier);
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isCollidable(Material material) {
|
||||
+ Preconditions.checkArgument(material.isBlock(), material + " is not a block");
|
||||
+ return getBlock(material).hasCollision;
|
||||
+ }
|
||||
// Paper end
|
||||
|
||||
/**
|
|
@ -1,42 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Seggan <segganew@gmail.com>
|
||||
Date: Thu, 5 Aug 2021 13:10:27 -0400
|
||||
Subject: [PATCH] Goat ram API
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java b/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java
|
||||
index 52f3f679568955b632a60d44de687c6db0e2b38a..ee1b2c1fec4b76a821e1d52fbb07e1f302b2efa1 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java
|
||||
@@ -392,4 +392,15 @@ public class Goat extends Animal {
|
||||
protected Vector3f getPassengerAttachmentPoint(Entity passenger, EntityDimensions dimensions, float scaleFactor) {
|
||||
return new Vector3f(0.0F, dimensions.height - 0.1875F * scaleFactor, 0.0F);
|
||||
}
|
||||
+
|
||||
+ // Paper start - Goat ram API
|
||||
+ public void ram(net.minecraft.world.entity.LivingEntity entity) {
|
||||
+ Brain<Goat> brain = this.getBrain();
|
||||
+ brain.setMemory(MemoryModuleType.RAM_TARGET, entity.position());
|
||||
+ brain.eraseMemory(MemoryModuleType.RAM_COOLDOWN_TICKS);
|
||||
+ brain.eraseMemory(MemoryModuleType.BREED_TARGET);
|
||||
+ brain.eraseMemory(MemoryModuleType.TEMPTING_PLAYER);
|
||||
+ brain.setActiveActivityIfPossible(net.minecraft.world.entity.schedule.Activity.RAM);
|
||||
+ }
|
||||
+ // Paper end - Goat ram API
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftGoat.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftGoat.java
|
||||
index 65fcb36e849da6949c123a6f3672b485036f368e..2c21de478bff9cdf13ba46cd041831d54c11e924 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftGoat.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftGoat.java
|
||||
@@ -48,4 +48,11 @@ public class CraftGoat extends CraftAnimals implements Goat {
|
||||
public void setScreaming(boolean screaming) {
|
||||
this.getHandle().setScreamingGoat(screaming);
|
||||
}
|
||||
+
|
||||
+ // Paper start - Goat ram API
|
||||
+ @Override
|
||||
+ public void ram(@org.jetbrains.annotations.NotNull org.bukkit.entity.LivingEntity entity) {
|
||||
+ this.getHandle().ram(((CraftLivingEntity) entity).getHandle());
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: booky10 <boooky10@gmail.com>
|
||||
Date: Fri, 5 Nov 2021 21:01:36 +0100
|
||||
Subject: [PATCH] Add API for resetting a single score
|
||||
|
||||
It was only possible to reset all scores for a specific entry, instead of resetting only specific scores.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScore.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScore.java
|
||||
index 29e24461e29e4cf3d31497198debcde18761ad73..ceb1a39c02c3cfa7632a0fdca414c7046888fcb1 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScore.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScore.java
|
||||
@@ -66,4 +66,12 @@ final class CraftScore implements Score {
|
||||
public CraftScoreboard getScoreboard() {
|
||||
return this.objective.getScoreboard();
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public void resetScore() {
|
||||
+ Scoreboard board = this.objective.checkState().board;
|
||||
+ board.resetSinglePlayerScore(entry, this.objective.getHandle());
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Mariell Hoversholm <proximyst@proximyst.com>
|
||||
Date: Sun, 24 Oct 2021 16:20:31 -0400
|
||||
Subject: [PATCH] Add Raw Byte Entity Serialization
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.entity.Entity setLevel(Lnet/minecraft/world/level/Level;)V
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index 11985b5c0e48178a7f995dfc35dd27a172261f1c..b9f61d08adf83bbaed522c2258db116492cb24c5 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -2078,6 +2078,15 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start - Entity serialization api
|
||||
+ public boolean serializeEntity(CompoundTag compound) {
|
||||
+ List<Entity> pass = new java.util.ArrayList<>(this.getPassengers());
|
||||
+ this.passengers = ImmutableList.of();
|
||||
+ boolean result = save(compound);
|
||||
+ this.passengers = ImmutableList.copyOf(pass);
|
||||
+ return result;
|
||||
+ }
|
||||
+ // Paper end - Entity serialization api
|
||||
public boolean save(CompoundTag nbt) {
|
||||
return this.isPassenger() ? false : this.saveAsPassenger(nbt);
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
index 65ce8ab201e7e36f6d2637e906af325e11e425dd..c819fa8e5b69c23558a89b68f9a5a31e1b233ca3 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
@@ -1058,6 +1058,18 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
||||
}
|
||||
// Paper end - tracked players API
|
||||
|
||||
+ // Paper start - raw entity serialization API
|
||||
+ @Override
|
||||
+ public boolean spawnAt(Location location, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) {
|
||||
+ Preconditions.checkNotNull(location, "location cannot be null");
|
||||
+ Preconditions.checkNotNull(reason, "reason cannot be null");
|
||||
+ this.entity.setLevel(((CraftWorld) location.getWorld()).getHandle());
|
||||
+ this.entity.setPos(location.getX(), location.getY(), location.getZ());
|
||||
+ this.entity.setRot(location.getYaw(), location.getPitch());
|
||||
+ return !this.entity.valid && this.entity.level().addFreshEntity(this.entity, reason);
|
||||
+ }
|
||||
+ // Paper end - raw entity serialization API
|
||||
+
|
||||
// Paper start - missing entity api
|
||||
@Override
|
||||
public boolean isInvisible() { // Paper - moved up from LivingEntity
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
index 2734f4187a4b92ef461e1f2fdae9139c6f54d8fc..be82e1d52d7026facb20bf07f4b3a394e77ab708 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
@@ -504,6 +504,32 @@ public final class CraftMagicNumbers implements UnsafeValues {
|
||||
return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.of(compound));
|
||||
}
|
||||
|
||||
+ @Override
|
||||
+ public byte[] serializeEntity(org.bukkit.entity.Entity entity) {
|
||||
+ Preconditions.checkNotNull(entity, "null cannot be serialized");
|
||||
+ Preconditions.checkArgument(entity instanceof org.bukkit.craftbukkit.entity.CraftEntity, "only CraftEntities can be serialized");
|
||||
+
|
||||
+ CompoundTag compound = new CompoundTag();
|
||||
+ ((org.bukkit.craftbukkit.entity.CraftEntity) entity).getHandle().serializeEntity(compound);
|
||||
+ return serializeNbtToBytes(compound);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public org.bukkit.entity.Entity deserializeEntity(byte[] data, org.bukkit.World world, boolean preserveUUID) {
|
||||
+ Preconditions.checkNotNull(data, "null cannot be deserialized");
|
||||
+ Preconditions.checkArgument(data.length > 0, "cannot deserialize nothing");
|
||||
+
|
||||
+ CompoundTag compound = deserializeNbtFromBytes(data);
|
||||
+ int dataVersion = compound.getInt("DataVersion");
|
||||
+ compound = (CompoundTag) MinecraftServer.getServer().fixerUpper.update(References.ENTITY, new Dynamic<>(NbtOps.INSTANCE, compound), dataVersion, this.getDataVersion()).getValue();
|
||||
+ if (!preserveUUID) {
|
||||
+ // Generate a new UUID so we don't have to worry about deserializing the same entity twice
|
||||
+ compound.remove("UUID");
|
||||
+ }
|
||||
+ return net.minecraft.world.entity.EntityType.create(compound, ((org.bukkit.craftbukkit.CraftWorld) world).getHandle())
|
||||
+ .orElseThrow(() -> new IllegalArgumentException("An ID was not found for the data. Did you downgrade?")).getBukkitEntity();
|
||||
+ }
|
||||
+
|
||||
private byte[] serializeNbtToBytes(CompoundTag compound) {
|
||||
compound.putInt("DataVersion", getDataVersion());
|
||||
java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream();
|
|
@ -1,81 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
|
||||
Date: Wed, 25 Aug 2021 13:19:53 -0700
|
||||
Subject: [PATCH] Vanilla command permission fixes
|
||||
|
||||
Fixes permission checks for vanilla commands which don't have a
|
||||
requirement, as well as for namespaced vanilla commands.
|
||||
|
||||
== AT ==
|
||||
public-f com.mojang.brigadier.tree.CommandNode requirement
|
||||
|
||||
diff --git a/src/main/java/com/mojang/brigadier/builder/ArgumentBuilder.java b/src/main/java/com/mojang/brigadier/builder/ArgumentBuilder.java
|
||||
index 899008b2980d13f1be6280cd8cb959c53a29bebf..d5f7da3502575f6847f3c22ab0e942848a7c6031 100644
|
||||
--- a/src/main/java/com/mojang/brigadier/builder/ArgumentBuilder.java
|
||||
+++ b/src/main/java/com/mojang/brigadier/builder/ArgumentBuilder.java
|
||||
@@ -14,9 +14,17 @@ import java.util.Collections;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public abstract class ArgumentBuilder<S, T extends ArgumentBuilder<S, T>> {
|
||||
+ // Paper start - Vanilla command permission fixes
|
||||
+ private static final Predicate<Object> DEFAULT_REQUIREMENT = s -> true;
|
||||
+
|
||||
+ @SuppressWarnings("unchecked")
|
||||
+ public static <S> Predicate<S> defaultRequirement() {
|
||||
+ return (Predicate<S>) DEFAULT_REQUIREMENT;
|
||||
+ }
|
||||
+ // Paper end - Vanilla command permission fixes
|
||||
private final RootCommandNode<S> arguments = new RootCommandNode<>();
|
||||
private Command<S> command;
|
||||
- private Predicate<S> requirement = s -> true;
|
||||
+ private Predicate<S> requirement = defaultRequirement(); // Paper - Vanilla command permission fixes
|
||||
private CommandNode<S> target;
|
||||
private RedirectModifier<S> modifier = null;
|
||||
private boolean forks;
|
||||
diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java
|
||||
index c11977dceeba4120cdb63972c4ec486640d8114e..8be58d29f2a4753a241e68bd305b3e30186ca0e9 100644
|
||||
--- a/src/main/java/net/minecraft/commands/Commands.java
|
||||
+++ b/src/main/java/net/minecraft/commands/Commands.java
|
||||
@@ -257,6 +257,13 @@ public class Commands {
|
||||
}
|
||||
this.vanillaCommandNodes.addAll(this.dispatcher.getRoot().getChildren()); // Paper - Add UnknownCommandEvent
|
||||
|
||||
+ // Paper start - Vanilla command permission fixes
|
||||
+ for (final CommandNode<CommandSourceStack> node : this.dispatcher.getRoot().getChildren()) {
|
||||
+ if (node.getRequirement() == com.mojang.brigadier.builder.ArgumentBuilder.<CommandSourceStack>defaultRequirement()) {
|
||||
+ node.requirement = stack -> stack.source == CommandSource.NULL || stack.getBukkitSender().hasPermission(org.bukkit.craftbukkit.command.VanillaCommandWrapper.getPermission(node));
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Vanilla command permission fixes
|
||||
// CraftBukkit start
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java b/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java
|
||||
index 5e6645e16b185aaa6f719055ddbf670b8741fead..bda9a0b99184adce28bb7851612ed7f4e324826d 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java
|
||||
@@ -86,7 +86,23 @@ public final class VanillaCommandWrapper extends BukkitCommand {
|
||||
}
|
||||
|
||||
public static String getPermission(CommandNode<CommandSourceStack> vanillaCommand) {
|
||||
- return "minecraft.command." + ((vanillaCommand.getRedirect() == null) ? vanillaCommand.getName() : vanillaCommand.getRedirect().getName());
|
||||
+ // Paper start - Vanilla command permission fixes
|
||||
+ final String commandName;
|
||||
+ if (vanillaCommand.getRedirect() == null) {
|
||||
+ commandName = vanillaCommand.getName();
|
||||
+ } else {
|
||||
+ commandName = vanillaCommand.getRedirect().getName();
|
||||
+ }
|
||||
+ return "minecraft.command." + stripDefaultNamespace(commandName);
|
||||
+ }
|
||||
+
|
||||
+ private static String stripDefaultNamespace(final String maybeNamespaced) {
|
||||
+ final String prefix = "minecraft:";
|
||||
+ if (maybeNamespaced.startsWith(prefix)) {
|
||||
+ return maybeNamespaced.substring(prefix.length());
|
||||
+ }
|
||||
+ return maybeNamespaced;
|
||||
+ // Paper end - Vanilla command permission fixes
|
||||
}
|
||||
|
||||
private String toDispatcher(String[] args, String name) {
|
|
@ -1,68 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Thu, 11 Mar 2021 03:03:32 -0800
|
||||
Subject: [PATCH] Do not run close logic for inventories on chunk unload
|
||||
|
||||
Still call the event and change the active container though. We
|
||||
want to avoid close logic because it's possible to load the
|
||||
chunk through it. This should also be OK from a leak prevention/
|
||||
state desync POV because the TE is getting unloaded anyways.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 14b3edc05a04f5049f994df5be68e4f01e8cf1ef..10eb5c342930d2efd7d919f286fe8fa64cebaea4 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -1270,9 +1270,13 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
// Spigot Start
|
||||
for (net.minecraft.world.level.block.entity.BlockEntity tileentity : chunk.getBlockEntities().values()) {
|
||||
if (tileentity instanceof net.minecraft.world.Container) {
|
||||
+ // Paper start - this area looks like it can load chunks, change the behavior
|
||||
+ // chests for example can apply physics to the world
|
||||
+ // so instead we just change the active container and call the event
|
||||
for (org.bukkit.entity.HumanEntity h : Lists.newArrayList(((net.minecraft.world.Container) tileentity).getViewers())) {
|
||||
- h.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper - Inventory close reason
|
||||
+ ((org.bukkit.craftbukkit.entity.CraftHumanEntity) h).getHandle().closeUnloadedInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper - Inventory close reason
|
||||
}
|
||||
+ // Paper end - this area looks like it can load chunks, change the behavior
|
||||
}
|
||||
}
|
||||
// Spigot End
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 3f4950e0c0525346a89c7402ea85edebc6b36698..5f43cd7f6cc1e14771c3df6ec1f074e670ec6206 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -1581,6 +1581,18 @@ public class ServerPlayer extends Player {
|
||||
this.connection.send(new ClientboundContainerClosePacket(this.containerMenu.containerId));
|
||||
this.doCloseContainer();
|
||||
}
|
||||
+ // Paper start - special close for unloaded inventory
|
||||
+ @Override
|
||||
+ public void closeUnloadedInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) {
|
||||
+ // copied from above
|
||||
+ CraftEventFactory.handleInventoryCloseEvent(this, reason); // CraftBukkit
|
||||
+ // Paper end
|
||||
+ // copied from below
|
||||
+ this.connection.send(new ClientboundContainerClosePacket(this.containerMenu.containerId));
|
||||
+ this.containerMenu = this.inventoryMenu;
|
||||
+ // do not run close logic
|
||||
+ }
|
||||
+ // Paper end - special close for unloaded inventory
|
||||
|
||||
@Override
|
||||
public void doCloseContainer() {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
index cb91111c1ae1cfbf256ba09f76ce0b0c8fc91f32..e06cb31f9e3eda651a44dcede095ef7b38ef2ba7 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
@@ -510,6 +510,11 @@ public abstract class Player extends LivingEntity {
|
||||
this.containerMenu = this.inventoryMenu;
|
||||
}
|
||||
// Paper end - Inventory close reason
|
||||
+ // Paper start - special close for unloaded inventory
|
||||
+ public void closeUnloadedInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) {
|
||||
+ this.containerMenu = this.inventoryMenu;
|
||||
+ }
|
||||
+ // Paper end - special close for unloaded inventory
|
||||
|
||||
public void closeContainer() {
|
||||
this.containerMenu = this.inventoryMenu;
|
|
@ -1,126 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Sat, 11 Jul 2020 05:09:28 -0700
|
||||
Subject: [PATCH] Fix GameProfileCache concurrency
|
||||
|
||||
Separate lookup and state access locks prevent lookups
|
||||
from stalling simple state access/write calls
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java
|
||||
index 1ec0f3a7148c2f412421772f6e1dff0bb92a51bc..d45fe762941dd6da45c890706bc9e4c0438522c3 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/GameProfileCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java
|
||||
@@ -60,6 +60,11 @@ public class GameProfileCache {
|
||||
@Nullable
|
||||
private Executor executor;
|
||||
|
||||
+ // Paper start - Fix GameProfileCache concurrency
|
||||
+ protected final java.util.concurrent.locks.ReentrantLock stateLock = new java.util.concurrent.locks.ReentrantLock();
|
||||
+ protected final java.util.concurrent.locks.ReentrantLock lookupLock = new java.util.concurrent.locks.ReentrantLock();
|
||||
+ // Paper end - Fix GameProfileCache concurrency
|
||||
+
|
||||
public GameProfileCache(GameProfileRepository profileRepository, File cacheFile) {
|
||||
this.profileRepository = profileRepository;
|
||||
this.file = cacheFile;
|
||||
@@ -67,11 +72,13 @@ public class GameProfileCache {
|
||||
}
|
||||
|
||||
private void safeAdd(GameProfileCache.GameProfileInfo entry) {
|
||||
+ try { this.stateLock.lock(); // Paper - Fix GameProfileCache concurrency
|
||||
GameProfile gameprofile = entry.getProfile();
|
||||
|
||||
entry.setLastAccess(this.getNextOperation());
|
||||
this.profilesByName.put(gameprofile.getName().toLowerCase(Locale.ROOT), entry);
|
||||
this.profilesByUUID.put(gameprofile.getId(), entry);
|
||||
+ } finally { this.stateLock.unlock(); } // Paper - Fix GameProfileCache concurrency
|
||||
}
|
||||
|
||||
private static Optional<GameProfile> lookupGameProfile(GameProfileRepository repository, String name) {
|
||||
@@ -128,17 +135,20 @@ public class GameProfileCache {
|
||||
|
||||
// Paper start
|
||||
public @Nullable GameProfile getProfileIfCached(String name) {
|
||||
+ try { this.stateLock.lock(); // Paper - Fix GameProfileCache concurrency
|
||||
GameProfileCache.GameProfileInfo entry = this.profilesByName.get(name.toLowerCase(Locale.ROOT));
|
||||
if (entry == null) {
|
||||
return null;
|
||||
}
|
||||
entry.setLastAccess(this.getNextOperation());
|
||||
return entry.getProfile();
|
||||
+ } finally { this.stateLock.unlock(); } // Paper - Fix GameProfileCache concurrency
|
||||
}
|
||||
// Paper end
|
||||
|
||||
public Optional<GameProfile> get(String name) {
|
||||
String s1 = name.toLowerCase(Locale.ROOT);
|
||||
+ boolean stateLocked = true; try { this.stateLock.lock(); // Paper - Fix GameProfileCache concurrency
|
||||
GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByName.get(s1);
|
||||
boolean flag = false;
|
||||
|
||||
@@ -154,8 +164,12 @@ public class GameProfileCache {
|
||||
if (usercache_usercacheentry != null) {
|
||||
usercache_usercacheentry.setLastAccess(this.getNextOperation());
|
||||
optional = Optional.of(usercache_usercacheentry.getProfile());
|
||||
+ stateLocked = false; this.stateLock.unlock(); // Paper - Fix GameProfileCache concurrency
|
||||
} else {
|
||||
+ stateLocked = false; this.stateLock.unlock(); // Paper - Fix GameProfileCache concurrency
|
||||
+ try { this.lookupLock.lock(); // Paper - Fix GameProfileCache concurrency
|
||||
optional = GameProfileCache.lookupGameProfile(this.profileRepository, name); // CraftBukkit - use correct case for offline players
|
||||
+ } finally { this.lookupLock.unlock(); } // Paper - Fix GameProfileCache concurrency
|
||||
if (optional.isPresent()) {
|
||||
this.add((GameProfile) optional.get());
|
||||
flag = false;
|
||||
@@ -167,6 +181,7 @@ public class GameProfileCache {
|
||||
}
|
||||
|
||||
return optional;
|
||||
+ } finally { if (stateLocked) { this.stateLock.unlock(); } } // Paper - Fix GameProfileCache concurrency
|
||||
}
|
||||
|
||||
public CompletableFuture<Optional<GameProfile>> getAsync(String username) {
|
||||
@@ -191,6 +206,7 @@ public class GameProfileCache {
|
||||
}
|
||||
|
||||
public Optional<GameProfile> get(UUID uuid) {
|
||||
+ try { this.stateLock.lock(); // Paper - Fix GameProfileCache concurrency
|
||||
GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByUUID.get(uuid);
|
||||
|
||||
if (usercache_usercacheentry == null) {
|
||||
@@ -199,6 +215,7 @@ public class GameProfileCache {
|
||||
usercache_usercacheentry.setLastAccess(this.getNextOperation());
|
||||
return Optional.of(usercache_usercacheentry.getProfile());
|
||||
}
|
||||
+ } finally { this.stateLock.unlock(); } // Paper - Fix GameProfileCache concurrency
|
||||
}
|
||||
|
||||
public void setExecutor(Executor executor) {
|
||||
@@ -279,7 +296,7 @@ public class GameProfileCache {
|
||||
JsonArray jsonarray = new JsonArray();
|
||||
DateFormat dateformat = GameProfileCache.createDateFormat();
|
||||
|
||||
- this.getTopMRUProfiles(org.spigotmc.SpigotConfig.userCacheCap).forEach((usercache_usercacheentry) -> { // Spigot
|
||||
+ this.listTopMRUProfiles(org.spigotmc.SpigotConfig.userCacheCap).forEach((usercache_usercacheentry) -> { // Spigot // Paper - Fix GameProfileCache concurrency
|
||||
jsonarray.add(GameProfileCache.writeGameProfile(usercache_usercacheentry, dateformat));
|
||||
});
|
||||
String s = this.gson.toJson(jsonarray);
|
||||
@@ -320,8 +337,19 @@ public class GameProfileCache {
|
||||
}
|
||||
|
||||
private Stream<GameProfileCache.GameProfileInfo> getTopMRUProfiles(int limit) {
|
||||
- return ImmutableList.copyOf(this.profilesByUUID.values()).stream().sorted(Comparator.comparing(GameProfileCache.GameProfileInfo::getLastAccess).reversed()).limit((long) limit);
|
||||
+ // Paper start - Fix GameProfileCache concurrency
|
||||
+ return this.listTopMRUProfiles(limit).stream();
|
||||
+ }
|
||||
+
|
||||
+ private List<GameProfileCache.GameProfileInfo> listTopMRUProfiles(int limit) {
|
||||
+ try {
|
||||
+ this.stateLock.lock();
|
||||
+ return this.profilesByUUID.values().stream().sorted(Comparator.comparing(GameProfileCache.GameProfileInfo::getLastAccess).reversed()).limit(limit).toList();
|
||||
+ } finally {
|
||||
+ this.stateLock.unlock();
|
||||
+ }
|
||||
}
|
||||
+ // Paper end - Fix GameProfileCache concurrency
|
||||
|
||||
private static JsonElement writeGameProfile(GameProfileCache.GameProfileInfo entry, DateFormat dateFormat) {
|
||||
JsonObject jsonobject = new JsonObject();
|
|
@ -1,227 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Wed, 25 Aug 2021 20:17:12 -0700
|
||||
Subject: [PATCH] Improve and expand AsyncCatcher
|
||||
|
||||
Log when the async catcher is tripped
|
||||
The chunk system can swallow the exception given it's all
|
||||
built with completablefuture, so ensure it is at least printed.
|
||||
|
||||
Add/move several async catchers
|
||||
|
||||
Async catch modifications to critical entity state
|
||||
These used to be here from Spigot, but were dropped with 1.17.
|
||||
Now in 1.17, this state is _even more_ critical than it was before,
|
||||
so these must exist to catch stupid plugins.
|
||||
|
||||
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 574efd531199332a36fb26c70cc44bd5a05ff37d..7efe0cc24590966075ae84d19c3899a43f9adc2a 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -1570,6 +1570,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
}
|
||||
|
||||
public void internalTeleport(double d0, double d1, double d2, float f, float f1, Set<RelativeMovement> set) { // Paper
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("teleport"); // Paper
|
||||
// Paper start - Prevent teleporting dead entities
|
||||
if (player.isRemoved()) {
|
||||
LOGGER.info("Attempt to teleport removed player {} restricted", player.getScoreboardName());
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index f01ace6a6e517ff3d3cd66e69e2594ae3d702072..31eb77e4e5f07b120708edeca497ef2eef1fcf13 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -1126,7 +1126,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
}
|
||||
|
||||
public boolean addEffect(MobEffectInstance mobeffect, @Nullable Entity entity, EntityPotionEffectEvent.Cause cause) {
|
||||
- org.spigotmc.AsyncCatcher.catchOp("effect add"); // Spigot
|
||||
+ // org.spigotmc.AsyncCatcher.catchOp("effect add"); // Spigot // Paper - move to API
|
||||
if (this.isTickingEffects) {
|
||||
this.effectsToProcess.add(new ProcessableEffect(mobeffect, cause));
|
||||
return true;
|
||||
diff --git a/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java b/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java
|
||||
index 8f23b45dce35617bb56b21fb4f7a09baf36d40c5..cbdb2a710a7217b750de3e782cad5b5a45c814b3 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java
|
||||
@@ -78,6 +78,7 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
|
||||
}
|
||||
|
||||
private boolean addEntityUuid(T entity) {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("Entity add by UUID"); // Paper
|
||||
if (!this.knownUuids.add(entity.getUUID())) {
|
||||
PersistentEntitySectionManager.LOGGER.warn("UUID of added entity already exists: {}", entity);
|
||||
return false;
|
||||
@@ -91,6 +92,7 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
|
||||
}
|
||||
|
||||
private boolean addEntity(T entity, boolean existing) {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("Entity add"); // Paper
|
||||
// Paper start - chunk system hooks
|
||||
if (existing) {
|
||||
// I don't want to know why this is a generic type.
|
||||
@@ -146,19 +148,23 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
|
||||
}
|
||||
|
||||
void startTicking(T entity) {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("Entity start ticking"); // Paper
|
||||
this.callbacks.onTickingStart(entity);
|
||||
}
|
||||
|
||||
void stopTicking(T entity) {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("Entity stop ticking"); // Paper
|
||||
this.callbacks.onTickingEnd(entity);
|
||||
}
|
||||
|
||||
void startTracking(T entity) {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("Entity start tracking"); // Paper
|
||||
this.visibleEntityStorage.add(entity);
|
||||
this.callbacks.onTrackingStart(entity);
|
||||
}
|
||||
|
||||
void stopTracking(T entity) {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("Entity stop tracking"); // Paper
|
||||
this.callbacks.onTrackingEnd(entity);
|
||||
this.visibleEntityStorage.remove(entity);
|
||||
}
|
||||
@@ -170,6 +176,7 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
|
||||
}
|
||||
|
||||
public void updateChunkStatus(ChunkPos chunkPos, Visibility trackingStatus) {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("Update chunk status"); // Paper
|
||||
long i = chunkPos.toLong();
|
||||
|
||||
if (trackingStatus == Visibility.HIDDEN) {
|
||||
@@ -214,6 +221,7 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
|
||||
}
|
||||
|
||||
public void ensureChunkQueuedForLoad(long chunkPos) {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("Entity chunk save"); // Paper
|
||||
PersistentEntitySectionManager.ChunkLoadStatus persistententitysectionmanager_b = (PersistentEntitySectionManager.ChunkLoadStatus) this.chunkLoadStatuses.get(chunkPos);
|
||||
|
||||
if (persistententitysectionmanager_b == PersistentEntitySectionManager.ChunkLoadStatus.FRESH) {
|
||||
@@ -258,6 +266,7 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
|
||||
}
|
||||
|
||||
private void requestChunkLoad(long chunkPos) {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("Entity chunk load request"); // Paper
|
||||
this.chunkLoadStatuses.put(chunkPos, PersistentEntitySectionManager.ChunkLoadStatus.PENDING);
|
||||
ChunkPos chunkcoordintpair = new ChunkPos(chunkPos);
|
||||
CompletableFuture completablefuture = this.permanentStorage.loadEntities(chunkcoordintpair);
|
||||
@@ -271,6 +280,7 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
|
||||
}
|
||||
|
||||
private boolean processChunkUnload(long chunkPos) {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("Entity chunk unload process"); // Paper
|
||||
boolean flag = this.storeChunkSections(chunkPos, (entityaccess) -> {
|
||||
entityaccess.getPassengersAndSelf().forEach(this::unloadEntity);
|
||||
}, true); // CraftBukkit - add boolean for event call
|
||||
@@ -295,6 +305,7 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
|
||||
}
|
||||
|
||||
private void processPendingLoads() {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("Entity chunk process pending loads"); // Paper
|
||||
ChunkEntities<T> chunkentities; // CraftBukkit - decompile error
|
||||
|
||||
while ((chunkentities = (ChunkEntities) this.loadingInbox.poll()) != null) {
|
||||
@@ -311,6 +322,7 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("Entity manager tick"); // Paper
|
||||
this.processPendingLoads();
|
||||
this.processUnloads();
|
||||
}
|
||||
@@ -331,6 +343,7 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
|
||||
}
|
||||
|
||||
public void autoSave() {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("Entity manager autosave"); // Paper
|
||||
this.getAllChunksToSave().forEach((java.util.function.LongConsumer) (i) -> { // CraftBukkit - decompile error
|
||||
boolean flag = this.chunkVisibility.get(i) == Visibility.HIDDEN;
|
||||
|
||||
@@ -345,6 +358,7 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
|
||||
}
|
||||
|
||||
public void saveAll() {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("Entity manager save"); // Paper
|
||||
LongSet longset = this.getAllChunksToSave();
|
||||
|
||||
while (!longset.isEmpty()) {
|
||||
@@ -452,6 +466,7 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
|
||||
long i = SectionPos.asLong(blockposition);
|
||||
|
||||
if (i != this.currentSectionKey) {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("Entity move"); // Paper
|
||||
Visibility visibility = this.currentSection.getStatus();
|
||||
|
||||
if (!this.currentSection.remove(this.entity)) {
|
||||
@@ -506,6 +521,7 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
|
||||
|
||||
@Override
|
||||
public void onRemove(Entity.RemovalReason reason) {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("Entity remove"); // Paper
|
||||
if (!this.currentSection.remove(this.entity)) {
|
||||
PersistentEntitySectionManager.LOGGER.warn("Entity {} wasn't found in section {} (destroying due to {})", new Object[]{this.entity, SectionPos.of(this.currentSectionKey), reason});
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
index 6d74a3a43aee0f7ba4c109bd2443c5fcd950fa54..0b1d918452deee4c75bc61cb6a620f69cefa80b3 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
@@ -1757,6 +1757,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
|
||||
@Override
|
||||
public void playSound(Location loc, Sound sound, org.bukkit.SoundCategory category, float volume, float pitch, long seed) {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("play sound"); // Paper
|
||||
if (loc == null || sound == null || category == null) return;
|
||||
|
||||
double x = loc.getX();
|
||||
@@ -1768,6 +1769,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
|
||||
@Override
|
||||
public void playSound(Location loc, String sound, org.bukkit.SoundCategory category, float volume, float pitch, long seed) {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("play sound"); // Paper
|
||||
if (loc == null || sound == null || category == null) return;
|
||||
|
||||
double x = loc.getX();
|
||||
@@ -1800,6 +1802,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
|
||||
@Override
|
||||
public void playSound(Entity entity, Sound sound, org.bukkit.SoundCategory category, float volume, float pitch, long seed) {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("play sound"); // Paper
|
||||
if (!(entity instanceof CraftEntity craftEntity) || entity.getWorld() != this || sound == null || category == null) return;
|
||||
|
||||
ClientboundSoundEntityPacket packet = new ClientboundSoundEntityPacket(CraftSound.bukkitToMinecraftHolder(sound), net.minecraft.sounds.SoundSource.valueOf(category.name()), craftEntity.getHandle(), volume, pitch, seed);
|
||||
@@ -1811,6 +1814,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
|
||||
@Override
|
||||
public void playSound(Entity entity, String sound, org.bukkit.SoundCategory category, float volume, float pitch, long seed) {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("play sound"); // Paper
|
||||
if (!(entity instanceof CraftEntity craftEntity) || entity.getWorld() != this || sound == null || category == null) return;
|
||||
|
||||
ClientboundSoundEntityPacket packet = new ClientboundSoundEntityPacket(Holder.direct(SoundEvent.createVariableRangeEvent(new ResourceLocation(sound))), net.minecraft.sounds.SoundSource.valueOf(category.name()), craftEntity.getHandle(), volume, pitch, seed);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
|
||||
index 4461663659f351f844ed78adc8c1ffd0531a7878..5a760234a4604cec289705f1439f03c821bb0aab 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
|
||||
@@ -517,6 +517,7 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
|
||||
|
||||
@Override
|
||||
public boolean addPotionEffect(PotionEffect effect, boolean force) {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("effect add"); // Paper
|
||||
this.getHandle().addEffect(org.bukkit.craftbukkit.potion.CraftPotionUtil.fromBukkit(effect), EntityPotionEffectEvent.Cause.PLUGIN); // Paper - Don't ignore icon
|
||||
return true;
|
||||
}
|
||||
diff --git a/src/main/java/org/spigotmc/AsyncCatcher.java b/src/main/java/org/spigotmc/AsyncCatcher.java
|
||||
index 78669fa035b7537ff7e533cf32aaf2995625424f..e8e3cc48cf1c58bd8151d1f28df28781859cd0e3 100644
|
||||
--- a/src/main/java/org/spigotmc/AsyncCatcher.java
|
||||
+++ b/src/main/java/org/spigotmc/AsyncCatcher.java
|
||||
@@ -11,6 +11,7 @@ public class AsyncCatcher
|
||||
{
|
||||
if ( (AsyncCatcher.enabled || io.papermc.paper.util.TickThread.STRICT_THREAD_CHECKS) && Thread.currentThread() != MinecraftServer.getServer().serverThread ) // Paper
|
||||
{
|
||||
+ MinecraftServer.LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason, new Throwable()); // Paper
|
||||
throw new IllegalStateException( "Asynchronous " + reason + "!" );
|
||||
}
|
||||
}
|
|
@ -1,341 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
|
||||
Date: Mon, 16 Aug 2021 01:31:54 -0500
|
||||
Subject: [PATCH] Add '/paper mobcaps' and '/paper playermobcaps'
|
||||
|
||||
Add commands to get the mobcaps for a world, as well as the mobcaps for
|
||||
each player when per-player mob spawning is enabled.
|
||||
|
||||
Also has a hover text on each mob category listing what entity types are
|
||||
in said category
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/command/PaperCommand.java b/src/main/java/io/papermc/paper/command/PaperCommand.java
|
||||
index 27775df10a490ff75ca377e8373931738f1b817c..c9bb2df0d884227576ed8d2e72219bbbd7ba827e 100644
|
||||
--- a/src/main/java/io/papermc/paper/command/PaperCommand.java
|
||||
+++ b/src/main/java/io/papermc/paper/command/PaperCommand.java
|
||||
@@ -40,6 +40,7 @@ public final class PaperCommand extends Command {
|
||||
commands.put(Set.of("dumpplugins"), new DumpPluginsCommand());
|
||||
commands.put(Set.of("syncloadinfo"), new SyncLoadInfoCommand());
|
||||
commands.put(Set.of("dumpitem"), new DumpItemCommand());
|
||||
+ commands.put(Set.of("mobcaps", "playermobcaps"), new MobcapsCommand());
|
||||
|
||||
return commands.entrySet().stream()
|
||||
.flatMap(entry -> entry.getKey().stream().map(s -> Map.entry(s, entry.getValue())))
|
||||
diff --git a/src/main/java/io/papermc/paper/command/subcommands/MobcapsCommand.java b/src/main/java/io/papermc/paper/command/subcommands/MobcapsCommand.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..d3b39d88a72ca25057fd8574d32f28db0d420818
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/command/subcommands/MobcapsCommand.java
|
||||
@@ -0,0 +1,229 @@
|
||||
+package io.papermc.paper.command.subcommands;
|
||||
+
|
||||
+import com.google.common.collect.ImmutableMap;
|
||||
+import io.papermc.paper.command.CommandUtil;
|
||||
+import io.papermc.paper.command.PaperSubcommand;
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.Collections;
|
||||
+import java.util.List;
|
||||
+import java.util.Map;
|
||||
+import java.util.function.ToIntFunction;
|
||||
+import net.kyori.adventure.text.Component;
|
||||
+import net.kyori.adventure.text.ComponentLike;
|
||||
+import net.kyori.adventure.text.JoinConfiguration;
|
||||
+import net.kyori.adventure.text.TextComponent;
|
||||
+import net.kyori.adventure.text.format.NamedTextColor;
|
||||
+import net.kyori.adventure.text.format.TextColor;
|
||||
+import net.minecraft.core.registries.BuiltInRegistries;
|
||||
+import net.minecraft.server.level.ServerLevel;
|
||||
+import net.minecraft.server.level.ServerPlayer;
|
||||
+import net.minecraft.world.entity.MobCategory;
|
||||
+import net.minecraft.world.level.NaturalSpawner;
|
||||
+import org.bukkit.Bukkit;
|
||||
+import org.bukkit.World;
|
||||
+import org.bukkit.command.CommandSender;
|
||||
+import org.bukkit.craftbukkit.CraftWorld;
|
||||
+import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
+import org.bukkit.entity.Player;
|
||||
+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 MobcapsCommand implements PaperSubcommand {
|
||||
+ static final Map<MobCategory, TextColor> MOB_CATEGORY_COLORS = ImmutableMap.<MobCategory, TextColor>builder()
|
||||
+ .put(MobCategory.MONSTER, NamedTextColor.RED)
|
||||
+ .put(MobCategory.CREATURE, NamedTextColor.GREEN)
|
||||
+ .put(MobCategory.AMBIENT, NamedTextColor.GRAY)
|
||||
+ .put(MobCategory.AXOLOTLS, TextColor.color(0x7324FF))
|
||||
+ .put(MobCategory.UNDERGROUND_WATER_CREATURE, TextColor.color(0x3541E6))
|
||||
+ .put(MobCategory.WATER_CREATURE, TextColor.color(0x006EFF))
|
||||
+ .put(MobCategory.WATER_AMBIENT, TextColor.color(0x00B3FF))
|
||||
+ .put(MobCategory.MISC, TextColor.color(0x636363))
|
||||
+ .build();
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean execute(final CommandSender sender, final String subCommand, final String[] args) {
|
||||
+ switch (subCommand) {
|
||||
+ case "mobcaps" -> this.printMobcaps(sender, args);
|
||||
+ case "playermobcaps" -> this.printPlayerMobcaps(sender, args);
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public List<String> tabComplete(final CommandSender sender, final String subCommand, final String[] args) {
|
||||
+ return switch (subCommand) {
|
||||
+ case "mobcaps" -> CommandUtil.getListMatchingLast(sender, args, this.suggestMobcaps(args));
|
||||
+ case "playermobcaps" -> CommandUtil.getListMatchingLast(sender, args, this.suggestPlayerMobcaps(sender, args));
|
||||
+ default -> throw new IllegalArgumentException();
|
||||
+ };
|
||||
+ }
|
||||
+
|
||||
+ private List<String> suggestMobcaps(final String[] args) {
|
||||
+ if (args.length == 1) {
|
||||
+ final List<String> worlds = new ArrayList<>(Bukkit.getWorlds().stream().map(World::getName).toList());
|
||||
+ worlds.add("*");
|
||||
+ return worlds;
|
||||
+ }
|
||||
+
|
||||
+ return Collections.emptyList();
|
||||
+ }
|
||||
+
|
||||
+ private List<String> suggestPlayerMobcaps(final CommandSender sender, final String[] args) {
|
||||
+ if (args.length == 1) {
|
||||
+ final List<String> list = new ArrayList<>();
|
||||
+ for (final Player player : Bukkit.getOnlinePlayers()) {
|
||||
+ if (!(sender instanceof Player senderPlayer) || senderPlayer.canSee(player)) {
|
||||
+ list.add(player.getName());
|
||||
+ }
|
||||
+ }
|
||||
+ return list;
|
||||
+ }
|
||||
+
|
||||
+ return Collections.emptyList();
|
||||
+ }
|
||||
+
|
||||
+ private void printMobcaps(final CommandSender sender, final String[] args) {
|
||||
+ final List<World> worlds;
|
||||
+ if (args.length == 0) {
|
||||
+ if (sender instanceof Player player) {
|
||||
+ worlds = List.of(player.getWorld());
|
||||
+ } else {
|
||||
+ sender.sendMessage(Component.text("Must specify a world! ex: '/paper mobcaps world'", NamedTextColor.RED));
|
||||
+ return;
|
||||
+ }
|
||||
+ } else if (args.length == 1) {
|
||||
+ final String input = args[0];
|
||||
+ if (input.equals("*")) {
|
||||
+ worlds = Bukkit.getWorlds();
|
||||
+ } else {
|
||||
+ final @Nullable World world = Bukkit.getWorld(input);
|
||||
+ if (world == null) {
|
||||
+ sender.sendMessage(Component.text("'" + input + "' is not a valid world!", NamedTextColor.RED));
|
||||
+ return;
|
||||
+ } else {
|
||||
+ worlds = List.of(world);
|
||||
+ }
|
||||
+ }
|
||||
+ } else {
|
||||
+ sender.sendMessage(Component.text("Too many arguments!", NamedTextColor.RED));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ for (final World world : worlds) {
|
||||
+ final ServerLevel level = ((CraftWorld) world).getHandle();
|
||||
+ final NaturalSpawner.@Nullable SpawnState state = level.getChunkSource().getLastSpawnState();
|
||||
+
|
||||
+ final int chunks;
|
||||
+ if (state == null) {
|
||||
+ chunks = 0;
|
||||
+ } else {
|
||||
+ chunks = state.getSpawnableChunkCount();
|
||||
+ }
|
||||
+ sender.sendMessage(Component.join(JoinConfiguration.noSeparators(),
|
||||
+ Component.text("Mobcaps for world: "),
|
||||
+ Component.text(world.getName(), NamedTextColor.AQUA),
|
||||
+ Component.text(" (" + chunks + " spawnable chunks)")
|
||||
+ ));
|
||||
+
|
||||
+ sender.sendMessage(createMobcapsComponent(
|
||||
+ category -> {
|
||||
+ if (state == null) {
|
||||
+ return 0;
|
||||
+ } else {
|
||||
+ return state.getMobCategoryCounts().getOrDefault(category, 0);
|
||||
+ }
|
||||
+ },
|
||||
+ category -> NaturalSpawner.globalLimitForCategory(level, category, chunks)
|
||||
+ ));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private void printPlayerMobcaps(final CommandSender sender, final String[] args) {
|
||||
+ final @Nullable Player player;
|
||||
+ if (args.length == 0) {
|
||||
+ if (sender instanceof Player pl) {
|
||||
+ player = pl;
|
||||
+ } else {
|
||||
+ sender.sendMessage(Component.text("Must specify a player! ex: '/paper playermobcount playerName'", NamedTextColor.RED));
|
||||
+ return;
|
||||
+ }
|
||||
+ } else if (args.length == 1) {
|
||||
+ final String input = args[0];
|
||||
+ player = Bukkit.getPlayerExact(input);
|
||||
+ if (player == null) {
|
||||
+ sender.sendMessage(Component.text("Could not find player named '" + input + "'", NamedTextColor.RED));
|
||||
+ return;
|
||||
+ }
|
||||
+ } else {
|
||||
+ sender.sendMessage(Component.text("Too many arguments!", NamedTextColor.RED));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ final ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
|
||||
+ final ServerLevel level = serverPlayer.serverLevel();
|
||||
+
|
||||
+ if (!level.paperConfig().entities.spawning.perPlayerMobSpawns) {
|
||||
+ sender.sendMessage(Component.text("Use '/paper mobcaps' for worlds where per-player mob spawning is disabled.", NamedTextColor.RED));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ sender.sendMessage(Component.join(JoinConfiguration.noSeparators(), Component.text("Mobcaps for player: "), Component.text(player.getName(), NamedTextColor.GREEN)));
|
||||
+ sender.sendMessage(createMobcapsComponent(
|
||||
+ category -> level.chunkSource.chunkMap.getMobCountNear(serverPlayer, category),
|
||||
+ category -> level.getWorld().getSpawnLimitUnsafe(org.bukkit.craftbukkit.util.CraftSpawnCategory.toBukkit(category))
|
||||
+ ));
|
||||
+ }
|
||||
+
|
||||
+ private static Component createMobcapsComponent(final ToIntFunction<MobCategory> countGetter, final ToIntFunction<MobCategory> limitGetter) {
|
||||
+ return MOB_CATEGORY_COLORS.entrySet().stream()
|
||||
+ .map(entry -> {
|
||||
+ final MobCategory category = entry.getKey();
|
||||
+ final TextColor color = entry.getValue();
|
||||
+
|
||||
+ final Component categoryHover = Component.join(JoinConfiguration.noSeparators(),
|
||||
+ Component.text("Entity types in category ", TextColor.color(0xE0E0E0)),
|
||||
+ Component.text(category.getName(), color),
|
||||
+ Component.text(':', NamedTextColor.GRAY),
|
||||
+ Component.newline(),
|
||||
+ Component.newline(),
|
||||
+ BuiltInRegistries.ENTITY_TYPE.entrySet().stream()
|
||||
+ .filter(it -> it.getValue().getCategory() == category)
|
||||
+ .map(it -> Component.translatable(it.getValue().getDescriptionId()))
|
||||
+ .collect(Component.toComponent(Component.text(", ", NamedTextColor.GRAY)))
|
||||
+ );
|
||||
+
|
||||
+ final Component categoryComponent = Component.text()
|
||||
+ .content(" " + category.getName())
|
||||
+ .color(color)
|
||||
+ .hoverEvent(categoryHover)
|
||||
+ .build();
|
||||
+
|
||||
+ final TextComponent.Builder builder = Component.text()
|
||||
+ .append(
|
||||
+ categoryComponent,
|
||||
+ Component.text(": ", NamedTextColor.GRAY)
|
||||
+ );
|
||||
+ final int limit = limitGetter.applyAsInt(category);
|
||||
+ if (limit != -1) {
|
||||
+ builder.append(
|
||||
+ Component.text(countGetter.applyAsInt(category)),
|
||||
+ Component.text("/", NamedTextColor.GRAY),
|
||||
+ Component.text(limit)
|
||||
+ );
|
||||
+ } else {
|
||||
+ builder.append(Component.text()
|
||||
+ .append(
|
||||
+ Component.text('n'),
|
||||
+ Component.text("/", NamedTextColor.GRAY),
|
||||
+ Component.text('a')
|
||||
+ )
|
||||
+ .hoverEvent(Component.text("This category does not naturally spawn.")));
|
||||
+ }
|
||||
+ return builder;
|
||||
+ })
|
||||
+ .map(ComponentLike::asComponent)
|
||||
+ .collect(Component.toComponent(Component.newline()));
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
||||
index 5247782edc426107fb4b3ade5d92f148c0b6e681..c44c10e15564af6ba0f6d60a1b5f38c6e874a43a 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
||||
@@ -157,6 +157,16 @@ public final class NaturalSpawner {
|
||||
world.getProfiler().pop();
|
||||
}
|
||||
|
||||
+ // Paper start - Add mobcaps commands
|
||||
+ public static int globalLimitForCategory(final ServerLevel level, final MobCategory category, final int spawnableChunkCount) {
|
||||
+ final int categoryLimit = level.getWorld().getSpawnLimitUnsafe(CraftSpawnCategory.toBukkit(category));
|
||||
+ if (categoryLimit < 1) {
|
||||
+ return categoryLimit;
|
||||
+ }
|
||||
+ return categoryLimit * spawnableChunkCount / NaturalSpawner.MAGIC_NUMBER;
|
||||
+ }
|
||||
+ // Paper end - Add mobcaps commands
|
||||
+
|
||||
public static void spawnCategoryForChunk(MobCategory group, ServerLevel world, LevelChunk chunk, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner) {
|
||||
BlockPos blockposition = NaturalSpawner.getRandomPosWithin(world, chunk);
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index 51337b1b2e74a67ad54c5d594004b649cb6af4ed..dc37989ab5e0971a144a8248152169b4fd868067 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -2286,6 +2286,11 @@ public final class CraftServer implements Server {
|
||||
|
||||
@Override
|
||||
public int getSpawnLimit(SpawnCategory spawnCategory) {
|
||||
+ // Paper start - Add mobcaps commands
|
||||
+ return this.getSpawnLimitUnsafe(spawnCategory);
|
||||
+ }
|
||||
+ public int getSpawnLimitUnsafe(final SpawnCategory spawnCategory) {
|
||||
+ // Paper end - Add mobcaps commands
|
||||
return this.spawnCategoryLimit.getOrDefault(spawnCategory, -1);
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
index 0b1d918452deee4c75bc61cb6a620f69cefa80b3..139281eab642a3676987fa9b3597b5b6e1a99e9c 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
@@ -1715,9 +1715,14 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
Preconditions.checkArgument(spawnCategory != null, "SpawnCategory cannot be null");
|
||||
Preconditions.checkArgument(CraftSpawnCategory.isValidForLimits(spawnCategory), "SpawnCategory.%s are not supported", spawnCategory);
|
||||
|
||||
+ // Paper start - Add mobcaps commands
|
||||
+ return this.getSpawnLimitUnsafe(spawnCategory);
|
||||
+ }
|
||||
+ public final int getSpawnLimitUnsafe(final SpawnCategory spawnCategory) {
|
||||
int limit = this.spawnCategoryLimit.getOrDefault(spawnCategory, -1);
|
||||
if (limit < 0) {
|
||||
- limit = this.server.getSpawnLimit(spawnCategory);
|
||||
+ limit = this.server.getSpawnLimitUnsafe(spawnCategory);
|
||||
+ // Paper end - Add mobcaps commands
|
||||
}
|
||||
return limit;
|
||||
}
|
||||
diff --git a/src/test/java/io/papermc/paper/command/subcommands/MobcapsCommandTest.java b/src/test/java/io/papermc/paper/command/subcommands/MobcapsCommandTest.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..fd238eacee24ebf0d0ce82b96107e093ca4866b0
|
||||
--- /dev/null
|
||||
+++ b/src/test/java/io/papermc/paper/command/subcommands/MobcapsCommandTest.java
|
||||
@@ -0,0 +1,20 @@
|
||||
+package io.papermc.paper.command.subcommands;
|
||||
+
|
||||
+import java.util.HashSet;
|
||||
+import java.util.Set;
|
||||
+import net.minecraft.world.entity.MobCategory;
|
||||
+import org.junit.jupiter.api.Assertions;
|
||||
+import org.junit.jupiter.api.Test;
|
||||
+
|
||||
+public class MobcapsCommandTest {
|
||||
+ @Test
|
||||
+ public void testMobCategoryColors() {
|
||||
+ final Set<String> missing = new HashSet<>();
|
||||
+ for (final MobCategory value : MobCategory.values()) {
|
||||
+ if (!MobcapsCommand.MOB_CATEGORY_COLORS.containsKey(value)) {
|
||||
+ missing.add(value.getName());
|
||||
+ }
|
||||
+ }
|
||||
+ Assertions.assertTrue(missing.isEmpty(), "MobcapsCommand.MOB_CATEGORY_COLORS map missing TextColors for [" + String.join(", ", missing + "]"));
|
||||
+ }
|
||||
+}
|
|
@ -1,28 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Nassim Jahnke <nassim@njahnke.dev>
|
||||
Date: Thu, 26 Aug 2021 12:09:47 +0200
|
||||
Subject: [PATCH] Sanitize ResourceLocation error logging
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/resources/ResourceLocation.java b/src/main/java/net/minecraft/resources/ResourceLocation.java
|
||||
index aed74e471126a8a66046a181973158d7d288d3f0..3908f88959e43d2f485d5f239257e6564dbda6cd 100644
|
||||
--- a/src/main/java/net/minecraft/resources/ResourceLocation.java
|
||||
+++ b/src/main/java/net/minecraft/resources/ResourceLocation.java
|
||||
@@ -207,7 +207,7 @@ public class ResourceLocation implements Comparable<ResourceLocation> {
|
||||
|
||||
private static String assertValidNamespace(String namespace, String path) {
|
||||
if (!isValidNamespace(namespace)) {
|
||||
- throw new ResourceLocationException("Non [a-z0-9_.-] character in namespace of location: " + namespace + ":" + path);
|
||||
+ throw new ResourceLocationException("Non [a-z0-9_.-] character in namespace of location: " + org.apache.commons.lang3.StringUtils.normalizeSpace(namespace) + ":" + org.apache.commons.lang3.StringUtils.normalizeSpace(path)); // Paper - Sanitize ResourceLocation error logging
|
||||
} else {
|
||||
return namespace;
|
||||
}
|
||||
@@ -233,7 +233,7 @@ public class ResourceLocation implements Comparable<ResourceLocation> {
|
||||
|
||||
private static String assertValidPath(String namespace, String path) {
|
||||
if (!isValidPath(path)) {
|
||||
- throw new ResourceLocationException("Non [a-z0-9/._-] character in path of location: " + namespace + ":" + path);
|
||||
+ throw new ResourceLocationException("Non [a-z0-9/._-] character in path of location: " + namespace + ":" + org.apache.commons.lang3.StringUtils.normalizeSpace(path)); // Paper - Sanitize ResourceLocation error logging
|
||||
} else {
|
||||
return path;
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Mon, 6 Jul 2020 22:48:48 -0700
|
||||
Subject: [PATCH] Manually inline methods in BlockPosition
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java
|
||||
index 4bc994bacdf1fbb7689d799d21a50b7903bf9e59..d80e3f5f53b9d28dea574cff5c65dfa3f8148f88 100644
|
||||
--- a/src/main/java/net/minecraft/core/BlockPos.java
|
||||
+++ b/src/main/java/net/minecraft/core/BlockPos.java
|
||||
@@ -536,9 +536,9 @@ public class BlockPos extends Vec3i {
|
||||
}
|
||||
|
||||
public BlockPos.MutableBlockPos set(int x, int y, int z) {
|
||||
- this.setX(x);
|
||||
- this.setY(y);
|
||||
- this.setZ(z);
|
||||
+ this.x = x; // Paper - Perf: Manually inline methods in BlockPosition
|
||||
+ this.y = y; // Paper - Perf: Manually inline methods in BlockPosition
|
||||
+ this.z = z; // Paper - Perf: Manually inline methods in BlockPosition
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -603,19 +603,19 @@ public class BlockPos extends Vec3i {
|
||||
|
||||
@Override
|
||||
public BlockPos.MutableBlockPos setX(int i) {
|
||||
- super.setX(i);
|
||||
+ this.x = i; // Paper - Perf: Manually inline methods in BlockPosition
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos.MutableBlockPos setY(int i) {
|
||||
- super.setY(i);
|
||||
+ this.y = i; // Paper - Perf: Manually inline methods in BlockPosition
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos.MutableBlockPos setZ(int i) {
|
||||
- super.setZ(i);
|
||||
+ this.z = i; // Paper - Perf: Manually inline methods in BlockPosition
|
||||
return this;
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/core/Vec3i.java b/src/main/java/net/minecraft/core/Vec3i.java
|
||||
index afb1e5ff7b1b6b42f81eaa7888a1ec3ded804ccb..21387401c7958414fa6f3fd530488481d92a6eca 100644
|
||||
--- a/src/main/java/net/minecraft/core/Vec3i.java
|
||||
+++ b/src/main/java/net/minecraft/core/Vec3i.java
|
||||
@@ -17,9 +17,9 @@ public class Vec3i implements Comparable<Vec3i> {
|
||||
vec -> IntStream.of(vec.getX(), vec.getY(), vec.getZ())
|
||||
);
|
||||
public static final Vec3i ZERO = new Vec3i(0, 0, 0);
|
||||
- private int x;
|
||||
- private int y;
|
||||
- private int z;
|
||||
+ protected int x; // Paper - Perf: Manually inline methods in BlockPosition; protected
|
||||
+ protected int y; // Paper - Perf: Manually inline methods in BlockPosition; protected
|
||||
+ protected int z; // Paper - Perf: Manually inline methods in BlockPosition; protected
|
||||
|
||||
public static Codec<Vec3i> offsetCodec(int maxAbsValue) {
|
||||
return ExtraCodecs.validate(
|
|
@ -1,33 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Sun, 19 Jul 2020 15:17:01 -0700
|
||||
Subject: [PATCH] Name craft scheduler threads according to the plugin using
|
||||
them
|
||||
|
||||
Provides quick access to culprits running far more threads than
|
||||
they should be
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncTask.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncTask.java
|
||||
index 365b7e7c665bec357fb76d1479bf17da6f603590..e97f6b76ef2fe21c7c2eca8d4a707e5866d70de9 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncTask.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncTask.java
|
||||
@@ -25,7 +25,10 @@ class CraftAsyncTask extends CraftTask {
|
||||
@Override
|
||||
public void run() {
|
||||
final Thread thread = Thread.currentThread();
|
||||
- synchronized (this.workers) {
|
||||
+ // Paper start - name threads according to running plugin
|
||||
+ final String nameBefore = thread.getName();
|
||||
+ thread.setName(nameBefore + " - " + this.getOwner().getName());
|
||||
+ try { synchronized (this.workers) { // Paper end - name threads according to running plugin
|
||||
if (this.getPeriod() == CraftTask.CANCEL) {
|
||||
// Never continue running after cancelled.
|
||||
// Checking this with the lock is important!
|
||||
@@ -92,6 +95,7 @@ class CraftAsyncTask extends CraftTask {
|
||||
}
|
||||
}
|
||||
}
|
||||
+ } finally { thread.setName(nameBefore); } // Paper - name threads according to running plugin
|
||||
}
|
||||
|
||||
LinkedList<BukkitWorker> getWorkers() {
|
|
@ -1,31 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Sun, 20 Sep 2020 16:10:49 -0700
|
||||
Subject: [PATCH] Make sure inlined getChunkAt has inlined logic for loaded
|
||||
chunks
|
||||
|
||||
Tux did some profiling some time ago and showed that the
|
||||
previous getChunkAt method which had inlined logic for loaded
|
||||
chunks did get inlined, but the standard CPS.getChunkAt
|
||||
method was not inlined.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
||||
index a1dbd23a5d8ea064f1b7909f3e285a4dadf34d88..1ed82afbc3aaa826f8067c65fdfc3ffce36a2ce5 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/Level.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
||||
@@ -358,6 +358,15 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
|
||||
@Override
|
||||
public final LevelChunk getChunk(int chunkX, int chunkZ) { // Paper - final to help inline
|
||||
+ // Paper start - Perf: make sure loaded chunks get the inlined variant of this function
|
||||
+ net.minecraft.server.level.ServerChunkCache cps = ((ServerLevel)this).getChunkSource();
|
||||
+ if (cps.mainThread == Thread.currentThread()) {
|
||||
+ LevelChunk ifLoaded = cps.getChunkAtIfLoadedMainThread(chunkX, chunkZ);
|
||||
+ if (ifLoaded != null) {
|
||||
+ return ifLoaded;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Perf: make sure loaded chunks get the inlined variant of this function
|
||||
return (LevelChunk) this.getChunk(chunkX, chunkZ, ChunkStatus.FULL, true); // Paper - avoid a method jump
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Sun, 11 Apr 2021 02:58:48 -0700
|
||||
Subject: [PATCH] Don't read neighbour chunk data off disk when converting
|
||||
chunks
|
||||
|
||||
Lighting is purged on update anyways, so let's not add more
|
||||
into the conversion process
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java
|
||||
index eaf978d15618b80d23c443acbd42db926d570d01..6743dca44e6552ad39aca757a24f3c4df400d83d 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java
|
||||
@@ -44,6 +44,7 @@ public class ChunkStorage implements AutoCloseable {
|
||||
|
||||
// CraftBukkit start
|
||||
private boolean check(ServerChunkCache cps, int x, int z) {
|
||||
+ if (true) return true; // Paper - Perf: this isn't even needed anymore, light is purged updating to 1.14+, why are we holding up the conversion process reading chunk data off disk - return true, we need to set light populated to true so the converter recognizes the chunk as being "full"
|
||||
ChunkPos pos = new ChunkPos(x, z);
|
||||
if (cps != null) {
|
||||
com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread");
|
|
@ -1,26 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Fri, 28 Aug 2020 12:33:47 -0700
|
||||
Subject: [PATCH] Don't lookup fluid state when raytracing, skip air blocks
|
||||
|
||||
Just use the iblockdata already retrieved, removes a getType call.
|
||||
|
||||
Also save approx. 5% for the raytrace call, as most (expensive)
|
||||
raytracing tends to go through air and returning early is an
|
||||
easy win. The remaining problems with this function
|
||||
are mostly with the block getting itself.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/BlockGetter.java b/src/main/java/net/minecraft/world/level/BlockGetter.java
|
||||
index c3760e0c8ac0b3ea200f4e1c237e250137a78caf..c978f3b2d42f512e982f289e76c2422e41b7eec6 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/BlockGetter.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/BlockGetter.java
|
||||
@@ -79,7 +79,8 @@ public interface BlockGetter extends LevelHeightAccessor {
|
||||
return BlockHitResult.miss(raytrace1.getTo(), Direction.getNearest(vec3d.x, vec3d.y, vec3d.z), BlockPos.containing(raytrace1.getTo()));
|
||||
}
|
||||
// Paper end - Prevent raytrace from loading chunks
|
||||
- FluidState fluid = this.getFluidState(blockposition);
|
||||
+ if (iblockdata.isAir()) return null; // Paper - Perf: optimise air cases
|
||||
+ FluidState fluid = iblockdata.getFluidState(); // Paper - Perf: don't need to go to world state again
|
||||
Vec3 vec3d = raytrace1.getFrom();
|
||||
Vec3 vec3d1 = raytrace1.getTo();
|
||||
VoxelShape voxelshape = raytrace1.getBlockShape(iblockdata, this, blockposition);
|
|
@ -1,43 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Tue, 21 Apr 2020 01:53:22 -0700
|
||||
Subject: [PATCH] Time scoreboard search
|
||||
|
||||
Plugins leaking scoreboards will make this very expensive,
|
||||
let server owners debug it easily
|
||||
|
||||
diff --git a/src/main/java/co/aikar/timings/MinecraftTimings.java b/src/main/java/co/aikar/timings/MinecraftTimings.java
|
||||
index e2764186bd6b838ed5cd86c15597a08d079ef984..6b3cde6d4d1e63bec01f502f2027ee9fddac08aa 100644
|
||||
--- a/src/main/java/co/aikar/timings/MinecraftTimings.java
|
||||
+++ b/src/main/java/co/aikar/timings/MinecraftTimings.java
|
||||
@@ -46,6 +46,7 @@ public final class MinecraftTimings {
|
||||
|
||||
public static final Timing antiXrayUpdateTimer = Timings.ofSafe("anti-xray - update");
|
||||
public static final Timing antiXrayObfuscateTimer = Timings.ofSafe("anti-xray - obfuscate");
|
||||
+ public static final Timing scoreboardScoreSearch = Timings.ofSafe("Scoreboard score search"); // Paper - add timings for scoreboard search
|
||||
|
||||
private static final Map<Class<?>, String> taskNameCache = new MapMaker().weakKeys().makeMap();
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java
|
||||
index c7ca6210d6ae37fe95068c9baa5fb654f95307e0..cad42a0f3c016bf65181e50d139ae4e2fb9158a5 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java
|
||||
@@ -113,9 +113,18 @@ public final class CraftScoreboardManager implements ScoreboardManager {
|
||||
|
||||
// CraftBukkit method
|
||||
public void forAllObjectives(ObjectiveCriteria criteria, ScoreHolder holder, Consumer<ScoreAccess> consumer) {
|
||||
+ // Paper start - add timings for scoreboard search
|
||||
+ // plugins leaking scoreboards will make this very expensive, let server owners debug it easily
|
||||
+ co.aikar.timings.MinecraftTimings.scoreboardScoreSearch.startTimingIfSync();
|
||||
+ try {
|
||||
+ // Paper end - add timings for scoreboard search
|
||||
for (CraftScoreboard scoreboard : this.scoreboards) {
|
||||
Scoreboard board = scoreboard.board;
|
||||
board.forAllObjectives(criteria, holder, (score) -> consumer.accept(score));
|
||||
}
|
||||
+ } finally { // Paper start - add timings for scoreboard search
|
||||
+ co.aikar.timings.MinecraftTimings.scoreboardScoreSearch.stopTimingIfSync();
|
||||
+ }
|
||||
+ // Paper end - add timings for scoreboard search
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Fri, 19 Feb 2021 22:51:52 -0800
|
||||
Subject: [PATCH] Oprimise map impl for tracked players
|
||||
|
||||
Reference2BooleanOpenHashMap is going to have
|
||||
better lookups than HashMap.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 4c1dd470ac561f61d7f49adf90d273b1f293d296..f2d3dc066b00b685715eb5104234945c41a15f92 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -1677,7 +1677,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
final Entity entity;
|
||||
private final int range;
|
||||
SectionPos lastSectionPos;
|
||||
- public final Set<ServerPlayerConnection> seenBy = Sets.newIdentityHashSet();
|
||||
+ public final Set<ServerPlayerConnection> seenBy = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(); // Paper - Perf: optimise map impl
|
||||
|
||||
public TrackedEntity(Entity entity, int i, int j, boolean flag) {
|
||||
this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, j, flag, this::broadcast, this.seenBy); // CraftBukkit
|
|
@ -1,22 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Wed, 27 Dec 2023 16:46:07 -0800
|
||||
Subject: [PATCH] Add missing InventoryType
|
||||
|
||||
Upstream did not add a DECORATED_POT inventory type
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
|
||||
index 3b0d3e9a067fccb10122c273aaf658ba240aa716..af1ae3dacb628da23f7d2988c6e76d3fb2d64103 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
|
||||
@@ -541,6 +541,10 @@ public class CraftInventory implements Inventory {
|
||||
return InventoryType.COMPOSTER;
|
||||
} else if (this.inventory instanceof JukeboxBlockEntity) {
|
||||
return InventoryType.JUKEBOX;
|
||||
+ // Paper start
|
||||
+ } else if (this.inventory instanceof net.minecraft.world.level.block.entity.DecoratedPotBlockEntity) {
|
||||
+ return org.bukkit.event.inventory.InventoryType.DECORATED_POT;
|
||||
+ // Paper end
|
||||
} else {
|
||||
return InventoryType.CHEST;
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Thu, 10 Jun 2021 14:36:00 -0700
|
||||
Subject: [PATCH] Optimise BlockSoil nearby water lookup
|
||||
|
||||
Apparently the abstract block iteration was taking about
|
||||
75% of the method call.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/FarmBlock.java b/src/main/java/net/minecraft/world/level/block/FarmBlock.java
|
||||
index 66106b821d7a384a2eb0f27993beb9f4257e6815..6e4c852c93f2418ea69e485ed3a10cbe3a6e3bd2 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/FarmBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/FarmBlock.java
|
||||
@@ -151,19 +151,28 @@ public class FarmBlock extends Block {
|
||||
}
|
||||
|
||||
private static boolean isNearWater(LevelReader world, BlockPos pos) {
|
||||
- Iterator iterator = BlockPos.betweenClosed(pos.offset(-4, 0, -4), pos.offset(4, 1, 4)).iterator();
|
||||
-
|
||||
- BlockPos blockposition1;
|
||||
-
|
||||
- do {
|
||||
- if (!iterator.hasNext()) {
|
||||
- return false;
|
||||
+ // Paper start - Perf: remove abstract block iteration
|
||||
+ int xOff = pos.getX();
|
||||
+ int yOff = pos.getY();
|
||||
+ int zOff = pos.getZ();
|
||||
+
|
||||
+ for (int dz = -4; dz <= 4; ++dz) {
|
||||
+ int z = dz + zOff;
|
||||
+ for (int dx = -4; dx <= 4; ++dx) {
|
||||
+ int x = xOff + dx;
|
||||
+ for (int dy = 0; dy <= 1; ++dy) {
|
||||
+ int y = dy + yOff;
|
||||
+ net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk)world.getChunk(x >> 4, z >> 4);
|
||||
+ net.minecraft.world.level.material.FluidState fluid = chunk.getBlockStateFinal(x, y, z).getFluidState();
|
||||
+ if (fluid.is(FluidTags.WATER)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
+ }
|
||||
|
||||
- blockposition1 = (BlockPos) iterator.next();
|
||||
- } while (!world.getFluidState(blockposition1).is(FluidTags.WATER));
|
||||
-
|
||||
- return true;
|
||||
+ return false;
|
||||
+ // Paper end - Perf: remove abstract block iteration
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,22 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Thu, 2 Sep 2021 00:24:06 -0700
|
||||
Subject: [PATCH] Fix merchant inventory not closing on entity removal
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 10eb5c342930d2efd7d919f286fe8fa64cebaea4..03a9f82ac2af6cb64081c2bb758cb02a7ffd5b89 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -2325,6 +2325,11 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
// Spigot end
|
||||
// Spigot Start
|
||||
if (entity.getBukkitEntity() instanceof org.bukkit.inventory.InventoryHolder && (!(entity instanceof ServerPlayer) || entity.getRemovalReason() != Entity.RemovalReason.KILLED)) { // SPIGOT-6876: closeInventory clears death message
|
||||
+ // Paper start - Fix merchant inventory not closing on entity removal
|
||||
+ if (entity.getBukkitEntity() instanceof org.bukkit.inventory.Merchant merchant && merchant.getTrader() != null) {
|
||||
+ merchant.getTrader().closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED);
|
||||
+ }
|
||||
+ // Paper end - Fix merchant inventory not closing on entity removal
|
||||
for (org.bukkit.entity.HumanEntity h : Lists.newArrayList(((org.bukkit.inventory.InventoryHolder) entity.getBukkitEntity()).getInventory().getViewers())) {
|
||||
h.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper - Inventory close reason
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: stonar96 <minecraft.stonar96@gmail.com>
|
||||
Date: Sun, 12 Sep 2021 00:14:21 +0200
|
||||
Subject: [PATCH] Check requirement before suggesting root nodes
|
||||
|
||||
Child nodes are handled by CommandDispatcher#parse checking
|
||||
requirements.
|
||||
|
||||
Vanilla clients only send ServerboundCommandSuggestionPacket when
|
||||
encountering a command node with ASK_SERVER suggestions, however a
|
||||
modified client can send this packet whenever it wants.
|
||||
|
||||
diff --git a/src/main/java/com/mojang/brigadier/CommandDispatcher.java b/src/main/java/com/mojang/brigadier/CommandDispatcher.java
|
||||
index 858e41fba7dc285dd21a93f3918cc5de3887df5f..92848b64a78fce7a92e1657c2da6fc5ee53eea44 100644
|
||||
--- a/src/main/java/com/mojang/brigadier/CommandDispatcher.java
|
||||
+++ b/src/main/java/com/mojang/brigadier/CommandDispatcher.java
|
||||
@@ -538,10 +538,14 @@ public class CommandDispatcher<S> {
|
||||
int i = 0;
|
||||
for (final CommandNode<S> node : parent.getChildren()) {
|
||||
CompletableFuture<Suggestions> future = Suggestions.empty();
|
||||
+ // Paper start - Don't suggest if the requirement isn't met
|
||||
+ if (parent != this.root || node.canUse(context.getSource())) {
|
||||
try {
|
||||
- if (node.canUse(parse.getContext().getSource())) future = node.listSuggestions(context.build(truncatedInput), new SuggestionsBuilder(truncatedInput, truncatedInputLowerCase, start)); // CraftBukkit
|
||||
+ future = node.listSuggestions(context.build(truncatedInput), new SuggestionsBuilder(truncatedInput, truncatedInputLowerCase, start)); // CraftBukkit
|
||||
} catch (final CommandSyntaxException ignored) {
|
||||
}
|
||||
+ }
|
||||
+ // Paper end - Don't suggest if the requirement isn't met
|
||||
futures[i++] = future;
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: stonar96 <minecraft.stonar96@gmail.com>
|
||||
Date: Sun, 12 Sep 2021 00:14:21 +0200
|
||||
Subject: [PATCH] Don't respond to ServerboundCommandSuggestionPacket when
|
||||
tab-complete is disabled
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 7efe0cc24590966075ae84d19c3899a43f9adc2a..8fcb241e8d161c9fb024a2a0488f8c29784a74f1 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -725,6 +725,11 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
return;
|
||||
}
|
||||
// CraftBukkit end
|
||||
+ // Paper start - Don't suggest if tab-complete is disabled
|
||||
+ if (org.spigotmc.SpigotConfig.tabComplete < 0) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end - Don't suggest if tab-complete is disabled
|
||||
// Paper start - AsyncTabCompleteEvent
|
||||
TAB_COMPLETE_EXECUTOR.execute(() -> this.handleCustomCommandSuggestions0(packet));
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Fri, 30 Oct 2020 22:37:16 -0700
|
||||
Subject: [PATCH] Add packet limiter config
|
||||
|
||||
Example config:
|
||||
packet-limiter:
|
||||
kick-message: '&cSent too many packets'
|
||||
limits:
|
||||
all:
|
||||
interval: 7.0
|
||||
max-packet-rate: 500.0
|
||||
ServerboundPlaceRecipePacket:
|
||||
interval: 4.0
|
||||
max-packet-rate: 5.0
|
||||
action: DROP
|
||||
|
||||
all section refers to all incoming packets, the action for all is
|
||||
hard coded to KICK.
|
||||
|
||||
For specific limits, the section name is the class's name,
|
||||
and an action can be defined: DROP or KICK
|
||||
|
||||
If interval or rate are less-than 0, the limit is ignored
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
|
||||
index 37b16918451859c22f92bcbcbce05c16b8beff75..22a7f17180b76b6c3548d3b54ae8218a469401a8 100644
|
||||
--- a/src/main/java/net/minecraft/network/Connection.java
|
||||
+++ b/src/main/java/net/minecraft/network/Connection.java
|
||||
@@ -128,6 +128,22 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
return null;
|
||||
}
|
||||
// Paper end - add utility methods
|
||||
+ // Paper start - packet limiter
|
||||
+ protected final Object PACKET_LIMIT_LOCK = new Object();
|
||||
+ protected final @Nullable io.papermc.paper.util.IntervalledCounter allPacketCounts = io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.allPackets.isEnabled() ? new io.papermc.paper.util.IntervalledCounter(
|
||||
+ (long)(io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.allPackets.interval() * 1.0e9)
|
||||
+ ) : null;
|
||||
+ protected final java.util.Map<Class<? extends net.minecraft.network.protocol.Packet<?>>, io.papermc.paper.util.IntervalledCounter> packetSpecificLimits = new java.util.HashMap<>();
|
||||
+
|
||||
+ private boolean stopReadingPackets;
|
||||
+ private void killForPacketSpam() {
|
||||
+ this.sendPacket(new ClientboundDisconnectPacket(io.papermc.paper.adventure.PaperAdventure.asVanilla(io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.kickMessage)), PacketSendListener.thenRun(() -> {
|
||||
+ this.disconnect(io.papermc.paper.adventure.PaperAdventure.asVanilla(io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.kickMessage));
|
||||
+ }), true);
|
||||
+ this.setReadOnly();
|
||||
+ this.stopReadingPackets = true;
|
||||
+ }
|
||||
+ // Paper end - packet limiter
|
||||
|
||||
public Connection(PacketFlow side) {
|
||||
this.receiving = side;
|
||||
@@ -220,6 +236,55 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
if (packetlistener == null) {
|
||||
throw new IllegalStateException("Received a packet before the packet listener was initialized");
|
||||
} else {
|
||||
+ // Paper start - packet limiter
|
||||
+ if (this.stopReadingPackets) {
|
||||
+ return;
|
||||
+ }
|
||||
+ if (this.allPacketCounts != null ||
|
||||
+ io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.overrides.containsKey(packet.getClass())) {
|
||||
+ long time = System.nanoTime();
|
||||
+ synchronized (PACKET_LIMIT_LOCK) {
|
||||
+ if (this.allPacketCounts != null) {
|
||||
+ this.allPacketCounts.updateAndAdd(1, time);
|
||||
+ if (this.allPacketCounts.getRate() >= io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.allPackets.maxPacketRate()) {
|
||||
+ this.killForPacketSpam();
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ for (Class<?> check = packet.getClass(); check != Object.class; check = check.getSuperclass()) {
|
||||
+ io.papermc.paper.configuration.GlobalConfiguration.PacketLimiter.PacketLimit packetSpecificLimit =
|
||||
+ io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.overrides.get(check);
|
||||
+ if (packetSpecificLimit == null || !packetSpecificLimit.isEnabled()) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ io.papermc.paper.util.IntervalledCounter counter = this.packetSpecificLimits.computeIfAbsent((Class)check, (clazz) -> {
|
||||
+ return new io.papermc.paper.util.IntervalledCounter((long)(packetSpecificLimit.interval() * 1.0e9));
|
||||
+ });
|
||||
+ counter.updateAndAdd(1, time);
|
||||
+ if (counter.getRate() >= packetSpecificLimit.maxPacketRate()) {
|
||||
+ switch (packetSpecificLimit.action()) {
|
||||
+ case DROP:
|
||||
+ return;
|
||||
+ case KICK:
|
||||
+ String deobfedPacketName = io.papermc.paper.util.ObfHelper.INSTANCE.deobfClassName(check.getName());
|
||||
+
|
||||
+ String playerName;
|
||||
+ if (this.packetListener instanceof net.minecraft.server.network.ServerCommonPacketListenerImpl impl) {
|
||||
+ playerName = impl.getOwner().getName();
|
||||
+ } else {
|
||||
+ playerName = this.getLoggableAddress(net.minecraft.server.MinecraftServer.getServer().logIPs());
|
||||
+ }
|
||||
+
|
||||
+ Connection.LOGGER.warn("{} kicked for packet spamming: {}", playerName, deobfedPacketName.substring(deobfedPacketName.lastIndexOf(".") + 1));
|
||||
+ this.killForPacketSpam();
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - packet limiter
|
||||
if (packetlistener.shouldHandleMessage(packet)) {
|
||||
try {
|
||||
Connection.genericsFtw(packet, packetlistener);
|
|
@ -1,71 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Bjarne Koll <lynxplay101@gmail.com>
|
||||
Date: Sat, 6 Nov 2021 23:15:20 +0100
|
||||
Subject: [PATCH] Fix setPatternColor on tropical fish bucket meta
|
||||
|
||||
Prior to this commit, the tropical fish bucket meta would set the body
|
||||
color to the previous metas pattern colour when updating the pattern
|
||||
colour.
|
||||
|
||||
This commit hence simply fixes this by using the proper body colour
|
||||
value when updating the pattern color.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaTropicalFishBucket.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaTropicalFishBucket.java
|
||||
index a4256ee1c1cd305d1253e7b8084d814428386369..67c56a4f643e1cb52139c8f3ffc4af0cf278339f 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaTropicalFishBucket.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaTropicalFishBucket.java
|
||||
@@ -107,7 +107,7 @@ class CraftMetaTropicalFishBucket extends CraftMetaItem implements TropicalFishB
|
||||
if (this.variant == null) {
|
||||
this.variant = 0;
|
||||
}
|
||||
- this.variant = CraftTropicalFish.getData(color, this.getPatternColor(), this.getPattern());
|
||||
+ this.variant = CraftTropicalFish.getData(color, this.getBodyColor(), this.getPattern()); // Paper - properly set tropical fish pattern color without mutating body color
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/test/java/io/papermc/paper/inventory/CraftMetaTropicalFishBucketTest.java b/src/test/java/io/papermc/paper/inventory/CraftMetaTropicalFishBucketTest.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..a71e1d488a74dcac70b1dca889181527395be9b5
|
||||
--- /dev/null
|
||||
+++ b/src/test/java/io/papermc/paper/inventory/CraftMetaTropicalFishBucketTest.java
|
||||
@@ -0,0 +1,40 @@
|
||||
+package io.papermc.paper.inventory;
|
||||
+
|
||||
+import org.bukkit.DyeColor;
|
||||
+import org.bukkit.Material;
|
||||
+import org.bukkit.entity.TropicalFish;
|
||||
+import org.bukkit.inventory.ItemStack;
|
||||
+import org.bukkit.inventory.meta.TropicalFishBucketMeta;
|
||||
+import org.bukkit.support.AbstractTestingBase;
|
||||
+import org.junit.jupiter.api.Assertions;
|
||||
+import org.junit.jupiter.api.Test;
|
||||
+
|
||||
+public class CraftMetaTropicalFishBucketTest extends AbstractTestingBase {
|
||||
+
|
||||
+ @Test
|
||||
+ public void testAllCombinations() {
|
||||
+ final var rawMeta = new ItemStack(Material.TROPICAL_FISH_BUCKET).getItemMeta();
|
||||
+ Assertions.assertTrue(rawMeta instanceof TropicalFishBucketMeta, "Meta was not a tropical fish bucket");
|
||||
+
|
||||
+ final var meta = (TropicalFishBucketMeta) rawMeta;
|
||||
+
|
||||
+ for (final var bodyColor : DyeColor.values()) {
|
||||
+ for (final var pattern : TropicalFish.Pattern.values()) {
|
||||
+ for (final var patternColor : DyeColor.values()) {
|
||||
+ meta.setBodyColor(bodyColor);
|
||||
+ Assertions.assertEquals(bodyColor, meta.getBodyColor(), "Body color did not match post body color!");
|
||||
+
|
||||
+ meta.setPattern(pattern);
|
||||
+ Assertions.assertEquals(pattern, meta.getPattern(), "Pattern did not match post pattern!");
|
||||
+ Assertions.assertEquals(bodyColor, meta.getBodyColor(), "Body color did not match post pattern!");
|
||||
+
|
||||
+ meta.setPatternColor(patternColor);
|
||||
+ Assertions.assertEquals(pattern, meta.getPattern(), "Pattern did not match post pattern color!");
|
||||
+ Assertions.assertEquals(bodyColor, meta.getBodyColor(), "Body color did not match post pattern color!");
|
||||
+ Assertions.assertEquals(patternColor, meta.getPatternColor(), "Pattern color did not match post pattern color!");
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+}
|
|
@ -1,19 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Nassim Jahnke <nassim@njahnke.dev>
|
||||
Date: Tue, 28 Sep 2021 09:47:47 +0200
|
||||
Subject: [PATCH] Ensure valid vehicle status
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 5f43cd7f6cc1e14771c3df6ec1f074e670ec6206..b5a3587a9074a1a2fcc2252d2db8b184b6ab6793 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -527,7 +527,7 @@ public class ServerPlayer extends Player {
|
||||
}
|
||||
}
|
||||
|
||||
- if (persistVehicle && entity1 != null && entity != this && entity.hasExactlyOnePlayerPassenger()) {
|
||||
+ if (persistVehicle && entity1 != null && entity != this && entity.hasExactlyOnePlayerPassenger() && !entity.isRemoved()) { // Paper - Ensure valid vehicle status
|
||||
// CraftBukkit end
|
||||
CompoundTag nbttagcompound2 = new CompoundTag();
|
||||
CompoundTag nbttagcompound3 = new CompoundTag();
|
|
@ -1,22 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Noah van der Aa <ndvdaa@gmail.com>
|
||||
Date: Mon, 30 Aug 2021 15:22:18 +0200
|
||||
Subject: [PATCH] Prevent softlocked end exit portal generation
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
|
||||
index 1c9bfcf595bcb247c3b9ffe8b0e0cfee0d0ba91f..50071bec6825ec2b34662de14128070510d16afb 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
|
||||
@@ -466,6 +466,11 @@ public class EndDragonFight {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start - Prevent "softlocked" exit portal generation
|
||||
+ if (this.portalLocation.getY() <= this.level.getMinBuildHeight()) {
|
||||
+ this.portalLocation = this.portalLocation.atY(this.level.getMinBuildHeight() + 1);
|
||||
+ }
|
||||
+ // Paper end - Prevent "softlocked" exit portal generation
|
||||
if (worldgenendtrophy.place(FeatureConfiguration.NONE, this.level, this.level.getChunkSource().getGenerator(), RandomSource.create(), this.portalLocation)) {
|
||||
int i = Mth.positiveCeilDiv(4, 16);
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Tue, 7 Sep 2021 21:29:38 +0100
|
||||
Subject: [PATCH] Fix CocaoDecorator causing a crash when trying to generate
|
||||
without logs
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/treedecorators/CocoaDecorator.java b/src/main/java/net/minecraft/world/level/levelgen/feature/treedecorators/CocoaDecorator.java
|
||||
index 05a874404daec8d7194e0d5bc8d17f76d3cc94ef..961a772eecb759c8c2a2e1461988fdb3f06dd1b0 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/levelgen/feature/treedecorators/CocoaDecorator.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/treedecorators/CocoaDecorator.java
|
||||
@@ -26,6 +26,7 @@ public class CocoaDecorator extends TreeDecorator {
|
||||
|
||||
@Override
|
||||
public void place(TreeDecorator.Context generator) {
|
||||
+ if (generator.logs().isEmpty()) return; // Paper - Fix crash when trying to generate without logs
|
||||
RandomSource randomSource = generator.random();
|
||||
if (!(randomSource.nextFloat() >= this.probability)) {
|
||||
List<BlockPos> list = generator.logs();
|
|
@ -1,19 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Noah van der Aa <ndvdaa@gmail.com>
|
||||
Date: Tue, 14 Sep 2021 16:24:45 +0200
|
||||
Subject: [PATCH] Don't log debug logging being disabled
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java
|
||||
index 56dbc23f10d946a7ec992b08fd868f3ee5089068..6c260403d91d640da0473a3df56e1c5582459fde 100644
|
||||
--- a/src/main/java/org/spigotmc/SpigotConfig.java
|
||||
+++ b/src/main/java/org/spigotmc/SpigotConfig.java
|
||||
@@ -382,7 +382,7 @@ public class SpigotConfig
|
||||
Bukkit.getLogger().info( "Debug logging is enabled" );
|
||||
} else
|
||||
{
|
||||
- Bukkit.getLogger().info( "Debug logging is disabled" );
|
||||
+ // Bukkit.getLogger().info( "Debug logging is disabled" ); // Paper - Don't log if debug logging isn't enabled.
|
||||
}
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sun, 11 Jul 2021 12:52:56 -0700
|
||||
Subject: [PATCH] fix various menus with empty level accesses
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/inventory/ContainerLevelAccess.java b/src/main/java/net/minecraft/world/inventory/ContainerLevelAccess.java
|
||||
index c96b04f045dda384cdee9254a1765ef97e5f7f03..85e336637db8643fc5aca1dba724c9b341cbf46f 100644
|
||||
--- a/src/main/java/net/minecraft/world/inventory/ContainerLevelAccess.java
|
||||
+++ b/src/main/java/net/minecraft/world/inventory/ContainerLevelAccess.java
|
||||
@@ -27,6 +27,12 @@ public interface ContainerLevelAccess {
|
||||
public <T> Optional<T> evaluate(BiFunction<Level, BlockPos, T> getter) {
|
||||
return Optional.empty();
|
||||
}
|
||||
+ // Paper start - fix menus with empty level accesses
|
||||
+ @Override
|
||||
+ public org.bukkit.Location getLocation() {
|
||||
+ return null;
|
||||
+ }
|
||||
+ // Paper end - fix menus with empty level accesses
|
||||
};
|
||||
|
||||
static ContainerLevelAccess create(final Level world, final BlockPos pos) {
|
|
@ -1,27 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: lexikiq <noellekiq@gmail.com>
|
||||
Date: Mon, 21 Jun 2021 23:21:58 -0400
|
||||
Subject: [PATCH] Preserve overstacked loot
|
||||
|
||||
Preserves overstacked items in loot tables, such as shulker box drops, to prevent the items
|
||||
from being deleted (as they'd overflow past the bounds of the container)-- or worse, causing
|
||||
chunk bans via the large amount of NBT created by unstacking the items.
|
||||
|
||||
Fixes GH-5140 and GH-4748.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/storage/loot/LootTable.java b/src/main/java/net/minecraft/world/level/storage/loot/LootTable.java
|
||||
index 214215d203892b8009595539f25ce26e8752debd..05af6fa0585406c4922d2eb174f7e53f4269acd6 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/storage/loot/LootTable.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/storage/loot/LootTable.java
|
||||
@@ -68,9 +68,10 @@ public class LootTable {
|
||||
}
|
||||
|
||||
public static Consumer<ItemStack> createStackSplitter(ServerLevel world, Consumer<ItemStack> consumer) {
|
||||
+ boolean skipSplitter = world != null && !world.paperConfig().fixes.splitOverstackedLoot; // Paper - preserve overstacked items
|
||||
return (itemstack) -> {
|
||||
if (itemstack.isItemEnabled(world.enabledFeatures())) {
|
||||
- if (itemstack.getCount() < itemstack.getMaxStackSize()) {
|
||||
+ if (skipSplitter || itemstack.getCount() < itemstack.getMaxStackSize()) { // Paper - preserve overstacked items
|
||||
consumer.accept(itemstack);
|
||||
} else {
|
||||
int i = itemstack.getCount();
|
|
@ -1,29 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
|
||||
Date: Mon, 21 Jun 2021 21:55:23 -0400
|
||||
Subject: [PATCH] Update head rotation in missing places
|
||||
|
||||
In certain areas the player's head rotation could be desynced when teleported/moved.
|
||||
This is because bukkit uses a separate head rotation field for yaw.
|
||||
This issue only applies to players.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index b9f61d08adf83bbaed522c2258db116492cb24c5..685cd5c719a0bf8d3e41aa95b0e84effe1241948 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -1790,6 +1790,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
|
||||
this.setXRot(Mth.clamp(pitch, -90.0F, 90.0F) % 360.0F);
|
||||
this.yRotO = this.getYRot();
|
||||
this.xRotO = this.getXRot();
|
||||
+ this.setYHeadRot(yaw); // Paper - Update head rotation
|
||||
}
|
||||
|
||||
public void absMoveTo(double x, double y, double z) {
|
||||
@@ -1828,6 +1829,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
|
||||
this.setXRot(pitch);
|
||||
this.setOldPosAndRot();
|
||||
this.reapplyPosition();
|
||||
+ this.setYHeadRot(yaw); // Paper - Update head rotation
|
||||
}
|
||||
|
||||
public final void setOldPosAndRot() {
|
|
@ -1,18 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Mon, 13 Sep 2021 18:55:45 -0700
|
||||
Subject: [PATCH] prevent unintended light block manipulation
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/LightBlock.java b/src/main/java/net/minecraft/world/level/block/LightBlock.java
|
||||
index 0fe3186b4edbbc93f5794d23dffe58c063be8d67..95d36c3a74d0b71662864f27c54cf52ba41d384c 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/LightBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/LightBlock.java
|
||||
@@ -52,6 +52,7 @@ public class LightBlock extends Block implements SimpleWaterloggedBlock {
|
||||
@Override
|
||||
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
|
||||
if (!world.isClientSide && player.canUseGameMasterBlocks()) {
|
||||
+ if (player.getItemInHand(hand).getItem() != Items.LIGHT || !player.mayInteract(world, pos) || !player.mayUseItemAt(pos, hit.getDirection(), player.getItemInHand(hand))) { return InteractionResult.FAIL; } // Paper - Prevent unintended light block manipulation
|
||||
world.setBlock(pos, state.cycle(LEVEL), 2);
|
||||
return InteractionResult.SUCCESS;
|
||||
} else {
|
|
@ -1,19 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Mon, 4 Oct 2021 22:31:51 -0700
|
||||
Subject: [PATCH] Fix CraftCriteria defaults map
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftCriteria.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftCriteria.java
|
||||
index 441e2122f837712a21328eb7659cc9925ff9b6f8..8464531a4ee400834d25c23b1eb723f49be8689e 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftCriteria.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftCriteria.java
|
||||
@@ -54,7 +54,7 @@ public final class CraftCriteria implements Criteria {
|
||||
}
|
||||
|
||||
static CraftCriteria getFromNMS(Objective objective) {
|
||||
- return CraftCriteria.DEFAULTS.get(objective.getCriteria().getName());
|
||||
+ return java.util.Objects.requireNonNullElseGet(CraftCriteria.DEFAULTS.get(objective.getCriteria().getName()), () -> new CraftCriteria(objective.getCriteria())); // Paper
|
||||
}
|
||||
|
||||
public static CraftCriteria getFromBukkit(String name) {
|
|
@ -1,441 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Wed, 6 Oct 2021 20:50:48 -0700
|
||||
Subject: [PATCH] Fix upstreams block state factories
|
||||
|
||||
Sometimes, blocks are changed and then logic is called before the associated
|
||||
tile entity is removed. When this happens, the factories were relying on the
|
||||
block at the position, not the tile entity. This change prioritizes using the
|
||||
tile entity type to determine the block state factory and falls back on
|
||||
the material type of the block at that location.
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.level.block.entity.BlockEntityType validBlocks
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
|
||||
index 53443b472d21633f49c102b330c8406c92f09d8d..4893eaf93738da860014ddf3ad003334c9ebc9fa 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
|
||||
@@ -247,7 +247,7 @@ public abstract class BlockEntity {
|
||||
// Paper end
|
||||
if (this.level == null) return null;
|
||||
org.bukkit.block.Block block = this.level.getWorld().getBlockAt(this.worldPosition.getX(), this.worldPosition.getY(), this.worldPosition.getZ());
|
||||
- if (block.getType() == org.bukkit.Material.AIR) return null;
|
||||
+ // if (block.getType() == org.bukkit.Material.AIR) return null; // Paper - actually get the tile entity if it still exists
|
||||
org.bukkit.block.BlockState state = block.getState(useSnapshot); // Paper
|
||||
if (state instanceof InventoryHolder) return (InventoryHolder) state;
|
||||
return null;
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
|
||||
index ff3f88f107a4c059688566b69dcdf48bc01210ab..7cd0fae59c497861063827eda4243cc6c11e7cff 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
|
||||
@@ -13,7 +13,7 @@ import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
-public class CraftBlockEntityState<T extends BlockEntity> extends CraftBlockState implements TileState {
|
||||
+public abstract class CraftBlockEntityState<T extends BlockEntity> extends CraftBlockState implements TileState { // Paper - revert upstream's revert of the block state changes
|
||||
|
||||
private final T tileEntity;
|
||||
private final T snapshot;
|
||||
@@ -153,9 +153,7 @@ public class CraftBlockEntityState<T extends BlockEntity> extends CraftBlockStat
|
||||
}
|
||||
|
||||
@Override
|
||||
- public CraftBlockEntityState<T> copy() {
|
||||
- return new CraftBlockEntityState<>(this);
|
||||
- }
|
||||
+ public abstract CraftBlockEntityState<T> copy(); // Paper - make abstract
|
||||
|
||||
// Paper start
|
||||
@Override
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java
|
||||
index 76a3f4ad26718f95f4cf64206efe16e598fa2285..f81c0d07a5efc92942d8ab5c50a8260db033307d 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java
|
||||
@@ -19,6 +19,7 @@ import net.minecraft.world.level.block.entity.BeehiveBlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BellBlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlastFurnaceBlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
+import net.minecraft.world.level.block.entity.BlockEntityType; // Paper
|
||||
import net.minecraft.world.level.block.entity.BrewingStandBlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BrushableBlockEntity;
|
||||
import net.minecraft.world.level.block.entity.CalibratedSculkSensorBlockEntity;
|
||||
@@ -114,227 +115,64 @@ public final class CraftBlockStates {
|
||||
private static final BlockStateFactory<?> DEFAULT_FACTORY = new BlockStateFactory<CraftBlockState>(CraftBlockState.class) {
|
||||
@Override
|
||||
public CraftBlockState createBlockState(World world, BlockPos blockPosition, net.minecraft.world.level.block.state.BlockState blockData, BlockEntity tileEntity) {
|
||||
- // SPIGOT-6754, SPIGOT-6817: Restore previous behaviour for tile entities with removed blocks (loot generation post-destroy)
|
||||
- if (tileEntity != null) {
|
||||
- // block with unhandled TileEntity:
|
||||
- return new CraftBlockEntityState<>(world, tileEntity);
|
||||
- }
|
||||
+ // Paper - revert upstream's revert of the block state changes. Block entities that have already had the block type set to AIR are still valid, upstream decided to ignore them
|
||||
Preconditions.checkState(tileEntity == null, "Unexpected BlockState for %s", CraftBlockType.minecraftToBukkit(blockData.getBlock()));
|
||||
return new CraftBlockState(world, blockPosition, blockData);
|
||||
}
|
||||
};
|
||||
+ // Paper start
|
||||
+ private static final Map<BlockEntityType<?>, BlockStateFactory<?>> FACTORIES_BY_BLOCK_ENTITY_TYPE = new HashMap<>();
|
||||
+ private static void register(BlockEntityType<?> type, BlockStateFactory<?> factory) {
|
||||
+ FACTORIES_BY_BLOCK_ENTITY_TYPE.put(type, factory);
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
static {
|
||||
- register(
|
||||
- Arrays.asList(
|
||||
- Material.ACACIA_SIGN,
|
||||
- Material.ACACIA_WALL_SIGN,
|
||||
- Material.BAMBOO_SIGN,
|
||||
- Material.BAMBOO_WALL_SIGN,
|
||||
- Material.BIRCH_SIGN,
|
||||
- Material.BIRCH_WALL_SIGN,
|
||||
- Material.CHERRY_SIGN,
|
||||
- Material.CHERRY_WALL_SIGN,
|
||||
- Material.CRIMSON_SIGN,
|
||||
- Material.CRIMSON_WALL_SIGN,
|
||||
- Material.DARK_OAK_SIGN,
|
||||
- Material.DARK_OAK_WALL_SIGN,
|
||||
- Material.JUNGLE_SIGN,
|
||||
- Material.JUNGLE_WALL_SIGN,
|
||||
- Material.MANGROVE_SIGN,
|
||||
- Material.MANGROVE_WALL_SIGN,
|
||||
- Material.OAK_SIGN,
|
||||
- Material.OAK_WALL_SIGN,
|
||||
- Material.SPRUCE_SIGN,
|
||||
- Material.SPRUCE_WALL_SIGN,
|
||||
- Material.WARPED_SIGN,
|
||||
- Material.WARPED_WALL_SIGN
|
||||
- ), CraftSign.class, CraftSign::new, SignBlockEntity::new
|
||||
- );
|
||||
-
|
||||
- register(
|
||||
- Arrays.asList(
|
||||
- Material.ACACIA_HANGING_SIGN,
|
||||
- Material.ACACIA_WALL_HANGING_SIGN,
|
||||
- Material.BAMBOO_HANGING_SIGN,
|
||||
- Material.BAMBOO_WALL_HANGING_SIGN,
|
||||
- Material.BIRCH_HANGING_SIGN,
|
||||
- Material.BIRCH_WALL_HANGING_SIGN,
|
||||
- Material.CHERRY_HANGING_SIGN,
|
||||
- Material.CHERRY_WALL_HANGING_SIGN,
|
||||
- Material.CRIMSON_HANGING_SIGN,
|
||||
- Material.CRIMSON_WALL_HANGING_SIGN,
|
||||
- Material.DARK_OAK_HANGING_SIGN,
|
||||
- Material.DARK_OAK_WALL_HANGING_SIGN,
|
||||
- Material.JUNGLE_HANGING_SIGN,
|
||||
- Material.JUNGLE_WALL_HANGING_SIGN,
|
||||
- Material.MANGROVE_HANGING_SIGN,
|
||||
- Material.MANGROVE_WALL_HANGING_SIGN,
|
||||
- Material.OAK_HANGING_SIGN,
|
||||
- Material.OAK_WALL_HANGING_SIGN,
|
||||
- Material.SPRUCE_HANGING_SIGN,
|
||||
- Material.SPRUCE_WALL_HANGING_SIGN,
|
||||
- Material.WARPED_HANGING_SIGN,
|
||||
- Material.WARPED_WALL_HANGING_SIGN
|
||||
- ), CraftHangingSign.class, CraftHangingSign::new, HangingSignBlockEntity::new
|
||||
- );
|
||||
-
|
||||
- register(
|
||||
- Arrays.asList(
|
||||
- Material.CREEPER_HEAD,
|
||||
- Material.CREEPER_WALL_HEAD,
|
||||
- Material.DRAGON_HEAD,
|
||||
- Material.DRAGON_WALL_HEAD,
|
||||
- Material.PIGLIN_HEAD,
|
||||
- Material.PIGLIN_WALL_HEAD,
|
||||
- Material.PLAYER_HEAD,
|
||||
- Material.PLAYER_WALL_HEAD,
|
||||
- Material.SKELETON_SKULL,
|
||||
- Material.SKELETON_WALL_SKULL,
|
||||
- Material.WITHER_SKELETON_SKULL,
|
||||
- Material.WITHER_SKELETON_WALL_SKULL,
|
||||
- Material.ZOMBIE_HEAD,
|
||||
- Material.ZOMBIE_WALL_HEAD
|
||||
- ), CraftSkull.class, CraftSkull::new, SkullBlockEntity::new
|
||||
- );
|
||||
-
|
||||
- register(
|
||||
- Arrays.asList(
|
||||
- Material.COMMAND_BLOCK,
|
||||
- Material.REPEATING_COMMAND_BLOCK,
|
||||
- Material.CHAIN_COMMAND_BLOCK
|
||||
- ), CraftCommandBlock.class, CraftCommandBlock::new, CommandBlockEntity::new
|
||||
- );
|
||||
-
|
||||
- register(
|
||||
- Arrays.asList(
|
||||
- Material.BLACK_BANNER,
|
||||
- Material.BLACK_WALL_BANNER,
|
||||
- Material.BLUE_BANNER,
|
||||
- Material.BLUE_WALL_BANNER,
|
||||
- Material.BROWN_BANNER,
|
||||
- Material.BROWN_WALL_BANNER,
|
||||
- Material.CYAN_BANNER,
|
||||
- Material.CYAN_WALL_BANNER,
|
||||
- Material.GRAY_BANNER,
|
||||
- Material.GRAY_WALL_BANNER,
|
||||
- Material.GREEN_BANNER,
|
||||
- Material.GREEN_WALL_BANNER,
|
||||
- Material.LIGHT_BLUE_BANNER,
|
||||
- Material.LIGHT_BLUE_WALL_BANNER,
|
||||
- Material.LIGHT_GRAY_BANNER,
|
||||
- Material.LIGHT_GRAY_WALL_BANNER,
|
||||
- Material.LIME_BANNER,
|
||||
- Material.LIME_WALL_BANNER,
|
||||
- Material.MAGENTA_BANNER,
|
||||
- Material.MAGENTA_WALL_BANNER,
|
||||
- Material.ORANGE_BANNER,
|
||||
- Material.ORANGE_WALL_BANNER,
|
||||
- Material.PINK_BANNER,
|
||||
- Material.PINK_WALL_BANNER,
|
||||
- Material.PURPLE_BANNER,
|
||||
- Material.PURPLE_WALL_BANNER,
|
||||
- Material.RED_BANNER,
|
||||
- Material.RED_WALL_BANNER,
|
||||
- Material.WHITE_BANNER,
|
||||
- Material.WHITE_WALL_BANNER,
|
||||
- Material.YELLOW_BANNER,
|
||||
- Material.YELLOW_WALL_BANNER
|
||||
- ), CraftBanner.class, CraftBanner::new, BannerBlockEntity::new
|
||||
- );
|
||||
-
|
||||
- register(
|
||||
- Arrays.asList(
|
||||
- Material.SHULKER_BOX,
|
||||
- Material.WHITE_SHULKER_BOX,
|
||||
- Material.ORANGE_SHULKER_BOX,
|
||||
- Material.MAGENTA_SHULKER_BOX,
|
||||
- Material.LIGHT_BLUE_SHULKER_BOX,
|
||||
- Material.YELLOW_SHULKER_BOX,
|
||||
- Material.LIME_SHULKER_BOX,
|
||||
- Material.PINK_SHULKER_BOX,
|
||||
- Material.GRAY_SHULKER_BOX,
|
||||
- Material.LIGHT_GRAY_SHULKER_BOX,
|
||||
- Material.CYAN_SHULKER_BOX,
|
||||
- Material.PURPLE_SHULKER_BOX,
|
||||
- Material.BLUE_SHULKER_BOX,
|
||||
- Material.BROWN_SHULKER_BOX,
|
||||
- Material.GREEN_SHULKER_BOX,
|
||||
- Material.RED_SHULKER_BOX,
|
||||
- Material.BLACK_SHULKER_BOX
|
||||
- ), CraftShulkerBox.class, CraftShulkerBox::new, ShulkerBoxBlockEntity::new
|
||||
- );
|
||||
-
|
||||
- register(
|
||||
- Arrays.asList(
|
||||
- Material.BLACK_BED,
|
||||
- Material.BLUE_BED,
|
||||
- Material.BROWN_BED,
|
||||
- Material.CYAN_BED,
|
||||
- Material.GRAY_BED,
|
||||
- Material.GREEN_BED,
|
||||
- Material.LIGHT_BLUE_BED,
|
||||
- Material.LIGHT_GRAY_BED,
|
||||
- Material.LIME_BED,
|
||||
- Material.MAGENTA_BED,
|
||||
- Material.ORANGE_BED,
|
||||
- Material.PINK_BED,
|
||||
- Material.PURPLE_BED,
|
||||
- Material.RED_BED,
|
||||
- Material.WHITE_BED,
|
||||
- Material.YELLOW_BED
|
||||
- ), CraftBed.class, CraftBed::new, BedBlockEntity::new
|
||||
- );
|
||||
-
|
||||
- register(
|
||||
- Arrays.asList(
|
||||
- Material.BEEHIVE,
|
||||
- Material.BEE_NEST
|
||||
- ), CraftBeehive.class, CraftBeehive::new, BeehiveBlockEntity::new
|
||||
- );
|
||||
-
|
||||
- register(
|
||||
- Arrays.asList(
|
||||
- Material.CAMPFIRE,
|
||||
- Material.SOUL_CAMPFIRE
|
||||
- ), CraftCampfire.class, CraftCampfire::new, CampfireBlockEntity::new
|
||||
- );
|
||||
-
|
||||
- register(Material.BARREL, CraftBarrel.class, CraftBarrel::new, BarrelBlockEntity::new);
|
||||
- register(Material.BEACON, CraftBeacon.class, CraftBeacon::new, BeaconBlockEntity::new);
|
||||
- register(Material.BELL, CraftBell.class, CraftBell::new, BellBlockEntity::new);
|
||||
- register(Material.BLAST_FURNACE, CraftBlastFurnace.class, CraftBlastFurnace::new, BlastFurnaceBlockEntity::new);
|
||||
- register(Material.BREWING_STAND, CraftBrewingStand.class, CraftBrewingStand::new, BrewingStandBlockEntity::new);
|
||||
- register(Material.CHEST, CraftChest.class, CraftChest::new, ChestBlockEntity::new);
|
||||
- register(Material.CHISELED_BOOKSHELF, CraftChiseledBookshelf.class, CraftChiseledBookshelf::new, ChiseledBookShelfBlockEntity::new);
|
||||
- register(Material.COMPARATOR, CraftComparator.class, CraftComparator::new, ComparatorBlockEntity::new);
|
||||
- register(Material.CONDUIT, CraftConduit.class, CraftConduit::new, ConduitBlockEntity::new);
|
||||
- register(Material.DAYLIGHT_DETECTOR, CraftDaylightDetector.class, CraftDaylightDetector::new, DaylightDetectorBlockEntity::new);
|
||||
- register(Material.DECORATED_POT, CraftDecoratedPot.class, CraftDecoratedPot::new, DecoratedPotBlockEntity::new);
|
||||
- register(Material.DISPENSER, CraftDispenser.class, CraftDispenser::new, DispenserBlockEntity::new);
|
||||
- register(Material.DROPPER, CraftDropper.class, CraftDropper::new, DropperBlockEntity::new);
|
||||
- register(Material.ENCHANTING_TABLE, CraftEnchantingTable.class, CraftEnchantingTable::new, EnchantmentTableBlockEntity::new);
|
||||
- register(Material.ENDER_CHEST, CraftEnderChest.class, CraftEnderChest::new, EnderChestBlockEntity::new);
|
||||
- register(Material.END_GATEWAY, CraftEndGateway.class, CraftEndGateway::new, TheEndGatewayBlockEntity::new);
|
||||
- register(Material.END_PORTAL, CraftEndPortal.class, CraftEndPortal::new, TheEndPortalBlockEntity::new);
|
||||
- register(Material.FURNACE, CraftFurnaceFurnace.class, CraftFurnaceFurnace::new, FurnaceBlockEntity::new);
|
||||
- register(Material.HOPPER, CraftHopper.class, CraftHopper::new, HopperBlockEntity::new);
|
||||
- register(Material.JIGSAW, CraftJigsaw.class, CraftJigsaw::new, JigsawBlockEntity::new);
|
||||
- register(Material.JUKEBOX, CraftJukebox.class, CraftJukebox::new, JukeboxBlockEntity::new);
|
||||
- register(Material.LECTERN, CraftLectern.class, CraftLectern::new, LecternBlockEntity::new);
|
||||
- register(Material.MOVING_PISTON, CraftMovingPiston.class, CraftMovingPiston::new, PistonMovingBlockEntity::new);
|
||||
- register(Material.SCULK_CATALYST, CraftSculkCatalyst.class, CraftSculkCatalyst::new, SculkCatalystBlockEntity::new);
|
||||
- register(Material.CALIBRATED_SCULK_SENSOR, CraftCalibratedSculkSensor.class, CraftCalibratedSculkSensor::new, CalibratedSculkSensorBlockEntity::new);
|
||||
- register(Material.SCULK_SENSOR, CraftSculkSensor.class, CraftSculkSensor::new, SculkSensorBlockEntity::new);
|
||||
- register(Material.SCULK_SHRIEKER, CraftSculkShrieker.class, CraftSculkShrieker::new, SculkShriekerBlockEntity::new);
|
||||
- register(Material.SMOKER, CraftSmoker.class, CraftSmoker::new, SmokerBlockEntity::new);
|
||||
- register(Material.SPAWNER, CraftCreatureSpawner.class, CraftCreatureSpawner::new, SpawnerBlockEntity::new);
|
||||
- register(Material.STRUCTURE_BLOCK, CraftStructureBlock.class, CraftStructureBlock::new, StructureBlockEntity::new);
|
||||
- register(Material.SUSPICIOUS_SAND, CraftSuspiciousSand.class, CraftSuspiciousSand::new, BrushableBlockEntity::new);
|
||||
- register(Material.SUSPICIOUS_GRAVEL, CraftBrushableBlock.class, CraftBrushableBlock::new, BrushableBlockEntity::new);
|
||||
- register(Material.TRAPPED_CHEST, CraftChest.class, CraftChest::new, TrappedChestBlockEntity::new);
|
||||
- register(Material.CRAFTER, CraftCrafter.class, CraftCrafter::new, CrafterBlockEntity::new);
|
||||
- register(Material.TRIAL_SPAWNER, CraftTrialSpawner.class, CraftTrialSpawner::new, TrialSpawnerBlockEntity::new);
|
||||
+ // Paper start - simplify
|
||||
+ register(BlockEntityType.SIGN, CraftSign.class, CraftSign::new);
|
||||
+ register(BlockEntityType.HANGING_SIGN, CraftHangingSign.class, CraftHangingSign::new);
|
||||
+ register(BlockEntityType.SKULL, CraftSkull.class, CraftSkull::new);
|
||||
+ register(BlockEntityType.COMMAND_BLOCK, CraftCommandBlock.class, CraftCommandBlock::new);
|
||||
+ register(BlockEntityType.BANNER, CraftBanner.class, CraftBanner::new);
|
||||
+ register(BlockEntityType.SHULKER_BOX, CraftShulkerBox.class, CraftShulkerBox::new);
|
||||
+ register(BlockEntityType.BED, CraftBed.class, CraftBed::new);
|
||||
+ register(BlockEntityType.BEEHIVE, CraftBeehive.class, CraftBeehive::new);
|
||||
+ register(BlockEntityType.CAMPFIRE, CraftCampfire.class, CraftCampfire::new);
|
||||
+ register(BlockEntityType.BARREL, CraftBarrel.class, CraftBarrel::new);
|
||||
+ register(BlockEntityType.BEACON, CraftBeacon.class, CraftBeacon::new);
|
||||
+ register(BlockEntityType.BELL, CraftBell.class, CraftBell::new);
|
||||
+ register(BlockEntityType.BLAST_FURNACE, CraftBlastFurnace.class, CraftBlastFurnace::new);
|
||||
+ register(BlockEntityType.BREWING_STAND, CraftBrewingStand.class, CraftBrewingStand::new);
|
||||
+ register(BlockEntityType.CHEST, CraftChest.class, CraftChest::new);
|
||||
+ register(BlockEntityType.CHISELED_BOOKSHELF, CraftChiseledBookshelf.class, CraftChiseledBookshelf::new);
|
||||
+ register(BlockEntityType.COMPARATOR, CraftComparator.class, CraftComparator::new);
|
||||
+ register(BlockEntityType.CONDUIT, CraftConduit.class, CraftConduit::new);
|
||||
+ register(BlockEntityType.DAYLIGHT_DETECTOR, CraftDaylightDetector.class, CraftDaylightDetector::new);
|
||||
+ register(BlockEntityType.DECORATED_POT, CraftDecoratedPot.class, CraftDecoratedPot::new);
|
||||
+ register(BlockEntityType.DISPENSER, CraftDispenser.class, CraftDispenser::new);
|
||||
+ register(BlockEntityType.DROPPER, CraftDropper.class, CraftDropper::new);
|
||||
+ register(BlockEntityType.ENCHANTING_TABLE, CraftEnchantingTable.class, CraftEnchantingTable::new);
|
||||
+ register(BlockEntityType.ENDER_CHEST, CraftEnderChest.class, CraftEnderChest::new);
|
||||
+ register(BlockEntityType.END_GATEWAY, CraftEndGateway.class, CraftEndGateway::new);
|
||||
+ register(BlockEntityType.END_PORTAL, CraftEndPortal.class, CraftEndPortal::new);
|
||||
+ register(BlockEntityType.FURNACE, CraftFurnaceFurnace.class, CraftFurnaceFurnace::new);
|
||||
+ register(BlockEntityType.HOPPER, CraftHopper.class, CraftHopper::new);
|
||||
+ register(BlockEntityType.JIGSAW, CraftJigsaw.class, CraftJigsaw::new);
|
||||
+ register(BlockEntityType.JUKEBOX, CraftJukebox.class, CraftJukebox::new);
|
||||
+ register(BlockEntityType.LECTERN, CraftLectern.class, CraftLectern::new);
|
||||
+ register(BlockEntityType.PISTON, CraftMovingPiston.class, CraftMovingPiston::new);
|
||||
+ register(BlockEntityType.SCULK_CATALYST, CraftSculkCatalyst.class, CraftSculkCatalyst::new);
|
||||
+ register(BlockEntityType.SCULK_SENSOR, CraftSculkSensor.class, CraftSculkSensor::new);
|
||||
+ register(BlockEntityType.SCULK_SHRIEKER, CraftSculkShrieker.class, CraftSculkShrieker::new);
|
||||
+ register(BlockEntityType.CALIBRATED_SCULK_SENSOR, CraftCalibratedSculkSensor.class, CraftCalibratedSculkSensor::new);
|
||||
+ register(BlockEntityType.SMOKER, CraftSmoker.class, CraftSmoker::new);
|
||||
+ register(BlockEntityType.MOB_SPAWNER, CraftCreatureSpawner.class, CraftCreatureSpawner::new);
|
||||
+ register(BlockEntityType.STRUCTURE_BLOCK, CraftStructureBlock.class, CraftStructureBlock::new);
|
||||
+ register(BlockEntityType.BRUSHABLE_BLOCK, CraftBrushableBlock.class, CraftBrushableBlock::new); // note: spigot still uses CraftSuspiciousSand impl for that block type
|
||||
+ register(BlockEntityType.TRAPPED_CHEST, CraftChest.class, CraftChest::new);
|
||||
+ register(BlockEntityType.CRAFTER, CraftCrafter.class, CraftCrafter::new);
|
||||
+ register(BlockEntityType.TRIAL_SPAWNER, CraftTrialSpawner.class, CraftTrialSpawner::new);
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
private static void register(Material blockType, BlockStateFactory<?> factory) {
|
||||
@@ -342,30 +180,33 @@ public final class CraftBlockStates {
|
||||
}
|
||||
|
||||
private static <T extends BlockEntity, B extends CraftBlockEntityState<T>> void register(
|
||||
- Material blockType,
|
||||
- Class<B> blockStateType,
|
||||
- BiFunction<World, T, B> blockStateConstructor,
|
||||
- BiFunction<BlockPos, net.minecraft.world.level.block.state.BlockState, T> tileEntityConstructor
|
||||
- ) {
|
||||
- CraftBlockStates.register(Collections.singletonList(blockType), blockStateType, blockStateConstructor, tileEntityConstructor);
|
||||
- }
|
||||
-
|
||||
- private static <T extends BlockEntity, B extends CraftBlockEntityState<T>> void register(
|
||||
- List<Material> blockTypes,
|
||||
+ net.minecraft.world.level.block.entity.BlockEntityType<? extends T> blockEntityType, // Paper
|
||||
Class<B> blockStateType,
|
||||
- BiFunction<World, T, B> blockStateConstructor,
|
||||
- BiFunction<BlockPos, net.minecraft.world.level.block.state.BlockState, T> tileEntityConstructor
|
||||
+ BiFunction<World, T, B> blockStateConstructor // Paper
|
||||
) {
|
||||
- BlockStateFactory<B> factory = new BlockEntityStateFactory<>(blockStateType, blockStateConstructor, tileEntityConstructor);
|
||||
- for (Material blockType : blockTypes) {
|
||||
- CraftBlockStates.register(blockType, factory);
|
||||
+ // Paper start
|
||||
+ BlockStateFactory<B> factory = new BlockEntityStateFactory<>(blockStateType, blockStateConstructor, blockEntityType::create);
|
||||
+ for (net.minecraft.world.level.block.Block block : blockEntityType.validBlocks) {
|
||||
+ CraftBlockStates.register(CraftBlockType.minecraftToBukkit(block), factory);
|
||||
}
|
||||
+ CraftBlockStates.register(blockEntityType, factory);
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
private static BlockStateFactory<?> getFactory(Material material) {
|
||||
return CraftBlockStates.FACTORIES.getOrDefault(material, CraftBlockStates.DEFAULT_FACTORY);
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ private static BlockStateFactory<?> getFactory(Material material, BlockEntityType<?> type) {
|
||||
+ if (type != null) {
|
||||
+ return CraftBlockStates.FACTORIES_BY_BLOCK_ENTITY_TYPE.getOrDefault(type, getFactory(material));
|
||||
+ } else {
|
||||
+ return getFactory(material);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
public static Class<? extends CraftBlockState> getBlockStateType(Material material) {
|
||||
Preconditions.checkNotNull(material, "material is null");
|
||||
return CraftBlockStates.getFactory(material).blockStateType;
|
||||
@@ -381,6 +222,13 @@ public final class CraftBlockStates {
|
||||
return null;
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ public static Class<? extends CraftBlockState> getBlockStateType(BlockEntityType<?> blockEntityType) {
|
||||
+ Preconditions.checkNotNull(blockEntityType, "blockEntityType is null");
|
||||
+ return CraftBlockStates.getFactory(null, blockEntityType).blockStateType;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
public static BlockState getBlockState(Block block) {
|
||||
// Paper start
|
||||
return CraftBlockStates.getBlockState(block, true);
|
||||
@@ -438,7 +286,7 @@ public final class CraftBlockStates {
|
||||
if (world != null && tileEntity == null && CraftBlockStates.isTileEntityOptional(material)) {
|
||||
factory = CraftBlockStates.DEFAULT_FACTORY;
|
||||
} else {
|
||||
- factory = CraftBlockStates.getFactory(material);
|
||||
+ factory = CraftBlockStates.getFactory(material, tileEntity != null ? tileEntity.getType() : null); // Paper
|
||||
}
|
||||
return factory.createBlockState(world, blockPosition, blockData, tileEntity);
|
||||
}
|
||||
diff --git a/src/test/java/org/bukkit/craftbukkit/block/BlockStateTest.java b/src/test/java/org/bukkit/craftbukkit/block/BlockStateTest.java
|
||||
index 81d4c8867ebcba1b805be1828e0a6a476963a855..9ff1a8068533ba5fc2fb43188d9a5c544a907618 100644
|
||||
--- a/src/test/java/org/bukkit/craftbukkit/block/BlockStateTest.java
|
||||
+++ b/src/test/java/org/bukkit/craftbukkit/block/BlockStateTest.java
|
||||
@@ -7,6 +7,7 @@ import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.EntityBlock;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
+import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.support.AbstractTestingBase;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -41,4 +42,13 @@ public class BlockStateTest extends AbstractTestingBase {
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ @Test
|
||||
+ public void testBlockEntityTypes() {
|
||||
+ for (var blockEntityType : BuiltInRegistries.BLOCK_ENTITY_TYPE) {
|
||||
+ org.junit.jupiter.api.Assertions.assertNotNull(CraftBlockStates.getBlockStateType(blockEntityType));
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue