Moar, fix API
This commit is contained in:
parent
0edb5458e5
commit
dfab659e53
165 changed files with 559 additions and 576 deletions
|
@ -1,20 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Fri, 18 Mar 2016 15:12:22 -0400
|
||||
Subject: [PATCH] Configurable Non Player Arrow Despawn Rate
|
||||
|
||||
Can set a much shorter despawn rate for arrows that players can not pick up.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
|
||||
index 0e3c8edf0891e815a67020bb094866fd47102d67..62cb9dff53d980399913c913893fca2c1110d184 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
|
||||
@@ -311,7 +311,7 @@ public abstract class AbstractArrow extends Projectile {
|
||||
|
||||
protected void tickDespawn() {
|
||||
++this.life;
|
||||
- if (this.life >= ((this instanceof ThrownTrident) ? level.spigotConfig.tridentDespawnRate : level.spigotConfig.arrowDespawnRate)) { // Spigot
|
||||
+ if (this.life >= (pickup == Pickup.CREATIVE_ONLY ? level.paperConfig().entities.spawning.creativeArrowDespawnRate.value() : (pickup == Pickup.DISALLOWED ? level.paperConfig().entities.spawning.nonPlayerArrowDespawnRate.value() : ((this instanceof ThrownTrident) ? level.spigotConfig.tridentDespawnRate : level.spigotConfig.arrowDespawnRate)))) { // Spigot // Paper - TODO: Extract this to init?
|
||||
this.discard();
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Fri, 18 Mar 2016 20:16:03 -0400
|
||||
Subject: [PATCH] Add World Util Methods
|
||||
|
||||
Methods that can be used for other patches to help improve logic.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 29e432e9bea9da307c96d42d9b45d1c3a3161fa1..d0e069e2dd950f2fe0d51594ceddcbbe44458acd 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -216,7 +216,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
public final LevelStorageSource.LevelStorageAccess convertable;
|
||||
public final UUID uuid;
|
||||
|
||||
- public LevelChunk getChunkIfLoaded(int x, int z) {
|
||||
+ @Override public LevelChunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI
|
||||
return this.chunkSource.getChunk(x, z, false);
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
||||
index 65fd3a3c1f0a55d034e6f91c4f222e6454e7166c..62c54a0c789ca460ec29b0c653f5abd113736fb9 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/Level.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
||||
@@ -333,6 +333,22 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
return chunk == null ? null : chunk.getFluidState(blockposition);
|
||||
}
|
||||
|
||||
+ public final boolean isLoadedAndInBounds(BlockPos blockposition) { // Paper - final for inline
|
||||
+ return getWorldBorder().isWithinBounds(blockposition) && getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) != null;
|
||||
+ }
|
||||
+
|
||||
+ public @Nullable LevelChunk getChunkIfLoaded(int x, int z) { // Overridden in WorldServer for ABI compat which has final
|
||||
+ return ((ServerLevel) this).getChunkSource().getChunkAtIfLoadedImmediately(x, z);
|
||||
+ }
|
||||
+ public final @Nullable LevelChunk getChunkIfLoaded(BlockPos blockposition) {
|
||||
+ return ((ServerLevel) this).getChunkSource().getChunkAtIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4);
|
||||
+ }
|
||||
+
|
||||
+ // reduces need to do isLoaded before getType
|
||||
+ public final @Nullable BlockState getBlockStateIfLoadedAndInBounds(BlockPos blockposition) {
|
||||
+ return getWorldBorder().isWithinBounds(blockposition) ? getBlockStateIfLoaded(blockposition) : null;
|
||||
+ }
|
||||
+
|
||||
@Override
|
||||
public final ChunkAccess getChunk(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) { // Paper - final for inline
|
||||
// Paper end
|
|
@ -1,49 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jedediah Smith <jedediah@silencegreys.com>
|
||||
Date: Sun, 21 Jun 2015 15:07:20 -0400
|
||||
Subject: [PATCH] Custom replacement for eaten items
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index 17426b43a16887653a63c34128aa97785a23796c..c276190251c152f343de74d9c9b4028e10532ae1 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -3614,10 +3614,11 @@ public abstract class LivingEntity extends Entity {
|
||||
this.triggerItemUseEffects(this.useItem, 16);
|
||||
// CraftBukkit start - fire PlayerItemConsumeEvent
|
||||
ItemStack itemstack;
|
||||
+ PlayerItemConsumeEvent event = null; // Paper
|
||||
if (this instanceof ServerPlayer) {
|
||||
org.bukkit.inventory.ItemStack craftItem = CraftItemStack.asBukkitCopy(this.useItem);
|
||||
org.bukkit.inventory.EquipmentSlot hand = org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(enumhand);
|
||||
- PlayerItemConsumeEvent event = new PlayerItemConsumeEvent((Player) this.getBukkitEntity(), craftItem, hand);
|
||||
+ event = new PlayerItemConsumeEvent((Player) this.getBukkitEntity(), craftItem, hand); // Paper
|
||||
level.getCraftServer().getPluginManager().callEvent(event);
|
||||
|
||||
if (event.isCancelled()) {
|
||||
@@ -3631,6 +3632,13 @@ public abstract class LivingEntity extends Entity {
|
||||
} else {
|
||||
itemstack = this.useItem.finishUsingItem(this.level, this);
|
||||
}
|
||||
+
|
||||
+ // Paper start - save the default replacement item and change it if necessary
|
||||
+ final ItemStack defaultReplacement = itemstack;
|
||||
+ if (event != null && event.getReplacement() != null) {
|
||||
+ itemstack = CraftItemStack.asNMSCopy(event.getReplacement());
|
||||
+ }
|
||||
+ // Paper end
|
||||
// CraftBukkit end
|
||||
|
||||
if (itemstack != this.useItem) {
|
||||
@@ -3638,6 +3646,11 @@ public abstract class LivingEntity extends Entity {
|
||||
}
|
||||
|
||||
this.stopUsingItem();
|
||||
+ // Paper start - if the replacement is anything but the default, update the client inventory
|
||||
+ if (this instanceof ServerPlayer && !com.google.common.base.Objects.equal(defaultReplacement, itemstack)) {
|
||||
+ ((ServerPlayer) this).getBukkitEntity().updateInventory();
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 27 Sep 2015 01:18:02 -0400
|
||||
Subject: [PATCH] handle NaN health/absorb values and repair bad data
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index c276190251c152f343de74d9c9b4028e10532ae1..766711e4d32ceebf9d94e39f9bcd14ff0371ad06 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -784,7 +784,13 @@ public abstract class LivingEntity extends Entity {
|
||||
|
||||
@Override
|
||||
public void readAdditionalSaveData(CompoundTag nbt) {
|
||||
- this.setAbsorptionAmount(nbt.getFloat("AbsorptionAmount"));
|
||||
+ // Paper start - jvm keeps optimizing the setter
|
||||
+ float absorptionAmount = nbt.getFloat("AbsorptionAmount");
|
||||
+ if (Float.isNaN(absorptionAmount)) {
|
||||
+ absorptionAmount = 0;
|
||||
+ }
|
||||
+ this.setAbsorptionAmount(absorptionAmount);
|
||||
+ // Paper end
|
||||
if (nbt.contains("Attributes", 9) && this.level != null && !this.level.isClientSide) {
|
||||
this.getAttributes().load(nbt.getList("Attributes", 10));
|
||||
}
|
||||
@@ -1271,6 +1277,10 @@ public abstract class LivingEntity extends Entity {
|
||||
}
|
||||
|
||||
public void setHealth(float health) {
|
||||
+ // Paper start
|
||||
+ if (Float.isNaN(health)) { health = getMaxHealth(); if (this.valid) {
|
||||
+ System.err.println("[NAN-HEALTH] " + getScoreboardName() + " had NaN health set");
|
||||
+ } } // Paper end
|
||||
// CraftBukkit start - Handle scaled health
|
||||
if (this instanceof ServerPlayer) {
|
||||
org.bukkit.craftbukkit.entity.CraftPlayer player = ((ServerPlayer) this).getBukkitEntity();
|
||||
@@ -3447,7 +3457,7 @@ public abstract class LivingEntity extends Entity {
|
||||
}
|
||||
|
||||
public void setAbsorptionAmount(float amount) {
|
||||
- if (amount < 0.0F) {
|
||||
+ if (amount < 0.0F || Float.isNaN(amount)) { // Paper
|
||||
amount = 0.0F;
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index 15257f9236d0c32c1c74a15ce4e7decf4d9f2f91..1e1deab4d8be5523a55daf072d7e12b08d36b560 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -2011,6 +2011,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
}
|
||||
|
||||
public void setRealHealth(double health) {
|
||||
+ if (Double.isNaN(health)) {return;} // Paper
|
||||
this.health = health;
|
||||
}
|
||||
|
|
@ -1,113 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 22 Mar 2016 00:33:47 -0400
|
||||
Subject: [PATCH] Use a Shared Random for Entities
|
||||
|
||||
Reduces memory usage and provides ensures more randomness, Especially since a lot of garbage entity objects get created.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index 70275d1db39c9809a5fc93cebb49beb32d616476..dd5e9dc310f30c008f0c8c60ac4305160261bad9 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -159,6 +159,79 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
||||
return tag.contains("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level;
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ public static RandomSource SHARED_RANDOM = new RandomRandomSource();
|
||||
+ private static final class RandomRandomSource extends java.util.Random implements net.minecraft.world.level.levelgen.BitRandomSource {
|
||||
+ private boolean locked = false;
|
||||
+
|
||||
+ @Override
|
||||
+ public synchronized void setSeed(long seed) {
|
||||
+ if (locked) {
|
||||
+ LOGGER.error("Ignoring setSeed on Entity.SHARED_RANDOM", new Throwable());
|
||||
+ } else {
|
||||
+ super.setSeed(seed);
|
||||
+ locked = true;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public RandomSource fork() {
|
||||
+ return new net.minecraft.world.level.levelgen.LegacyRandomSource(this.nextLong());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public net.minecraft.world.level.levelgen.PositionalRandomFactory forkPositional() {
|
||||
+ return new net.minecraft.world.level.levelgen.LegacyRandomSource.LegacyPositionalRandomFactory(this.nextLong());
|
||||
+ }
|
||||
+
|
||||
+ // these below are added to fix reobf issues that I don't wanna deal with right now
|
||||
+ @Override
|
||||
+ public int next(int bits) {
|
||||
+ return super.next(bits);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int nextInt(int origin, int bound) {
|
||||
+ return net.minecraft.world.level.levelgen.BitRandomSource.super.nextInt(origin, bound);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public long nextLong() {
|
||||
+ return net.minecraft.world.level.levelgen.BitRandomSource.super.nextLong();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int nextInt() {
|
||||
+ return net.minecraft.world.level.levelgen.BitRandomSource.super.nextInt();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int nextInt(int bound) {
|
||||
+ return net.minecraft.world.level.levelgen.BitRandomSource.super.nextInt(bound);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean nextBoolean() {
|
||||
+ return net.minecraft.world.level.levelgen.BitRandomSource.super.nextBoolean();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public float nextFloat() {
|
||||
+ return net.minecraft.world.level.levelgen.BitRandomSource.super.nextFloat();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public double nextDouble() {
|
||||
+ return net.minecraft.world.level.levelgen.BitRandomSource.super.nextDouble();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public double nextGaussian() {
|
||||
+ return super.nextGaussian();
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
private CraftEntity bukkitEntity;
|
||||
|
||||
public CraftEntity getBukkitEntity() {
|
||||
@@ -398,7 +471,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
||||
this.bb = Entity.INITIAL_AABB;
|
||||
this.stuckSpeedMultiplier = Vec3.ZERO;
|
||||
this.nextStep = 1.0F;
|
||||
- this.random = RandomSource.create();
|
||||
+ this.random = SHARED_RANDOM; // Paper
|
||||
this.remainingFireTicks = -this.getFireImmuneTicks();
|
||||
this.fluidHeight = new Object2DoubleArrayMap(2);
|
||||
this.fluidOnEyes = new HashSet();
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/Squid.java b/src/main/java/net/minecraft/world/entity/animal/Squid.java
|
||||
index 8e63ab510e4c2e458da726ca67be4d3b5274e7b7..a51424d29ac353cf1bec4d1484db0acb63bebba5 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/Squid.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/Squid.java
|
||||
@@ -46,7 +46,7 @@ public class Squid extends WaterAnimal {
|
||||
|
||||
public Squid(EntityType<? extends Squid> type, Level world) {
|
||||
super(type, world);
|
||||
- this.random.setSeed((long) this.getId());
|
||||
+ //this.random.setSeed((long) this.getId()); // Paper - we set the random to shared, do not clobber the seed
|
||||
this.tentacleSpeed = 1.0F / (this.random.nextFloat() + 1.0F) * 0.2F;
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach.brown@destroystokyo.com>
|
||||
Date: Tue, 22 Mar 2016 12:04:28 -0500
|
||||
Subject: [PATCH] Configurable spawn chances for skeleton horses
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index d0e069e2dd950f2fe0d51594ceddcbbe44458acd..5f3c21172dbb9a4a0cb8aa0bffcb17bc357ef04e 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -696,7 +696,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
blockposition = this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15));
|
||||
if (this.isRainingAt(blockposition)) {
|
||||
DifficultyInstance difficultydamagescaler = this.getCurrentDifficultyAt(blockposition);
|
||||
- boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * 0.01D && !this.getBlockState(blockposition.below()).is(Blocks.LIGHTNING_ROD);
|
||||
+ boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * this.paperConfig().entities.spawning.skeletonHorseThunderSpawnChance.or(0.01D) && !this.getBlockState(blockposition.below()).is(Blocks.LIGHTNING_ROD); // Paper
|
||||
|
||||
if (flag1) {
|
||||
SkeletonHorse entityhorseskeleton = (SkeletonHorse) EntityType.SKELETON_HORSE.create(this);
|
|
@ -1,166 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Thu, 3 Mar 2016 02:07:55 -0600
|
||||
Subject: [PATCH] Optimize isInWorldBounds and getBlockState for inlining
|
||||
|
||||
Hot methods, so reduce # of instructions for the method.
|
||||
|
||||
Move is valid location test to the BlockPosition class so that it can access local variables.
|
||||
|
||||
Replace all calls to the new place to the unnecessary forward.
|
||||
|
||||
Optimize getType and getBlockData to manually inline and optimize the calls
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/core/Vec3i.java b/src/main/java/net/minecraft/core/Vec3i.java
|
||||
index 4587a3668b6be9222cdd74a38229f89f611d1af6..9f32861d791f7e4cb39d2ad01f48e1916fc2b4b1 100644
|
||||
--- a/src/main/java/net/minecraft/core/Vec3i.java
|
||||
+++ b/src/main/java/net/minecraft/core/Vec3i.java
|
||||
@@ -33,6 +33,12 @@ public class Vec3i implements Comparable<Vec3i> {
|
||||
return CODEC.flatXmap(checkOffsetAxes(maxAbsValue), checkOffsetAxes(maxAbsValue));
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ public final boolean isInsideBuildHeightAndWorldBoundsHorizontal(net.minecraft.world.level.LevelHeightAccessor levelHeightAccessor) {
|
||||
+ return getX() >= -30000000 && getZ() >= -30000000 && getX() < 30000000 && getZ() < 30000000 && !levelHeightAccessor.isOutsideBuildHeight(getY());
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
public Vec3i(int x, int y, int z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
||||
index 62c54a0c789ca460ec29b0c653f5abd113736fb9..d612b59e04fcd01a8e2c4c7f43d8735fc208b520 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/Level.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
||||
@@ -276,7 +276,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
}
|
||||
|
||||
public boolean isInWorldBounds(BlockPos pos) {
|
||||
- return !this.isOutsideBuildHeight(pos) && Level.isInWorldBoundsHorizontal(pos);
|
||||
+ return pos.isInsideBuildHeightAndWorldBoundsHorizontal(this); // Paper - use better/optimized check
|
||||
}
|
||||
|
||||
public static boolean isInSpawnableBounds(BlockPos pos) {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
|
||||
index 0e787d877901dfcea714b0e14e9fc4358ee30bbe..41e61e6c128f22224665af3f07cd11d69a43062b 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
|
||||
@@ -160,6 +160,7 @@ public abstract class ChunkAccess implements BlockGetter, BiomeManager.NoiseBiom
|
||||
return GameEventDispatcher.NOOP;
|
||||
}
|
||||
|
||||
+ public abstract BlockState getBlockState(final int x, final int y, final int z); // Paper
|
||||
@Nullable
|
||||
public abstract BlockState setBlockState(BlockPos pos, BlockState state, boolean moved);
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java
|
||||
index 2eb92dde607d7c8968cb07c6f3c24e1c45e9990f..908f71721daf4305692f424d7712cbfdddddae83 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java
|
||||
@@ -55,6 +55,12 @@ public class EmptyLevelChunk extends LevelChunk {
|
||||
public void setBlockEmptinessMap(final boolean[] emptinessMap) {}
|
||||
// Paper end - starlight
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public BlockState getBlockState(int x, int y, int z) {
|
||||
+ return Blocks.VOID_AIR.defaultBlockState();
|
||||
+ }
|
||||
+ // Paper end
|
||||
@Override
|
||||
public BlockState getBlockState(BlockPos pos) {
|
||||
return Blocks.VOID_AIR.defaultBlockState();
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java
|
||||
index ac5dff35e2df23b8790bbe65c40acc6a3c77e6ac..8ffc206a858864d277ff94de7c66ffdb07d8f491 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java
|
||||
@@ -89,6 +89,12 @@ public class ImposterProtoChunk extends ProtoChunk {
|
||||
public BlockState getBlockState(BlockPos pos) {
|
||||
return this.wrapped.getBlockState(pos);
|
||||
}
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public final BlockState getBlockState(final int x, final int y, final int z) {
|
||||
+ return this.wrapped.getBlockStateFinal(x, y, z);
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
@Override
|
||||
public FluidState getFluidState(BlockPos pos) {
|
||||
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 ea2176501dfa773a1114f5db4e6dbe4c2d2c7abe..0a08287d3b0471b01ee38eb62f92f542da35c07d 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -342,12 +342,29 @@ public class LevelChunk extends ChunkAccess {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start - Optimize getBlockData to reduce instructions
|
||||
@Override
|
||||
public BlockState getBlockState(BlockPos pos) {
|
||||
- int i = pos.getX();
|
||||
- int j = pos.getY();
|
||||
- int k = pos.getZ();
|
||||
+ return this.getBlockStateFinal(pos.getX(), pos.getY(), pos.getZ());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public BlockState getBlockState(final int x, final int y, final int z) {
|
||||
+ return this.getBlockStateFinal(x, y, z);
|
||||
+ }
|
||||
+ public final BlockState getBlockStateFinal(final int x, final int y, final int z) {
|
||||
+ // Method body / logic copied from below
|
||||
+ final int i = this.getSectionIndex(y);
|
||||
+ if (i < 0 || i >= this.sections.length || this.sections[i].nonEmptyBlockCount == 0 || this.sections[i].hasOnlyAir()) {
|
||||
+ return Blocks.AIR.defaultBlockState();
|
||||
+ }
|
||||
+ // Inlined ChunkSection.getType() and DataPaletteBlock.a(int,int,int)
|
||||
+ return this.sections[i].states.get((y & 15) << 8 | (z & 15) << 4 | x & 15);
|
||||
|
||||
+ }
|
||||
+
|
||||
+ public BlockState getBlockState_unused(int i, int j, int k) {
|
||||
+ // Paper end
|
||||
if (this.level.isDebug()) {
|
||||
BlockState iblockdata = null;
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
|
||||
index dddae1e226d8f58cdcfc597e25d4228cd3245cb4..ae37e97e52557b48f129cc02eeea395378a48444 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
|
||||
@@ -21,7 +21,7 @@ public class LevelChunkSection {
|
||||
public static final int SECTION_SIZE = 4096;
|
||||
public static final int BIOME_CONTAINER_BITS = 2;
|
||||
private final int bottomBlockY;
|
||||
- private short nonEmptyBlockCount;
|
||||
+ short nonEmptyBlockCount; // Paper - package-private
|
||||
private short tickingBlockCount;
|
||||
private short tickingFluidCount;
|
||||
public final PalettedContainer<BlockState> states;
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java
|
||||
index 0b67858f8d6689b34816f9556f3424af512a7401..c24b4c6a560aab2df07783b3481981deb8571a50 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java
|
||||
@@ -94,14 +94,18 @@ public class ProtoChunk extends ChunkAccess {
|
||||
|
||||
@Override
|
||||
public BlockState getBlockState(BlockPos pos) {
|
||||
- int i = pos.getY();
|
||||
- if (this.isOutsideBuildHeight(i)) {
|
||||
+ // Paper start
|
||||
+ return getBlockState(pos.getX(), pos.getY(), pos.getZ());
|
||||
+ }
|
||||
+ public BlockState getBlockState(final int x, final int y, final int z) {
|
||||
+ if (this.isOutsideBuildHeight(y)) {
|
||||
return Blocks.VOID_AIR.defaultBlockState();
|
||||
} else {
|
||||
- LevelChunkSection levelChunkSection = this.getSection(this.getSectionIndex(i));
|
||||
- return levelChunkSection.hasOnlyAir() ? Blocks.AIR.defaultBlockState() : levelChunkSection.getBlockState(pos.getX() & 15, i & 15, pos.getZ() & 15);
|
||||
+ LevelChunkSection levelChunkSection = this.getSections()[this.getSectionIndex(y)];
|
||||
+ return levelChunkSection.hasOnlyAir() ? Blocks.AIR.defaultBlockState() : levelChunkSection.getBlockState(x & 15, y & 15, z & 15);
|
||||
}
|
||||
}
|
||||
+ // Paper end
|
||||
|
||||
@Override
|
||||
public FluidState getFluidState(BlockPos pos) {
|
|
@ -1,70 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 28 Mar 2016 19:55:45 -0400
|
||||
Subject: [PATCH] Only process BlockPhysicsEvent if a plugin has a listener
|
||||
|
||||
Saves on some object allocation and processing when no plugin listens to this
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 093ac159fcc34de9901395ad9450372efdf7cb5b..c5e3f7f0623731c02e4625971fc82acbc834f51a 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1350,6 +1350,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
ServerLevel worldserver = (ServerLevel) iterator.next();
|
||||
+ worldserver.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper
|
||||
|
||||
this.profiler.push(() -> {
|
||||
return worldserver + " " + worldserver.dimension().location();
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 5f3c21172dbb9a4a0cb8aa0bffcb17bc357ef04e..1cfd73068455b1108a74156e9715061d2dca231f 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -215,6 +215,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
// CraftBukkit start
|
||||
public final LevelStorageSource.LevelStorageAccess convertable;
|
||||
public final UUID uuid;
|
||||
+ public boolean hasPhysicsEvent = true; // Paper
|
||||
|
||||
@Override public LevelChunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI
|
||||
return this.chunkSource.getChunk(x, z, false);
|
||||
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
||||
index d612b59e04fcd01a8e2c4c7f43d8735fc208b520..39b2071a6fc6510929416ccbdf2022cf471ab26c 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/Level.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
||||
@@ -493,7 +493,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
// CraftBukkit start
|
||||
iblockdata1.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); // Don't call an event for the old block to limit event spam
|
||||
CraftWorld world = ((ServerLevel) this).getWorld();
|
||||
- if (world != null) {
|
||||
+ if (world != null && ((ServerLevel)this).hasPhysicsEvent) { // Paper
|
||||
BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftBlockData.fromData(iblockdata));
|
||||
this.getCraftServer().getPluginManager().callEvent(event);
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/BushBlock.java b/src/main/java/net/minecraft/world/level/block/BushBlock.java
|
||||
index d40e791529911ca81398ac267a819415da91502a..03fde6e47c4a347c62fe9b4a3351769aedf874f6 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/BushBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/BushBlock.java
|
||||
@@ -24,7 +24,7 @@ public class BushBlock extends Block {
|
||||
public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) {
|
||||
// CraftBukkit start
|
||||
if (!state.canSurvive(world, pos)) {
|
||||
- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, pos).isCancelled()) {
|
||||
+ if (!(world instanceof net.minecraft.server.level.ServerLevel && ((net.minecraft.server.level.ServerLevel) world).hasPhysicsEvent) || !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, pos).isCancelled()) { // Paper
|
||||
return Blocks.AIR.defaultBlockState();
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java b/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java
|
||||
index a90f6cc0d8c0f6d115e59d07b1b4c9b45fe0ad1e..fa97966d39f01301a8ba976c02dc697e0a74bfb1 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java
|
||||
@@ -93,7 +93,7 @@ public class DoublePlantBlock extends BushBlock {
|
||||
|
||||
protected static void preventCreativeDropFromBottomPart(Level world, BlockPos pos, BlockState state, Player player) {
|
||||
// CraftBukkit start
|
||||
- if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, pos).isCancelled()) {
|
||||
+ if (((net.minecraft.server.level.ServerLevel)world).hasPhysicsEvent && org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, pos).isCancelled()) { // Paper
|
||||
return;
|
||||
}
|
||||
// CraftBukkit end
|
|
@ -1,26 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 28 Mar 2016 20:32:58 -0400
|
||||
Subject: [PATCH] Entity AddTo/RemoveFrom World Events
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 1cfd73068455b1108a74156e9715061d2dca231f..b255f8bd65006240153cb607f65e277f8a560b75 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -2245,6 +2245,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
entity.setOrigin(entity.getOriginVector().toLocation(getWorld()));
|
||||
}
|
||||
// Paper end
|
||||
+ new com.destroystokyo.paper.event.entity.EntityAddToWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid
|
||||
}
|
||||
|
||||
public void onTrackingEnd(Entity entity) {
|
||||
@@ -2320,6 +2321,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
}
|
||||
}
|
||||
// CraftBukkit end
|
||||
+ new com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid
|
||||
}
|
||||
|
||||
public void onSectionChange(Entity entity) {
|
|
@ -1,30 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 28 Mar 2016 20:46:14 -0400
|
||||
Subject: [PATCH] Configurable Chunk Inhabited Time
|
||||
|
||||
Vanilla stores how long a chunk has been active on a server, and dynamically scales some
|
||||
aspects of vanilla gameplay to this factor.
|
||||
|
||||
For people who want all chunks to be treated equally, you can chose a fixed value.
|
||||
|
||||
This allows to fine-tune vanilla gameplay.
|
||||
|
||||
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 0a08287d3b0471b01ee38eb62f92f542da35c07d..3a613d3fb6240a504724ba42b9aadaa0881b3ac1 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -327,6 +327,13 @@ public class LevelChunk extends ChunkAccess {
|
||||
return new ChunkAccess.TicksToSave(this.blockTicks, this.fluidTicks);
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public long getInhabitedTime() {
|
||||
+ return this.level.paperConfig().chunks.fixedChunkInhabitedTime < 0 ? super.getInhabitedTime() : this.level.paperConfig().chunks.fixedChunkInhabitedTime;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public GameEventDispatcher getEventDispatcher(int ySectionCoord) {
|
||||
Level world = this.level;
|
|
@ -1,149 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 28 Mar 2016 21:22:26 -0400
|
||||
Subject: [PATCH] EntityPathfindEvent
|
||||
|
||||
Fires when an Entity decides to start moving to a location.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java
|
||||
index 0b2e10a0f508448d9e7d003e6c822f0a56d4022f..27cd393e81f6ef9b5690c051624d8d2af50acd34 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java
|
||||
@@ -35,7 +35,7 @@ public class FlyingPathNavigation extends PathNavigation {
|
||||
|
||||
@Override
|
||||
public Path createPath(Entity entity, int distance) {
|
||||
- return this.createPath(entity.blockPosition(), distance);
|
||||
+ return this.createPath(entity.blockPosition(), entity, distance); // Paper - Forward target entity
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java
|
||||
index 27b072943328aca4489a9565bda700e7e7dcbb6a..f0248d839255763005ba333b0bfcf691407fb69b 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java
|
||||
@@ -39,14 +39,14 @@ public class GroundPathNavigation extends PathNavigation {
|
||||
}
|
||||
|
||||
@Override
|
||||
- public Path createPath(BlockPos target, int distance) {
|
||||
+ public Path createPath(BlockPos target, @javax.annotation.Nullable Entity entity, int distance) { // Paper
|
||||
if (this.level.getBlockState(target).isAir()) {
|
||||
BlockPos blockPos;
|
||||
for(blockPos = target.below(); blockPos.getY() > this.level.getMinBuildHeight() && this.level.getBlockState(blockPos).isAir(); blockPos = blockPos.below()) {
|
||||
}
|
||||
|
||||
if (blockPos.getY() > this.level.getMinBuildHeight()) {
|
||||
- return super.createPath(blockPos.above(), distance);
|
||||
+ return super.createPath(blockPos.above(), entity, distance); // Paper
|
||||
}
|
||||
|
||||
while(blockPos.getY() < this.level.getMaxBuildHeight() && this.level.getBlockState(blockPos).isAir()) {
|
||||
@@ -57,19 +57,19 @@ public class GroundPathNavigation extends PathNavigation {
|
||||
}
|
||||
|
||||
if (!this.level.getBlockState(target).getMaterial().isSolid()) {
|
||||
- return super.createPath(target, distance);
|
||||
+ return super.createPath(target, entity, distance); // Paper
|
||||
} else {
|
||||
BlockPos blockPos2;
|
||||
for(blockPos2 = target.above(); blockPos2.getY() < this.level.getMaxBuildHeight() && this.level.getBlockState(blockPos2).getMaterial().isSolid(); blockPos2 = blockPos2.above()) {
|
||||
}
|
||||
|
||||
- return super.createPath(blockPos2, distance);
|
||||
+ return super.createPath(blockPos2, entity, distance); // Paper
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path createPath(Entity entity, int distance) {
|
||||
- return this.createPath(entity.blockPosition(), distance);
|
||||
+ return this.createPath(entity.blockPosition(), entity, distance); // Paper - Forward target entity
|
||||
}
|
||||
|
||||
private int getSurfaceY() {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java
|
||||
index eaf1653b14e5fdacae38abe75260a64d0ffbfc1d..b6b6106ad2105c19273dc9f983fabd6573d35e5a 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java
|
||||
@@ -108,7 +108,13 @@ public abstract class PathNavigation {
|
||||
|
||||
@Nullable
|
||||
public Path createPath(BlockPos target, int distance) {
|
||||
- return this.createPath(ImmutableSet.of(target), 8, false, distance);
|
||||
+ // Paper start - add target entity parameter
|
||||
+ return this.createPath(target, null, distance);
|
||||
+ }
|
||||
+ @Nullable
|
||||
+ public Path createPath(BlockPos target, @Nullable Entity entity, int distance) {
|
||||
+ return this.createPath(ImmutableSet.of(target), entity, 8, false, distance);
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -118,7 +124,7 @@ public abstract class PathNavigation {
|
||||
|
||||
@Nullable
|
||||
public Path createPath(Entity entity, int distance) {
|
||||
- return this.createPath(ImmutableSet.of(entity.blockPosition()), 16, true, distance);
|
||||
+ return this.createPath(ImmutableSet.of(entity.blockPosition()), entity, 16, true, distance); // Paper
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -128,6 +134,16 @@ public abstract class PathNavigation {
|
||||
|
||||
@Nullable
|
||||
protected Path createPath(Set<BlockPos> positions, int range, boolean useHeadPos, int distance, float followRange) {
|
||||
+ return this.createPath(positions, null, range, useHeadPos, distance, followRange);
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ protected Path createPath(Set<BlockPos> positions, @Nullable Entity target, int range, boolean useHeadPos, int distance) {
|
||||
+ return this.createPath(positions, target, range, useHeadPos, distance, (float) this.mob.getAttributeValue(Attributes.FOLLOW_RANGE));
|
||||
+ }
|
||||
+
|
||||
+ @Nullable protected Path createPath(Set<BlockPos> positions, @Nullable Entity target, int range, boolean useHeadPos, int distance, float followRange) {
|
||||
+ // Paper end
|
||||
if (positions.isEmpty()) {
|
||||
return null;
|
||||
} else if (this.mob.getY() < (double)this.level.getMinBuildHeight()) {
|
||||
@@ -137,6 +153,23 @@ public abstract class PathNavigation {
|
||||
} else if (this.path != null && !this.path.isDone() && positions.contains(this.targetPos)) {
|
||||
return this.path;
|
||||
} else {
|
||||
+ // Paper start - Pathfind event
|
||||
+ boolean copiedSet = false;
|
||||
+ for (BlockPos possibleTarget : positions) {
|
||||
+ if (!new com.destroystokyo.paper.event.entity.EntityPathfindEvent(this.mob.getBukkitEntity(),
|
||||
+ io.papermc.paper.util.MCUtil.toLocation(this.mob.level, possibleTarget), target == null ? null : target.getBukkitEntity()).callEvent()) {
|
||||
+ if (!copiedSet) {
|
||||
+ copiedSet = true;
|
||||
+ positions = new java.util.HashSet<>(positions);
|
||||
+ }
|
||||
+ // note: since we copy the set this remove call is safe, since we're iterating over the old copy
|
||||
+ positions.remove(possibleTarget);
|
||||
+ if (positions.isEmpty()) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
this.level.getProfiler().push("pathfind");
|
||||
BlockPos blockPos = useHeadPos ? this.mob.blockPosition().above() : this.mob.blockPosition();
|
||||
int i = (int)(followRange + (float)range);
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/WallClimberNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/WallClimberNavigation.java
|
||||
index d11e9f4f7ae5f2666d67878309b4a1359ef90e39..de1f178fa18ae3ff3c73bc59b10eb39857800bf9 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/ai/navigation/WallClimberNavigation.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/WallClimberNavigation.java
|
||||
@@ -16,9 +16,9 @@ public class WallClimberNavigation extends GroundPathNavigation {
|
||||
}
|
||||
|
||||
@Override
|
||||
- public Path createPath(BlockPos target, int distance) {
|
||||
+ public Path createPath(BlockPos target, @Nullable Entity entity, int distance) { // Paper
|
||||
this.pathToPosition = target;
|
||||
- return super.createPath(target, distance);
|
||||
+ return super.createPath(target, entity, distance); // Paper
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,25 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Antony Riley <antony@cyberiantiger.org>
|
||||
Date: Tue, 29 Mar 2016 08:22:55 +0300
|
||||
Subject: [PATCH] Sanitise RegionFileCache and make configurable.
|
||||
|
||||
RegionFileCache prior to this patch would close every single open region
|
||||
file upon reaching a size of 256.
|
||||
This patch modifies that behaviour so it closes the the least recently
|
||||
used RegionFile.
|
||||
The implementation uses a LinkedHashMap as an LRU cache (modified from HashMap).
|
||||
The maximum size of the RegionFileCache is also made configurable.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
|
||||
index ece0fd4b51d124be232e24d08f115b9267cb21cb..9a4f9251d655b86af5a410cfab8df285098e01cc 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
|
||||
@@ -57,7 +57,7 @@ public class RegionFileStorage implements AutoCloseable {
|
||||
// Paper end
|
||||
return regionfile;
|
||||
} else {
|
||||
- if (this.regionCache.size() >= 256) {
|
||||
+ if (this.regionCache.size() >= io.papermc.paper.configuration.GlobalConfiguration.get().misc.regionFileCacheSize) { // Paper - configurable
|
||||
((RegionFile) this.regionCache.removeLast()).close();
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Thu, 31 Mar 2016 19:17:58 -0400
|
||||
Subject: [PATCH] Do not load chunks for Pathfinding
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java
|
||||
index 235b01e23a8997d0d65de3655b3b3ff50a204c06..c48e097464977dbec22d1370c3393ba1fe105137 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java
|
||||
@@ -477,7 +477,12 @@ public class WalkNodeEvaluator extends NodeEvaluator {
|
||||
for(int n = -1; n <= 1; ++n) {
|
||||
if (l != 0 || n != 0) {
|
||||
pos.set(i + l, j + m, k + n);
|
||||
- BlockState blockState = world.getBlockState(pos);
|
||||
+ // Paper start
|
||||
+ BlockState blockState = world.getBlockStateIfLoaded(pos);
|
||||
+ if (blockState == null) {
|
||||
+ return BlockPathTypes.BLOCKED;
|
||||
+ } else {
|
||||
+ // Paper end
|
||||
if (blockState.is(Blocks.CACTUS)) {
|
||||
return BlockPathTypes.DANGER_CACTUS;
|
||||
}
|
||||
@@ -493,6 +498,7 @@ public class WalkNodeEvaluator extends NodeEvaluator {
|
||||
if (world.getFluidState(pos).is(FluidTags.WATER)) {
|
||||
return BlockPathTypes.WATER_BORDER;
|
||||
}
|
||||
+ } // Paper
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -502,7 +508,8 @@ public class WalkNodeEvaluator extends NodeEvaluator {
|
||||
}
|
||||
|
||||
protected static BlockPathTypes getBlockPathTypeRaw(BlockGetter world, BlockPos pos) {
|
||||
- BlockState blockState = world.getBlockState(pos);
|
||||
+ BlockState blockState = world.getBlockStateIfLoaded(pos); // Paper
|
||||
+ if (blockState == null) return BlockPathTypes.BLOCKED; // Paper
|
||||
Block block = blockState.getBlock();
|
||||
Material material = blockState.getMaterial();
|
||||
if (blockState.isAir()) {
|
|
@ -1,65 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jedediah Smith <jedediah@silencegreys.com>
|
||||
Date: Sat, 2 Apr 2016 05:09:16 -0400
|
||||
Subject: [PATCH] Add PlayerUseUnknownEntityEvent
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.network.protocol.game.ServerboundInteractPacket$ActionType
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/network/protocol/game/ServerboundInteractPacket.java b/src/main/java/net/minecraft/network/protocol/game/ServerboundInteractPacket.java
|
||||
index 8834ed411a7db86b4d2b88183a1315317107d719..c45b5ab6776f3ac79f856c3a6467c510e20db25a 100644
|
||||
--- a/src/main/java/net/minecraft/network/protocol/game/ServerboundInteractPacket.java
|
||||
+++ b/src/main/java/net/minecraft/network/protocol/game/ServerboundInteractPacket.java
|
||||
@@ -10,8 +10,8 @@ import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class ServerboundInteractPacket implements Packet<ServerGamePacketListener> {
|
||||
- private final int entityId;
|
||||
- private final ServerboundInteractPacket.Action action;
|
||||
+ private final int entityId; public final int getEntityId() { return this.entityId; } // Paper - add accessor
|
||||
+ private final ServerboundInteractPacket.Action action; public final ServerboundInteractPacket.ActionType getActionType() { return this.action.getType(); } // Paper - add accessor
|
||||
private final boolean usingSecondaryAction;
|
||||
static final ServerboundInteractPacket.Action ATTACK_ACTION = new ServerboundInteractPacket.Action() {
|
||||
@Override
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 5443c0008ae3bb0264dbfc1b2bb3921de306c1dd..65bd9005b722db154842978d359e0a2277bbb8b2 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -2644,8 +2644,37 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
||||
});
|
||||
}
|
||||
}
|
||||
+ // Paper start - fire event
|
||||
+ else {
|
||||
+ packet.dispatch(new net.minecraft.network.protocol.game.ServerboundInteractPacket.Handler() {
|
||||
+ @Override
|
||||
+ public void onInteraction(net.minecraft.world.InteractionHand hand) {
|
||||
+ ServerGamePacketListenerImpl.this.callPlayerUseUnknownEntityEvent(packet, hand);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onInteraction(net.minecraft.world.InteractionHand hand, net.minecraft.world.phys.Vec3 pos) {
|
||||
+ ServerGamePacketListenerImpl.this.callPlayerUseUnknownEntityEvent(packet, hand);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onAttack() {
|
||||
+ ServerGamePacketListenerImpl.this.callPlayerUseUnknownEntityEvent(packet, net.minecraft.world.InteractionHand.MAIN_HAND);
|
||||
+ }
|
||||
+ });
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
|
||||
+ private void callPlayerUseUnknownEntityEvent(ServerboundInteractPacket packet, InteractionHand hand) {
|
||||
+ this.cserver.getPluginManager().callEvent(new com.destroystokyo.paper.event.player.PlayerUseUnknownEntityEvent(
|
||||
+ this.getCraftPlayer(),
|
||||
+ packet.getEntityId(),
|
||||
+ packet.getActionType() == ServerboundInteractPacket.ActionType.ATTACK,
|
||||
+ hand == InteractionHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND
|
||||
+ ));
|
||||
}
|
||||
+ // Paper end
|
||||
|
||||
@Override
|
||||
public void handleClientCommand(ServerboundClientCommandPacket packet) {
|
|
@ -1,26 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 3 Apr 2016 16:28:17 -0400
|
||||
Subject: [PATCH] Configurable Grass Spread Tick Rate
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java b/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java
|
||||
index bd5a45765b53bf4f2f9aaea4769c71ffb008741d..61783f17b655cbb6430d22fb3a81931ab3ea130c 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java
|
||||
@@ -2,6 +2,7 @@ package net.minecraft.world.level.block;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.tags.FluidTags;
|
||||
import net.minecraft.util.RandomSource;
|
||||
@@ -39,6 +40,7 @@ public abstract class SpreadingSnowyDirtBlock extends SnowyDirtBlock {
|
||||
|
||||
@Override
|
||||
public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
|
||||
+ if (this instanceof GrassBlock && world.paperConfig().tickRates.grassSpread != 1 && (world.paperConfig().tickRates.grassSpread < 1 || (MinecraftServer.currentTick + pos.hashCode()) % world.paperConfig().tickRates.grassSpread != 0)) { return; } // Paper
|
||||
if (!SpreadingSnowyDirtBlock.canBeGrass(state, world, pos)) {
|
||||
// CraftBukkit start
|
||||
if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(world, pos, Blocks.DIRT.defaultBlockState()).isCancelled()) {
|
|
@ -1,18 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 3 Apr 2016 17:48:50 -0400
|
||||
Subject: [PATCH] Fix Cancelling BlockPlaceEvent triggering physics
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index b255f8bd65006240153cb607f65e277f8a560b75..67c4b724b6b799c02ee4c5034d3472e44cb591fa 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -1476,6 +1476,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
|
||||
@Override
|
||||
public void updateNeighborsAt(BlockPos pos, Block sourceBlock) {
|
||||
+ if (captureBlockStates) { return; } // Paper - Cancel all physics during placement
|
||||
this.neighborUpdater.updateNeighborsAtExceptFromFacing(pos, sourceBlock, (Direction) null);
|
||||
}
|
||||
|
|
@ -1,118 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 5 Apr 2016 21:38:58 -0400
|
||||
Subject: [PATCH] Optimize DataBits
|
||||
|
||||
Remove Debug checks as these are super hot and causing noticeable hits
|
||||
|
||||
Before: http://i.imgur.com/nQsMzAE.png
|
||||
After: http://i.imgur.com/nJ46crB.png
|
||||
|
||||
Optimize redundant converting of static fields into an unsigned long each call by precomputing it in ctor
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/util/SimpleBitStorage.java b/src/main/java/net/minecraft/util/SimpleBitStorage.java
|
||||
index c8ae9d25eedb7cb2d9f95b799a507727b655f11f..9b81ce9d85cba07e9752c29fb5a842c4b00aa873 100644
|
||||
--- a/src/main/java/net/minecraft/util/SimpleBitStorage.java
|
||||
+++ b/src/main/java/net/minecraft/util/SimpleBitStorage.java
|
||||
@@ -11,8 +11,8 @@ public class SimpleBitStorage implements BitStorage {
|
||||
private final long mask;
|
||||
private final int size;
|
||||
private final int valuesPerLong;
|
||||
- private final int divideMul;
|
||||
- private final int divideAdd;
|
||||
+ private final int divideMul; private final long divideMulUnsigned; // Paper - referenced in b(int) with 2 Integer.toUnsignedLong calls
|
||||
+ private final int divideAdd; private final long divideAddUnsigned; // Paper
|
||||
private final int divideShift;
|
||||
|
||||
public SimpleBitStorage(int elementBits, int size, int[] data) {
|
||||
@@ -56,8 +56,8 @@ public class SimpleBitStorage implements BitStorage {
|
||||
this.mask = (1L << elementBits) - 1L;
|
||||
this.valuesPerLong = (char)(64 / elementBits);
|
||||
int i = 3 * (this.valuesPerLong - 1);
|
||||
- this.divideMul = MAGIC[i + 0];
|
||||
- this.divideAdd = MAGIC[i + 1];
|
||||
+ this.divideMul = MAGIC[i + 0]; this.divideMulUnsigned = Integer.toUnsignedLong(this.divideMul); // Paper
|
||||
+ this.divideAdd = MAGIC[i + 1]; this.divideAddUnsigned = Integer.toUnsignedLong(this.divideAdd); // Paper
|
||||
this.divideShift = MAGIC[i + 2];
|
||||
int j = (size + this.valuesPerLong - 1) / this.valuesPerLong;
|
||||
if (data != null) {
|
||||
@@ -73,15 +73,15 @@ public class SimpleBitStorage implements BitStorage {
|
||||
}
|
||||
|
||||
private int cellIndex(int index) {
|
||||
- long l = Integer.toUnsignedLong(this.divideMul);
|
||||
- long m = Integer.toUnsignedLong(this.divideAdd);
|
||||
- return (int)((long)index * l + m >> 32 >> this.divideShift);
|
||||
+ //long l = Integer.toUnsignedLong(this.divideMul); // Paper
|
||||
+ //long m = Integer.toUnsignedLong(this.divideAdd); // Paper
|
||||
+ return (int) ((long) index * this.divideMulUnsigned + this.divideAddUnsigned >> 32 >> this.divideShift); // Paper
|
||||
}
|
||||
|
||||
@Override
|
||||
- public int getAndSet(int index, int value) {
|
||||
- Validate.inclusiveBetween(0L, (long)(this.size - 1), (long)index);
|
||||
- Validate.inclusiveBetween(0L, this.mask, (long)value);
|
||||
+ public final int getAndSet(int index, int value) { // Paper - make final for inline
|
||||
+ //Validate.inclusiveBetween(0L, (long)(this.size - 1), (long)index); // Paper
|
||||
+ //Validate.inclusiveBetween(0L, this.mask, (long)value); // Paper
|
||||
int i = this.cellIndex(index);
|
||||
long l = this.data[i];
|
||||
int j = (index - i * this.valuesPerLong) * this.bits;
|
||||
@@ -91,9 +91,9 @@ public class SimpleBitStorage implements BitStorage {
|
||||
}
|
||||
|
||||
@Override
|
||||
- public void set(int index, int value) {
|
||||
- Validate.inclusiveBetween(0L, (long)(this.size - 1), (long)index);
|
||||
- Validate.inclusiveBetween(0L, this.mask, (long)value);
|
||||
+ public final void set(int index, int value) { // Paper - make final for inline
|
||||
+ //Validate.inclusiveBetween(0L, (long)(this.size - 1), (long)index); // Paper
|
||||
+ //Validate.inclusiveBetween(0L, this.mask, (long)value); // Paper
|
||||
int i = this.cellIndex(index);
|
||||
long l = this.data[i];
|
||||
int j = (index - i * this.valuesPerLong) * this.bits;
|
||||
@@ -101,8 +101,8 @@ public class SimpleBitStorage implements BitStorage {
|
||||
}
|
||||
|
||||
@Override
|
||||
- public int get(int index) {
|
||||
- Validate.inclusiveBetween(0L, (long)(this.size - 1), (long)index);
|
||||
+ public final int get(int index) { // Paper - make final for inline
|
||||
+ //Validate.inclusiveBetween(0L, (long)(this.size - 1), (long)index);
|
||||
int i = this.cellIndex(index);
|
||||
long l = this.data[i];
|
||||
int j = (index - i * this.valuesPerLong) * this.bits;
|
||||
diff --git a/src/main/java/net/minecraft/util/ZeroBitStorage.java b/src/main/java/net/minecraft/util/ZeroBitStorage.java
|
||||
index 172e7a0761724cc802387e613258830a0defb04a..9686ce7536c9924b1b2aced4f013f46759cbc72e 100644
|
||||
--- a/src/main/java/net/minecraft/util/ZeroBitStorage.java
|
||||
+++ b/src/main/java/net/minecraft/util/ZeroBitStorage.java
|
||||
@@ -13,21 +13,21 @@ public class ZeroBitStorage implements BitStorage {
|
||||
}
|
||||
|
||||
@Override
|
||||
- public int getAndSet(int index, int value) {
|
||||
- Validate.inclusiveBetween(0L, (long)(this.size - 1), (long)index);
|
||||
- Validate.inclusiveBetween(0L, 0L, (long)value);
|
||||
+ public final int getAndSet(int index, int value) { // Paper - make final for inline
|
||||
+ //Validate.inclusiveBetween(0L, (long)(this.size - 1), (long)index); // Paper
|
||||
+ //Validate.inclusiveBetween(0L, 0L, (long)value); // Paper
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
- public void set(int index, int value) {
|
||||
- Validate.inclusiveBetween(0L, (long)(this.size - 1), (long)index);
|
||||
- Validate.inclusiveBetween(0L, 0L, (long)value);
|
||||
+ public final void set(int index, int value) { // Paper - make final for inline
|
||||
+ //Validate.inclusiveBetween(0L, (long)(this.size - 1), (long)index); // Paper
|
||||
+ //Validate.inclusiveBetween(0L, 0L, (long)value); // Paper
|
||||
}
|
||||
|
||||
@Override
|
||||
- public int get(int index) {
|
||||
- Validate.inclusiveBetween(0L, (long)(this.size - 1), (long)index);
|
||||
+ public final int get(int index) { // Paper - make final for inline
|
||||
+ //Validate.inclusiveBetween(0L, (long)(this.size - 1), (long)index); // Paper
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach.brown@destroystokyo.com>
|
||||
Date: Wed, 6 Apr 2016 01:04:23 -0500
|
||||
Subject: [PATCH] Option to use vanilla per-world scoreboard coloring on names
|
||||
|
||||
This change is basically a bandaid to fix CB's complete and utter lack
|
||||
of support for vanilla scoreboard name modifications.
|
||||
|
||||
In the future, finding a way to merge the vanilla expectations in with
|
||||
bukkit's concept of a display name would be preferable. There was a PR
|
||||
for this on CB at one point but I can't find it. We may need to do this
|
||||
ourselves at some point in the future.
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java
|
||||
index 12ea885e815b6814a74ac3aa9d9c325e53721ecd..28ddab1121e314e82bf764fd89f36714bd7445f8 100644
|
||||
--- a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java
|
||||
+++ b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java
|
||||
@@ -24,8 +24,10 @@ import net.minecraft.network.chat.PlayerChatMessage;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
+import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
+import org.bukkit.craftbukkit.CraftWorld;
|
||||
import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.util.LazyPlayerSet;
|
||||
import org.bukkit.craftbukkit.util.Waitable;
|
||||
@@ -332,10 +334,16 @@ public final class ChatProcessor {
|
||||
}
|
||||
|
||||
static String legacyDisplayName(final CraftPlayer player) {
|
||||
+ if (((org.bukkit.craftbukkit.CraftWorld) player.getWorld()).getHandle().paperConfig().scoreboards.useVanillaWorldScoreboardNameColoring) {
|
||||
+ return legacySection().serialize(player.teamDisplayName()) + ChatColor.RESET;
|
||||
+ }
|
||||
return player.getDisplayName();
|
||||
}
|
||||
|
||||
static Component displayName(final CraftPlayer player) {
|
||||
+ if (((CraftWorld) player.getWorld()).getHandle().paperConfig().scoreboards.useVanillaWorldScoreboardNameColoring) {
|
||||
+ return player.teamDisplayName();
|
||||
+ }
|
||||
return player.displayName();
|
||||
}
|
||||
|
|
@ -1,109 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 13 Apr 2016 02:10:49 -0400
|
||||
Subject: [PATCH] Configurable Player Collision
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java
|
||||
index 1294b38262505b0d54089e428df9b363219de1f0..ee37ec0de1ca969144824427ae42b0c81434a1b4 100644
|
||||
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java
|
||||
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java
|
||||
@@ -193,7 +193,7 @@ public class ClientboundSetPlayerTeamPacket implements Packet<ClientGamePacketLi
|
||||
buf.writeComponent(this.displayName);
|
||||
buf.writeByte(this.options);
|
||||
buf.writeUtf(this.nametagVisibility);
|
||||
- buf.writeUtf(this.collisionRule);
|
||||
+ buf.writeUtf(!io.papermc.paper.configuration.GlobalConfiguration.get().collisions.enablePlayerCollisions ? "never" : this.collisionRule); // Paper
|
||||
buf.writeEnum(this.color);
|
||||
buf.writeComponent(this.playerPrefix);
|
||||
buf.writeComponent(this.playerSuffix);
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index c5e3f7f0623731c02e4625971fc82acbc834f51a..17ad0051afaaa0e201782228628c691b75b6cebc 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -580,6 +580,20 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
this.server.getPluginManager().callEvent(new org.bukkit.event.world.WorldLoadEvent(worldserver.getWorld()));
|
||||
}
|
||||
|
||||
+ // Paper start - Handle collideRule team for player collision toggle
|
||||
+ final ServerScoreboard scoreboard = this.getScoreboard();
|
||||
+ final java.util.Collection<String> toRemove = scoreboard.getPlayerTeams().stream().filter(team -> team.getName().startsWith("collideRule_")).map(net.minecraft.world.scores.PlayerTeam::getName).collect(java.util.stream.Collectors.toList());
|
||||
+ for (String teamName : toRemove) {
|
||||
+ scoreboard.removePlayerTeam(scoreboard.getPlayerTeam(teamName)); // Clean up after ourselves
|
||||
+ }
|
||||
+
|
||||
+ if (!io.papermc.paper.configuration.GlobalConfiguration.get().collisions.enablePlayerCollisions) {
|
||||
+ this.getPlayerList().collideRuleTeamName = org.apache.commons.lang3.StringUtils.left("collideRule_" + java.util.concurrent.ThreadLocalRandom.current().nextInt(), 16);
|
||||
+ net.minecraft.world.scores.PlayerTeam collideTeam = scoreboard.addPlayerTeam(this.getPlayerList().collideRuleTeamName);
|
||||
+ collideTeam.setSeeFriendlyInvisibles(false); // Because we want to mimic them not being on a team at all
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
this.server.enablePlugins(org.bukkit.plugin.PluginLoadOrder.POSTWORLD);
|
||||
this.server.getPluginManager().callEvent(new ServerLoadEvent(ServerLoadEvent.LoadType.STARTUP));
|
||||
this.connection.acceptConnections();
|
||||
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
index 1357b444cf2efbd7f6a1918709b9743d230f1fd5..afbb45f2ee55f193e30c19bc20edc42434f16784 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
@@ -94,6 +94,7 @@ import net.minecraft.world.level.storage.PlayerDataStorage;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraft.world.scores.Objective;
|
||||
import net.minecraft.world.scores.PlayerTeam;
|
||||
+import net.minecraft.world.scores.Scoreboard; // Paper
|
||||
import net.minecraft.world.scores.Team;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
@@ -155,6 +156,7 @@ public abstract class PlayerList {
|
||||
// CraftBukkit start
|
||||
private CraftServer cserver;
|
||||
private final Map<String,ServerPlayer> playersByName = new java.util.HashMap<>();
|
||||
+ public @Nullable String collideRuleTeamName; // Paper - Team name used for collideRule
|
||||
|
||||
public PlayerList(MinecraftServer server, RegistryAccess.Frozen registryManager, PlayerDataStorage saveHandler, int maxPlayers) {
|
||||
this.cserver = server.server = new CraftServer((DedicatedServer) server, this);
|
||||
@@ -391,6 +393,13 @@ public abstract class PlayerList {
|
||||
|
||||
player.initInventoryMenu();
|
||||
// CraftBukkit - Moved from above, added world
|
||||
+ // Paper start - Add to collideRule team if needed
|
||||
+ final Scoreboard scoreboard = this.getServer().getLevel(Level.OVERWORLD).getScoreboard();
|
||||
+ final PlayerTeam collideRuleTeam = scoreboard.getPlayerTeam(this.collideRuleTeamName);
|
||||
+ if (this.collideRuleTeamName != null && collideRuleTeam != null && player.getTeam() == null) {
|
||||
+ scoreboard.addPlayerToTeam(player.getScoreboardName(), collideRuleTeam);
|
||||
+ }
|
||||
+ // Paper end
|
||||
PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", player.getName().getString(), s1, player.getId(), worldserver1.serverLevelData.getLevelName(), player.getX(), player.getY(), player.getZ());
|
||||
}
|
||||
|
||||
@@ -510,6 +519,16 @@ public abstract class PlayerList {
|
||||
entityplayer.doTick(); // SPIGOT-924
|
||||
// CraftBukkit end
|
||||
|
||||
+ // Paper start - Remove from collideRule team if needed
|
||||
+ if (this.collideRuleTeamName != null) {
|
||||
+ final Scoreboard scoreBoard = this.server.getLevel(Level.OVERWORLD).getScoreboard();
|
||||
+ final PlayerTeam team = scoreBoard.getPlayersTeam(this.collideRuleTeamName);
|
||||
+ if (entityplayer.getTeam() == team && team != null) {
|
||||
+ scoreBoard.removePlayerFromTeam(entityplayer.getScoreboardName(), team);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
this.save(entityplayer);
|
||||
if (entityplayer.isPassenger()) {
|
||||
Entity entity = entityplayer.getRootVehicle();
|
||||
@@ -1138,6 +1157,13 @@ public abstract class PlayerList {
|
||||
}
|
||||
// CraftBukkit end
|
||||
|
||||
+ // Paper start - Remove collideRule team if it exists
|
||||
+ if (this.collideRuleTeamName != null) {
|
||||
+ final Scoreboard scoreboard = this.getServer().getLevel(Level.OVERWORLD).getScoreboard();
|
||||
+ final PlayerTeam team = scoreboard.getPlayersTeam(this.collideRuleTeamName);
|
||||
+ if (team != null) scoreboard.removePlayerTeam(team);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
// CraftBukkit start
|
|
@ -1,49 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: kashike <kashike@vq.lc>
|
||||
Date: Wed, 13 Apr 2016 20:21:38 -0700
|
||||
Subject: [PATCH] Add handshake event to allow plugins to handle client
|
||||
handshaking logic themselves
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
|
||||
index 5948138f3697c0cce9638524a0f481eb368da911..8284d49c8e30645d00be952c847bab7ce5753d78 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
|
||||
@@ -88,9 +88,36 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL
|
||||
this.connection.disconnect(ichatmutablecomponent);
|
||||
} else {
|
||||
this.connection.setListener(new ServerLoginPacketListenerImpl(this.server, this.connection));
|
||||
+ // Paper start - handshake event
|
||||
+ boolean proxyLogicEnabled = org.spigotmc.SpigotConfig.bungee;
|
||||
+ boolean handledByEvent = false;
|
||||
+ // Try and handle the handshake through the event
|
||||
+ if (com.destroystokyo.paper.event.player.PlayerHandshakeEvent.getHandlerList().getRegisteredListeners().length != 0) { // Hello? Can you hear me?
|
||||
+ java.net.SocketAddress socketAddress = this.connection.address;
|
||||
+ String hostnameOfRemote = socketAddress instanceof java.net.InetSocketAddress ? ((java.net.InetSocketAddress) socketAddress).getHostString() : InetAddress.getLoopbackAddress().getHostAddress();
|
||||
+ com.destroystokyo.paper.event.player.PlayerHandshakeEvent event = new com.destroystokyo.paper.event.player.PlayerHandshakeEvent(packet.hostName, hostnameOfRemote, !proxyLogicEnabled);
|
||||
+ if (event.callEvent()) {
|
||||
+ // If we've failed somehow, let the client know so and go no further.
|
||||
+ if (event.isFailed()) {
|
||||
+ Component component = io.papermc.paper.adventure.PaperAdventure.asVanilla(event.failMessage());
|
||||
+ this.connection.send(new ClientboundLoginDisconnectPacket(component));
|
||||
+ this.connection.disconnect(component);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (event.getServerHostname() != null) packet.hostName = event.getServerHostname();
|
||||
+ if (event.getSocketAddressHostname() != null) this.connection.address = new java.net.InetSocketAddress(event.getSocketAddressHostname(), socketAddress instanceof java.net.InetSocketAddress ? ((java.net.InetSocketAddress) socketAddress).getPort() : 0);
|
||||
+ this.connection.spoofedUUID = event.getUniqueId();
|
||||
+ this.connection.spoofedProfile = gson.fromJson(event.getPropertiesJson(), com.mojang.authlib.properties.Property[].class);
|
||||
+ handledByEvent = true; // Hooray, we did it!
|
||||
+ }
|
||||
+ }
|
||||
// Spigot Start
|
||||
String[] split = packet.hostName.split("\00");
|
||||
- if (org.spigotmc.SpigotConfig.bungee) {
|
||||
+ // Don't try and handle default logic if it's been handled by the event.
|
||||
+ if (!handledByEvent && proxyLogicEnabled) {
|
||||
+ // Paper end
|
||||
+ // if (org.spigotmc.SpigotConfig.bungee) { // Paper - comment out, we check above!
|
||||
if ( ( split.length == 3 || split.length == 4 ) && ( ServerHandshakePacketListenerImpl.HOST_PATTERN.matcher( split[1] ).matches() ) ) {
|
||||
packet.hostName = split[0];
|
||||
connection.address = new java.net.InetSocketAddress(split[1], ((java.net.InetSocketAddress) this.connection.getRemoteAddress()).getPort());
|
|
@ -1,47 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 16 Apr 2016 00:39:33 -0400
|
||||
Subject: [PATCH] Configurable RCON IP address
|
||||
|
||||
For servers with multiple IP's, ability to bind to a specific interface.
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.server.dedicated.Settings getStringRaw(Ljava/lang/String;)Ljava/lang/String;
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java
|
||||
index efa2dd7947f68aaec479d835f2b1e60d16254ae1..1e01277448a3cf2b2045b54b182166a66c822e20 100644
|
||||
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java
|
||||
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java
|
||||
@@ -100,6 +100,8 @@ public class DedicatedServerProperties extends Settings<DedicatedServerPropertie
|
||||
@Nullable
|
||||
private WorldGenSettings worldGenSettings;
|
||||
|
||||
+ public final String rconIp; // Paper - Add rcon ip
|
||||
+
|
||||
// CraftBukkit start
|
||||
public DedicatedServerProperties(Properties properties, OptionSet optionset) {
|
||||
super(properties, optionset);
|
||||
@@ -152,6 +154,10 @@ public class DedicatedServerProperties extends Settings<DedicatedServerPropertie
|
||||
return s.toLowerCase(Locale.ROOT);
|
||||
}, WorldPresets.NORMAL.location().toString()));
|
||||
this.serverResourcePackInfo = DedicatedServerProperties.getServerPackInfo(this.get("resource-pack", ""), this.get("resource-pack-sha1", ""), this.getLegacyString("resource-pack-hash"), this.get("require-resource-pack", false), this.get("resource-pack-prompt", ""));
|
||||
+ // Paper start - Configurable rcon ip
|
||||
+ final String rconIp = this.getStringRaw("rcon.ip");
|
||||
+ this.rconIp = rconIp == null ? this.serverIp : rconIp;
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
// CraftBukkit start
|
||||
diff --git a/src/main/java/net/minecraft/server/rcon/thread/RconThread.java b/src/main/java/net/minecraft/server/rcon/thread/RconThread.java
|
||||
index cb61eaf8447c8340c4b4e1079c0a6aecd41a6116..3bf60f640aa9fa4cabd2b3e5d3931e8467b9df24 100644
|
||||
--- a/src/main/java/net/minecraft/server/rcon/thread/RconThread.java
|
||||
+++ b/src/main/java/net/minecraft/server/rcon/thread/RconThread.java
|
||||
@@ -60,7 +60,7 @@ public class RconThread extends GenericThread {
|
||||
@Nullable
|
||||
public static RconThread create(ServerInterface server) {
|
||||
DedicatedServerProperties dedicatedServerProperties = server.getProperties();
|
||||
- String string = server.getServerIp();
|
||||
+ String string = dedicatedServerProperties.rconIp; // Paper - Configurable rcon ip
|
||||
if (string.isEmpty()) {
|
||||
string = "0.0.0.0";
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach.brown@destroystokyo.com>
|
||||
Date: Fri, 22 Apr 2016 01:43:11 -0500
|
||||
Subject: [PATCH] EntityRegainHealthEvent isFastRegen API
|
||||
|
||||
Don't even get me started
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index 766711e4d32ceebf9d94e39f9bcd14ff0371ad06..a0d6273a8a5613ee732c3dbb6eff46ecf42b5f4a 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -1250,10 +1250,16 @@ public abstract class LivingEntity extends Entity {
|
||||
}
|
||||
|
||||
public void heal(float f, EntityRegainHealthEvent.RegainReason regainReason) {
|
||||
+ // Paper start - Forward
|
||||
+ heal(f, regainReason, false);
|
||||
+ }
|
||||
+
|
||||
+ public void heal(float f, EntityRegainHealthEvent.RegainReason regainReason, boolean isFastRegen) {
|
||||
+ // Paper end
|
||||
float f1 = this.getHealth();
|
||||
|
||||
if (f1 > 0.0F) {
|
||||
- EntityRegainHealthEvent event = new EntityRegainHealthEvent(this.getBukkitEntity(), f, regainReason);
|
||||
+ EntityRegainHealthEvent event = new EntityRegainHealthEvent(this.getBukkitEntity(), f, regainReason, isFastRegen); // Paper
|
||||
// Suppress during worldgen
|
||||
if (this.valid) {
|
||||
this.level.getCraftServer().getPluginManager().callEvent(event);
|
||||
diff --git a/src/main/java/net/minecraft/world/food/FoodData.java b/src/main/java/net/minecraft/world/food/FoodData.java
|
||||
index ae323c786b5a0d61d9292469baa50a3ad8e4ccff..2934b6de1f1fb914a532ee20184df99d1acd8e65 100644
|
||||
--- a/src/main/java/net/minecraft/world/food/FoodData.java
|
||||
+++ b/src/main/java/net/minecraft/world/food/FoodData.java
|
||||
@@ -84,7 +84,7 @@ public class FoodData {
|
||||
if (this.tickTimer >= this.saturatedRegenRate) { // CraftBukkit
|
||||
float f = Math.min(this.saturationLevel, 6.0F);
|
||||
|
||||
- player.heal(f / 6.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.SATIATED); // CraftBukkit - added RegainReason
|
||||
+ player.heal(f / 6.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.SATIATED, true); // CraftBukkit - added RegainReason // Paper - This is fast regen
|
||||
// this.addExhaustion(f); CraftBukkit - EntityExhaustionEvent
|
||||
player.causeFoodExhaustion(f, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.REGEN); // CraftBukkit - EntityExhaustionEvent
|
||||
this.tickTimer = 0;
|
|
@ -1,33 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: kashike <kashike@vq.lc>
|
||||
Date: Thu, 21 Apr 2016 23:51:55 -0700
|
||||
Subject: [PATCH] Add ability to configure frosted_ice properties
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java b/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java
|
||||
index e1916fe8a7aa736d9266efde954bbfbda38a3a65..331b642c36af97f7f05bd63f96d42d1af443e5a3 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java
|
||||
@@ -32,6 +32,7 @@ public class FrostedIceBlock extends IceBlock {
|
||||
|
||||
@Override
|
||||
public void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
|
||||
+ if (!world.paperConfig().environment.frostedIce.enabled) return; // Paper - add ability to disable frosted ice
|
||||
if ((random.nextInt(3) == 0 || this.fewerNeigboursThan(world, pos, 4)) && world.getMaxLocalRawBrightness(pos) > 11 - state.getValue(AGE) - state.getLightBlock(world, pos) && this.slightlyMelt(state, world, pos)) {
|
||||
BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
|
||||
|
||||
@@ -39,12 +40,12 @@ public class FrostedIceBlock extends IceBlock {
|
||||
mutableBlockPos.setWithOffset(pos, direction);
|
||||
BlockState blockState = world.getBlockState(mutableBlockPos);
|
||||
if (blockState.is(this) && !this.slightlyMelt(blockState, world, mutableBlockPos)) {
|
||||
- world.scheduleTick(mutableBlockPos, this, Mth.nextInt(random, 20, 40));
|
||||
+ world.scheduleTick(mutableBlockPos, this, Mth.nextInt(random, world.paperConfig().environment.frostedIce.delay.min, world.paperConfig().environment.frostedIce.delay.max)); // Paper - use configurable min/max delay
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
- world.scheduleTick(pos, this, Mth.nextInt(random, 20, 40));
|
||||
+ world.scheduleTick(pos, this, Mth.nextInt(random, world.paperConfig().environment.frostedIce.delay.min, world.paperConfig().environment.frostedIce.delay.max)); // Paper - use configurable min/max delay
|
||||
}
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Thu, 28 Apr 2016 00:57:27 -0400
|
||||
Subject: [PATCH] remove null possibility for getServer singleton
|
||||
|
||||
to stop IDE complaining about potential NPE
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 17ad0051afaaa0e201782228628c691b75b6cebc..e24bd9c2be84dd11bf109e65ea4e1e577fe647ca 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -181,6 +181,7 @@ import co.aikar.timings.MinecraftTimings; // Paper
|
||||
|
||||
public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTask> implements CommandSource, AutoCloseable {
|
||||
|
||||
+ private static MinecraftServer SERVER; // Paper
|
||||
public static final Logger LOGGER = LogUtils.getLogger();
|
||||
public static final String VANILLA_BRAND = "vanilla";
|
||||
private static final float AVERAGE_TICK_TIME_SMOOTHING = 0.8F;
|
||||
@@ -307,6 +308,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
|
||||
public MinecraftServer(OptionSet options, DataPackConfig datapackconfiguration, DynamicOps<Tag> registryreadops, Thread thread, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PackRepository resourcepackrepository, WorldStem worldstem, Proxy proxy, DataFixer datafixer, Services services, ChunkProgressListenerFactory worldloadlistenerfactory) {
|
||||
super("Server");
|
||||
+ SERVER = this; // Paper - better singleton
|
||||
this.metricsRecorder = InactiveMetricsRecorder.INSTANCE;
|
||||
this.profiler = this.metricsRecorder.getProfiler();
|
||||
this.onMetricsRecordingStopped = (methodprofilerresults) -> {
|
||||
@@ -2291,9 +2293,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
return false;
|
||||
}
|
||||
|
||||
- @Deprecated
|
||||
public static MinecraftServer getServer() {
|
||||
- return (Bukkit.getServer() instanceof CraftServer) ? ((CraftServer) Bukkit.getServer()).getServer() : null;
|
||||
+ return SERVER; // Paper
|
||||
}
|
||||
// CraftBukkit end
|
||||
|
|
@ -1,128 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Fri, 29 Apr 2016 20:02:00 -0400
|
||||
Subject: [PATCH] Improve Maps (in item frames) performance and bug fixes
|
||||
|
||||
Maps used a modified version of rendering to support plugin controlled
|
||||
imaging on maps. The Craft Map Renderer is much slower than Vanilla,
|
||||
causing maps in item frames to cause a noticeable hit on server performance.
|
||||
|
||||
This updates the map system to not use the Craft system if we detect that no
|
||||
custom renderers are in use, defaulting to the much simpler Vanilla system.
|
||||
|
||||
Additionally, numerous issues to player position tracking on maps has been fixed.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 67c4b724b6b799c02ee4c5034d3472e44cb591fa..ec2d94e7b34b4384c5c37265869e6ddb15d6e6eb 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -2266,6 +2266,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
{
|
||||
if ( iter.next().player == entity )
|
||||
{
|
||||
+ map.decorations.remove(entity.getName().getString()); // Paper
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
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 4751fea5e7319600422c4fb3e40026a36db85a6a..845e52baf57492cfb0eb20318c84585e30001f0b 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
@@ -763,6 +763,14 @@ public abstract class Player extends LivingEntity {
|
||||
return null;
|
||||
}
|
||||
// CraftBukkit end
|
||||
+ // Paper start - remove player from map on drop
|
||||
+ if (itemstack.getItem() == Items.FILLED_MAP) {
|
||||
+ net.minecraft.world.level.saveddata.maps.MapItemSavedData worldmap = net.minecraft.world.item.MapItem.getSavedData(itemstack, this.level);
|
||||
+ if (worldmap != null) {
|
||||
+ worldmap.tickCarriedBy(this, itemstack);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
return entityitem;
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
|
||||
index b8d33dc1dc31fb2bcde0d74504f3972b0cc28f17..7254e7a42c58737cfc04f09aaca2fe1ebeec6d08 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
|
||||
@@ -63,6 +63,7 @@ public class MapItemSavedData extends SavedData {
|
||||
public final Map<String, MapDecoration> decorations = Maps.newLinkedHashMap();
|
||||
private final Map<String, MapFrame> frameMarkers = Maps.newHashMap();
|
||||
private int trackedDecorationCount;
|
||||
+ private org.bukkit.craftbukkit.map.RenderData vanillaRender = new org.bukkit.craftbukkit.map.RenderData(); // Paper
|
||||
|
||||
// CraftBukkit start
|
||||
public final CraftMapView mapView;
|
||||
@@ -83,6 +84,7 @@ public class MapItemSavedData extends SavedData {
|
||||
// CraftBukkit start
|
||||
this.mapView = new CraftMapView(this);
|
||||
this.server = (CraftServer) org.bukkit.Bukkit.getServer();
|
||||
+ this.vanillaRender.buffer = colors; // Paper
|
||||
// CraftBukkit end
|
||||
}
|
||||
|
||||
@@ -138,6 +140,7 @@ public class MapItemSavedData extends SavedData {
|
||||
if (abyte.length == 16384) {
|
||||
worldmap.colors = abyte;
|
||||
}
|
||||
+ worldmap.vanillaRender.buffer = abyte; // Paper
|
||||
|
||||
ListTag nbttaglist = nbt.getList("banners", 10);
|
||||
|
||||
@@ -548,6 +551,21 @@ public class MapItemSavedData extends SavedData {
|
||||
|
||||
public class HoldingPlayer {
|
||||
|
||||
+ // Paper start
|
||||
+ private void addSeenPlayers(java.util.Collection<MapDecoration> icons) {
|
||||
+ org.bukkit.entity.Player player = (org.bukkit.entity.Player) this.player.getBukkitEntity();
|
||||
+ MapItemSavedData.this.decorations.forEach((name, mapIcon) -> {
|
||||
+ // If this cursor is for a player check visibility with vanish system
|
||||
+ org.bukkit.entity.Player other = org.bukkit.Bukkit.getPlayerExact(name); // Spigot
|
||||
+ if (other == null || player.canSee(other)) {
|
||||
+ icons.add(mapIcon);
|
||||
+ }
|
||||
+ });
|
||||
+ }
|
||||
+ private boolean shouldUseVanillaMap() {
|
||||
+ return mapView.getRenderers().size() == 1 && mapView.getRenderers().get(0).getClass() == org.bukkit.craftbukkit.map.CraftMapRenderer.class;
|
||||
+ }
|
||||
+ // Paper end
|
||||
public final Player player;
|
||||
private boolean dirtyData = true;
|
||||
private int minDirtyX;
|
||||
@@ -581,7 +599,9 @@ public class MapItemSavedData extends SavedData {
|
||||
@Nullable
|
||||
Packet<?> nextUpdatePacket(int mapId) {
|
||||
MapItemSavedData.MapPatch worldmap_b;
|
||||
- org.bukkit.craftbukkit.map.RenderData render = MapItemSavedData.this.mapView.render((org.bukkit.craftbukkit.entity.CraftPlayer) this.player.getBukkitEntity()); // CraftBukkit
|
||||
+ if (!this.dirtyData && this.tick % 5 != 0) { this.tick++; return null; } // Paper - this won't end up sending, so don't render it!
|
||||
+ boolean vanillaMaps = shouldUseVanillaMap(); // Paper
|
||||
+ org.bukkit.craftbukkit.map.RenderData render = !vanillaMaps ? MapItemSavedData.this.mapView.render((org.bukkit.craftbukkit.entity.CraftPlayer) this.player.getBukkitEntity()) : MapItemSavedData.this.vanillaRender; // CraftBukkit // Paper
|
||||
|
||||
if (this.dirtyData) {
|
||||
this.dirtyData = false;
|
||||
@@ -597,6 +617,8 @@ public class MapItemSavedData extends SavedData {
|
||||
// CraftBukkit start
|
||||
java.util.Collection<MapDecoration> icons = new java.util.ArrayList<MapDecoration>();
|
||||
|
||||
+ if (vanillaMaps) addSeenPlayers(icons); // Paper
|
||||
+
|
||||
for (org.bukkit.map.MapCursor cursor : render.cursors) {
|
||||
if (cursor.isVisible()) {
|
||||
icons.add(new MapDecoration(MapDecoration.Type.byIcon(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), PaperAdventure.asVanilla(cursor.caption()))); // Paper - Adventure
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/map/RenderData.java b/src/main/java/org/bukkit/craftbukkit/map/RenderData.java
|
||||
index 256a131781721c86dd6cdbc329335964570cbe8c..5768cd512ec166f1e8d1f4a28792015347297c3f 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/map/RenderData.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/map/RenderData.java
|
||||
@@ -5,7 +5,7 @@ import org.bukkit.map.MapCursor;
|
||||
|
||||
public class RenderData {
|
||||
|
||||
- public final byte[] buffer;
|
||||
+ public byte[] buffer; // Paper
|
||||
public final ArrayList<MapCursor> cursors;
|
||||
|
||||
public RenderData() {
|
|
@ -1,770 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 1 May 2016 21:19:14 -0400
|
||||
Subject: [PATCH] LootTable API & Replenishable Lootables Feature
|
||||
|
||||
Provides an API to control the loot table for an object.
|
||||
Also provides a feature that any Lootable Inventory (Chests in Structures)
|
||||
can automatically replenish after a given time.
|
||||
|
||||
This feature is good for long term worlds so that newer players
|
||||
do not suffer with "Every chest has been looted"
|
||||
|
||||
== AT ==
|
||||
public org.bukkit.craftbukkit.block.CraftBlockEntityState getTileEntity()Lnet/minecraft/world/level/block/entity/BlockEntity;
|
||||
public org.bukkit.craftbukkit.block.CraftLootable setLootTable(Lorg/bukkit/loot/LootTable;J)V
|
||||
public org.bukkit.craftbukkit.entity.CraftMinecartContainer setLootTable(Lorg/bukkit/loot/LootTable;J)V
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperContainerEntityLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperContainerEntityLootableInventory.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..88e32ed64f90bfd277dac84ba4bd84f0d943f5f8
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperContainerEntityLootableInventory.java
|
||||
@@ -0,0 +1,63 @@
|
||||
+package com.destroystokyo.paper.loottable;
|
||||
+
|
||||
+import net.minecraft.world.entity.Entity;
|
||||
+import net.minecraft.world.entity.vehicle.AbstractMinecartContainer;
|
||||
+import net.minecraft.world.entity.vehicle.ContainerEntity;
|
||||
+import net.minecraft.world.level.Level;
|
||||
+import org.bukkit.Bukkit;
|
||||
+import org.bukkit.craftbukkit.util.CraftNamespacedKey;
|
||||
+
|
||||
+public class PaperContainerEntityLootableInventory implements PaperLootableEntityInventory {
|
||||
+
|
||||
+ private final ContainerEntity entity;
|
||||
+
|
||||
+ public PaperContainerEntityLootableInventory(ContainerEntity entity) {
|
||||
+ this.entity = entity;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public org.bukkit.loot.LootTable getLootTable() {
|
||||
+ return entity.getLootTable() != null ? Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(entity.getLootTable())) : null;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setLootTable(org.bukkit.loot.LootTable table, long seed) {
|
||||
+ setLootTable(table);
|
||||
+ setSeed(seed);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setSeed(long seed) {
|
||||
+ entity.setLootTableSeed(seed);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public long getSeed() {
|
||||
+ return entity.getLootTableSeed();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setLootTable(org.bukkit.loot.LootTable table) {
|
||||
+ entity.setLootTable((table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public PaperLootableInventoryData getLootableData() {
|
||||
+ return entity.getLootableData();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Entity getHandle() {
|
||||
+ return entity.getEntity();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public LootableInventory getAPILootableInventory() {
|
||||
+ return (LootableInventory) entity.getEntity().getBukkitEntity();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Level getNMSWorld() {
|
||||
+ return entity.getLevel();
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..70ca5625ff5d13a8e9cd64953066a7e1547ff223
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java
|
||||
@@ -0,0 +1,33 @@
|
||||
+package com.destroystokyo.paper.loottable;
|
||||
+
|
||||
+import net.minecraft.core.BlockPos;
|
||||
+import net.minecraft.world.level.Level;
|
||||
+import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity;
|
||||
+import org.bukkit.Chunk;
|
||||
+import org.bukkit.block.Block;
|
||||
+
|
||||
+public interface PaperLootableBlockInventory extends LootableBlockInventory, PaperLootableInventory {
|
||||
+
|
||||
+ RandomizableContainerBlockEntity getTileEntity();
|
||||
+
|
||||
+ @Override
|
||||
+ default LootableInventory getAPILootableInventory() {
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default Level getNMSWorld() {
|
||||
+ return getTileEntity().getLevel();
|
||||
+ }
|
||||
+
|
||||
+ default Block getBlock() {
|
||||
+ final BlockPos position = getTileEntity().getBlockPos();
|
||||
+ final Chunk bukkitChunk = getTileEntity().getLevel().getChunkAt(position).bukkitChunk;
|
||||
+ return bukkitChunk.getBlock(position.getX(), position.getY(), position.getZ());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default PaperLootableInventoryData getLootableData() {
|
||||
+ return getTileEntity().lootableData;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..2fba5bc0f982e143ad5f5bda55d768edc5f847df
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java
|
||||
@@ -0,0 +1,28 @@
|
||||
+package com.destroystokyo.paper.loottable;
|
||||
+
|
||||
+import net.minecraft.world.level.Level;
|
||||
+import org.bukkit.entity.Entity;
|
||||
+
|
||||
+public interface PaperLootableEntityInventory extends LootableEntityInventory, PaperLootableInventory {
|
||||
+
|
||||
+ net.minecraft.world.entity.Entity getHandle();
|
||||
+
|
||||
+ @Override
|
||||
+ default LootableInventory getAPILootableInventory() {
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ default Entity getEntity() {
|
||||
+ return getHandle().getBukkitEntity();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default Level getNMSWorld() {
|
||||
+ return getHandle().getCommandSenderWorld();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default PaperLootableInventoryData getLootableData() {
|
||||
+ return getHandle().lootableData;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..ce135d990c785b02df468391ea622aa236290f07
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java
|
||||
@@ -0,0 +1,70 @@
|
||||
+package com.destroystokyo.paper.loottable;
|
||||
+
|
||||
+import org.bukkit.loot.Lootable;
|
||||
+import java.util.UUID;
|
||||
+import net.minecraft.world.level.Level;
|
||||
+
|
||||
+public interface PaperLootableInventory extends LootableInventory, Lootable {
|
||||
+
|
||||
+ PaperLootableInventoryData getLootableData();
|
||||
+ LootableInventory getAPILootableInventory();
|
||||
+
|
||||
+ Level getNMSWorld();
|
||||
+
|
||||
+ default org.bukkit.World getBukkitWorld() {
|
||||
+ return getNMSWorld().getWorld();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default boolean isRefillEnabled() {
|
||||
+ return getNMSWorld().paperConfig().lootables.autoReplenish;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default boolean hasBeenFilled() {
|
||||
+ return getLastFilled() != -1;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default boolean hasPlayerLooted(UUID player) {
|
||||
+ return getLootableData().hasPlayerLooted(player);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default Long getLastLooted(UUID player) {
|
||||
+ return getLootableData().getLastLooted(player);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default boolean setHasPlayerLooted(UUID player, boolean looted) {
|
||||
+ final boolean hasLooted = hasPlayerLooted(player);
|
||||
+ if (hasLooted != looted) {
|
||||
+ getLootableData().setPlayerLootedState(player, looted);
|
||||
+ }
|
||||
+ return hasLooted;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default boolean hasPendingRefill() {
|
||||
+ long nextRefill = getLootableData().getNextRefill();
|
||||
+ return nextRefill != -1 && nextRefill > getLootableData().getLastFill();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default long getLastFilled() {
|
||||
+ return getLootableData().getLastFill();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default long getNextRefill() {
|
||||
+ return getLootableData().getNextRefill();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default long setNextRefill(long refillAt) {
|
||||
+ if (refillAt < -1) {
|
||||
+ refillAt = -1;
|
||||
+ }
|
||||
+ return getLootableData().setNextRefill(refillAt);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..e5ea9f27a1936ed9e329e74317c91c5df89b9fbd
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java
|
||||
@@ -0,0 +1,179 @@
|
||||
+package com.destroystokyo.paper.loottable;
|
||||
+
|
||||
+import io.papermc.paper.configuration.WorldConfiguration;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.loot.LootTable;
|
||||
+import javax.annotation.Nullable;
|
||||
+import net.minecraft.nbt.CompoundTag;
|
||||
+import net.minecraft.nbt.ListTag;
|
||||
+import java.util.HashMap;
|
||||
+import java.util.Map;
|
||||
+import java.util.Random;
|
||||
+import java.util.UUID;
|
||||
+
|
||||
+public class PaperLootableInventoryData {
|
||||
+
|
||||
+ private static final Random RANDOM = new Random();
|
||||
+
|
||||
+ private long lastFill = -1;
|
||||
+ private long nextRefill = -1;
|
||||
+ private int numRefills = 0;
|
||||
+ private Map<UUID, Long> lootedPlayers;
|
||||
+ private final PaperLootableInventory lootable;
|
||||
+
|
||||
+ public PaperLootableInventoryData(PaperLootableInventory lootable) {
|
||||
+ this.lootable = lootable;
|
||||
+ }
|
||||
+
|
||||
+ long getLastFill() {
|
||||
+ return this.lastFill;
|
||||
+ }
|
||||
+
|
||||
+ long getNextRefill() {
|
||||
+ return this.nextRefill;
|
||||
+ }
|
||||
+
|
||||
+ long setNextRefill(long nextRefill) {
|
||||
+ long prev = this.nextRefill;
|
||||
+ this.nextRefill = nextRefill;
|
||||
+ return prev;
|
||||
+ }
|
||||
+
|
||||
+ public boolean shouldReplenish(@Nullable net.minecraft.world.entity.player.Player player) {
|
||||
+ LootTable table = this.lootable.getLootTable();
|
||||
+
|
||||
+ // No Loot Table associated
|
||||
+ if (table == null) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ // ALWAYS process the first fill or if the feature is disabled
|
||||
+ if (this.lastFill == -1 || !this.lootable.getNMSWorld().paperConfig().lootables.autoReplenish) {
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ // Only process refills when a player is set
|
||||
+ if (player == null) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ // Chest is not scheduled for refill
|
||||
+ if (this.nextRefill == -1) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ final WorldConfiguration paperConfig = this.lootable.getNMSWorld().paperConfig();
|
||||
+
|
||||
+ // Check if max refills has been hit
|
||||
+ if (paperConfig.lootables.maxRefills != -1 && this.numRefills >= paperConfig.lootables.maxRefills) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ // Refill has not been reached
|
||||
+ if (this.nextRefill > System.currentTimeMillis()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ final Player bukkitPlayer = (Player) player.getBukkitEntity();
|
||||
+ LootableInventoryReplenishEvent event = new LootableInventoryReplenishEvent(bukkitPlayer, lootable.getAPILootableInventory());
|
||||
+ if (paperConfig.lootables.restrictPlayerReloot && hasPlayerLooted(player.getUUID())) {
|
||||
+ event.setCancelled(true);
|
||||
+ }
|
||||
+ return event.callEvent();
|
||||
+ }
|
||||
+ public void processRefill(@Nullable net.minecraft.world.entity.player.Player player) {
|
||||
+ this.lastFill = System.currentTimeMillis();
|
||||
+ final WorldConfiguration paperConfig = this.lootable.getNMSWorld().paperConfig();
|
||||
+ if (paperConfig.lootables.autoReplenish) {
|
||||
+ long min = paperConfig.lootables.refreshMin.seconds();
|
||||
+ long max = paperConfig.lootables.refreshMax.seconds();
|
||||
+ this.nextRefill = this.lastFill + (min + RANDOM.nextLong(max - min + 1)) * 1000L;
|
||||
+ this.numRefills++;
|
||||
+ if (paperConfig.lootables.resetSeedOnFill) {
|
||||
+ this.lootable.setSeed(0);
|
||||
+ }
|
||||
+ if (player != null) { // This means that numRefills can be incremented without a player being in the lootedPlayers list - Seems to be EntityMinecartChest specific
|
||||
+ this.setPlayerLootedState(player.getUUID(), true);
|
||||
+ }
|
||||
+ } else {
|
||||
+ this.lootable.clearLootTable();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ public void loadNbt(CompoundTag base) {
|
||||
+ if (!base.contains("Paper.LootableData", 10)) { // 10 = compound
|
||||
+ return;
|
||||
+ }
|
||||
+ CompoundTag comp = base.getCompound("Paper.LootableData");
|
||||
+ if (comp.contains("lastFill")) {
|
||||
+ this.lastFill = comp.getLong("lastFill");
|
||||
+ }
|
||||
+ if (comp.contains("nextRefill")) {
|
||||
+ this.nextRefill = comp.getLong("nextRefill");
|
||||
+ }
|
||||
+
|
||||
+ if (comp.contains("numRefills")) {
|
||||
+ this.numRefills = comp.getInt("numRefills");
|
||||
+ }
|
||||
+ if (comp.contains("lootedPlayers", 9)) { // 9 = list
|
||||
+ ListTag list = comp.getList("lootedPlayers", 10); // 10 = compound
|
||||
+ final int size = list.size();
|
||||
+ if (size > 0) {
|
||||
+ this.lootedPlayers = new HashMap<>(list.size());
|
||||
+ }
|
||||
+ for (int i = 0; i < size; i++) {
|
||||
+ final CompoundTag cmp = list.getCompound(i);
|
||||
+ lootedPlayers.put(cmp.getUUID("UUID"), cmp.getLong("Time"));
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ public void saveNbt(CompoundTag base) {
|
||||
+ CompoundTag comp = new CompoundTag();
|
||||
+ if (this.nextRefill != -1) {
|
||||
+ comp.putLong("nextRefill", this.nextRefill);
|
||||
+ }
|
||||
+ if (this.lastFill != -1) {
|
||||
+ comp.putLong("lastFill", this.lastFill);
|
||||
+ }
|
||||
+ if (this.numRefills != 0) {
|
||||
+ comp.putInt("numRefills", this.numRefills);
|
||||
+ }
|
||||
+ if (this.lootedPlayers != null && !this.lootedPlayers.isEmpty()) {
|
||||
+ ListTag list = new ListTag();
|
||||
+ for (Map.Entry<UUID, Long> entry : this.lootedPlayers.entrySet()) {
|
||||
+ CompoundTag cmp = new CompoundTag();
|
||||
+ cmp.putUUID("UUID", entry.getKey());
|
||||
+ cmp.putLong("Time", entry.getValue());
|
||||
+ list.add(cmp);
|
||||
+ }
|
||||
+ comp.put("lootedPlayers", list);
|
||||
+ }
|
||||
+
|
||||
+ if (!comp.isEmpty()) {
|
||||
+ base.put("Paper.LootableData", comp);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ void setPlayerLootedState(UUID player, boolean looted) {
|
||||
+ if (looted && this.lootedPlayers == null) {
|
||||
+ this.lootedPlayers = new HashMap<>();
|
||||
+ }
|
||||
+ if (looted) {
|
||||
+ if (!this.lootedPlayers.containsKey(player)) {
|
||||
+ this.lootedPlayers.put(player, System.currentTimeMillis());
|
||||
+ }
|
||||
+ } else if (this.lootedPlayers != null) {
|
||||
+ this.lootedPlayers.remove(player);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ boolean hasPlayerLooted(UUID player) {
|
||||
+ return this.lootedPlayers != null && this.lootedPlayers.containsKey(player);
|
||||
+ }
|
||||
+
|
||||
+ Long getLastLooted(UUID player) {
|
||||
+ return lootedPlayers != null ? lootedPlayers.get(player) : null;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..9cfa5d36a6991067a3866e0d437749fafcc0158e
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java
|
||||
@@ -0,0 +1,65 @@
|
||||
+package com.destroystokyo.paper.loottable;
|
||||
+
|
||||
+import io.papermc.paper.util.MCUtil;
|
||||
+import net.minecraft.world.level.Level;
|
||||
+import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity;
|
||||
+import org.bukkit.Bukkit;
|
||||
+import org.bukkit.craftbukkit.util.CraftNamespacedKey;
|
||||
+
|
||||
+public class PaperTileEntityLootableInventory implements PaperLootableBlockInventory {
|
||||
+ private RandomizableContainerBlockEntity tileEntityLootable;
|
||||
+
|
||||
+ public PaperTileEntityLootableInventory(RandomizableContainerBlockEntity tileEntityLootable) {
|
||||
+ this.tileEntityLootable = tileEntityLootable;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public org.bukkit.loot.LootTable getLootTable() {
|
||||
+ return tileEntityLootable.lootTable != null ? Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(tileEntityLootable.lootTable)) : null;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setLootTable(org.bukkit.loot.LootTable table, long seed) {
|
||||
+ setLootTable(table);
|
||||
+ setSeed(seed);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setLootTable(org.bukkit.loot.LootTable table) {
|
||||
+ tileEntityLootable.lootTable = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setSeed(long seed) {
|
||||
+ tileEntityLootable.lootTableSeed = seed;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public long getSeed() {
|
||||
+ return tileEntityLootable.lootTableSeed;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public PaperLootableInventoryData getLootableData() {
|
||||
+ return tileEntityLootable.lootableData;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public RandomizableContainerBlockEntity getTileEntity() {
|
||||
+ return tileEntityLootable;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public LootableInventory getAPILootableInventory() {
|
||||
+ Level world = tileEntityLootable.getLevel();
|
||||
+ if (world == null) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ return (LootableInventory) getBukkitWorld().getBlockAt(MCUtil.toLocation(world, tileEntityLootable.getBlockPos())).getState();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Level getNMSWorld() {
|
||||
+ return tileEntityLootable.getLevel();
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index dd5e9dc310f30c008f0c8c60ac4305160261bad9..a6b5527e97e8a5b2eeca762477a7b695223a0d4d 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -232,6 +232,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
||||
}
|
||||
// Paper end
|
||||
|
||||
+ public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper
|
||||
private CraftEntity bukkitEntity;
|
||||
|
||||
public CraftEntity getBukkitEntity() {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java
|
||||
index 9347faecdaa3ef8c375fe8b0a89fc3385b6823bd..b8fb7b5a347298ada16bc8b818edf1863e3f6040 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java
|
||||
@@ -32,6 +32,20 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme
|
||||
public ResourceLocation lootTable;
|
||||
public long lootTableSeed;
|
||||
|
||||
+ // Paper start
|
||||
+ {
|
||||
+ this.lootableData = new com.destroystokyo.paper.loottable.PaperLootableInventoryData(new com.destroystokyo.paper.loottable.PaperContainerEntityLootableInventory(this));
|
||||
+ }
|
||||
+ @Override
|
||||
+ public Entity getEntity() {
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public com.destroystokyo.paper.loottable.PaperLootableInventoryData getLootableData() {
|
||||
+ return this.lootableData;
|
||||
+ }
|
||||
+ // Paper end
|
||||
// CraftBukkit start
|
||||
public List<HumanEntity> transaction = new java.util.ArrayList<HumanEntity>();
|
||||
private int maxStack = MAX_STACK;
|
||||
@@ -134,12 +148,14 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme
|
||||
@Override
|
||||
protected void addAdditionalSaveData(CompoundTag nbt) {
|
||||
super.addAdditionalSaveData(nbt);
|
||||
+ this.lootableData.loadNbt(nbt); // Paper
|
||||
this.addChestVehicleSaveData(nbt);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void readAdditionalSaveData(CompoundTag nbt) {
|
||||
super.readAdditionalSaveData(nbt);
|
||||
+ this.lootableData.loadNbt(nbt); // Paper
|
||||
this.readChestVehicleSaveData(nbt);
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/vehicle/ChestBoat.java b/src/main/java/net/minecraft/world/entity/vehicle/ChestBoat.java
|
||||
index abb35b675fc075c1004a85cd8f0c6f65d290a809..ba14657c6911bfd54da6ee9e248b3a050455d68a 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/vehicle/ChestBoat.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/vehicle/ChestBoat.java
|
||||
@@ -65,12 +65,14 @@ public class ChestBoat extends Boat implements HasCustomInventoryScreen, Contain
|
||||
@Override
|
||||
protected void addAdditionalSaveData(CompoundTag nbt) {
|
||||
super.addAdditionalSaveData(nbt);
|
||||
+ this.lootableData.loadNbt(nbt); // Paper
|
||||
this.addChestVehicleSaveData(nbt);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void readAdditionalSaveData(CompoundTag nbt) {
|
||||
super.readAdditionalSaveData(nbt);
|
||||
+ this.lootableData.loadNbt(nbt); // Paper
|
||||
this.readChestVehicleSaveData(nbt);
|
||||
}
|
||||
|
||||
@@ -223,6 +225,20 @@ public class ChestBoat extends Boat implements HasCustomInventoryScreen, Contain
|
||||
this.itemStacks = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY);
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ {
|
||||
+ this.lootableData = new com.destroystokyo.paper.loottable.PaperLootableInventoryData(new com.destroystokyo.paper.loottable.PaperContainerEntityLootableInventory(this));
|
||||
+ }
|
||||
+ @Override
|
||||
+ public Entity getEntity() {
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public com.destroystokyo.paper.loottable.PaperLootableInventoryData getLootableData() {
|
||||
+ return this.lootableData;
|
||||
+ }
|
||||
+ // Paper end
|
||||
// CraftBukkit start
|
||||
public List<HumanEntity> transaction = new java.util.ArrayList<HumanEntity>();
|
||||
private int maxStack = MAX_STACK;
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/vehicle/ContainerEntity.java b/src/main/java/net/minecraft/world/entity/vehicle/ContainerEntity.java
|
||||
index e2a9782e0ae60eb5557dce0831084c5722687df6..6ae9cccb28b2354ee47e6682082f92f3ecd56a67 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/vehicle/ContainerEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/vehicle/ContainerEntity.java
|
||||
@@ -61,7 +61,7 @@ public interface ContainerEntity extends Container, MenuProvider {
|
||||
if (this.getLootTableSeed() != 0L) {
|
||||
nbt.putLong("LootTableSeed", this.getLootTableSeed());
|
||||
}
|
||||
- } else {
|
||||
+ } else if (true) { // Paper - always load the items, table may still remain
|
||||
ContainerHelper.saveAllItems(nbt, this.getItemStacks());
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ public interface ContainerEntity extends Container, MenuProvider {
|
||||
if (nbt.contains("LootTable", 8)) {
|
||||
this.setLootTable(new ResourceLocation(nbt.getString("LootTable")));
|
||||
this.setLootTableSeed(nbt.getLong("LootTableSeed"));
|
||||
- } else {
|
||||
+ } else if (true) { // Paper - always load the items, table may still remain
|
||||
ContainerHelper.loadAllItems(nbt, this.getItemStacks());
|
||||
}
|
||||
|
||||
@@ -104,13 +104,15 @@ public interface ContainerEntity extends Container, MenuProvider {
|
||||
|
||||
default void unpackChestVehicleLootTable(@Nullable Player player) {
|
||||
MinecraftServer minecraftServer = this.getLevel().getServer();
|
||||
- if (this.getLootTable() != null && minecraftServer != null) {
|
||||
+ if (this.getLootableData().shouldReplenish(player) && minecraftServer != null) { // Paper
|
||||
LootTable lootTable = minecraftServer.getLootTables().get(this.getLootTable());
|
||||
if (player != null) {
|
||||
CriteriaTriggers.GENERATE_LOOT.trigger((ServerPlayer)player, this.getLootTable());
|
||||
}
|
||||
|
||||
- this.setLootTable((ResourceLocation)null);
|
||||
+ // this.setLootTable((ResourceLocation)null); // Paper
|
||||
+ this.getLootableData().processRefill(player); // Paper
|
||||
+
|
||||
LootContext.Builder builder = (new LootContext.Builder((ServerLevel)this.getLevel())).withParameter(LootContextParams.ORIGIN, this.position()).withOptionalRandomSeed(this.getLootTableSeed());
|
||||
if (player != null) {
|
||||
builder.withLuck(player.getLuck()).withParameter(LootContextParams.THIS_ENTITY, player);
|
||||
@@ -184,4 +186,13 @@ public interface ContainerEntity extends Container, MenuProvider {
|
||||
default boolean isChestVehicleStillValid(Player player) {
|
||||
return !this.isRemoved() && this.position().closerThan(player.position(), 8.0D);
|
||||
}
|
||||
+ // Paper start
|
||||
+ default Entity getEntity() {
|
||||
+ throw new UnsupportedOperationException();
|
||||
+ }
|
||||
+
|
||||
+ default com.destroystokyo.paper.loottable.PaperLootableInventoryData getLootableData() {
|
||||
+ throw new UnsupportedOperationException();
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
|
||||
index 216fc20326d71121098430dc1b9f7477265a91b7..e3bee2df77d87630e96621470e940d9d9e152e7f 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
|
||||
@@ -28,6 +28,7 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc
|
||||
@Nullable
|
||||
public ResourceLocation lootTable;
|
||||
public long lootTableSeed;
|
||||
+ public final com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData = new com.destroystokyo.paper.loottable.PaperLootableInventoryData(new com.destroystokyo.paper.loottable.PaperTileEntityLootableInventory(this)); // Paper
|
||||
|
||||
protected RandomizableContainerBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
||||
super(type, pos, state);
|
||||
@@ -42,16 +43,19 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc
|
||||
}
|
||||
|
||||
protected boolean tryLoadLootTable(CompoundTag nbt) {
|
||||
+ this.lootableData.loadNbt(nbt); // Paper
|
||||
if (nbt.contains("LootTable", 8)) {
|
||||
this.lootTable = new ResourceLocation(nbt.getString("LootTable"));
|
||||
+ try { org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(this.lootTable); } catch (IllegalArgumentException ex) { this.lootTable = null; } // Paper - validate
|
||||
this.lootTableSeed = nbt.getLong("LootTableSeed");
|
||||
- return true;
|
||||
+ return false; // Paper - always load the items, table may still remain
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean trySaveLootTable(CompoundTag nbt) {
|
||||
+ this.lootableData.saveNbt(nbt); // Paper
|
||||
if (this.lootTable == null) {
|
||||
return false;
|
||||
} else {
|
||||
@@ -60,18 +64,19 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc
|
||||
nbt.putLong("LootTableSeed", this.lootTableSeed);
|
||||
}
|
||||
|
||||
- return true;
|
||||
+ return false; // Paper - always save the items, table may still remain
|
||||
}
|
||||
}
|
||||
|
||||
public void unpackLootTable(@Nullable Player player) {
|
||||
- if (this.lootTable != null && this.level.getServer() != null) {
|
||||
+ if (this.lootableData.shouldReplenish(player) && this.level.getServer() != null) { // Paper
|
||||
LootTable lootTable = this.level.getServer().getLootTables().get(this.lootTable);
|
||||
if (player instanceof ServerPlayer) {
|
||||
CriteriaTriggers.GENERATE_LOOT.trigger((ServerPlayer)player, this.lootTable);
|
||||
}
|
||||
|
||||
- this.lootTable = null;
|
||||
+ //this.lootTable = null; // Paper
|
||||
+ this.lootableData.processRefill(player); // Paper
|
||||
LootContext.Builder builder = (new LootContext.Builder((ServerLevel)this.level)).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(this.worldPosition)).withOptionalRandomSeed(this.lootTableSeed);
|
||||
if (player != null) {
|
||||
builder.withLuck(player.getLuck()).withParameter(LootContextParams.THIS_ENTITY, player);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java
|
||||
index b31fa63019822bc172d85427b3f3f2c154d7e179..82b3f3b3aced73ce136b6b94fe212972ac6090ef 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java
|
||||
@@ -12,8 +12,9 @@ import org.bukkit.craftbukkit.CraftWorld;
|
||||
import org.bukkit.craftbukkit.inventory.CraftInventory;
|
||||
import org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
+import com.destroystokyo.paper.loottable.PaperLootableBlockInventory; // Paper
|
||||
|
||||
-public class CraftChest extends CraftLootable<ChestBlockEntity> implements Chest {
|
||||
+public class CraftChest extends CraftLootable<ChestBlockEntity> implements Chest, PaperLootableBlockInventory { // Paper
|
||||
|
||||
public CraftChest(World world, ChestBlockEntity tileEntity) {
|
||||
super(world, tileEntity);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java b/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java
|
||||
index 982adacb361b0590799dc68f9b7c13c7195627fd..e49eece9bff3a53469673d03a7bbf8f9cf8776b8 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java
|
||||
@@ -9,7 +9,7 @@ import org.bukkit.craftbukkit.util.CraftNamespacedKey;
|
||||
import org.bukkit.loot.LootTable;
|
||||
import org.bukkit.loot.Lootable;
|
||||
|
||||
-public abstract class CraftLootable<T extends RandomizableContainerBlockEntity> extends CraftContainer<T> implements Nameable, Lootable {
|
||||
+public abstract class CraftLootable<T extends RandomizableContainerBlockEntity> extends CraftContainer<T> implements Nameable, Lootable, com.destroystokyo.paper.loottable.PaperLootableBlockInventory { // Paper
|
||||
|
||||
public CraftLootable(World world, T tileEntity) {
|
||||
super(world, tileEntity);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftChestBoat.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftChestBoat.java
|
||||
index ae07db69b11b993b50782c94aa5c45b97d949612..06a96f027f90fd5bf05de72c8722ff5a81608b66 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftChestBoat.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftChestBoat.java
|
||||
@@ -11,8 +11,7 @@ import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.loot.LootTable;
|
||||
|
||||
-public class CraftChestBoat extends CraftBoat implements org.bukkit.entity.ChestBoat {
|
||||
-
|
||||
+public class CraftChestBoat extends CraftBoat implements org.bukkit.entity.ChestBoat, com.destroystokyo.paper.loottable.PaperLootableEntityInventory { // Paper
|
||||
private final Inventory inventory;
|
||||
|
||||
public CraftChestBoat(CraftServer server, ChestBoat entity) {
|
||||
@@ -66,7 +65,7 @@ public class CraftChestBoat extends CraftBoat implements org.bukkit.entity.Chest
|
||||
return this.getHandle().getLootTableSeed();
|
||||
}
|
||||
|
||||
- private void setLootTable(LootTable table, long seed) {
|
||||
+ public void setLootTable(LootTable table, long seed) { // Paper - change visibility since it overrides a public method
|
||||
ResourceLocation newKey = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey());
|
||||
this.getHandle().setLootTable(newKey);
|
||||
this.getHandle().setLootTableSeed(seed);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java
|
||||
index eb21b8457774d5ac765fa9008157cb29d9b72509..abf58bef2042a9efba5a78fd7f97339deceaa780 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java
|
||||
@@ -8,7 +8,7 @@ import org.bukkit.entity.minecart.StorageMinecart;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
-public class CraftMinecartChest extends CraftMinecartContainer implements StorageMinecart {
|
||||
+public class CraftMinecartChest extends CraftMinecartContainer implements StorageMinecart, com.destroystokyo.paper.loottable.PaperLootableEntityInventory { // Paper
|
||||
private final CraftInventory inventory;
|
||||
|
||||
public CraftMinecartChest(CraftServer server, MinecartChest entity) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java
|
||||
index 34b8f103625f087bb725bed595dd9c30f4a6f70c..ee9648739fb39c5842063d7442df6eb5c9336d7f 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java
|
||||
@@ -7,7 +7,7 @@ import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.minecart.HopperMinecart;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
|
||||
-public final class CraftMinecartHopper extends CraftMinecartContainer implements HopperMinecart {
|
||||
+public final class CraftMinecartHopper extends CraftMinecartContainer implements HopperMinecart, com.destroystokyo.paper.loottable.PaperLootableEntityInventory { // Paper
|
||||
private final CraftInventory inventory;
|
||||
|
||||
public CraftMinecartHopper(CraftServer server, MinecartHopper entity) {
|
|
@ -1,18 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 7 May 2016 23:33:08 -0400
|
||||
Subject: [PATCH] Don't save empty scoreboard teams to scoreboard.dat
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/scores/ScoreboardSaveData.java b/src/main/java/net/minecraft/world/scores/ScoreboardSaveData.java
|
||||
index b837b6616a2384b253cca8ed62c9488b639f6298..2be7a697f08045b974579e6942b38571e744efac 100644
|
||||
--- a/src/main/java/net/minecraft/world/scores/ScoreboardSaveData.java
|
||||
+++ b/src/main/java/net/minecraft/world/scores/ScoreboardSaveData.java
|
||||
@@ -136,6 +136,7 @@ public class ScoreboardSaveData extends SavedData {
|
||||
ListTag listTag = new ListTag();
|
||||
|
||||
for(PlayerTeam playerTeam : this.scoreboard.getPlayerTeams()) {
|
||||
+ if (!io.papermc.paper.configuration.GlobalConfiguration.get().scoreboards.saveEmptyScoreboardTeams && playerTeam.getPlayers().isEmpty()) continue; // Paper
|
||||
CompoundTag compoundTag = new CompoundTag();
|
||||
compoundTag.putString("Name", playerTeam.getName());
|
||||
compoundTag.putString("DisplayName", Component.Serializer.toJson(playerTeam.getDisplayName()));
|
|
@ -1,19 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach.brown@destroystokyo.com>
|
||||
Date: Thu, 12 May 2016 23:02:58 -0500
|
||||
Subject: [PATCH] System property for disabling watchdoge
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java
|
||||
index 3ad14bf0697e682a2e777baa8faeb323d127fb13..a9897c494b3dc56d900356d74030359832febbaa 100644
|
||||
--- a/src/main/java/org/spigotmc/WatchdogThread.java
|
||||
+++ b/src/main/java/org/spigotmc/WatchdogThread.java
|
||||
@@ -61,7 +61,7 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa
|
||||
while ( !this.stopping )
|
||||
{
|
||||
//
|
||||
- if ( this.lastTick != 0 && this.timeoutTime > 0 && WatchdogThread.monotonicMillis() > this.lastTick + this.timeoutTime )
|
||||
+ if ( this.lastTick != 0 && this.timeoutTime > 0 && WatchdogThread.monotonicMillis() > this.lastTick + this.timeoutTime && !Boolean.getBoolean("disable.watchdog")) // Paper - Add property to disable
|
||||
{
|
||||
Logger log = Bukkit.getServer().getLogger();
|
||||
log.log( Level.SEVERE, "------------------------------" );
|
|
@ -1,86 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 16 May 2016 20:47:41 -0400
|
||||
Subject: [PATCH] Async GameProfileCache saving
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index e24bd9c2be84dd11bf109e65ea4e1e577fe647ca..f438056c74dd24142bd94b505160711d0f94a5d5 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -926,7 +926,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
} catch (java.lang.InterruptedException ignored) {} // Paper
|
||||
if (org.spigotmc.SpigotConfig.saveUserCacheOnStopOnly) {
|
||||
MinecraftServer.LOGGER.info("Saving usercache.json");
|
||||
- this.getProfileCache().save();
|
||||
+ this.getProfileCache().save(false); // Paper
|
||||
}
|
||||
// Spigot end
|
||||
io.papermc.paper.chunk.system.io.RegionFileIOThread.close(true); // Paper // Paper - rewrite chunk system
|
||||
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
index 528bf80bdd786b13b3c46eaf922bf6870865f040..f3c65b5f4a0cc3bc0004cc6f8cc974a87a1123bb 100644
|
||||
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
@@ -247,7 +247,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||
}
|
||||
|
||||
if (this.convertOldUsers()) {
|
||||
- this.getProfileCache().save();
|
||||
+ this.getProfileCache().save(false); // Paper
|
||||
}
|
||||
|
||||
if (!OldUsersConverter.serverReadyAfterUserconversion(this)) {
|
||||
diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java
|
||||
index d246563021c32127e570809f4d849b6a156f4dc6..225e15d686675e21969c4210fa38fef58d920355 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/GameProfileCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java
|
||||
@@ -127,7 +127,7 @@ public class GameProfileCache {
|
||||
GameProfileCache.GameProfileInfo usercache_usercacheentry = new GameProfileCache.GameProfileInfo(profile, date);
|
||||
|
||||
this.safeAdd(usercache_usercacheentry);
|
||||
- if( !org.spigotmc.SpigotConfig.saveUserCacheOnStopOnly ) this.save(); // Spigot - skip saving if disabled
|
||||
+ if( !org.spigotmc.SpigotConfig.saveUserCacheOnStopOnly ) this.save(true); // Spigot - skip saving if disabled // Paper - async
|
||||
}
|
||||
|
||||
private long getNextOperation() {
|
||||
@@ -160,7 +160,7 @@ public class GameProfileCache {
|
||||
}
|
||||
|
||||
if (flag && !org.spigotmc.SpigotConfig.saveUserCacheOnStopOnly) { // Spigot - skip saving if disabled
|
||||
- this.save();
|
||||
+ this.save(true); // Paper
|
||||
}
|
||||
|
||||
return optional;
|
||||
@@ -274,7 +274,7 @@ public class GameProfileCache {
|
||||
return arraylist;
|
||||
}
|
||||
|
||||
- public void save() {
|
||||
+ public void save(boolean asyncSave) { // Paper
|
||||
JsonArray jsonarray = new JsonArray();
|
||||
DateFormat dateformat = GameProfileCache.createDateFormat();
|
||||
|
||||
@@ -282,6 +282,7 @@ public class GameProfileCache {
|
||||
jsonarray.add(GameProfileCache.writeGameProfile(usercache_usercacheentry, dateformat));
|
||||
});
|
||||
String s = this.gson.toJson(jsonarray);
|
||||
+ Runnable save = () -> { // Paper
|
||||
|
||||
try {
|
||||
BufferedWriter bufferedwriter = Files.newWriter(this.file, StandardCharsets.UTF_8);
|
||||
@@ -306,6 +307,14 @@ public class GameProfileCache {
|
||||
} catch (IOException ioexception) {
|
||||
;
|
||||
}
|
||||
+ // Paper start
|
||||
+ };
|
||||
+ if (asyncSave) {
|
||||
+ io.papermc.paper.util.MCUtil.scheduleAsyncTask(save);
|
||||
+ } else {
|
||||
+ save.run();
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
}
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach.brown@destroystokyo.com>
|
||||
Date: Sun, 22 May 2016 20:20:55 -0500
|
||||
Subject: [PATCH] Optional TNT doesn't move in water
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java
|
||||
index 8b3ca38f029b8918f02c51995e4359cbbf741c76..d6f34adbdf45bbef4a39e629dd7cb6d7fcb5db0f 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerEntity.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
|
||||
@@ -65,7 +65,7 @@ public class ServerEntity {
|
||||
private boolean wasRiding;
|
||||
private boolean wasOnGround;
|
||||
// CraftBukkit start
|
||||
- private final Set<ServerPlayerConnection> trackedPlayers;
|
||||
+ final Set<ServerPlayerConnection> trackedPlayers; // Paper - private -> package
|
||||
|
||||
public ServerEntity(ServerLevel worldserver, Entity entity, int i, boolean flag, Consumer<Packet<?>> consumer, Set<ServerPlayerConnection> trackedPlayers) {
|
||||
this.trackedPlayers = trackedPlayers;
|
||||
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 7a2ec239cd59b95dfd87ab1164d17bad23c4e558..65f0aa076dbfc4cd72d14ec485d1edf5533d825e 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java
|
||||
@@ -97,6 +97,27 @@ public class PrimedTnt extends Entity {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start - Optional prevent TNT from moving in water
|
||||
+ if (!this.isRemoved() && this.wasTouchingWater && this.level.paperConfig().fixes.preventTntFromMovingInWater) {
|
||||
+ /*
|
||||
+ * Author: Jedediah Smith <jedediah@silencegreys.com>
|
||||
+ */
|
||||
+ // Send position and velocity updates to nearby players on every tick while the TNT is in water.
|
||||
+ // This does pretty well at keeping their clients in sync with the server.
|
||||
+ net.minecraft.server.level.ChunkMap.TrackedEntity ete = ((net.minecraft.server.level.ServerLevel)this.level).getChunkSource().chunkMap.entityMap.get(this.getId());
|
||||
+ if (ete != null) {
|
||||
+ net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket velocityPacket = new net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket(this);
|
||||
+ net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket positionPacket = new net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket(this);
|
||||
+
|
||||
+ ete.seenBy.stream()
|
||||
+ .filter(viewer -> (viewer.getPlayer().getX() - this.getX()) * (viewer.getPlayer().getY() - this.getY()) * (viewer.getPlayer().getZ() - this.getZ()) < 16 * 16)
|
||||
+ .forEach(viewer -> {
|
||||
+ viewer.send(velocityPacket);
|
||||
+ viewer.send(positionPacket);
|
||||
+ });
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
private void explode() {
|
||||
@@ -152,4 +173,11 @@ public class PrimedTnt extends Entity {
|
||||
public Packet<?> getAddEntityPacket() {
|
||||
return new ClientboundAddEntityPacket(this);
|
||||
}
|
||||
+
|
||||
+ // Paper start - Optional prevent TNT from moving in water
|
||||
+ @Override
|
||||
+ public boolean isPushedByFluid() {
|
||||
+ return !level.paperConfig().fixes.preventTntFromMovingInWater && super.isPushedByFluid();
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Panzer <postremus1996@googlemail.com>
|
||||
Date: Mon, 23 May 2016 12:12:37 +0200
|
||||
Subject: [PATCH] Faster redstone torch rapid clock removal
|
||||
|
||||
Only resize the the redstone torch list once, since resizing arrays / lists is costly
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
||||
index 39b2071a6fc6510929416ccbdf2022cf471ab26c..807df663f710311276d69288875bb80e7fa37893 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/Level.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
||||
@@ -167,6 +167,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
private org.spigotmc.TickLimiter tileLimiter;
|
||||
private int tileTickPosition;
|
||||
public final Map<Explosion.CacheKey, Float> explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions
|
||||
+ public java.util.ArrayDeque<net.minecraft.world.level.block.RedstoneTorchBlock.Toggle> redstoneUpdateInfos; // Paper - Move from Map in BlockRedstoneTorch to here
|
||||
|
||||
public CraftWorld getWorld() {
|
||||
return this.world;
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java b/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java
|
||||
index 9b6f8508d16bcecd9dc148f75598655e3585f175..da07fce0cf7c9fbdb57d2c59e431b59bf583bf50 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java
|
||||
@@ -21,7 +21,7 @@ import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit
|
||||
public class RedstoneTorchBlock extends TorchBlock {
|
||||
|
||||
public static final BooleanProperty LIT = BlockStateProperties.LIT;
|
||||
- private static final Map<BlockGetter, List<RedstoneTorchBlock.Toggle>> RECENT_TOGGLES = new WeakHashMap();
|
||||
+ // Paper - Move the mapped list to World
|
||||
public static final int RECENT_TOGGLE_TIMER = 60;
|
||||
public static final int MAX_RECENT_TOGGLES = 8;
|
||||
public static final int RESTART_DELAY = 160;
|
||||
@@ -72,11 +72,15 @@ public class RedstoneTorchBlock extends TorchBlock {
|
||||
@Override
|
||||
public void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
|
||||
boolean flag = this.hasNeighborSignal(world, pos, state);
|
||||
- List list = (List) RedstoneTorchBlock.RECENT_TOGGLES.get(world);
|
||||
-
|
||||
- while (list != null && !list.isEmpty() && world.getGameTime() - ((RedstoneTorchBlock.Toggle) list.get(0)).when > 60L) {
|
||||
- list.remove(0);
|
||||
+ // Paper start
|
||||
+ java.util.ArrayDeque<RedstoneTorchBlock.Toggle> redstoneUpdateInfos = world.redstoneUpdateInfos;
|
||||
+ if (redstoneUpdateInfos != null) {
|
||||
+ RedstoneTorchBlock.Toggle curr;
|
||||
+ while ((curr = redstoneUpdateInfos.peek()) != null && world.getGameTime() - curr.when > 60L) {
|
||||
+ redstoneUpdateInfos.poll();
|
||||
+ }
|
||||
}
|
||||
+ // Paper end
|
||||
|
||||
// CraftBukkit start
|
||||
org.bukkit.plugin.PluginManager manager = world.getCraftServer().getPluginManager();
|
||||
@@ -152,9 +156,12 @@ public class RedstoneTorchBlock extends TorchBlock {
|
||||
}
|
||||
|
||||
private static boolean isToggledTooFrequently(Level world, BlockPos pos, boolean addNew) {
|
||||
- List<RedstoneTorchBlock.Toggle> list = (List) RedstoneTorchBlock.RECENT_TOGGLES.computeIfAbsent(world, (iblockaccess) -> {
|
||||
- return Lists.newArrayList();
|
||||
- });
|
||||
+ // Paper start
|
||||
+ java.util.ArrayDeque<RedstoneTorchBlock.Toggle> list = world.redstoneUpdateInfos;
|
||||
+ if (list == null) {
|
||||
+ list = world.redstoneUpdateInfos = new java.util.ArrayDeque<>();
|
||||
+ }
|
||||
+
|
||||
|
||||
if (addNew) {
|
||||
list.add(new RedstoneTorchBlock.Toggle(pos.immutable(), world.getGameTime()));
|
||||
@@ -162,9 +169,9 @@ public class RedstoneTorchBlock extends TorchBlock {
|
||||
|
||||
int i = 0;
|
||||
|
||||
- for (int j = 0; j < list.size(); ++j) {
|
||||
- RedstoneTorchBlock.Toggle blockredstonetorch_redstoneupdateinfo = (RedstoneTorchBlock.Toggle) list.get(j);
|
||||
-
|
||||
+ for (java.util.Iterator<RedstoneTorchBlock.Toggle> iterator = list.iterator(); iterator.hasNext();) {
|
||||
+ RedstoneTorchBlock.Toggle blockredstonetorch_redstoneupdateinfo = iterator.next();
|
||||
+ // Paper end
|
||||
if (blockredstonetorch_redstoneupdateinfo.pos.equals(pos)) {
|
||||
++i;
|
||||
if (i >= 8) {
|
|
@ -1,25 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Panzer <postremus1996@googlemail.com>
|
||||
Date: Sat, 28 May 2016 16:54:03 +0200
|
||||
Subject: [PATCH] Add server-name parameter
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
index dbdb2a30c5dbe4f02bc1d1a8ce7294d25e1749d4..e15375f6985f841ca42dd41eb0035aab0b64a9fb 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
@@ -156,6 +156,14 @@ public class Main {
|
||||
.defaultsTo(new File[] {})
|
||||
.describedAs("Jar file");
|
||||
// Paper end
|
||||
+
|
||||
+ // Paper start
|
||||
+ acceptsAll(asList("server-name"), "Name of the server")
|
||||
+ .withRequiredArg()
|
||||
+ .ofType(String.class)
|
||||
+ .defaultsTo("Unknown Server")
|
||||
+ .describedAs("Name");
|
||||
+ // Paper end
|
||||
}
|
||||
};
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 31 May 2016 22:53:50 -0400
|
||||
Subject: [PATCH] Only send global sounds to same world if limiting radius
|
||||
|
||||
Co-authored-by: Evan McCarthy <evanmccarthy@outlook.com>
|
||||
Co-authored-by: lexikiq <noellekiq@gmail.com>
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
||||
index dd1d606543da93e6068b8fa4239d369a4b648523..127aab56eef67d7f02f5c3de80d8f445ba70e7db 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
||||
@@ -654,7 +654,7 @@ public class EnderDragon extends Mob implements Enemy {
|
||||
// CraftBukkit start - Use relative location for far away sounds
|
||||
// this.world.b(1028, this.getChunkCoordinates(), 0);
|
||||
int viewDistance = ((ServerLevel) this.level).getCraftServer().getViewDistance() * 16;
|
||||
- for (net.minecraft.server.level.ServerPlayer player : this.level.getServer().getPlayerList().players) {
|
||||
+ for (net.minecraft.server.level.ServerPlayer player : level.spigotConfig.dragonDeathSoundRadius > 0 ? ((ServerLevel) level).players() : level.getServer().getPlayerList().players) { // Paper
|
||||
double deltaX = this.getX() - player.getX();
|
||||
double deltaZ = this.getZ() - player.getZ();
|
||||
double distanceSquared = deltaX * deltaX + deltaZ * deltaZ;
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java
|
||||
index 78bffaddbc9e478fb53639396e9c4970e9961b21..0d36a903b7aa8d26232e6edcb0fdbba1defde660 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java
|
||||
@@ -272,7 +272,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob
|
||||
// CraftBukkit start - Use relative location for far away sounds
|
||||
// this.world.globalLevelEvent(1023, new BlockPosition(this), 0);
|
||||
int viewDistance = ((ServerLevel) this.level).getCraftServer().getViewDistance() * 16;
|
||||
- for (ServerPlayer player : (List<ServerPlayer>) MinecraftServer.getServer().getPlayerList().players) {
|
||||
+ for (ServerPlayer player : level.spigotConfig.witherSpawnSoundRadius > 0 ? ((ServerLevel) level).players() : level.getServer().getPlayerList().players) { // Paper
|
||||
double deltaX = this.getX() - player.getX();
|
||||
double deltaZ = this.getZ() - player.getZ();
|
||||
double distanceSquared = deltaX * deltaX + deltaZ * deltaZ;
|
||||
diff --git a/src/main/java/net/minecraft/world/item/EnderEyeItem.java b/src/main/java/net/minecraft/world/item/EnderEyeItem.java
|
||||
index a88ffff41481d346a99762352094cdb4e8dd6cc2..e0c3aa1285709a40ff0ea8c1d74d43d2b341aecc 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/EnderEyeItem.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/EnderEyeItem.java
|
||||
@@ -64,7 +64,7 @@ public class EnderEyeItem extends Item {
|
||||
// world.b(1038, blockposition1.c(1, 0, 1), 0);
|
||||
int viewDistance = world.getCraftServer().getViewDistance() * 16;
|
||||
BlockPos soundPos = blockposition1.offset(1, 0, 1);
|
||||
- for (ServerPlayer player : world.getServer().getPlayerList().players) {
|
||||
+ for (ServerPlayer player : world.spigotConfig.endPortalSoundRadius > 0 ? ((ServerLevel) world).players() : world.getServer().getPlayerList().players) { // Paper
|
||||
double deltaX = soundPos.getX() - player.getX();
|
||||
double deltaZ = soundPos.getZ() - player.getZ();
|
||||
double distanceSquared = deltaX * deltaX + deltaZ * deltaZ;
|
|
@ -1,49 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Fri, 17 Jun 2016 20:50:11 -0400
|
||||
Subject: [PATCH] Fix Old Sign Conversion
|
||||
|
||||
1) Sign loading code was trying to parse the JSON before the check for oldSign.
|
||||
That code could then skip the old sign converting code if it triggers a JSON parse exception.
|
||||
2) New Mojang Schematic system has Tile Entities in the new converted format, but missing the Bukkit.isConverted flag
|
||||
This causes Igloos and such to render broken signs. We fix this by ignoring sign conversion for Defined Structures
|
||||
|
||||
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 c518704386f14cd033307dd976455c35760d7236..148e79ae4e24fe16dbbb17550c3f258d4362c266 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
|
||||
@@ -32,6 +32,7 @@ public abstract class BlockEntity {
|
||||
private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry();
|
||||
public CraftPersistentDataContainer persistentDataContainer;
|
||||
// CraftBukkit end
|
||||
+ public boolean isLoadingStructure = false; // Paper
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private final BlockEntityType<?> type;
|
||||
@Nullable
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java
|
||||
index 715873e52708762b25c29caf6d41d7cb8f79ce57..39bd98b9496e4a27fd69a2de7c83c40689017ebc 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java
|
||||
@@ -93,7 +93,7 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C
|
||||
s = "\"\"";
|
||||
}
|
||||
|
||||
- if (oldSign) {
|
||||
+ if (oldSign && !this.isLoadingStructure) { // Paper - saved structures will be in the new format, but will not have isConverted
|
||||
this.messages[i] = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(s)[0];
|
||||
continue;
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java
|
||||
index 3112173b3449f2c4c9b0851ceaf02abb01853362..9c45e49f480ccd72f6d6c94e5dec41c4becc76cf 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java
|
||||
@@ -285,7 +285,9 @@ public class StructureTemplate {
|
||||
definedstructure_blockinfo.nbt.putLong("LootTableSeed", random.nextLong());
|
||||
}
|
||||
|
||||
+ tileentity.isLoadingStructure = true; // Paper
|
||||
tileentity.load(definedstructure_blockinfo.nbt);
|
||||
+ tileentity.isLoadingStructure = false; // Paper
|
||||
}
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 16 May 2016 23:19:16 -0400
|
||||
Subject: [PATCH] Avoid blocking on Network Manager creation
|
||||
|
||||
Per Paper issue 294
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
|
||||
index a44520e8fb35d349d6481f369e39db1fdb475749..0e04532b8f1d48116eb46dcef7952bfcc0d11394 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
|
||||
@@ -63,6 +63,15 @@ public class ServerConnectionListener {
|
||||
public volatile boolean running;
|
||||
private final List<ChannelFuture> channels = Collections.synchronizedList(Lists.newArrayList());
|
||||
final List<Connection> connections = Collections.synchronizedList(Lists.newArrayList());
|
||||
+ // Paper start - prevent blocking on adding a new network manager while the server is ticking
|
||||
+ private final java.util.Queue<Connection> pending = new java.util.concurrent.ConcurrentLinkedQueue<>();
|
||||
+ private final void addPending() {
|
||||
+ Connection manager = null;
|
||||
+ while ((manager = pending.poll()) != null) {
|
||||
+ connections.add(manager);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
public ServerConnectionListener(MinecraftServer server) {
|
||||
this.server = server;
|
||||
@@ -98,7 +107,8 @@ public class ServerConnectionListener {
|
||||
int j = ServerConnectionListener.this.server.getRateLimitPacketsPerSecond();
|
||||
Object object = j > 0 ? new RateKickingConnection(j) : new Connection(PacketFlow.SERVERBOUND);
|
||||
|
||||
- ServerConnectionListener.this.connections.add((Connection) object); // CraftBukkit - decompile error
|
||||
+ // ServerConnectionListener.this.connections.add((Connection) object); // CraftBukkit - decompile error
|
||||
+ pending.add((Connection) object); // Paper
|
||||
channel.pipeline().addLast("packet_handler", (ChannelHandler) object);
|
||||
((Connection) object).setListener(new ServerHandshakePacketListenerImpl(ServerConnectionListener.this.server, (Connection) object));
|
||||
}
|
||||
@@ -157,6 +167,7 @@ public class ServerConnectionListener {
|
||||
|
||||
synchronized (this.connections) {
|
||||
// Spigot Start
|
||||
+ this.addPending(); // Paper
|
||||
// This prevents players from 'gaming' the server, and strategically relogging to increase their position in the tick order
|
||||
if ( org.spigotmc.SpigotConfig.playerShuffle > 0 && MinecraftServer.currentTick % org.spigotmc.SpigotConfig.playerShuffle == 0 )
|
||||
{
|
|
@ -1,18 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach.brown@destroystokyo.com>
|
||||
Date: Sat, 16 Jul 2016 19:11:17 -0500
|
||||
Subject: [PATCH] Don't lookup game profiles that have no UUID and no name
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java
|
||||
index 225e15d686675e21969c4210fa38fef58d920355..5288aec173549a982e42aeeccf7f5f394080955d 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/GameProfileCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java
|
||||
@@ -98,6 +98,7 @@ public class GameProfileCache {
|
||||
}
|
||||
};
|
||||
|
||||
+ if (!org.apache.commons.lang3.StringUtils.isBlank(name)) // Paper - Don't lookup a profile with a blank name)
|
||||
repository.findProfilesByNames(new String[]{name}, Agent.MINECRAFT, profilelookupcallback);
|
||||
GameProfile gameprofile = (GameProfile) atomicreference.get();
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Gabriele C <sgdc3.mail@gmail.com>
|
||||
Date: Fri, 5 Aug 2016 01:03:08 +0200
|
||||
Subject: [PATCH] Add setting for proxy online mode status
|
||||
|
||||
TODO: Add isProxyOnlineMode check to Metrics
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java
|
||||
index 5288aec173549a982e42aeeccf7f5f394080955d..58e923f4ef1980bc7fff1e3b3fcdaad8c4eded53 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/GameProfileCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java
|
||||
@@ -98,7 +98,8 @@ public class GameProfileCache {
|
||||
}
|
||||
};
|
||||
|
||||
- if (!org.apache.commons.lang3.StringUtils.isBlank(name)) // Paper - Don't lookup a profile with a blank name)
|
||||
+ if (!org.apache.commons.lang3.StringUtils.isBlank(name) // Paper - Don't lookup a profile with a blank name
|
||||
+ && io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode()) // Paper - only run in online mode - 100 COL
|
||||
repository.findProfilesByNames(new String[]{name}, Agent.MINECRAFT, profilelookupcallback);
|
||||
GameProfile gameprofile = (GameProfile) atomicreference.get();
|
||||
|
||||
@@ -116,7 +117,7 @@ public class GameProfileCache {
|
||||
}
|
||||
|
||||
private static boolean usesAuthentication() {
|
||||
- return GameProfileCache.usesAuthentication;
|
||||
+ return io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode(); // Paper
|
||||
}
|
||||
|
||||
public void add(GameProfile profile) {
|
||||
diff --git a/src/main/java/net/minecraft/server/players/OldUsersConverter.java b/src/main/java/net/minecraft/server/players/OldUsersConverter.java
|
||||
index da98f074ccd5a40c635824112c97fd174c393cb1..6599f874d9f97e9ef4862039ecad7277bbc5fd91 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/OldUsersConverter.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/OldUsersConverter.java
|
||||
@@ -66,7 +66,8 @@ public class OldUsersConverter {
|
||||
return new String[i];
|
||||
});
|
||||
|
||||
- if (server.usesAuthentication() || org.spigotmc.SpigotConfig.bungee) { // Spigot: bungee = online mode, for now.
|
||||
+ if (server.usesAuthentication()
|
||||
+ || (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode())) { // Spigot: bungee = online mode, for now. // Paper - Handle via setting
|
||||
server.getProfileRepository().findProfilesByNames(astring, Agent.MINECRAFT, callback);
|
||||
} else {
|
||||
String[] astring1 = astring;
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index 943971ce16c0c39085f029ab5b57685dda1c6b0f..0d6dcb670c583f47a299cd96574426932d3b98c8 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -1706,7 +1706,7 @@ public final class CraftServer implements Server {
|
||||
// Spigot Start
|
||||
GameProfile profile = null;
|
||||
// Only fetch an online UUID in online mode
|
||||
- if ( this.getOnlineMode() || org.spigotmc.SpigotConfig.bungee )
|
||||
+ if ( this.getOnlineMode() || io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode() ) // Paper - Handle via setting
|
||||
{
|
||||
profile = this.console.getProfileCache().get(name).orElse(null);
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alfie Cleveland <alfeh@me.com>
|
||||
Date: Fri, 19 Aug 2016 01:52:56 +0100
|
||||
Subject: [PATCH] Optimise BlockState's hashCode/equals
|
||||
|
||||
These are singleton "single instance" objects. We can rely on
|
||||
object identity checks safely.
|
||||
|
||||
Use a simpler optimized hashcode
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java b/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java
|
||||
index 6cdb0716f2a4b29f7a5ecd109bf3c4700ebd22ad..ff1a0d125edd2ea10c870cbb62ae9aa23644b6dc 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java
|
||||
@@ -30,8 +30,7 @@ public class BooleanProperty extends Property<Boolean> {
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
- @Override
|
||||
- public boolean equals(Object object) {
|
||||
+ public boolean equals_unused(Object object) { // Paper
|
||||
if (this == object) {
|
||||
return true;
|
||||
} else if (object instanceof BooleanProperty && super.equals(object)) {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java b/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java
|
||||
index 4d6e7b5889ecb81195c7152225ae8e3343d3408c..0bca0f971dac994bd8b6ecd87e8b33e26c0f18f9 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java
|
||||
@@ -45,8 +45,7 @@ public class EnumProperty<T extends Enum<T> & StringRepresentable> extends Prope
|
||||
return value.getSerializedName();
|
||||
}
|
||||
|
||||
- @Override
|
||||
- public boolean equals(Object object) {
|
||||
+ public boolean equals_unused(Object object) { // Paper
|
||||
if (this == object) {
|
||||
return true;
|
||||
} else if (object instanceof EnumProperty && super.equals(object)) {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/IntegerProperty.java b/src/main/java/net/minecraft/world/level/block/state/properties/IntegerProperty.java
|
||||
index 59b5b22a567e4e2be499a2a35aedb10218a7432a..bdbe0362e49e73c05237f9f3143230e0b03e494e 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/state/properties/IntegerProperty.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/state/properties/IntegerProperty.java
|
||||
@@ -35,8 +35,7 @@ public class IntegerProperty extends Property<Integer> {
|
||||
return this.values;
|
||||
}
|
||||
|
||||
- @Override
|
||||
- public boolean equals(Object object) {
|
||||
+ public boolean equals_unused(Object object) { // Paper
|
||||
if (this == object) {
|
||||
return true;
|
||||
} else if (object instanceof IntegerProperty && super.equals(object)) {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/Property.java b/src/main/java/net/minecraft/world/level/block/state/properties/Property.java
|
||||
index 5a973c1536291e79aa8377ca5bda8ef84127e20a..a37424bbc6bee02354abaa793aa0865c556c6bbe 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/state/properties/Property.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/state/properties/Property.java
|
||||
@@ -68,14 +68,7 @@ public abstract class Property<T extends Comparable<T>> {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
- if (this == object) {
|
||||
- return true;
|
||||
- } else if (!(object instanceof Property)) {
|
||||
- return false;
|
||||
- } else {
|
||||
- Property<?> property = (Property)object;
|
||||
- return this.clazz.equals(property.clazz) && this.name.equals(property.name);
|
||||
- }
|
||||
+ return this == object; // Paper
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,27 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach.brown@destroystokyo.com>
|
||||
Date: Sun, 11 Sep 2016 14:30:57 -0500
|
||||
Subject: [PATCH] Configurable packet in spam threshold
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 65bd9005b722db154842978d359e0a2277bbb8b2..3978ba09a5e29aaf9e48d5e4f800b1027181a4ad 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -1611,13 +1611,14 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
||||
// Spigot start - limit place/interactions
|
||||
private int limitedPackets;
|
||||
private long lastLimitedPacket = -1;
|
||||
+ private static final int THRESHOLD = io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.incomingPacketThreshold; // Paper - Configurable threshold
|
||||
|
||||
private boolean checkLimit(long timestamp) {
|
||||
- if (this.lastLimitedPacket != -1 && timestamp - this.lastLimitedPacket < 30 && this.limitedPackets++ >= 4) {
|
||||
+ if (this.lastLimitedPacket != -1 && timestamp - this.lastLimitedPacket < THRESHOLD && this.limitedPackets++ >= 8) { // Paper - Use threshold, raise packet limit to 8
|
||||
return false;
|
||||
}
|
||||
|
||||
- if (this.lastLimitedPacket == -1 || timestamp - this.lastLimitedPacket >= 30) {
|
||||
+ if (this.lastLimitedPacket == -1 || timestamp - this.lastLimitedPacket >= THRESHOLD) { // Paper
|
||||
this.lastLimitedPacket = timestamp;
|
||||
this.limitedPackets = 0;
|
||||
return true;
|
|
@ -1,28 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: kashike <kashike@vq.lc>
|
||||
Date: Tue, 20 Sep 2016 00:58:01 +0000
|
||||
Subject: [PATCH] Configurable flying kick messages
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 3978ba09a5e29aaf9e48d5e4f800b1027181a4ad..e032a9f72aa5d55daa9c680734e45e3dda13ca9b 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -358,7 +358,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
||||
if (this.clientIsFloating && !this.player.isSleeping() && !this.player.isPassenger()) {
|
||||
if (++this.aboveGroundTickCount > 80) {
|
||||
ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked for floating too long!", this.player.getName().getString());
|
||||
- this.disconnect(Component.translatable("multiplayer.disconnect.flying"));
|
||||
+ this.disconnect(io.papermc.paper.configuration.GlobalConfiguration.get().messages.kick.flyingPlayer); // Paper - use configurable kick message
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@@ -377,7 +377,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
||||
if (this.clientVehicleIsFloating && this.player.getRootVehicle().getControllingPassenger() == this.player) {
|
||||
if (++this.aboveGroundVehicleTickCount > 80) {
|
||||
ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked for floating a vehicle too long!", this.player.getName().getString());
|
||||
- this.disconnect(Component.translatable("multiplayer.disconnect.flying"));
|
||||
+ this.disconnect(io.papermc.paper.configuration.GlobalConfiguration.get().messages.kick.flyingVehicle); // Paper - use configurable kick message
|
||||
return;
|
||||
}
|
||||
} else {
|
|
@ -1,48 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: AlphaBlend <whizkid3000@hotmail.com>
|
||||
Date: Sun, 16 Oct 2016 23:19:30 -0700
|
||||
Subject: [PATCH] Add EntityZapEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java
|
||||
index 2a7c82be934a965ba26dc7bf1f60689360bda487..33d1a6b31afec4dbeb00dcabf50c5840852102d6 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java
|
||||
@@ -836,9 +836,17 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
|
||||
@Override
|
||||
public void thunderHit(ServerLevel world, LightningBolt lightning) {
|
||||
if (world.getDifficulty() != Difficulty.PEACEFUL) {
|
||||
- Villager.LOGGER.info("Villager {} was struck by lightning {}.", this, lightning);
|
||||
+ // Paper - move log down, event can cancel
|
||||
Witch entitywitch = (Witch) EntityType.WITCH.create(world);
|
||||
|
||||
+ // Paper start
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityZapEvent(this, lightning, entitywitch).isCancelled()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
+ if (org.spigotmc.SpigotConfig.logVillagerDeaths) Villager.LOGGER.info("Villager {} was struck by lightning {}.", this, lightning); // Paper - move log down, event can cancel
|
||||
+
|
||||
entitywitch.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot());
|
||||
entitywitch.finalizeSpawn(world, world.getCurrentDifficultyAt(entitywitch.blockPosition()), MobSpawnType.CONVERSION, (SpawnGroupData) null, (CompoundTag) null);
|
||||
entitywitch.setNoAi(this.isNoAi());
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
index 2766f670f7bbe03c23552eb2ccf71d6397cfb150..5ccaa797f0f794c71c9402c3b440c681defd0952 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
@@ -1157,6 +1157,14 @@ public class CraftEventFactory {
|
||||
return event;
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ public static com.destroystokyo.paper.event.entity.EntityZapEvent callEntityZapEvent (Entity entity, Entity lightning, Entity changedEntity) {
|
||||
+ com.destroystokyo.paper.event.entity.EntityZapEvent event = new com.destroystokyo.paper.event.entity.EntityZapEvent(entity.getBukkitEntity(), (LightningStrike) lightning.getBukkitEntity(), changedEntity.getBukkitEntity());
|
||||
+ entity.getBukkitEntity().getServer().getPluginManager().callEvent(event);
|
||||
+ return event;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
public static HorseJumpEvent callHorseJumpEvent(Entity horse, float power) {
|
||||
HorseJumpEvent event = new HorseJumpEvent((AbstractHorse) horse.getBukkitEntity(), power);
|
||||
horse.getBukkitEntity().getServer().getPluginManager().callEvent(event);
|
|
@ -1,29 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach.brown@destroystokyo.com>
|
||||
Date: Sat, 12 Nov 2016 23:25:22 -0600
|
||||
Subject: [PATCH] Filter bad data from ArmorStand and SpawnEgg items
|
||||
|
||||
|
||||
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 9ef526b3da1185f32257b8fb2fa79ff281855713..108c9ea0eb4a7f381042bfe0203ac40a9c4f27a7 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
|
||||
@@ -316,6 +316,18 @@ public class FallingBlockEntity extends Entity {
|
||||
@Override
|
||||
protected void readAdditionalSaveData(CompoundTag nbt) {
|
||||
this.blockState = NbtUtils.readBlockState(nbt.getCompound("BlockState"));
|
||||
+ // Paper start - Block FallingBlocks with Command Blocks
|
||||
+ final Block b = this.blockState.getBlock();
|
||||
+ if (this.level.paperConfig().entities.spawning.filterNbtDataFromSpawnEggsAndRelated
|
||||
+ && (b == Blocks.COMMAND_BLOCK
|
||||
+ || b == Blocks.REPEATING_COMMAND_BLOCK
|
||||
+ || b == Blocks.CHAIN_COMMAND_BLOCK
|
||||
+ || b == Blocks.JIGSAW
|
||||
+ || b == Blocks.STRUCTURE_BLOCK
|
||||
+ || b instanceof net.minecraft.world.level.block.GameMasterBlock)) {
|
||||
+ this.blockState = Blocks.STONE.defaultBlockState();
|
||||
+ }
|
||||
+ // Paper end
|
||||
this.time = nbt.getInt("Time");
|
||||
if (nbt.contains("HurtEntities", 99)) {
|
||||
this.hurtEntities = nbt.getBoolean("HurtEntities");
|
|
@ -1,63 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alfie Cleveland <alfeh@me.com>
|
||||
Date: Fri, 25 Nov 2016 13:22:40 +0000
|
||||
Subject: [PATCH] Cache user authenticator threads
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
index 5d2687d3f73529fd45011c011710e2386ff17c82..9011b43dbf28f1f19809c1b45898b727d679c12f 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
@@ -117,6 +117,8 @@ public class ServerLoginPacketListenerImpl implements TickablePacketListener, Se
|
||||
|
||||
}
|
||||
|
||||
+ private static final java.util.concurrent.ExecutorService authenticatorPool = new java.util.concurrent.ThreadPoolExecutor(0, 16, 60L, java.util.concurrent.TimeUnit.SECONDS, new java.util.concurrent.LinkedBlockingQueue<>(), new com.google.common.util.concurrent.ThreadFactoryBuilder().setNameFormat("User Authenticator #%d").setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LOGGER)).build()); // Paper - Cache authenticator threads
|
||||
+
|
||||
// Spigot start
|
||||
public void initUUID()
|
||||
{
|
||||
@@ -241,8 +243,8 @@ public class ServerLoginPacketListenerImpl implements TickablePacketListener, Se
|
||||
this.connection.send(new ClientboundHelloPacket("", this.server.getKeyPair().getPublic().getEncoded(), this.nonce));
|
||||
} else {
|
||||
// Spigot start
|
||||
- new Thread("User Authenticator #" + ServerLoginPacketListenerImpl.UNIQUE_THREAD_ID.incrementAndGet()) {
|
||||
-
|
||||
+ // Paper start - Cache authenticator threads
|
||||
+ authenticatorPool.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
@@ -253,7 +255,8 @@ public class ServerLoginPacketListenerImpl implements TickablePacketListener, Se
|
||||
server.server.getLogger().log(java.util.logging.Level.WARNING, "Exception verifying " + ServerLoginPacketListenerImpl.this.gameProfile.getName(), ex);
|
||||
}
|
||||
}
|
||||
- }.start();
|
||||
+ });
|
||||
+ // Paper end
|
||||
// Spigot end
|
||||
}
|
||||
|
||||
@@ -296,7 +299,8 @@ public class ServerLoginPacketListenerImpl implements TickablePacketListener, Se
|
||||
throw new IllegalStateException("Protocol error", cryptographyexception);
|
||||
}
|
||||
|
||||
- Thread thread = new Thread("User Authenticator #" + ServerLoginPacketListenerImpl.UNIQUE_THREAD_ID.incrementAndGet()) {
|
||||
+ // Paper start - Cache authenticator threads
|
||||
+ authenticatorPool.execute(new Runnable() {
|
||||
public void run() {
|
||||
GameProfile gameprofile = ServerLoginPacketListenerImpl.this.gameProfile;
|
||||
|
||||
@@ -341,10 +345,8 @@ public class ServerLoginPacketListenerImpl implements TickablePacketListener, Se
|
||||
|
||||
return ServerLoginPacketListenerImpl.this.server.getPreventProxyConnections() && socketaddress instanceof InetSocketAddress ? ((InetSocketAddress) socketaddress).getAddress() : null;
|
||||
}
|
||||
- };
|
||||
-
|
||||
- thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(ServerLoginPacketListenerImpl.LOGGER));
|
||||
- thread.start();
|
||||
+ });
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
// Spigot start
|
|
@ -1,36 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: willies952002 <admin@domnian.com>
|
||||
Date: Mon, 28 Nov 2016 10:21:52 -0500
|
||||
Subject: [PATCH] Allow Reloading of Command Aliases
|
||||
|
||||
Reload the aliases stored in commands.yml
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index 0d6dcb670c583f47a299cd96574426932d3b98c8..8072e45c656e8de0f9061360d353675554ae0182 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -2563,5 +2563,24 @@ public final class CraftServer implements Server {
|
||||
DefaultPermissions.registerCorePermissions();
|
||||
CraftDefaultPermissions.registerCorePermissions();
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean reloadCommandAliases() {
|
||||
+ Set<String> removals = getCommandAliases().keySet().stream()
|
||||
+ .map(key -> key.toLowerCase(java.util.Locale.ENGLISH))
|
||||
+ .collect(java.util.stream.Collectors.toSet());
|
||||
+ getCommandMap().getKnownCommands().keySet().removeIf(removals::contains);
|
||||
+ File file = getCommandsConfigFile();
|
||||
+ try {
|
||||
+ commandsConfiguration.load(file);
|
||||
+ } catch (FileNotFoundException ex) {
|
||||
+ return false;
|
||||
+ } catch (IOException | org.bukkit.configuration.InvalidConfigurationException ex) {
|
||||
+ Bukkit.getLogger().log(Level.SEVERE, "Cannot load " + file, ex);
|
||||
+ return false;
|
||||
+ }
|
||||
+ commandMap.registerServerAliases();
|
||||
+ return true;
|
||||
+ }
|
||||
// Paper end
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: AlphaBlend <whizkid3000@hotmail.com>
|
||||
Date: Thu, 8 Sep 2016 08:48:33 -0700
|
||||
Subject: [PATCH] Add source to PlayerExpChangeEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java
|
||||
index 7942338e300cf5c70cb52e6ddce32f8cf9163c27..63b57d47d7dbb7a8a655b1447241e20c67a3f9c2 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java
|
||||
@@ -247,7 +247,7 @@ public class ExperienceOrb extends Entity {
|
||||
int i = this.repairPlayerItems(player, this.value);
|
||||
|
||||
if (i > 0) {
|
||||
- player.giveExperiencePoints(CraftEventFactory.callPlayerExpChangeEvent(player, i).getAmount()); // CraftBukkit - this.value -> event.getAmount()
|
||||
+ player.giveExperiencePoints(CraftEventFactory.callPlayerExpChangeEvent(player, this).getAmount()); // CraftBukkit - this.value -> event.getAmount() // Paper - supply experience orb object
|
||||
}
|
||||
|
||||
--this.count;
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
index 5ccaa797f0f794c71c9402c3b440c681defd0952..e74335de3685e90abc97fbefe91a0c5837ed0551 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
@@ -1116,6 +1116,17 @@ public class CraftEventFactory {
|
||||
return event;
|
||||
}
|
||||
|
||||
+ // Paper start - Add orb
|
||||
+ public static PlayerExpChangeEvent callPlayerExpChangeEvent(net.minecraft.world.entity.player.Player entity, net.minecraft.world.entity.ExperienceOrb entityOrb) {
|
||||
+ Player player = (Player) entity.getBukkitEntity();
|
||||
+ ExperienceOrb source = (ExperienceOrb) entityOrb.getBukkitEntity();
|
||||
+ int expAmount = source.getExperience();
|
||||
+ PlayerExpChangeEvent event = new PlayerExpChangeEvent(player, source, expAmount);
|
||||
+ Bukkit.getPluginManager().callEvent(event);
|
||||
+ return event;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
public static boolean handleBlockGrowEvent(Level world, BlockPos pos, net.minecraft.world.level.block.state.BlockState block) {
|
||||
return CraftEventFactory.handleBlockGrowEvent(world, pos, block, 3);
|
||||
}
|
|
@ -1,109 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Techcable <Techcable@outlook.com>
|
||||
Date: Fri, 16 Dec 2016 21:25:39 -0600
|
||||
Subject: [PATCH] Add ProjectileCollideEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
|
||||
index 62cb9dff53d980399913c913893fca2c1110d184..da92f324322f4fb18f9aa72c4298ffc8ab040953 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
|
||||
@@ -226,6 +226,17 @@ public abstract class AbstractArrow extends Projectile {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start - Call ProjectileCollideEvent
|
||||
+ // TODO: flag - noclip - call cancelled?
|
||||
+ if (object instanceof EntityHitResult) {
|
||||
+ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileCollideEvent(this, (EntityHitResult)object);
|
||||
+ if (event.isCancelled()) {
|
||||
+ object = null;
|
||||
+ movingobjectpositionentity = null;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
if (object != null && !flag) {
|
||||
this.preOnHit((HitResult) object); // CraftBukkit - projectile hit event
|
||||
this.hasImpulse = true;
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java
|
||||
index 867e50769af3c5bdbed15cfd637e429dcfcb6920..d71dc286673fa7ed708be5bec4c5a6868874c090 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java
|
||||
@@ -11,6 +11,7 @@ import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.level.Level;
|
||||
+import net.minecraft.world.phys.EntityHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit
|
||||
@@ -82,7 +83,16 @@ public abstract class AbstractHurtingProjectile extends Projectile {
|
||||
|
||||
HitResult movingobjectposition = ProjectileUtil.getHitResult(this, this::canHitEntity);
|
||||
|
||||
- if (movingobjectposition.getType() != HitResult.Type.MISS) {
|
||||
+ // Paper start - Call ProjectileCollideEvent
|
||||
+ if (movingobjectposition instanceof EntityHitResult) {
|
||||
+ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = CraftEventFactory.callProjectileCollideEvent(this, (EntityHitResult)movingobjectposition);
|
||||
+ if (event.isCancelled()) {
|
||||
+ movingobjectposition = null;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
+ if (movingobjectposition != null && movingobjectposition.getType() != HitResult.Type.MISS) { // Paper - add null check in case cancelled
|
||||
this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event
|
||||
|
||||
// CraftBukkit start - Fire ProjectileHitEvent
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrowableProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/ThrowableProjectile.java
|
||||
index 88181c59e604ba3b132b9e695cef5eaf5b836029..94d09b05737679b133ec462815b010b19c01b4fa 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/projectile/ThrowableProjectile.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/projectile/ThrowableProjectile.java
|
||||
@@ -10,6 +10,7 @@ import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.TheEndGatewayBlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
+import net.minecraft.world.phys.EntityHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
@@ -66,7 +67,17 @@ public abstract class ThrowableProjectile extends Projectile {
|
||||
}
|
||||
|
||||
if (movingobjectposition.getType() != HitResult.Type.MISS && !flag) {
|
||||
+ // Paper start - Call ProjectileCollideEvent
|
||||
+ if (movingobjectposition instanceof EntityHitResult) {
|
||||
+ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileCollideEvent(this, (EntityHitResult)movingobjectposition);
|
||||
+ if (event.isCancelled()) {
|
||||
+ movingobjectposition = null;
|
||||
+ }
|
||||
+ }
|
||||
+ if (movingobjectposition != null) {
|
||||
+ // Paper end
|
||||
this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event
|
||||
+ } // Paper
|
||||
}
|
||||
|
||||
this.checkInsideBlocks();
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
index e74335de3685e90abc97fbefe91a0c5837ed0551..b267e220e0b8fcd69f1b672db27273e76a46731a 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
@@ -1260,6 +1260,16 @@ public class CraftEventFactory {
|
||||
return CraftItemStack.asNMSCopy(bitem);
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ public static com.destroystokyo.paper.event.entity.ProjectileCollideEvent callProjectileCollideEvent(Entity entity, EntityHitResult position) {
|
||||
+ Projectile projectile = (Projectile) entity.getBukkitEntity();
|
||||
+ org.bukkit.entity.Entity collided = position.getEntity().getBukkitEntity();
|
||||
+ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = new com.destroystokyo.paper.event.entity.ProjectileCollideEvent(projectile, collided);
|
||||
+ Bukkit.getPluginManager().callEvent(event);
|
||||
+ return event;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
public static ProjectileLaunchEvent callProjectileLaunchEvent(Entity entity) {
|
||||
Projectile bukkitEntity = (Projectile) entity.getBukkitEntity();
|
||||
ProjectileLaunchEvent event = new ProjectileLaunchEvent(bukkitEntity);
|
|
@ -1,27 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 19 Dec 2016 23:07:42 -0500
|
||||
Subject: [PATCH] Prevent Pathfinding out of World Border
|
||||
|
||||
This prevents Entities from trying to run outside of the World Border
|
||||
|
||||
TODO: This doesn't prevent the pathfinder from using blocks outside the world border as nodes. We can fix this
|
||||
by adding code to all overrides in:
|
||||
NodeEvaluator:
|
||||
public abstract BlockPathTypes getBlockPathType(BlockGetter world, int x, int y, int z);
|
||||
|
||||
to return BLOCKED if it is outside the world border.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java
|
||||
index b6b6106ad2105c19273dc9f983fabd6573d35e5a..185f0bce91f03dfe9a37412710aa7319a15f57ff 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java
|
||||
@@ -156,7 +156,7 @@ public abstract class PathNavigation {
|
||||
// Paper start - Pathfind event
|
||||
boolean copiedSet = false;
|
||||
for (BlockPos possibleTarget : positions) {
|
||||
- if (!new com.destroystokyo.paper.event.entity.EntityPathfindEvent(this.mob.getBukkitEntity(),
|
||||
+ if (!this.mob.getCommandSenderWorld().getWorldBorder().isWithinBounds(possibleTarget) || !new com.destroystokyo.paper.event.entity.EntityPathfindEvent(this.mob.getBukkitEntity(), // Paper - don't path out of world border
|
||||
io.papermc.paper.util.MCUtil.toLocation(this.mob.level, possibleTarget), target == null ? null : target.getBukkitEntity()).callEvent()) {
|
||||
if (!copiedSet) {
|
||||
copiedSet = true;
|
|
@ -1,23 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Fri, 2 Dec 2016 00:11:43 -0500
|
||||
Subject: [PATCH] Optimize World.isLoaded(BlockPosition)Z
|
||||
|
||||
Reduce method invocations for World.isLoaded(BlockPosition)Z
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
||||
index 807df663f710311276d69288875bb80e7fa37893..64b763d6dc695e9cb9dd381deb5609e4902713dd 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/Level.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
||||
@@ -334,6 +334,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
return chunk == null ? null : chunk.getFluidState(blockposition);
|
||||
}
|
||||
|
||||
+ @Override
|
||||
+ public final boolean hasChunkAt(BlockPos pos) {
|
||||
+ return getChunkIfLoaded(pos.getX() >> 4, pos.getZ() >> 4) != null; // Paper
|
||||
+ }
|
||||
+
|
||||
public final boolean isLoadedAndInBounds(BlockPos blockposition) { // Paper - final for inline
|
||||
return getWorldBorder().isWithinBounds(blockposition) && getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) != null;
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 20 Dec 2016 15:15:11 -0500
|
||||
Subject: [PATCH] Bound Treasure Maps to World Border
|
||||
|
||||
Make it so a Treasure Map does not target a structure outside of the
|
||||
World Border, where players are not even able to reach.
|
||||
|
||||
This also would help the case where a players close to the border, and one
|
||||
that is outside happens to be closer, but unreachable, yet another reachable
|
||||
one is in border that would of been missed.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java
|
||||
index 6ec5a1525d0b8ced8fe78d3eab29c5eb82996844..2442c287a7f26cfee10a19e9015558cdebdcf3ac 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java
|
||||
@@ -37,6 +37,18 @@ public class WorldBorder {
|
||||
return (double) (pos.getX() + 1) > this.getMinX() && (double) pos.getX() < this.getMaxX() && (double) (pos.getZ() + 1) > this.getMinZ() && (double) pos.getZ() < this.getMaxZ();
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ private final BlockPos.MutableBlockPos mutPos = new BlockPos.MutableBlockPos();
|
||||
+ public boolean isBlockInBounds(int chunkX, int chunkZ) {
|
||||
+ this.mutPos.set(chunkX, 64, chunkZ);
|
||||
+ return this.isWithinBounds(this.mutPos);
|
||||
+ }
|
||||
+ public boolean isChunkInBounds(int chunkX, int chunkZ) {
|
||||
+ this.mutPos.set(((chunkX << 4) + 15), 64, (chunkZ << 4) + 15);
|
||||
+ return this.isWithinBounds(this.mutPos);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
public boolean isWithinBounds(ChunkPos pos) {
|
||||
return (double) pos.getMaxBlockX() > this.getMinX() && (double) pos.getMinBlockX() < this.getMaxX() && (double) pos.getMaxBlockZ() > this.getMinZ() && (double) pos.getMinBlockZ() < this.getMaxZ();
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
|
||||
index f284eefe5de6ad8b42f7d4185fc4c3b8b2cd5895..6e2185bbaac889d51a54ec97907da3b1faa465c4 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
|
||||
@@ -390,6 +390,7 @@ public abstract class ChunkGenerator {
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
ChunkPos chunkcoordintpair = (ChunkPos) iterator.next();
|
||||
+ if (!world.getWorldBorder().isChunkInBounds(chunkcoordintpair.x, chunkcoordintpair.z)) { continue; } // Paper
|
||||
|
||||
blockposition_mutableblockposition.set(SectionPos.sectionToBlockCoord(chunkcoordintpair.x, 8), 32, SectionPos.sectionToBlockCoord(chunkcoordintpair.z, 8));
|
||||
double d1 = blockposition_mutableblockposition.distSqr(center);
|
|
@ -1,46 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 20 Dec 2016 15:26:27 -0500
|
||||
Subject: [PATCH] Configurable Cartographer Treasure Maps
|
||||
|
||||
Allow configuring for cartographers to return the same map location
|
||||
|
||||
Also allow turning off treasure maps all together as they can eat up Map ID's
|
||||
which are limited in quantity.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java
|
||||
index f95999daa1955dd4d919d0e668fe099901a0481c..770a91fcc351a2d1de4762c0fd9bae2b49c363b5 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java
|
||||
@@ -386,7 +386,8 @@ public class VillagerTrades {
|
||||
return null;
|
||||
} else {
|
||||
ServerLevel serverLevel = (ServerLevel)entity.level;
|
||||
- BlockPos blockPos = serverLevel.findNearestMapStructure(this.destination, entity.blockPosition(), 100, true);
|
||||
+ if (!serverLevel.paperConfig().environment.treasureMaps.enabled) return null; // Paper
|
||||
+ BlockPos blockPos = serverLevel.findNearestMapStructure(this.destination, entity.blockPosition(), 100, !serverLevel.paperConfig().environment.treasureMaps.findAlreadyDiscoveredVillager); // Paper
|
||||
if (blockPos != null) {
|
||||
ItemStack itemStack = MapItem.create(serverLevel, blockPos.getX(), blockPos.getZ(), (byte)2, true, true);
|
||||
MapItem.renderBiomePreviewMap(serverLevel, itemStack);
|
||||
diff --git a/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java b/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java
|
||||
index 321384730cacbdc22eedc53651e4d24f06c73b99..b734c0f9b831c20a239b5341ff3a0b4d6a6c102c 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java
|
||||
@@ -68,7 +68,16 @@ public class ExplorationMapFunction extends LootItemConditionalFunction {
|
||||
Vec3 vec3 = context.getParamOrNull(LootContextParams.ORIGIN);
|
||||
if (vec3 != null) {
|
||||
ServerLevel serverLevel = context.getLevel();
|
||||
- BlockPos blockPos = serverLevel.findNearestMapStructure(this.destination, new BlockPos(vec3), this.searchRadius, this.skipKnownStructures);
|
||||
+ // Paper start
|
||||
+ if (!serverLevel.paperConfig().environment.treasureMaps.enabled) {
|
||||
+ /*
|
||||
+ * NOTE: I fear users will just get a plain map as their "treasure"
|
||||
+ * This is preferable to disrespecting the config.
|
||||
+ */
|
||||
+ return stack;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+ BlockPos blockPos = serverLevel.findNearestMapStructure(this.destination, new BlockPos(vec3), this.searchRadius, serverLevel.paperConfig().environment.treasureMaps.findAlreadyDiscoveredLootTable.or(this.skipKnownStructures)); // Paper
|
||||
if (blockPos != null) {
|
||||
ItemStack itemStack = MapItem.create(serverLevel, blockPos.getX(), blockPos.getZ(), this.zoom, true, true);
|
||||
MapItem.renderBiomePreviewMap(serverLevel, itemStack);
|
|
@ -1,20 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 21 Dec 2016 03:48:29 -0500
|
||||
Subject: [PATCH] Optimize ItemStack.isEmpty()
|
||||
|
||||
Remove hashMap lookup every check, simplify code to remove ternary
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
index 28a8ad5f42a5ba2e2a9d4c9a04a7add621b28e82..7b61f9c45b9e23562bd5cf448df319ba9e1e091a 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
@@ -245,7 +245,7 @@ public final class ItemStack {
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
- return this == ItemStack.EMPTY ? true : (this.getItem() != null && !this.is(Items.AIR) ? this.count <= 0 : true);
|
||||
+ return this == ItemStack.EMPTY || this.item == null || this.item == Items.AIR || this.count <= 0; // Paper
|
||||
}
|
||||
|
||||
public ItemStack split(int amount) {
|
|
@ -1,52 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: kashike <kashike@vq.lc>
|
||||
Date: Wed, 21 Dec 2016 11:47:25 -0600
|
||||
Subject: [PATCH] Add API methods to control if armour stands can move
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
|
||||
index 3869aae0bcf3d4fb53009b314f8b869198e26ce5..58882569595a21b0499921dfddcbc9d01248cf1c 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
|
||||
@@ -91,6 +91,7 @@ public class ArmorStand extends LivingEntity {
|
||||
public Rotations rightArmPose;
|
||||
public Rotations leftLegPose;
|
||||
public Rotations rightLegPose;
|
||||
+ public boolean canMove = true; // Paper
|
||||
|
||||
public ArmorStand(EntityType<? extends ArmorStand> type, Level world) {
|
||||
super(type, world);
|
||||
@@ -926,4 +927,13 @@ public class ArmorStand extends LivingEntity {
|
||||
public boolean canBeSeenByAnyone() {
|
||||
return !this.isInvisible() && !this.isMarker();
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public void move(net.minecraft.world.entity.MoverType type, Vec3 movement) {
|
||||
+ if (this.canMove) {
|
||||
+ super.move(type, movement);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java
|
||||
index 47ca72e264950dd950f037a21bb0ad6cc1700751..06cedeea447f53d100e32a6eba6f83b4719cb231 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java
|
||||
@@ -228,4 +228,15 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand {
|
||||
public boolean hasEquipmentLock(EquipmentSlot equipmentSlot, LockType lockType) {
|
||||
return (this.getHandle().disabledSlots & (1 << CraftEquipmentSlot.getNMS(equipmentSlot).getFilterFlag() + lockType.ordinal() * 8)) != 0;
|
||||
}
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public boolean canMove() {
|
||||
+ return getHandle().canMove;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setCanMove(boolean move) {
|
||||
+ getHandle().canMove = move;
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 27 Dec 2016 15:02:42 -0500
|
||||
Subject: [PATCH] String based Action Bar API
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetActionBarTextPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetActionBarTextPacket.java
|
||||
index 32ef3edebe94a2014168b7e438752a80b2687e5f..ab6c58eed6707ab7b0aa3e7549a871ad7dfad87f 100644
|
||||
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetActionBarTextPacket.java
|
||||
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetActionBarTextPacket.java
|
||||
@@ -7,6 +7,7 @@ import net.minecraft.network.protocol.Packet;
|
||||
public class ClientboundSetActionBarTextPacket implements Packet<ClientGamePacketListener> {
|
||||
private final Component text;
|
||||
public net.kyori.adventure.text.Component adventure$text; // Paper
|
||||
+ public net.md_5.bungee.api.chat.BaseComponent[] components; // Paper
|
||||
|
||||
public ClientboundSetActionBarTextPacket(Component message) {
|
||||
this.text = message;
|
||||
@@ -21,6 +22,8 @@ public class ClientboundSetActionBarTextPacket implements Packet<ClientGamePacke
|
||||
// Paper start
|
||||
if (this.adventure$text != null) {
|
||||
buf.writeComponent(this.adventure$text);
|
||||
+ } else if (this.components != null) {
|
||||
+ buf.writeComponent(this.components);
|
||||
} else
|
||||
// Paper end
|
||||
buf.writeComponent(this.text);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index 1e1deab4d8be5523a55daf072d7e12b08d36b560..87c8e494aa374b8bfb8b8432723783b00ba94763 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -355,6 +355,26 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
}
|
||||
|
||||
// Paper start
|
||||
+ @Override
|
||||
+ public void sendActionBar(BaseComponent[] message) {
|
||||
+ if (getHandle().connection == null) return;
|
||||
+ net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket packet = new net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket((net.minecraft.network.chat.Component) null);
|
||||
+ packet.components = message;
|
||||
+ getHandle().connection.send(packet);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void sendActionBar(String message) {
|
||||
+ if (getHandle().connection == null || message == null || message.isEmpty()) return;
|
||||
+ getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket(CraftChatMessage.fromStringOrNull(message)));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void sendActionBar(char alternateChar, String message) {
|
||||
+ if (message == null || message.isEmpty()) return;
|
||||
+ sendActionBar(org.bukkit.ChatColor.translateAlternateColorCodes(alternateChar, message));
|
||||
+ }
|
||||
+
|
||||
@Override
|
||||
public void setPlayerListHeaderFooter(BaseComponent[] header, BaseComponent[] footer) {
|
||||
if (header != null) {
|
|
@ -1,33 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alfie Cleveland <alfeh@me.com>
|
||||
Date: Tue, 27 Dec 2016 01:57:57 +0000
|
||||
Subject: [PATCH] Properly fix item duplication bug
|
||||
|
||||
Credit to prplz for figuring out the real issue
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 3cea2ceb5d30329aa84f6659330eea075387fe18..0fded4890038de77781c27565fa3c8fe60e50aac 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -2203,7 +2203,7 @@ public class ServerPlayer extends Player {
|
||||
|
||||
@Override
|
||||
public boolean isImmobile() {
|
||||
- return super.isImmobile() || !this.getBukkitEntity().isOnline();
|
||||
+ return super.isImmobile() || (this.connection != null && this.connection.isDisconnected()); // Paper
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index e032a9f72aa5d55daa9c680734e45e3dda13ca9b..6282cebfa3786c9ac72fcebeee1b8c4cdf5d7238 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -3283,7 +3283,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
||||
}
|
||||
|
||||
public final boolean isDisconnected() {
|
||||
- return !this.player.joining && !this.connection.isConnected();
|
||||
+ return (!this.player.joining && !this.connection.isConnected()) || this.processedDisconnect; // Paper
|
||||
}
|
||||
// CraftBukkit end
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 28 Dec 2016 07:18:33 +0100
|
||||
Subject: [PATCH] Firework API's
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.entity.projectile.FireworkRocketEntity attachedToEntity
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java b/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java
|
||||
index ba13507263d78d34eb8d3038c437229c0469d476..61252ef8a79bac0ea2d3d231ec6b12166f39d072 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java
|
||||
@@ -39,6 +39,7 @@ public class FireworkRocketEntity extends Projectile implements ItemSupplier {
|
||||
public int lifetime;
|
||||
@Nullable
|
||||
public LivingEntity attachedToEntity; // PAIL private -> public
|
||||
+ public java.util.UUID spawningEntity; // Paper
|
||||
|
||||
public FireworkRocketEntity(EntityType<? extends FireworkRocketEntity> type, Level world) {
|
||||
super(type, world);
|
||||
@@ -318,6 +319,11 @@ public class FireworkRocketEntity extends Projectile implements ItemSupplier {
|
||||
}
|
||||
|
||||
nbt.putBoolean("ShotAtAngle", (Boolean) this.entityData.get(FireworkRocketEntity.DATA_SHOT_AT_ANGLE));
|
||||
+ // Paper start
|
||||
+ if (this.spawningEntity != null) {
|
||||
+ nbt.putUUID("SpawningEntity", this.spawningEntity);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -334,7 +340,11 @@ public class FireworkRocketEntity extends Projectile implements ItemSupplier {
|
||||
if (nbt.contains("ShotAtAngle")) {
|
||||
this.entityData.set(FireworkRocketEntity.DATA_SHOT_AT_ANGLE, nbt.getBoolean("ShotAtAngle"));
|
||||
}
|
||||
-
|
||||
+ // Paper start
|
||||
+ if (nbt.hasUUID("SpawningEntity")) {
|
||||
+ this.spawningEntity = nbt.getUUID("SpawningEntity");
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/net/minecraft/world/item/CrossbowItem.java b/src/main/java/net/minecraft/world/item/CrossbowItem.java
|
||||
index 17b797a036ac0f58b58f627dc61ac503c8f321db..d86ec8c4c1c3e7974463a545d80ed9744de0fbbb 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/CrossbowItem.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/CrossbowItem.java
|
||||
@@ -220,6 +220,7 @@ public class CrossbowItem extends ProjectileWeaponItem implements Vanishable {
|
||||
|
||||
if (flag1) {
|
||||
object = new FireworkRocketEntity(world, projectile, shooter, shooter.getX(), shooter.getEyeY() - 0.15000000596046448D, shooter.getZ(), true);
|
||||
+ ((FireworkRocketEntity) object).spawningEntity = shooter.getUUID(); // Paper
|
||||
} else {
|
||||
object = CrossbowItem.getArrow(world, shooter, crossbow, projectile);
|
||||
if (creative || simulated != 0.0F) {
|
||||
diff --git a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java
|
||||
index cdf35c5873f68245891241c0efa3bcf5658c3f6d..766af1f45b14654d3655a06ae0bfb0d4cfbdff7a 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java
|
||||
@@ -44,6 +44,7 @@ public class FireworkRocketItem extends Item {
|
||||
Vec3 vec3 = context.getClickLocation();
|
||||
Direction direction = context.getClickedFace();
|
||||
FireworkRocketEntity fireworkRocketEntity = new FireworkRocketEntity(level, context.getPlayer(), vec3.x + (double)direction.getStepX() * 0.15D, vec3.y + (double)direction.getStepY() * 0.15D, vec3.z + (double)direction.getStepZ() * 0.15D, itemStack);
|
||||
+ fireworkRocketEntity.spawningEntity = context.getPlayer() == null ? null : context.getPlayer().getUUID(); // Paper
|
||||
level.addFreshEntity(fireworkRocketEntity);
|
||||
itemStack.shrink(1);
|
||||
}
|
||||
@@ -57,6 +58,7 @@ public class FireworkRocketItem extends Item {
|
||||
ItemStack itemStack = user.getItemInHand(hand);
|
||||
if (!world.isClientSide) {
|
||||
FireworkRocketEntity fireworkRocketEntity = new FireworkRocketEntity(world, itemStack, user);
|
||||
+ fireworkRocketEntity.spawningEntity = user.getUUID(); // Paper
|
||||
world.addFreshEntity(fireworkRocketEntity);
|
||||
if (!user.getAbilities().instabuild) {
|
||||
itemStack.shrink(1);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java
|
||||
index 59d5c314711b4ec239e5bcb4272b11ed72705c5a..c242f654c88ca1773429348939d3bb2ffae3768c 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java
|
||||
@@ -135,4 +135,11 @@ public class CraftFirework extends CraftProjectile implements Firework {
|
||||
public void setShotAtAngle(boolean shotAtAngle) {
|
||||
this.getHandle().getEntityData().set(FireworkRocketEntity.DATA_SHOT_AT_ANGLE, shotAtAngle);
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public java.util.UUID getSpawningEntity() {
|
||||
+ return getHandle().spawningEntity;
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 31 Dec 2016 21:44:50 -0500
|
||||
Subject: [PATCH] PlayerTeleportEndGatewayEvent
|
||||
|
||||
Allows you to access the Gateway being used in a teleport event
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java
|
||||
index 0a792513ac71df24aa8ea4e5d47caad07c22c65e..575e9ced37b6b865de342d305af2c5762ae6fcb9 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java
|
||||
@@ -11,6 +11,7 @@ import net.minecraft.data.worldgen.features.EndFeatures;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtUtils;
|
||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
||||
+import io.papermc.paper.util.MCUtil;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.util.Mth;
|
||||
@@ -210,7 +211,7 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity {
|
||||
location.setPitch(player.getLocation().getPitch());
|
||||
location.setYaw(player.getLocation().getYaw());
|
||||
|
||||
- PlayerTeleportEvent teleEvent = new PlayerTeleportEvent(player, player.getLocation(), location, PlayerTeleportEvent.TeleportCause.END_GATEWAY);
|
||||
+ PlayerTeleportEvent teleEvent = new com.destroystokyo.paper.event.player.PlayerTeleportEndGatewayEvent(player, player.getLocation(), location, new org.bukkit.craftbukkit.block.CraftEndGateway(worldserver.getWorld(), blockEntity)); // Paper
|
||||
Bukkit.getPluginManager().callEvent(teleEvent);
|
||||
if (teleEvent.isCancelled()) {
|
||||
return;
|
|
@ -1,82 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 7 Jan 2017 15:24:46 -0500
|
||||
Subject: [PATCH] Provide E/TE/Chunk count stat methods
|
||||
|
||||
Provides counts without the ineffeciency of using .getEntities().size()
|
||||
which creates copy of the collections.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
||||
index 64b763d6dc695e9cb9dd381deb5609e4902713dd..1954a93a1f566c1c79cdc2e0eb1b41141d6b5fde 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/Level.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
||||
@@ -112,7 +112,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
public static final int TICKS_PER_DAY = 24000;
|
||||
public static final int MAX_ENTITY_SPAWN_Y = 20000000;
|
||||
public static final int MIN_ENTITY_SPAWN_Y = -20000000;
|
||||
- protected final List<TickingBlockEntity> blockEntityTickers = Lists.newArrayList();
|
||||
+ protected final List<TickingBlockEntity> blockEntityTickers = Lists.newArrayList(); public final int getTotalTileEntityTickers() { return this.blockEntityTickers.size(); } // Paper
|
||||
protected final NeighborUpdater neighborUpdater;
|
||||
private final List<TickingBlockEntity> pendingBlockEntityTickers = Lists.newArrayList();
|
||||
private boolean tickingBlockEntities;
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
index fe2f5364e526cfe9e25760301165934b7fbbdd85..2636ef8f827b30315693f1b406debcdea0716170 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
@@ -152,6 +152,56 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
private final CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(CraftWorld.DATA_TYPE_REGISTRY);
|
||||
private net.kyori.adventure.pointer.Pointers adventure$pointers; // Paper - implement pointers
|
||||
|
||||
+ // Paper start - Provide fast information methods
|
||||
+ @Override
|
||||
+ public int getEntityCount() {
|
||||
+ int ret = 0;
|
||||
+ for (net.minecraft.world.entity.Entity entity : world.getEntities().getAll()) {
|
||||
+ if (entity.isChunkLoaded()) {
|
||||
+ ++ret;
|
||||
+ }
|
||||
+ }
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getTileEntityCount() {
|
||||
+ // We don't use the full world tile entity list, so we must iterate chunks
|
||||
+ int size = 0;
|
||||
+ for (ChunkHolder playerchunk : io.papermc.paper.chunk.system.ChunkSystem.getVisibleChunkHolders(this.world)) {
|
||||
+ net.minecraft.world.level.chunk.LevelChunk chunk = playerchunk.getTickingChunk();
|
||||
+ if (chunk == null) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ size += chunk.blockEntities.size();
|
||||
+ }
|
||||
+ return size;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getTickableTileEntityCount() {
|
||||
+ return world.getTotalTileEntityTickers();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getChunkCount() {
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ for (ChunkHolder chunkHolder : io.papermc.paper.chunk.system.ChunkSystem.getVisibleChunkHolders(this.world)) {
|
||||
+ if (chunkHolder.getTickingChunk() != null) {
|
||||
+ ++ret;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getPlayerCount() {
|
||||
+ return world.players().size();
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
private static final Random rand = new Random();
|
||||
|
||||
public CraftWorld(ServerLevel world, ChunkGenerator gen, BiomeProvider biomeProvider, Environment env) {
|
|
@ -1,27 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 7 Jan 2017 15:41:58 -0500
|
||||
Subject: [PATCH] Enforce Sync Player Saves
|
||||
|
||||
Saving players async is extremely dangerous. This will force it to main
|
||||
the same way we handle async chunk loads.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
index afbb45f2ee55f193e30c19bc20edc42434f16784..51add7e60fbd9eebbddc4893de044edc35854409 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
@@ -1042,11 +1042,13 @@ public abstract class PlayerList {
|
||||
}
|
||||
|
||||
public void saveAll() {
|
||||
+ io.papermc.paper.util.MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main
|
||||
MinecraftTimings.savePlayers.startTiming(); // Paper
|
||||
for (int i = 0; i < this.players.size(); ++i) {
|
||||
- this.save((ServerPlayer) this.players.get(i));
|
||||
+ this.save(this.players.get(i));
|
||||
}
|
||||
MinecraftTimings.savePlayers.stopTiming(); // Paper
|
||||
+ return null; }); // Paper - ensure main
|
||||
}
|
||||
|
||||
public UserWhiteList getWhiteList() {
|
|
@ -1,18 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alfie Cleveland <alfeh@me.com>
|
||||
Date: Sun, 8 Jan 2017 04:31:36 +0000
|
||||
Subject: [PATCH] Don't allow entities to ride themselves - #572
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index a6b5527e97e8a5b2eeca762477a7b695223a0d4d..86fa079f9f1f958ed586c966467d26a44e09b11c 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -2385,6 +2385,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
||||
}
|
||||
|
||||
protected boolean addPassenger(Entity entity) { // CraftBukkit
|
||||
+ if (entity == this) throw new IllegalArgumentException("Entities cannot become a passenger of themselves"); // Paper - issue 572
|
||||
if (entity.getVehicle() != this) {
|
||||
throw new IllegalStateException("Use x.startRiding(y), not y.addPassenger(x)");
|
||||
} else {
|
|
@ -1,353 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 19 Dec 2017 16:31:46 -0500
|
||||
Subject: [PATCH] ExperienceOrbs API for Reason/Source/Triggering player
|
||||
|
||||
Adds lots of information about why this orb exists.
|
||||
|
||||
Replaces isFromBottle() with logic that persists entity reloads too.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
index cd3b4c97374d44f5a0e710e03f4ac38938757e25..b18bb06caf5f034dffbb72120c8f21da482ae3df 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
@@ -419,7 +419,7 @@ public class ServerPlayerGameMode {
|
||||
|
||||
// Drop event experience
|
||||
if (flag && event != null) {
|
||||
- iblockdata.getBlock().popExperience(this.level, pos, event.getExpToDrop());
|
||||
+ iblockdata.getBlock().popExperience(this.level, pos, event.getExpToDrop(), this.player); // Paper
|
||||
}
|
||||
|
||||
return true;
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java
|
||||
index 63b57d47d7dbb7a8a655b1447241e20c67a3f9c2..0c19aa68dc444373bf1a9bd3b349d12df7d8dd9d 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java
|
||||
@@ -37,13 +37,65 @@ public class ExperienceOrb extends Entity {
|
||||
public int value;
|
||||
private int count;
|
||||
private Player followingPlayer;
|
||||
+ // Paper start
|
||||
+ public java.util.UUID sourceEntityId;
|
||||
+ public java.util.UUID triggerEntityId;
|
||||
+ public org.bukkit.entity.ExperienceOrb.SpawnReason spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN;
|
||||
+
|
||||
+ private void loadPaperNBT(CompoundTag nbttagcompound) {
|
||||
+ if (!nbttagcompound.contains("Paper.ExpData", 10)) { // 10 = compound
|
||||
+ return;
|
||||
+ }
|
||||
+ CompoundTag comp = nbttagcompound.getCompound("Paper.ExpData");
|
||||
+ if (comp.hasUUID("source")) {
|
||||
+ this.sourceEntityId = comp.getUUID("source");
|
||||
+ }
|
||||
+ if (comp.hasUUID("trigger")) {
|
||||
+ this.triggerEntityId = comp.getUUID("trigger");
|
||||
+ }
|
||||
+ if (comp.contains("reason")) {
|
||||
+ String reason = comp.getString("reason");
|
||||
+ try {
|
||||
+ this.spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.valueOf(reason);
|
||||
+ } catch (Exception e) {
|
||||
+ this.level.getCraftServer().getLogger().warning("Invalid spawnReason set for experience orb: " + e.getMessage() + " - " + reason);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ private void savePaperNBT(CompoundTag nbttagcompound) {
|
||||
+ CompoundTag comp = new CompoundTag();
|
||||
+ if (this.sourceEntityId != null) {
|
||||
+ comp.putUUID("source", this.sourceEntityId);
|
||||
+ }
|
||||
+ if (this.triggerEntityId != null) {
|
||||
+ comp.putUUID("trigger", triggerEntityId);
|
||||
+ }
|
||||
+ if (this.spawnReason != null && this.spawnReason != org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN) {
|
||||
+ comp.putString("reason", this.spawnReason.name());
|
||||
+ }
|
||||
+ nbttagcompound.put("Paper.ExpData", comp);
|
||||
+ }
|
||||
|
||||
+ @io.papermc.paper.annotation.DoNotUse
|
||||
+ @Deprecated
|
||||
public ExperienceOrb(Level world, double x, double y, double z, int amount) {
|
||||
+ this(world, x, y, z, amount, null, null);
|
||||
+ }
|
||||
+
|
||||
+ public ExperienceOrb(Level world, double d0, double d1, double d2, int i, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId) {
|
||||
+ this(world, d0, d1, d2, i, reason, triggerId, null);
|
||||
+ }
|
||||
+
|
||||
+ public ExperienceOrb(Level world, double d0, double d1, double d2, int i, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId, Entity sourceId) {
|
||||
this(EntityType.EXPERIENCE_ORB, world);
|
||||
- this.setPos(x, y, z);
|
||||
+ this.sourceEntityId = sourceId != null ? sourceId.getUUID() : null;
|
||||
+ this.triggerEntityId = triggerId != null ? triggerId.getUUID() : null;
|
||||
+ this.spawnReason = reason != null ? reason : org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN;
|
||||
+ // Paper end
|
||||
+ this.setPos(d0, d1, d2);
|
||||
this.setYRot((float) (this.random.nextDouble() * 360.0D));
|
||||
this.setDeltaMovement((this.random.nextDouble() * 0.20000000298023224D - 0.10000000149011612D) * 2.0D, this.random.nextDouble() * 0.2D * 2.0D, (this.random.nextDouble() * 0.20000000298023224D - 0.10000000149011612D) * 2.0D);
|
||||
- this.value = amount;
|
||||
+ this.value = i;
|
||||
}
|
||||
|
||||
public ExperienceOrb(EntityType<? extends ExperienceOrb> type, Level world) {
|
||||
@@ -153,12 +205,20 @@ public class ExperienceOrb extends Entity {
|
||||
}
|
||||
|
||||
public static void award(ServerLevel world, Vec3 pos, int amount) {
|
||||
+ // Paper start - add reasons for orbs
|
||||
+ award(world, pos, amount, null, null, null);
|
||||
+ }
|
||||
+ public static void award(ServerLevel world, Vec3 pos, int amount, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId) {
|
||||
+ award(world, pos, amount, reason, triggerId, null);
|
||||
+ }
|
||||
+ public static void award(ServerLevel world, Vec3 pos, int amount, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId, Entity sourceId) {
|
||||
+ // Paper end - add reasons for orbs
|
||||
while (amount > 0) {
|
||||
int j = ExperienceOrb.getExperienceValue(amount);
|
||||
|
||||
amount -= j;
|
||||
if (!ExperienceOrb.tryMergeToExisting(world, pos, j)) {
|
||||
- world.addFreshEntity(new ExperienceOrb(world, pos.x(), pos.y(), pos.z(), j));
|
||||
+ world.addFreshEntity(new ExperienceOrb(world, pos.x(), pos.y(), pos.z(), j, reason, triggerId, sourceId)); // Paper - add reason
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,6 +288,7 @@ public class ExperienceOrb extends Entity {
|
||||
nbt.putShort("Age", (short) this.age);
|
||||
nbt.putShort("Value", (short) this.value);
|
||||
nbt.putInt("Count", this.count);
|
||||
+ this.savePaperNBT(nbt); // Paper
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -236,6 +297,7 @@ public class ExperienceOrb extends Entity {
|
||||
this.age = nbt.getShort("Age");
|
||||
this.value = nbt.getShort("Value");
|
||||
this.count = Math.max(nbt.getInt("Count"), 1);
|
||||
+ this.loadPaperNBT(nbt); // Paper
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index a0d6273a8a5613ee732c3dbb6eff46ecf42b5f4a..a42983b4d7dbd360bbe4206dcf6aa95375ef9b2b 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -1726,7 +1726,8 @@ public abstract class LivingEntity extends Entity {
|
||||
protected void dropExperience() {
|
||||
// CraftBukkit start - Update getExpReward() above if the removed if() changes!
|
||||
if (true && !(this instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon)) { // CraftBukkit - SPIGOT-2420: Special case ender dragon will drop the xp over time
|
||||
- ExperienceOrb.award((ServerLevel) this.level, this.position(), this.expToDrop);
|
||||
+ LivingEntity attacker = this.lastHurtByPlayer != null ? this.lastHurtByPlayer : this.lastHurtByMob; // Paper
|
||||
+ ExperienceOrb.award((ServerLevel) this.level, this.position(), this.expToDrop, this instanceof ServerPlayer ? org.bukkit.entity.ExperienceOrb.SpawnReason.PLAYER_DEATH : org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, attacker, this); // Paper
|
||||
this.expToDrop = 0;
|
||||
}
|
||||
// CraftBukkit end
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/Animal.java b/src/main/java/net/minecraft/world/entity/animal/Animal.java
|
||||
index 3cdd7180a41b87caa942d2b3436ba90726686ecb..6216513805add7c8f52e1ed6c77e2d26786b3ab5 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/Animal.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/Animal.java
|
||||
@@ -262,7 +262,7 @@ public abstract class Animal extends AgeableMob {
|
||||
if (world.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
|
||||
// CraftBukkit start - use event experience
|
||||
if (experience > 0) {
|
||||
- world.addFreshEntity(new ExperienceOrb(world, this.getX(), this.getY(), this.getZ(), experience));
|
||||
+ world.addFreshEntity(new ExperienceOrb(world, this.getX(), this.getY(), this.getZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer, entityageable)); // Paper
|
||||
}
|
||||
// CraftBukkit end
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/Fox.java b/src/main/java/net/minecraft/world/entity/animal/Fox.java
|
||||
index 113b31a5a0247abc436d04ba2fe03cb41ca86f15..fb3b42611d8386b110ea079094d5d50fefceac1a 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/Fox.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/Fox.java
|
||||
@@ -892,7 +892,7 @@ public class Fox extends Animal {
|
||||
if (this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
|
||||
// CraftBukkit start - use event experience
|
||||
if (experience > 0) {
|
||||
- this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), experience));
|
||||
+ this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer, entityfox)); // Paper
|
||||
}
|
||||
// CraftBukkit end
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/Turtle.java b/src/main/java/net/minecraft/world/entity/animal/Turtle.java
|
||||
index 7c90063be2a7eb66b7f0981059018f20413256c6..37125ffe47fcd5fe93ab62ad8a46e8188f362436 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/Turtle.java
|
||||
@@ -448,7 +448,7 @@ public class Turtle extends Animal {
|
||||
RandomSource randomsource = this.animal.getRandom();
|
||||
|
||||
if (this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
|
||||
- this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), randomsource.nextInt(7) + 1));
|
||||
+ this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), randomsource.nextInt(7) + 1, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer)); // Paper;
|
||||
}
|
||||
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java b/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java
|
||||
index fe660bbaa4113fb2ffa1ea2f10e4e1e674fbb86d..bb6063ae7f4438916306ce876057f7488537b444 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java
|
||||
@@ -274,7 +274,7 @@ public class Frog extends Animal {
|
||||
this.getBrain().setMemory(MemoryModuleType.IS_PREGNANT, Unit.INSTANCE);
|
||||
world.broadcastEntityEvent(this, (byte)18);
|
||||
if (world.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
|
||||
- world.addFreshEntity(new ExperienceOrb(world, this.getX(), this.getY(), this.getZ(), this.getRandom().nextInt(7) + 1));
|
||||
+ world.addFreshEntity(new ExperienceOrb(world, this.getX(), this.getY(), this.getZ(), this.getRandom().nextInt(7) + 1, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, serverPlayer)); // Paper
|
||||
}
|
||||
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
||||
index 127aab56eef67d7f02f5c3de80d8f445ba70e7db..6eada8313e468e4ea851094976ac98c11710fb45 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
||||
@@ -647,7 +647,7 @@ public class EnderDragon extends Mob implements Enemy {
|
||||
|
||||
if (this.level instanceof ServerLevel) {
|
||||
if (this.dragonDeathTime > 150 && this.dragonDeathTime % 5 == 0 && true) { // CraftBukkit - SPIGOT-2420: Already checked for the game rule when calculating the xp
|
||||
- ExperienceOrb.award((ServerLevel) this.level, this.position(), Mth.floor((float) short0 * 0.08F));
|
||||
+ ExperienceOrb.award((ServerLevel) this.level, this.position(), Mth.floor((float) short0 * 0.08F), org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, this.lastHurtByPlayer, this); // Paper
|
||||
}
|
||||
|
||||
if (this.dragonDeathTime == 1 && !this.isSilent()) {
|
||||
@@ -677,7 +677,7 @@ public class EnderDragon extends Mob implements Enemy {
|
||||
this.yBodyRot = this.getYRot();
|
||||
if (this.dragonDeathTime == 200 && this.level instanceof ServerLevel) {
|
||||
if (true) { // CraftBukkit - SPIGOT-2420: Already checked for the game rule when calculating the xp
|
||||
- ExperienceOrb.award((ServerLevel) this.level, this.position(), Mth.floor((float) short0 * 0.2F));
|
||||
+ ExperienceOrb.award((ServerLevel) this.level, this.position(), Mth.floor((float) short0 * 0.2F), org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, this.lastHurtByPlayer, this); // Paper
|
||||
}
|
||||
|
||||
if (this.dragonFight != null) {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java
|
||||
index 33d1a6b31afec4dbeb00dcabf50c5840852102d6..25cd8a4101cf44955d95924c9794c238ddde2901 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java
|
||||
@@ -624,7 +624,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
|
||||
}
|
||||
|
||||
if (offer.shouldRewardExp()) {
|
||||
- this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY() + 0.5D, this.getZ(), i));
|
||||
+ this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY() + 0.5D, this.getZ(), i, org.bukkit.entity.ExperienceOrb.SpawnReason.VILLAGER_TRADE, this.getTradingPlayer(), this)); // Paper
|
||||
}
|
||||
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java
|
||||
index 9bc9307966b77e34cb091fc895db3d3a66f7be82..e594cf4b8084b7448c29208a2070e766e391713d 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java
|
||||
@@ -186,7 +186,7 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill
|
||||
if (offer.shouldRewardExp()) {
|
||||
int i = 3 + this.random.nextInt(4);
|
||||
|
||||
- this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY() + 0.5D, this.getZ(), i));
|
||||
+ this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY() + 0.5D, this.getZ(), i, org.bukkit.entity.ExperienceOrb.SpawnReason.VILLAGER_TRADE, this.getTradingPlayer(), this)); // Paper
|
||||
}
|
||||
|
||||
}
|
||||
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 00fe96650e4d973e97b46968297f55f4c3674629..11ac510ad4095438d4904d521bfb18aa5f743faf 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
|
||||
@@ -513,7 +513,7 @@ public class FishingHook extends Projectile {
|
||||
this.level.addFreshEntity(entityitem);
|
||||
// CraftBukkit start - this.random.nextInt(6) + 1 -> playerFishEvent.getExpToDrop()
|
||||
if (playerFishEvent.getExpToDrop() > 0) {
|
||||
- entityhuman.level.addFreshEntity(new ExperienceOrb(entityhuman.level, entityhuman.getX(), entityhuman.getY() + 0.5D, entityhuman.getZ() + 0.5D, playerFishEvent.getExpToDrop()));
|
||||
+ entityhuman.level.addFreshEntity(new ExperienceOrb(entityhuman.level, entityhuman.getX(), entityhuman.getY() + 0.5D, entityhuman.getZ() + 0.5D, playerFishEvent.getExpToDrop(), org.bukkit.entity.ExperienceOrb.SpawnReason.FISHING, this.getPlayerOwner(), this)); // Paper
|
||||
}
|
||||
// CraftBukkit end
|
||||
if (itemstack1.is(ItemTags.FISHES)) {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java
|
||||
index db6b1a9804a6d75dce22b780044beb04ca69cc94..dcbbff3a8dfcac869f07025e0e8e3d9c47956093 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java
|
||||
@@ -51,7 +51,7 @@ public class ThrownExperienceBottle extends ThrowableItemProjectile {
|
||||
}
|
||||
// CraftBukkit end
|
||||
|
||||
- ExperienceOrb.award((ServerLevel) this.level, this.position(), i);
|
||||
+ ExperienceOrb.award((ServerLevel) this.level, this.position(), i, org.bukkit.entity.ExperienceOrb.SpawnReason.EXP_BOTTLE, this.getOwner(), this); // Paper
|
||||
this.discard();
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java
|
||||
index dbdba510d8ff3c622ed928151cf525cfd1d1b1b5..aa0ba9c7dcb0ee81c9081031c447eeab61d92a10 100644
|
||||
--- a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java
|
||||
+++ b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java
|
||||
@@ -97,7 +97,7 @@ public class GrindstoneMenu extends AbstractContainerMenu {
|
||||
public void onTake(net.minecraft.world.entity.player.Player player, ItemStack stack) {
|
||||
context.execute((world, blockposition) -> {
|
||||
if (world instanceof ServerLevel) {
|
||||
- ExperienceOrb.award((ServerLevel) world, Vec3.atCenterOf(blockposition), this.getExperienceAmount(world));
|
||||
+ ExperienceOrb.award((ServerLevel) world, Vec3.atCenterOf(blockposition), this.getExperienceAmount(world), org.bukkit.entity.ExperienceOrb.SpawnReason.GRINDSTONE, player); // Paper
|
||||
}
|
||||
|
||||
world.levelEvent(1042, blockposition, 0);
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java
|
||||
index 4b3dc4648709abbdd6ac0972c298a64a875e5f6c..77125720fcbeb7bfc180effb27cfb78c74832ce5 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/Block.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/Block.java
|
||||
@@ -376,8 +376,13 @@ public class Block extends BlockBehaviour implements ItemLike {
|
||||
}
|
||||
|
||||
public void popExperience(ServerLevel world, BlockPos pos, int size) {
|
||||
+ // Paper start - add player parameter
|
||||
+ popExperience(world, pos, size, null);
|
||||
+ }
|
||||
+ public void popExperience(ServerLevel world, BlockPos pos, int size, net.minecraft.server.level.ServerPlayer player) {
|
||||
+ // Paper end - add player parameter
|
||||
if (world.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) {
|
||||
- ExperienceOrb.award(world, Vec3.atCenterOf(pos), size);
|
||||
+ ExperienceOrb.award(world, Vec3.atCenterOf(pos), size, org.bukkit.entity.ExperienceOrb.SpawnReason.BLOCK_BREAK, player); // Paper
|
||||
}
|
||||
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
||||
index e90fa66b4716f55844818a2770d9e02d68658e46..bbccb2f97ee88fe43af4eec30fbb2ecea1ebb1b4 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
||||
@@ -642,7 +642,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
|
||||
j = event.getExpToDrop();
|
||||
// CraftBukkit end
|
||||
|
||||
- ExperienceOrb.award(worldserver, vec3d, j);
|
||||
+ ExperienceOrb.award(worldserver, vec3d, j, org.bukkit.entity.ExperienceOrb.SpawnReason.FURNACE, entityhuman); // Paper
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
|
||||
index e1f478359d959157f60b866ab59bba3b5b16521c..c4f8d2c090e3cde562a2ab6103da53ded666599b 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
|
||||
@@ -909,7 +909,7 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
|
||||
} else if (TNTPrimed.class.isAssignableFrom(clazz)) {
|
||||
entity = new PrimedTnt(world, x, y, z, null);
|
||||
} else if (ExperienceOrb.class.isAssignableFrom(clazz)) {
|
||||
- entity = new net.minecraft.world.entity.ExperienceOrb(world, x, y, z, 0);
|
||||
+ entity = new net.minecraft.world.entity.ExperienceOrb(world, x, y, z, 0, org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM, null, null); // Paper
|
||||
} else if (LightningStrike.class.isAssignableFrom(clazz)) {
|
||||
entity = net.minecraft.world.entity.EntityType.LIGHTNING_BOLT.create(world);
|
||||
entity.moveTo(location.getX(), location.getY(), location.getZ());
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java
|
||||
index 40713228b149b4532fcee3a54bbe63e161318258..84899284703baeb04bfc79251941265d52ac07e8 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java
|
||||
@@ -19,6 +19,18 @@ public class CraftExperienceOrb extends CraftEntity implements ExperienceOrb {
|
||||
this.getHandle().value = value;
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ public java.util.UUID getTriggerEntityId() {
|
||||
+ return getHandle().triggerEntityId;
|
||||
+ }
|
||||
+ public java.util.UUID getSourceEntityId() {
|
||||
+ return getHandle().sourceEntityId;
|
||||
+ }
|
||||
+ public SpawnReason getSpawnReason() {
|
||||
+ return getHandle().spawnReason;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public net.minecraft.world.entity.ExperienceOrb getHandle() {
|
||||
return (net.minecraft.world.entity.ExperienceOrb) entity;
|
|
@ -1,42 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 22 Jan 2017 18:07:56 -0500
|
||||
Subject: [PATCH] Cap Entity Collisions
|
||||
|
||||
Limit a single entity to colliding a max of configurable times per tick.
|
||||
This will alleviate issues where living entities are hoarded in 1x1 pens
|
||||
|
||||
This is not tied to the maxEntityCramming rule. Cramming will still apply
|
||||
just as it does in Vanilla, but entity pushing logic will be capped.
|
||||
|
||||
You can set this to 0 to disable collisions.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index 86fa079f9f1f958ed586c966467d26a44e09b11c..58256b341aa15e946abef464453c0ffcaf55b372 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -379,6 +379,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
||||
public void inactiveTick() { }
|
||||
// Spigot end
|
||||
// Paper start
|
||||
+ protected int numCollisions = 0; // Paper
|
||||
@javax.annotation.Nullable
|
||||
private org.bukkit.util.Vector origin;
|
||||
@javax.annotation.Nullable
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index a42983b4d7dbd360bbe4206dcf6aa95375ef9b2b..6295c89211ba86c10009775f4d399f597d240fd0 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -3289,8 +3289,11 @@ public abstract class LivingEntity extends Entity {
|
||||
}
|
||||
}
|
||||
|
||||
- for (j = 0; j < list.size(); ++j) {
|
||||
+ this.numCollisions = Math.max(0, this.numCollisions - this.level.paperConfig().collisions.maxEntityCollisions); // Paper
|
||||
+ for (j = 0; j < list.size() && this.numCollisions < this.level.paperConfig().collisions.maxEntityCollisions; ++j) { // Paper
|
||||
Entity entity = (Entity) list.get(j);
|
||||
+ entity.numCollisions++; // Paper
|
||||
+ this.numCollisions++; // Paper
|
||||
|
||||
this.doPush(entity);
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 5 Feb 2017 00:04:04 -0500
|
||||
Subject: [PATCH] Remove CraftScheduler Async Task Debugger
|
||||
|
||||
I have not once ever seen this system help debug a crash.
|
||||
One report of a suspected memory leak with the system.
|
||||
|
||||
This adds additional overhead to asynchronous task dispatching
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java
|
||||
index dfc2789009fcaa08baa8054bdac915590b8701d6..d96292052633941102c052894bef747817b2998f 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java
|
||||
@@ -445,7 +445,7 @@ public class CraftScheduler implements BukkitScheduler {
|
||||
}
|
||||
this.parsePending();
|
||||
} else {
|
||||
- this.debugTail = this.debugTail.setNext(new CraftAsyncDebugger(currentTick + CraftScheduler.RECENT_TICKS, task.getOwner(), task.getTaskClass()));
|
||||
+ //this.debugTail = this.debugTail.setNext(new CraftAsyncDebugger(currentTick + CraftScheduler.RECENT_TICKS, task.getOwner(), task.getTaskClass())); // Paper
|
||||
this.executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper
|
||||
// We don't need to parse pending
|
||||
// (async tasks must live with race-conditions if they attempt to cancel between these few lines of code)
|
||||
@@ -462,7 +462,7 @@ public class CraftScheduler implements BukkitScheduler {
|
||||
this.pending.addAll(temp);
|
||||
temp.clear();
|
||||
MinecraftTimings.bukkitSchedulerFinishTimer.stopTiming(); // Paper
|
||||
- this.debugHead = this.debugHead.getNextHead(currentTick);
|
||||
+ //this.debugHead = this.debugHead.getNextHead(currentTick); // Paper
|
||||
}
|
||||
|
||||
private void addTask(final CraftTask task) {
|
||||
@@ -527,10 +527,15 @@ public class CraftScheduler implements BukkitScheduler {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
+ // Paper start
|
||||
+ return "";
|
||||
+ /*
|
||||
int debugTick = this.currentTick;
|
||||
StringBuilder string = new StringBuilder("Recent tasks from ").append(debugTick - CraftScheduler.RECENT_TICKS).append('-').append(debugTick).append('{');
|
||||
this.debugHead.debugTo(string);
|
||||
return string.append('}').toString();
|
||||
+ */
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
@Deprecated
|
|
@ -1,23 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach.brown@destroystokyo.com>
|
||||
Date: Sat, 18 Feb 2017 19:29:58 -0600
|
||||
Subject: [PATCH] Do not let armorstands drown
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
|
||||
index 58882569595a21b0499921dfddcbc9d01248cf1c..4398a33df4e0f0e9d28c51af3d48e41d957d7c9e 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
|
||||
@@ -935,5 +935,12 @@ public class ArmorStand extends LivingEntity {
|
||||
super.move(type, movement);
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public boolean canBreatheUnderwater() { // Skips a bit of damage handling code, probably a micro-optimization
|
||||
+ return true;
|
||||
+ }
|
||||
+ // Paper end
|
||||
// Paper end
|
||||
}
|
|
@ -1,290 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach.brown@destroystokyo.com>
|
||||
Date: Fri, 12 May 2017 23:34:11 -0500
|
||||
Subject: [PATCH] Properly handle async calls to restart the server
|
||||
|
||||
The watchdog thread calls the server restart function asynchronously. Prior to
|
||||
this change, it attempted to do several non-safe operations from the watchdog
|
||||
thread, rather than the main. Specifically, because of a separate upstream change,
|
||||
it causes player entities to be ticked asynchronously, among other things.
|
||||
|
||||
This is dangerous.
|
||||
|
||||
This patch moves the old handling into a synchronous variant, for calls from the
|
||||
restart command, and adds separate handling for async calls, such as those from
|
||||
the watchdog thread.
|
||||
|
||||
When calling from the watchdog thread, we cannot assume the main thread is in a
|
||||
tickable state; it may be completely deadlocked. In order to handle this, we mark
|
||||
the server as stopping, in order to account for situations where the server should
|
||||
complete a tick reasonbly soon, i.e. 99% of cases.
|
||||
|
||||
Should the server not enter a state where it is stopping within 10 seconds, We
|
||||
will assume that the server has in fact deadlocked and will proceed to force
|
||||
kill the server.
|
||||
|
||||
This modification does not force restart the server should we actually enter a
|
||||
deadlocked state where the server is stopping, whereas this will in most cases
|
||||
exit within a reasonable amount of time, to put a fixed limit on a process that
|
||||
will have plugins and worlds saving to the disk has a high potential to result
|
||||
in corruption/dataloss.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index f438056c74dd24142bd94b505160711d0f94a5d5..f852c1315cf9dcba56f5877063254d4c608abd61 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -221,6 +221,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
private Map<ResourceKey<Level>, ServerLevel> levels;
|
||||
private PlayerList playerList;
|
||||
private volatile boolean running;
|
||||
+ private volatile boolean isRestarting = false; // Paper - flag to signify we're attempting to restart
|
||||
private boolean stopped;
|
||||
private int tickCount;
|
||||
protected final Proxy proxy;
|
||||
@@ -894,7 +895,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
if (this.playerList != null) {
|
||||
MinecraftServer.LOGGER.info("Saving players");
|
||||
this.playerList.saveAll();
|
||||
- this.playerList.removeAll();
|
||||
+ this.playerList.removeAll(this.isRestarting); // Paper
|
||||
try { Thread.sleep(100); } catch (InterruptedException ex) {} // CraftBukkit - SPIGOT-625 - give server at least a chance to send packets
|
||||
}
|
||||
|
||||
@@ -945,6 +946,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
}
|
||||
|
||||
public void halt(boolean flag) {
|
||||
+ // Paper start - allow passing of the intent to restart
|
||||
+ this.safeShutdown(flag, false);
|
||||
+ }
|
||||
+ public void safeShutdown(boolean flag, boolean isRestarting) {
|
||||
+ this.isRestarting = isRestarting;
|
||||
+ // Paper end
|
||||
this.running = false;
|
||||
if (flag) {
|
||||
try {
|
||||
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
index 51add7e60fbd9eebbddc4893de044edc35854409..dbc8f0b962371902fc5e84f1171046d794eb1367 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
@@ -1153,8 +1153,15 @@ public abstract class PlayerList {
|
||||
}
|
||||
|
||||
public void removeAll() {
|
||||
+ // Paper start - Extract method to allow for restarting flag
|
||||
+ this.removeAll(false);
|
||||
+ }
|
||||
+
|
||||
+ public void removeAll(boolean isRestarting) {
|
||||
+ // Paper end
|
||||
// CraftBukkit start - disconnect safely
|
||||
for (ServerPlayer player : this.players) {
|
||||
+ if (isRestarting) player.connection.disconnect(org.spigotmc.SpigotConfig.restartMessage); else // Paper
|
||||
player.connection.disconnect(this.server.server.shutdownMessage()); // CraftBukkit - add custom shutdown message // Paper - Adventure
|
||||
}
|
||||
// CraftBukkit end
|
||||
diff --git a/src/main/java/org/spigotmc/RestartCommand.java b/src/main/java/org/spigotmc/RestartCommand.java
|
||||
index 94d8ba376cd1f024b244654cac9bb62bb19e3060..a142a56a920e153ed84c08cece993f10d76f7793 100644
|
||||
--- a/src/main/java/org/spigotmc/RestartCommand.java
|
||||
+++ b/src/main/java/org/spigotmc/RestartCommand.java
|
||||
@@ -46,86 +46,134 @@ public class RestartCommand extends Command
|
||||
org.spigotmc.AsyncCatcher.shuttingDown = true; // Paper
|
||||
try
|
||||
{
|
||||
- String[] split = restartScript.split( " " );
|
||||
- if ( split.length > 0 && new File( split[0] ).isFile() )
|
||||
+ // Paper - extract method and cleanup
|
||||
+ boolean isRestarting = addShutdownHook( restartScript );
|
||||
+ if ( isRestarting )
|
||||
{
|
||||
- System.out.println( "Attempting to restart with " + restartScript );
|
||||
+ System.out.println( "Attempting to restart with " + SpigotConfig.restartScript );
|
||||
+ } else
|
||||
+ {
|
||||
+ System.out.println( "Startup script '" + SpigotConfig.restartScript + "' does not exist! Stopping server." );
|
||||
+ }
|
||||
+ // Stop the watchdog
|
||||
+ WatchdogThread.doStop();
|
||||
|
||||
- // Disable Watchdog
|
||||
- WatchdogThread.doStop();
|
||||
+ shutdownServer( isRestarting );
|
||||
+ // Paper end
|
||||
+ } catch ( Exception ex )
|
||||
+ {
|
||||
+ ex.printStackTrace();
|
||||
+ }
|
||||
+ }
|
||||
|
||||
- // Kick all players
|
||||
- for ( ServerPlayer p : (List<ServerPlayer>) MinecraftServer.getServer().getPlayerList().players )
|
||||
- {
|
||||
- p.connection.disconnect(SpigotConfig.restartMessage);
|
||||
- }
|
||||
- // Give the socket a chance to send the packets
|
||||
- try
|
||||
- {
|
||||
- Thread.sleep( 100 );
|
||||
- } catch ( InterruptedException ex )
|
||||
- {
|
||||
- }
|
||||
- // Close the socket so we can rebind with the new process
|
||||
- MinecraftServer.getServer().getConnection().stop();
|
||||
+ // Paper start - sync copied from above with minor changes, async added
|
||||
+ private static void shutdownServer(boolean isRestarting)
|
||||
+ {
|
||||
+ if ( MinecraftServer.getServer().isSameThread() )
|
||||
+ {
|
||||
+ // Kick all players
|
||||
+ for ( ServerPlayer p : com.google.common.collect.ImmutableList.copyOf( MinecraftServer.getServer().getPlayerList().players ) )
|
||||
+ {
|
||||
+ p.connection.disconnect(SpigotConfig.restartMessage);
|
||||
+ }
|
||||
+ // Give the socket a chance to send the packets
|
||||
+ try
|
||||
+ {
|
||||
+ Thread.sleep( 100 );
|
||||
+ } catch ( InterruptedException ex )
|
||||
+ {
|
||||
+ }
|
||||
|
||||
- // Give time for it to kick in
|
||||
- try
|
||||
- {
|
||||
- Thread.sleep( 100 );
|
||||
- } catch ( InterruptedException ex )
|
||||
- {
|
||||
- }
|
||||
+ closeSocket();
|
||||
|
||||
- // Actually shutdown
|
||||
- try
|
||||
- {
|
||||
- MinecraftServer.getServer().close();
|
||||
- } catch ( Throwable t )
|
||||
- {
|
||||
- }
|
||||
+ // Actually shutdown
|
||||
+ try
|
||||
+ {
|
||||
+ MinecraftServer.getServer().close(); // calls stop()
|
||||
+ } catch ( Throwable t )
|
||||
+ {
|
||||
+ }
|
||||
+
|
||||
+ // Actually stop the JVM
|
||||
+ System.exit( 0 );
|
||||
|
||||
- // This will be done AFTER the server has completely halted
|
||||
- Thread shutdownHook = new Thread()
|
||||
+ } else
|
||||
+ {
|
||||
+ // Mark the server to shutdown at the end of the tick
|
||||
+ MinecraftServer.getServer().safeShutdown( false, isRestarting );
|
||||
+
|
||||
+ // wait 10 seconds to see if we're actually going to try shutdown
|
||||
+ try
|
||||
+ {
|
||||
+ Thread.sleep( 10000 );
|
||||
+ }
|
||||
+ catch (InterruptedException ignored)
|
||||
+ {
|
||||
+ }
|
||||
+
|
||||
+ // Check if we've actually hit a state where the server is going to safely shutdown
|
||||
+ // if we have, let the server stop as usual
|
||||
+ if (MinecraftServer.getServer().isStopped()) return;
|
||||
+
|
||||
+ // If the server hasn't stopped by now, assume worse case and kill
|
||||
+ closeSocket();
|
||||
+ System.exit( 0 );
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
+ // Paper - Split from moved code
|
||||
+ private static void closeSocket()
|
||||
+ {
|
||||
+ // Close the socket so we can rebind with the new process
|
||||
+ MinecraftServer.getServer().getConnection().stop();
|
||||
+
|
||||
+ // Give time for it to kick in
|
||||
+ try
|
||||
+ {
|
||||
+ Thread.sleep( 100 );
|
||||
+ } catch ( InterruptedException ex )
|
||||
+ {
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
+ // Paper start - copied from above and modified to return if the hook registered
|
||||
+ private static boolean addShutdownHook(String restartScript)
|
||||
+ {
|
||||
+ String[] split = restartScript.split( " " );
|
||||
+ if ( split.length > 0 && new File( split[0] ).isFile() )
|
||||
+ {
|
||||
+ Thread shutdownHook = new Thread()
|
||||
+ {
|
||||
+ @Override
|
||||
+ public void run()
|
||||
{
|
||||
- @Override
|
||||
- public void run()
|
||||
+ try
|
||||
{
|
||||
- try
|
||||
+ String os = System.getProperty( "os.name" ).toLowerCase(java.util.Locale.ENGLISH);
|
||||
+ if ( os.contains( "win" ) )
|
||||
{
|
||||
- String os = System.getProperty( "os.name" ).toLowerCase(java.util.Locale.ENGLISH);
|
||||
- if ( os.contains( "win" ) )
|
||||
- {
|
||||
- Runtime.getRuntime().exec( "cmd /c start " + restartScript );
|
||||
- } else
|
||||
- {
|
||||
- Runtime.getRuntime().exec( "sh " + restartScript );
|
||||
- }
|
||||
- } catch ( Exception e )
|
||||
+ Runtime.getRuntime().exec( "cmd /c start " + restartScript );
|
||||
+ } else
|
||||
{
|
||||
- e.printStackTrace();
|
||||
+ Runtime.getRuntime().exec( "sh " + restartScript );
|
||||
}
|
||||
+ } catch ( Exception e )
|
||||
+ {
|
||||
+ e.printStackTrace();
|
||||
}
|
||||
- };
|
||||
-
|
||||
- shutdownHook.setDaemon( true );
|
||||
- Runtime.getRuntime().addShutdownHook( shutdownHook );
|
||||
- } else
|
||||
- {
|
||||
- System.out.println( "Startup script '" + SpigotConfig.restartScript + "' does not exist! Stopping server." );
|
||||
-
|
||||
- // Actually shutdown
|
||||
- try
|
||||
- {
|
||||
- MinecraftServer.getServer().close();
|
||||
- } catch ( Throwable t )
|
||||
- {
|
||||
}
|
||||
- }
|
||||
- System.exit( 0 );
|
||||
- } catch ( Exception ex )
|
||||
+ };
|
||||
+
|
||||
+ shutdownHook.setDaemon( true );
|
||||
+ Runtime.getRuntime().addShutdownHook( shutdownHook );
|
||||
+ return true;
|
||||
+ } else
|
||||
{
|
||||
- ex.printStackTrace();
|
||||
+ return false;
|
||||
}
|
||||
}
|
||||
+ // Paper end
|
||||
+
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach.brown@destroystokyo.com>
|
||||
Date: Tue, 16 May 2017 21:29:08 -0500
|
||||
Subject: [PATCH] Add option to make parrots stay on shoulders despite movement
|
||||
|
||||
Makes parrots not fall off whenever the player changes height, or touches water, or gets hit by a passing leaf.
|
||||
Instead, switches the behavior so that players have to sneak to make the birds leave.
|
||||
|
||||
I suspect Mojang may switch to this behavior before full release.
|
||||
|
||||
To be converted into a Paper-API event at some point in the future?
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.entity.player.Player removeEntitiesOnShoulder()V
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 6282cebfa3786c9ac72fcebeee1b8c4cdf5d7238..5a8008b507b93768526184ddaca170bccb67f92a 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -2464,6 +2464,13 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
||||
switch (packet.getAction()) {
|
||||
case PRESS_SHIFT_KEY:
|
||||
this.player.setShiftKeyDown(true);
|
||||
+
|
||||
+ // Paper start - Hang on!
|
||||
+ if (this.player.level.paperConfig().entities.behavior.parrotsAreUnaffectedByPlayerMovement) {
|
||||
+ this.player.removeEntitiesOnShoulder();
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
break;
|
||||
case RELEASE_SHIFT_KEY:
|
||||
this.player.setShiftKeyDown(false);
|
||||
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 845e52baf57492cfb0eb20318c84585e30001f0b..d68ad0bc89565d207f46b106bacce8e6efc890dc 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
@@ -588,7 +588,7 @@ public abstract class Player extends LivingEntity {
|
||||
this.playShoulderEntityAmbientSound(this.getShoulderEntityLeft());
|
||||
this.playShoulderEntityAmbientSound(this.getShoulderEntityRight());
|
||||
if (!this.level.isClientSide && (this.fallDistance > 0.5F || this.isInWater()) || this.abilities.flying || this.isSleeping() || this.isInPowderSnow) {
|
||||
- this.removeEntitiesOnShoulder();
|
||||
+ if (!this.level.paperConfig().entities.behavior.parrotsAreUnaffectedByPlayerMovement) this.removeEntitiesOnShoulder(); // Paper - Hang on!
|
||||
}
|
||||
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: kashike <kashike@vq.lc>
|
||||
Date: Fri, 9 Jun 2017 07:24:34 -0700
|
||||
Subject: [PATCH] Add configuration option to prevent player names from being
|
||||
suggested
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index 8072e45c656e8de0f9061360d353675554ae0182..a458cf93af182e2b6b7c7ef89a4a7fe7f64f7be5 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -2582,5 +2582,10 @@ public final class CraftServer implements Server {
|
||||
commandMap.registerServerAliases();
|
||||
return true;
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean suggestPlayerNamesWhenNullTabCompletions() {
|
||||
+ return io.papermc.paper.configuration.GlobalConfiguration.get().commands.suggestPlayerNamesWhenNullTabCompletions;
|
||||
+ }
|
||||
// Paper end
|
||||
}
|
|
@ -1,518 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Minecrell <minecrell@minecrell.net>
|
||||
Date: Fri, 9 Jun 2017 19:03:43 +0200
|
||||
Subject: [PATCH] Use TerminalConsoleAppender for console improvements
|
||||
|
||||
Rewrite console improvements (console colors, tab completion,
|
||||
persistent input line, ...) using JLine 3.x and TerminalConsoleAppender.
|
||||
|
||||
New features:
|
||||
- Support console colors for Vanilla commands
|
||||
- Add console colors for warnings and errors
|
||||
- Server can now be turned off safely using CTRL + C. JLine catches
|
||||
the signal and the implementation shuts down the server cleanly.
|
||||
- Support console colors and persistent input line when running in
|
||||
IntelliJ IDEA
|
||||
|
||||
Other changes:
|
||||
- Server starts 1-2 seconds faster thanks to optimizations in Log4j
|
||||
configuration
|
||||
|
||||
diff --git a/build.gradle.kts b/build.gradle.kts
|
||||
index cfdb20447e6ad3efcdee8889712f77931773beaf..d4141a24cb5ba20e8c53c85206b32120ff18eb48 100644
|
||||
--- a/build.gradle.kts
|
||||
+++ b/build.gradle.kts
|
||||
@@ -8,7 +8,17 @@ plugins {
|
||||
|
||||
dependencies {
|
||||
implementation(project(":paper-api"))
|
||||
- implementation("jline:jline:2.12.1")
|
||||
+ // Paper start
|
||||
+ implementation("org.jline:jline-terminal-jansi:3.21.0")
|
||||
+ implementation("net.minecrell:terminalconsoleappender:1.3.0")
|
||||
+ /*
|
||||
+ Required to add the missing Log4j2Plugins.dat file from log4j-core
|
||||
+ which has been removed by Mojang. Without it, log4j has to classload
|
||||
+ all its classes to check if they are plugins.
|
||||
+ Scanning takes about 1-2 seconds so adding this speeds up the server start.
|
||||
+ */
|
||||
+ runtimeOnly("org.apache.logging.log4j:log4j-core:2.14.1")
|
||||
+ // Paper end
|
||||
implementation("org.apache.logging.log4j:log4j-iostreams:2.17.1") // Paper
|
||||
implementation("org.ow2.asm:asm:9.3")
|
||||
implementation("org.ow2.asm:asm-commons:9.3") // Paper - ASM event executor generation
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..a4070b59e261f0f1ac4beec47b11492f4724bf27
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java
|
||||
@@ -0,0 +1,41 @@
|
||||
+package com.destroystokyo.paper.console;
|
||||
+
|
||||
+import net.minecraft.server.dedicated.DedicatedServer;
|
||||
+import net.minecrell.terminalconsole.SimpleTerminalConsole;
|
||||
+import org.bukkit.craftbukkit.command.ConsoleCommandCompleter;
|
||||
+import org.jline.reader.LineReader;
|
||||
+import org.jline.reader.LineReaderBuilder;
|
||||
+
|
||||
+public final class PaperConsole extends SimpleTerminalConsole {
|
||||
+
|
||||
+ private final DedicatedServer server;
|
||||
+
|
||||
+ public PaperConsole(DedicatedServer server) {
|
||||
+ this.server = server;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ protected LineReader buildReader(LineReaderBuilder builder) {
|
||||
+ return super.buildReader(builder
|
||||
+ .appName("Paper")
|
||||
+ .variable(LineReader.HISTORY_FILE, java.nio.file.Paths.get(".console_history"))
|
||||
+ .completer(new ConsoleCommandCompleter(this.server))
|
||||
+ );
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ protected boolean isRunning() {
|
||||
+ return !this.server.isStopped() && this.server.isRunning();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ protected void runCommand(String command) {
|
||||
+ this.server.handleConsoleInput(command, this.server.createCommandSourceStack());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ protected void shutdown() {
|
||||
+ this.server.halt(false);
|
||||
+ }
|
||||
+
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java b/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..685deaa0e5d1ddc13e3a7c0471b1cfcf1710c869
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java
|
||||
@@ -0,0 +1,17 @@
|
||||
+package com.destroystokyo.paper.console;
|
||||
+
|
||||
+import org.apache.logging.log4j.LogManager;
|
||||
+import org.apache.logging.log4j.Logger;
|
||||
+import org.bukkit.craftbukkit.command.CraftConsoleCommandSender;
|
||||
+
|
||||
+public class TerminalConsoleCommandSender extends CraftConsoleCommandSender {
|
||||
+
|
||||
+ private static final Logger LOGGER = LogManager.getRootLogger();
|
||||
+
|
||||
+ @Override
|
||||
+ public void sendRawMessage(String message) {
|
||||
+ // TerminalConsoleAppender supports color codes directly in log messages
|
||||
+ LOGGER.info(message);
|
||||
+ }
|
||||
+
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index f852c1315cf9dcba56f5877063254d4c608abd61..b404a222e741064185269a42a102d3e4c1f481d7 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -156,7 +156,7 @@ import org.slf4j.Logger;
|
||||
import com.mojang.serialization.DynamicOps;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import java.util.Random;
|
||||
-import jline.console.ConsoleReader;
|
||||
+// import jline.console.ConsoleReader; // Paper
|
||||
import joptsimple.OptionSet;
|
||||
import net.minecraft.server.bossevents.CustomBossEvents;
|
||||
import net.minecraft.server.dedicated.DedicatedServer;
|
||||
@@ -271,7 +271,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
public OptionSet options;
|
||||
public org.bukkit.command.ConsoleCommandSender console;
|
||||
public org.bukkit.command.RemoteConsoleCommandSender remoteConsole;
|
||||
- public ConsoleReader reader;
|
||||
+ //public ConsoleReader reader; // Paper
|
||||
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;
|
||||
@@ -355,7 +355,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
this.datapackconfiguration = datapackconfiguration;
|
||||
this.registryreadops = registryreadops;
|
||||
this.vanillaCommandDispatcher = worldstem.dataPackResources().commands; // CraftBukkit
|
||||
+ // Paper start - Handled by TerminalConsoleAppender
|
||||
// Try to see if we're actually running in a terminal, disable jline if not
|
||||
+ /*
|
||||
if (System.console() == null && System.getProperty("jline.terminal") == null) {
|
||||
System.setProperty("jline.terminal", "jline.UnsupportedTerminal");
|
||||
Main.useJline = false;
|
||||
@@ -376,6 +378,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
MinecraftServer.LOGGER.warn((String) null, ex);
|
||||
}
|
||||
}
|
||||
+ */
|
||||
+ // Paper end
|
||||
Runtime.getRuntime().addShutdownHook(new org.bukkit.craftbukkit.util.ServerShutdownThread(this));
|
||||
this.paperConfigurations = services.paperConfigurations(); // Paper
|
||||
}
|
||||
@@ -1129,7 +1133,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
org.spigotmc.WatchdogThread.doStop(); // Spigot
|
||||
// CraftBukkit start - Restore terminal to original settings
|
||||
try {
|
||||
- this.reader.getTerminal().restore();
|
||||
+ net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Use TerminalConsoleAppender
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
// CraftBukkit end
|
||||
@@ -1564,7 +1568,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
|
||||
@Override
|
||||
public void sendSystemMessage(Component message) {
|
||||
- MinecraftServer.LOGGER.info(message.getString());
|
||||
+ MinecraftServer.LOGGER.info(net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(io.papermc.paper.adventure.PaperAdventure.asAdventure(message))); // Paper - Log message with colors
|
||||
}
|
||||
|
||||
public KeyPair getKeyPair() {
|
||||
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
index f3c65b5f4a0cc3bc0004cc6f8cc974a87a1123bb..bada827fe2a8a58d029d9459bf576d598e4a196f 100644
|
||||
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
@@ -103,6 +103,9 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||
if (!org.bukkit.craftbukkit.Main.useConsole) {
|
||||
return;
|
||||
}
|
||||
+ // Paper start - Use TerminalConsoleAppender
|
||||
+ new com.destroystokyo.paper.console.PaperConsole(DedicatedServer.this).start();
|
||||
+ /*
|
||||
jline.console.ConsoleReader bufferedreader = reader;
|
||||
|
||||
// MC-33041, SPIGOT-5538: if System.in is not valid due to javaw, then return
|
||||
@@ -134,7 +137,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||
continue;
|
||||
}
|
||||
if (s.trim().length() > 0) { // Trim to filter lines which are just spaces
|
||||
- DedicatedServer.this.handleConsoleInput(s, DedicatedServer.this.createCommandSourceStack());
|
||||
+ DedicatedServer.this.issueCommand(s, DedicatedServer.this.getServerCommandListener());
|
||||
}
|
||||
// CraftBukkit end
|
||||
}
|
||||
@@ -142,6 +145,8 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||
DedicatedServer.LOGGER.error("Exception handling console input", ioexception);
|
||||
}
|
||||
|
||||
+ */
|
||||
+ // Paper end
|
||||
}
|
||||
};
|
||||
|
||||
@@ -153,6 +158,9 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||
}
|
||||
global.addHandler(new org.bukkit.craftbukkit.util.ForwardLogHandler());
|
||||
|
||||
+ // Paper start - Not needed with TerminalConsoleAppender
|
||||
+ final org.apache.logging.log4j.Logger logger = LogManager.getRootLogger();
|
||||
+ /*
|
||||
final org.apache.logging.log4j.core.Logger logger = ((org.apache.logging.log4j.core.Logger) LogManager.getRootLogger());
|
||||
for (org.apache.logging.log4j.core.Appender appender : logger.getAppenders().values()) {
|
||||
if (appender instanceof org.apache.logging.log4j.core.appender.ConsoleAppender) {
|
||||
@@ -161,6 +169,8 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||
}
|
||||
|
||||
new org.bukkit.craftbukkit.util.TerminalConsoleWriterThread(System.out, this.reader).start();
|
||||
+ */
|
||||
+ // Paper end
|
||||
|
||||
System.setOut(IoBuilder.forLogger(logger).setLevel(Level.INFO).buildPrintStream());
|
||||
System.setErr(IoBuilder.forLogger(logger).setLevel(Level.WARN).buildPrintStream());
|
||||
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
index dbc8f0b962371902fc5e84f1171046d794eb1367..4f47a48aad54bec10fa8d79be2e6401cd8166591 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
@@ -160,8 +160,7 @@ public abstract class PlayerList {
|
||||
|
||||
public PlayerList(MinecraftServer server, RegistryAccess.Frozen registryManager, PlayerDataStorage saveHandler, int maxPlayers) {
|
||||
this.cserver = server.server = new CraftServer((DedicatedServer) server, this);
|
||||
- server.console = org.bukkit.craftbukkit.command.ColouredConsoleSender.getInstance();
|
||||
- server.reader.addCompleter(new org.bukkit.craftbukkit.command.ConsoleCommandCompleter(server.server));
|
||||
+ server.console = new com.destroystokyo.paper.console.TerminalConsoleCommandSender(); // Paper
|
||||
// CraftBukkit end
|
||||
|
||||
this.bans = new UserBanList(PlayerList.USERBANLIST_FILE);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index a458cf93af182e2b6b7c7ef89a4a7fe7f64f7be5..eb7dd4143f545ab93e55ffac7f3322ce676dfb92 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -45,7 +45,6 @@ import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.imageio.ImageIO;
|
||||
-import jline.console.ConsoleReader;
|
||||
import net.minecraft.advancements.Advancement;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
@@ -1276,9 +1275,13 @@ public final class CraftServer implements Server {
|
||||
return this.logger;
|
||||
}
|
||||
|
||||
+ // Paper start - JLine update
|
||||
+ /*
|
||||
public ConsoleReader getReader() {
|
||||
return console.reader;
|
||||
}
|
||||
+ */
|
||||
+ // Paper end
|
||||
|
||||
@Override
|
||||
public PluginCommand getPluginCommand(String name) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
index e15375f6985f841ca42dd41eb0035aab0b64a9fb..5cae8fdd1ad63f49580d69a8c337ae22c0923c5c 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
@@ -12,7 +12,7 @@ import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import joptsimple.OptionParser;
|
||||
import joptsimple.OptionSet;
|
||||
-import org.fusesource.jansi.AnsiConsole;
|
||||
+import net.minecrell.terminalconsole.TerminalConsoleAppender; // Paper
|
||||
|
||||
public class Main {
|
||||
public static boolean useJline = true;
|
||||
@@ -202,6 +202,8 @@ public class Main {
|
||||
}
|
||||
|
||||
try {
|
||||
+ // Paper start - Handled by TerminalConsoleAppender
|
||||
+ /*
|
||||
// This trick bypasses Maven Shade's clever rewriting of our getProperty call when using String literals
|
||||
String jline_UnsupportedTerminal = new String(new char[]{'j', 'l', 'i', 'n', 'e', '.', 'U', 'n', 's', 'u', 'p', 'p', 'o', 'r', 't', 'e', 'd', 'T', 'e', 'r', 'm', 'i', 'n', 'a', 'l'});
|
||||
String jline_terminal = new String(new char[]{'j', 'l', 'i', 'n', 'e', '.', 't', 'e', 'r', 'm', 'i', 'n', 'a', 'l'});
|
||||
@@ -219,9 +221,18 @@ public class Main {
|
||||
// This ensures the terminal literal will always match the jline implementation
|
||||
System.setProperty(jline.TerminalFactory.JLINE_TERMINAL, jline.UnsupportedTerminal.class.getName());
|
||||
}
|
||||
+ */
|
||||
+
|
||||
+ if (options.has("nojline")) {
|
||||
+ System.setProperty(TerminalConsoleAppender.JLINE_OVERRIDE_PROPERTY, "false");
|
||||
+ useJline = false;
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
if (options.has("noconsole")) {
|
||||
Main.useConsole = false;
|
||||
+ useJline = false; // Paper
|
||||
+ System.setProperty(TerminalConsoleAppender.JLINE_OVERRIDE_PROPERTY, "false"); // Paper
|
||||
}
|
||||
|
||||
if (Main.class.getPackage().getImplementationVendor() != null && System.getProperty("IReallyKnowWhatIAmDoingISwear") == null) {
|
||||
@@ -249,7 +260,7 @@ public class Main {
|
||||
System.out.println("Unable to read system info");
|
||||
}
|
||||
// Paper end
|
||||
-
|
||||
+ System.setProperty( "library.jansi.version", "Paper" ); // Paper - set meaningless jansi version to prevent git builds from crashing on Windows
|
||||
System.out.println("Loading libraries, please wait...");
|
||||
net.minecraft.server.Main.main(options);
|
||||
} catch (Throwable t) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/command/ColouredConsoleSender.java b/src/main/java/org/bukkit/craftbukkit/command/ColouredConsoleSender.java
|
||||
index 76fb1ecd47cb86b50486effe8cc7fe4abf8e311c..21f889ddec72b40f5954eec07417e08d192b4661 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/command/ColouredConsoleSender.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/command/ColouredConsoleSender.java
|
||||
@@ -5,15 +5,13 @@ import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
-import jline.Terminal;
|
||||
+//import jline.Terminal;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.craftbukkit.CraftServer;
|
||||
-import org.fusesource.jansi.Ansi;
|
||||
-import org.fusesource.jansi.Ansi.Attribute;
|
||||
|
||||
-public class ColouredConsoleSender extends CraftConsoleCommandSender {
|
||||
+public class ColouredConsoleSender /*extends CraftConsoleCommandSender */{/* // Paper - disable
|
||||
private final Terminal terminal;
|
||||
private final Map<ChatColor, String> replacements = new EnumMap<ChatColor, String>(ChatColor.class);
|
||||
private final ChatColor[] colors = ChatColor.values();
|
||||
@@ -93,5 +91,5 @@ public class ColouredConsoleSender extends CraftConsoleCommandSender {
|
||||
} else {
|
||||
return new ColouredConsoleSender();
|
||||
}
|
||||
- }
|
||||
+ }*/ // Paper
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java
|
||||
index 0b4c62387c1093652ac15b64a8703249de4cf088..b996fde481cebbbcce80a6c267591136db7cc0bc 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java
|
||||
@@ -4,50 +4,73 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.logging.Level;
|
||||
-import jline.console.completer.Completer;
|
||||
+import net.minecraft.server.dedicated.DedicatedServer;
|
||||
import org.bukkit.craftbukkit.CraftServer;
|
||||
import org.bukkit.craftbukkit.util.Waitable;
|
||||
+
|
||||
+// Paper start - JLine update
|
||||
+import org.jline.reader.Candidate;
|
||||
+import org.jline.reader.Completer;
|
||||
+import org.jline.reader.LineReader;
|
||||
+import org.jline.reader.ParsedLine;
|
||||
+// Paper end
|
||||
import org.bukkit.event.server.TabCompleteEvent;
|
||||
|
||||
public class ConsoleCommandCompleter implements Completer {
|
||||
- private final CraftServer server;
|
||||
+ private final DedicatedServer server; // Paper - CraftServer -> DedicatedServer
|
||||
|
||||
- public ConsoleCommandCompleter(CraftServer server) {
|
||||
+ public ConsoleCommandCompleter(DedicatedServer server) { // Paper - CraftServer -> DedicatedServer
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
+ // Paper start - Change method signature for JLine update
|
||||
@Override
|
||||
- public int complete(final String buffer, final int cursor, final List<CharSequence> candidates) {
|
||||
+ public void complete(LineReader reader, ParsedLine line, List<Candidate> candidates) {
|
||||
+ final CraftServer server = this.server.server;
|
||||
+ final String buffer = line.line();
|
||||
+ // Paper end
|
||||
Waitable<List<String>> waitable = new Waitable<List<String>>() {
|
||||
@Override
|
||||
protected List<String> evaluate() {
|
||||
- List<String> offers = ConsoleCommandCompleter.this.server.getCommandMap().tabComplete(ConsoleCommandCompleter.this.server.getConsoleSender(), buffer);
|
||||
+ List<String> offers = server.getCommandMap().tabComplete(server.getConsoleSender(), buffer); // Paper - fix remap
|
||||
|
||||
- TabCompleteEvent tabEvent = new TabCompleteEvent(ConsoleCommandCompleter.this.server.getConsoleSender(), buffer, (offers == null) ? Collections.EMPTY_LIST : offers);
|
||||
- ConsoleCommandCompleter.this.server.getPluginManager().callEvent(tabEvent);
|
||||
+ TabCompleteEvent tabEvent = new TabCompleteEvent(server.getConsoleSender(), buffer, (offers == null) ? Collections.EMPTY_LIST : offers); // Paper - fix remap
|
||||
+ server.getPluginManager().callEvent(tabEvent); // Paper - fix remap
|
||||
|
||||
return tabEvent.isCancelled() ? Collections.EMPTY_LIST : tabEvent.getCompletions();
|
||||
}
|
||||
};
|
||||
- this.server.getServer().processQueue.add(waitable);
|
||||
+ server.getServer().processQueue.add(waitable); // Paper - Remove "this."
|
||||
try {
|
||||
List<String> offers = waitable.get();
|
||||
if (offers == null) {
|
||||
- return cursor;
|
||||
+ return; // Paper - Method returns void
|
||||
+ }
|
||||
+
|
||||
+ // Paper start - JLine update
|
||||
+ for (String completion : offers) {
|
||||
+ if (completion.isEmpty()) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ candidates.add(new Candidate(completion));
|
||||
}
|
||||
- candidates.addAll(offers);
|
||||
+ // Paper end
|
||||
|
||||
+ // Paper start - JLine handles cursor now
|
||||
+ /*
|
||||
final int lastSpace = buffer.lastIndexOf(' ');
|
||||
if (lastSpace == -1) {
|
||||
return cursor - buffer.length();
|
||||
} else {
|
||||
return cursor - (buffer.length() - lastSpace - 1);
|
||||
}
|
||||
+ */
|
||||
+ // Paper end
|
||||
} catch (ExecutionException e) {
|
||||
- this.server.getLogger().log(Level.WARNING, "Unhandled exception when tab completing", e);
|
||||
+ server.getLogger().log(Level.WARNING, "Unhandled exception when tab completing", e); // Paper - Remove "this."
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
- return cursor;
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java
|
||||
index 6a073a9dc44d93eba296a0e18a9c7be8a7881725..b4a19d80bbf71591f25729fd0e98590350cb31d0 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java
|
||||
@@ -17,7 +17,7 @@ public class ServerShutdownThread extends Thread {
|
||||
this.server.close();
|
||||
} finally {
|
||||
try {
|
||||
- server.reader.getTerminal().restore();
|
||||
+ net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Use TerminalConsoleAppender
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java b/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java
|
||||
index 1d8b279f3cbe6fde6bb1bfc4985c4133b0d4a95d..cdc52bbe5c6ae4688615a7732b10071f7f51718e 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java
|
||||
@@ -5,12 +5,12 @@ import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
-import jline.console.ConsoleReader;
|
||||
+//import jline.console.ConsoleReader;
|
||||
import org.bukkit.craftbukkit.Main;
|
||||
-import org.fusesource.jansi.Ansi;
|
||||
-import org.fusesource.jansi.Ansi.Erase;
|
||||
+//import org.fusesource.jansi.Ansi;
|
||||
+//import org.fusesource.jansi.Ansi.Erase;
|
||||
|
||||
-public class TerminalConsoleWriterThread extends Thread {
|
||||
+public class TerminalConsoleWriterThread /*extends Thread*/ {/* // Paper - disable
|
||||
private final ConsoleReader reader;
|
||||
private final OutputStream output;
|
||||
|
||||
@@ -54,5 +54,5 @@ public class TerminalConsoleWriterThread extends Thread {
|
||||
Logger.getLogger(TerminalConsoleWriterThread.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
- }
|
||||
+ }*/
|
||||
}
|
||||
diff --git a/src/main/resources/log4j2.component.properties b/src/main/resources/log4j2.component.properties
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0694b21465fb9e4164e71862ff24b62241b191f2
|
||||
--- /dev/null
|
||||
+++ b/src/main/resources/log4j2.component.properties
|
||||
@@ -0,0 +1 @@
|
||||
+log4j.skipJansi=true
|
||||
diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml
|
||||
index 722ca84968cbbbdeffd09939abff0cccd0a84010..620b9490e5f159080e50289d127404a1b56adbef 100644
|
||||
--- a/src/main/resources/log4j2.xml
|
||||
+++ b/src/main/resources/log4j2.xml
|
||||
@@ -1,17 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Configuration status="WARN" packages="com.mojang.util">
|
||||
<Appenders>
|
||||
- <Console name="SysOut" target="SYSTEM_OUT">
|
||||
- <PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level]: %msg%n" />
|
||||
- </Console>
|
||||
<Queue name="ServerGuiConsole">
|
||||
<PatternLayout pattern="[%d{HH:mm:ss} %level]: %msg%n" />
|
||||
</Queue>
|
||||
- <Queue name="TerminalConsole">
|
||||
- <PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level]: %msg%n" />
|
||||
- </Queue>
|
||||
+ <TerminalConsole name="TerminalConsole">
|
||||
+ <PatternLayout pattern="%highlightError{[%d{HH:mm:ss} %level]: %minecraftFormatting{%msg}%n%xEx}" />
|
||||
+ </TerminalConsole>
|
||||
<RollingRandomAccessFile name="File" fileName="logs/latest.log" filePattern="logs/%d{yyyy-MM-dd}-%i.log.gz">
|
||||
- <PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level]: %msg%n" />
|
||||
+ <PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level]: %minecraftFormatting{%msg}{strip}%n" />
|
||||
<Policies>
|
||||
<TimeBasedTriggeringPolicy />
|
||||
<OnStartupTriggeringPolicy />
|
||||
@@ -24,10 +21,9 @@
|
||||
<filters>
|
||||
<MarkerFilter marker="NETWORK_PACKETS" onMatch="DENY" onMismatch="NEUTRAL" />
|
||||
</filters>
|
||||
- <AppenderRef ref="SysOut" level="info"/>
|
||||
<AppenderRef ref="File"/>
|
||||
- <AppenderRef ref="ServerGuiConsole" level="info"/>
|
||||
<AppenderRef ref="TerminalConsole" level="info"/>
|
||||
+ <AppenderRef ref="ServerGuiConsole" level="info"/>
|
||||
</Root>
|
||||
</Loggers>
|
||||
</Configuration>
|
|
@ -1,20 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Sun, 11 Jun 2017 21:01:18 +0100
|
||||
Subject: [PATCH] provide a configurable option to disable creeper lingering
|
||||
effect spawns
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/Creeper.java b/src/main/java/net/minecraft/world/entity/monster/Creeper.java
|
||||
index 7a5eea3a2eaff5e08589fc240307da2beb44c307..441eee3d3a639b8eccc4369de0d9e3e7d28bac27 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Creeper.java
|
||||
@@ -281,7 +281,7 @@ public class Creeper extends Monster implements PowerableMob {
|
||||
private void spawnLingeringCloud() {
|
||||
Collection<MobEffectInstance> collection = this.getActiveEffects();
|
||||
|
||||
- if (!collection.isEmpty()) {
|
||||
+ if (!collection.isEmpty() && !level.paperConfig().entities.behavior.disableCreeperLingeringEffect) { // Paper
|
||||
AreaEffectCloud entityareaeffectcloud = new AreaEffectCloud(this.level, this.getX(), this.getY(), this.getZ());
|
||||
|
||||
entityareaeffectcloud.setOwner(this); // CraftBukkit
|
|
@ -1,57 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Fri, 5 May 2017 03:57:17 -0500
|
||||
Subject: [PATCH] Item#canEntityPickup
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java
|
||||
index d315d9e0e6724e210924ec5814545e8c52ba2d8b..4f3d3bb811ea767bbcc4327eeefcdc6d58ed5230 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Mob.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Mob.java
|
||||
@@ -635,6 +635,11 @@ public abstract class Mob extends LivingEntity {
|
||||
ItemEntity entityitem = (ItemEntity) iterator.next();
|
||||
|
||||
if (!entityitem.isRemoved() && !entityitem.getItem().isEmpty() && !entityitem.hasPickUpDelay() && this.wantsToPickUp(entityitem.getItem())) {
|
||||
+ // Paper Start
|
||||
+ if (!entityitem.canMobPickup) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ // Paper End
|
||||
this.pickUpItem(entityitem);
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
|
||||
index a938d75e229ce77973182c9dd25c995a16ef17f6..581725ab12f6bea1216dbf62d5cf3923d4340844 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
|
||||
@@ -52,6 +52,7 @@ public class ItemEntity extends Entity {
|
||||
private UUID owner;
|
||||
public final float bobOffs;
|
||||
private int lastTick = MinecraftServer.currentTick - 1; // CraftBukkit
|
||||
+ public boolean canMobPickup = true; // Paper
|
||||
|
||||
public ItemEntity(EntityType<? extends ItemEntity> type, Level world) {
|
||||
super(type, world);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java
|
||||
index 4ca76a7530f8679567d887cdf1491d110e7465ec..30c954efba587d69ff55df509339f03e7d5a476e 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java
|
||||
@@ -66,6 +66,18 @@ public class CraftItem extends CraftEntity implements Item {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper Start
|
||||
+ @Override
|
||||
+ public boolean canMobPickup() {
|
||||
+ return item.canMobPickup;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setCanMobPickup(boolean canMobPickup) {
|
||||
+ item.canMobPickup = canMobPickup;
|
||||
+ }
|
||||
+ // Paper End
|
||||
+
|
||||
@Override
|
||||
public void setOwner(UUID uuid) {
|
||||
this.item.setOwner(uuid);
|
|
@ -1,46 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Sun, 7 May 2017 06:26:09 -0500
|
||||
Subject: [PATCH] PlayerPickupItemEvent#setFlyAtPlayer
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
|
||||
index 581725ab12f6bea1216dbf62d5cf3923d4340844..bd78031511b8c7facc3f61f3a23cbf4264fa2d0c 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
|
||||
@@ -388,6 +388,7 @@ public class ItemEntity extends Entity {
|
||||
// CraftBukkit start - fire PlayerPickupItemEvent
|
||||
int canHold = player.getInventory().canHold(itemstack);
|
||||
int remaining = i - canHold;
|
||||
+ boolean flyAtPlayer = false; // Paper
|
||||
|
||||
if (this.pickupDelay <= 0 && canHold > 0) {
|
||||
itemstack.setCount(canHold);
|
||||
@@ -395,8 +396,14 @@ public class ItemEntity extends Entity {
|
||||
PlayerPickupItemEvent playerEvent = new PlayerPickupItemEvent((org.bukkit.entity.Player) player.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining);
|
||||
playerEvent.setCancelled(!playerEvent.getPlayer().getCanPickupItems());
|
||||
this.level.getCraftServer().getPluginManager().callEvent(playerEvent);
|
||||
+ flyAtPlayer = playerEvent.getFlyAtPlayer(); // Paper
|
||||
if (playerEvent.isCancelled()) {
|
||||
itemstack.setCount(i); // SPIGOT-5294 - restore count
|
||||
+ // Paper Start
|
||||
+ if (flyAtPlayer) {
|
||||
+ player.take(this, i);
|
||||
+ }
|
||||
+ // Paper End
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -426,7 +433,11 @@ public class ItemEntity extends Entity {
|
||||
// CraftBukkit end
|
||||
|
||||
if (this.pickupDelay == 0 && (this.owner == null || this.owner.equals(player.getUUID())) && player.getInventory().add(itemstack)) {
|
||||
- player.take(this, i);
|
||||
+ // Paper Start
|
||||
+ if (flyAtPlayer) {
|
||||
+ player.take(this, i);
|
||||
+ }
|
||||
+ // Paper End
|
||||
if (itemstack.isEmpty()) {
|
||||
this.discard();
|
||||
itemstack.setCount(i);
|
|
@ -1,41 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Sun, 11 Jun 2017 16:30:30 -0500
|
||||
Subject: [PATCH] PlayerAttemptPickupItemEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
|
||||
index bd78031511b8c7facc3f61f3a23cbf4264fa2d0c..6ecab1dd5932c4c346cde987cb9463b00a32d385 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
|
||||
@@ -36,6 +36,7 @@ import net.minecraft.util.Mth;
|
||||
import org.bukkit.event.entity.EntityPickupItemEvent;
|
||||
import org.bukkit.event.player.PlayerPickupItemEvent;
|
||||
// CraftBukkit end
|
||||
+import org.bukkit.event.player.PlayerAttemptPickupItemEvent; // Paper
|
||||
|
||||
public class ItemEntity extends Entity {
|
||||
|
||||
@@ -390,6 +391,22 @@ public class ItemEntity extends Entity {
|
||||
int remaining = i - canHold;
|
||||
boolean flyAtPlayer = false; // Paper
|
||||
|
||||
+ // Paper start
|
||||
+ if (this.pickupDelay <= 0) {
|
||||
+ PlayerAttemptPickupItemEvent attemptEvent = new PlayerAttemptPickupItemEvent((org.bukkit.entity.Player) player.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining);
|
||||
+ this.level.getCraftServer().getPluginManager().callEvent(attemptEvent);
|
||||
+
|
||||
+ flyAtPlayer = attemptEvent.getFlyAtPlayer();
|
||||
+ if (attemptEvent.isCancelled()) {
|
||||
+ if (flyAtPlayer) {
|
||||
+ player.take(this, i);
|
||||
+ }
|
||||
+
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
if (this.pickupDelay <= 0 && canHold > 0) {
|
||||
itemstack.setCount(canHold);
|
||||
// Call legacy event
|
|
@ -1,77 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Sun, 8 Aug 2021 16:26:46 -0700
|
||||
Subject: [PATCH] Do not submit profile lookups to worldgen threads
|
||||
|
||||
They block. On network I/O.
|
||||
|
||||
If enough tasks are submitted the server will eventually stall
|
||||
out due to a sync load, as the worldgen threads will be
|
||||
stalling on profile lookups.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java
|
||||
index 168ab805ecc48dd55db90eb7fe1c56fda3f2776c..336a26733b5bf73455f8ec10347c1e08b8e866f7 100644
|
||||
--- a/src/main/java/net/minecraft/Util.java
|
||||
+++ b/src/main/java/net/minecraft/Util.java
|
||||
@@ -81,6 +81,22 @@ public class Util {
|
||||
private static final AtomicInteger WORKER_COUNT = new AtomicInteger(1);
|
||||
private static final ExecutorService BOOTSTRAP_EXECUTOR = makeExecutor("Bootstrap");
|
||||
private static final ExecutorService BACKGROUND_EXECUTOR = makeExecutor("Main");
|
||||
+ // Paper start - don't submit BLOCKING PROFILE LOOKUPS to the world gen thread
|
||||
+ public static final ExecutorService PROFILE_EXECUTOR = Executors.newFixedThreadPool(2, new java.util.concurrent.ThreadFactory() {
|
||||
+
|
||||
+ private final AtomicInteger count = new AtomicInteger();
|
||||
+
|
||||
+ @Override
|
||||
+ public Thread newThread(Runnable run) {
|
||||
+ Thread ret = new Thread(run);
|
||||
+ ret.setName("Profile Lookup Executor #" + this.count.getAndIncrement());
|
||||
+ ret.setUncaughtExceptionHandler((Thread thread, Throwable throwable) -> {
|
||||
+ LOGGER.error("Uncaught exception in thread " + thread.getName(), throwable);
|
||||
+ });
|
||||
+ return ret;
|
||||
+ }
|
||||
+ });
|
||||
+ // Paper end - don't submit BLOCKING PROFILE LOOKUPS to the world gen thread
|
||||
private static final ExecutorService IO_POOL = makeIoExecutor();
|
||||
private static final DateTimeFormatter FILENAME_DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss", Locale.ROOT);
|
||||
public static TimeSource.NanoTimeSource timeSource = System::nanoTime;
|
||||
diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java
|
||||
index 58e923f4ef1980bc7fff1e3b3fcdaad8c4eded53..4038bb76339d43f18770624bd7fecc79b8d7f2a9 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/GameProfileCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java
|
||||
@@ -181,7 +181,7 @@ public class GameProfileCache {
|
||||
} else {
|
||||
this.requests.put(username, CompletableFuture.supplyAsync(() -> {
|
||||
return this.get(username);
|
||||
- }, Util.backgroundExecutor()).whenCompleteAsync((optional, throwable) -> {
|
||||
+ }, Util.PROFILE_EXECUTOR).whenCompleteAsync((optional, throwable) -> { // Paper - not a good idea to use BLOCKING OPERATIONS on the worldgen executor
|
||||
this.requests.remove(username);
|
||||
}, this.executor).whenCompleteAsync((optional, throwable) -> {
|
||||
consumer.accept(optional);
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java
|
||||
index 0c7e29b589ab106013d979a20edc415b4b32a677..c5d5d90d10b30f30d1262367b3d75df43fbdb231 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java
|
||||
@@ -120,7 +120,7 @@ public class SkullBlockEntity extends BlockEntity {
|
||||
public static void updateGameprofile(@Nullable GameProfile owner, Consumer<GameProfile> callback) {
|
||||
if (owner != null && !StringUtil.isNullOrEmpty(owner.getName()) && (!owner.isComplete() || !owner.getProperties().containsKey("textures")) && profileCache != null && sessionService != null) {
|
||||
profileCache.getAsync(owner.getName(), (profile) -> {
|
||||
- Util.backgroundExecutor().execute(() -> {
|
||||
+ Util.PROFILE_EXECUTOR.execute(() -> { // Paper - not a good idea to use BLOCKING OPERATIONS on the worldgen executor
|
||||
Util.ifElse(profile, (profilex) -> {
|
||||
Property property = Iterables.getFirst(profilex.getProperties().get("textures"), (Property)null);
|
||||
if (property == null) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java b/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java
|
||||
index 3030c153725415802f68c144e0b577d919307058..3e40d47f504248cd7caeef6b841a8aa6f1976170 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java
|
||||
@@ -121,7 +121,7 @@ public final class CraftPlayerProfile implements PlayerProfile {
|
||||
|
||||
@Override
|
||||
public CompletableFuture<PlayerProfile> update() {
|
||||
- return CompletableFuture.supplyAsync(this::getUpdatedProfile, Util.backgroundExecutor());
|
||||
+ return CompletableFuture.supplyAsync(this::getUpdatedProfile, Util.PROFILE_EXECUTOR); // Paper - not a good idea to use BLOCKING OPERATIONS on the worldgen executor
|
||||
}
|
||||
|
||||
private CraftPlayerProfile getUpdatedProfile() {
|
|
@ -1,25 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Sweepyoface <github@sweepy.pw>
|
||||
Date: Sat, 17 Jun 2017 18:48:21 -0400
|
||||
Subject: [PATCH] Add UnknownCommandEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index eb7dd4143f545ab93e55ffac7f3322ce676dfb92..75b9d496860d7f3a9d5f680cbdfe89860286522e 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -892,7 +892,13 @@ public final class CraftServer implements Server {
|
||||
|
||||
// Spigot start
|
||||
if (!org.spigotmc.SpigotConfig.unknownCommandMessage.isEmpty()) {
|
||||
- sender.sendMessage(org.spigotmc.SpigotConfig.unknownCommandMessage);
|
||||
+ // Paper start
|
||||
+ org.bukkit.event.command.UnknownCommandEvent event = new org.bukkit.event.command.UnknownCommandEvent(sender, commandLine, org.spigotmc.SpigotConfig.unknownCommandMessage);
|
||||
+ Bukkit.getServer().getPluginManager().callEvent(event);
|
||||
+ if (event.message() != null) {
|
||||
+ sender.sendMessage(event.message());
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
// Spigot end
|
||||
|
|
@ -1,770 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 15 Jan 2018 22:11:48 -0500
|
||||
Subject: [PATCH] Basic PlayerProfile API
|
||||
|
||||
Establishes base extension of profile systems for future edits too
|
||||
|
||||
== AT ==
|
||||
public org.bukkit.craftbukkit.profile.CraftProfileProperty
|
||||
public org.bukkit.craftbukkit.profile.CraftPlayerTextures
|
||||
public org.bukkit.craftbukkit.profile.CraftPlayerTextures copyFrom(Lorg/bukkit/profile/PlayerTextures;)V
|
||||
public org.bukkit.craftbukkit.profile.CraftPlayerTextures rebuildPropertyIfDirty()V
|
||||
public org.bukkit.craftbukkit.profile.CraftPlayerProfile toString(Lcom/mojang/authlib/properties/PropertyMap;)Ljava/lang/String;
|
||||
# needed to maintain visibility with overriden methods
|
||||
public org.bukkit.craftbukkit.profile.CraftPlayerProfile getProperty(Ljava/lang/String;)Lcom/mojang/authlib/properties/Property;
|
||||
public org.bukkit.craftbukkit.profile.CraftPlayerProfile setProperty(Ljava/lang/String;Lcom/mojang/authlib/properties/Property;)V
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java b/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..3ff790cec1ad89caec4be64421dd7d51652be598
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java
|
||||
@@ -0,0 +1,399 @@
|
||||
+package com.destroystokyo.paper.profile;
|
||||
+
|
||||
+import io.papermc.paper.configuration.GlobalConfiguration;
|
||||
+import com.google.common.base.Charsets;
|
||||
+import com.google.common.collect.Iterables;
|
||||
+import com.mojang.authlib.GameProfile;
|
||||
+import com.mojang.authlib.properties.Property;
|
||||
+import com.mojang.authlib.properties.PropertyMap;
|
||||
+import net.minecraft.Util;
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
+import net.minecraft.server.players.GameProfileCache;
|
||||
+import org.apache.commons.lang3.Validate;
|
||||
+import org.bukkit.configuration.serialization.SerializableAs;
|
||||
+import org.bukkit.craftbukkit.configuration.ConfigSerializationUtil;
|
||||
+import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
+import org.bukkit.craftbukkit.profile.CraftPlayerTextures;
|
||||
+import org.bukkit.craftbukkit.profile.CraftProfileProperty;
|
||||
+import org.bukkit.profile.PlayerTextures;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+import javax.annotation.Nonnull;
|
||||
+import javax.annotation.Nullable;
|
||||
+import java.util.*;
|
||||
+import java.util.concurrent.CompletableFuture;
|
||||
+
|
||||
+@SerializableAs("PlayerProfile")
|
||||
+public class CraftPlayerProfile implements PlayerProfile, SharedPlayerProfile {
|
||||
+
|
||||
+ private GameProfile profile;
|
||||
+ private final PropertySet properties = new PropertySet();
|
||||
+
|
||||
+ public CraftPlayerProfile(CraftPlayer player) {
|
||||
+ this.profile = player.getHandle().getGameProfile();
|
||||
+ }
|
||||
+
|
||||
+ public CraftPlayerProfile(UUID id, String name) {
|
||||
+ this.profile = new GameProfile(id, name);
|
||||
+ }
|
||||
+
|
||||
+ public CraftPlayerProfile(GameProfile profile) {
|
||||
+ Validate.notNull(profile, "GameProfile cannot be null!");
|
||||
+ this.profile = profile;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean hasProperty(String property) {
|
||||
+ return profile.getProperties().containsKey(property);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setProperty(ProfileProperty property) {
|
||||
+ String name = property.getName();
|
||||
+ PropertyMap properties = profile.getProperties();
|
||||
+ properties.removeAll(name);
|
||||
+ properties.put(name, new Property(name, property.getValue(), property.getSignature()));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public CraftPlayerTextures getTextures() {
|
||||
+ return new CraftPlayerTextures(this);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setTextures(@Nullable PlayerTextures textures) {
|
||||
+ if (textures == null) {
|
||||
+ this.removeProperty("textures");
|
||||
+ } else {
|
||||
+ CraftPlayerTextures craftPlayerTextures = new CraftPlayerTextures(this);
|
||||
+ craftPlayerTextures.copyFrom(textures);
|
||||
+ craftPlayerTextures.rebuildPropertyIfDirty();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public GameProfile getGameProfile() {
|
||||
+ return profile;
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ @Override
|
||||
+ public UUID getId() {
|
||||
+ return profile.getId();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ @Deprecated(forRemoval = true)
|
||||
+ public UUID setId(@Nullable UUID uuid) {
|
||||
+ GameProfile prev = this.profile;
|
||||
+ this.profile = new GameProfile(uuid, prev.getName());
|
||||
+ copyProfileProperties(prev, this.profile);
|
||||
+ return prev.getId();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public UUID getUniqueId() {
|
||||
+ return getId();
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ @Override
|
||||
+ public String getName() {
|
||||
+ return profile.getName();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ @Deprecated(forRemoval = true)
|
||||
+ public String setName(@Nullable String name) {
|
||||
+ GameProfile prev = this.profile;
|
||||
+ this.profile = new GameProfile(prev.getId(), name);
|
||||
+ copyProfileProperties(prev, this.profile);
|
||||
+ return prev.getName();
|
||||
+ }
|
||||
+
|
||||
+ @Nonnull
|
||||
+ @Override
|
||||
+ public Set<ProfileProperty> getProperties() {
|
||||
+ return properties;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setProperties(Collection<ProfileProperty> properties) {
|
||||
+ properties.forEach(this::setProperty);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void clearProperties() {
|
||||
+ profile.getProperties().clear();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean removeProperty(String property) {
|
||||
+ return !profile.getProperties().removeAll(property).isEmpty();
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ @Override
|
||||
+ public Property getProperty(String property) {
|
||||
+ return Iterables.getFirst(this.profile.getProperties().get(property), null);
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ @Override
|
||||
+ public void setProperty(@NotNull String propertyName, @Nullable Property property) {
|
||||
+ PropertyMap properties = profile.getProperties();
|
||||
+ properties.removeAll(propertyName);
|
||||
+ if (property != null) {
|
||||
+ properties.put(propertyName, property);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull GameProfile buildGameProfile() {
|
||||
+ GameProfile profile = new GameProfile(this.profile.getId(), this.profile.getName());
|
||||
+ profile.getProperties().putAll(this.profile.getProperties());
|
||||
+ return profile;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public CraftPlayerProfile clone() {
|
||||
+ CraftPlayerProfile clone = new CraftPlayerProfile(this.getId(), this.getName());
|
||||
+ clone.setProperties(getProperties());
|
||||
+ return clone;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isComplete() {
|
||||
+ return profile.isComplete();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull CompletableFuture<PlayerProfile> update() {
|
||||
+ return CompletableFuture.supplyAsync(() -> {
|
||||
+ final CraftPlayerProfile clone = clone();
|
||||
+ clone.complete(true);
|
||||
+ return clone;
|
||||
+ }, Util.PROFILE_EXECUTOR);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean completeFromCache() {
|
||||
+ return completeFromCache(false, GlobalConfiguration.get().proxies.isProxyOnlineMode());
|
||||
+ }
|
||||
+
|
||||
+ public boolean completeFromCache(boolean onlineMode) {
|
||||
+ return completeFromCache(false, onlineMode);
|
||||
+ }
|
||||
+
|
||||
+ public boolean completeFromCache(boolean lookupUUID, boolean onlineMode) {
|
||||
+ MinecraftServer server = MinecraftServer.getServer();
|
||||
+ String name = profile.getName();
|
||||
+ GameProfileCache userCache = server.getProfileCache();
|
||||
+ if (profile.getId() == null) {
|
||||
+ final GameProfile profile;
|
||||
+ if (onlineMode) {
|
||||
+ profile = lookupUUID ? userCache.get(name).orElse(null) : userCache.getProfileIfCached(name);
|
||||
+ } else {
|
||||
+ // Make an OfflinePlayer using an offline mode UUID since the name has no profile
|
||||
+ profile = new GameProfile(UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8)), name);
|
||||
+ }
|
||||
+ if (profile != null) {
|
||||
+ // if old has it, assume its newer, so overwrite, else use cached if it was set and ours wasn't
|
||||
+ copyProfileProperties(this.profile, profile);
|
||||
+ this.profile = profile;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if ((profile.getName() == null || !hasTextures()) && profile.getId() != null) {
|
||||
+ Optional<GameProfile> optProfile = userCache.get(this.profile.getId());
|
||||
+ if (optProfile.isPresent()) {
|
||||
+ GameProfile profile = optProfile.get();
|
||||
+ if (this.profile.getName() == null) {
|
||||
+ // if old has it, assume its newer, so overwrite, else use cached if it was set and ours wasn't
|
||||
+ copyProfileProperties(this.profile, profile);
|
||||
+ this.profile = profile;
|
||||
+ } else {
|
||||
+ copyProfileProperties(profile, this.profile);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return this.profile.isComplete();
|
||||
+ }
|
||||
+
|
||||
+ public boolean complete(boolean textures) {
|
||||
+ return complete(textures, GlobalConfiguration.get().proxies.isProxyOnlineMode());
|
||||
+ }
|
||||
+ public boolean complete(boolean textures, boolean onlineMode) {
|
||||
+ MinecraftServer server = MinecraftServer.getServer();
|
||||
+ boolean isCompleteFromCache = this.completeFromCache(true, onlineMode);
|
||||
+ if (onlineMode && (!isCompleteFromCache || textures && !hasTextures())) {
|
||||
+ GameProfile result = server.getSessionService().fillProfileProperties(profile, true);
|
||||
+ if (result != null) {
|
||||
+ copyProfileProperties(result, this.profile, true);
|
||||
+ }
|
||||
+ if (this.profile.isComplete()) {
|
||||
+ server.getProfileCache().add(this.profile);
|
||||
+ }
|
||||
+ }
|
||||
+ return profile.isComplete() && (!onlineMode || !textures || hasTextures());
|
||||
+ }
|
||||
+
|
||||
+ private static void copyProfileProperties(GameProfile source, GameProfile target) {
|
||||
+ copyProfileProperties(source, target, false);
|
||||
+ }
|
||||
+
|
||||
+ private static void copyProfileProperties(GameProfile source, GameProfile target, boolean clearTarget) {
|
||||
+ PropertyMap sourceProperties = source.getProperties();
|
||||
+ PropertyMap targetProperties = target.getProperties();
|
||||
+ if (clearTarget) targetProperties.clear();
|
||||
+ if (sourceProperties.isEmpty()) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ for (Property property : sourceProperties.values()) {
|
||||
+ targetProperties.removeAll(property.getName());
|
||||
+ targetProperties.put(property.getName(), property);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private static ProfileProperty toBukkit(Property property) {
|
||||
+ return new ProfileProperty(property.getName(), property.getValue(), property.getSignature());
|
||||
+ }
|
||||
+
|
||||
+ public static PlayerProfile asBukkitCopy(GameProfile gameProfile) {
|
||||
+ CraftPlayerProfile profile = new CraftPlayerProfile(gameProfile.getId(), gameProfile.getName());
|
||||
+ copyProfileProperties(gameProfile, profile.profile);
|
||||
+ return profile;
|
||||
+ }
|
||||
+
|
||||
+ public static PlayerProfile asBukkitMirror(GameProfile profile) {
|
||||
+ return new CraftPlayerProfile(profile);
|
||||
+ }
|
||||
+
|
||||
+ public static Property asAuthlib(ProfileProperty property) {
|
||||
+ return new Property(property.getName(), property.getValue(), property.getSignature());
|
||||
+ }
|
||||
+
|
||||
+ public static GameProfile asAuthlibCopy(PlayerProfile profile) {
|
||||
+ CraftPlayerProfile craft = ((CraftPlayerProfile) profile);
|
||||
+ return asAuthlib(craft.clone());
|
||||
+ }
|
||||
+
|
||||
+ public static GameProfile asAuthlib(PlayerProfile profile) {
|
||||
+ CraftPlayerProfile craft = ((CraftPlayerProfile) profile);
|
||||
+ return craft.getGameProfile();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull Map<String, Object> serialize() {
|
||||
+ Map<String, Object> map = new LinkedHashMap<>();
|
||||
+ if (this.getId() != null) {
|
||||
+ map.put("uniqueId", this.getId().toString());
|
||||
+ }
|
||||
+ if (this.getName() != null) {
|
||||
+ map.put("name", getName());
|
||||
+ }
|
||||
+ if (!this.properties.isEmpty()) {
|
||||
+ List<Object> propertiesData = new ArrayList<>();
|
||||
+ for (ProfileProperty property : properties) {
|
||||
+ propertiesData.add(CraftProfileProperty.serialize(new Property(property.getName(), property.getValue(), property.getSignature())));
|
||||
+ }
|
||||
+ map.put("properties", propertiesData);
|
||||
+ }
|
||||
+ return map;
|
||||
+ }
|
||||
+
|
||||
+ public static CraftPlayerProfile deserialize(Map<String, Object> map) {
|
||||
+ UUID uniqueId = ConfigSerializationUtil.getUuid(map, "uniqueId", true);
|
||||
+ String name = ConfigSerializationUtil.getString(map, "name", true);
|
||||
+
|
||||
+ // This also validates the deserialized unique id and name (ensures that not both are null):
|
||||
+ CraftPlayerProfile profile = new CraftPlayerProfile(uniqueId, name);
|
||||
+
|
||||
+ if (map.containsKey("properties")) {
|
||||
+ for (Object propertyData : (List<?>) map.get("properties")) {
|
||||
+ if (!(propertyData instanceof Map)) {
|
||||
+ throw new IllegalArgumentException("Property data (" + propertyData + ") is not a valid Map");
|
||||
+ }
|
||||
+ Property property = CraftProfileProperty.deserialize((Map<?, ?>) propertyData);
|
||||
+ profile.profile.getProperties().put(property.getName(), property);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return profile;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean equals(Object obj) {
|
||||
+ if (this == obj) return true;
|
||||
+ if (!(obj instanceof CraftPlayerProfile otherProfile)) return false;
|
||||
+ return Objects.equals(this.profile, otherProfile.profile);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public String toString() {
|
||||
+ return "CraftPlayerProfile [uniqueId=" + getId() +
|
||||
+ ", name=" + getName() +
|
||||
+ ", properties=" + org.bukkit.craftbukkit.profile.CraftPlayerProfile.toString(this.profile.getProperties()) +
|
||||
+ "]";
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int hashCode() {
|
||||
+ return this.profile.hashCode();
|
||||
+ }
|
||||
+
|
||||
+ private class PropertySet extends AbstractSet<ProfileProperty> {
|
||||
+
|
||||
+ @Override
|
||||
+ @Nonnull
|
||||
+ public Iterator<ProfileProperty> iterator() {
|
||||
+ return new ProfilePropertyIterator(profile.getProperties().values().iterator());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int size() {
|
||||
+ return profile.getProperties().size();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean add(ProfileProperty property) {
|
||||
+ setProperty(property);
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean addAll(Collection<? extends ProfileProperty> c) {
|
||||
+ //noinspection unchecked
|
||||
+ setProperties((Collection<ProfileProperty>) c);
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean contains(Object o) {
|
||||
+ return o instanceof ProfileProperty && profile.getProperties().containsKey(((ProfileProperty) o).getName());
|
||||
+ }
|
||||
+
|
||||
+ private class ProfilePropertyIterator implements Iterator<ProfileProperty> {
|
||||
+ private final Iterator<Property> iterator;
|
||||
+
|
||||
+ ProfilePropertyIterator(Iterator<Property> iterator) {
|
||||
+ this.iterator = iterator;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean hasNext() {
|
||||
+ return iterator.hasNext();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public ProfileProperty next() {
|
||||
+ return toBukkit(iterator.next());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void remove() {
|
||||
+ iterator.remove();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperAuthenticationService.java b/src/main/java/com/destroystokyo/paper/profile/PaperAuthenticationService.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..1459a1f99fe614d072a087cda18788cf13102645
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/profile/PaperAuthenticationService.java
|
||||
@@ -0,0 +1,31 @@
|
||||
+package com.destroystokyo.paper.profile;
|
||||
+
|
||||
+import com.mojang.authlib.*;
|
||||
+import com.mojang.authlib.minecraft.MinecraftSessionService;
|
||||
+import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
|
||||
+import com.mojang.authlib.yggdrasil.YggdrasilEnvironment;
|
||||
+
|
||||
+import java.net.Proxy;
|
||||
+
|
||||
+public class PaperAuthenticationService extends YggdrasilAuthenticationService {
|
||||
+ private final Environment environment;
|
||||
+ public PaperAuthenticationService(Proxy proxy) {
|
||||
+ super(proxy);
|
||||
+ this.environment = EnvironmentParser.getEnvironmentFromProperties().orElse(YggdrasilEnvironment.PROD.getEnvironment());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public UserAuthentication createUserAuthentication(Agent agent) {
|
||||
+ return new PaperUserAuthentication(this, agent);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public MinecraftSessionService createMinecraftSessionService() {
|
||||
+ return new PaperMinecraftSessionService(this, this.environment);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public GameProfileRepository createProfileRepository() {
|
||||
+ return new PaperGameProfileRepository(this, this.environment);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..582c169c85ac66f1f9430f79042e4655f776c157
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java
|
||||
@@ -0,0 +1,18 @@
|
||||
+package com.destroystokyo.paper.profile;
|
||||
+
|
||||
+import com.mojang.authlib.Agent;
|
||||
+import com.mojang.authlib.Environment;
|
||||
+import com.mojang.authlib.ProfileLookupCallback;
|
||||
+import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
|
||||
+import com.mojang.authlib.yggdrasil.YggdrasilGameProfileRepository;
|
||||
+
|
||||
+public class PaperGameProfileRepository extends YggdrasilGameProfileRepository {
|
||||
+ public PaperGameProfileRepository(YggdrasilAuthenticationService authenticationService, Environment environment) {
|
||||
+ super(authenticationService, environment);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void findProfilesByNames(String[] names, Agent agent, ProfileLookupCallback callback) {
|
||||
+ super.findProfilesByNames(names, agent, callback);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..93d73c27340645c7502acafdc0b2cfbc1a759dd8
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java
|
||||
@@ -0,0 +1,30 @@
|
||||
+package com.destroystokyo.paper.profile;
|
||||
+
|
||||
+import com.mojang.authlib.Environment;
|
||||
+import com.mojang.authlib.GameProfile;
|
||||
+import com.mojang.authlib.minecraft.MinecraftProfileTexture;
|
||||
+import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
|
||||
+import com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService;
|
||||
+
|
||||
+import java.util.Map;
|
||||
+
|
||||
+public class PaperMinecraftSessionService extends YggdrasilMinecraftSessionService {
|
||||
+ protected PaperMinecraftSessionService(YggdrasilAuthenticationService authenticationService, Environment environment) {
|
||||
+ super(authenticationService, environment);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> getTextures(GameProfile profile, boolean requireSecure) {
|
||||
+ return super.getTextures(profile, requireSecure);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public GameProfile fillProfileProperties(GameProfile profile, boolean requireSecure) {
|
||||
+ return super.fillProfileProperties(profile, requireSecure);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ protected GameProfile fillGameProfile(GameProfile profile, boolean requireSecure) {
|
||||
+ return super.fillGameProfile(profile, requireSecure);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperUserAuthentication.java b/src/main/java/com/destroystokyo/paper/profile/PaperUserAuthentication.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..3cdd06d3af7ff94f1fe1a11b9a9275e17c695a38
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/profile/PaperUserAuthentication.java
|
||||
@@ -0,0 +1,12 @@
|
||||
+package com.destroystokyo.paper.profile;
|
||||
+
|
||||
+import com.mojang.authlib.Agent;
|
||||
+import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
|
||||
+import com.mojang.authlib.yggdrasil.YggdrasilUserAuthentication;
|
||||
+import java.util.UUID;
|
||||
+
|
||||
+public class PaperUserAuthentication extends YggdrasilUserAuthentication {
|
||||
+ public PaperUserAuthentication(YggdrasilAuthenticationService authenticationService, Agent agent) {
|
||||
+ super(authenticationService, UUID.randomUUID().toString(), agent);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/profile/SharedPlayerProfile.java b/src/main/java/com/destroystokyo/paper/profile/SharedPlayerProfile.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..7ac27392a8647ef7d0dc78efe78703e993885017
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/profile/SharedPlayerProfile.java
|
||||
@@ -0,0 +1,23 @@
|
||||
+package com.destroystokyo.paper.profile;
|
||||
+
|
||||
+import com.mojang.authlib.GameProfile;
|
||||
+import com.mojang.authlib.properties.Property;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+import java.util.UUID;
|
||||
+
|
||||
+public interface SharedPlayerProfile {
|
||||
+
|
||||
+ @Nullable UUID getUniqueId();
|
||||
+
|
||||
+ @Nullable String getName();
|
||||
+
|
||||
+ boolean removeProperty(@NotNull String property);
|
||||
+
|
||||
+ @Nullable Property getProperty(@NotNull String propertyName);
|
||||
+
|
||||
+ @Nullable void setProperty(@NotNull String propertyName, @Nullable Property property);
|
||||
+
|
||||
+ @NotNull GameProfile buildGameProfile();
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/util/MCUtil.java b/src/main/java/io/papermc/paper/util/MCUtil.java
|
||||
index cf3e083c2ada3275a52c303de16a62576696e83f..b19850ae31f6c796cb3491dd5070d28e0ffd242c 100644
|
||||
--- a/src/main/java/io/papermc/paper/util/MCUtil.java
|
||||
+++ b/src/main/java/io/papermc/paper/util/MCUtil.java
|
||||
@@ -1,5 +1,7 @@
|
||||
package io.papermc.paper.util;
|
||||
|
||||
+import com.destroystokyo.paper.profile.CraftPlayerProfile;
|
||||
+import com.destroystokyo.paper.profile.PlayerProfile;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
@@ -25,6 +27,7 @@ import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import org.apache.commons.lang.exception.ExceptionUtils;
|
||||
+import com.mojang.authlib.GameProfile;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
@@ -372,6 +375,10 @@ public final class MCUtil {
|
||||
return run.get();
|
||||
}
|
||||
|
||||
+ public static PlayerProfile toBukkit(GameProfile profile) {
|
||||
+ return CraftPlayerProfile.asBukkitMirror(profile);
|
||||
+ }
|
||||
+
|
||||
/**
|
||||
* Calculates distance between 2 entities
|
||||
* @param e1
|
||||
diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java
|
||||
index 45db9f1b1d19319e7f92bd4e61be9ea9b06dd5e5..151b13e257c09fc5c4bbccfc388b15ad76133909 100644
|
||||
--- a/src/main/java/net/minecraft/server/Main.java
|
||||
+++ b/src/main/java/net/minecraft/server/Main.java
|
||||
@@ -155,7 +155,7 @@ public class Main {
|
||||
}
|
||||
|
||||
File file = (File) optionset.valueOf("universe"); // CraftBukkit
|
||||
- Services services = Services.create(new YggdrasilAuthenticationService(Proxy.NO_PROXY), file, optionset); // Paper
|
||||
+ Services services = Services.create(new com.destroystokyo.paper.profile.PaperAuthenticationService(Proxy.NO_PROXY), file, optionset); // Paper
|
||||
// CraftBukkit start
|
||||
String s = (String) Optional.ofNullable((String) optionset.valueOf("world")).orElse(dedicatedserversettings.getProperties().levelName);
|
||||
LevelStorageSource convertable = LevelStorageSource.createDefault(file.toPath());
|
||||
diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java
|
||||
index 4038bb76339d43f18770624bd7fecc79b8d7f2a9..2456edc11b29a92b1648937cd3dd6a9a05706803 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/GameProfileCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java
|
||||
@@ -136,6 +136,17 @@ public class GameProfileCache {
|
||||
return this.operationCount.incrementAndGet();
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ public @Nullable GameProfile getProfileIfCached(String name) {
|
||||
+ GameProfileCache.GameProfileInfo entry = this.profilesByName.get(name.toLowerCase(Locale.ROOT));
|
||||
+ if (entry == null) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ entry.setLastAccess(this.getNextOperation());
|
||||
+ return entry.getProfile();
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
public Optional<GameProfile> get(String name) {
|
||||
String s1 = name.toLowerCase(Locale.ROOT);
|
||||
GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByName.get(s1);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index 75b9d496860d7f3a9d5f680cbdfe89860286522e..7013b11fc0cd5fbb5a7e62be45d84d54d3052237 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -244,6 +244,9 @@ import org.yaml.snakeyaml.error.MarkedYAMLException;
|
||||
|
||||
import net.md_5.bungee.api.chat.BaseComponent; // Spigot
|
||||
|
||||
+import javax.annotation.Nullable; // Paper
|
||||
+import javax.annotation.Nonnull; // Paper
|
||||
+
|
||||
public final class CraftServer implements Server {
|
||||
private final String serverName = "Paper"; // Paper
|
||||
private final String serverVersion;
|
||||
@@ -284,6 +287,7 @@ public final class CraftServer implements Server {
|
||||
static {
|
||||
ConfigurationSerialization.registerClass(CraftOfflinePlayer.class);
|
||||
ConfigurationSerialization.registerClass(CraftPlayerProfile.class);
|
||||
+ ConfigurationSerialization.registerClass(com.destroystokyo.paper.profile.CraftPlayerProfile.class); // Paper
|
||||
CraftItemFactory.instance();
|
||||
}
|
||||
|
||||
@@ -2596,5 +2600,37 @@ public final class CraftServer implements Server {
|
||||
public boolean suggestPlayerNamesWhenNullTabCompletions() {
|
||||
return io.papermc.paper.configuration.GlobalConfiguration.get().commands.suggestPlayerNamesWhenNullTabCompletions;
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nonnull UUID uuid) {
|
||||
+ return createProfile(uuid, null);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nonnull String name) {
|
||||
+ return createProfile(null, name);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nullable UUID uuid, @Nullable String name) {
|
||||
+ Player player = uuid != null ? Bukkit.getPlayer(uuid) : (name != null ? Bukkit.getPlayerExact(name) : null);
|
||||
+ if (player != null) return new com.destroystokyo.paper.profile.CraftPlayerProfile((CraftPlayer) player);
|
||||
+
|
||||
+ return new com.destroystokyo.paper.profile.CraftPlayerProfile(uuid, name);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public com.destroystokyo.paper.profile.PlayerProfile createProfileExact(@Nullable UUID uuid, @Nullable String name) {
|
||||
+ Player player = uuid != null ? Bukkit.getPlayer(uuid) : (name != null ? Bukkit.getPlayerExact(name) : null);
|
||||
+ if (player == null) return new com.destroystokyo.paper.profile.CraftPlayerProfile(uuid, name);
|
||||
+
|
||||
+ if (Objects.equals(uuid, player.getUniqueId()) && Objects.equals(name, player.getName())) {
|
||||
+ return new com.destroystokyo.paper.profile.CraftPlayerProfile((CraftPlayer) player);
|
||||
+ }
|
||||
+
|
||||
+ final com.mojang.authlib.GameProfile profile = new com.mojang.authlib.GameProfile(uuid, name);
|
||||
+ profile.getProperties().putAll(((CraftPlayer)player).getHandle().getGameProfile().getProperties());
|
||||
+ return new com.destroystokyo.paper.profile.CraftPlayerProfile(profile);
|
||||
+ }
|
||||
// Paper end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java b/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java
|
||||
index 3e40d47f504248cd7caeef6b841a8aa6f1976170..6ca6467a47c6658d3a2e2029821aa727599a6f74 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java
|
||||
@@ -27,7 +27,7 @@ import org.bukkit.profile.PlayerProfile;
|
||||
import org.bukkit.profile.PlayerTextures;
|
||||
|
||||
@SerializableAs("PlayerProfile")
|
||||
-public final class CraftPlayerProfile implements PlayerProfile {
|
||||
+public final class CraftPlayerProfile implements PlayerProfile, com.destroystokyo.paper.profile.SharedPlayerProfile { // Paper
|
||||
|
||||
@Nonnull
|
||||
public static GameProfile validateSkullProfile(@Nonnull GameProfile gameProfile) {
|
||||
@@ -92,8 +92,10 @@ public final class CraftPlayerProfile implements PlayerProfile {
|
||||
}
|
||||
}
|
||||
|
||||
- void removeProperty(String propertyName) {
|
||||
- this.properties.removeAll(propertyName);
|
||||
+ // Paper start - change return value for shared interface
|
||||
+ public boolean removeProperty(String propertyName) {
|
||||
+ return !this.properties.removeAll(propertyName).isEmpty();
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
void rebuildDirtyProperties() {
|
||||
@@ -236,6 +238,7 @@ public final class CraftPlayerProfile implements PlayerProfile {
|
||||
|
||||
@Override
|
||||
public Map<String, Object> serialize() {
|
||||
+ // Paper - diff on change
|
||||
Map<String, Object> map = new LinkedHashMap<>();
|
||||
if (this.uniqueId != null) {
|
||||
map.put("uniqueId", this.uniqueId.toString());
|
||||
@@ -251,10 +254,12 @@ public final class CraftPlayerProfile implements PlayerProfile {
|
||||
});
|
||||
map.put("properties", propertiesData);
|
||||
}
|
||||
+ // Paper - diff on change
|
||||
return map;
|
||||
}
|
||||
|
||||
public static CraftPlayerProfile deserialize(Map<String, Object> map) {
|
||||
+ // Paper - diff on change
|
||||
UUID uniqueId = ConfigSerializationUtil.getUuid(map, "uniqueId", true);
|
||||
String name = ConfigSerializationUtil.getString(map, "name", true);
|
||||
|
||||
@@ -270,7 +275,7 @@ public final class CraftPlayerProfile implements PlayerProfile {
|
||||
profile.properties.put(property.getName(), property);
|
||||
}
|
||||
}
|
||||
-
|
||||
+ // Paper - diff on change
|
||||
return profile;
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerTextures.java b/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerTextures.java
|
||||
index e5b61bc1f3a4bfccca386360c4920ffb8b768308..ab1fd3fb39bd40fb867432861462db5f866bce6f 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerTextures.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerTextures.java
|
||||
@@ -48,7 +48,7 @@ public final class CraftPlayerTextures implements PlayerTextures {
|
||||
}
|
||||
}
|
||||
|
||||
- private final CraftPlayerProfile profile;
|
||||
+ private final com.destroystokyo.paper.profile.SharedPlayerProfile profile; // Paper
|
||||
|
||||
// The textures data is loaded lazily:
|
||||
private boolean loaded = false;
|
||||
@@ -67,7 +67,7 @@ public final class CraftPlayerTextures implements PlayerTextures {
|
||||
// GameProfiles (even if these modifications are later reverted).
|
||||
private boolean dirty = false;
|
||||
|
||||
- CraftPlayerTextures(@Nonnull CraftPlayerProfile profile) {
|
||||
+ public CraftPlayerTextures(@Nonnull com.destroystokyo.paper.profile.SharedPlayerProfile profile) { // Paper
|
||||
this.profile = profile;
|
||||
}
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 17 Jun 2017 15:18:30 -0400
|
||||
Subject: [PATCH] Shoulder Entities Release API
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
index d68ad0bc89565d207f46b106bacce8e6efc890dc..2fd52878415fca31d053d8d83a53748e8743e352 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
@@ -2036,20 +2036,44 @@ public abstract class Player extends LivingEntity {
|
||||
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ public Entity releaseLeftShoulderEntity() {
|
||||
+ Entity entity = this.spawnEntityFromShoulder0(this.getShoulderEntityLeft());
|
||||
+ if (entity != null) {
|
||||
+ this.setShoulderEntityLeft(new CompoundTag());
|
||||
+ }
|
||||
+ return entity;
|
||||
+ }
|
||||
+
|
||||
+ public Entity releaseRightShoulderEntity() {
|
||||
+ Entity entity = this.spawnEntityFromShoulder0(this.getShoulderEntityRight());
|
||||
+ if (entity != null) {
|
||||
+ this.setShoulderEntityRight(new CompoundTag());
|
||||
+ }
|
||||
+ return entity;
|
||||
+ }
|
||||
+ // Paper - maintain old signature
|
||||
private boolean spawnEntityFromShoulder(CompoundTag nbttagcompound) { // CraftBukkit void->boolean
|
||||
- if (!this.level.isClientSide && !nbttagcompound.isEmpty()) {
|
||||
+ return spawnEntityFromShoulder0(nbttagcompound) != null;
|
||||
+ }
|
||||
+
|
||||
+ // Paper - return entity
|
||||
+ private Entity spawnEntityFromShoulder0(@Nullable CompoundTag nbttagcompound) {
|
||||
+ if (!this.level.isClientSide && nbttagcompound != null && !nbttagcompound.isEmpty()) {
|
||||
return EntityType.create(nbttagcompound, this.level).map((entity) -> { // CraftBukkit
|
||||
if (entity instanceof TamableAnimal) {
|
||||
((TamableAnimal) entity).setOwnerUUID(this.uuid);
|
||||
}
|
||||
|
||||
entity.setPos(this.getX(), this.getY() + 0.699999988079071D, this.getZ());
|
||||
- return ((ServerLevel) this.level).addWithUUID(entity, CreatureSpawnEvent.SpawnReason.SHOULDER_ENTITY); // CraftBukkit
|
||||
- }).orElse(true); // CraftBukkit
|
||||
+ boolean addedToWorld = ((ServerLevel) this.level).addWithUUID(entity, CreatureSpawnEvent.SpawnReason.SHOULDER_ENTITY); // CraftBukkit
|
||||
+ return addedToWorld ? entity : null;
|
||||
+ }).orElse(null); // CraftBukkit // Paper - true -> null
|
||||
}
|
||||
|
||||
- return true; // CraftBukkit
|
||||
+ return null; // Paper - return null
|
||||
}
|
||||
+ // Paper end
|
||||
|
||||
@Override
|
||||
public abstract boolean isSpectator();
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
|
||||
index 19549dda26c24388bd13a5a2579789e2d1e3ad88..3ca0d08a9e6511b8a96abcf0807a77d52f303a44 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
|
||||
@@ -507,6 +507,32 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
|
||||
this.getHandle().getCooldowns().addCooldown(CraftMagicNumbers.getItem(material), ticks);
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public org.bukkit.entity.Entity releaseLeftShoulderEntity() {
|
||||
+ if (!getHandle().getShoulderEntityLeft().isEmpty()) {
|
||||
+ Entity entity = getHandle().releaseLeftShoulderEntity();
|
||||
+ if (entity != null) {
|
||||
+ return entity.getBukkitEntity();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public org.bukkit.entity.Entity releaseRightShoulderEntity() {
|
||||
+ if (!getHandle().getShoulderEntityRight().isEmpty()) {
|
||||
+ Entity entity = getHandle().releaseRightShoulderEntity();
|
||||
+ if (entity != null) {
|
||||
+ return entity.getBukkitEntity();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return null;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public boolean discoverRecipe(NamespacedKey recipe) {
|
||||
return this.discoverRecipes(Arrays.asList(recipe)) != 0;
|
|
@ -1,81 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 17 Jun 2017 17:00:32 -0400
|
||||
Subject: [PATCH] Profile Lookup Events
|
||||
|
||||
Adds a Pre Lookup Event and a Post Lookup Event so that plugins may prefill in profile data, and cache the responses from
|
||||
profiles that had to be looked up.
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java
|
||||
index 582c169c85ac66f1f9430f79042e4655f776c157..08fdb681a68e8be6e4062af0630957ce3e524806 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java
|
||||
@@ -1,11 +1,16 @@
|
||||
package com.destroystokyo.paper.profile;
|
||||
|
||||
+import com.destroystokyo.paper.event.profile.LookupProfileEvent;
|
||||
+import com.destroystokyo.paper.event.profile.PreLookupProfileEvent;
|
||||
+import com.google.common.collect.Sets;
|
||||
import com.mojang.authlib.Agent;
|
||||
import com.mojang.authlib.Environment;
|
||||
+import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.ProfileLookupCallback;
|
||||
import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
|
||||
import com.mojang.authlib.yggdrasil.YggdrasilGameProfileRepository;
|
||||
|
||||
+import java.util.Set;
|
||||
public class PaperGameProfileRepository extends YggdrasilGameProfileRepository {
|
||||
public PaperGameProfileRepository(YggdrasilAuthenticationService authenticationService, Environment environment) {
|
||||
super(authenticationService, environment);
|
||||
@@ -13,6 +18,50 @@ public class PaperGameProfileRepository extends YggdrasilGameProfileRepository {
|
||||
|
||||
@Override
|
||||
public void findProfilesByNames(String[] names, Agent agent, ProfileLookupCallback callback) {
|
||||
- super.findProfilesByNames(names, agent, callback);
|
||||
+ Set<String> unfoundNames = Sets.newHashSet();
|
||||
+ for (String name : names) {
|
||||
+ PreLookupProfileEvent event = new PreLookupProfileEvent(name);
|
||||
+ event.callEvent();
|
||||
+ if (event.getUUID() != null) {
|
||||
+ // Plugin provided UUI, we can skip network call.
|
||||
+ GameProfile gameprofile = new GameProfile(event.getUUID(), name);
|
||||
+ // We might even have properties!
|
||||
+ Set<ProfileProperty> profileProperties = event.getProfileProperties();
|
||||
+ if (!profileProperties.isEmpty()) {
|
||||
+ for (ProfileProperty property : profileProperties) {
|
||||
+ gameprofile.getProperties().put(property.getName(), CraftPlayerProfile.asAuthlib(property));
|
||||
+ }
|
||||
+ }
|
||||
+ callback.onProfileLookupSucceeded(gameprofile);
|
||||
+ } else {
|
||||
+ unfoundNames.add(name);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Some things were not found.... Proceed to look up.
|
||||
+ if (!unfoundNames.isEmpty()) {
|
||||
+ String[] namesArr = unfoundNames.toArray(new String[unfoundNames.size()]);
|
||||
+ super.findProfilesByNames(namesArr, agent, new PreProfileLookupCallback(callback));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private static class PreProfileLookupCallback implements ProfileLookupCallback {
|
||||
+ private final ProfileLookupCallback callback;
|
||||
+
|
||||
+ PreProfileLookupCallback(ProfileLookupCallback callback) {
|
||||
+ this.callback = callback;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onProfileLookupSucceeded(GameProfile gameProfile) {
|
||||
+ PlayerProfile from = CraftPlayerProfile.asBukkitMirror(gameProfile);
|
||||
+ new LookupProfileEvent(from).callEvent();
|
||||
+ callback.onProfileLookupSucceeded(gameProfile);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onProfileLookupFailed(GameProfile gameProfile, Exception e) {
|
||||
+ callback.onProfileLookupFailed(gameProfile, e);
|
||||
+ }
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach.brown@destroystokyo.com>
|
||||
Date: Sun, 2 Jul 2017 21:35:56 -0500
|
||||
Subject: [PATCH] Block player logins during server shutdown
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
index 9011b43dbf28f1f19809c1b45898b727d679c12f..187692ea25983195a0fe14a7dc070fd33acb0037 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
@@ -76,6 +76,12 @@ public class ServerLoginPacketListenerImpl implements TickablePacketListener, Se
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
+ // Paper start - Do not allow logins while the server is shutting down
|
||||
+ if (!MinecraftServer.getServer().isRunning()) {
|
||||
+ this.disconnect(org.bukkit.craftbukkit.util.CraftChatMessage.fromString(org.spigotmc.SpigotConfig.restartMessage)[0]);
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end
|
||||
if (this.state == ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT) {
|
||||
this.handleAcceptedLogin();
|
||||
} else if (this.state == ServerLoginPacketListenerImpl.State.DELAY_ACCEPT) {
|
|
@ -1,65 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Sun, 18 Jun 2017 18:17:05 -0500
|
||||
Subject: [PATCH] Entity#fromMobSpawner()
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index 58256b341aa15e946abef464453c0ffcaf55b372..36beb42ccdb348c91020502f935b3a1590a7472e 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -380,6 +380,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
||||
// Spigot end
|
||||
// Paper start
|
||||
protected int numCollisions = 0; // Paper
|
||||
+ public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one
|
||||
@javax.annotation.Nullable
|
||||
private org.bukkit.util.Vector origin;
|
||||
@javax.annotation.Nullable
|
||||
@@ -2020,6 +2021,10 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
||||
}
|
||||
nbt.put("Paper.Origin", this.newDoubleList(origin.getX(), origin.getY(), origin.getZ()));
|
||||
}
|
||||
+ // Save entity's from mob spawner status
|
||||
+ if (spawnedViaMobSpawner) {
|
||||
+ nbt.putBoolean("Paper.FromMobSpawner", true);
|
||||
+ }
|
||||
// Paper end
|
||||
return nbt;
|
||||
} catch (Throwable throwable) {
|
||||
@@ -2159,6 +2164,8 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
||||
this.originWorld = originWorld;
|
||||
origin = new org.bukkit.util.Vector(originTag.getDouble(0), originTag.getDouble(1), originTag.getDouble(2));
|
||||
}
|
||||
+
|
||||
+ spawnedViaMobSpawner = nbt.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status
|
||||
// Paper end
|
||||
|
||||
} catch (Throwable throwable) {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java
|
||||
index 02ee392c810d96d05f5ad27b1d75fa06dd28ee4c..d09d586fd649f5b13c1515a8b0f869c1d6033cce 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java
|
||||
@@ -159,6 +159,7 @@ public abstract class BaseSpawner {
|
||||
}
|
||||
// Spigot End
|
||||
}
|
||||
+ entity.spawnedViaMobSpawner = true; // Paper
|
||||
// Spigot Start
|
||||
if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, pos).isCancelled()) {
|
||||
Entity vehicle = entity.getVehicle();
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
index b9599f4f431098d63be98b5175890371103f8813..d3a8c68f5186f69432fb8af8b34b174b04368fc1 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
@@ -1260,5 +1260,10 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
||||
//noinspection ConstantConditions
|
||||
return originVector.toLocation(world);
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean fromMobSpawner() {
|
||||
+ return getHandle().spawnedViaMobSpawner;
|
||||
+ }
|
||||
// Paper end
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 10 Dec 2016 16:24:06 -0500
|
||||
Subject: [PATCH] Improve the Saddle API for Horses
|
||||
|
||||
Not all horses with Saddles have armor. This lets us break up the horses with saddles
|
||||
and access their saddle state separately from an interface shared with Armor.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java
|
||||
index d74c9eeb7f622f0a7265fec51d851ffd3de1c69b..a5202ee012034678efbbd5ca1eccf2fd72a315bd 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java
|
||||
@@ -5,6 +5,7 @@ import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.craftbukkit.CraftServer;
|
||||
import org.bukkit.craftbukkit.inventory.CraftInventoryAbstractHorse;
|
||||
+import org.bukkit.craftbukkit.inventory.CraftSaddledInventory;
|
||||
import org.bukkit.entity.AbstractHorse;
|
||||
import org.bukkit.entity.AnimalTamer;
|
||||
import org.bukkit.entity.Horse;
|
||||
@@ -108,6 +109,6 @@ public abstract class CraftAbstractHorse extends CraftAnimals implements Abstrac
|
||||
|
||||
@Override
|
||||
public AbstractHorseInventory getInventory() {
|
||||
- return new CraftInventoryAbstractHorse(this.getHandle().inventory);
|
||||
+ return new CraftSaddledInventory(getHandle().inventory);
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java
|
||||
index 7013059856c2471dc34112a1a2068b96b809dd96..b72b4260fc1c0e9928d70f97589d8db00849b9e8 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java
|
||||
@@ -4,7 +4,7 @@ import net.minecraft.world.Container;
|
||||
import org.bukkit.inventory.HorseInventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
-public class CraftInventoryHorse extends CraftInventoryAbstractHorse implements HorseInventory {
|
||||
+public class CraftInventoryHorse extends CraftSaddledInventory implements HorseInventory {
|
||||
|
||||
public CraftInventoryHorse(Container inventory) {
|
||||
super(inventory);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftSaddledInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftSaddledInventory.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..3a617c07d445bacf5a13e0e3ff6481823cfc8477
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftSaddledInventory.java
|
||||
@@ -0,0 +1,12 @@
|
||||
+package org.bukkit.craftbukkit.inventory;
|
||||
+
|
||||
+import net.minecraft.world.Container;
|
||||
+import org.bukkit.inventory.SaddledHorseInventory;
|
||||
+
|
||||
+public class CraftSaddledInventory extends CraftInventoryAbstractHorse implements SaddledHorseInventory {
|
||||
+
|
||||
+ public CraftSaddledInventory(Container inventory) {
|
||||
+ super(inventory);
|
||||
+ }
|
||||
+
|
||||
+}
|
|
@ -1,24 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 4 May 2016 22:43:12 -0400
|
||||
Subject: [PATCH] Implement ensureServerConversions API
|
||||
|
||||
This will take a Bukkit ItemStack and run it through any conversions a server process would perform on it,
|
||||
to ensure it meets latest minecraft expectations.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
|
||||
index a06f9775a43a245380edabde63e7999082e7958a..5f83838f3f40b778088187904b747abff703c3f2 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
|
||||
@@ -386,5 +386,11 @@ public final class CraftItemFactory implements ItemFactory {
|
||||
public net.kyori.adventure.text.@org.jetbrains.annotations.NotNull Component displayName(@org.jetbrains.annotations.NotNull ItemStack itemStack) {
|
||||
return io.papermc.paper.adventure.PaperAdventure.asAdventure(CraftItemStack.asNMSCopy(itemStack).getDisplayName());
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public ItemStack ensureServerConversions(ItemStack item) {
|
||||
+ return CraftItemStack.asCraftMirror(CraftItemStack.asNMSCopy(item));
|
||||
+ }
|
||||
// Paper end
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 4 May 2016 23:59:38 -0400
|
||||
Subject: [PATCH] Implement getI18NDisplayName
|
||||
|
||||
Gets the Display name as seen in the Client.
|
||||
Currently the server only supports the English language. To override this,
|
||||
You must replace the language file embedded in the server jar.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
|
||||
index 5f83838f3f40b778088187904b747abff703c3f2..f05923a6292f02a01791627abce2770daff24b6a 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
|
||||
@@ -392,5 +392,18 @@ public final class CraftItemFactory implements ItemFactory {
|
||||
public ItemStack ensureServerConversions(ItemStack item) {
|
||||
return CraftItemStack.asCraftMirror(CraftItemStack.asNMSCopy(item));
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public String getI18NDisplayName(ItemStack item) {
|
||||
+ net.minecraft.world.item.ItemStack nms = null;
|
||||
+ if (item instanceof CraftItemStack) {
|
||||
+ nms = ((CraftItemStack) item).handle;
|
||||
+ }
|
||||
+ if (nms == null) {
|
||||
+ nms = CraftItemStack.asNMSCopy(item);
|
||||
+ }
|
||||
+
|
||||
+ return nms != null ? net.minecraft.locale.Language.getInstance().getOrDefault(nms.getItem().getDescriptionId(nms)) : null;
|
||||
+ }
|
||||
// Paper end
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 3 Jul 2017 18:11:10 -0500
|
||||
Subject: [PATCH] ProfileWhitelistVerifyEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
index 4f47a48aad54bec10fa8d79be2e6401cd8166591..4dcc44b925ac261aaa2f4ee84e321d6c8852e835 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
@@ -621,9 +621,9 @@ public abstract class PlayerList {
|
||||
|
||||
// return chatmessage;
|
||||
event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(ichatmutablecomponent)); // Paper - Adventure
|
||||
- } else if (!this.isWhiteListed(gameprofile)) {
|
||||
- ichatmutablecomponent = Component.translatable("multiplayer.disconnect.not_whitelisted");
|
||||
- event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(org.spigotmc.SpigotConfig.whitelistMessage)); // Spigot // Paper - Adventure
|
||||
+ } else if (!this.isWhiteListed(gameprofile, event)) { // Paper
|
||||
+ //ichatmutablecomponent = Component.translatable("multiplayer.disconnect.not_whitelisted"); // Paper
|
||||
+ //event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(org.spigotmc.SpigotConfig.whitelistMessage)); // Spigot // Paper - Adventure - moved to isWhitelisted
|
||||
} else if (this.getIpBans().isBanned(socketaddress) && !this.getIpBans().get(socketaddress).hasExpired()) {
|
||||
IpBanListEntry ipbanentry = this.ipBans.get(socketaddress);
|
||||
|
||||
@@ -1005,7 +1005,23 @@ public abstract class PlayerList {
|
||||
}
|
||||
|
||||
public boolean isWhiteListed(GameProfile profile) {
|
||||
- return !this.doWhiteList || this.ops.contains(profile) || this.whitelist.contains(profile);
|
||||
+ // Paper start
|
||||
+ return isWhiteListed(profile, null);
|
||||
+ }
|
||||
+ public boolean isWhiteListed(GameProfile gameprofile, org.bukkit.event.player.PlayerLoginEvent loginEvent) {
|
||||
+ boolean isOp = this.ops.contains(gameprofile);
|
||||
+ boolean isWhitelisted = !this.doWhiteList || isOp || this.whitelist.contains(gameprofile);
|
||||
+ final com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent event;
|
||||
+ event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(io.papermc.paper.util.MCUtil.toBukkit(gameprofile), this.doWhiteList, isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage);
|
||||
+ event.callEvent();
|
||||
+ if (!event.isWhitelisted()) {
|
||||
+ if (loginEvent != null) {
|
||||
+ loginEvent.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(event.getKickMessage() == null ? org.spigotmc.SpigotConfig.whitelistMessage : event.getKickMessage()));
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+ return true;
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
public boolean isOp(GameProfile profile) {
|
|
@ -1,52 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Kyle Wood <kyle@denwav.dev>
|
||||
Date: Sun, 6 Aug 2017 17:17:53 -0500
|
||||
Subject: [PATCH] Fix this stupid bullshit
|
||||
|
||||
Disable the 15 second sleep when the server jar hasn't been rebuilt within a period of time.
|
||||
|
||||
modified in order to prevent merge conflicts when Spigot changes/disables the warning,
|
||||
and to provide some level of hint without being disruptive.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/Bootstrap.java b/src/main/java/net/minecraft/server/Bootstrap.java
|
||||
index e359919de57f97d18667df1b2f1bf54a19a49c2f..c5822637e48fad4ca4e8cf210431b5eafbf5abb1 100644
|
||||
--- a/src/main/java/net/minecraft/server/Bootstrap.java
|
||||
+++ b/src/main/java/net/minecraft/server/Bootstrap.java
|
||||
@@ -46,7 +46,7 @@ public class Bootstrap {
|
||||
public static void bootStrap() {
|
||||
if (!Bootstrap.isBootstrapped) {
|
||||
// CraftBukkit start
|
||||
- String name = Bootstrap.class.getSimpleName();
|
||||
+ /*String name = Bootstrap.class.getSimpleName(); // Paper
|
||||
switch (name) {
|
||||
case "DispenserRegistry":
|
||||
break;
|
||||
@@ -60,7 +60,7 @@ public class Bootstrap {
|
||||
System.err.println("*** WARNING: This server jar is unsupported, use at your own risk. ***");
|
||||
System.err.println("**********************************************************************");
|
||||
break;
|
||||
- }
|
||||
+ }*/ // Paper
|
||||
// CraftBukkit end
|
||||
Bootstrap.isBootstrapped = true;
|
||||
if (Registry.REGISTRY.keySet().isEmpty()) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
index 5cae8fdd1ad63f49580d69a8c337ae22c0923c5c..d7d2618bed5188c6e6cc4db6669f3842d0bfff0c 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
@@ -241,10 +241,12 @@ public class Main {
|
||||
Calendar deadline = Calendar.getInstance();
|
||||
deadline.add(Calendar.DAY_OF_YEAR, -28);
|
||||
if (buildDate.before(deadline.getTime())) {
|
||||
- System.err.println("*** Error, this build is outdated ***");
|
||||
+ // Paper start - This is some stupid bullshit
|
||||
+ System.err.println("*** Warning, you've not updated in a while! ***");
|
||||
System.err.println("*** Please download a new build as per instructions from https://papermc.io/downloads ***"); // Paper
|
||||
- System.err.println("*** Server will start in 20 seconds ***");
|
||||
- Thread.sleep(TimeUnit.SECONDS.toMillis(20));
|
||||
+ //System.err.println("*** Server will start in 20 seconds ***");
|
||||
+ //Thread.sleep(TimeUnit.SECONDS.toMillis(20));
|
||||
+ // Paper End
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Mon, 31 Jul 2017 01:49:48 -0500
|
||||
Subject: [PATCH] LivingEntity#setKiller
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.entity.LivingEntity lastHurtByPlayerTime
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
|
||||
index 4f4ee7071183e7eef918741e38c2bc2e522c72df..a08fd99fb97d8c880c855e6af2a99afcfa8098b5 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
|
||||
@@ -347,6 +347,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
|
||||
return this.getHandle().lastHurtByPlayer == null ? null : (Player) this.getHandle().lastHurtByPlayer.getBukkitEntity();
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public void setKiller(Player killer) {
|
||||
+ net.minecraft.server.level.ServerPlayer entityPlayer = killer == null ? null : ((CraftPlayer) killer).getHandle();
|
||||
+ getHandle().lastHurtByPlayer = entityPlayer;
|
||||
+ getHandle().lastHurtByMob = entityPlayer;
|
||||
+ getHandle().lastHurtByPlayerTime = entityPlayer == null ? 0 : 100; // 100 value taken from EntityLiving#damageEntity
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public boolean addPotionEffect(PotionEffect effect) {
|
||||
return this.addPotionEffect(effect, false);
|
|
@ -1,19 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Mon, 31 Jul 2017 01:54:40 -0500
|
||||
Subject: [PATCH] Ocelot despawns should honor nametags and leash
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/Ocelot.java b/src/main/java/net/minecraft/world/entity/animal/Ocelot.java
|
||||
index 4b9e3729279f3bfabab4227c511c4bf89488ff8c..6a459435493295ee5bb44fe2ba79cba6acea2e35 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/Ocelot.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/Ocelot.java
|
||||
@@ -133,7 +133,7 @@ public class Ocelot extends Animal {
|
||||
|
||||
@Override
|
||||
public boolean removeWhenFarAway(double distanceSquared) {
|
||||
- return !this.isTrusting() && this.tickCount > 2400;
|
||||
+ return !this.isTrusting() && this.tickCount > 2400 && !this.hasCustomName() && !this.isLeashed(); // Paper - honor name and leash
|
||||
}
|
||||
|
||||
public static AttributeSupplier.Builder createAttributes() {
|
|
@ -1,27 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Mon, 31 Jul 2017 01:45:19 -0500
|
||||
Subject: [PATCH] Reset spawner timer when spawner event is cancelled
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java
|
||||
index d09d586fd649f5b13c1515a8b0f869c1d6033cce..796e3bde04a118076ea004b0d58fd25641a7611e 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java
|
||||
@@ -160,6 +160,7 @@ public abstract class BaseSpawner {
|
||||
// Spigot End
|
||||
}
|
||||
entity.spawnedViaMobSpawner = true; // Paper
|
||||
+ flag = true; // Paper
|
||||
// Spigot Start
|
||||
if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, pos).isCancelled()) {
|
||||
Entity vehicle = entity.getVehicle();
|
||||
@@ -184,7 +185,7 @@ public abstract class BaseSpawner {
|
||||
((Mob) entity).spawnAnim();
|
||||
}
|
||||
|
||||
- flag = true;
|
||||
+ //flag = true; // Paper - moved up above cancellable event
|
||||
}
|
||||
}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: kashike <kashike@vq.lc>
|
||||
Date: Thu, 17 Aug 2017 16:08:20 -0700
|
||||
Subject: [PATCH] Allow specifying a custom "authentication servers down" kick
|
||||
message
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
index 187692ea25983195a0fe14a7dc070fd33acb0037..1cbcee5b2cebe9f2c2ede3d7628ace6452a480f0 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
@@ -333,7 +333,7 @@ public class ServerLoginPacketListenerImpl implements TickablePacketListener, Se
|
||||
ServerLoginPacketListenerImpl.this.gameProfile = gameprofile;
|
||||
ServerLoginPacketListenerImpl.this.state = ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT;
|
||||
} else {
|
||||
- ServerLoginPacketListenerImpl.this.disconnect(Component.translatable("multiplayer.disconnect.authservers_down"));
|
||||
+ ServerLoginPacketListenerImpl.this.disconnect(io.papermc.paper.adventure.PaperAdventure.asVanilla(io.papermc.paper.configuration.GlobalConfiguration.get().messages.kick.authenticationServersDown)); // Paper
|
||||
ServerLoginPacketListenerImpl.LOGGER.error("Couldn't verify username because servers are unavailable");
|
||||
}
|
||||
// CraftBukkit start - catch all exceptions
|
|
@ -1,71 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Minecrell <minecrell@minecrell.net>
|
||||
Date: Thu, 21 Sep 2017 16:14:55 +0200
|
||||
Subject: [PATCH] Handle plugin prefixes using Log4J configuration
|
||||
|
||||
Display logger name in the console for all loggers except the
|
||||
root logger, Bukkit's logger ("Minecraft") and Minecraft loggers.
|
||||
Since plugins now use the plugin name as logger name this will
|
||||
restore the plugin prefixes without having to prepend them manually
|
||||
to the log messages.
|
||||
|
||||
Logger prefixes are shown by default for all loggers except for
|
||||
the root logger, the Minecraft/Mojang loggers and the Bukkit loggers.
|
||||
This may cause additional prefixes to be disabled for plugins bypassing
|
||||
the plugin logger.
|
||||
|
||||
diff --git a/build.gradle.kts b/build.gradle.kts
|
||||
index d4141a24cb5ba20e8c53c85206b32120ff18eb48..a57fad0a75fe18f70d3dd6cd5c6a2ab90eb0498d 100644
|
||||
--- a/build.gradle.kts
|
||||
+++ b/build.gradle.kts
|
||||
@@ -17,7 +17,7 @@ dependencies {
|
||||
all its classes to check if they are plugins.
|
||||
Scanning takes about 1-2 seconds so adding this speeds up the server start.
|
||||
*/
|
||||
- runtimeOnly("org.apache.logging.log4j:log4j-core:2.14.1")
|
||||
+ implementation("org.apache.logging.log4j:log4j-core:2.14.1") // Paper - implementation
|
||||
// Paper end
|
||||
implementation("org.apache.logging.log4j:log4j-iostreams:2.17.1") // Paper
|
||||
implementation("org.ow2.asm:asm:9.3")
|
||||
diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java
|
||||
index 051d7c7fc5796ad056ae1ba5e5e630fde8794108..c2e3d32e51902503af88f089e366e784f42d999a 100644
|
||||
--- a/src/main/java/org/spigotmc/SpigotConfig.java
|
||||
+++ b/src/main/java/org/spigotmc/SpigotConfig.java
|
||||
@@ -290,7 +290,7 @@ public class SpigotConfig
|
||||
private static void playerSample()
|
||||
{
|
||||
SpigotConfig.playerSample = SpigotConfig.getInt( "settings.sample-count", 12 );
|
||||
- System.out.println( "Server Ping Player Sample Count: " + SpigotConfig.playerSample );
|
||||
+ Bukkit.getLogger().log( Level.INFO, "Server Ping Player Sample Count: {0}", playerSample ); // Paper - Use logger
|
||||
}
|
||||
|
||||
public static int playerShuffle;
|
||||
diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml
|
||||
index 620b9490e5f159080e50289d127404a1b56adbef..a8bdaaeaa1a9316848416f0533739b9b083ca151 100644
|
||||
--- a/src/main/resources/log4j2.xml
|
||||
+++ b/src/main/resources/log4j2.xml
|
||||
@@ -5,10 +5,22 @@
|
||||
<PatternLayout pattern="[%d{HH:mm:ss} %level]: %msg%n" />
|
||||
</Queue>
|
||||
<TerminalConsole name="TerminalConsole">
|
||||
- <PatternLayout pattern="%highlightError{[%d{HH:mm:ss} %level]: %minecraftFormatting{%msg}%n%xEx}" />
|
||||
+ <PatternLayout>
|
||||
+ <LoggerNamePatternSelector defaultPattern="%highlightError{[%d{HH:mm:ss} %level]: [%logger] %minecraftFormatting{%msg}%n%xEx}">
|
||||
+ <!-- Log root, Minecraft, Mojang and Bukkit loggers without prefix -->
|
||||
+ <PatternMatch key=",net.minecraft.,Minecraft,com.mojang."
|
||||
+ pattern="%highlightError{[%d{HH:mm:ss} %level]: %minecraftFormatting{%msg}%n%xEx}" />
|
||||
+ </LoggerNamePatternSelector>
|
||||
+ </PatternLayout>
|
||||
</TerminalConsole>
|
||||
<RollingRandomAccessFile name="File" fileName="logs/latest.log" filePattern="logs/%d{yyyy-MM-dd}-%i.log.gz">
|
||||
- <PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level]: %minecraftFormatting{%msg}{strip}%n" />
|
||||
+ <PatternLayout>
|
||||
+ <LoggerNamePatternSelector defaultPattern="[%d{HH:mm:ss}] [%t/%level]: [%logger] %minecraftFormatting{%msg}{strip}%n">
|
||||
+ <!-- Log root, Minecraft, Mojang and Bukkit loggers without prefix -->
|
||||
+ <PatternMatch key=",net.minecraft.,Minecraft,com.mojang."
|
||||
+ pattern="[%d{HH:mm:ss}] [%t/%level]: %minecraftFormatting{%msg}{strip}%n" />
|
||||
+ </LoggerNamePatternSelector>
|
||||
+ </PatternLayout>
|
||||
<Policies>
|
||||
<TimeBasedTriggeringPolicy />
|
||||
<OnStartupTriggeringPolicy />
|
|
@ -1,47 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Minecrell <minecrell@minecrell.net>
|
||||
Date: Sat, 23 Sep 2017 21:07:20 +0200
|
||||
Subject: [PATCH] Improve Log4J Configuration / Plugin Loggers
|
||||
|
||||
Add full exceptions to log4j to not truncate stack traces
|
||||
|
||||
Disable logger prefix for various plugins bypassing the plugin logger
|
||||
|
||||
Some plugins bypass the plugin logger and add the plugin prefix
|
||||
manually to the log message. Since they use other logger names
|
||||
(e.g. qualified class names) these would now also appear in the
|
||||
log. Disable the logger prefix for these plugins so the messages
|
||||
show up correctly.
|
||||
|
||||
diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml
|
||||
index a8bdaaeaa1a9316848416f0533739b9b083ca151..476f4a5cbe664ddd05474cb88553018bd334a5b8 100644
|
||||
--- a/src/main/resources/log4j2.xml
|
||||
+++ b/src/main/resources/log4j2.xml
|
||||
@@ -6,19 +6,21 @@
|
||||
</Queue>
|
||||
<TerminalConsole name="TerminalConsole">
|
||||
<PatternLayout>
|
||||
- <LoggerNamePatternSelector defaultPattern="%highlightError{[%d{HH:mm:ss} %level]: [%logger] %minecraftFormatting{%msg}%n%xEx}">
|
||||
+ <LoggerNamePatternSelector defaultPattern="%highlightError{[%d{HH:mm:ss} %level]: [%logger] %minecraftFormatting{%msg}%n%xEx{full}}">
|
||||
<!-- Log root, Minecraft, Mojang and Bukkit loggers without prefix -->
|
||||
- <PatternMatch key=",net.minecraft.,Minecraft,com.mojang."
|
||||
- pattern="%highlightError{[%d{HH:mm:ss} %level]: %minecraftFormatting{%msg}%n%xEx}" />
|
||||
+ <!-- Disable prefix for various plugins that bypass the plugin logger -->
|
||||
+ <PatternMatch key=",net.minecraft.,Minecraft,com.mojang.,com.sk89q.,ru.tehkode.,Minecraft.AWE"
|
||||
+ pattern="%highlightError{[%d{HH:mm:ss} %level]: %minecraftFormatting{%msg}%n%xEx{full}}" />
|
||||
</LoggerNamePatternSelector>
|
||||
</PatternLayout>
|
||||
</TerminalConsole>
|
||||
<RollingRandomAccessFile name="File" fileName="logs/latest.log" filePattern="logs/%d{yyyy-MM-dd}-%i.log.gz">
|
||||
<PatternLayout>
|
||||
- <LoggerNamePatternSelector defaultPattern="[%d{HH:mm:ss}] [%t/%level]: [%logger] %minecraftFormatting{%msg}{strip}%n">
|
||||
+ <LoggerNamePatternSelector defaultPattern="[%d{HH:mm:ss}] [%t/%level]: [%logger] %minecraftFormatting{%msg}{strip}%n%xEx{full}">
|
||||
<!-- Log root, Minecraft, Mojang and Bukkit loggers without prefix -->
|
||||
- <PatternMatch key=",net.minecraft.,Minecraft,com.mojang."
|
||||
- pattern="[%d{HH:mm:ss}] [%t/%level]: %minecraftFormatting{%msg}{strip}%n" />
|
||||
+ <!-- Disable prefix for various plugins that bypass the plugin logger -->
|
||||
+ <PatternMatch key=",net.minecraft.,Minecraft,com.mojang.,com.sk89q.,ru.tehkode.,Minecraft.AWE"
|
||||
+ pattern="[%d{HH:mm:ss}] [%t/%level]: %minecraftFormatting{%msg}{strip}%n%xEx{full}" />
|
||||
</LoggerNamePatternSelector>
|
||||
</PatternLayout>
|
||||
<Policies>
|
|
@ -1,46 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach.brown@destroystokyo.com>
|
||||
Date: Thu, 28 Sep 2017 17:21:44 -0400
|
||||
Subject: [PATCH] Add PlayerJumpEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 5a8008b507b93768526184ddaca170bccb67f92a..4f677103cdbda994355924ebeb822009a97345cd 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -1293,7 +1293,34 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
||||
boolean flag = d8 > 0.0D;
|
||||
|
||||
if (this.player.isOnGround() && !packet.isOnGround() && flag) {
|
||||
- this.player.jumpFromGround();
|
||||
+ // Paper start - Add player jump event
|
||||
+ Player player = this.getCraftPlayer();
|
||||
+ Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location.
|
||||
+ Location to = player.getLocation().clone(); // Start off the To location as the Players current location.
|
||||
+
|
||||
+ // If the packet contains movement information then we update the To location with the correct XYZ.
|
||||
+ if (packet.hasPos) {
|
||||
+ to.setX(packet.x);
|
||||
+ to.setY(packet.y);
|
||||
+ to.setZ(packet.z);
|
||||
+ }
|
||||
+
|
||||
+ // If the packet contains look information then we update the To location with the correct Yaw & Pitch.
|
||||
+ if (packet.hasRot) {
|
||||
+ to.setYaw(packet.yRot);
|
||||
+ to.setPitch(packet.xRot);
|
||||
+ }
|
||||
+
|
||||
+ com.destroystokyo.paper.event.player.PlayerJumpEvent event = new com.destroystokyo.paper.event.player.PlayerJumpEvent(player, from, to);
|
||||
+
|
||||
+ if (event.callEvent()) {
|
||||
+ this.player.jumpFromGround();
|
||||
+ } else {
|
||||
+ from = event.getFrom();
|
||||
+ this.internalTeleport(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch(), Collections.emptySet(), false);
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
boolean flag1 = this.player.verticalCollisionBelow;
|
|
@ -1,40 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Thu, 5 Oct 2017 01:54:07 +0100
|
||||
Subject: [PATCH] handle ServerboundKeepAlivePacket async
|
||||
|
||||
In 1.12.2, Mojang moved the processing of ServerboundKeepAlivePacket off the main
|
||||
thread, while entirely correct for the server, this causes issues with
|
||||
plugins which are expecting the PlayerQuitEvent on the main thread.
|
||||
|
||||
In order to counteract some bad behavior, we will post handling of the
|
||||
disconnection to the main thread, but leave the actual processing of the packet
|
||||
off the main thread.
|
||||
|
||||
also adding some additional logging in order to help work out what is causing
|
||||
random disconnections for clients.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 4f677103cdbda994355924ebeb822009a97345cd..66668dbd2a26f566b3a965921de25a1998fbcd53 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -3242,14 +3242,18 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
||||
|
||||
@Override
|
||||
public void handleKeepAlive(ServerboundKeepAlivePacket packet) {
|
||||
- PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); // CraftBukkit
|
||||
+ //PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); // CraftBukkit // Paper - This shouldn't be on the main thread
|
||||
if (this.keepAlivePending && packet.getId() == this.keepAliveChallenge) {
|
||||
int i = (int) (Util.getMillis() - this.keepAliveTime);
|
||||
|
||||
this.player.latency = (this.player.latency * 3 + i) / 4;
|
||||
this.keepAlivePending = false;
|
||||
} else if (!this.isSingleplayerOwner()) {
|
||||
+ // Paper start - This needs to be handled on the main thread for plugins
|
||||
+ server.submit(() -> {
|
||||
this.disconnect(Component.translatable("disconnect.timeout"));
|
||||
+ });
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
}
|
|
@ -1,116 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Minecrell <minecrell@minecrell.net>
|
||||
Date: Tue, 10 Oct 2017 18:45:20 +0200
|
||||
Subject: [PATCH] Expose client protocol version and virtual host
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/network/PaperNetworkClient.java b/src/main/java/com/destroystokyo/paper/network/PaperNetworkClient.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..a5a7624f1f372a26b982836cd31cff15e2589e9b
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/network/PaperNetworkClient.java
|
||||
@@ -0,0 +1,49 @@
|
||||
+package com.destroystokyo.paper.network;
|
||||
+
|
||||
+import java.net.InetSocketAddress;
|
||||
+
|
||||
+import javax.annotation.Nullable;
|
||||
+import net.minecraft.network.Connection;
|
||||
+
|
||||
+public class PaperNetworkClient implements NetworkClient {
|
||||
+
|
||||
+ private final Connection networkManager;
|
||||
+
|
||||
+ PaperNetworkClient(Connection networkManager) {
|
||||
+ this.networkManager = networkManager;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public InetSocketAddress getAddress() {
|
||||
+ return (InetSocketAddress) this.networkManager.getRemoteAddress();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getProtocolVersion() {
|
||||
+ return this.networkManager.protocolVersion;
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ @Override
|
||||
+ public InetSocketAddress getVirtualHost() {
|
||||
+ return this.networkManager.virtualHost;
|
||||
+ }
|
||||
+
|
||||
+ public static InetSocketAddress prepareVirtualHost(String host, int port) {
|
||||
+ int len = host.length();
|
||||
+
|
||||
+ // FML appends a marker to the host to recognize FML clients (\0FML\0)
|
||||
+ int pos = host.indexOf('\0');
|
||||
+ if (pos >= 0) {
|
||||
+ len = pos;
|
||||
+ }
|
||||
+
|
||||
+ // When clients connect with a SRV record, their host contains a trailing '.'
|
||||
+ if (len > 0 && host.charAt(len - 1) == '.') {
|
||||
+ len--;
|
||||
+ }
|
||||
+
|
||||
+ return InetSocketAddress.createUnresolved(host.substring(0, len), port);
|
||||
+ }
|
||||
+
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
|
||||
index 463d54c6c808808d3d7fe6d5303be48844bb4444..8774d3f1a1b0019751e515ad94c85ba2f11e80c7 100644
|
||||
--- a/src/main/java/net/minecraft/network/Connection.java
|
||||
+++ b/src/main/java/net/minecraft/network/Connection.java
|
||||
@@ -112,6 +112,10 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
}
|
||||
}
|
||||
// Paper end - add pending task queue
|
||||
+ // Paper start - NetworkClient implementation
|
||||
+ public int protocolVersion;
|
||||
+ public java.net.InetSocketAddress virtualHost;
|
||||
+ // Paper end
|
||||
|
||||
public Connection(PacketFlow side) {
|
||||
this.receiving = side;
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
|
||||
index 8284d49c8e30645d00be952c847bab7ce5753d78..a738b79e775a0a4abed1a05e12495d85f3de14bb 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
|
||||
@@ -154,6 +154,10 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL
|
||||
throw new UnsupportedOperationException("Invalid intention " + packet.getIntention());
|
||||
}
|
||||
|
||||
+ // Paper start - NetworkClient implementation
|
||||
+ this.connection.protocolVersion = packet.getProtocolVersion();
|
||||
+ this.connection.virtualHost = com.destroystokyo.paper.network.PaperNetworkClient.prepareVirtualHost(packet.hostName, packet.port);
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index 87c8e494aa374b8bfb8b8432723783b00ba94763..6dd5deecd404a3b9858e63da6837caf2d5d382f0 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -299,6 +299,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start - Implement NetworkClient
|
||||
+ @Override
|
||||
+ public int getProtocolVersion() {
|
||||
+ if (getHandle().connection == null) return -1;
|
||||
+ return getHandle().connection.connection.protocolVersion;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public InetSocketAddress getVirtualHost() {
|
||||
+ if (getHandle().connection == null) return null;
|
||||
+ return getHandle().connection.connection.virtualHost;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public double getEyeHeight(boolean ignorePose) {
|
||||
if (ignorePose) {
|
|
@ -1,72 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Sun, 15 Oct 2017 00:29:07 +0100
|
||||
Subject: [PATCH] revert serverside behavior of keepalives
|
||||
|
||||
This patch intends to bump up the time that a client has to reply to the
|
||||
server back to 30 seconds as per pre 1.12.2, which allowed clients
|
||||
more than enough time to reply potentially allowing them to be less
|
||||
tempermental due to lag spikes on the network thread, e.g. that caused
|
||||
by plugins that are interacting with netty.
|
||||
|
||||
We also add a system property to allow people to tweak how long the server
|
||||
will wait for a reply. There is a compromise here between lower and higher
|
||||
values, lower values will mean that dead connections can be closed sooner,
|
||||
whereas higher values will make this less sensitive to issues such as spikes
|
||||
from networking or during connections flood of chunk packets on slower clients,
|
||||
at the cost of dead connections being kept open for longer.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 66668dbd2a26f566b3a965921de25a1998fbcd53..f1e3955625e3ae3e4b47cd53d3af7ec70892add6 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -256,7 +256,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
||||
public ServerPlayer player;
|
||||
private int tickCount;
|
||||
private int ackBlockChangesUpTo = -1;
|
||||
- private long keepAliveTime;
|
||||
+ private long keepAliveTime = Util.getMillis();
|
||||
private boolean keepAlivePending;
|
||||
private long keepAliveChallenge;
|
||||
// CraftBukkit start - multithreaded fields
|
||||
@@ -293,6 +293,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
||||
private final SignedMessageChain.Decoder signedMessageDecoder;
|
||||
private final LastSeenMessagesValidator lastSeenMessagesValidator;
|
||||
private final FutureChain chatMessageChain;
|
||||
+ private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit
|
||||
|
||||
public ServerGamePacketListenerImpl(MinecraftServer server, Connection connection, ServerPlayer player) {
|
||||
this.lastChatTimeStamp = new AtomicReference(Instant.EPOCH);
|
||||
@@ -391,18 +392,25 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
||||
}
|
||||
|
||||
this.server.getProfiler().push("keepAlive");
|
||||
- long i = Util.getMillis();
|
||||
+ // Paper Start - give clients a longer time to respond to pings as per pre 1.12.2 timings
|
||||
+ // This should effectively place the keepalive handling back to "as it was" before 1.12.2
|
||||
+ long currentTime = Util.getMillis();
|
||||
+ long elapsedTime = currentTime - this.keepAliveTime;
|
||||
|
||||
- if (i - this.keepAliveTime >= 25000L) { // CraftBukkit
|
||||
- if (this.keepAlivePending) {
|
||||
- this.disconnect(Component.translatable("disconnect.timeout"));
|
||||
- } else {
|
||||
+ if (this.keepAlivePending) {
|
||||
+ if (!this.processedDisconnect && elapsedTime >= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected
|
||||
+ ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked due to keepalive timeout!", this.player.getScoreboardName()); // more info
|
||||
+ this.disconnect(Component.translatable("disconnect.timeout", new Object[0]));
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (elapsedTime >= 15000L) { // 15 seconds
|
||||
this.keepAlivePending = true;
|
||||
- this.keepAliveTime = i;
|
||||
- this.keepAliveChallenge = i;
|
||||
+ this.keepAliveTime = currentTime;
|
||||
+ this.keepAliveChallenge = currentTime;
|
||||
this.send(new ClientboundKeepAlivePacket(this.keepAliveChallenge));
|
||||
}
|
||||
}
|
||||
+ // Paper end
|
||||
|
||||
this.server.getProfiler().pop();
|
||||
// CraftBukkit start
|
|
@ -1,72 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Brokkonaut <hannos17@gmx.de>
|
||||
Date: Tue, 31 Oct 2017 03:26:18 +0100
|
||||
Subject: [PATCH] Send attack SoundEffects only to players who can see the
|
||||
attacker
|
||||
|
||||
|
||||
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 2fd52878415fca31d053d8d83a53748e8743e352..0dc19e4701b35e94e94f07d261b3dbbdf9567d7b 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
@@ -1246,7 +1246,7 @@ public abstract class Player extends LivingEntity {
|
||||
int i = b0 + EnchantmentHelper.getKnockbackBonus(this);
|
||||
|
||||
if (this.isSprinting() && flag) {
|
||||
- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_KNOCKBACK, this.getSoundSource(), 1.0F, 1.0F);
|
||||
+ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_KNOCKBACK, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility
|
||||
++i;
|
||||
flag1 = true;
|
||||
}
|
||||
@@ -1321,7 +1321,7 @@ public abstract class Player extends LivingEntity {
|
||||
}
|
||||
}
|
||||
|
||||
- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_SWEEP, this.getSoundSource(), 1.0F, 1.0F);
|
||||
+ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_SWEEP, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility
|
||||
this.sweepAttack();
|
||||
}
|
||||
|
||||
@@ -1349,15 +1349,15 @@ public abstract class Player extends LivingEntity {
|
||||
}
|
||||
|
||||
if (flag2) {
|
||||
- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_CRIT, this.getSoundSource(), 1.0F, 1.0F);
|
||||
+ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_CRIT, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility
|
||||
this.crit(target);
|
||||
}
|
||||
|
||||
if (!flag2 && !flag3) {
|
||||
if (flag) {
|
||||
- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_STRONG, this.getSoundSource(), 1.0F, 1.0F);
|
||||
+ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_STRONG, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility
|
||||
} else {
|
||||
- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_WEAK, this.getSoundSource(), 1.0F, 1.0F);
|
||||
+ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_WEAK, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1409,7 +1409,7 @@ public abstract class Player extends LivingEntity {
|
||||
|
||||
this.causeFoodExhaustion(level.spigotConfig.combatExhaustion, EntityExhaustionEvent.ExhaustionReason.ATTACK); // CraftBukkit - EntityExhaustionEvent // Spigot - Change to use configurable value
|
||||
} else {
|
||||
- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_NODAMAGE, this.getSoundSource(), 1.0F, 1.0F);
|
||||
+ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_NODAMAGE, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility
|
||||
if (flag4) {
|
||||
target.clearFire();
|
||||
}
|
||||
@@ -1871,6 +1871,14 @@ public abstract class Player extends LivingEntity {
|
||||
public int getXpNeededForNextLevel() {
|
||||
return this.experienceLevel >= 30 ? 112 + (this.experienceLevel - 30) * 9 : (this.experienceLevel >= 15 ? 37 + (this.experienceLevel - 15) * 5 : 7 + this.experienceLevel * 2);
|
||||
}
|
||||
+ // Paper start - send SoundEffect to everyone who can see fromEntity
|
||||
+ private static void sendSoundEffect(Player fromEntity, double x, double y, double z, SoundEvent soundEffect, SoundSource soundCategory, float volume, float pitch) {
|
||||
+ fromEntity.level.playSound(fromEntity, x, y, z, soundEffect, soundCategory, volume, pitch); // This will not send the effect to the entity himself
|
||||
+ if (fromEntity instanceof ServerPlayer) {
|
||||
+ ((ServerPlayer) fromEntity).connection.send(new net.minecraft.network.protocol.game.ClientboundSoundPacket(soundEffect, soundCategory, x, y, z, volume, pitch, fromEntity.random.nextLong()));
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
// CraftBukkit start
|
||||
public void causeFoodExhaustion(float exhaustion) {
|
|
@ -1,31 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: pkt77 <parkerkt77@gmail.com>
|
||||
Date: Fri, 10 Nov 2017 23:46:34 -0500
|
||||
Subject: [PATCH] Add PlayerArmorChangeEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index 6295c89211ba86c10009775f4d399f597d240fd0..e49803f36ffea3329a67542882ee58e4762a08e5 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.minecraft.world.entity;
|
||||
|
||||
+import com.destroystokyo.paper.event.player.PlayerArmorChangeEvent; // Paper
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
@@ -3002,6 +3003,13 @@ public abstract class LivingEntity extends Entity {
|
||||
ItemStack itemstack1 = this.getItemBySlot(enumitemslot);
|
||||
|
||||
if (!ItemStack.matches(itemstack1, itemstack)) {
|
||||
+ // Paper start - PlayerArmorChangeEvent
|
||||
+ if (this instanceof ServerPlayer && enumitemslot.getType() == EquipmentSlot.Type.ARMOR) {
|
||||
+ final org.bukkit.inventory.ItemStack oldItem = CraftItemStack.asBukkitCopy(itemstack);
|
||||
+ final org.bukkit.inventory.ItemStack newItem = CraftItemStack.asBukkitCopy(itemstack1);
|
||||
+ new PlayerArmorChangeEvent((Player) this.getBukkitEntity(), PlayerArmorChangeEvent.SlotType.valueOf(enumitemslot.name()), oldItem, newItem).callEvent();
|
||||
+ }
|
||||
+ // Paper end
|
||||
if (map == null) {
|
||||
map = Maps.newEnumMap(EquipmentSlot.class);
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: killme <killme-git@ibts.me>
|
||||
Date: Sun, 12 Nov 2017 19:40:01 +0100
|
||||
Subject: [PATCH] Prevent logins from being processed when the player has
|
||||
disconnected
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
index 1cbcee5b2cebe9f2c2ede3d7628ace6452a480f0..07784c0e6eea2a4a91f1453e937e14a4a1faedf5 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
@@ -83,7 +83,11 @@ public class ServerLoginPacketListenerImpl implements TickablePacketListener, Se
|
||||
}
|
||||
// Paper end
|
||||
if (this.state == ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT) {
|
||||
- this.handleAcceptedLogin();
|
||||
+ // Paper start - prevent logins to be processed even though disconnect was called
|
||||
+ if (connection.isConnected()) {
|
||||
+ this.handleAcceptedLogin();
|
||||
+ }
|
||||
+ // Paper end
|
||||
} else if (this.state == ServerLoginPacketListenerImpl.State.DELAY_ACCEPT) {
|
||||
ServerPlayer entityplayer = this.server.getPlayerList().getPlayer(this.gameProfile.getId());
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: mezz <tehgeek@gmail.com>
|
||||
Date: Wed, 9 Aug 2017 17:51:22 -0500
|
||||
Subject: [PATCH] Fix MC-117075: TE Unload Lag Spike
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
||||
index 1954a93a1f566c1c79cdc2e0eb1b41141d6b5fde..6cc047624746d33ed971ec2dc8f64490bdcaeea8 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/Level.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
||||
@@ -696,6 +696,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
// Spigot start
|
||||
// Iterator iterator = this.blockEntityTickers.iterator();
|
||||
int tilesThisCycle = 0;
|
||||
+ var toRemove = new it.unimi.dsi.fastutil.objects.ObjectOpenCustomHashSet<TickingBlockEntity>(net.minecraft.Util.identityStrategy()); // Paper - use removeAll
|
||||
+ toRemove.add(null);
|
||||
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(tileTickPosition);
|
||||
@@ -703,7 +705,6 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
if (tickingblockentity == null) {
|
||||
this.getCraftServer().getLogger().severe("Spigot has detected a null entity and has removed it, preventing a crash");
|
||||
tilesThisCycle--;
|
||||
- this.blockEntityTickers.remove(this.tileTickPosition--);
|
||||
continue;
|
||||
}
|
||||
// Spigot end
|
||||
@@ -711,12 +712,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
if (tickingblockentity.isRemoved()) {
|
||||
// Spigot start
|
||||
tilesThisCycle--;
|
||||
- this.blockEntityTickers.remove(this.tileTickPosition--);
|
||||
+ toRemove.add(tickingblockentity); // Paper - use removeAll
|
||||
// Spigot end
|
||||
} else if (this.shouldTickBlocksAt(tickingblockentity.getPos())) {
|
||||
tickingblockentity.tick();
|
||||
}
|
||||
}
|
||||
+ this.blockEntityTickers.removeAll(toRemove);
|
||||
|
||||
timings.tileEntityTick.stopTiming(); // Spigot
|
||||
this.tickingBlockEntities = false;
|
|
@ -1,60 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Thu, 16 Nov 2017 12:12:41 +0000
|
||||
Subject: [PATCH] use CB BlockState implementations for captured blocks
|
||||
|
||||
When modifying the world, CB will store a copy of the affected
|
||||
blocks in order to restore their state in the case that the event
|
||||
is cancelled. This change only modifies the collection of blocks
|
||||
in the world by normal means, e.g. not during tree population,
|
||||
as the potentially marginal overheads would serve no advantage.
|
||||
|
||||
CB was using a CraftBlockState for all blocks, which causes issues
|
||||
should any block that uses information beyond a data ID would suffer
|
||||
from missing information, e.g. Skulls.
|
||||
|
||||
By using CBs CraftBlock#getState(), we will maintain a proper copy of
|
||||
the blockstate that will be valid for restoration, as opposed to dropping
|
||||
information on restoration when the event is cancelled.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
||||
index 6cc047624746d33ed971ec2dc8f64490bdcaeea8..e11e3ee5a11ebed7a1550da14c3c5c54962e4fdf 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/Level.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
||||
@@ -148,7 +148,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
public boolean preventPoiUpdated = false; // CraftBukkit - SPIGOT-5710
|
||||
public boolean captureBlockStates = false;
|
||||
public boolean captureTreeGeneration = false;
|
||||
- public Map<BlockPos, CapturedBlockState> capturedBlockStates = new java.util.LinkedHashMap<>();
|
||||
+ public Map<BlockPos, org.bukkit.craftbukkit.block.CraftBlockState> capturedBlockStates = new java.util.LinkedHashMap<>(); // Paper
|
||||
public Map<BlockPos, BlockEntity> capturedTileEntities = new HashMap<>();
|
||||
public List<ItemEntity> captureDrops;
|
||||
public final it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap<SpawnCategory> ticksPerSpawnCategory = new it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap<>();
|
||||
@@ -376,7 +376,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) {
|
||||
// CraftBukkit start - tree generation
|
||||
if (this.captureTreeGeneration) {
|
||||
- CapturedBlockState blockstate = this.capturedBlockStates.get(pos);
|
||||
+ CraftBlockState blockstate = this.capturedBlockStates.get(pos);
|
||||
if (blockstate == null) {
|
||||
blockstate = CapturedBlockState.getTreeBlockState(this, pos, flags);
|
||||
this.capturedBlockStates.put(pos.immutable(), blockstate);
|
||||
@@ -396,7 +396,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
// CraftBukkit start - capture blockstates
|
||||
boolean captured = false;
|
||||
if (this.captureBlockStates && !this.capturedBlockStates.containsKey(pos)) {
|
||||
- CapturedBlockState blockstate = CapturedBlockState.getBlockState(this, pos, flags);
|
||||
+ CraftBlockState blockstate = (CraftBlockState) world.getBlockAt(pos.getX(), pos.getY(), pos.getZ()).getState(); // Paper - use CB getState to get a suitable snapshot
|
||||
+ blockstate.setFlag(flags); // Paper - set flag
|
||||
this.capturedBlockStates.put(pos.immutable(), blockstate);
|
||||
captured = true;
|
||||
}
|
||||
@@ -608,7 +609,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
public BlockState getBlockState(BlockPos pos) {
|
||||
// CraftBukkit start - tree generation
|
||||
if (this.captureTreeGeneration) {
|
||||
- CapturedBlockState previous = this.capturedBlockStates.get(pos);
|
||||
+ CraftBlockState previous = this.capturedBlockStates.get(pos); // Paper
|
||||
if (previous != null) {
|
||||
return previous.getHandle();
|
||||
}
|
|
@ -1,165 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 6 Nov 2017 21:08:22 -0500
|
||||
Subject: [PATCH] API to get a BlockState without a snapshot
|
||||
|
||||
This allows you to get a BlockState without creating a snapshot, operating
|
||||
on the real tile entity.
|
||||
|
||||
This is useful for where performance is needed
|
||||
|
||||
also Avoid NPE during CraftBlockEntityState load if could not get TE
|
||||
|
||||
If Tile Entity was null, correct Sign to return empty lines instead of null
|
||||
|
||||
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 148e79ae4e24fe16dbbb17550c3f258d4362c266..06beb18e5e1950aeb6cb427876fcc4c5ea95adb2 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
|
||||
@@ -45,6 +45,7 @@ public abstract class BlockEntity {
|
||||
this.type = type;
|
||||
this.worldPosition = pos.immutable();
|
||||
this.blockState = state;
|
||||
+ this.persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); // Paper - always init
|
||||
}
|
||||
|
||||
public static BlockPos getPosFromTag(CompoundTag nbt) {
|
||||
@@ -66,7 +67,7 @@ public abstract class BlockEntity {
|
||||
|
||||
// CraftBukkit start - read container
|
||||
public void load(CompoundTag nbt) {
|
||||
- this.persistentDataContainer = new CraftPersistentDataContainer(BlockEntity.DATA_TYPE_REGISTRY);
|
||||
+ this.persistentDataContainer.clear(); // Paper - clear instead of init
|
||||
|
||||
net.minecraft.nbt.Tag persistentDataTag = nbt.get("PublicBukkitValues");
|
||||
if (persistentDataTag instanceof CompoundTag) {
|
||||
@@ -240,8 +241,15 @@ public abstract class BlockEntity {
|
||||
|
||||
// CraftBukkit start - add method
|
||||
public InventoryHolder getOwner() {
|
||||
+ // Paper start
|
||||
+ return getOwner(true);
|
||||
+ }
|
||||
+ public InventoryHolder getOwner(boolean useSnapshot) {
|
||||
+ // Paper end
|
||||
if (this.level == null) return null;
|
||||
- org.bukkit.block.BlockState state = this.level.getWorld().getBlockAt(this.worldPosition.getX(), this.worldPosition.getY(), this.worldPosition.getZ()).getState();
|
||||
+ org.bukkit.block.Block block = this.level.getWorld().getBlockAt(this.worldPosition.getX(), this.worldPosition.getY(), this.worldPosition.getZ());
|
||||
+ if (block.getType() == org.bukkit.Material.AIR) return null;
|
||||
+ org.bukkit.block.BlockState state = block.getState(useSnapshot); // Paper
|
||||
if (state instanceof InventoryHolder) return (InventoryHolder) state;
|
||||
return null;
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
|
||||
index 52fc42050d5df0882586c8f4bb4890ef1dbf979e..ba8f9ffed49bf377be8b37532d4f2bdcb8c44d82 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
|
||||
@@ -329,6 +329,13 @@ public class CraftBlock implements Block {
|
||||
return CraftBlockStates.getBlockState(this);
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public BlockState getState(boolean useSnapshot) {
|
||||
+ return CraftBlockStates.getBlockState(this, useSnapshot);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public Biome getBiome() {
|
||||
return this.getWorld().getBiome(this.getX(), this.getY(), this.getZ());
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
|
||||
index 7629a51ec284cab0db7e9238027d6acfa4f3083c..a76cce199acdcecfdd8b998ec08974c2ed0751cf 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
|
||||
@@ -10,15 +10,26 @@ public class CraftBlockEntityState<T extends BlockEntity> extends CraftBlockStat
|
||||
|
||||
private final T tileEntity;
|
||||
private final T snapshot;
|
||||
+ public final boolean snapshotDisabled; // Paper
|
||||
+ public static boolean DISABLE_SNAPSHOT = false; // Paper
|
||||
|
||||
public CraftBlockEntityState(World world, T tileEntity) {
|
||||
super(world, tileEntity.getBlockPos(), tileEntity.getBlockState());
|
||||
|
||||
this.tileEntity = tileEntity;
|
||||
|
||||
+ // Paper start
|
||||
+ this.snapshotDisabled = DISABLE_SNAPSHOT;
|
||||
+ if (DISABLE_SNAPSHOT) {
|
||||
+ this.snapshot = this.tileEntity;
|
||||
+ } else {
|
||||
+ this.snapshot = this.createSnapshot(tileEntity);
|
||||
+ }
|
||||
// copy tile entity data:
|
||||
- this.snapshot = this.createSnapshot(tileEntity);
|
||||
- this.load(snapshot);
|
||||
+ if (this.snapshot != null) {
|
||||
+ this.load(this.snapshot);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
public void refreshSnapshot() {
|
||||
@@ -105,4 +116,11 @@ public class CraftBlockEntityState<T extends BlockEntity> extends CraftBlockStat
|
||||
public PersistentDataContainer getPersistentDataContainer() {
|
||||
return this.getSnapshot().persistentDataContainer;
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public boolean isSnapshot() {
|
||||
+ return !this.snapshotDisabled;
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java
|
||||
index 521d981e72955b1e2c96427882e336b034456678..e609cfeaf5aa6807f57360dde9b0dccf40a23eb1 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java
|
||||
@@ -336,15 +336,30 @@ public final class CraftBlockStates {
|
||||
}
|
||||
|
||||
public static BlockState getBlockState(Block block) {
|
||||
+ // Paper start
|
||||
+ return CraftBlockStates.getBlockState(block, true);
|
||||
+ }
|
||||
+ public static BlockState getBlockState(Block block, boolean useSnapshot) {
|
||||
+ // Paper end
|
||||
Preconditions.checkNotNull(block, "block is null");
|
||||
CraftBlock craftBlock = (CraftBlock) block;
|
||||
CraftWorld world = (CraftWorld) block.getWorld();
|
||||
BlockPos blockPosition = craftBlock.getPosition();
|
||||
net.minecraft.world.level.block.state.BlockState blockData = craftBlock.getNMS();
|
||||
BlockEntity tileEntity = craftBlock.getHandle().getBlockEntity(blockPosition);
|
||||
+ // Paper start - block state snapshots
|
||||
+ boolean prev = CraftBlockEntityState.DISABLE_SNAPSHOT;
|
||||
+ CraftBlockEntityState.DISABLE_SNAPSHOT = !useSnapshot;
|
||||
+ try {
|
||||
+ // Paper end
|
||||
CraftBlockState blockState = CraftBlockStates.getBlockState(world, blockPosition, blockData, tileEntity);
|
||||
blockState.setWorldHandle(craftBlock.getHandle()); // Inject the block's generator access
|
||||
return blockState;
|
||||
+ // Paper start
|
||||
+ } finally {
|
||||
+ CraftBlockEntityState.DISABLE_SNAPSHOT = prev;
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
public static BlockState getBlockState(Material material, @Nullable CompoundTag blockEntityTag) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java
|
||||
index 3fc3907172f12ee24ea70bd6a1ffbbc6084ed971..2c59f09a9261a1690951161fd856a5848d9885b7 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java
|
||||
@@ -156,4 +156,10 @@ public class CraftPersistentDataContainer implements PersistentDataContainer {
|
||||
public Map<String, Object> serialize() {
|
||||
return (Map<String, Object>) CraftNBTTagConfigSerializer.serialize(this.toTagCompound());
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ public void clear() {
|
||||
+ this.customDataTags.clear();
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
|
@ -1,185 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
|
||||
Date: Sun, 26 Nov 2017 13:19:58 -0500
|
||||
Subject: [PATCH] AsyncTabCompleteEvent
|
||||
|
||||
Let plugins be able to control tab completion of commands and chat async.
|
||||
|
||||
This will be useful for frameworks like ACF so we can define async safe completion handlers,
|
||||
and avoid going to main for tab completions.
|
||||
|
||||
Especially useful if you need to query a database in order to obtain the results for tab
|
||||
completion, such as offline players.
|
||||
|
||||
Also adds isCommand and getLocation to the sync TabCompleteEvent
|
||||
|
||||
Co-authored-by: Aikar <aikar@aikar.co>
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index f1e3955625e3ae3e4b47cd53d3af7ec70892add6..b7d700c85d3a8c92e6c3cdd3d266f20f90fb8da8 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -784,12 +784,16 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
||||
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ private static final java.util.concurrent.ExecutorService TAB_COMPLETE_EXECUTOR = java.util.concurrent.Executors.newFixedThreadPool(4,
|
||||
+ new com.google.common.util.concurrent.ThreadFactoryBuilder().setDaemon(true).setNameFormat("Async Tab Complete Thread - #%d").setUncaughtExceptionHandler(new net.minecraft.DefaultUncaughtExceptionHandlerWithName(net.minecraft.server.MinecraftServer.LOGGER)).build());
|
||||
+ // Paper end
|
||||
@Override
|
||||
public void handleCustomCommandSuggestions(ServerboundCommandSuggestionPacket packet) {
|
||||
- PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel());
|
||||
+ // PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); // Paper - run this async
|
||||
// CraftBukkit start
|
||||
if (this.chatSpamTickCount.addAndGet(1) > 500 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) {
|
||||
- this.disconnect(Component.translatable("disconnect.spam"));
|
||||
+ server.scheduleOnMain(() -> this.disconnect(Component.translatable("disconnect.spam", new Object[0]))); // Paper
|
||||
return;
|
||||
}
|
||||
// Paper start
|
||||
@@ -800,18 +804,45 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
||||
}
|
||||
// Paper end
|
||||
// CraftBukkit end
|
||||
+ // Paper start - async tab completion
|
||||
+ TAB_COMPLETE_EXECUTOR.execute(() -> {
|
||||
StringReader stringreader = new StringReader(packet.getCommand());
|
||||
|
||||
if (stringreader.canRead() && stringreader.peek() == '/') {
|
||||
stringreader.skip();
|
||||
}
|
||||
+ final String command = packet.getCommand();
|
||||
+ final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getCraftPlayer(), command, true, null);
|
||||
+ event.callEvent();
|
||||
+ final java.util.List<com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion> completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.completions();
|
||||
+ // If the event isn't handled, we can assume that we have no completions, and so we'll ask the server
|
||||
+ if (!event.isHandled()) {
|
||||
+ if (!event.isCancelled()) {
|
||||
|
||||
- ParseResults<CommandSourceStack> parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack());
|
||||
+ this.server.scheduleOnMain(() -> { // This needs to be on main
|
||||
+ ParseResults<CommandSourceStack> parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack());
|
||||
|
||||
- this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> {
|
||||
- if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [<args>] from showing for plugins with nothing more to offer
|
||||
- this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), suggestions));
|
||||
+ this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> {
|
||||
+ if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [<args>] from showing for plugins with nothing more to offer
|
||||
+ this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), suggestions));
|
||||
+ });
|
||||
+ });
|
||||
+ }
|
||||
+ } else if (!completions.isEmpty()) {
|
||||
+ final com.mojang.brigadier.suggestion.SuggestionsBuilder builder0 = new com.mojang.brigadier.suggestion.SuggestionsBuilder(command, stringreader.getTotalLength());
|
||||
+ final com.mojang.brigadier.suggestion.SuggestionsBuilder builder = builder0.createOffset(builder0.getInput().lastIndexOf(' ') + 1);
|
||||
+ completions.forEach(completion -> {
|
||||
+ final Integer intSuggestion = com.google.common.primitives.Ints.tryParse(completion.suggestion());
|
||||
+ if (intSuggestion != null) {
|
||||
+ builder.suggest(intSuggestion, PaperAdventure.asVanilla(completion.tooltip()));
|
||||
+ } else {
|
||||
+ builder.suggest(completion.suggestion(), PaperAdventure.asVanilla(completion.tooltip()));
|
||||
+ }
|
||||
+ });
|
||||
+ player.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), builder.buildFuture().join()));
|
||||
+ }
|
||||
});
|
||||
+ // Paper end - async tab completion
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index 7013b11fc0cd5fbb5a7e62be45d84d54d3052237..bbf9550e7a7c78e961160ef09466e5f962172b6c 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -2086,7 +2086,7 @@ public final class CraftServer implements Server {
|
||||
offers = this.tabCompleteChat(player, message);
|
||||
}
|
||||
|
||||
- TabCompleteEvent tabEvent = new TabCompleteEvent(player, message, offers);
|
||||
+ TabCompleteEvent tabEvent = new TabCompleteEvent(player, message, offers, message.startsWith("/") || forceCommand, pos != null ? io.papermc.paper.util.MCUtil.toLocation(((CraftWorld) player.getWorld()).getHandle(), new BlockPos(pos)) : null); // Paper
|
||||
this.getPluginManager().callEvent(tabEvent);
|
||||
|
||||
return tabEvent.isCancelled() ? Collections.EMPTY_LIST : tabEvent.getCompletions();
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java
|
||||
index b996fde481cebbbcce80a6c267591136db7cc0bc..14cd8ae69d9b25dc5edad4ff96ff4a9acb1f22cb 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java
|
||||
@@ -28,6 +28,61 @@ public class ConsoleCommandCompleter implements Completer {
|
||||
public void complete(LineReader reader, ParsedLine line, List<Candidate> candidates) {
|
||||
final CraftServer server = this.server.server;
|
||||
final String buffer = line.line();
|
||||
+ // Async Tab Complete
|
||||
+ final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event =
|
||||
+ new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(server.getConsoleSender(), buffer, true, null);
|
||||
+ event.callEvent();
|
||||
+ final List<com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion> completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.completions();
|
||||
+
|
||||
+ if (event.isCancelled() || event.isHandled()) {
|
||||
+ // Still fire sync event with the provided completions, if someone is listening
|
||||
+ if (!event.isCancelled() && TabCompleteEvent.getHandlerList().getRegisteredListeners().length > 0) {
|
||||
+ List<com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion> finalCompletions = new java.util.ArrayList<>(completions);
|
||||
+ Waitable<List<String>> syncCompletions = new Waitable<List<String>>() {
|
||||
+ @Override
|
||||
+ protected List<String> evaluate() {
|
||||
+ org.bukkit.event.server.TabCompleteEvent syncEvent = new org.bukkit.event.server.TabCompleteEvent(server.getConsoleSender(), buffer,
|
||||
+ finalCompletions.stream()
|
||||
+ .map(com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion::suggestion)
|
||||
+ .collect(java.util.stream.Collectors.toList()));
|
||||
+ return syncEvent.callEvent() ? syncEvent.getCompletions() : com.google.common.collect.ImmutableList.of();
|
||||
+ }
|
||||
+ };
|
||||
+ server.getServer().processQueue.add(syncCompletions);
|
||||
+ try {
|
||||
+ final List<String> legacyCompletions = syncCompletions.get();
|
||||
+ completions.removeIf(it -> !legacyCompletions.contains(it.suggestion())); // remove any suggestions that were removed
|
||||
+ // add any new suggestions
|
||||
+ for (final String completion : legacyCompletions) {
|
||||
+ if (notNewSuggestion(completions, completion)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ completions.add(com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion.completion(completion));
|
||||
+ }
|
||||
+ } catch (InterruptedException | ExecutionException e1) {
|
||||
+ e1.printStackTrace();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!completions.isEmpty()) {
|
||||
+ for (final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion completion : completions) {
|
||||
+ if (completion.suggestion().isEmpty()) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ candidates.add(new Candidate(
|
||||
+ completion.suggestion(),
|
||||
+ completion.suggestion(),
|
||||
+ null,
|
||||
+ io.papermc.paper.adventure.PaperAdventure.PLAIN.serializeOr(completion.tooltip(), null),
|
||||
+ null,
|
||||
+ null,
|
||||
+ false
|
||||
+ ));
|
||||
+ }
|
||||
+ }
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
// Paper end
|
||||
Waitable<List<String>> waitable = new Waitable<List<String>>() {
|
||||
@Override
|
||||
@@ -73,4 +128,15 @@ public class ConsoleCommandCompleter implements Completer {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ private boolean notNewSuggestion(final List<com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion> completions, final String completion) {
|
||||
+ for (final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion it : completions) {
|
||||
+ if (it.suggestion().equals(completion)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue