More more work

This commit is contained in:
Nassim Jahnke 2023-12-05 20:39:26 +01:00
parent 603b32976b
commit d7fc0c5ab2
35 changed files with 242 additions and 246 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,105 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Sun, 3 Mar 2019 20:53:18 -0800
Subject: [PATCH] Add TickThread
Placeholder patch, to be used by chunksystem rewrite
diff --git a/src/main/java/io/papermc/paper/util/TickThread.java b/src/main/java/io/papermc/paper/util/TickThread.java
new file mode 100644
index 0000000000000000000000000000000000000000..d59885ee9c8b29d5bac34dce0597e345e5358c77
--- /dev/null
+++ b/src/main/java/io/papermc/paper/util/TickThread.java
@@ -0,0 +1,79 @@
+package io.papermc.paper.util;
+
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.server.level.ServerLevel;
+import net.minecraft.world.entity.Entity;
+import org.bukkit.Bukkit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public final class TickThread extends Thread {
+
+ public static final boolean STRICT_THREAD_CHECKS = Boolean.getBoolean("paper.strict-thread-checks");
+
+ static {
+ if (STRICT_THREAD_CHECKS) {
+ MinecraftServer.LOGGER.warn("Strict thread checks enabled - performance may suffer");
+ }
+ }
+
+ public static void softEnsureTickThread(final String reason) {
+ if (!STRICT_THREAD_CHECKS) {
+ return;
+ }
+ ensureTickThread(reason);
+ }
+
+ public static void ensureTickThread(final String reason) {
+ if (!isTickThread()) {
+ MinecraftServer.LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason, new Throwable());
+ throw new IllegalStateException(reason);
+ }
+ }
+
+ public static void ensureTickThread(final ServerLevel world, final int chunkX, final int chunkZ, final String reason) {
+ if (!isTickThreadFor(world, chunkX, chunkZ)) {
+ MinecraftServer.LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason, new Throwable());
+ throw new IllegalStateException(reason);
+ }
+ }
+
+ public static void ensureTickThread(final Entity entity, final String reason) {
+ if (!isTickThreadFor(entity)) {
+ MinecraftServer.LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason, new Throwable());
+ throw new IllegalStateException(reason);
+ }
+ }
+
+ public final int id; /* We don't override getId as the spec requires that it be unique (with respect to all other threads) */
+
+ private static final AtomicInteger ID_GENERATOR = new AtomicInteger();
+
+ public TickThread(final String name) {
+ this(null, name);
+ }
+
+ public TickThread(final Runnable run, final String name) {
+ this(run, name, ID_GENERATOR.incrementAndGet());
+ }
+
+ private TickThread(final Runnable run, final String name, final int id) {
+ super(run, name);
+ this.id = id;
+ }
+
+ public static TickThread getCurrentTickThread() {
+ return (TickThread)Thread.currentThread();
+ }
+
+ public static boolean isTickThread() {
+ return Bukkit.isPrimaryThread();
+ }
+
+ public static boolean isTickThreadFor(final ServerLevel world, final int chunkX, final int chunkZ) {
+ return Bukkit.isPrimaryThread();
+ }
+
+ public static boolean isTickThreadFor(final Entity entity) {
+ return Bukkit.isPrimaryThread();
+ }
+}
diff --git a/src/main/java/org/spigotmc/AsyncCatcher.java b/src/main/java/org/spigotmc/AsyncCatcher.java
index bbf0d9d9c44fe8d7add2f978994ec129420814c7..78669fa035b7537ff7e533cf32aaf2995625424f 100644
--- a/src/main/java/org/spigotmc/AsyncCatcher.java
+++ b/src/main/java/org/spigotmc/AsyncCatcher.java
@@ -9,7 +9,7 @@ public class AsyncCatcher
public static void catchOp(String reason)
{
- if ( AsyncCatcher.enabled && Thread.currentThread() != MinecraftServer.getServer().serverThread )
+ if ( (AsyncCatcher.enabled || io.papermc.paper.util.TickThread.STRICT_THREAD_CHECKS) && Thread.currentThread() != MinecraftServer.getServer().serverThread ) // Paper
{
throw new IllegalStateException( "Asynchronous " + reason + "!" );
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,65 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
Date: Tue, 18 May 2021 14:39:44 -0700
Subject: [PATCH] Add command line option to load extra plugin jars not in the
plugins folder
ex: java -jar paperclip.jar nogui -add-plugin=/path/to/plugin.jar -add-plugin=/path/to/another/plugin_jar.jar
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index e411d9e821604f07e744f2457654f6ac4bb34db7..012634a64a39cbcbb49d2c8948fac92eca15cebe 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -426,6 +426,35 @@ public final class CraftServer implements Server {
io.papermc.paper.plugin.entrypoint.LaunchEntryPointHandler.INSTANCE.enter(io.papermc.paper.plugin.entrypoint.Entrypoint.PLUGIN); // Paper - replace implementation
}
+ // Paper start
+ @Override
+ public File getPluginsFolder() {
+ return (File) this.console.options.valueOf("plugins");
+ }
+
+ private List<File> extraPluginJars() {
+ @SuppressWarnings("unchecked")
+ final List<File> jars = (List<File>) this.console.options.valuesOf("add-plugin");
+ final List<File> list = new ArrayList<>();
+ for (final File file : jars) {
+ if (!file.exists()) {
+ net.minecraft.server.MinecraftServer.LOGGER.warn("File '{}' specified through 'add-plugin' argument does not exist, cannot load a plugin from it!", file.getAbsolutePath());
+ continue;
+ }
+ if (!file.isFile()) {
+ net.minecraft.server.MinecraftServer.LOGGER.warn("File '{}' specified through 'add-plugin' argument is not a file, cannot load a plugin from it!", file.getAbsolutePath());
+ continue;
+ }
+ if (!file.getName().endsWith(".jar")) {
+ net.minecraft.server.MinecraftServer.LOGGER.warn("File '{}' specified through 'add-plugin' argument is not a jar file, cannot load a plugin from it!", file.getAbsolutePath());
+ continue;
+ }
+ list.add(file);
+ }
+ return list;
+ }
+ // Paper end
+
public void enablePlugins(PluginLoadOrder type) {
if (type == PluginLoadOrder.STARTUP) {
this.helpMap.clear();
diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java
index 328118a19ce409ad9a15e75d54d70eb3be65ea6a..7285510dc618327b578b179165023414d595a354 100644
--- a/src/main/java/org/bukkit/craftbukkit/Main.java
+++ b/src/main/java/org/bukkit/craftbukkit/Main.java
@@ -160,6 +160,12 @@ public class Main {
.ofType(File.class)
.defaultsTo(new File("paper.yml"))
.describedAs("Yml file");
+
+ acceptsAll(asList("add-plugin", "add-extra-plugin-jar"), "Specify paths to extra plugin jars to be loaded in addition to those in the plugins folder. This argument can be specified multiple times, once for each extra plugin jar path.")
+ .withRequiredArg()
+ .ofType(File.class)
+ .defaultsTo(new File[] {})
+ .describedAs("Jar file");
// Paper end
}
};

View file

@ -0,0 +1,92 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zach Brown <zach.brown@destroystokyo.com>
Date: Tue, 1 Mar 2016 13:02:51 -0600
Subject: [PATCH] Configurable cactus bamboo and reed growth heights
Bamboo - Both the minimum fully-grown heights and the maximum are configurable
- Machine_Maker
diff --git a/src/main/java/net/minecraft/world/level/block/BambooStalkBlock.java b/src/main/java/net/minecraft/world/level/block/BambooStalkBlock.java
index bd72deadb59289ae90afc379ee61e8198ddaf4ed..1dd85da8da9e2040d740c5f573e7438380f9a7a8 100644
--- a/src/main/java/net/minecraft/world/level/block/BambooStalkBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BambooStalkBlock.java
@@ -137,7 +137,7 @@ public class BambooStalkBlock extends Block implements BonemealableBlock {
if (random.nextFloat() < (world.spigotConfig.bambooModifier / (100.0f * 3)) && world.isEmptyBlock(pos.above()) && world.getRawBrightness(pos.above(), 0) >= 9) { // Spigot - SPIGOT-7159: Better modifier resolution
int i = this.getHeightBelowUpToMax(world, pos) + 1;
- if (i < 16) {
+ if (i < world.paperConfig().maxGrowthHeight.bamboo.max) { // Paper
this.growBamboo(state, world, pos, random, i);
}
}
@@ -168,7 +168,7 @@ public class BambooStalkBlock extends Block implements BonemealableBlock {
int i = this.getHeightAboveUpToMax(world, pos);
int j = this.getHeightBelowUpToMax(world, pos);
- return i + j + 1 < 16 && (Integer) world.getBlockState(pos.above(i)).getValue(BambooStalkBlock.STAGE) != 1;
+ return i + j + 1 < ((Level) world).paperConfig().maxGrowthHeight.bamboo.max && (Integer) world.getBlockState(pos.above(i)).getValue(BambooStalkBlock.STAGE) != 1; // Paper
}
@Override
@@ -187,7 +187,7 @@ public class BambooStalkBlock extends Block implements BonemealableBlock {
BlockPos blockposition1 = pos.above(i);
BlockState iblockdata1 = world.getBlockState(blockposition1);
- if (k >= 16 || !iblockdata1.is(Blocks.BAMBOO) || (Integer) iblockdata1.getValue(BambooStalkBlock.STAGE) == 1 || !world.isEmptyBlock(blockposition1.above())) { // CraftBukkit - If the BlockSpreadEvent was cancelled, we have no bamboo here
+ if (k >= world.paperConfig().maxGrowthHeight.bamboo.max || !iblockdata1.is(Blocks.BAMBOO) || (Integer) iblockdata1.getValue(BambooStalkBlock.STAGE) == 1 || !world.isEmptyBlock(blockposition1.above())) { // CraftBukkit - If the BlockSpreadEvent was cancelled, we have no bamboo here // Paper - Configurable cactus bamboo and reed growth heights
return;
}
@@ -228,7 +228,7 @@ public class BambooStalkBlock extends Block implements BonemealableBlock {
}
int j = (Integer) state.getValue(BambooStalkBlock.AGE) != 1 && !iblockdata2.is(Blocks.BAMBOO) ? 0 : 1;
- int k = (height < 11 || random.nextFloat() >= 0.25F) && height != 15 ? 0 : 1;
+ int k = (height < world.paperConfig().maxGrowthHeight.bamboo.min || random.nextFloat() >= 0.25F) && height != (world.paperConfig().maxGrowthHeight.bamboo.max - 1) ? 0 : 1; // Paper
// CraftBukkit start
if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, pos, pos.above(), (BlockState) ((BlockState) ((BlockState) this.defaultBlockState().setValue(BambooStalkBlock.AGE, j)).setValue(BambooStalkBlock.LEAVES, blockpropertybamboosize)).setValue(BambooStalkBlock.STAGE, k), 3)) {
@@ -243,7 +243,7 @@ public class BambooStalkBlock extends Block implements BonemealableBlock {
protected int getHeightAboveUpToMax(BlockGetter world, BlockPos pos) {
int i;
- for (i = 0; i < 16 && world.getBlockState(pos.above(i + 1)).is(Blocks.BAMBOO); ++i) {
+ for (i = 0; i < ((Level) world).paperConfig().maxGrowthHeight.bamboo.max && world.getBlockState(pos.above(i + 1)).is(Blocks.BAMBOO); ++i) { // Paper
;
}
@@ -253,7 +253,7 @@ public class BambooStalkBlock extends Block implements BonemealableBlock {
protected int getHeightBelowUpToMax(BlockGetter world, BlockPos pos) {
int i;
- for (i = 0; i < 16 && world.getBlockState(pos.below(i + 1)).is(Blocks.BAMBOO); ++i) {
+ for (i = 0; i < ((Level) world).paperConfig().maxGrowthHeight.bamboo.max && world.getBlockState(pos.below(i + 1)).is(Blocks.BAMBOO); ++i) { // Paper
;
}
diff --git a/src/main/java/net/minecraft/world/level/block/CactusBlock.java b/src/main/java/net/minecraft/world/level/block/CactusBlock.java
index fcd5b593c79aab42928cb1ddd0e6c1b03b7bafaf..3c7bbfcb3a88f23056cd0db3da2a281a81dc8c85 100644
--- a/src/main/java/net/minecraft/world/level/block/CactusBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/CactusBlock.java
@@ -61,7 +61,7 @@ public class CactusBlock extends Block {
;
}
- if (i < 3) {
+ if (i < world.paperConfig().maxGrowthHeight.cactus) { // Paper - Configurable growth height
int j = (Integer) state.getValue(CactusBlock.AGE);
int modifier = world.spigotConfig.cactusModifier; // Spigot - SPIGOT-7159: Better modifier resolution
diff --git a/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java b/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java
index 47d4fc5bcf2657078abc7a2637b6337fc0ea0977..ceaec1776067b7635c3952025f00f13f4ea86c88 100644
--- a/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java
@@ -59,7 +59,7 @@ public class SugarCaneBlock extends Block {
;
}
- if (i < 3) {
+ if (i < world.paperConfig().maxGrowthHeight.reeds) { // Paper - Configurable growth height
int j = (Integer) state.getValue(SugarCaneBlock.AGE);
int modifier = world.spigotConfig.caneModifier; // Spigot - SPIGOT-7159: Better modifier resolution

View file

@ -0,0 +1,30 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zach Brown <zach.brown@destroystokyo.com>
Date: Tue, 1 Mar 2016 13:09:16 -0600
Subject: [PATCH] Configurable baby zombie movement speed
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 190a02bce0026b2c6df796a5f14e639b5a84ccf1..37824f2470c7ddb77216ffbf4da02cc10a95a171 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
@@ -78,6 +78,7 @@ public class Zombie extends Monster {
private static final UUID SPEED_MODIFIER_BABY_UUID = UUID.fromString("B9766B59-9566-4402-BC1F-2EE2A276D836");
private static final AttributeModifier SPEED_MODIFIER_BABY = new AttributeModifier(Zombie.SPEED_MODIFIER_BABY_UUID, "Baby speed boost", 0.5D, AttributeModifier.Operation.MULTIPLY_BASE);
+ private final AttributeModifier babyModifier = new net.minecraft.world.entity.ai.attributes.AttributeModifier(SPEED_MODIFIER_BABY.getId(), SPEED_MODIFIER_BABY.getName(), this.level().paperConfig().entities.behavior.babyZombieMovementModifier, SPEED_MODIFIER_BABY.getOperation()); // Paper - Make baby speed configurable
private static final EntityDataAccessor<Boolean> DATA_BABY_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.BOOLEAN);
private static final EntityDataAccessor<Integer> DATA_SPECIAL_TYPE_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.INT);
public static final EntityDataAccessor<Boolean> DATA_DROWNED_CONVERSION_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.BOOLEAN);
@@ -186,9 +187,9 @@ public class Zombie extends Monster {
if (this.level() != null && !this.level().isClientSide) {
AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED);
- attributemodifiable.removeModifier(Zombie.SPEED_MODIFIER_BABY.getId());
+ attributemodifiable.removeModifier(this.babyModifier.getId()); // Paper
if (baby) {
- attributemodifiable.addTransientModifier(Zombie.SPEED_MODIFIER_BABY);
+ attributemodifiable.addTransientModifier(this.babyModifier); // Paper
}
}

View file

@ -0,0 +1,30 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zach Brown <zach.brown@destroystokyo.com>
Date: Tue, 1 Mar 2016 13:14:11 -0600
Subject: [PATCH] Configurable fishing time ranges
diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
index e5d9902331e3c4e461e855290a95980b41f5efe2..af6829c25fcd186adc3575d50cab6d46db9a2fac 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
@@ -92,6 +92,10 @@ public class FishingHook extends Projectile {
this.noCulling = true;
this.luck = Math.max(0, luckOfTheSeaLevel);
this.lureSpeed = Math.max(0, lureLevel);
+ // Paper start
+ minWaitTime = world.paperConfig().fishingTimeRange.minimum;
+ maxWaitTime = world.paperConfig().fishingTimeRange.maximum;
+ // Paper end
}
public FishingHook(EntityType<? extends FishingHook> type, Level world) {
@@ -409,7 +413,7 @@ public class FishingHook extends Projectile {
} else {
// CraftBukkit start - logic to modify fishing wait time
this.timeUntilLured = Mth.nextInt(this.random, this.minWaitTime, this.maxWaitTime);
- this.timeUntilLured -= (this.applyLure) ? this.lureSpeed * 20 * 5 : 0;
+ this.timeUntilLured -= (this.applyLure) ? (this.lureSpeed * 20 * 5 >= this.maxWaitTime ? this.timeUntilLured - 1 : this.lureSpeed * 20 * 5) : 0; // Paper - Fix Lure infinite loop
// CraftBukkit end
}
}

View file

@ -0,0 +1,47 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zach Brown <zach.brown@destroystokyo.com>
Date: Tue, 1 Mar 2016 13:24:16 -0600
Subject: [PATCH] Allow nerfed mobs to jump
diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java
index 01761d37c9e4be4e498b62c7612885648b2968a6..183866636eb67f632728a01c8e5e11b514d89f84 100644
--- a/src/main/java/net/minecraft/world/entity/Mob.java
+++ b/src/main/java/net/minecraft/world/entity/Mob.java
@@ -112,6 +112,7 @@ public abstract class Mob extends LivingEntity implements Targeting {
private final BodyRotationControl bodyRotationControl;
protected PathNavigation navigation;
public GoalSelector goalSelector;
+ @Nullable public net.minecraft.world.entity.ai.goal.FloatGoal goalFloat; // Paper
public GoalSelector targetSelector;
@Nullable
private LivingEntity target;
@@ -877,7 +878,15 @@ public abstract class Mob extends LivingEntity implements Targeting {
@Override
protected final void serverAiStep() {
++this.noActionTime;
- if (!this.aware) return; // CraftBukkit
+ // Paper start - Allow nerfed mobs to jump and float
+ if (!this.aware) {
+ if (goalFloat != null) {
+ if (goalFloat.canUse()) goalFloat.tick();
+ this.getJumpControl().tick();
+ }
+ return;
+ }
+ // Paper end
this.level().getProfiler().push("sensing");
this.sensing.tick();
this.level().getProfiler().pop();
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/FloatGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/FloatGoal.java
index 01950951ea06e43bedeeede489a112e577617829..7093c62be53fe99ed9880fc8ddaa07440fe4f715 100644
--- a/src/main/java/net/minecraft/world/entity/ai/goal/FloatGoal.java
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/FloatGoal.java
@@ -9,6 +9,7 @@ public class FloatGoal extends Goal {
public FloatGoal(Mob mob) {
this.mob = mob;
+ if (mob.getCommandSenderWorld().paperConfig().entities.behavior.spawnerNerfedMobsShouldJump) mob.goalFloat = this; // Paper
this.setFlags(EnumSet.of(Goal.Flag.JUMP));
mob.getNavigation().setCanFloat(true);
}

View file

@ -0,0 +1,27 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Suddenly <suddenly@suddenly.coffee>
Date: Tue, 1 Mar 2016 13:51:54 -0600
Subject: [PATCH] Add configurable despawn distances for living entities
diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java
index 183866636eb67f632728a01c8e5e11b514d89f84..007a5c9a6dc70ca6a215fdeb3fe77f8a8ee46818 100644
--- a/src/main/java/net/minecraft/world/entity/Mob.java
+++ b/src/main/java/net/minecraft/world/entity/Mob.java
@@ -853,14 +853,14 @@ public abstract class Mob extends LivingEntity implements Targeting {
if (entityhuman != null) {
double d0 = entityhuman.distanceToSqr((Entity) this);
- int i = this.getType().getCategory().getDespawnDistance();
+ int i = this.level().paperConfig().entities.spawning.despawnRanges.get(this.getType().getCategory()).hard(); // Paper - custom despawn distances
int j = i * i;
if (d0 > (double) j && this.removeWhenFarAway(d0)) {
this.discard();
}
- int k = this.getType().getCategory().getNoDespawnDistance();
+ int k = this.level().paperConfig().entities.spawning.despawnRanges.get(this.getType().getCategory()).soft(); // Paper - custom despawn distances
int l = k * k;
if (this.noActionTime > 600 && this.random.nextInt(800) == 0 && d0 > (double) l && this.removeWhenFarAway(d0)) {

View file

@ -0,0 +1,18 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zach Brown <zach.brown@destroystokyo.com>
Date: Thu, 3 Mar 2016 03:53:43 -0600
Subject: [PATCH] Allow for toggling of spawn chunks
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index 2922b90241e81245dbd56c53ab2eb661314c04fd..9369e0346a6b511a332d54577c781c3d2c2b5c86 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -264,6 +264,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
});
// CraftBukkit end
this.timings = new co.aikar.timings.WorldTimingsHandler(this); // Paper - code below can generate new world and access timings
+ this.keepSpawnInMemory = this.paperConfig().spawn.keepSpawnLoaded; // Paper
this.entityLimiter = new org.spigotmc.TickLimiter(this.spigotConfig.entityMaxTickTime);
this.tileLimiter = new org.spigotmc.TickLimiter(this.spigotConfig.tileMaxTickTime);
}

View file

@ -0,0 +1,62 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Byteflux <byte@byteflux.net>
Date: Tue, 1 Mar 2016 14:14:15 -0600
Subject: [PATCH] Drop falling block and tnt entities at the specified height
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
index d344b13e3726f0fe8a57c098769d1beea9705cdd..5d09790876c3c50d126678565001645f6aece16f 100644
--- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
+++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
@@ -142,6 +142,16 @@ public class FallingBlockEntity extends Entity {
}
this.move(MoverType.SELF, this.getDeltaMovement());
+ // Paper start - Configurable EntityFallingBlock height nerf
+ if (this.level().paperConfig().fixes.fallingBlockHeightNerf.test(v -> this.getY() > v)) {
+ if (this.dropItem && this.level().getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) {
+ this.spawnAtLocation(block);
+ }
+
+ this.discard();
+ return;
+ }
+ // Paper end
if (!this.level().isClientSide) {
BlockPos blockposition = this.blockPosition();
boolean flag = this.blockState.getBlock() instanceof ConcretePowderBlock;
diff --git a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java
index 36d93ee421406302c05945db17d46b04b485e4c0..f08c021f867c00611139a17db48352944eb2aa99 100644
--- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java
+++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java
@@ -77,6 +77,12 @@ public class PrimedTnt extends Entity implements TraceableEntity {
}
this.move(MoverType.SELF, this.getDeltaMovement());
+ // Paper start - Configurable TNT entity height nerf
+ if (this.level().paperConfig().fixes.tntEntityHeightNerf.test(v -> this.getY() > v)) {
+ this.discard();
+ return;
+ }
+ // Paper end
this.setDeltaMovement(this.getDeltaMovement().scale(0.98D));
if (this.onGround()) {
this.setDeltaMovement(this.getDeltaMovement().multiply(0.7D, -0.5D, 0.7D));
diff --git a/src/main/java/net/minecraft/world/entity/vehicle/MinecartTNT.java b/src/main/java/net/minecraft/world/entity/vehicle/MinecartTNT.java
index 0fc58f38bbd855414ad36b682e60b069d7b68cb1..9ec8821cf6571c5cc6b32212fe6f33bc4f6b949f 100644
--- a/src/main/java/net/minecraft/world/entity/vehicle/MinecartTNT.java
+++ b/src/main/java/net/minecraft/world/entity/vehicle/MinecartTNT.java
@@ -53,6 +53,12 @@ public class MinecartTNT extends AbstractMinecart {
public void tick() {
super.tick();
if (this.fuse > 0) {
+ // Paper start - Configurable TNT entity height nerf
+ if (this.level().paperConfig().fixes.tntEntityHeightNerf.test(v -> this.getY() > v)) {
+ this.discard();
+ return;
+ }
+ // Paper end
--this.fuse;
this.level().addParticle(ParticleTypes.SMOKE, this.getX(), this.getY() + 0.5D, this.getZ(), 0.0D, 0.0D, 0.0D);
} else if (this.fuse == 0) {

View file

@ -0,0 +1,104 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zach Brown <zach.brown@destroystokyo.com>
Date: Tue, 1 Mar 2016 14:32:43 -0600
Subject: [PATCH] Show 'Paper' in client crashes, server lists, and Mojang
stats
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 2021526bf6b8bdc286c31aaa62ab0235fac073cd..b082e17b9fbcc0e8ee881a89df1207d26bbeda0b 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1559,7 +1559,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@DontObfuscate
public String getServerModName() {
- return "Spigot"; // Spigot - Spigot > // CraftBukkit - cb > vanilla!
+ return "Paper"; // Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla!
}
public SystemReport fillSystemReport(SystemReport details) {
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 012634a64a39cbcbb49d2c8948fac92eca15cebe..d89f832288e197e6c7cf3a0eaab699b3ce1a2c0c 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -267,7 +267,7 @@ import org.yaml.snakeyaml.error.MarkedYAMLException;
import net.md_5.bungee.api.chat.BaseComponent; // Spigot
public final class CraftServer implements Server {
- private final String serverName = "CraftBukkit";
+ private final String serverName = "Paper"; // Paper
private final String serverVersion;
private final String bukkitVersion = Versioning.getBukkitVersion();
private final Logger logger = Logger.getLogger("Minecraft");
diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java
index 7285510dc618327b578b179165023414d595a354..176ffe9f5007bf4bb83bfc0d1186116c98481f45 100644
--- a/src/main/java/org/bukkit/craftbukkit/Main.java
+++ b/src/main/java/org/bukkit/craftbukkit/Main.java
@@ -241,12 +241,25 @@ public class Main {
deadline.add(Calendar.DAY_OF_YEAR, -3);
if (buildDate.before(deadline.getTime())) {
System.err.println("*** Error, this build is outdated ***");
- System.err.println("*** Please download a new build as per instructions from https://www.spigotmc.org/go/outdated-spigot ***");
+ System.err.println("*** Please download a new build as per instructions from https://papermc.io/downloads/paper ***"); // Paper
System.err.println("*** Server will start in 20 seconds ***");
Thread.sleep(TimeUnit.SECONDS.toMillis(20));
}
}
+ // Paper start - Log Java and OS versioning to help with debugging plugin issues
+ java.lang.management.RuntimeMXBean runtimeMX = java.lang.management.ManagementFactory.getRuntimeMXBean();
+ java.lang.management.OperatingSystemMXBean osMX = java.lang.management.ManagementFactory.getOperatingSystemMXBean();
+ if (runtimeMX != null && osMX != null) {
+ String javaInfo = "Java " + runtimeMX.getSpecVersion() + " (" + runtimeMX.getVmName() + " " + runtimeMX.getVmVersion() + ")";
+ String osInfo = "Host: " + osMX.getName() + " " + osMX.getVersion() + " (" + osMX.getArch() + ")";
+
+ System.out.println("System Info: " + javaInfo + " " + osInfo);
+ } else {
+ System.out.println("Unable to read system info");
+ }
+ // Paper end
+
System.out.println("Loading libraries, please wait...");
net.minecraft.server.Main.main(options);
} catch (Throwable t) {
diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java
index 7621bf889ef765ed57af221edf95b07346f4ae43..cacbde8ac27a70b5e3bcd76ad90bc667abee3817 100644
--- a/src/main/java/org/spigotmc/WatchdogThread.java
+++ b/src/main/java/org/spigotmc/WatchdogThread.java
@@ -19,7 +19,7 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa
private WatchdogThread(long timeoutTime, boolean restart)
{
- super( "Spigot Watchdog Thread" );
+ super( "Paper Watchdog Thread" );
this.timeoutTime = timeoutTime;
this.restart = restart;
}
@@ -65,14 +65,14 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa
{
Logger log = Bukkit.getServer().getLogger();
log.log( Level.SEVERE, "------------------------------" );
- log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Spigot bug." );
+ log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Paper bug." ); // Paper
log.log( Level.SEVERE, "If you see a plugin in the Server thread dump below, then please report it to that author" );
log.log( Level.SEVERE, "\t *Especially* if it looks like HTTP or MySQL operations are occurring" );
log.log( Level.SEVERE, "If you see a world save or edit, then it means you did far more than your server can handle at once" );
log.log( Level.SEVERE, "\t If this is the case, consider increasing timeout-time in spigot.yml but note that this will replace the crash with LARGE lag spikes" );
- log.log( Level.SEVERE, "If you are unsure or still think this is a Spigot bug, please report to https://www.spigotmc.org/" );
+ log.log( Level.SEVERE, "If you are unsure or still think this is a Paper bug, please report this to https://github.com/PaperMC/Paper/issues" );
log.log( Level.SEVERE, "Be sure to include ALL relevant console errors and Minecraft crash reports" );
- log.log( Level.SEVERE, "Spigot version: " + Bukkit.getServer().getVersion() );
+ log.log( Level.SEVERE, "Paper version: " + Bukkit.getServer().getVersion() );
//
if ( net.minecraft.world.level.Level.lastPhysicsProblem != null )
{
@@ -82,7 +82,7 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa
}
//
log.log( Level.SEVERE, "------------------------------" );
- log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Spigot!):" );
+ log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper
io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler.dumpAllChunkLoadInfo(isLongTimeout); // Paper // Paper - rewrite chunk system
WatchdogThread.dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log );
log.log( Level.SEVERE, "------------------------------" );

View file

@ -0,0 +1,157 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zach Brown <zach@zachbr.io>
Date: Mon, 27 May 2019 03:40:05 -0500
Subject: [PATCH] Implement Paper VersionChecker
diff --git a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java
new file mode 100644
index 0000000000000000000000000000000000000000..22a55be34fde453fedd987173d95b8b347a03588
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java
@@ -0,0 +1,129 @@
+package com.destroystokyo.paper;
+
+import com.destroystokyo.paper.util.VersionFetcher;
+import com.google.common.base.Charsets;
+import com.google.common.io.Resources;
+import com.google.gson.*;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.event.ClickEvent;
+import net.kyori.adventure.text.format.NamedTextColor;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import java.io.*;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.stream.StreamSupport;
+
+public class PaperVersionFetcher implements VersionFetcher {
+ private static final java.util.regex.Pattern VER_PATTERN = java.util.regex.Pattern.compile("^([0-9\\.]*)\\-.*R"); // R is an anchor, will always give '-R' at end
+ private static final String GITHUB_BRANCH_NAME = "master";
+ private static final String DOWNLOAD_PAGE = "https://papermc.io/downloads/paper";
+ private static @Nullable String mcVer;
+
+ @Override
+ public long getCacheTime() {
+ return 720000;
+ }
+
+ @Nonnull
+ @Override
+ public Component getVersionMessage(@Nonnull String serverVersion) {
+ String[] parts = serverVersion.substring("git-Paper-".length()).split("[-\\s]");
+ return getUpdateStatusMessage("PaperMC/Paper", GITHUB_BRANCH_NAME, parts[0]);
+ }
+
+ private static @Nullable String getMinecraftVersion() {
+ if (mcVer == null) {
+ java.util.regex.Matcher matcher = VER_PATTERN.matcher(org.bukkit.Bukkit.getBukkitVersion());
+ if (matcher.find()) {
+ String result = matcher.group();
+ mcVer = result.substring(0, result.length() - 2); // strip 'R' anchor and trailing '-'
+ } else {
+ org.bukkit.Bukkit.getLogger().warning("Unable to match version to pattern! Report to PaperMC!");
+ org.bukkit.Bukkit.getLogger().warning("Pattern: " + VER_PATTERN.toString());
+ org.bukkit.Bukkit.getLogger().warning("Version: " + org.bukkit.Bukkit.getBukkitVersion());
+ }
+ }
+
+ return mcVer;
+ }
+
+ private static Component getUpdateStatusMessage(@Nonnull String repo, @Nonnull String branch, @Nonnull String versionInfo) {
+ int distance;
+ try {
+ int jenkinsBuild = Integer.parseInt(versionInfo);
+ distance = fetchDistanceFromSiteApi(jenkinsBuild, getMinecraftVersion());
+ } catch (NumberFormatException ignored) {
+ versionInfo = versionInfo.replace("\"", "");
+ distance = fetchDistanceFromGitHub(repo, branch, versionInfo);
+ }
+
+ switch (distance) {
+ case -1:
+ return Component.text("Error obtaining version information", NamedTextColor.YELLOW);
+ case 0:
+ return Component.text("You are running the latest version", NamedTextColor.GREEN);
+ case -2:
+ return Component.text("Unknown version", NamedTextColor.YELLOW);
+ default:
+ return Component.text("You are " + distance + " version(s) behind", NamedTextColor.YELLOW)
+ .append(Component.newline())
+ .append(Component.text("Download the new version at: ")
+ .append(Component.text(DOWNLOAD_PAGE, NamedTextColor.GOLD)
+ .hoverEvent(Component.text("Click to open", NamedTextColor.WHITE))
+ .clickEvent(ClickEvent.openUrl(DOWNLOAD_PAGE))));
+ }
+ }
+
+ private static int fetchDistanceFromSiteApi(int jenkinsBuild, @Nullable String siteApiVersion) {
+ if (siteApiVersion == null) { return -1; }
+ try {
+ try (BufferedReader reader = Resources.asCharSource(
+ new URL("https://api.papermc.io/v2/projects/paper/versions/" + siteApiVersion),
+ Charsets.UTF_8
+ ).openBufferedStream()) {
+ JsonObject json = new Gson().fromJson(reader, JsonObject.class);
+ JsonArray builds = json.getAsJsonArray("builds");
+ int latest = StreamSupport.stream(builds.spliterator(), false)
+ .mapToInt(e -> e.getAsInt())
+ .max()
+ .getAsInt();
+ return latest - jenkinsBuild;
+ } catch (JsonSyntaxException ex) {
+ ex.printStackTrace();
+ return -1;
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ return -1;
+ }
+ }
+
+ // Contributed by Techcable <Techcable@outlook.com> in GH-65
+ private static int fetchDistanceFromGitHub(@Nonnull String repo, @Nonnull String branch, @Nonnull String hash) {
+ try {
+ HttpURLConnection connection = (HttpURLConnection) new URL("https://api.github.com/repos/" + repo + "/compare/" + branch + "..." + hash).openConnection();
+ connection.connect();
+ if (connection.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) return -2; // Unknown commit
+ try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), Charsets.UTF_8))) {
+ JsonObject obj = new Gson().fromJson(reader, JsonObject.class);
+ String status = obj.get("status").getAsString();
+ switch (status) {
+ case "identical":
+ return 0;
+ case "behind":
+ return obj.get("behind_by").getAsInt();
+ default:
+ return -1;
+ }
+ } catch (JsonSyntaxException | NumberFormatException e) {
+ e.printStackTrace();
+ return -1;
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ return -1;
+ }
+ }
+}
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
index 677335c3888adc25fbf3c5ec4d5a6c5ecf58ea5d..e31ead0d99203a018757cb2e765b5d28dd373eef 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
@@ -453,6 +453,11 @@ public final class CraftMagicNumbers implements UnsafeValues {
public String getTimingsServerName() {
return io.papermc.paper.configuration.GlobalConfiguration.get().timings.serverName;
}
+
+ @Override
+ public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() {
+ return new com.destroystokyo.paper.PaperVersionFetcher();
+ }
// Paper end
/**

View file

@ -0,0 +1,222 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Kyle Wood <kyle@denwav.dev>
Date: Thu, 1 Mar 2018 19:37:52 -0600
Subject: [PATCH] Add version history to version command
diff --git a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java
index 22a55be34fde453fedd987173d95b8b347a03588..9d687da5bdf398bb3f6c84cdf1249a7213d09f2e 100644
--- a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java
+++ b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java
@@ -7,6 +7,8 @@ import com.google.gson.*;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.format.NamedTextColor;
+import net.kyori.adventure.text.format.TextDecoration;
+import net.kyori.adventure.text.TextComponent;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -30,7 +32,10 @@ public class PaperVersionFetcher implements VersionFetcher {
@Override
public Component getVersionMessage(@Nonnull String serverVersion) {
String[] parts = serverVersion.substring("git-Paper-".length()).split("[-\\s]");
- return getUpdateStatusMessage("PaperMC/Paper", GITHUB_BRANCH_NAME, parts[0]);
+ final Component updateMessage = getUpdateStatusMessage("PaperMC/Paper", GITHUB_BRANCH_NAME, parts[0]);
+ final Component history = getHistory();
+
+ return history != null ? TextComponent.ofChildren(updateMessage, Component.newline(), history) : updateMessage;
}
private static @Nullable String getMinecraftVersion() {
@@ -126,4 +131,19 @@ public class PaperVersionFetcher implements VersionFetcher {
return -1;
}
}
+
+ @Nullable
+ private Component getHistory() {
+ final VersionHistoryManager.VersionData data = VersionHistoryManager.INSTANCE.getVersionData();
+ if (data == null) {
+ return null;
+ }
+
+ final String oldVersion = data.getOldVersion();
+ if (oldVersion == null) {
+ return null;
+ }
+
+ return Component.text("Previous version: " + oldVersion, NamedTextColor.GRAY, TextDecoration.ITALIC);
+ }
}
diff --git a/src/main/java/com/destroystokyo/paper/VersionHistoryManager.java b/src/main/java/com/destroystokyo/paper/VersionHistoryManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..660b2ec6b63a4ceffee44ab11f54dfa7c0d0996f
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/VersionHistoryManager.java
@@ -0,0 +1,153 @@
+package com.destroystokyo.paper;
+
+import com.google.common.base.MoreObjects;
+import com.google.gson.Gson;
+import com.google.gson.JsonSyntaxException;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.util.Objects;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.bukkit.Bukkit;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+public enum VersionHistoryManager {
+ INSTANCE;
+
+ private final Gson gson = new Gson();
+
+ private final Logger logger = Bukkit.getLogger();
+
+ private VersionData currentData = null;
+
+ VersionHistoryManager() {
+ final Path path = Paths.get("version_history.json");
+
+ if (Files.exists(path)) {
+ // Basic file santiy checks
+ if (!Files.isRegularFile(path)) {
+ if (Files.isDirectory(path)) {
+ logger.severe(path + " is a directory, cannot be used for version history");
+ } else {
+ logger.severe(path + " is not a regular file, cannot be used for version history");
+ }
+ // We can't continue
+ return;
+ }
+
+ try (final BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
+ currentData = gson.fromJson(reader, VersionData.class);
+ } catch (final IOException e) {
+ logger.log(Level.SEVERE, "Failed to read version history file '" + path + "'", e);
+ return;
+ } catch (final JsonSyntaxException e) {
+ logger.log(Level.SEVERE, "Invalid json syntax for file '" + path + "'", e);
+ return;
+ }
+
+ final String version = Bukkit.getVersion();
+ if (version == null) {
+ logger.severe("Failed to retrieve current version");
+ return;
+ }
+
+ if (currentData == null) {
+ // Empty file
+ currentData = new VersionData();
+ currentData.setCurrentVersion(version);
+ writeFile(path);
+ return;
+ }
+
+ if (!version.equals(currentData.getCurrentVersion())) {
+ // The version appears to have changed
+ currentData.setOldVersion(currentData.getCurrentVersion());
+ currentData.setCurrentVersion(version);
+ writeFile(path);
+ }
+ } else {
+ // File doesn't exist, start fresh
+ currentData = new VersionData();
+ // oldVersion is null
+ currentData.setCurrentVersion(Bukkit.getVersion());
+ writeFile(path);
+ }
+ }
+
+ private void writeFile(@Nonnull final Path path) {
+ try (final BufferedWriter writer = Files.newBufferedWriter(
+ path,
+ StandardCharsets.UTF_8,
+ StandardOpenOption.WRITE,
+ StandardOpenOption.CREATE,
+ StandardOpenOption.TRUNCATE_EXISTING
+ )) {
+ gson.toJson(currentData, writer);
+ } catch (final IOException e) {
+ logger.log(Level.SEVERE, "Failed to write to version history file", e);
+ }
+ }
+
+ @Nullable
+ public VersionData getVersionData() {
+ return currentData;
+ }
+
+ public static class VersionData {
+ private String oldVersion;
+
+ private String currentVersion;
+
+ @Nullable
+ public String getOldVersion() {
+ return oldVersion;
+ }
+
+ public void setOldVersion(@Nullable String oldVersion) {
+ this.oldVersion = oldVersion;
+ }
+
+ @Nullable
+ public String getCurrentVersion() {
+ return currentVersion;
+ }
+
+ public void setCurrentVersion(@Nullable String currentVersion) {
+ this.currentVersion = currentVersion;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("oldVersion", oldVersion)
+ .add("currentVersion", currentVersion)
+ .toString();
+ }
+
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ final VersionData versionData = (VersionData) o;
+ return Objects.equals(oldVersion, versionData.oldVersion) &&
+ Objects.equals(currentVersion, versionData.currentVersion);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(oldVersion, currentVersion);
+ }
+ }
+}
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
index b6d5e0962abb62a30c1561d3b1e970884b5b13dc..a267ab0b217573373d7b6a1f48cadab0f431da40 100644
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
@@ -189,6 +189,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
paperConfigurations.initializeWorldDefaultsConfiguration(this.registryAccess());
io.papermc.paper.command.PaperCommands.registerCommands(this);
com.destroystokyo.paper.Metrics.PaperMetrics.startMetrics();
+ com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now
// Paper end
this.setPvpAllowed(dedicatedserverproperties.pvp);

View file

@ -0,0 +1,160 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jedediah Smith <jedediah@silencegreys.com>
Date: Tue, 1 Mar 2016 14:47:52 -0600
Subject: [PATCH] Player affects spawning API
diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java
index 3126e8cab3c40e3af47f4c8925e1c6a9523309ba..170fbb1d80947b9b21c2106497baae5c37bcdc0c 100644
--- a/src/main/java/net/minecraft/world/entity/EntitySelector.java
+++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java
@@ -30,6 +30,11 @@ public final class EntitySelector {
public static final Predicate<Entity> CAN_BE_COLLIDED_WITH = EntitySelector.NO_SPECTATORS.and(Entity::canBeCollidedWith);
private EntitySelector() {}
+ // Paper start
+ public static final Predicate<Entity> PLAYER_AFFECTS_SPAWNING = (entity) -> {
+ return !entity.isSpectator() && entity.isAlive() && entity instanceof Player player && player.affectsSpawning;
+ };
+ // Paper end
public static Predicate<Entity> withinDistance(double x, double y, double z, double max) {
double d4 = max * max;
diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java
index 007a5c9a6dc70ca6a215fdeb3fe77f8a8ee46818..3d054cfa5050f4b75eab4a18035655c1bfd9290b 100644
--- a/src/main/java/net/minecraft/world/entity/Mob.java
+++ b/src/main/java/net/minecraft/world/entity/Mob.java
@@ -849,7 +849,7 @@ public abstract class Mob extends LivingEntity implements Targeting {
if (this.level().getDifficulty() == Difficulty.PEACEFUL && this.shouldDespawnInPeaceful()) {
this.discard();
} else if (!this.isPersistenceRequired() && !this.requiresCustomPersistence()) {
- Player entityhuman = this.level().getNearestPlayer(this, -1.0D);
+ Player entityhuman = this.level().findNearbyPlayer(this, -1.0D, EntitySelector.PLAYER_AFFECTS_SPAWNING); // Paper
if (entityhuman != null) {
double d0 = entityhuman.distanceToSqr((Entity) this);
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java
index c7ab59aa0e2fd0f3e7252647ddb25b82ac604830..8f20239f3ef7ebe41fac8ee6e024c36dafec33c4 100644
--- a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java
@@ -25,7 +25,7 @@ public class SkeletonTrapGoal extends Goal {
@Override
public boolean canUse() {
- return this.horse.level().hasNearbyAlivePlayer(this.horse.getX(), this.horse.getY(), this.horse.getZ(), 10.0D);
+ return this.horse.level().hasNearbyAlivePlayerThatAffectsSpawning(this.horse.getX(), this.horse.getY(), this.horse.getZ(), 10.0D); // Paper - Affects Spawning API
}
@Override
diff --git a/src/main/java/net/minecraft/world/entity/monster/Silverfish.java b/src/main/java/net/minecraft/world/entity/monster/Silverfish.java
index 96181e8925aef7f3d0a2010305caf1f6d9bcfcc9..6f452605e9dc9ebd9980eae9fdeea34417a37a88 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Silverfish.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Silverfish.java
@@ -127,7 +127,7 @@ public class Silverfish extends Monster {
if (checkAnyLightMonsterSpawnRules(type, world, spawnReason, pos, random)) {
Player entityhuman = world.getNearestPlayer((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, 5.0D, true);
- return entityhuman == null;
+ return !(entityhuman != null && !entityhuman.affectsSpawning) && entityhuman == null; // Paper - Affects Spawning API
} else {
return false;
}
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 37824f2470c7ddb77216ffbf4da02cc10a95a171..0c9a91990376482bc16f74a8b183ebf049ee1949 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
@@ -326,7 +326,7 @@ public class Zombie extends Monster {
if (NaturalSpawner.isSpawnPositionOk(entitypositiontypes_surface, this.level(), blockposition, entitytypes) && SpawnPlacements.checkSpawnRules(entitytypes, worldserver, MobSpawnType.REINFORCEMENT, blockposition, this.level().random)) {
entityzombie.setPos((double) i1, (double) j1, (double) k1);
- if (!this.level().hasNearbyAlivePlayer((double) i1, (double) j1, (double) k1, 7.0D) && this.level().isUnobstructed(entityzombie) && this.level().noCollision((Entity) entityzombie) && !this.level().containsAnyLiquid(entityzombie.getBoundingBox())) {
+ if (!this.level().hasNearbyAlivePlayerThatAffectsSpawning((double) i1, (double) j1, (double) k1, 7.0D) && this.level().isUnobstructed(entityzombie) && this.level().noCollision((Entity) entityzombie) && !this.level().containsAnyLiquid(entityzombie.getBoundingBox())) { // Paper - Affects Spawning API
entityzombie.setTarget(entityliving, EntityTargetEvent.TargetReason.REINFORCEMENT_TARGET, true); // CraftBukkit
entityzombie.finalizeSpawn(worldserver, this.level().getCurrentDifficultyAt(entityzombie.blockPosition()), MobSpawnType.REINFORCEMENT, (SpawnGroupData) null, (CompoundTag) null);
worldserver.addFreshEntityWithPassengers(entityzombie, CreatureSpawnEvent.SpawnReason.REINFORCEMENTS); // CraftBukkit
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 eed6481bc88ed15a5e3fe7056b545ab44ed81983..86d187cadb73dbe0757f9417c4549e358ff303ca 100644
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
@@ -179,6 +179,9 @@ public abstract class Player extends LivingEntity {
@Nullable
public FishingHook fishing;
protected float hurtDir;
+ // Paper start
+ public boolean affectsSpawning = true;
+ // Paper end
// CraftBukkit start
public boolean fauxSleeping;
diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java
index d156f7e3430685947d2b4c30aa867e8002ca70ad..e888cf862662ae6baa6d0de8188aa74a9c6a8e00 100644
--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java
+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java
@@ -56,7 +56,7 @@ public abstract class BaseSpawner {
}
public boolean isNearPlayer(Level world, BlockPos pos) {
- return world.hasNearbyAlivePlayer((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, (double) this.requiredPlayerRange);
+ return world.hasNearbyAlivePlayerThatAffectsSpawning((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, (double) this.requiredPlayerRange); // Paper - Affects Spawning API
}
public void clientTick(Level world, BlockPos pos) {
diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java
index 2ec2b1d9d987c7f31c685aec3d3c87f42758c94b..36d793b492d9776ee36f8285b5bab09e6463cdce 100644
--- a/src/main/java/net/minecraft/world/level/EntityGetter.java
+++ b/src/main/java/net/minecraft/world/level/EntityGetter.java
@@ -82,6 +82,11 @@ public interface EntityGetter {
}
}
+ // Paper start
+ default @Nullable Player findNearbyPlayer(Entity entity, double maxDistance, @Nullable Predicate<Entity> predicate) {
+ return this.getNearestPlayer(entity.getX(), entity.getY(), entity.getZ(), maxDistance, predicate);
+ }
+ // Paper end
@Nullable
default Player getNearestPlayer(double x, double y, double z, double maxDistance, @Nullable Predicate<Entity> targetPredicate) {
double d = -1.0D;
@@ -111,6 +116,20 @@ public interface EntityGetter {
return this.getNearestPlayer(x, y, z, maxDistance, predicate);
}
+ // Paper start
+ default boolean hasNearbyAlivePlayerThatAffectsSpawning(double x, double y, double z, double range) {
+ for (Player player : this.players()) {
+ if (EntitySelector.PLAYER_AFFECTS_SPAWNING.test(player)) { // combines NO_SPECTATORS and LIVING_ENTITY_STILL_ALIVE with an "affects spawning" check
+ double distanceSqr = player.distanceToSqr(x, y, z);
+ if (range < 0.0D || distanceSqr < range * range) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ // Paper end
+
default boolean hasNearbyAlivePlayer(double x, double y, double z, double range) {
for(Player player : this.players()) {
if (EntitySelector.NO_SPECTATORS.test(player) && EntitySelector.LIVING_ENTITY_STILL_ALIVE.test(player)) {
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 24c282c0727fa814c403716837b2d44b216c5b16..e6f67e770f97f239e545c2d4396c86b546c712e0 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -2266,6 +2266,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
return this.getHandle().language;
}
+ // Paper start
+ public void setAffectsSpawning(boolean affects) {
+ this.getHandle().affectsSpawning = affects;
+ }
+
+ @Override
+ public boolean getAffectsSpawning() {
+ return this.getHandle().affectsSpawning;
+ }
+ // Paper end
+
@Override
public void updateCommands() {
if (this.getHandle().connection == null) return;

View file

@ -0,0 +1,233 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Tue, 1 Mar 2016 23:09:29 -0600
Subject: [PATCH] Further improve server tick loop
Improves how the catchup buffer is handled, allowing it to roll both ways
increasing the effeciency of the thread sleep so it only will sleep once.
Also increases the buffer of the catchup to ensure server stays at 20 TPS unless extreme conditions
Previous implementation did not calculate TPS correctly.
Switch to a realistic rolling average and factor in std deviation as an extra reporting variable
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index b082e17b9fbcc0e8ee881a89df1207d26bbeda0b..2955636e2afd425988e9377d4bbe93258fd4e412 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -283,7 +283,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
public OptionSet options;
public org.bukkit.command.ConsoleCommandSender console;
public ConsoleReader reader;
- public static int currentTick = (int) (System.currentTimeMillis() / 50);
+ public static int currentTick = 0; // Paper - Further improve tick loop
public java.util.Queue<Runnable> processQueue = new java.util.concurrent.ConcurrentLinkedQueue<Runnable>();
public int autosavePeriod;
public Commands vanillaCommandDispatcher;
@@ -292,7 +292,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
// Spigot start
public static final int TPS = 20;
public static final int TICK_TIME = 1000000000 / MinecraftServer.TPS;
- private static final int SAMPLE_INTERVAL = 100;
+ private static final int SAMPLE_INTERVAL = 20; // Paper
public final double[] recentTps = new double[ 3 ];
// Spigot end
public final io.papermc.paper.configuration.PaperConfigurations paperConfigurations;
@@ -979,6 +979,57 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
{
return ( avg * exp ) + ( tps * ( 1 - exp ) );
}
+
+ // Paper start - Further improve server tick loop
+ private static final long SEC_IN_NANO = 1000000000;
+ private static final long MAX_CATCHUP_BUFFER = TICK_TIME * TPS * 60L;
+ private long lastTick = 0;
+ private long catchupTime = 0;
+ public final RollingAverage tps1 = new RollingAverage(60);
+ public final RollingAverage tps5 = new RollingAverage(60 * 5);
+ public final RollingAverage tps15 = new RollingAverage(60 * 15);
+
+ public static class RollingAverage {
+ private final int size;
+ private long time;
+ private java.math.BigDecimal total;
+ private int index = 0;
+ private final java.math.BigDecimal[] samples;
+ private final long[] times;
+
+ RollingAverage(int size) {
+ this.size = size;
+ this.time = size * SEC_IN_NANO;
+ this.total = dec(TPS).multiply(dec(SEC_IN_NANO)).multiply(dec(size));
+ this.samples = new java.math.BigDecimal[size];
+ this.times = new long[size];
+ for (int i = 0; i < size; i++) {
+ this.samples[i] = dec(TPS);
+ this.times[i] = SEC_IN_NANO;
+ }
+ }
+
+ private static java.math.BigDecimal dec(long t) {
+ return new java.math.BigDecimal(t);
+ }
+ public void add(java.math.BigDecimal x, long t) {
+ time -= times[index];
+ total = total.subtract(samples[index].multiply(dec(times[index])));
+ samples[index] = x;
+ times[index] = t;
+ time += t;
+ total = total.add(x.multiply(dec(t)));
+ if (++index == size) {
+ index = 0;
+ }
+ }
+
+ public double getAverage() {
+ return total.divide(dec(time), 30, java.math.RoundingMode.HALF_UP).doubleValue();
+ }
+ }
+ private static final java.math.BigDecimal TPS_BASE = new java.math.BigDecimal(1E9).multiply(new java.math.BigDecimal(SAMPLE_INTERVAL));
+ // Paper End
// Spigot End
public static volatile RuntimeException chunkSystemCrash; // Paper - rewrite chunk system
@@ -995,7 +1046,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
// Spigot start
Arrays.fill( this.recentTps, 20 );
- long tickSection = Util.getMillis(), tickCount = 1;
+ long tickSection = Util.getNanos(), curTime, tickCount = 1; // Paper
while (this.running) {
// Paper start - rewrite chunk system
// guarantee that nothing can stop the server from halting if it can at least still tick
@@ -1024,15 +1075,22 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
// Spigot start
++MinecraftServer.currentTickLong; // Paper
- if ( tickCount++ % MinecraftServer.SAMPLE_INTERVAL == 0 )
+ if ( ++MinecraftServer.currentTick % MinecraftServer.SAMPLE_INTERVAL == 0 ) // Paper
{
- long curTime = Util.getMillis();
- double currentTps = 1E3 / ( curTime - tickSection ) * MinecraftServer.SAMPLE_INTERVAL;
- this.recentTps[0] = MinecraftServer.calcTps( this.recentTps[0], 0.92, currentTps ); // 1/exp(5sec/1min)
- this.recentTps[1] = MinecraftServer.calcTps( this.recentTps[1], 0.9835, currentTps ); // 1/exp(5sec/5min)
- this.recentTps[2] = MinecraftServer.calcTps( this.recentTps[2], 0.9945, currentTps ); // 1/exp(5sec/15min)
+ // Paper start
+ curTime = Util.getNanos();
+ final long diff = curTime - tickSection;
+ java.math.BigDecimal currentTps = TPS_BASE.divide(new java.math.BigDecimal(diff), 30, java.math.RoundingMode.HALF_UP);
+ tps1.add(currentTps, diff);
+ tps5.add(currentTps, diff);
+ tps15.add(currentTps, diff);
+ // Backwards compat with bad plugins
+ this.recentTps[0] = tps1.getAverage();
+ this.recentTps[1] = tps5.getAverage();
+ this.recentTps[2] = tps15.getAverage();
+ // Paper end
tickSection = curTime;
- }
+ } else curTime = Util.getNanos(); // Paper
// Spigot end
boolean flag = i == 0L;
@@ -1042,7 +1100,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.debugCommandProfiler = new MinecraftServer.TimeProfiler(Util.getNanos(), this.tickCount);
}
- MinecraftServer.currentTick = (int) (System.currentTimeMillis() / 50); // CraftBukkit
+ //MinecraftServer.currentTick = (int) (System.currentTimeMillis() / 50); // CraftBukkit // Paper - don't overwrite current tick time
+ lastTick = curTime;
this.nextTickTimeNanos += i;
this.startMetricsRecordingTick();
this.profiler.push("tick");
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index d89f832288e197e6c7cf3a0eaab699b3ce1a2c0c..7102165a09afdf6f33257f9fcd6c2c96aefd566a 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -2572,6 +2572,17 @@ public final class CraftServer implements Server {
return CraftMagicNumbers.INSTANCE;
}
+ // Paper - Add getTPS API - Further improve tick loop
+ @Override
+ public double[] getTPS() {
+ return new double[] {
+ net.minecraft.server.MinecraftServer.getServer().tps1.getAverage(),
+ net.minecraft.server.MinecraftServer.getServer().tps5.getAverage(),
+ net.minecraft.server.MinecraftServer.getServer().tps15.getAverage()
+ };
+ }
+ // Paper end
+
// Spigot start
private final org.bukkit.Server.Spigot spigot = new org.bukkit.Server.Spigot()
{
diff --git a/src/main/java/org/spigotmc/TicksPerSecondCommand.java b/src/main/java/org/spigotmc/TicksPerSecondCommand.java
index d9ec48be0fdd2bfea938aa29e36b0f6ffa839ab2..9eb2823cc8f83bad2626fc77578b0162d9ed5782 100644
--- a/src/main/java/org/spigotmc/TicksPerSecondCommand.java
+++ b/src/main/java/org/spigotmc/TicksPerSecondCommand.java
@@ -15,6 +15,12 @@ public class TicksPerSecondCommand extends Command
this.usageMessage = "/tps";
this.setPermission( "bukkit.command.tps" );
}
+ // Paper start
+ private static final net.kyori.adventure.text.Component WARN_MSG = net.kyori.adventure.text.Component.text()
+ .append(net.kyori.adventure.text.Component.text("Warning: ", net.kyori.adventure.text.format.NamedTextColor.RED))
+ .append(net.kyori.adventure.text.Component.text("Memory usage on modern garbage collectors is not a stable value and it is perfectly normal to see it reach max. Please do not pay it much attention.", net.kyori.adventure.text.format.NamedTextColor.GOLD))
+ .build();
+ // Paper end
@Override
public boolean execute(CommandSender sender, String currentAlias, String[] args)
@@ -24,22 +30,40 @@ public class TicksPerSecondCommand extends Command
return true;
}
- StringBuilder sb = new StringBuilder( ChatColor.GOLD + "TPS from last 1m, 5m, 15m: " );
- for ( double tps : MinecraftServer.getServer().recentTps )
- {
- sb.append( this.format( tps ) );
- sb.append( ", " );
+ // Paper start - Further improve tick handling
+ double[] tps = org.bukkit.Bukkit.getTPS();
+ net.kyori.adventure.text.Component[] tpsAvg = new net.kyori.adventure.text.Component[tps.length];
+
+ for ( int i = 0; i < tps.length; i++) {
+ tpsAvg[i] = TicksPerSecondCommand.format( tps[i] );
+ }
+
+ net.kyori.adventure.text.TextComponent.Builder builder = net.kyori.adventure.text.Component.text();
+ builder.append(net.kyori.adventure.text.Component.text("TPS from last 1m, 5m, 15m: ", net.kyori.adventure.text.format.NamedTextColor.GOLD));
+ builder.append(net.kyori.adventure.text.Component.join(net.kyori.adventure.text.JoinConfiguration.commas(true), tpsAvg));
+ sender.sendMessage(builder.asComponent());
+ if (args.length > 0 && args[0].equals("mem") && sender.hasPermission("bukkit.command.tpsmemory")) {
+ sender.sendMessage(net.kyori.adventure.text.Component.text()
+ .append(net.kyori.adventure.text.Component.text("Current Memory Usage: ", net.kyori.adventure.text.format.NamedTextColor.GOLD))
+ .append(net.kyori.adventure.text.Component.text(((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024)) + "/" + (Runtime.getRuntime().totalMemory() / (1024 * 1024)) + " mb (Max: " + (Runtime.getRuntime().maxMemory() / (1024 * 1024)) + " mb)", net.kyori.adventure.text.format.NamedTextColor.GREEN))
+ );
+ if (!this.hasShownMemoryWarning) {
+ sender.sendMessage(WARN_MSG);
+ this.hasShownMemoryWarning = true;
+ }
}
- sender.sendMessage( sb.substring( 0, sb.length() - 2 ) );
- sender.sendMessage(ChatColor.GOLD + "Current Memory Usage: " + ChatColor.GREEN + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024)) + "/" + (Runtime.getRuntime().totalMemory() / (1024 * 1024)) + " mb (Max: "
- + (Runtime.getRuntime().maxMemory() / (1024 * 1024)) + " mb)");
+ // Paper end
return true;
}
- private String format(double tps)
+ private boolean hasShownMemoryWarning; // Paper
+ private static net.kyori.adventure.text.Component format(double tps) // Paper - Made static
{
- return ( ( tps > 18.0 ) ? ChatColor.GREEN : ( tps > 16.0 ) ? ChatColor.YELLOW : ChatColor.RED ).toString()
- + ( ( tps > 20.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 );
+ // Paper
+ net.kyori.adventure.text.format.TextColor color = ( ( tps > 18.0 ) ? net.kyori.adventure.text.format.NamedTextColor.GREEN : ( tps > 16.0 ) ? net.kyori.adventure.text.format.NamedTextColor.YELLOW : net.kyori.adventure.text.format.NamedTextColor.RED );
+ String amount = Math.min(Math.round(tps * 100.0) / 100.0, 20.0) + (tps > 21.0 ? "*" : ""); // Paper - only print * at 21, we commonly peak to 20.02 as the tick sleep is not accurate enough, stop the noise
+ return net.kyori.adventure.text.Component.text(amount, color);
+ // Paper end
}
}

View file

@ -0,0 +1,25 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zach Brown <zach.brown@destroystokyo.com>
Date: Tue, 1 Mar 2016 23:12:03 -0600
Subject: [PATCH] Only refresh abilities if needed
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index e6f67e770f97f239e545c2d4396c86b546c712e0..eb0409c01d8e1259414803495c48ec14179f457b 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -1937,12 +1937,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@Override
public void setFlying(boolean value) {
+ boolean needsUpdate = getHandle().getAbilities().flying != value; // Paper - Only refresh abilities if needed
if (!this.getAllowFlight()) {
Preconditions.checkArgument(!value, "Player is not allowed to fly (check #getAllowFlight())");
}
this.getHandle().getAbilities().flying = value;
- this.getHandle().onUpdateAbilities();
+ if (needsUpdate) this.getHandle().onUpdateAbilities(); // Paper - Only refresh abilities if needed
}
@Override

View file

@ -0,0 +1,158 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Byteflux <byte@byteflux.net>
Date: Tue, 1 Mar 2016 23:45:08 -0600
Subject: [PATCH] Entity Origin API
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 51f0705499003ea71274e1d5c8a77306fa868485..0c8042a515daeeb95b14147214e0a3151ef6f5a1 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -2390,6 +2390,15 @@ public class ServerLevel extends Level implements WorldGenLevel {
entity.updateDynamicGameEventListener(DynamicGameEventListener::add);
entity.valid = true; // CraftBukkit
+ // Paper start - Set origin location when the entity is being added to the world
+ if (entity.getOriginVector() == null) {
+ entity.setOrigin(entity.getBukkitEntity().getLocation());
+ }
+ // Default to current world if unknown, gross assumption but entities rarely change world
+ if (entity.getOriginWorld() == null) {
+ entity.setOrigin(entity.getOriginVector().toLocation(getWorld()));
+ }
+ // Paper end
}
public void onTrackingEnd(Entity entity) {
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index fa3d294b36eb0c23b293466fc72bd2970a452b55..9f3598371c854ec74f3b5752c9779d6c0d99ec39 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -317,7 +317,27 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
public long activatedTick = Integer.MIN_VALUE;
public void inactiveTick() { }
// Spigot end
+ // Paper start
+ @javax.annotation.Nullable
+ private org.bukkit.util.Vector origin;
+ @javax.annotation.Nullable
+ private UUID originWorld;
+
+ public void setOrigin(@javax.annotation.Nonnull Location location) {
+ this.origin = location.toVector();
+ this.originWorld = location.getWorld().getUID();
+ }
+ @javax.annotation.Nullable
+ public org.bukkit.util.Vector getOriginVector() {
+ return this.origin != null ? this.origin.clone() : null;
+ }
+
+ @javax.annotation.Nullable
+ public UUID getOriginWorld() {
+ return this.originWorld;
+ }
+ // Paper end
public float getBukkitYaw() {
return this.yRot;
}
@@ -2093,6 +2113,15 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
this.bukkitEntity.storeBukkitValues(nbttagcompound);
}
// CraftBukkit end
+ // Paper start - Save the entity's origin location
+ if (this.origin != null) {
+ UUID originWorld = this.originWorld != null ? this.originWorld : this.level != null ? this.level.getWorld().getUID() : null;
+ if (originWorld != null) {
+ nbttagcompound.putUUID("Paper.OriginWorld", originWorld);
+ }
+ nbttagcompound.put("Paper.Origin", this.newDoubleList(origin.getX(), origin.getY(), origin.getZ()));
+ }
+ // Paper end
return nbttagcompound;
} catch (Throwable throwable) {
CrashReport crashreport = CrashReport.forThrowable(throwable, "Saving entity NBT");
@@ -2220,6 +2249,20 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
}
// CraftBukkit end
+ // Paper start - Restore the entity's origin location
+ ListTag originTag = nbt.getList("Paper.Origin", 6);
+ if (!originTag.isEmpty()) {
+ UUID originWorld = null;
+ if (nbt.contains("Paper.OriginWorld")) {
+ originWorld = nbt.getUUID("Paper.OriginWorld");
+ } else if (this.level != null) {
+ originWorld = this.level.getWorld().getUID();
+ }
+ this.originWorld = originWorld;
+ origin = new org.bukkit.util.Vector(originTag.getDouble(0), originTag.getDouble(1), originTag.getDouble(2));
+ }
+ // Paper end
+
} catch (Throwable throwable) {
CrashReport crashreport = CrashReport.forThrowable(throwable, "Loading entity NBT");
CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being loaded");
diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
index 5d09790876c3c50d126678565001645f6aece16f..6c4224e4752b655710c5b992d9acf9563b183483 100644
--- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
+++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
@@ -343,6 +343,14 @@ public class FallingBlockEntity extends Entity {
this.blockState = Blocks.SAND.defaultBlockState();
}
+ // Paper start - Try and load origin location from the old NBT tags for backwards compatibility
+ if (nbt.contains("SourceLoc_x")) {
+ int srcX = nbt.getInt("SourceLoc_x");
+ int srcY = nbt.getInt("SourceLoc_y");
+ int srcZ = nbt.getInt("SourceLoc_z");
+ this.setOrigin(new org.bukkit.Location(this.level().getWorld(), srcX, srcY, srcZ));
+ }
+ // Paper end
}
public void setHurtsEntities(float fallHurtAmount, int fallHurtMax) {
diff --git a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java
index f08c021f867c00611139a17db48352944eb2aa99..5c3b86e2301079e775971aa4da6a8f2dc6a40d1f 100644
--- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java
+++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java
@@ -132,6 +132,14 @@ public class PrimedTnt extends Entity implements TraceableEntity {
this.setBlockState(NbtUtils.readBlockState(this.level().holderLookup(Registries.BLOCK), nbt.getCompound("block_state")));
}
+ // Paper start - Try and load origin location from the old NBT tags for backwards compatibility
+ if (nbt.contains("SourceLoc_x")) {
+ int srcX = nbt.getInt("SourceLoc_x");
+ int srcY = nbt.getInt("SourceLoc_y");
+ int srcZ = nbt.getInt("SourceLoc_z");
+ this.setOrigin(new org.bukkit.Location(this.level().getWorld(), srcX, srcY, srcZ));
+ }
+ // Paper end
}
@Nullable
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index 9efb4615d6d196a658940a2211c73af46e1c54b5..beae7b8cf726f61b25c5afb553da8c34dce1dd37 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -1316,5 +1316,20 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
return ret;
}
+
+ @Override
+ public Location getOrigin() {
+ Vector originVector = this.getHandle().getOriginVector();
+ if (originVector == null) {
+ return null;
+ }
+ World world = this.getWorld();
+ if (this.getHandle().getOriginWorld() != null) {
+ world = org.bukkit.Bukkit.getWorld(this.getHandle().getOriginWorld());
+ }
+
+ //noinspection ConstantConditions
+ return originVector.toLocation(world);
+ }
// Paper end
}

View file

@ -0,0 +1,66 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Tue, 1 Mar 2016 23:52:34 -0600
Subject: [PATCH] Prevent tile entity and entity crashes
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index 9369e0346a6b511a332d54577c781c3d2c2b5c86..8bfab45b506aa514956a99354a7dc5009ffa9cbf 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -739,11 +739,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
try {
tickConsumer.accept(entity);
} catch (Throwable throwable) {
- CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking entity");
- CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being ticked");
-
- entity.fillCrashReportCategory(crashreportsystemdetails);
- throw new ReportedException(crashreport);
+ // Paper start - Prevent tile entity and entity crashes
+ final String msg = String.format("Entity threw exception at %s:%s,%s,%s", entity.level().getWorld().getName(), entity.getX(), entity.getY(), entity.getZ());
+ MinecraftServer.LOGGER.error(msg, throwable);
+ entity.discard();
+ // Paper end
}
}
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 b300d12e9e00519028b53aca9c3fb01f589eaa91..63acd109a79ed752a05df3d4f1b99309297c2055 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
@@ -213,7 +213,12 @@ public abstract class BlockEntity {
return minecraftkey + " // " + this.getClass().getCanonicalName();
});
if (this.level != null) {
- CrashReportCategory.populateBlockDetails(crashReportSection, this.level, this.worldPosition, this.getBlockState());
+ // Paper start - Prevent TileEntity and Entity crashes
+ BlockState block = this.getBlockState();
+ if (block != null) {
+ CrashReportCategory.populateBlockDetails(crashReportSection, this.level, this.worldPosition, block);
+ }
+ // Paper end
CrashReportCategory.populateBlockDetails(crashReportSection, this.level, this.worldPosition, this.level.getBlockState(this.worldPosition));
}
}
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
index c2663fadd2c714b25fe411777ca9be957c3545df..86bcebd778e5d51e1029b96048145622cd2811f3 100644
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
@@ -1143,11 +1143,11 @@ public class LevelChunk extends ChunkAccess {
gameprofilerfiller.pop();
} catch (Throwable throwable) {
- CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking block entity");
- CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block entity being ticked");
-
- this.blockEntity.fillCrashReportCategory(crashreportsystemdetails);
- throw new ReportedException(crashreport);
+ // Paper start - Prevent tile entity and entity crashes
+ final String msg = String.format("BlockEntity threw exception at %s:%s,%s,%s", LevelChunk.this.getLevel().getWorld().getName(), this.getPos().getX(), this.getPos().getY(), this.getPos().getZ());
+ net.minecraft.server.MinecraftServer.LOGGER.error(msg, throwable);
+ LevelChunk.this.removeBlockEntity(this.getPos());
+ // Paper end
// Spigot start
} finally {
this.blockEntity.tickTimer.stopTiming();

View file

@ -0,0 +1,49 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zach Brown <zach.brown@destroystokyo.com>
Date: Tue, 1 Mar 2016 23:58:50 -0600
Subject: [PATCH] Configurable top of nether void damage
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 9f3598371c854ec74f3b5752c9779d6c0d99ec39..450a55fd1b01ac67d911d152a04a3dee3aa0a2e9 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -720,7 +720,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
}
public void checkBelowWorld() {
- if (this.getY() < (double) (this.level().getMinBuildHeight() - 64)) {
+ // Paper start - Configurable nether ceiling damage
+ if (this.getY() < (double) (this.level.getMinBuildHeight() - 64) || (this.level.getWorld().getEnvironment() == org.bukkit.World.Environment.NETHER
+ && this.level.paperConfig().environment.netherCeilingVoidDamageHeight.test(v -> this.getY() >= v)
+ && (!(this instanceof Player player) || !player.getAbilities().invulnerable))) {
+ // Paper end
this.onBelowWorld();
}
diff --git a/src/main/java/net/minecraft/world/level/portal/PortalForcer.java b/src/main/java/net/minecraft/world/level/portal/PortalForcer.java
index 02e3322ec41108fe9275510e2daa833d180353dc..0762bb248b3bd43a06e89aa1893a6189f0e13866 100644
--- a/src/main/java/net/minecraft/world/level/portal/PortalForcer.java
+++ b/src/main/java/net/minecraft/world/level/portal/PortalForcer.java
@@ -55,7 +55,7 @@ public class PortalForcer {
Optional<PoiRecord> optional = villageplace.getInSquare((holder) -> {
return holder.is(PoiTypes.NETHER_PORTAL);
}, blockposition, i, PoiManager.Occupancy.ANY).filter((villageplacerecord) -> {
- return worldborder.isWithinBounds(villageplacerecord.getPos());
+ return worldborder.isWithinBounds(villageplacerecord.getPos()) && !(this.level.getTypeKey() == net.minecraft.world.level.dimension.LevelStem.NETHER && this.level.paperConfig().environment.netherCeilingVoidDamageHeight.test(v -> villageplacerecord.getPos().getY() >= v)); // Paper - don't teleport into void damage
}).sorted(Comparator.comparingDouble((PoiRecord villageplacerecord) -> { // CraftBukkit - decompile error
return villageplacerecord.getPos().distSqr(blockposition);
}).thenComparingInt((villageplacerecord) -> {
@@ -90,6 +90,11 @@ public class PortalForcer {
BlockPos blockposition2 = null;
WorldBorder worldborder = this.level.getWorldBorder();
int i = Math.min(this.level.getMaxBuildHeight(), this.level.getMinBuildHeight() + this.level.getLogicalHeight()) - 1;
+ // Paper start - if ceiling void damage is enabled, make sure the max height doesn't exceed the void damage height
+ if (this.level.getTypeKey() == net.minecraft.world.level.dimension.LevelStem.NETHER && this.level.paperConfig().environment.netherCeilingVoidDamageHeight.enabled()) {
+ i = Math.min(i, this.level.paperConfig().environment.netherCeilingVoidDamageHeight.intValue() - 1);
+ }
+ // Paper end
BlockPos.MutableBlockPos blockposition_mutableblockposition = blockposition.mutable();
Iterator iterator = BlockPos.spiralAround(blockposition, createRadius, Direction.EAST, Direction.SOUTH).iterator(); // CraftBukkit

View file

@ -0,0 +1,19 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zach Brown <zach.brown@destroystokyo.com>
Date: Wed, 2 Mar 2016 00:03:55 -0600
Subject: [PATCH] Check online mode before converting and renaming player data
diff --git a/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java b/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java
index 3d74ffc6e38b0dbe7ca6d8d84a63f78d6b1908a7..08f4cc47ec3aa4dd6980ba543219891a510b010b 100644
--- a/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java
+++ b/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java
@@ -60,7 +60,7 @@ public class PlayerDataStorage {
File file = new File(this.playerDir, player.getStringUUID() + ".dat");
// Spigot Start
boolean usingWrongFile = false;
- if ( !file.exists() )
+ if ( org.bukkit.Bukkit.getOnlineMode() && !file.exists() ) // Paper - Check online mode first
{
file = new File( this.playerDir, java.util.UUID.nameUUIDFromBytes( ( "OfflinePlayer:" + player.getScoreboardName() ).getBytes( "UTF-8" ) ).toString() + ".dat");
if ( file.exists() )

View file

@ -0,0 +1,18 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zach Brown <zach.brown@destroystokyo.com>
Date: Wed, 2 Mar 2016 00:32:25 -0600
Subject: [PATCH] Always tick falling blocks
diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java
index 47e7fd7baf3ec6ed3ec9b5e6d73ed8611c2b1ce1..e4efed4e50188b71ff30238b3517a924b45b24b8 100644
--- a/src/main/java/org/spigotmc/ActivationRange.java
+++ b/src/main/java/org/spigotmc/ActivationRange.java
@@ -89,6 +89,7 @@ public class ActivationRange
|| entity instanceof AbstractHurtingProjectile
|| entity instanceof LightningBolt
|| entity instanceof PrimedTnt
+ || entity instanceof net.minecraft.world.entity.item.FallingBlockEntity // Paper - Always tick falling blocks
|| entity instanceof EndCrystal
|| entity instanceof FireworkRocketEntity
|| entity instanceof ThrownTrident )

View file

@ -0,0 +1,18 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: DoctorDark <doctordark11@gmail.com>
Date: Wed, 16 Mar 2016 02:21:39 -0500
Subject: [PATCH] Configurable end credits
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index b6939932a4b8800c8751125a4a6d4dcea39110c1..bf89ea0f7506434848cb9c1cbfb3fe6dd2eb3212 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -1074,6 +1074,7 @@ public class ServerPlayer extends Player {
this.unRide();
this.serverLevel().removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION);
if (!this.wonGame) {
+ if (this.level().paperConfig().misc.disableEndCredits) this.seenCredits = true; // Paper - Toggle to always disable end credits
this.wonGame = true;
this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.WIN_GAME, this.seenCredits ? 0.0F : 1.0F));
this.seenCredits = true;

View file

@ -0,0 +1,19 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Iceee <andrew@opticgaming.tv>
Date: Wed, 2 Mar 2016 01:39:52 -0600
Subject: [PATCH] Fix lag from explosions processing dead entities
diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java
index 725ea53e6143d29f9619e1045341bc30155b248e..c5d644876e0c92a444a574ee7571227e19b28482 100644
--- a/src/main/java/net/minecraft/world/level/Explosion.java
+++ b/src/main/java/net/minecraft/world/level/Explosion.java
@@ -225,7 +225,7 @@ public class Explosion {
int i1 = Mth.floor(this.y + (double) f2 + 1.0D);
int j1 = Mth.floor(this.z - (double) f2 - 1.0D);
int k1 = Mth.floor(this.z + (double) f2 + 1.0D);
- List<Entity> list = this.level.getEntities(this.source, new AABB((double) i, (double) l, (double) j1, (double) j, (double) i1, (double) k1));
+ List<Entity> list = this.level.getEntities(this.source, new AABB((double) i, (double) l, (double) j1, (double) j, (double) i1, (double) k1), (com.google.common.base.Predicate<Entity>) entity -> entity.isAlive() && !entity.isSpectator()); // Paper - Fix lag from explosions processing dead entities
Vec3 vec3d = new Vec3(this.x, this.y, this.z);
Iterator iterator = list.iterator();

View file

@ -0,0 +1,133 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Byteflux <byte@byteflux.net>
Date: Wed, 2 Mar 2016 11:59:48 -0600
Subject: [PATCH] Optimize explosions
The process of determining an entity's exposure from explosions can be
expensive when there are hundreds or more entities in range.
This patch adds a per-tick cache that is used for storing and retrieving
an entity's exposure during an explosion.
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 2955636e2afd425988e9377d4bbe93258fd4e412..6986109ca6de3c73d63c4539477997361044e64f 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1492,6 +1492,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.profiler.pop();
this.profiler.pop();
+ worldserver.explosionDensityCache.clear(); // Paper - Optimize explosions
}
this.profiler.popPush("connection");
diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java
index c5d644876e0c92a444a574ee7571227e19b28482..4e382cfae7a3a1889bc36bad24c6ea38b7eb14a6 100644
--- a/src/main/java/net/minecraft/world/level/Explosion.java
+++ b/src/main/java/net/minecraft/world/level/Explosion.java
@@ -279,7 +279,7 @@ public class Explosion {
// CraftBukkit end
}
- double d12 = (1.0D - d7) * (double) Explosion.getSeenPercent(vec3d, entity);
+ double d12 = (1.0D - d7) * this.getBlockDensity(vec3d, entity); // Paper - Optimize explosions
double d13;
if (entity instanceof LivingEntity) {
@@ -520,4 +520,84 @@ public class Explosion {
private BlockInteraction() {}
}
+ // Paper start - Optimize explosions
+ private float getBlockDensity(Vec3 vec3d, Entity entity) {
+ if (!this.level.paperConfig().environment.optimizeExplosions) {
+ return getSeenPercent(vec3d, entity);
+ }
+ CacheKey key = new CacheKey(this, entity.getBoundingBox());
+ Float blockDensity = this.level.explosionDensityCache.get(key);
+ if (blockDensity == null) {
+ blockDensity = getSeenPercent(vec3d, entity);
+ this.level.explosionDensityCache.put(key, blockDensity);
+ }
+
+ return blockDensity;
+ }
+
+ static class CacheKey {
+ private final Level world;
+ private final double posX, posY, posZ;
+ private final double minX, minY, minZ;
+ private final double maxX, maxY, maxZ;
+
+ public CacheKey(Explosion explosion, AABB aabb) {
+ this.world = explosion.level;
+ this.posX = explosion.x;
+ this.posY = explosion.y;
+ this.posZ = explosion.z;
+ this.minX = aabb.minX;
+ this.minY = aabb.minY;
+ this.minZ = aabb.minZ;
+ this.maxX = aabb.maxX;
+ this.maxY = aabb.maxY;
+ this.maxZ = aabb.maxZ;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ CacheKey cacheKey = (CacheKey) o;
+
+ if (Double.compare(cacheKey.posX, posX) != 0) return false;
+ if (Double.compare(cacheKey.posY, posY) != 0) return false;
+ if (Double.compare(cacheKey.posZ, posZ) != 0) return false;
+ if (Double.compare(cacheKey.minX, minX) != 0) return false;
+ if (Double.compare(cacheKey.minY, minY) != 0) return false;
+ if (Double.compare(cacheKey.minZ, minZ) != 0) return false;
+ if (Double.compare(cacheKey.maxX, maxX) != 0) return false;
+ if (Double.compare(cacheKey.maxY, maxY) != 0) return false;
+ if (Double.compare(cacheKey.maxZ, maxZ) != 0) return false;
+ return world.equals(cacheKey.world);
+ }
+
+ @Override
+ public int hashCode() {
+ int result;
+ long temp;
+ result = world.hashCode();
+ temp = Double.doubleToLongBits(posX);
+ result = 31 * result + (int) (temp ^ (temp >>> 32));
+ temp = Double.doubleToLongBits(posY);
+ result = 31 * result + (int) (temp ^ (temp >>> 32));
+ temp = Double.doubleToLongBits(posZ);
+ result = 31 * result + (int) (temp ^ (temp >>> 32));
+ temp = Double.doubleToLongBits(minX);
+ result = 31 * result + (int) (temp ^ (temp >>> 32));
+ temp = Double.doubleToLongBits(minY);
+ result = 31 * result + (int) (temp ^ (temp >>> 32));
+ temp = Double.doubleToLongBits(minZ);
+ result = 31 * result + (int) (temp ^ (temp >>> 32));
+ temp = Double.doubleToLongBits(maxX);
+ result = 31 * result + (int) (temp ^ (temp >>> 32));
+ temp = Double.doubleToLongBits(maxY);
+ result = 31 * result + (int) (temp ^ (temp >>> 32));
+ temp = Double.doubleToLongBits(maxZ);
+ result = 31 * result + (int) (temp ^ (temp >>> 32));
+ return result;
+ }
+ }
+ // Paper end
}
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index 8bfab45b506aa514956a99354a7dc5009ffa9cbf..cf081c6d270053b7d9a042b65495fe17f0ee4826 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -170,6 +170,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
private org.spigotmc.TickLimiter entityLimiter;
private org.spigotmc.TickLimiter tileLimiter;
private int tileTickPosition;
+ public final Map<Explosion.CacheKey, Float> explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions
public CraftWorld getWorld() {
return this.world;

View file

@ -0,0 +1,28 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sudzzy <originmc@outlook.com>
Date: Wed, 2 Mar 2016 14:48:03 -0600
Subject: [PATCH] Disable explosion knockback
diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java
index 4e382cfae7a3a1889bc36bad24c6ea38b7eb14a6..e59348b849a71ff5eba5bd74a9e2819a560787db 100644
--- a/src/main/java/net/minecraft/world/level/Explosion.java
+++ b/src/main/java/net/minecraft/world/level/Explosion.java
@@ -285,7 +285,7 @@ public class Explosion {
if (entity instanceof LivingEntity) {
LivingEntity entityliving = (LivingEntity) entity;
- d13 = ProtectionEnchantment.getExplosionKnockbackAfterDampener(entityliving, d12);
+ d13 = entity instanceof Player && level.paperConfig().environment.disableExplosionKnockback ? 0 : ProtectionEnchantment.getExplosionKnockbackAfterDampener(entityliving, d12); // Paper - disable explosion knockback
} else {
d13 = d12;
}
@@ -299,7 +299,7 @@ public class Explosion {
if (entity instanceof Player) {
Player entityhuman = (Player) entity;
- if (!entityhuman.isSpectator() && (!entityhuman.isCreative() || !entityhuman.getAbilities().flying)) {
+ if (!entityhuman.isSpectator() && (!entityhuman.isCreative() || !entityhuman.getAbilities().flying) && !level.paperConfig().environment.disableExplosionKnockback) { // Paper - Disable explosion knockback
this.hitPlayers.put(entityhuman, vec3d1);
}
}

View file

@ -0,0 +1,19 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sudzzy <originmc@outlook.com>
Date: Wed, 2 Mar 2016 14:52:43 -0600
Subject: [PATCH] Disable thunder
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 0c8042a515daeeb95b14147214e0a3151ef6f5a1..3c324ffd8300da534a9877b677294ebcd7949622 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -842,7 +842,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
ProfilerFiller gameprofilerfiller = this.getProfiler();
gameprofilerfiller.push("thunder");
- if (flag && this.isThundering() && this.spigotConfig.thunderChance > 0 && this.random.nextInt(this.spigotConfig.thunderChance) == 0) { // Spigot
+ if (!this.paperConfig().environment.disableThunder && flag && this.isThundering() && this.spigotConfig.thunderChance > 0 && this.random.nextInt(this.spigotConfig.thunderChance) == 0) { // Spigot // Paper - disable thunder
BlockPos blockposition = this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15));
if (this.isRainingAt(blockposition)) {

View file

@ -0,0 +1,24 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sudzzy <originmc@outlook.com>
Date: Wed, 2 Mar 2016 14:57:24 -0600
Subject: [PATCH] Disable ice and snow
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 3c324ffd8300da534a9877b677294ebcd7949622..fa6cec1933582fefeffd9382cbc24fea83b5eb13 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -872,11 +872,13 @@ public class ServerLevel extends Level implements WorldGenLevel {
gameprofilerfiller.popPush("iceandsnow");
+ if (!this.paperConfig().environment.disableIceAndSnow) { // Paper
for (int l = 0; l < randomTickSpeed; ++l) {
if (this.random.nextInt(48) == 0) {
this.tickPrecipitation(this.getBlockRandomPos(j, 0, k, 15));
}
}
+ } // Paper
gameprofilerfiller.popPush("tickBlocks");
timings.chunkTicksBlocks.startTiming(); // Paper

View file

@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sudzzy <originmc@outlook.com>
Date: Wed, 2 Mar 2016 15:03:53 -0600
Subject: [PATCH] Configurable mob spawner tick rate
diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java
index e888cf862662ae6baa6d0de8188aa74a9c6a8e00..bd48f49d50709354abc5bcff155b5abb9ab20191 100644
--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java
+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java
@@ -47,6 +47,7 @@ public abstract class BaseSpawner {
public int maxNearbyEntities = 6;
public int requiredPlayerRange = 16;
public int spawnRange = 4;
+ private int tickDelay = 0; // Paper
public BaseSpawner() {}
@@ -81,13 +82,18 @@ public abstract class BaseSpawner {
}
public void serverTick(ServerLevel world, BlockPos pos) {
+ // Paper start - Configurable mob spawner tick rate
+ if (spawnDelay > 0 && --tickDelay > 0) return;
+ tickDelay = world.paperConfig().tickRates.mobSpawner;
+ if (tickDelay == -1) { return; } // If disabled
+ // Paper end
if (this.isNearPlayer(world, pos)) {
- if (this.spawnDelay == -1) {
+ if (this.spawnDelay < -tickDelay) {
this.delay(world, pos);
}
if (this.spawnDelay > 0) {
- --this.spawnDelay;
+ this.spawnDelay -= tickDelay; // Paper
} else {
boolean flag = false;
RandomSource randomsource = world.getRandom();

View file

@ -0,0 +1,56 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Isaac Moore <rmsy@me.com>
Date: Tue, 19 Apr 2016 14:09:31 -0500
Subject: [PATCH] Implement PlayerLocaleChangeEvent
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index bf89ea0f7506434848cb9c1cbfb3fe6dd2eb3212..686b42a9b4475fe3d530a9b950c1cc8f04717a65 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -222,7 +222,7 @@ public class ServerPlayer extends Player {
private int levitationStartTime;
private boolean disconnected;
private int requestedViewDistance;
- public String language = "en_us"; // CraftBukkit - default
+ public String language = null; // CraftBukkit - default // Paper - default to null
public java.util.Locale adventure$locale = java.util.Locale.US; // Paper
@Nullable
private Vec3 startingToFallPosition;
@@ -316,7 +316,7 @@ public class ServerPlayer extends Player {
this.lastActionTime = Util.getMillis();
this.recipeBook = new ServerRecipeBook();
this.requestedViewDistance = 2;
- this.language = "en_us";
+ this.language = null; // Paper - default to null
this.lastSectionPos = SectionPos.of(0, 0, 0);
this.chunkTrackingView = ChunkTrackingView.EMPTY;
this.respawnDimension = Level.OVERWORLD;
@@ -1964,9 +1964,10 @@ public class ServerPlayer extends Player {
PlayerChangedMainHandEvent event = new PlayerChangedMainHandEvent(this.getBukkitEntity(), this.getMainArm() == HumanoidArm.LEFT ? MainHand.LEFT : MainHand.RIGHT);
this.server.server.getPluginManager().callEvent(event);
}
- if (!this.language.equals(clientOptions.language())) {
+ if (this.language == null || !this.language.equals(clientOptions.language())) { // Paper
PlayerLocaleChangeEvent event = new PlayerLocaleChangeEvent(this.getBukkitEntity(), clientOptions.language());
this.server.server.getPluginManager().callEvent(event);
+ this.server.server.getPluginManager().callEvent(new com.destroystokyo.paper.event.player.PlayerLocaleChangeEvent(this.getBukkitEntity(), this.language, clientOptions.language())); // Paper
}
// CraftBukkit end
this.language = clientOptions.language();
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index eb0409c01d8e1259414803495c48ec14179f457b..1e395d14382c79231dc81d6cf7ea864e45906add 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -2264,7 +2264,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@Override
public String getLocale() {
- return this.getHandle().language;
+ // Paper start - Locale change event
+ final String locale = this.getHandle().language;
+ return locale != null ? locale : "en_us";
+ // Paper end
}
// Paper start

View file

@ -0,0 +1,62 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Byteflux <byte@byteflux.net>
Date: Wed, 2 Mar 2016 23:30:53 -0600
Subject: [PATCH] Add BeaconEffectEvent
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
index 9fb27f93a7ccbf64f9babf19f626d1f45b1c7103..18349957bd6d1a4bc21aff781a791f912dddff1d 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
@@ -43,6 +43,10 @@ import net.minecraft.world.phys.AABB;
import org.bukkit.craftbukkit.potion.CraftPotionUtil;
import org.bukkit.potion.PotionEffect;
// CraftBukkit end
+// Paper start
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import com.destroystokyo.paper.event.block.BeaconEffectEvent;
+// Paper end
public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Nameable {
@@ -289,15 +293,23 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name
}
}
- private static void applyEffect(List list, MobEffect mobeffectlist, int j, int b0) {
- {
+ private static void applyEffect(List list, MobEffect effects, int i, int b0, boolean isPrimary, BlockPos worldPosition) { // Paper - BeaconEffectEvent
+ if (!list.isEmpty()) { // Paper - BeaconEffectEvent
Iterator iterator = list.iterator();
Player entityhuman;
+ // Paper start - BeaconEffectEvent
+ org.bukkit.block.Block block = ((Player) list.get(0)).level().getWorld().getBlockAt(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ());
+ PotionEffect effect = CraftPotionUtil.toBukkit(new MobEffectInstance(effects, i, b0, true, true));
+ // Paper end
while (iterator.hasNext()) {
- entityhuman = (Player) iterator.next();
- entityhuman.addEffect(new MobEffectInstance(mobeffectlist, j, b0, true, true), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.BEACON);
+ // Paper start - BeaconEffectEvent
+ entityhuman = (ServerPlayer) iterator.next();
+ BeaconEffectEvent event = new BeaconEffectEvent(block, effect, (org.bukkit.entity.Player) entityhuman.getBukkitEntity(), isPrimary);
+ if (CraftEventFactory.callEvent(event).isCancelled()) continue;
+ entityhuman.addEffect(new MobEffectInstance(CraftPotionUtil.fromBukkit(event.getEffect())), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.BEACON);
+ // Paper end
}
}
}
@@ -320,10 +332,10 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name
int j = BeaconBlockEntity.getLevel(beaconLevel);
List list = BeaconBlockEntity.getHumansInRange(world, pos, beaconLevel);
- BeaconBlockEntity.applyEffect(list, primaryEffect, j, b0);
+ BeaconBlockEntity.applyEffect(list, primaryEffect, j, b0, true, pos); // Paper - BeaconEffectEvent
if (BeaconBlockEntity.hasSecondaryEffect(beaconLevel, primaryEffect, secondaryEffect)) {
- BeaconBlockEntity.applyEffect(list, secondaryEffect, j, 0);
+ BeaconBlockEntity.applyEffect(list, secondaryEffect, j, 0, false, pos); // Paper - BeaconEffectEvent
}
}

View file

@ -0,0 +1,32 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sudzzy <originmc@outlook.com>
Date: Wed, 2 Mar 2016 23:34:44 -0600
Subject: [PATCH] Configurable container update tick rate
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index 686b42a9b4475fe3d530a9b950c1cc8f04717a65..d986c09392182335112040d4b6feae6a1a740d84 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -247,6 +247,7 @@ public class ServerPlayer extends Player {
private RemoteChatSession chatSession;
private int containerCounter;
public boolean wonGame;
+ private int containerUpdateDelay; // Paper
// CraftBukkit start
public String displayName;
@@ -683,7 +684,12 @@ public class ServerPlayer extends Player {
--this.invulnerableTime;
}
- this.containerMenu.broadcastChanges();
+ // Paper start - Configurable container update tick rate
+ if (--containerUpdateDelay <= 0) {
+ this.containerMenu.broadcastChanges();
+ containerUpdateDelay = this.level().paperConfig().tickRates.containerUpdate;
+ }
+ // Paper end
if (!this.level().isClientSide && !this.containerMenu.stillValid(this)) {
this.closeContainer();
this.containerMenu = this.inventoryMenu;

View file

@ -0,0 +1,25 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Techcable <Techcable@outlook.com>
Date: Wed, 2 Mar 2016 23:42:37 -0600
Subject: [PATCH] Use UserCache for player heads
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java
index 51e94e6f97a7c75e2281ad751c8e2dbee2e28afd..062594cebbe8cc0a0c94ecf7c8da4ee349a27521 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java
@@ -211,7 +211,13 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta {
if (name == null) {
this.setProfile(null);
} else {
- this.setProfile(new GameProfile(Util.NIL_UUID, name));
+ // Paper start - Use Online Players Skull
+ GameProfile newProfile = null;
+ net.minecraft.server.level.ServerPlayer player = net.minecraft.server.MinecraftServer.getServer().getPlayerList().getPlayerByName(name);
+ if (player != null) newProfile = player.getGameProfile();
+ if (newProfile == null) newProfile = new GameProfile(Util.NIL_UUID, name);
+ this.setProfile(newProfile);
+ // Paper end
}
return true;

View file

@ -0,0 +1,21 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zach Brown <zach.brown@destroystokyo.com>
Date: Wed, 2 Mar 2016 23:45:17 -0600
Subject: [PATCH] Disable spigot tick limiters
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index cf081c6d270053b7d9a042b65495fe17f0ee4826..ac169632113c3d2177910723ce920cd9a4f7af66 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -705,9 +705,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
boolean flag = this.tickRateManager().runsNormally();
int tilesThisCycle = 0;
- for (this.tileLimiter.initTick();
- tilesThisCycle < this.blockEntityTickers.size() && (tilesThisCycle % 10 != 0 || this.tileLimiter.shouldContinue());
- this.tileTickPosition++, tilesThisCycle++) {
+ for (tileTickPosition = 0; tileTickPosition < this.blockEntityTickers.size(); tileTickPosition++) { // Paper - Disable tick limiters
this.tileTickPosition = (this.tileTickPosition < this.blockEntityTickers.size()) ? this.tileTickPosition : 0;
TickingBlockEntity tickingblockentity = (TickingBlockEntity) this.blockEntityTickers.get(this.tileTickPosition);
// Spigot start

View file

@ -0,0 +1,38 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Steve Anton <anxuiz.nx@gmail.com>
Date: Thu, 3 Mar 2016 00:09:38 -0600
Subject: [PATCH] Add PlayerInitialSpawnEvent
For modifying a player's initial spawn location as they join the server
This is a duplicate API from spigot, so use our duplicate subclass and
improve setPosition to use raw
== AT ==
public net.minecraft.world.entity.Entity setRot(FF)V
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index fdf3bf3decb14378f5e59e41bab26e965bc7be14..b74689297ca20efee391fe1da80377082d1758e5 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -227,7 +227,7 @@ public abstract class PlayerList {
// Spigot start - spawn location event
Player spawnPlayer = player.getBukkitEntity();
- org.spigotmc.event.player.PlayerSpawnLocationEvent ev = new org.spigotmc.event.player.PlayerSpawnLocationEvent(spawnPlayer, spawnPlayer.getLocation());
+ org.spigotmc.event.player.PlayerSpawnLocationEvent ev = new com.destroystokyo.paper.event.player.PlayerInitialSpawnEvent(spawnPlayer, spawnPlayer.getLocation()); // Paper use our duplicate event
this.cserver.getPluginManager().callEvent(ev);
Location loc = ev.getSpawnLocation();
@@ -235,7 +235,10 @@ public abstract class PlayerList {
player.spawnIn(worldserver1);
player.gameMode.setLevel((ServerLevel) player.level());
- player.absMoveTo(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch());
+ // Paper start - set raw so we aren't fully joined to the world (not added to chunk or world)
+ player.setPosRaw(loc.getX(), loc.getY(), loc.getZ());
+ player.setRot(loc.getYaw(), loc.getPitch());
+ // Paper end
// Spigot end
// CraftBukkit - Moved message to after join