patches and patches
This commit is contained in:
parent
79f1d1a078
commit
41a5f14f9e
34 changed files with 231 additions and 261 deletions
30
patches/server/0282-Reset-players-airTicks-on-respawn.patch
Normal file
30
patches/server/0282-Reset-players-airTicks-on-respawn.patch
Normal file
|
@ -0,0 +1,30 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: GreenMeanie <GreenMeanieMC@gmail.com>
|
||||
Date: Sat, 20 Oct 2018 22:34:02 -0400
|
||||
Subject: [PATCH] Reset players airTicks on respawn
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index b2324b53b3cec3e577a8ec8c45b113c232d220a6..5eb37fb1ae861940839fe6815b57111812d6b3ec 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -2210,6 +2210,7 @@ public class ServerPlayer extends Player {
|
||||
}
|
||||
|
||||
this.setHealth(this.getMaxHealth());
|
||||
+ this.setAirSupply(this.getMaxAirTicks()); // Paper
|
||||
this.remainingFireTicks = 0;
|
||||
this.fallDistance = 0;
|
||||
this.foodData = new FoodData(this);
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index 0974781e2f7fc541eaf397de033fb12b87dbf8ba..c3bbe8429ee792b881953c5894a55505cdba63d3 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -2585,6 +2585,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
|
||||
|
||||
}
|
||||
|
||||
+ public final int getMaxAirTicks() { return getMaxAirSupply(); } // Paper - OBFHELPER
|
||||
public int getMaxAirSupply() {
|
||||
return 300;
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 23 Oct 2018 20:25:05 -0400
|
||||
Subject: [PATCH] Don't sleep after profile lookups if not needed
|
||||
|
||||
Mojang was sleeping even if we had no more requests to go after
|
||||
the current one finished, resulting in 100ms lost per profile lookup
|
||||
|
||||
diff --git a/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java b/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java
|
||||
index a3ab666b5fa89aad7ee167d9aeff2f62019a4a78..8e182fdd69dba6e1c52e2f6a893534d77fb3bfaa 100644
|
||||
--- a/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java
|
||||
+++ b/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java
|
||||
@@ -43,6 +43,7 @@ public class YggdrasilGameProfileRepository implements GameProfileRepository {
|
||||
}
|
||||
|
||||
final int page = 0;
|
||||
+ boolean hasRequested = false; // Paper
|
||||
|
||||
for (final List<String> request : Iterables.partition(criteria, ENTRIES_PER_PAGE)) {
|
||||
int failCount = 0;
|
||||
@@ -68,6 +69,12 @@ public class YggdrasilGameProfileRepository implements GameProfileRepository {
|
||||
LOGGER.debug("Couldn't find profile {}", name);
|
||||
callback.onProfileLookupFailed(new GameProfile(null, name), new ProfileNotFoundException("Server did not find the requested profile"));
|
||||
}
|
||||
+ // Paper start
|
||||
+ if (!hasRequested) {
|
||||
+ hasRequested = true;
|
||||
+ continue;
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
try {
|
||||
Thread.sleep(DELAY_BETWEEN_PAGES);
|
|
@ -0,0 +1,109 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 23 Oct 2018 23:14:38 -0400
|
||||
Subject: [PATCH] Improve Server Thread Pool and Thread Priorities
|
||||
|
||||
Use a simple executor since Fork join is a much more complex pool
|
||||
type and we are not using its capabilities.
|
||||
|
||||
Set thread priorities so main thread has above normal priority over
|
||||
server threads
|
||||
|
||||
Allow usage of a single thread executor by not using ForkJoin so single core CPU's.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java
|
||||
index 6f29d1fc437764a75d592ccb0c0ddc0593a89967..99d52a9643efe38b449b59b6aac81c5b20ed9477 100644
|
||||
--- a/src/main/java/net/minecraft/Util.java
|
||||
+++ b/src/main/java/net/minecraft/Util.java
|
||||
@@ -56,7 +56,7 @@ import java.util.stream.Stream;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.Bootstrap;
|
||||
-import net.minecraft.util.Mth;
|
||||
+import net.minecraft.server.ServerWorkerThread;
|
||||
import net.minecraft.util.datafix.DataFixers;
|
||||
import net.minecraft.world.level.block.state.properties.Property;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
@@ -65,8 +65,8 @@ import org.apache.logging.log4j.Logger;
|
||||
|
||||
public class Util {
|
||||
private static final AtomicInteger WORKER_COUNT = new AtomicInteger(1);
|
||||
- private static final ExecutorService BOOTSTRAP_EXECUTOR = makeExecutor("Bootstrap");
|
||||
- private static final ExecutorService BACKGROUND_EXECUTOR = makeExecutor("Main");
|
||||
+ private static final ExecutorService BOOTSTRAP_EXECUTOR = makeExecutor("Bootstrap", -2); // Paper - add -2 priority
|
||||
+ private static final ExecutorService BACKGROUND_EXECUTOR = makeExecutor("Main", -1); // Paper - add -1 priority
|
||||
private static final ExecutorService IO_POOL = makeIoExecutor();
|
||||
public static LongSupplier timeSource = System::nanoTime;
|
||||
public static final UUID NIL_UUID = new UUID(0L, 0L);
|
||||
@@ -101,14 +101,18 @@ public class Util {
|
||||
return Instant.now().toEpochMilli();
|
||||
}
|
||||
|
||||
- private static ExecutorService makeExecutor(String name) {
|
||||
- int i = Mth.clamp(Runtime.getRuntime().availableProcessors() - 1, 1, 7);
|
||||
+ private static ExecutorService makeExecutor(String s, int priorityModifier) { // Paper - add priority
|
||||
+ // Paper start - use simpler thread pool that allows 1 thread
|
||||
+ int i = Math.min(8, Math.max(Runtime.getRuntime().availableProcessors() - 2, 1));
|
||||
+ i = Integer.getInteger("Paper.WorkerThreadCount", i);
|
||||
ExecutorService executorService;
|
||||
+
|
||||
if (i <= 0) {
|
||||
executorService = MoreExecutors.newDirectExecutorService();
|
||||
} else {
|
||||
- executorService = new ForkJoinPool(i, (forkJoinPool) -> {
|
||||
- ForkJoinWorkerThread forkJoinWorkerThread = new ForkJoinWorkerThread(forkJoinPool) {
|
||||
+ executorService = new java.util.concurrent.ThreadPoolExecutor(i, i,0L, TimeUnit.MILLISECONDS, new java.util.concurrent.LinkedBlockingQueue<Runnable>(), target -> new ServerWorkerThread(target, s, priorityModifier));
|
||||
+ }
|
||||
+ /*
|
||||
@Override
|
||||
protected void onTermination(Throwable throwable) {
|
||||
if (throwable != null) {
|
||||
@@ -124,6 +128,7 @@ public class Util {
|
||||
return forkJoinWorkerThread;
|
||||
}, Util::onThreadException, true);
|
||||
}
|
||||
+ }*/ // Paper end
|
||||
|
||||
return executorService;
|
||||
}
|
||||
@@ -180,7 +185,7 @@ public class Util {
|
||||
throw t instanceof RuntimeException ? (RuntimeException)t : new RuntimeException(t);
|
||||
}
|
||||
|
||||
- private static void onThreadException(Thread thread, Throwable t) {
|
||||
+ public static void onThreadException(Thread thread, Throwable t) { // Paper - make public
|
||||
pauseInIde(t);
|
||||
if (t instanceof CompletionException) {
|
||||
t = t.getCause();
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 24fc2eb3ee067a4164db166aa3e07ecbb426bbba..a302d232da3fbaa2cb3e1903cfd096d404847c54 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -318,6 +318,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
S s0 = serverFactory.apply(thread); // CraftBukkit - decompile error
|
||||
|
||||
atomicreference.set(s0);
|
||||
+ thread.setPriority(Thread.NORM_PRIORITY+2); // Paper - boost priority
|
||||
thread.start();
|
||||
return s0;
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/ServerWorkerThread.java b/src/main/java/net/minecraft/server/ServerWorkerThread.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..480129f430da33157342becb9d3b010f9f7c5edd
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/net/minecraft/server/ServerWorkerThread.java
|
||||
@@ -0,0 +1,14 @@
|
||||
+package net.minecraft.server;
|
||||
+
|
||||
+import java.util.concurrent.atomic.AtomicInteger;
|
||||
+import net.minecraft.Util;
|
||||
+
|
||||
+public class ServerWorkerThread extends Thread {
|
||||
+ private static final AtomicInteger threadId = new AtomicInteger(1);
|
||||
+ public ServerWorkerThread(Runnable target, String poolName, int prioritityModifier) {
|
||||
+ super(target, "Worker-" + poolName + "-" + threadId.getAndIncrement());
|
||||
+ setPriority(Thread.NORM_PRIORITY+prioritityModifier); // Deprioritize over main
|
||||
+ this.setDaemon(true);
|
||||
+ this.setUncaughtExceptionHandler(Util::onThreadException);
|
||||
+ }
|
||||
+}
|
42
patches/server/0285-Optimize-World-Time-Updates.patch
Normal file
42
patches/server/0285-Optimize-World-Time-Updates.patch
Normal file
|
@ -0,0 +1,42 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Fri, 2 Nov 2018 23:11:51 -0400
|
||||
Subject: [PATCH] Optimize World Time Updates
|
||||
|
||||
Splits time updates into incremental updates as well as does
|
||||
the updates per world, so that we can re-use the same packet
|
||||
object for every player unless they have per-player time enabled.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index a302d232da3fbaa2cb3e1903cfd096d404847c54..a1c65ea148692e50dbc466d87dae5198e0b6a51f 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1387,12 +1387,24 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
|
||||
MinecraftTimings.timeUpdateTimer.startTiming(); // Spigot // Paper
|
||||
// Send time updates to everyone, it will get the right time from the world the player is in.
|
||||
- if (this.tickCount % 20 == 0) {
|
||||
- for (int i = 0; i < this.getPlayerList().players.size(); ++i) {
|
||||
- ServerPlayer entityplayer = (ServerPlayer) this.getPlayerList().players.get(i);
|
||||
- entityplayer.connection.send(new ClientboundSetTimePacket(entityplayer.level.getGameTime(), entityplayer.getPlayerTime(), entityplayer.level.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT))); // Add support for per player time
|
||||
+ // Paper start - optimize time updates
|
||||
+ for (final ServerLevel world : this.getAllLevels()) {
|
||||
+ final boolean doDaylight = world.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT);
|
||||
+ final long dayTime = world.getDayTime();
|
||||
+ long worldTime = world.getGameTime();
|
||||
+ final ClientboundSetTimePacket worldPacket = new ClientboundSetTimePacket(worldTime, dayTime, doDaylight);
|
||||
+ for (Player entityhuman : world.players()) {
|
||||
+ if (!(entityhuman instanceof ServerPlayer) || (tickCount + entityhuman.getId()) % 20 != 0) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ ServerPlayer entityplayer = (ServerPlayer) entityhuman;
|
||||
+ long playerTime = entityplayer.getPlayerTime();
|
||||
+ ClientboundSetTimePacket packet = (playerTime == dayTime) ? worldPacket :
|
||||
+ new ClientboundSetTimePacket(worldTime, playerTime, doDaylight);
|
||||
+ entityplayer.connection.send(packet); // Add support for per player time
|
||||
}
|
||||
}
|
||||
+ // Paper end
|
||||
MinecraftTimings.timeUpdateTimer.stopTiming(); // Spigot // Paper
|
||||
|
||||
while (iterator.hasNext()) {
|
|
@ -0,0 +1,46 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Mon, 5 Nov 2018 04:23:51 +0000
|
||||
Subject: [PATCH] Restore custom InventoryHolder support
|
||||
|
||||
Upstream removed the ability to consistently use a custom InventoryHolder,
|
||||
However, the implementation does not use an InventoryHolder in any form
|
||||
outside of custom inventories.
|
||||
|
||||
We can take that knowledge and apply some expected behavior, if we're given
|
||||
an inventory holder, we should use it and return a custom inventory with the
|
||||
holder, otherwise, create an inventory backed by the intended inventory, as
|
||||
per upstream behavior.
|
||||
|
||||
This provides a "best of both worlds" scenario: plugins with InventoryHolder's
|
||||
will always work as intended in the past, those without will create implementation
|
||||
based inventories.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java
|
||||
index 0899afd175f969da0df9371d96d3b5e1de4c8533..fc307213a4bc9675c6011a81e4e06cd23a22926d 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java
|
||||
@@ -40,6 +40,11 @@ public final class CraftInventoryCreator {
|
||||
}
|
||||
|
||||
public Inventory createInventory(InventoryHolder holder, InventoryType type) {
|
||||
+ // Paper start
|
||||
+ if (holder != null) {
|
||||
+ return this.DEFAULT_CONVERTER.createInventory(holder, type);
|
||||
+ }
|
||||
+ //noinspection ConstantConditions // Paper end
|
||||
return this.converterMap.get(type).createInventory(holder, type);
|
||||
}
|
||||
|
||||
@@ -55,6 +60,11 @@ public final class CraftInventoryCreator {
|
||||
// Paper end
|
||||
|
||||
public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) {
|
||||
+ // Paper start
|
||||
+ if (holder != null) {
|
||||
+ return DEFAULT_CONVERTER.createInventory(holder, type, title);
|
||||
+ }
|
||||
+ //noinspection ConstantConditions // Paper end
|
||||
return this.converterMap.get(type).createInventory(holder, type, title);
|
||||
}
|
||||
|
24
patches/server/0287-Use-Vanilla-Minecart-Speeds.patch
Normal file
24
patches/server/0287-Use-Vanilla-Minecart-Speeds.patch
Normal file
|
@ -0,0 +1,24 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Thu, 8 Nov 2018 21:33:09 -0500
|
||||
Subject: [PATCH] Use Vanilla Minecart Speeds
|
||||
|
||||
CraftBukkit changed the values on flying speed, restore back to vanilla
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java
|
||||
index 1963a47d8b5471aadc6a054854025e270da15f8b..fa889f93a5c6782957bdbf803915cb5e80e05f3e 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java
|
||||
@@ -105,9 +105,9 @@ public abstract class AbstractMinecart extends Entity {
|
||||
private double derailedX = 0.5;
|
||||
private double derailedY = 0.5;
|
||||
private double derailedZ = 0.5;
|
||||
- private double flyingX = 0.95;
|
||||
- private double flyingY = 0.95;
|
||||
- private double flyingZ = 0.95;
|
||||
+ private double flyingX = 0.949999988079071D; // Paper - restore vanilla precision
|
||||
+ private double flyingY = 0.949999988079071D; // Paper - restore vanilla precision
|
||||
+ private double flyingZ = 0.949999988079071D; // Paper - restore vanilla precision
|
||||
public double maxSpeed = 0.4D;
|
||||
// CraftBukkit end
|
||||
|
25
patches/server/0288-Fix-SpongeAbsortEvent-handling.patch
Normal file
25
patches/server/0288-Fix-SpongeAbsortEvent-handling.patch
Normal file
|
@ -0,0 +1,25 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Sat, 10 Nov 2018 05:15:21 +0000
|
||||
Subject: [PATCH] Fix SpongeAbsortEvent handling
|
||||
|
||||
Only process drops when the block is actually going to be removed
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/SpongeBlock.java b/src/main/java/net/minecraft/world/level/block/SpongeBlock.java
|
||||
index b8ae2000a44469245c6ba3cda0c0e87b07156b06..1ef8eadd4e59f2e5d2bbd84f6f9bcf37b59db5bd 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/SpongeBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/SpongeBlock.java
|
||||
@@ -130,8 +130,11 @@ public class SpongeBlock extends Block {
|
||||
// NOP
|
||||
} else if (material == Material.WATER_PLANT || material == Material.REPLACEABLE_WATER_PLANT) {
|
||||
BlockEntity tileentity = iblockdata.hasBlockEntity() ? world.getBlockEntity(blockposition2) : null;
|
||||
-
|
||||
- dropResources(iblockdata, world, blockposition2, tileentity);
|
||||
+ // Paper start
|
||||
+ if (block.getHandle().getMaterial() == Material.AIR) {
|
||||
+ dropResources(iblockdata, world, blockposition2, tileentity);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
}
|
||||
world.setBlock(blockposition2, block.getHandle(), block.getFlag());
|
|
@ -0,0 +1,68 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Sun, 11 Nov 2018 21:01:09 +0000
|
||||
Subject: [PATCH] Don't allow digging into unloaded chunks
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
index 315dad4789f5f2582ee9b4fc176affd1f57537ef..f4a056185990181e486f452960159a5287947382 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
@@ -119,8 +119,8 @@ public class ServerPlayerGameMode {
|
||||
BlockState iblockdata;
|
||||
|
||||
if (this.hasDelayedDestroy) {
|
||||
- iblockdata = this.level.getBlockState(this.delayedDestroyPos);
|
||||
- if (iblockdata.isAir()) {
|
||||
+ iblockdata = this.level.getTypeIfLoaded(this.delayedDestroyPos); // Paper
|
||||
+ if (iblockdata == null || iblockdata.isAir()) { // Paper
|
||||
this.hasDelayedDestroy = false;
|
||||
} else {
|
||||
float f = this.incrementDestroyProgress(iblockdata, this.delayedDestroyPos, this.delayedTickStart);
|
||||
@@ -131,7 +131,13 @@ public class ServerPlayerGameMode {
|
||||
}
|
||||
}
|
||||
} else if (this.isDestroyingBlock) {
|
||||
- iblockdata = this.level.getBlockState(this.destroyPos);
|
||||
+ // Paper start - don't want to do same logic as above, return instead
|
||||
+ iblockdata = this.level.getTypeIfLoaded(this.destroyPos);
|
||||
+ if (iblockdata == null) {
|
||||
+ this.isDestroyingBlock = false;
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end
|
||||
if (iblockdata.isAir()) {
|
||||
this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1);
|
||||
this.lastSentState = -1;
|
||||
@@ -295,10 +301,12 @@ public class ServerPlayerGameMode {
|
||||
this.player.connection.send(new ClientboundBlockBreakAckPacket(pos, this.level.getBlockState(pos), action, true, "stopped destroying"));
|
||||
} else if (action == ServerboundPlayerActionPacket.Action.ABORT_DESTROY_BLOCK) {
|
||||
this.isDestroyingBlock = false;
|
||||
- if (!Objects.equals(this.destroyPos, pos)) {
|
||||
+ if (!Objects.equals(this.destroyPos, pos) && !BlockPos.ZERO.equals(this.destroyPos)) {
|
||||
ServerPlayerGameMode.LOGGER.debug("Mismatch in destroy block pos: {} {}", this.destroyPos, pos); // CraftBukkit - SPIGOT-5457 sent by client when interact event cancelled
|
||||
- this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1);
|
||||
- this.player.connection.send(new ClientboundBlockBreakAckPacket(this.destroyPos, this.level.getBlockState(this.destroyPos), action, true, "aborted mismatched destroying"));
|
||||
+ BlockState type = this.level.getTypeIfLoaded(this.destroyPos); // Paper - don't load unloaded chunks for stale records here
|
||||
+ if (type != null) this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1); // Paper
|
||||
+ if (type != null) this.player.connection.send(new ClientboundBlockBreakAckPacket(this.destroyPos, type, action, true, "aborted mismatched destroying")); // Paper
|
||||
+ this.destroyPos = BlockPos.ZERO; // Paper
|
||||
}
|
||||
|
||||
this.level.destroyBlockProgress(this.player.getId(), pos, -1);
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 5f4718fa42be0ade1a40c0472efbbd0c65f061a7..8b716c625c363d7143fe6fbc26d3d674d62a5833 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -1558,6 +1558,11 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
|
||||
case START_DESTROY_BLOCK:
|
||||
case ABORT_DESTROY_BLOCK:
|
||||
case STOP_DESTROY_BLOCK:
|
||||
+ // Paper start - Don't allow digging in unloaded chunks
|
||||
+ if (this.player.level.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) == null) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end - Don't allow digging in unloaded chunks
|
||||
this.player.gameMode.handleBlockBreakAction(blockposition, packetplayinblockdig_enumplayerdigtype, packet.getDirection(), this.player.level.getMaxBuildHeight());
|
||||
return;
|
||||
default:
|
|
@ -0,0 +1,47 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Sun, 18 Nov 2018 19:49:56 +0000
|
||||
Subject: [PATCH] Make the default permission message configurable
|
||||
|
||||
TODO: Change the message in PaperCommand
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
index 9768c591e72ce2ef5fdb43e2fc63378c57773216..11d628869a9a6eda8bf21a4f213ff23ad753b18e 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
@@ -20,6 +20,7 @@ import java.util.regex.Pattern;
|
||||
import com.google.common.collect.Lists;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import org.bukkit.Bukkit;
|
||||
+import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
@@ -288,6 +289,11 @@ public class PaperConfig {
|
||||
connectionThrottleKickMessage = getString("messages.kick.connection-throttle", connectionThrottleKickMessage);
|
||||
}
|
||||
|
||||
+ public static String noPermissionMessage = "&cI'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is in error.";
|
||||
+ private static void noPermissionMessage() {
|
||||
+ noPermissionMessage = ChatColor.translateAlternateColorCodes('&', getString("messages.no-permission", noPermissionMessage));
|
||||
+ }
|
||||
+
|
||||
private static void savePlayerData() {
|
||||
Object val = config.get("settings.save-player-data");
|
||||
if (val instanceof Boolean) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index 717ad1c24bbc882db8f76cfef7bf847c58914e5a..0448e6b4c512f512bda13f41f1feb58de02fc9d4 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -2341,6 +2341,11 @@ public final class CraftServer implements Server {
|
||||
return com.destroystokyo.paper.PaperConfig.suggestPlayersWhenNullTabCompletions;
|
||||
}
|
||||
|
||||
+ @Override
|
||||
+ public String getPermissionMessage() {
|
||||
+ return com.destroystokyo.paper.PaperConfig.noPermissionMessage;
|
||||
+ }
|
||||
+
|
||||
@Override
|
||||
public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nonnull UUID uuid) {
|
||||
return createProfile(uuid, null);
|
|
@ -0,0 +1,29 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 26 Nov 2018 19:21:58 -0500
|
||||
Subject: [PATCH] Prevent rayTrace from loading chunks
|
||||
|
||||
ray tracing into an unloaded chunk should be treated as a miss
|
||||
this saves a ton of lag for when AI tries to raytrace near unloaded chunks.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/BlockGetter.java b/src/main/java/net/minecraft/world/level/BlockGetter.java
|
||||
index e85e4a2dfceb0aa40e73b43a5e122a5906cac585..fe4dba491b586757a16aa36e62682f364daa2602 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/BlockGetter.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/BlockGetter.java
|
||||
@@ -75,7 +75,15 @@ public interface BlockGetter extends LevelHeightAccessor {
|
||||
|
||||
// CraftBukkit start - moved block handling into separate method for use by Block#rayTrace
|
||||
default BlockHitResult rayTraceBlock(ClipContext raytrace1, BlockPos blockposition) {
|
||||
- BlockState iblockdata = this.getBlockState(blockposition);
|
||||
+ // Paper start - Prevent raytrace from loading chunks
|
||||
+ BlockState iblockdata = this.getTypeIfLoaded(blockposition);
|
||||
+ if (iblockdata == null) {
|
||||
+ // copied the last function parameter (listed below)
|
||||
+ Vec3 vec3d = raytrace1.getFrom().subtract(raytrace1.getTo());
|
||||
+
|
||||
+ return BlockHitResult.miss(raytrace1.getTo(), Direction.getNearest(vec3d.x, vec3d.y, vec3d.z), new BlockPos(raytrace1.getTo()));
|
||||
+ }
|
||||
+ // Paper end
|
||||
FluidState fluid = this.getFluidState(blockposition);
|
||||
Vec3 vec3d = raytrace1.getFrom();
|
||||
Vec3 vec3d1 = raytrace1.getTo();
|
|
@ -0,0 +1,115 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 27 Nov 2018 21:18:06 -0500
|
||||
Subject: [PATCH] Handle Large Packets disconnecting client
|
||||
|
||||
If a players inventory is too big to send in a single packet,
|
||||
split the inventory set into multiple packets instead.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
|
||||
index 0c5c62be83223e20f216df84413b8c2438db81ff..8bbf13a7aea1142b3154a1c76837a98aa5ed431d 100644
|
||||
--- a/src/main/java/net/minecraft/network/Connection.java
|
||||
+++ b/src/main/java/net/minecraft/network/Connection.java
|
||||
@@ -120,6 +120,15 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
}
|
||||
|
||||
public void exceptionCaught(ChannelHandlerContext channelhandlercontext, Throwable throwable) {
|
||||
+ // Paper start
|
||||
+ if (throwable instanceof io.netty.handler.codec.EncoderException && throwable.getCause() instanceof PacketEncoder.PacketTooLargeException) {
|
||||
+ if (((PacketEncoder.PacketTooLargeException) throwable.getCause()).getPacket().packetTooLarge(this)) {
|
||||
+ return;
|
||||
+ } else {
|
||||
+ throwable = throwable.getCause();
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
if (throwable instanceof SkipPacketException) {
|
||||
Connection.LOGGER.debug("Skipping packet due to errors", throwable.getCause());
|
||||
} else {
|
||||
diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/java/net/minecraft/network/PacketEncoder.java
|
||||
index b8a0c0411fd2caab21672de7f3e721645b61a8ba..c0df136c408d7f001395291d8c80da5b4b54d462 100644
|
||||
--- a/src/main/java/net/minecraft/network/PacketEncoder.java
|
||||
+++ b/src/main/java/net/minecraft/network/PacketEncoder.java
|
||||
@@ -54,7 +54,31 @@ public class PacketEncoder extends MessageToByteEncoder<Packet<?>> {
|
||||
throw var9;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ int packetLength = friendlyByteBuf.readableBytes();
|
||||
+ if (packetLength > MAX_PACKET_SIZE) {
|
||||
+ throw new PacketTooLargeException(packet, packetLength);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ private static int MAX_PACKET_SIZE = 2097152;
|
||||
+
|
||||
+ public static class PacketTooLargeException extends RuntimeException {
|
||||
+ private final Packet<?> packet;
|
||||
+
|
||||
+ PacketTooLargeException(Packet<?> packet, int packetLength) {
|
||||
+ super("PacketTooLarge - " + packet.getClass().getSimpleName() + " is " + packetLength + ". Max is " + MAX_PACKET_SIZE);
|
||||
+ this.packet = packet;
|
||||
+ }
|
||||
+
|
||||
+ public Packet<?> getPacket() {
|
||||
+ return packet;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java
|
||||
index 10c1f2d8a92f848c3f2be9d1d06fd254978e6dcc..74bfe0d3942259c45702b099efdc4e101a4e3022 100644
|
||||
--- a/src/main/java/net/minecraft/network/protocol/Packet.java
|
||||
+++ b/src/main/java/net/minecraft/network/protocol/Packet.java
|
||||
@@ -8,6 +8,12 @@ public interface Packet<T extends PacketListener> {
|
||||
|
||||
void handle(T listener);
|
||||
|
||||
+ // Paper start
|
||||
+ default boolean packetTooLarge(net.minecraft.network.Connection manager) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
default boolean isSkippable() {
|
||||
return false;
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java
|
||||
index a27d46e90ad04c624d41f6cbededcd3121dfeee8..d5ca796408f975f4f002a5b385574d3516915507 100644
|
||||
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java
|
||||
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java
|
||||
@@ -10,6 +10,16 @@ public class ClientboundContainerSetContentPacket implements Packet<ClientGamePa
|
||||
private final int containerId;
|
||||
private final List<ItemStack> items;
|
||||
|
||||
+ //Paper start
|
||||
+ @Override
|
||||
+ public boolean packetTooLarge(net.minecraft.network.Connection manager) {
|
||||
+ for (int i = 0 ; i < this.items.size() ; i++) {
|
||||
+ manager.send(new ClientboundContainerSetSlotPacket(this.containerId, i, this.items.get(i)));
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
public ClientboundContainerSetContentPacket(int syncId, NonNullList<ItemStack> contents) {
|
||||
this.containerId = syncId;
|
||||
this.items = NonNullList.withSize(contents.size(), ItemStack.EMPTY);
|
||||
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java
|
||||
index 1451a98d69b185dd15a2d1d7681bcecb6a4f99c1..96626835fee3c0fdb452acacdc9f737ad90c08de 100644
|
||||
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java
|
||||
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java
|
||||
@@ -64,7 +64,7 @@ public class ClientboundLevelChunkPacket implements Packet<ClientGamePacketListe
|
||||
} else {
|
||||
this.biomes = buf.readVarIntArray(ChunkBiomeContainer.MAX_SIZE);
|
||||
int i = buf.readVarInt();
|
||||
- if (i > 2097152) {
|
||||
+ if (i > 2097152) { // Paper - diff on change - if this changes, update PacketEncoder
|
||||
throw new RuntimeException("Chunk Packet trying to allocate too much memory on read.");
|
||||
} else {
|
||||
this.buffer = new byte[i];
|
|
@ -0,0 +1,134 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Thu, 15 Nov 2018 13:38:37 +0000
|
||||
Subject: [PATCH] force entity dismount during teleportation
|
||||
|
||||
Entities must be dismounted before teleportation in order to avoid
|
||||
multiple issues in the server with regards to teleportation, shamefully,
|
||||
too many plugins rely on the events firing, which means that not firing
|
||||
these events caues more issues than it solves;
|
||||
|
||||
In order to counteract this, Entity dismount/exit vehicle events have
|
||||
been modified to supress cancellation (and has a method to allow plugins
|
||||
to check if this has been set), noting that cancellation will be silently
|
||||
surpressed given that plugins are not expecting this event to not be cancellable.
|
||||
|
||||
This is a far from ideal scenario, however: given the current state of this
|
||||
event and other alternatives causing issues elsewhere, I believe that
|
||||
this is going to be the best soultion all around.
|
||||
|
||||
Improvements/suggestions welcome!
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 5eb37fb1ae861940839fe6815b57111812d6b3ec..963a3c159e912a39b98dfcb3fdb8c384765990d7 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -1299,11 +1299,13 @@ public class ServerPlayer extends Player {
|
||||
}
|
||||
}
|
||||
|
||||
- @Override
|
||||
- public void stopRiding() {
|
||||
+ // Paper start
|
||||
+ @Override public void stopRiding() { stopRiding(false); }
|
||||
+ @Override public void stopRiding(boolean suppressCancellation) {
|
||||
+ // paper end
|
||||
Entity entity = this.getVehicle();
|
||||
|
||||
- super.stopRiding();
|
||||
+ super.stopRiding(suppressCancellation); // Paper
|
||||
Entity entity1 = this.getVehicle();
|
||||
|
||||
if (entity1 != entity && this.connection != null) {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index c3bbe8429ee792b881953c5894a55505cdba63d3..8df9bd656374d0b43af378c61c1df7b951085b58 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -2212,12 +2212,15 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
|
||||
|
||||
}
|
||||
|
||||
- public void removeVehicle() {
|
||||
+ // Paper start
|
||||
+ public void removeVehicle() { stopRiding(false); }
|
||||
+ public void stopRiding(boolean suppressCancellation) {
|
||||
+ // Paper end
|
||||
if (this.vehicle != null) {
|
||||
Entity entity = this.vehicle;
|
||||
|
||||
this.vehicle = null;
|
||||
- if (!entity.removePassenger(this)) this.vehicle = entity; // CraftBukkit
|
||||
+ if (!entity.removePassenger(this, suppressCancellation)) this.vehicle = entity; // CraftBukkit // Paper
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2280,7 +2283,10 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
|
||||
return true; // CraftBukkit
|
||||
}
|
||||
|
||||
- protected boolean removePassenger(Entity entity) { // CraftBukkit
|
||||
+ // Paper start
|
||||
+ protected boolean removePassenger(Entity entity) { return removePassenger(entity, false);}
|
||||
+ protected boolean removePassenger(Entity entity, boolean suppressCancellation) { // CraftBukkit
|
||||
+ // Paper end
|
||||
if (entity.getVehicle() == this) {
|
||||
throw new IllegalStateException("Use x.stopRiding(y), not y.removePassenger(x)");
|
||||
} else {
|
||||
@@ -2290,7 +2296,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
|
||||
if (this.getBukkitEntity() instanceof Vehicle && entity.getBukkitEntity() instanceof LivingEntity) {
|
||||
VehicleExitEvent event = new VehicleExitEvent(
|
||||
(Vehicle) this.getBukkitEntity(),
|
||||
- (LivingEntity) entity.getBukkitEntity()
|
||||
+ (LivingEntity) entity.getBukkitEntity(), !suppressCancellation // Paper
|
||||
);
|
||||
// Suppress during worldgen
|
||||
if (this.valid) {
|
||||
@@ -2304,7 +2310,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
|
||||
}
|
||||
// CraftBukkit end
|
||||
// Spigot start
|
||||
- org.spigotmc.event.entity.EntityDismountEvent event = new org.spigotmc.event.entity.EntityDismountEvent(entity.getBukkitEntity(), this.getBukkitEntity());
|
||||
+ org.spigotmc.event.entity.EntityDismountEvent event = new org.spigotmc.event.entity.EntityDismountEvent(entity.getBukkitEntity(), this.getBukkitEntity(), !suppressCancellation); // Paper
|
||||
// Suppress during worldgen
|
||||
if (this.valid) {
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index 8333d604fce05349455bf1779f3e5b0a980c4c16..1dabdba428c10e65b634b6e2036f993c4be186a7 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -3329,11 +3329,13 @@ public abstract class LivingEntity extends Entity {
|
||||
return ((Byte) this.entityData.get(LivingEntity.DATA_LIVING_ENTITY_FLAGS) & 4) != 0;
|
||||
}
|
||||
|
||||
- @Override
|
||||
- public void stopRiding() {
|
||||
+ // Paper start
|
||||
+ @Override public void stopRiding() { stopRiding(false); }
|
||||
+ @Override public void stopRiding(boolean suppressCancellation) {
|
||||
+ // Paper end
|
||||
Entity entity = this.getVehicle();
|
||||
|
||||
- super.stopRiding();
|
||||
+ super.stopRiding(suppressCancellation); // Paper - suppress
|
||||
if (entity != null && entity != this.getVehicle() && !this.level.isClientSide) {
|
||||
this.dismountVehicle(entity);
|
||||
}
|
||||
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 e0e33dd92b686939f622f0a7da0d5a971f43d0d6..4c9261c68518ab7429325f0366dfb2930663288c 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
@@ -1096,9 +1096,11 @@ public abstract class Player extends LivingEntity {
|
||||
return -0.35D;
|
||||
}
|
||||
|
||||
- @Override
|
||||
- public void removeVehicle() {
|
||||
- super.removeVehicle();
|
||||
+ // Paper start
|
||||
+ @Override public void removeVehicle() { stopRiding(false); }
|
||||
+ @Override public void stopRiding(boolean suppressCancellation) {
|
||||
+ // Paper end
|
||||
+ super.stopRiding(suppressCancellation); // Paper - suppress
|
||||
this.boardingCooldown = 0;
|
||||
}
|
||||
|
117
patches/server/0294-Add-more-Zombie-API.patch
Normal file
117
patches/server/0294-Add-more-Zombie-API.patch
Normal file
|
@ -0,0 +1,117 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Sun, 7 Oct 2018 04:29:59 -0500
|
||||
Subject: [PATCH] Add more Zombie API
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
|
||||
index 017d8de4d09f524aed2ee03af7ef79468503edf0..c60d9775230b2ff554eeb38136f8e7c32c47d8cf 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
|
||||
@@ -96,6 +96,7 @@ public class Zombie extends Monster {
|
||||
private int inWaterTime;
|
||||
public int conversionTime;
|
||||
private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field
|
||||
+ private boolean shouldBurnInDay = true; // Paper
|
||||
|
||||
public Zombie(EntityType<? extends Zombie> type, Level world) {
|
||||
super(type, world);
|
||||
@@ -264,6 +265,12 @@ public class Zombie extends Monster {
|
||||
super.aiStep();
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ public void stopDrowning() {
|
||||
+ this.conversionTime = -1;
|
||||
+ this.getEntityData().set(Zombie.DATA_DROWNED_CONVERSION_ID, false);
|
||||
+ }
|
||||
+ // Paper end
|
||||
public void startUnderWaterConversion(int ticksUntilWaterConversion) {
|
||||
this.lastTick = MinecraftServer.currentTick; // CraftBukkit
|
||||
this.conversionTime = ticksUntilWaterConversion;
|
||||
@@ -292,10 +299,17 @@ public class Zombie extends Monster {
|
||||
|
||||
}
|
||||
|
||||
+ public boolean isSunSensitivePublic() { return this.isSunSensitive(); } // Paper - public getter
|
||||
protected boolean isSunSensitive() {
|
||||
- return true;
|
||||
+ return this.shouldBurnInDay; // Paper - use api value instead
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ public void setShouldBurnInDay(boolean shouldBurnInDay) {
|
||||
+ this.shouldBurnInDay = shouldBurnInDay;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public boolean hurt(DamageSource source, float amount) {
|
||||
if (!super.hurt(source, amount)) {
|
||||
@@ -415,6 +429,7 @@ public class Zombie extends Monster {
|
||||
nbt.putBoolean("CanBreakDoors", this.canBreakDoors());
|
||||
nbt.putInt("InWaterTime", this.isInWater() ? this.inWaterTime : -1);
|
||||
nbt.putInt("DrownedConversionTime", this.isUnderWaterConverting() ? this.conversionTime : -1);
|
||||
+ nbt.putBoolean("Paper.ShouldBurnInDay", this.shouldBurnInDay); // Paper
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -426,6 +441,11 @@ public class Zombie extends Monster {
|
||||
if (nbt.contains("DrownedConversionTime", 99) && nbt.getInt("DrownedConversionTime") > -1) {
|
||||
this.startUnderWaterConversion(nbt.getInt("DrownedConversionTime"));
|
||||
}
|
||||
+ // Paper start
|
||||
+ if (nbt.contains("Paper.ShouldBurnInDay")) {
|
||||
+ this.shouldBurnInDay = nbt.getBoolean("Paper.ShouldBurnInDay");
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java
|
||||
index 2e643e92569512ac4e75c0ef2ee7aa4b688e7356..41b5059f6fde8a1afa8c70b983750854ac0207a6 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java
|
||||
@@ -93,6 +93,42 @@ public class CraftZombie extends CraftMonster implements Zombie {
|
||||
@Override
|
||||
public void setAgeLock(boolean b) {
|
||||
}
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public boolean isDrowning() {
|
||||
+ return getHandle().isUnderWaterConverting();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void startDrowning(int drownedConversionTime) {
|
||||
+ getHandle().startUnderWaterConversion(drownedConversionTime);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void stopDrowning() {
|
||||
+ getHandle().stopDrowning();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean shouldBurnInDay() {
|
||||
+ return getHandle().isSunSensitivePublic();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isArmsRaised() {
|
||||
+ return getHandle().isAggressive();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setArmsRaised(final boolean raised) {
|
||||
+ getHandle().setAggressive(raised);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setShouldBurnInDay(boolean shouldBurnInDay) {
|
||||
+ getHandle().setShouldBurnInDay(shouldBurnInDay);
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
@Override
|
||||
public boolean getAgeLock() {
|
82
patches/server/0295-Book-Size-Limits.patch
Normal file
82
patches/server/0295-Book-Size-Limits.patch
Normal file
|
@ -0,0 +1,82 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Fri, 16 Nov 2018 23:08:50 -0500
|
||||
Subject: [PATCH] Book Size Limits
|
||||
|
||||
Puts some limits on the size of books.
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
index 11d628869a9a6eda8bf21a4f213ff23ad753b18e..8bf4d2b8c38c02d6a5b2fea37113689a252f1571 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
@@ -347,6 +347,13 @@ public class PaperConfig {
|
||||
}
|
||||
}
|
||||
|
||||
+ public static int maxBookPageSize = 2560;
|
||||
+ public static double maxBookTotalSizeMultiplier = 0.98D;
|
||||
+ private static void maxBookSize() {
|
||||
+ maxBookPageSize = getInt("settings.book-size.page-max", maxBookPageSize);
|
||||
+ maxBookTotalSizeMultiplier = getDouble("settings.book-size.total-multiplier", maxBookTotalSizeMultiplier);
|
||||
+ }
|
||||
+
|
||||
public static boolean asyncChunks = false;
|
||||
private static void asyncChunks() {
|
||||
ConfigurationSection section;
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 8b716c625c363d7143fe6fbc26d3d674d62a5833..f1a8470d0b314c8fa5eade198cffc1f8cd5e6832 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -1002,6 +1002,52 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
|
||||
|
||||
@Override
|
||||
public void handleEditBook(ServerboundEditBookPacket packet) {
|
||||
+ // Paper start
|
||||
+ ItemStack testStack = packet.getBook();
|
||||
+ if (!this.cserver.isPrimaryThread() && !testStack.isEmpty() && testStack.getTag() != null) {
|
||||
+ ListTag pageList = testStack.getTag().getList("pages", 8);
|
||||
+ if (pageList.size() > 100) {
|
||||
+ ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send a book with too many pages");
|
||||
+ server.scheduleOnMain(() -> this.disconnect("Book too large!"));
|
||||
+ return;
|
||||
+ }
|
||||
+ long byteTotal = 0;
|
||||
+ int maxBookPageSize = com.destroystokyo.paper.PaperConfig.maxBookPageSize;
|
||||
+ double multiplier = Math.max(0.3D, Math.min(1D, com.destroystokyo.paper.PaperConfig.maxBookTotalSizeMultiplier));
|
||||
+ long byteAllowed = maxBookPageSize;
|
||||
+ for (int i = 0; i < pageList.size(); ++i) {
|
||||
+ String testString = pageList.getString(i);
|
||||
+ int byteLength = testString.getBytes(java.nio.charset.StandardCharsets.UTF_8).length;
|
||||
+ if (byteLength > 256 * 4) {
|
||||
+ ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send a book with with a page too large!");
|
||||
+ server.scheduleOnMain(() -> this.disconnect("Book too large!"));
|
||||
+ return;
|
||||
+ }
|
||||
+ byteTotal += byteLength;
|
||||
+ int length = testString.length();
|
||||
+ int multibytes = 0;
|
||||
+ if (byteLength != length) {
|
||||
+ for (char c : testString.toCharArray()) {
|
||||
+ if (c > 127) {
|
||||
+ multibytes++;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ byteAllowed += (maxBookPageSize * Math.min(1, Math.max(0.1D, (double) length / 255D))) * multiplier;
|
||||
+
|
||||
+ if (multibytes > 1) {
|
||||
+ // penalize MB
|
||||
+ byteAllowed -= multibytes;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (byteTotal > byteAllowed) {
|
||||
+ ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send too large of a book. Book Size: " + byteTotal + " - Allowed: "+ byteAllowed + " - Pages: " + pageList.size());
|
||||
+ server.scheduleOnMain(() -> this.disconnect("Book too large!"));
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
// CraftBukkit start
|
||||
if (this.lastBookTick + 20 > MinecraftServer.currentTick) {
|
||||
this.disconnect("Book edited too quickly!");
|
83
patches/server/0296-Add-PlayerConnectionCloseEvent.patch
Normal file
83
patches/server/0296-Add-PlayerConnectionCloseEvent.patch
Normal file
|
@ -0,0 +1,83 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Sun, 7 Oct 2018 12:05:28 -0700
|
||||
Subject: [PATCH] Add PlayerConnectionCloseEvent
|
||||
|
||||
This event is invoked when a player has disconnected. It is guaranteed that,
|
||||
if the server is in online-mode, that the provided uuid and username have been
|
||||
validated.
|
||||
|
||||
The event is invoked for players who have not yet logged into the world, whereas
|
||||
PlayerQuitEvent is only invoked on players who have logged into the world.
|
||||
|
||||
The event is invoked for players who have already logged into the world,
|
||||
although whether or not the player exists in the world at the time of
|
||||
firing is undefined. (That is, whether the plugin can retrieve a Player object
|
||||
using the event parameters is undefined). However, it is guaranteed that this
|
||||
event is invoked AFTER PlayerQuitEvent, if the player has already logged into
|
||||
the world.
|
||||
|
||||
This event is guaranteed to never fire unless AsyncPlayerPreLoginEvent has
|
||||
been called beforehand, and this event may not be called in parallel with
|
||||
AsyncPlayerPreLoginEvent for the same connection.
|
||||
|
||||
Cancelling the AsyncPlayerPreLoginEvent guarantees the corresponding
|
||||
PlayerConnectionCloseEvent is never called.
|
||||
|
||||
The event may be invoked asynchronously or synchronously. As it stands,
|
||||
it is never invoked asynchronously. However, plugins should check
|
||||
Event#isAsynchronous to be future-proof.
|
||||
|
||||
On purpose, the deprecated PlayerPreLoginEvent event is left out of the
|
||||
API spec for this event. Plugins should not be using that event, and
|
||||
how PlayerPreLoginEvent interacts with PlayerConnectionCloseEvent
|
||||
is undefined.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
|
||||
index 8bbf13a7aea1142b3154a1c76837a98aa5ed431d..9f0537799a3cae43fb120056b8fe805a4883cc4d 100644
|
||||
--- a/src/main/java/net/minecraft/network/Connection.java
|
||||
+++ b/src/main/java/net/minecraft/network/Connection.java
|
||||
@@ -418,6 +418,26 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
this.getPacketListener().onDisconnect(new TranslatableComponent("multiplayer.disconnect.generic"));
|
||||
}
|
||||
this.queue.clear(); // Free up packet queue.
|
||||
+ // Paper start - Add PlayerConnectionCloseEvent
|
||||
+ final PacketListener packetListener = this.getPacketListener();
|
||||
+ if (packetListener instanceof ServerGamePacketListenerImpl) {
|
||||
+ /* Player was logged in */
|
||||
+ final ServerGamePacketListenerImpl playerConnection = (ServerGamePacketListenerImpl) packetListener;
|
||||
+ new com.destroystokyo.paper.event.player.PlayerConnectionCloseEvent(playerConnection.player.getUUID(),
|
||||
+ playerConnection.player.getScoreboardName(), ((java.net.InetSocketAddress)address).getAddress(), false).callEvent();
|
||||
+ } else if (packetListener instanceof ServerLoginPacketListenerImpl) {
|
||||
+ /* Player is login stage */
|
||||
+ final ServerLoginPacketListenerImpl loginListener = (ServerLoginPacketListenerImpl) packetListener;
|
||||
+ switch (loginListener.getLoginState()) {
|
||||
+ case READY_TO_ACCEPT:
|
||||
+ case DELAY_ACCEPT:
|
||||
+ case ACCEPTED:
|
||||
+ final com.mojang.authlib.GameProfile profile = loginListener.getGameProfile(); /* Should be non-null at this stage */
|
||||
+ new com.destroystokyo.paper.event.player.PlayerConnectionCloseEvent(profile.getId(), profile.getName(),
|
||||
+ ((java.net.InetSocketAddress)address).getAddress(), false).callEvent();
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
index a196ab2510a1c302ef1c946400c1a7c07619994a..abbd1926107b49f9b7c8097419ba19baf6f6b7d3 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
@@ -56,10 +56,10 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener
|
||||
private final byte[] nonce = new byte[4];
|
||||
final MinecraftServer server;
|
||||
public final Connection connection;
|
||||
- ServerLoginPacketListenerImpl.State state;
|
||||
+ ServerLoginPacketListenerImpl.State state; public final ServerLoginPacketListenerImpl.State getLoginState() { return this.state; }; // Paper - OBFHELPER
|
||||
private int tick;
|
||||
@Nullable
|
||||
- GameProfile gameProfile;
|
||||
+ GameProfile gameProfile; private void setGameProfile(final GameProfile profile) { this.gameProfile = profile; } public GameProfile getGameProfile() { return this.gameProfile; } // Paper - OBFHELPER
|
||||
private final String serverId;
|
||||
@Nullable
|
||||
private ServerPlayer delayedAcceptPlayer;
|
|
@ -0,0 +1,30 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Tue, 18 Dec 2018 02:15:08 +0000
|
||||
Subject: [PATCH] Prevent Enderman from loading chunks
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java
|
||||
index abd1130529dd74780054e26bac89cf757ba9cdc1..a39f4a1585ba888d27588a86130f6dae24f5a71b 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java
|
||||
@@ -465,7 +465,8 @@ public class EnderMan extends Monster implements NeutralMob {
|
||||
int j = Mth.floor(this.enderman.getY() + random.nextDouble() * 2.0D);
|
||||
int k = Mth.floor(this.enderman.getZ() - 1.0D + random.nextDouble() * 2.0D);
|
||||
BlockPos blockposition = new BlockPos(i, j, k);
|
||||
- BlockState iblockdata = world.getBlockState(blockposition);
|
||||
+ BlockState iblockdata = world.getTypeIfLoaded(blockposition); // Paper
|
||||
+ if (iblockdata == null) return; // Paper
|
||||
BlockPos blockposition1 = blockposition.below();
|
||||
BlockState iblockdata1 = world.getBlockState(blockposition1);
|
||||
BlockState iblockdata2 = this.enderman.getCarriedBlock();
|
||||
@@ -511,7 +512,8 @@ public class EnderMan extends Monster implements NeutralMob {
|
||||
int j = Mth.floor(this.enderman.getY() + random.nextDouble() * 3.0D);
|
||||
int k = Mth.floor(this.enderman.getZ() - 2.0D + random.nextDouble() * 4.0D);
|
||||
BlockPos blockposition = new BlockPos(i, j, k);
|
||||
- BlockState iblockdata = world.getBlockState(blockposition);
|
||||
+ BlockState iblockdata = world.getTypeIfLoaded(blockposition); // Paper
|
||||
+ if (iblockdata == null) return; // Paper
|
||||
Vec3 vec3d = new Vec3((double) this.enderman.getBlockX() + 0.5D, (double) j + 0.5D, (double) this.enderman.getBlockZ() + 0.5D);
|
||||
Vec3 vec3d1 = new Vec3((double) i + 0.5D, (double) j + 0.5D, (double) k + 0.5D);
|
||||
BlockHitResult movingobjectpositionblock = world.clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this.enderman));
|
|
@ -0,0 +1,164 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach@zachbr.io>
|
||||
Date: Wed, 2 Jan 2019 00:35:43 -0600
|
||||
Subject: [PATCH] Add APIs to replace OfflinePlayer#getLastPlayed
|
||||
|
||||
Currently OfflinePlayer#getLastPlayed could more accurately be described
|
||||
as "OfflinePlayer#getLastTimeTheirDataWasSaved".
|
||||
|
||||
The API doc says it should return the last time the server "witnessed"
|
||||
the player, whilst also saying it should return the last time they
|
||||
logged in. The current implementation does neither.
|
||||
|
||||
Given this interesting contradiction in the API documentation and the
|
||||
current defacto implementation, I've elected to deprecate (with no
|
||||
intent to remove) and replace it with two new methods, clearly named and
|
||||
documented as to their purpose.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 963a3c159e912a39b98dfcb3fdb8c384765990d7..44da4efc23a3273449431845308ba889615ac425 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -218,6 +218,7 @@ public class ServerPlayer extends Player {
|
||||
public int latency;
|
||||
public boolean wonGame;
|
||||
private int containerUpdateDelay; // Paper
|
||||
+ public long loginTime; // Paper
|
||||
// Paper start - cancellable death event
|
||||
public boolean queueHealthUpdatePacket = false;
|
||||
public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket;
|
||||
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
index b62aa9f934c33b4d22b985b5e56937baa8454677..0df68991eb2ef3dabe779f42c2bf44846ac0d862 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
@@ -169,6 +169,7 @@ public abstract class PlayerList {
|
||||
}
|
||||
|
||||
public void placeNewPlayer(Connection connection, ServerPlayer player) {
|
||||
+ player.loginTime = System.currentTimeMillis(); // Paper
|
||||
GameProfile gameprofile = player.getGameProfile();
|
||||
GameProfileCache usercache = this.server.getProfileCache();
|
||||
GameProfile gameprofile1 = usercache.get(gameprofile.getId());
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
|
||||
index 93de44b05a698515457052c9c684c4ef44c5cc40..b20bfe5ab165bf86985e5ff2f93f415d9710e0e4 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
|
||||
@@ -244,6 +244,61 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa
|
||||
return this.getData() != null;
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public long getLastLogin() {
|
||||
+ Player player = getPlayer();
|
||||
+ if (player != null) return player.getLastLogin();
|
||||
+
|
||||
+ CompoundTag data = getPaperData();
|
||||
+
|
||||
+ if (data != null) {
|
||||
+ if (data.contains("LastLogin")) {
|
||||
+ return data.getLong("LastLogin");
|
||||
+ } else {
|
||||
+ // if the player file cannot provide accurate data, this is probably the closest we can approximate
|
||||
+ File file = getDataFile();
|
||||
+ return file.lastModified();
|
||||
+ }
|
||||
+ } else {
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public long getLastSeen() {
|
||||
+ Player player = getPlayer();
|
||||
+ if (player != null) return player.getLastSeen();
|
||||
+
|
||||
+ CompoundTag data = getPaperData();
|
||||
+
|
||||
+ if (data != null) {
|
||||
+ if (data.contains("LastSeen")) {
|
||||
+ return data.getLong("LastSeen");
|
||||
+ } else {
|
||||
+ // if the player file cannot provide accurate data, this is probably the closest we can approximate
|
||||
+ File file = getDataFile();
|
||||
+ return file.lastModified();
|
||||
+ }
|
||||
+ } else {
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private CompoundTag getPaperData() {
|
||||
+ CompoundTag result = getData();
|
||||
+
|
||||
+ if (result != null) {
|
||||
+ if (!result.contains("Paper")) {
|
||||
+ result.put("Paper", new CompoundTag());
|
||||
+ }
|
||||
+ result = result.getCompound("Paper");
|
||||
+ }
|
||||
+
|
||||
+ return result;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public Location getBedSpawnLocation() {
|
||||
CompoundTag data = this.getData();
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index 686dc5859c081d3b86d8e58a63abee49258208d7..f0bdf17d86458da3678945aeb23fdb5bceabc366 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -150,6 +150,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
private org.bukkit.event.player.PlayerResourcePackStatusEvent.Status resourcePackStatus;
|
||||
private String resourcePackHash;
|
||||
private static final boolean DISABLE_CHANNEL_LIMIT = System.getProperty("paper.disableChannelLimit") != null; // Paper - add a flag to disable the channel limit
|
||||
+ private long lastSaveTime;
|
||||
// Paper end
|
||||
|
||||
public CraftPlayer(CraftServer server, ServerPlayer entity) {
|
||||
@@ -1502,6 +1503,18 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
this.firstPlayed = firstPlayed;
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public long getLastLogin() {
|
||||
+ return getHandle().loginTime;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public long getLastSeen() {
|
||||
+ return isOnline() ? System.currentTimeMillis() : this.lastSaveTime;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
public void readExtraData(CompoundTag nbttagcompound) {
|
||||
this.hasPlayedBefore = true;
|
||||
if (nbttagcompound.contains("bukkit")) {
|
||||
@@ -1524,6 +1537,8 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
}
|
||||
|
||||
public void setExtraData(CompoundTag nbttagcompound) {
|
||||
+ this.lastSaveTime = System.currentTimeMillis(); // Paper
|
||||
+
|
||||
if (!nbttagcompound.contains("bukkit")) {
|
||||
nbttagcompound.put("bukkit", new CompoundTag());
|
||||
}
|
||||
@@ -1538,6 +1553,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
data.putLong("firstPlayed", this.getFirstPlayed());
|
||||
data.putLong("lastPlayed", System.currentTimeMillis());
|
||||
data.putString("lastKnownName", handle.getScoreboardName());
|
||||
+
|
||||
+ // Paper start - persist for use in offline save data
|
||||
+ if (!nbttagcompound.contains("Paper")) {
|
||||
+ nbttagcompound.put("Paper", new CompoundTag());
|
||||
+ }
|
||||
+
|
||||
+ CompoundTag paper = nbttagcompound.getCompound("Paper");
|
||||
+ paper.putLong("LastLogin", handle.loginTime);
|
||||
+ paper.putLong("LastSeen", System.currentTimeMillis());
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
@Override
|
|
@ -0,0 +1,24 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: connorhartley <vectrixu+gh@gmail.com>
|
||||
Date: Mon, 7 Jan 2019 14:43:48 -0600
|
||||
Subject: [PATCH] Workaround for vehicle tracking issue on disconnect
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 44da4efc23a3273449431845308ba889615ac425..955a7fcd80a57f920e402a5533f5029b9683104c 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -1538,6 +1538,13 @@ public class ServerPlayer extends Player {
|
||||
public void disconnect() {
|
||||
this.disconnected = true;
|
||||
this.ejectPassengers();
|
||||
+
|
||||
+ // Paper start - Workaround an issue where the vehicle doesn't track the passenger disconnection dismount.
|
||||
+ if (this.isPassenger() && this.getVehicle() instanceof ServerPlayer) {
|
||||
+ this.stopRiding();
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
if (this.isSleeping()) {
|
||||
this.stopSleepInBed(true, false);
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach@zachbr.io>
|
||||
Date: Thu, 31 Jan 2019 16:33:36 -0500
|
||||
Subject: [PATCH] Fire BlockPistonRetractEvent for all empty pistons
|
||||
|
||||
There is an explicit check in the handling code for empty pistons that
|
||||
prevents sticky pistons from firing the event. However when we look back
|
||||
at the history we see that this check was originally added so that ONLY
|
||||
sticky pistons would fire the retract event. I'm not sure why.
|
||||
https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/commits/1092acbddf07edfa4100bc6824504ac75088e913
|
||||
|
||||
Over the course of several updates, the meaning of that field appears to
|
||||
have changed from "is NOT sticky" to "is sticky". So now its having the
|
||||
opposite effect. Only normal pistons fire the retraction event. And like
|
||||
all things in CB, it's just been carried around since.
|
||||
|
||||
If we are to believe the history, the correct fix for this issue is to
|
||||
flip it so it only fires for sticky pistons, but that puts us in a
|
||||
bind. It's already firing for non-sticky pistons, changing it now would
|
||||
likely result in breakage. Furthermore, there is little documentation as
|
||||
to WHY that was ever intended to be the case.
|
||||
|
||||
Instead we opt to remove the check entirely so that the event fires for
|
||||
all piston types.
|
||||
|
||||
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 ca9e94b92d26eb6cd3ca6ff4b8cb1cd98aabf4e0..c345bd7542f3ffa09719864887e1516f1182e7e3 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
|
||||
@@ -147,7 +147,7 @@ public class PistonBaseBlock extends DirectionalBlock {
|
||||
}
|
||||
|
||||
// CraftBukkit start
|
||||
- if (!this.isSticky) {
|
||||
+ //if (!this.sticky) { // Paper - Prevents empty sticky pistons from firing retract - history behind is odd
|
||||
org.bukkit.block.Block block = world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ());
|
||||
BlockPistonRetractEvent event = new BlockPistonRetractEvent(block, ImmutableList.<org.bukkit.block.Block>of(), CraftBlock.notchToBlockFace(enumdirection));
|
||||
world.getCraftServer().getPluginManager().callEvent(event);
|
||||
@@ -155,7 +155,7 @@ public class PistonBaseBlock extends DirectionalBlock {
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
- }
|
||||
+ //} // Paper
|
||||
// PAIL: checkME - what happened to setTypeAndData?
|
||||
// CraftBukkit end
|
||||
world.blockEvent(pos, this, b0, enumdirection.get3DDataValue());
|
|
@ -0,0 +1,33 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach@zachbr.io>
|
||||
Date: Mon, 4 Feb 2019 23:33:24 -0500
|
||||
Subject: [PATCH] Block Entity#remove from being called on Players
|
||||
|
||||
This doesn't result in the same behavior as other entities and causes
|
||||
several problems. Anyone ever complain about the "Cannot send chat
|
||||
message" thing? That's one of the issues this causes, among others.
|
||||
|
||||
If a plugin developer can come up with a valid reason to call this on a
|
||||
Player we will look at limiting the scope of this change. It appears to
|
||||
be unintentional in the few cases we've seen so far.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index f0bdf17d86458da3678945aeb23fdb5bceabc366..2ed7920b0e046bc9d581878a10b04ad784bb8655 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -2255,6 +2255,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
public void resetCooldown() {
|
||||
getHandle().resetAttackStrengthTicker();
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public void remove() {
|
||||
+ if (this.getHandle().getClass().equals(ServerPlayer.class)) { // special case for NMS plugins inheriting
|
||||
+ throw new UnsupportedOperationException("Calling Entity#remove on players produces undefined (bad) behavior");
|
||||
+ } else {
|
||||
+ super.remove();
|
||||
+ }
|
||||
+ }
|
||||
// Paper end
|
||||
|
||||
// Spigot start
|
46
patches/server/0302-BlockDestroyEvent.patch
Normal file
46
patches/server/0302-BlockDestroyEvent.patch
Normal file
|
@ -0,0 +1,46 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 6 Feb 2019 00:20:33 -0500
|
||||
Subject: [PATCH] BlockDestroyEvent
|
||||
|
||||
Adds an event for when the server is going to destroy a current block,
|
||||
potentially causing it to drop. This event can be cancelled to avoid
|
||||
the block destruction, such as preventing signs from popping when
|
||||
floating in the air.
|
||||
|
||||
This can replace many uses of BlockPhysicsEvent
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
||||
index 8d4f8719b30a66fbb68c9407ee8484312f05b3fb..a1b713391c2445967c3b5a645304f193c013d551 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/Level.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
||||
@@ -28,6 +28,7 @@ import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
+import net.minecraft.server.MCUtil;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ChunkHolder;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
@@ -567,8 +568,20 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
return false;
|
||||
} else {
|
||||
FluidState fluid = this.getFluidState(pos);
|
||||
+ // Paper start - while the above setAir method is named same and looks very similar
|
||||
+ // they are NOT used with same intent and the above should not fire this event. The above method is more of a BlockSetToAirEvent,
|
||||
+ // it doesn't imply destruction of a block that plays a sound effect / drops an item.
|
||||
+ boolean playEffect = true;
|
||||
+ if (com.destroystokyo.paper.event.block.BlockDestroyEvent.getHandlerList().getRegisteredListeners().length > 0) {
|
||||
+ com.destroystokyo.paper.event.block.BlockDestroyEvent event = new com.destroystokyo.paper.event.block.BlockDestroyEvent(MCUtil.toBukkitBlock(this, pos), fluid.createLegacyBlock().createCraftBlockData(), drop);
|
||||
+ if (!event.callEvent()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ playEffect = event.playEffect();
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
- if (!(iblockdata.getBlock() instanceof BaseFireBlock)) {
|
||||
+ if (playEffect && !(iblockdata.getBlock() instanceof BaseFireBlock)) { // Paper
|
||||
this.levelEvent(2001, pos, Block.getId(iblockdata));
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Fri, 18 Jan 2019 00:08:15 -0500
|
||||
Subject: [PATCH] Fix Custom Shapeless Custom Crafting Recipes
|
||||
|
||||
Mojang implemented Shapeless different than Shaped
|
||||
|
||||
This made the Bukkit RecipeChoice API not work for Shapeless.
|
||||
|
||||
This reimplements vanilla logic using the same test logic as Shaped
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java b/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java
|
||||
index 4e1159b3188d39c998e6887c2846209c10b701f9..6b960f0a31175bcfd8d477ee5b3c4d783303cdd5 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java
|
||||
@@ -76,16 +76,49 @@ public class ShapelessRecipe implements CraftingRecipe {
|
||||
StackedContents autorecipestackmanager = new StackedContents();
|
||||
int i = 0;
|
||||
|
||||
+ // Paper start
|
||||
+ java.util.List<ItemStack> providedItems = new java.util.ArrayList<>();
|
||||
+ co.aikar.util.Counter<ItemStack> matchedProvided = new co.aikar.util.Counter<>();
|
||||
+ co.aikar.util.Counter<Ingredient> matchedIngredients = new co.aikar.util.Counter<>();
|
||||
+ // Paper end
|
||||
for (int j = 0; j < inventory.getContainerSize(); ++j) {
|
||||
ItemStack itemstack = inventory.getItem(j);
|
||||
|
||||
if (!itemstack.isEmpty()) {
|
||||
- ++i;
|
||||
- autorecipestackmanager.accountStack(itemstack, 1);
|
||||
+ // Paper start
|
||||
+ itemstack = itemstack.copy();
|
||||
+ providedItems.add(itemstack);
|
||||
+ for (Ingredient ingredient : ingredients) {
|
||||
+ if (ingredient.test(itemstack)) {
|
||||
+ matchedProvided.increment(itemstack);
|
||||
+ matchedIngredients.increment(ingredient);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
}
|
||||
|
||||
- return i == this.ingredients.size() && autorecipestackmanager.canCraft(this, (IntList) null);
|
||||
+ // Paper start
|
||||
+ if (matchedProvided.isEmpty() || matchedIngredients.isEmpty()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ java.util.List<Ingredient> ingredients = new java.util.ArrayList<>(this.ingredients);
|
||||
+ providedItems.sort(java.util.Comparator.comparingInt((ItemStack c) -> (int) matchedProvided.getCount(c)).reversed());
|
||||
+ ingredients.sort(java.util.Comparator.comparingInt((Ingredient c) -> (int) matchedIngredients.getCount(c)));
|
||||
+
|
||||
+ PROVIDED:
|
||||
+ for (ItemStack provided : providedItems) {
|
||||
+ for (Iterator<Ingredient> itIngredient = ingredients.iterator(); itIngredient.hasNext(); ) {
|
||||
+ Ingredient ingredient = itIngredient.next();
|
||||
+ if (ingredient.test(provided)) {
|
||||
+ itIngredient.remove();
|
||||
+ continue PROVIDED;
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+ return ingredients.isEmpty();
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
public ItemStack assemble(CraftingContainer inventory) {
|
58
patches/server/0304-Limit-Client-Sign-length-more.patch
Normal file
58
patches/server/0304-Limit-Client-Sign-length-more.patch
Normal file
|
@ -0,0 +1,58 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 27 Feb 2019 22:18:40 -0500
|
||||
Subject: [PATCH] Limit Client Sign length more
|
||||
|
||||
modified clients can send more data from the client
|
||||
to the server and it would get stored on the sign as sent.
|
||||
|
||||
Mojang has a limit of 384 which is much higher than reasonable.
|
||||
|
||||
the client can barely render around 16 characters as-is, but formatting
|
||||
codes can get it to be more than 16 actual length.
|
||||
|
||||
Set a limit of 80 which should give an average of 16 characters 2
|
||||
sets of legacy formatting codes which should be plenty for all uses.
|
||||
|
||||
This does not strip any existing data from the NBT as plugins
|
||||
may use this for storing data out of the rendered area.
|
||||
|
||||
it only impacts data sent from the client.
|
||||
|
||||
Set -DPaper.maxSignLength=XX to change limit or -1 to disable
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index f1a8470d0b314c8fa5eade198cffc1f8cd5e6832..defebf7b45e4f006fa7e575b5dbd01ac1e231d5a 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -255,6 +255,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
|
||||
private int aboveGroundVehicleTickCount;
|
||||
private int receivedMovePacketCount;
|
||||
private int knownMovePacketCount;
|
||||
+ private static final int MAX_SIGN_LINE_LENGTH = Integer.getInteger("Paper.maxSignLength", 80);
|
||||
private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit
|
||||
|
||||
public ServerGamePacketListenerImpl(MinecraftServer server, Connection connection, ServerPlayer player) {
|
||||
@@ -2867,10 +2868,20 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
|
||||
List<net.kyori.adventure.text.Component> lines = new java.util.ArrayList<>();
|
||||
|
||||
for (int i = 0; i < list.size(); ++i) {
|
||||
+ // Paper start - cap line length - modified clients can send longer data than normal
|
||||
+ net.minecraft.server.network.TextFilter.FilteredText currentLine = list.get(i);
|
||||
+ if (MAX_SIGN_LINE_LENGTH > 0 && currentLine.getRaw().length() > MAX_SIGN_LINE_LENGTH) {
|
||||
+ // This handles multibyte characters as 1
|
||||
+ int offset = currentLine.getRaw().codePoints().limit(MAX_SIGN_LINE_LENGTH).map(Character::charCount).sum();
|
||||
+ if (offset < currentLine.getRaw().length()) {
|
||||
+ list.set(i, currentLine = net.minecraft.server.network.TextFilter.FilteredText.passThrough(currentLine.getRaw().substring(0, offset))); // this will break any filtering, but filtering is NYI as of 1.17
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
if (this.player.isTextFilteringEnabled()) {
|
||||
- lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterText(list.get(i).getFiltered())));
|
||||
+ lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterText(currentLine.getFiltered())));
|
||||
} else {
|
||||
- lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterText(list.get(i).getRaw())));
|
||||
+ lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterText(currentLine.getRaw())));
|
||||
}
|
||||
}
|
||||
SignChangeEvent event = new SignChangeEvent((org.bukkit.craftbukkit.block.CraftBlock) player.getWorld().getBlockAt(x, y, z), this.cserver.getPlayer(this.player), lines);
|
Loading…
Add table
Add a link
Reference in a new issue