354
This commit is contained in:
parent
1d7d7e92f2
commit
9079c90d22
55 changed files with 192 additions and 236 deletions
|
@ -1,21 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||
Date: Sat, 20 Apr 2019 19:47:34 -0500
|
||||
Subject: [PATCH] Expose the internal current tick
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index 43c69ec522a2c91d47b5cea05aaf86f979c5fcb2..fd038c105d12c76c9e2645ad146e77b4a9cc1079 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -2861,5 +2861,10 @@ public final class CraftServer implements Server {
|
||||
profile.getProperties().putAll(((CraftPlayer) player).getHandle().getGameProfile().getProperties());
|
||||
return new com.destroystokyo.paper.profile.CraftPlayerProfile(profile);
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public int getCurrentTick() {
|
||||
+ return net.minecraft.server.MinecraftServer.currentTick;
|
||||
+ }
|
||||
// Paper end
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Sat, 15 Jun 2019 10:28:25 -0700
|
||||
Subject: [PATCH] Show blockstate location if we failed to read it
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
|
||||
index e7fd9ebd47af277d6dbced0f17e954722c202776..ff3f88f107a4c059688566b69dcdf48bc01210ab 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
|
||||
@@ -25,6 +25,7 @@ public class CraftBlockEntityState<T extends BlockEntity> extends CraftBlockStat
|
||||
|
||||
this.tileEntity = tileEntity;
|
||||
|
||||
+ try { // Paper - Show blockstate location if we failed to read it
|
||||
// Paper start
|
||||
this.snapshotDisabled = DISABLE_SNAPSHOT;
|
||||
if (DISABLE_SNAPSHOT) {
|
||||
@@ -37,6 +38,14 @@ public class CraftBlockEntityState<T extends BlockEntity> extends CraftBlockStat
|
||||
this.load(this.snapshot);
|
||||
}
|
||||
// Paper end
|
||||
+ // Paper start - Show blockstate location if we failed to read it
|
||||
+ } catch (Throwable thr) {
|
||||
+ if (thr instanceof ThreadDeath) {
|
||||
+ throw (ThreadDeath)thr;
|
||||
+ }
|
||||
+ throw new RuntimeException("Failed to read BlockState at: world: " + this.getWorld().getName() + " location: (" + this.getX() + ", " + this.getY() + ", " + this.getZ() + ")", thr);
|
||||
+ }
|
||||
+ // Paper end - Show blockstate location if we failed to read it
|
||||
}
|
||||
|
||||
protected CraftBlockEntityState(CraftBlockEntityState<T> state) {
|
|
@ -1,36 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 24 Mar 2019 01:01:32 -0400
|
||||
Subject: [PATCH] Only count Natural Spawned mobs towards natural spawn mob
|
||||
limit
|
||||
|
||||
This resolves the super common complaint about mobs not spawning.
|
||||
|
||||
This was ultimately a flaw in the vanilla count algorithim that allows
|
||||
spawners and other misc mobs to count against the mob limit, which are
|
||||
not bounded, and can prevent the entire world from spawning new.
|
||||
|
||||
I believe Bukkits changes around persistence may of actually made it
|
||||
worse than vanilla.
|
||||
|
||||
This should fully solve all of the issues around it so that only natural
|
||||
influences natural spawns.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
||||
index d5ada3301429e7fec0d157d7a33d4937e0f82fbb..5247782edc426107fb4b3ade5d92f148c0b6e681 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
||||
@@ -88,6 +88,13 @@ public final class NaturalSpawner {
|
||||
MobCategory enumcreaturetype = entity.getType().getCategory();
|
||||
|
||||
if (enumcreaturetype != MobCategory.MISC) {
|
||||
+ // Paper start - Only count natural spawns
|
||||
+ if (!entity.level().paperConfig().entities.spawning.countAllMobsForSpawning &&
|
||||
+ !(entity.spawnReason == org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL ||
|
||||
+ entity.spawnReason == org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CHUNK_GEN)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ // Paper end - Only count natural spawns
|
||||
BlockPos blockposition = entity.blockPosition();
|
||||
|
||||
chunkSource.query(ChunkPos.asLong(blockposition), (chunk) -> {
|
|
@ -1,39 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lucavon <lucavonlp@gmail.com>
|
||||
Date: Tue, 23 Jul 2019 20:29:20 -0500
|
||||
Subject: [PATCH] Configurable projectile relative velocity
|
||||
|
||||
This patch adds an option "disable relative projectile velocity", which, when
|
||||
enabled, will cause projectiles to ignore the shooter's current velocity,
|
||||
like they did in Minecraft 1.8 and prior.
|
||||
If a player is falling, for example, their shooting range will be drastically
|
||||
reduced, as a downwards velocity is applied to the projectile. This prevents
|
||||
players from saving themselves from falling off floating islands, for example,
|
||||
as a thrown ender pearl will not make it back to the island, while it would
|
||||
have in 1.8.
|
||||
|
||||
While this could easily be done with plugins, too, there are multiple problems:
|
||||
P1) If multiple plugins cancel the velocity by subtracting the shooter's velocity
|
||||
from the projectile's velocity, the projectile's velocity would be different.
|
||||
As there's no way to detect whether the projectile's velocity has already been
|
||||
adjusted to ignore the player's velocity, plugins can't not do it if it's not
|
||||
necessary.
|
||||
P2) I've noticed some inconsistencies, e.g. weird velocity when shooting while
|
||||
using an elytra. Checking for those inconsistencies is possible, but not as
|
||||
efficient as just not applying the velocity in the first place.
|
||||
P3) Solutions for 1) and especially 2) might not be future-proof, while this
|
||||
server-internal fix makes this change future-proof.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
|
||||
index 4ebc38d0666d01c67c2728355fbbef296a0672e3..20842ed5b730dda88efd0cda9292a37f879a4017 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
|
||||
@@ -173,7 +173,7 @@ public abstract class Projectile extends Entity implements TraceableEntity {
|
||||
this.shoot((double) f5, (double) f6, (double) f7, speed, divergence);
|
||||
Vec3 vec3d = shooter.getDeltaMovement();
|
||||
|
||||
- this.setDeltaMovement(this.getDeltaMovement().add(vec3d.x, shooter.onGround() ? 0.0D : vec3d.y, vec3d.z));
|
||||
+ if (!shooter.level().paperConfig().misc.disableRelativeProjectileVelocity) this.setDeltaMovement(this.getDeltaMovement().add(vec3d.x, shooter.onGround() ? 0.0D : vec3d.y, vec3d.z)); // Paper - allow disabling relative velocity
|
||||
}
|
||||
|
||||
// CraftBukkit start - call projectile hit event
|
|
@ -1,19 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: kickash32 <kickash32@gmail.com>
|
||||
Date: Tue, 30 Jul 2019 03:17:16 +0500
|
||||
Subject: [PATCH] offset item frame ticking
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java b/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java
|
||||
index aaa579ba04445aa350a439610d460a2415320cfc..4dea85a8ab8ae16d02e35d226fd155891ce2319a 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java
|
||||
@@ -39,7 +39,7 @@ public abstract class HangingEntity extends Entity {
|
||||
protected static final Predicate<Entity> HANGING_ENTITY = (entity) -> {
|
||||
return entity instanceof HangingEntity;
|
||||
};
|
||||
- private int checkInterval;
|
||||
+ private int checkInterval; { this.checkInterval = this.getId() % this.level().spigotConfig.hangingTickFrequency; } // Paper - Perf: offset item frame ticking
|
||||
public BlockPos pos;
|
||||
protected Direction direction;
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: kickash32 <kickash32@gmail.com>
|
||||
Date: Mon, 19 Aug 2019 19:42:35 +0500
|
||||
Subject: [PATCH] Prevent consuming the wrong itemstack
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index 4be7b136dd2b35b0637a1455985ab99bbd3af0a5..b4a817e047a78723d746740c88503441625ac8e7 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -3730,9 +3730,14 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
}
|
||||
|
||||
public void startUsingItem(InteractionHand hand) {
|
||||
+ // Paper start - Prevent consuming the wrong itemstack
|
||||
+ this.startUsingItem(hand, false);
|
||||
+ }
|
||||
+ public void startUsingItem(InteractionHand hand, boolean forceUpdate) {
|
||||
+ // Paper end - Prevent consuming the wrong itemstack
|
||||
ItemStack itemstack = this.getItemInHand(hand);
|
||||
|
||||
- if (!itemstack.isEmpty() && !this.isUsingItem()) {
|
||||
+ if (!itemstack.isEmpty() && !this.isUsingItem() || forceUpdate) { // Paper - Prevent consuming the wrong itemstack
|
||||
this.useItem = itemstack;
|
||||
this.useItemRemaining = itemstack.getUseDuration();
|
||||
if (!this.level().isClientSide) {
|
||||
@@ -3812,6 +3817,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
this.releaseUsingItem();
|
||||
} else {
|
||||
if (!this.useItem.isEmpty() && this.isUsingItem()) {
|
||||
+ this.startUsingItem(this.getUsedItemHand(), true); // Paper - Prevent consuming the wrong itemstack
|
||||
this.triggerItemUseEffects(this.useItem, 16);
|
||||
// CraftBukkit start - fire PlayerItemConsumeEvent
|
||||
ItemStack itemstack;
|
||||
@@ -3846,8 +3852,8 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
}
|
||||
|
||||
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)) {
|
||||
+ // Paper start
|
||||
+ if (this instanceof ServerPlayer) {
|
||||
((ServerPlayer) this).getBukkitEntity().updateInventory();
|
||||
}
|
||||
// Paper end
|
|
@ -1,18 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Nassim Jahnke <nassim@njahnke.dev>
|
||||
Date: Sat, 11 Sep 2021 11:56:51 +0200
|
||||
Subject: [PATCH] Dont send unnecessary sign update
|
||||
|
||||
|
||||
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 a822b190aeee1d644c3509bb75106fa4dfdd963f..9939cad5af2d7873f188f18978029663a8d785de 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
|
||||
@@ -184,6 +184,7 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C
|
||||
this.level.sendBlockUpdated(this.getBlockPos(), this.getBlockState(), this.getBlockState(), 3);
|
||||
} else {
|
||||
SignBlockEntity.LOGGER.warn("Player {} just tried to change non-editable sign", player.getName().getString());
|
||||
+ if (player.distanceToSqr(this.getBlockPos().getX(), this.getBlockPos().getY(), this.getBlockPos().getZ()) < 32 * 32) // Paper - Dont send far away sign update
|
||||
((ServerPlayer) player).connection.send(this.getUpdatePacket()); // CraftBukkit
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||
Date: Wed, 9 Oct 2019 21:46:15 -0500
|
||||
Subject: [PATCH] Add option to disable pillager patrols
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java
|
||||
index 65d9211b812995869e58900a2873583658122312..c7aea059de151cf8ae6e660785e176586bc23ff3 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java
|
||||
@@ -25,6 +25,7 @@ public class PatrolSpawner implements CustomSpawner {
|
||||
|
||||
@Override
|
||||
public int tick(ServerLevel world, boolean spawnMonsters, boolean spawnAnimals) {
|
||||
+ if (world.paperConfig().entities.behavior.pillagerPatrols.disable) return 0; // Paper - Add option to disable pillager patrols
|
||||
if (!spawnMonsters) {
|
||||
return 0;
|
||||
} else if (!world.getGameRules().getBoolean(GameRules.RULE_DO_PATROL_SPAWNING)) {
|
|
@ -1,20 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Callahan <mr.callahhh@gmail.com>
|
||||
Date: Mon, 13 Jan 2020 23:47:28 -0600
|
||||
Subject: [PATCH] Prevent sync chunk loads when villagers try to find beds
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/SleepInBed.java b/src/main/java/net/minecraft/world/entity/ai/behavior/SleepInBed.java
|
||||
index 6fe337e8d6db168ea181ed2597674f4829b03c47..e552ae6a7db765301a3d280dbf9348d9dc28b9c2 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/ai/behavior/SleepInBed.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/SleepInBed.java
|
||||
@@ -42,7 +42,8 @@ public class SleepInBed extends Behavior<LivingEntity> {
|
||||
}
|
||||
}
|
||||
|
||||
- BlockState blockState = world.getBlockState(globalPos.pos());
|
||||
+ BlockState blockState = world.getBlockStateIfLoaded(globalPos.pos()); // Paper - Prevent sync chunk loads when villagers try to find beds
|
||||
+ if (blockState == null) { return false; } // Paper - Prevent sync chunk loads when villagers try to find beds
|
||||
return globalPos.pos().closerToCenterThan(entity.position(), 2.0) && blockState.is(BlockTags.BEDS) && !blockState.getValue(BedBlock.OCCUPIED);
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Wed, 18 Dec 2019 22:21:35 -0600
|
||||
Subject: [PATCH] MC-145656 Fix Follow Range Initial Target
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoal.java
|
||||
index 0dad5be671f990d0edf0a155e2534b3812438902..175ba1184fc997f562f0834b172e17dc1b5b3027 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoal.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoal.java
|
||||
@@ -38,6 +38,7 @@ public class NearestAttackableTargetGoal<T extends LivingEntity> extends TargetG
|
||||
this.randomInterval = reducedTickDelay(reciprocalChance);
|
||||
this.setFlags(EnumSet.of(Goal.Flag.TARGET));
|
||||
this.targetConditions = TargetingConditions.forCombat().range(this.getFollowDistance()).selector(targetPredicate);
|
||||
+ if (mob.level().paperConfig().entities.entitiesTargetWithFollowRange) this.targetConditions.useFollowRange(); // Paper - Fix MC-145656
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java
|
||||
index bc4b9a46056e83762e29bb04485ad7c754a20336..aecb0ad814586bfc5e56755ee14379a69388b38c 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java
|
||||
@@ -77,7 +77,7 @@ public class TargetingConditions {
|
||||
|
||||
if (this.range > 0.0) {
|
||||
double d = this.testInvisible ? targetEntity.getVisibilityPercent(baseEntity) : 1.0;
|
||||
- double e = Math.max(this.range * d, 2.0);
|
||||
+ double e = Math.max((this.useFollowRange ? this.getFollowRange(baseEntity) : this.range) * d, 2.0); // Paper - Fix MC-145656
|
||||
double f = baseEntity.distanceToSqr(targetEntity.getX(), targetEntity.getY(), targetEntity.getZ());
|
||||
if (f > e * e) {
|
||||
return false;
|
||||
@@ -92,4 +92,18 @@ public class TargetingConditions {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // Paper start - Fix MC-145656
|
||||
+ private boolean useFollowRange = false;
|
||||
+
|
||||
+ public TargetingConditions useFollowRange() {
|
||||
+ this.useFollowRange = true;
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ private double getFollowRange(LivingEntity entityliving) {
|
||||
+ net.minecraft.world.entity.ai.attributes.AttributeInstance attributeinstance = entityliving.getAttribute(net.minecraft.world.entity.ai.attributes.Attributes.FOLLOW_RANGE);
|
||||
+ return attributeinstance == null ? 16.0D : attributeinstance.getValue();
|
||||
+ }
|
||||
+ // Paper end - Fix MC-145656
|
||||
}
|
|
@ -1,92 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 21 Jul 2018 14:27:34 -0400
|
||||
Subject: [PATCH] Duplicate UUID Resolve Option
|
||||
|
||||
Due to a bug in https://github.com/PaperMC/Paper/commit/2e29af3df05ec0a383f48be549d1c03200756d24
|
||||
which was added all the way back in March of 2016, it was unknown (potentially not at the time)
|
||||
that an entity might actually change the seed of the random object.
|
||||
|
||||
At some point, EntitySquid did start setting the seed. Due to this shared random, this caused
|
||||
every entity to use a Random object with a predictable seed.
|
||||
|
||||
This has caused entities to potentially generate with the same UUID....
|
||||
|
||||
Over the years, servers have had entities disappear, but no sign of trouble
|
||||
because CraftBukkit removed the log lines indicating that something was wrong.
|
||||
|
||||
We have fixed the root issue causing duplicate UUID's, however we now have chunk
|
||||
files full of entities that have the same UUID as another entity!
|
||||
|
||||
When these chunks load, the 2nd entity will not be added to the world correctly.
|
||||
|
||||
If that chunk loads in a different order in the future, then it will reverse and the
|
||||
missing one is now the one added to the world and not the other. This results in very
|
||||
inconsistent entity behavior.
|
||||
|
||||
This change allows you to recover any duplicate entity by generating a new UUID for it.
|
||||
This also lets you delete them instead if you don't want to risk having new entities added to
|
||||
the world that you previously did not see.
|
||||
|
||||
But for those who are ok with leaving this inconsistent behavior, you may use WARN or NOTHING options.
|
||||
|
||||
It is recommended you regenerate the entities, as these were legit entities, and deserve your love.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 05b838f7008d5d031b18e161bbde7e72b8205b90..8805fd57e7198aa9afaafe45fab13fd343e2a545 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -880,6 +880,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
entity.discard(null); // CraftBukkit - add Bukkit remove cause
|
||||
needsRemoval = true;
|
||||
}
|
||||
+ checkDupeUUID(world, entity); // Paper - duplicate uuid resolving
|
||||
return !needsRemoval;
|
||||
}));
|
||||
// CraftBukkit end
|
||||
@@ -930,6 +931,45 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
});
|
||||
}
|
||||
|
||||
+ // Paper start - duplicate uuid resolving
|
||||
+ // rets true if to prevent the entity from being added
|
||||
+ public static boolean checkDupeUUID(ServerLevel level, Entity entity) {
|
||||
+ io.papermc.paper.configuration.WorldConfiguration.Entities.Spawning.DuplicateUUID.DuplicateUUIDMode mode = level.paperConfig().entities.spawning.duplicateUuid.mode;
|
||||
+ if (mode != io.papermc.paper.configuration.WorldConfiguration.Entities.Spawning.DuplicateUUID.DuplicateUUIDMode.WARN
|
||||
+ && mode != io.papermc.paper.configuration.WorldConfiguration.Entities.Spawning.DuplicateUUID.DuplicateUUIDMode.DELETE
|
||||
+ && mode != io.papermc.paper.configuration.WorldConfiguration.Entities.Spawning.DuplicateUUID.DuplicateUUIDMode.SAFE_REGEN) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ Entity other = level.getEntity(entity.getUUID());
|
||||
+
|
||||
+ if (other == null || other == entity) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (mode == io.papermc.paper.configuration.WorldConfiguration.Entities.Spawning.DuplicateUUID.DuplicateUUIDMode.SAFE_REGEN && other != null && !other.isRemoved()
|
||||
+ && Objects.equals(other.getEncodeId(), entity.getEncodeId())
|
||||
+ && entity.getBukkitEntity().getLocation().distance(other.getBukkitEntity().getLocation()) < level.paperConfig().entities.spawning.duplicateUuid.safeRegenDeleteRange
|
||||
+ ) {
|
||||
+ entity.discard(null);
|
||||
+ return true;
|
||||
+ }
|
||||
+ if (!other.isRemoved()) {
|
||||
+ switch (mode) {
|
||||
+ case SAFE_REGEN: {
|
||||
+ entity.setUUID(java.util.UUID.randomUUID());
|
||||
+ break;
|
||||
+ }
|
||||
+ case DELETE: {
|
||||
+ entity.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD);
|
||||
+ return true;
|
||||
+ }
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Paper end - duplicate uuid resolving
|
||||
public CompletableFuture<Either<LevelChunk, ChunkHolder.ChunkLoadingFailure>> prepareTickingChunk(ChunkHolder holder) {
|
||||
CompletableFuture<Either<List<ChunkAccess>, ChunkHolder.ChunkLoadingFailure>> completablefuture = this.getChunkRangeFuture(holder, 1, (i) -> {
|
||||
return ChunkStatus.FULL;
|
|
@ -1,19 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Tue, 24 Dec 2019 00:35:42 +0000
|
||||
Subject: [PATCH] PlayerDeathEvent#shouldDropExperience
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index eb9668f94dbc36f3abc7d5c47c9b1b657aa94ced..79a0accd8230c76d792ed3f7558e8b3ea6d2f6d1 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -934,7 +934,7 @@ public class ServerPlayer extends Player {
|
||||
this.tellNeutralMobsThatIDied();
|
||||
}
|
||||
// SPIGOT-5478 must be called manually now
|
||||
- this.dropExperience();
|
||||
+ if (event.shouldDropExperience()) this.dropExperience(); // Paper - tie to event
|
||||
// we clean the player's inventory after the EntityDeathEvent is called so plugins can get the exact state of the inventory.
|
||||
if (!event.getKeepInventory()) {
|
||||
// Paper start - PlayerDeathEvent#getItemsToKeep
|
|
@ -1,18 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Sun, 5 Jan 2020 17:24:34 -0600
|
||||
Subject: [PATCH] Prevent bees loading chunks checking hive position
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java
|
||||
index d3ef1bf0be4584dbe41576fa7036b11ff405b9d8..0f7b02d39b5dc781e65537c1b6d924e6c51e5dc7 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/Bee.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java
|
||||
@@ -509,6 +509,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
|
||||
} else if (this.isTooFarAway(this.hivePos)) {
|
||||
return false;
|
||||
} else {
|
||||
+ if (this.level().getChunkIfLoadedImmediately(this.hivePos.getX() >> 4, this.hivePos.getZ() >> 4) == null) return true; // Paper - just assume the hive is still there, no need to load the chunk(s)
|
||||
BlockEntity tileentity = this.level().getBlockEntity(this.hivePos);
|
||||
|
||||
return tileentity != null && tileentity.getType() == BlockEntityType.BEEHIVE;
|
|
@ -1,32 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Thu, 3 Nov 2016 20:28:12 -0400
|
||||
Subject: [PATCH] Don't load Chunks from Hoppers and other things
|
||||
|
||||
Hoppers call this to I guess "get the primary side" of a double sided chest.
|
||||
|
||||
If the double sided chest crosses chunk lines, it causes the chunk to load.
|
||||
This will end up causing sync chunk loads, which will unload with Chunk GC,
|
||||
only to be reloaded again the next tick.
|
||||
|
||||
This of course is undesirable, so just return the loaded side as "primary"
|
||||
and treat it as a single chest if the other sides are unloaded
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/DoubleBlockCombiner.java b/src/main/java/net/minecraft/world/level/block/DoubleBlockCombiner.java
|
||||
index 963092cd5a4e756ad6a471379a81d8996cc2b091..20c9921339ec6b5127fbadcedc19577f3906074d 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/DoubleBlockCombiner.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/DoubleBlockCombiner.java
|
||||
@@ -34,7 +34,12 @@ public class DoubleBlockCombiner {
|
||||
return new DoubleBlockCombiner.NeighborCombineResult.Single<>(blockEntity);
|
||||
} else {
|
||||
BlockPos blockPos = pos.relative(directionMapper.apply(state));
|
||||
- BlockState blockState = world.getBlockState(blockPos);
|
||||
+ // Paper start - Don't load Chunks from Hoppers and other things
|
||||
+ BlockState blockState = world.getBlockStateIfLoaded(blockPos);
|
||||
+ if (blockState == null) {
|
||||
+ return new DoubleBlockCombiner.NeighborCombineResult.Single<>(blockEntity);
|
||||
+ }
|
||||
+ // Paper end - Don't load Chunks from Hoppers and other things
|
||||
if (blockState.is(state.getBlock())) {
|
||||
DoubleBlockCombiner.BlockType blockType2 = typeMapper.apply(blockState);
|
||||
if (blockType2 != DoubleBlockCombiner.BlockType.SINGLE
|
|
@ -1,27 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Sat, 11 Jan 2020 21:50:56 -0800
|
||||
Subject: [PATCH] Optimise EntityGetter#getPlayerByUUID
|
||||
|
||||
Use the PlayerList map instead of iterating over all players
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 20de3be232ccc7ec7bbc3c6aee9acf66fd396af1..54c0aa440cd8e7e1cedc6ef9ae963c68558b6080 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -324,6 +324,15 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
}
|
||||
// Paper end
|
||||
|
||||
+ // Paper start - optimise getPlayerByUUID
|
||||
+ @Nullable
|
||||
+ @Override
|
||||
+ public Player getPlayerByUUID(UUID uuid) {
|
||||
+ final Player player = this.getServer().getPlayerList().getPlayer(uuid);
|
||||
+ return player != null && player.level() == this ? player : null;
|
||||
+ }
|
||||
+ // Paper end - optimise getPlayerByUUID
|
||||
+
|
||||
// Add env and gen to constructor, IWorldDataServer -> WorldDataServer
|
||||
public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PrimaryLevelData iworlddataserver, ResourceKey<Level> resourcekey, LevelStem worlddimension, ChunkProgressListener worldloadlistener, boolean flag, long i, List<CustomSpawner> list, boolean flag1, @Nullable RandomSequences randomsequences, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) {
|
||||
// IRegistryCustom.Dimension iregistrycustom_dimension = minecraftserver.registryAccess(); // CraftBukkit - decompile error
|
|
@ -1,42 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: AJMFactsheets <AJMFactsheets@gmail.com>
|
||||
Date: Fri, 17 Jan 2020 17:17:54 -0600
|
||||
Subject: [PATCH] Fix items not falling correctly
|
||||
|
||||
Since 1.14, Mojang has added an optimization which skips checking if
|
||||
an item should fall every fourth tick.
|
||||
|
||||
However, Spigot's entity activation range class also has an
|
||||
optimization which skips ticking active entities every fourth tick.
|
||||
This can result in a state where an item will never properly fall
|
||||
due to its move method never being called.
|
||||
|
||||
This patch resolves the conflict by offsetting checking Spigot's entity
|
||||
activation range check from an item's move method.
|
||||
|
||||
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 bfbbb9382cf483a23acf35c17250f6f9223f7507..5994cb69575d365f435f5ef6da5fa61ee9298fe1 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
|
||||
@@ -169,7 +169,7 @@ public class ItemEntity extends Entity implements TraceableEntity {
|
||||
}
|
||||
}
|
||||
|
||||
- if (!this.onGround() || this.getDeltaMovement().horizontalDistanceSqr() > 9.999999747378752E-6D || (this.tickCount + this.getId()) % 4 == 0) {
|
||||
+ if (!this.onGround() || this.getDeltaMovement().horizontalDistanceSqr() > 9.999999747378752E-6D || (this.tickCount + this.getId()) % 4 == 0) { // Paper - Diff on change
|
||||
this.move(MoverType.SELF, this.getDeltaMovement());
|
||||
float f1 = 0.98F;
|
||||
|
||||
diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java
|
||||
index 6d51464f6368151e8acc532414ee223714584e96..9fb9fa62c32445ac3c3883a6433759c86dcfc428 100644
|
||||
--- a/src/main/java/org/spigotmc/ActivationRange.java
|
||||
+++ b/src/main/java/org/spigotmc/ActivationRange.java
|
||||
@@ -256,7 +256,7 @@ public class ActivationRange
|
||||
isActive = true;
|
||||
}
|
||||
// Add a little performance juice to active entities. Skip 1/4 if not immune.
|
||||
- } else if ( !entity.defaultActivationState && entity.tickCount % 4 == 0 && !ActivationRange.checkEntityImmunities( entity ) )
|
||||
+ } else if ( !entity.defaultActivationState && (entity.tickCount + entity.getId()) % 4 == 0 && !ActivationRange.checkEntityImmunities( entity ) ) // Paper - Ensure checking item movement is offset from Spigot's entity activation range check
|
||||
{
|
||||
isActive = false;
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BrodyBeckwith <brody@beckwith.dev>
|
||||
Date: Tue, 14 Jan 2020 17:49:03 -0500
|
||||
Subject: [PATCH] Optimize call to getFluid for explosions
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java
|
||||
index ade10a9fd93f4c0f04cd56ce5e1da06af4a05060..b057a67a416928ae30bd407b3da982b73ae3be03 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/Explosion.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/Explosion.java
|
||||
@@ -191,7 +191,7 @@ public class Explosion {
|
||||
for (float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) {
|
||||
BlockPos blockposition = BlockPos.containing(d4, d5, d6);
|
||||
BlockState iblockdata = this.level.getBlockState(blockposition);
|
||||
- FluidState fluid = this.level.getFluidState(blockposition);
|
||||
+ FluidState fluid = iblockdata.getFluidState(); // Paper - Perf: Optimize call to getFluid for explosions
|
||||
|
||||
if (!this.level.isInWorldBounds(blockposition)) {
|
||||
break;
|
|
@ -1,22 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Fri, 17 Jan 2020 18:44:55 -0800
|
||||
Subject: [PATCH] Fix last firework in stack not having effects when dispensed
|
||||
|
||||
CB used the resulting item in the dispenser rather than the item
|
||||
dispensed. The resulting item would have size == 0 and therefore
|
||||
be convertered to air, hence why the effects disappeared.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
||||
index 42f541c609c3d94bee9b40b8e5307ad41a39c619..8c8d2e81f0866dc1441e181f2580852d87263bcc 100644
|
||||
--- a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
||||
+++ b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
||||
@@ -516,7 +516,7 @@ public interface DispenseItemBehavior {
|
||||
|
||||
itemstack1 = CraftItemStack.asNMSCopy(event.getItem());
|
||||
Vec3 vec3d = DispenseItemBehavior.getEntityPokingOutOfBlockPos(pointer, EntityType.FIREWORK_ROCKET, enumdirection);
|
||||
- FireworkRocketEntity entityfireworks = new FireworkRocketEntity(pointer.level(), stack, vec3d.x(), vec3d.y(), vec3d.z(), true);
|
||||
+ FireworkRocketEntity entityfireworks = new FireworkRocketEntity(pointer.level(), itemstack1, vec3d.x(), vec3d.y(), vec3d.z(), true); // Paper - GH-2871 - fix last firework in stack having no effects when dispensed
|
||||
|
||||
entityfireworks.shoot((double) enumdirection.getStepX(), (double) enumdirection.getStepY(), (double) enumdirection.getStepZ(), 0.5F, 1.0F);
|
||||
pointer.level().addFreshEntity(entityfireworks);
|
|
@ -1,51 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Fri, 27 Dec 2019 09:42:26 -0800
|
||||
Subject: [PATCH] Guard against serializing mismatching chunk coordinate
|
||||
|
||||
Should help if something dumb happens
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
|
||||
index ba7a816bd9dd4aec79e2560f0968374dbb28442c..cbc8e95c8f890f0c0eb717d4d2ae3f427dc260d8 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
|
||||
@@ -86,8 +86,20 @@ public class ChunkSerializer {
|
||||
|
||||
public ChunkSerializer() {}
|
||||
|
||||
+ // Paper start - guard against serializing mismatching coordinates
|
||||
+ // TODO Note: This needs to be re-checked each update
|
||||
+ public static ChunkPos getChunkCoordinate(final CompoundTag chunkData) {
|
||||
+ final int dataVersion = ChunkStorage.getVersion(chunkData);
|
||||
+ if (dataVersion < 2842) { // Level tag is removed after this version
|
||||
+ final CompoundTag levelData = chunkData.getCompound("Level");
|
||||
+ return new ChunkPos(levelData.getInt("xPos"), levelData.getInt("zPos"));
|
||||
+ } else {
|
||||
+ return new ChunkPos(chunkData.getInt("xPos"), chunkData.getInt("zPos"));
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - guard against serializing mismatching coordinates
|
||||
public static ProtoChunk read(ServerLevel world, PoiManager poiStorage, ChunkPos chunkPos, CompoundTag nbt) {
|
||||
- ChunkPos chunkcoordintpair1 = new ChunkPos(nbt.getInt("xPos"), nbt.getInt("zPos"));
|
||||
+ ChunkPos chunkcoordintpair1 = new ChunkPos(nbt.getInt("xPos"), nbt.getInt("zPos")); // Paper - guard against serializing mismatching coordinates; diff on change, see ChunkSerializer#getChunkCoordinate
|
||||
|
||||
if (!Objects.equals(chunkPos, chunkcoordintpair1)) {
|
||||
ChunkSerializer.LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", new Object[]{chunkPos, chunkPos, chunkcoordintpair1});
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java
|
||||
index 25623dcd44edc475c5dce2756bf99fc18e142b63..eaf978d15618b80d23c443acbd42db926d570d01 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java
|
||||
@@ -157,6 +157,13 @@ public class ChunkStorage implements AutoCloseable {
|
||||
}
|
||||
|
||||
public void write(ChunkPos chunkPos, CompoundTag nbt) {
|
||||
+ // Paper start - guard against serializing mismatching coordinates
|
||||
+ if (nbt != null && !chunkPos.equals(ChunkSerializer.getChunkCoordinate(nbt))) {
|
||||
+ final String world = (this instanceof net.minecraft.server.level.ChunkMap) ? ((net.minecraft.server.level.ChunkMap) this).level.getWorld().getName() : null;
|
||||
+ throw new IllegalArgumentException("Chunk coordinate and serialized data do not have matching coordinates, trying to serialize coordinate " + chunkPos
|
||||
+ + " but compound says coordinate is " + ChunkSerializer.getChunkCoordinate(nbt) + (world == null ? " for an unknown world" : (" for world: " + world)));
|
||||
+ }
|
||||
+ // Paper end - guard against serializing mismatching coordinates
|
||||
this.worker.store(chunkPos, nbt);
|
||||
if (this.legacyStructureHandler != null) {
|
||||
this.legacyStructureHandler.removeIndex(chunkPos.toLong());
|
|
@ -1,63 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: kickash32 <kickash32@gmail.com>
|
||||
Date: Mon, 3 Jun 2019 02:02:39 -0400
|
||||
Subject: [PATCH] Alternative item-despawn-rate
|
||||
|
||||
Co-authored-by: Noah van der Aa <ndvdaa@gmail.com>
|
||||
|
||||
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 5994cb69575d365f435f5ef6da5fa61ee9298fe1..e67e8d0593e3ba3fc8e9da59ad6494ea589ab337 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
|
||||
@@ -57,6 +57,7 @@ public class ItemEntity extends Entity implements TraceableEntity {
|
||||
public final float bobOffs;
|
||||
private int lastTick = MinecraftServer.currentTick - 1; // CraftBukkit
|
||||
public boolean canMobPickup = true; // Paper - Item#canEntityPickup
|
||||
+ private int despawnRate = -1; // Paper - Alternative item-despawn-rate
|
||||
|
||||
public ItemEntity(EntityType<? extends ItemEntity> type, Level world) {
|
||||
super(type, world);
|
||||
@@ -209,7 +210,7 @@ public class ItemEntity extends Entity implements TraceableEntity {
|
||||
}
|
||||
}
|
||||
|
||||
- if (!this.level().isClientSide && this.age >= this.level().spigotConfig.itemDespawnRate) { // Spigot
|
||||
+ if (!this.level().isClientSide && this.age >= this.despawnRate) { // Spigot // Paper - Alternative item-despawn-rate
|
||||
// CraftBukkit start - fire ItemDespawnEvent
|
||||
if (CraftEventFactory.callItemDespawnEvent(this).isCancelled()) {
|
||||
this.age = 0;
|
||||
@@ -233,7 +234,7 @@ public class ItemEntity extends Entity implements TraceableEntity {
|
||||
this.lastTick = MinecraftServer.currentTick;
|
||||
// CraftBukkit end
|
||||
|
||||
- if (!this.level().isClientSide && this.age >= this.level().spigotConfig.itemDespawnRate) { // Spigot
|
||||
+ if (!this.level().isClientSide && this.age >= this.despawnRate) { // Spigot // Paper - Alternative item-despawn-rate
|
||||
// CraftBukkit start - fire ItemDespawnEvent
|
||||
if (org.bukkit.craftbukkit.event.CraftEventFactory.callItemDespawnEvent(this).isCancelled()) {
|
||||
this.age = 0;
|
||||
@@ -289,7 +290,7 @@ public class ItemEntity extends Entity implements TraceableEntity {
|
||||
private boolean isMergable() {
|
||||
ItemStack itemstack = this.getItem();
|
||||
|
||||
- return this.isAlive() && this.pickupDelay != 32767 && this.age != -32768 && this.age < 6000 && itemstack.getCount() < itemstack.getMaxStackSize();
|
||||
+ return this.isAlive() && this.pickupDelay != 32767 && this.age != -32768 && this.age < this.despawnRate && itemstack.getCount() < itemstack.getMaxStackSize(); // Paper - Alternative item-despawn-rate
|
||||
}
|
||||
|
||||
private void tryToMerge(ItemEntity other) {
|
||||
@@ -532,6 +533,7 @@ public class ItemEntity extends Entity implements TraceableEntity {
|
||||
|
||||
public void setItem(ItemStack stack) {
|
||||
this.getEntityData().set(ItemEntity.DATA_ITEM, stack);
|
||||
+ this.despawnRate = this.level().paperConfig().entities.spawning.altItemDespawnRate.enabled ? this.level().paperConfig().entities.spawning.altItemDespawnRate.items.getOrDefault(stack.getItem(), this.level().spigotConfig.itemDespawnRate) : this.level().spigotConfig.itemDespawnRate; // Paper - Alternative item-despawn-rate
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -586,7 +588,7 @@ public class ItemEntity extends Entity implements TraceableEntity {
|
||||
|
||||
public void makeFakeItem() {
|
||||
this.setNeverPickUp();
|
||||
- this.age = this.level().spigotConfig.itemDespawnRate - 1; // Spigot
|
||||
+ this.age = this.despawnRate - 1; // Spigot // Paper - Alternative item-despawn-rate
|
||||
}
|
||||
|
||||
public float getSpin(float tickDelta) {
|
|
@ -1,78 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: kickash32 <kickash32@gmail.com>
|
||||
Date: Sat, 21 Dec 2019 15:22:09 -0500
|
||||
Subject: [PATCH] Tracking Range Improvements
|
||||
|
||||
Sets tracking range of watermobs to animals instead of misc and simplifies code
|
||||
|
||||
Also ignores Enderdragon, defaulting it to Mojang's setting
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 8805fd57e7198aa9afaafe45fab13fd343e2a545..c69f1d970e1014f1be601e34bdd8b5fd749da339 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -1761,6 +1761,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
while (iterator.hasNext()) {
|
||||
Entity entity = (Entity) iterator.next();
|
||||
int j = entity.getType().clientTrackingRange() * 16;
|
||||
+ j = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, j); // Paper
|
||||
|
||||
if (j > i) {
|
||||
i = j;
|
||||
diff --git a/src/main/java/org/spigotmc/TrackingRange.java b/src/main/java/org/spigotmc/TrackingRange.java
|
||||
index 73f9563551632a5369ba55e8fe9211afc325e869..bb06f89a29f30144e7e2113e088a503db006a83c 100644
|
||||
--- a/src/main/java/org/spigotmc/TrackingRange.java
|
||||
+++ b/src/main/java/org/spigotmc/TrackingRange.java
|
||||
@@ -7,7 +7,6 @@ import net.minecraft.world.entity.ExperienceOrb;
|
||||
import net.minecraft.world.entity.decoration.ItemFrame;
|
||||
import net.minecraft.world.entity.decoration.Painting;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
-import net.minecraft.world.entity.monster.Ghast;
|
||||
|
||||
public class TrackingRange
|
||||
{
|
||||
@@ -30,22 +29,21 @@ public class TrackingRange
|
||||
if ( entity instanceof ServerPlayer )
|
||||
{
|
||||
return config.playerTrackingRange;
|
||||
- } else if ( entity.activationType == ActivationRange.ActivationType.MONSTER || entity.activationType == ActivationRange.ActivationType.RAIDER )
|
||||
- {
|
||||
- return config.monsterTrackingRange;
|
||||
- } else if ( entity instanceof Ghast )
|
||||
- {
|
||||
- if ( config.monsterTrackingRange > config.monsterActivationRange )
|
||||
- {
|
||||
+ // Paper start - Simplify and set water mobs to animal tracking range
|
||||
+ }
|
||||
+ switch (entity.activationType) {
|
||||
+ case RAIDER:
|
||||
+ case MONSTER:
|
||||
+ case FLYING_MONSTER:
|
||||
return config.monsterTrackingRange;
|
||||
- } else
|
||||
- {
|
||||
- return config.monsterActivationRange;
|
||||
- }
|
||||
- } else if ( entity.activationType == ActivationRange.ActivationType.ANIMAL )
|
||||
- {
|
||||
- return config.animalTrackingRange;
|
||||
- } else if ( entity instanceof ItemFrame || entity instanceof Painting || entity instanceof ItemEntity || entity instanceof ExperienceOrb )
|
||||
+ case WATER:
|
||||
+ case VILLAGER:
|
||||
+ case ANIMAL:
|
||||
+ return config.animalTrackingRange;
|
||||
+ case MISC:
|
||||
+ }
|
||||
+ if ( entity instanceof ItemFrame || entity instanceof Painting || entity instanceof ItemEntity || entity instanceof ExperienceOrb )
|
||||
+ // Paper end
|
||||
{
|
||||
return config.miscTrackingRange;
|
||||
} else if ( entity instanceof Display )
|
||||
@@ -53,6 +51,7 @@ public class TrackingRange
|
||||
return config.displayTrackingRange;
|
||||
} else
|
||||
{
|
||||
+ if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon) return ((net.minecraft.server.level.ServerLevel)(entity.getCommandSenderWorld())).getChunkSource().chunkMap.serverViewDistance; // Paper - enderdragon is exempt
|
||||
return config.otherTrackingRange;
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: AJMFactsheets <AJMFactsheets@gmail.com>
|
||||
Date: Wed, 22 Jan 2020 19:52:28 -0600
|
||||
Subject: [PATCH] Fix items vanishing through end portal
|
||||
|
||||
If the Paper configuration option "keep-spawn-loaded" is set to false,
|
||||
items entering the overworld from the end will spawn at Y = 0.
|
||||
|
||||
This is due to logic in the getHighestBlockYAt method in World.java
|
||||
only searching the heightmap if the chunk is loaded.
|
||||
|
||||
Quickly loading the exact world spawn chunk before searching the
|
||||
heightmap resolves the issue without having to load all spawn chunks.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index 257be4dd3f38c089dd970b9ac6f292b4f010a01c..98db75a013905ddd38ffd26d615ad8d02d8ddd22 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -3363,6 +3363,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
|
||||
if (flag1) {
|
||||
blockposition1 = ServerLevel.END_SPAWN_POINT;
|
||||
} else {
|
||||
+ destination.getChunkAt(destination.getSharedSpawnPos()); // Paper - Ensure spawn chunk is always loaded before calculating Y coordinate
|
||||
blockposition1 = destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, destination.getSharedSpawnPos());
|
||||
}
|
||||
// CraftBukkit start
|
|
@ -1,34 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Sun, 26 Jan 2020 16:30:19 -0600
|
||||
Subject: [PATCH] Bees get gravity in void. Fixes MC-167279
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java
|
||||
index 0f7b02d39b5dc781e65537c1b6d924e6c51e5dc7..06e990b6957a4ef48c8778bbd175d3afddf52ca3 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/Bee.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java
|
||||
@@ -147,7 +147,22 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
|
||||
public Bee(EntityType<? extends Bee> type, Level world) {
|
||||
super(type, world);
|
||||
this.remainingCooldownBeforeLocatingNewFlower = Mth.nextInt(this.random, 20, 60);
|
||||
- this.moveControl = new FlyingMoveControl(this, 20, true);
|
||||
+ // Paper start - Fix MC-167279
|
||||
+ class BeeFlyingMoveControl extends FlyingMoveControl {
|
||||
+ public BeeFlyingMoveControl(final Mob entity, final int maxPitchChange, final boolean noGravity) {
|
||||
+ super(entity, maxPitchChange, noGravity);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void tick() {
|
||||
+ if (this.mob.getY() <= Bee.this.level().getMinBuildHeight()) {
|
||||
+ this.mob.setNoGravity(false);
|
||||
+ }
|
||||
+ super.tick();
|
||||
+ }
|
||||
+ }
|
||||
+ this.moveControl = new BeeFlyingMoveControl(this, 20, true);
|
||||
+ // Paper end - Fix MC-167279
|
||||
this.lookControl = new Bee.BeeLookControl(this);
|
||||
this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, -1.0F);
|
||||
this.setPathfindingMalus(BlockPathTypes.WATER, -1.0F);
|
|
@ -1,95 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Thu, 2 Jan 2020 12:25:07 -0600
|
||||
Subject: [PATCH] Improve Block#breakNaturally API
|
||||
|
||||
Adds bool parameter to play world effect on block break
|
||||
|
||||
Adds bool parameter to drop xp from blocks
|
||||
|
||||
Fixes fluid-logged blocks not leaving fluid behind if
|
||||
broken
|
||||
|
||||
Handles special cases for ice and turtle eggs
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.level.block.TurtleEggBlock decreaseEggs(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)V
|
||||
|
||||
Co-authored-by: William Blake Galbreath <Blake.Galbreath@GMail.com>
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/IceBlock.java b/src/main/java/net/minecraft/world/level/block/IceBlock.java
|
||||
index c919b5a382b1bfcafd938ff926d9146cc5cf0cdc..52c6c26a300cfd19c478afba411a17c8d5ea0c3c 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/IceBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/IceBlock.java
|
||||
@@ -35,6 +35,11 @@ public class IceBlock extends HalfTransparentBlock {
|
||||
@Override
|
||||
public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
|
||||
super.playerDestroy(world, player, pos, state, blockEntity, tool);
|
||||
+ // Paper start - Improve Block#breakNaturally API
|
||||
+ this.afterDestroy(world, pos, tool);
|
||||
+ }
|
||||
+ public void afterDestroy(Level world, BlockPos pos, ItemStack tool) {
|
||||
+ // Paper end - Improve Block#breakNaturally API
|
||||
if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool) == 0) {
|
||||
if (world.dimensionType().ultraWarm()) {
|
||||
world.removeBlock(pos, false);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
|
||||
index d4e14ac1514e2d8b87b4667a91c90eded3ba6636..f041b5d80bff9c022b007e04ef1558e9116acc6b 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
|
||||
@@ -452,6 +452,18 @@ public class CraftBlock implements Block {
|
||||
|
||||
@Override
|
||||
public boolean breakNaturally(ItemStack item) {
|
||||
+ // Paper start
|
||||
+ return this.breakNaturally(item, false);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean breakNaturally(boolean triggerEffect, boolean dropExperience) {
|
||||
+ return this.breakNaturally(null, triggerEffect, dropExperience);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean breakNaturally(ItemStack item, boolean triggerEffect, boolean dropExperience) {
|
||||
+ // Paper end
|
||||
// Order matters here, need to drop before setting to air so skulls can get their data
|
||||
net.minecraft.world.level.block.state.BlockState iblockdata = this.getNMS();
|
||||
net.minecraft.world.level.block.Block block = iblockdata.getBlock();
|
||||
@@ -461,11 +473,35 @@ public class CraftBlock implements Block {
|
||||
// Modelled off EntityHuman#hasBlock
|
||||
if (block != Blocks.AIR && (item == null || !iblockdata.requiresCorrectToolForDrops() || nmsItem.isCorrectToolForDrops(iblockdata))) {
|
||||
net.minecraft.world.level.block.Block.dropResources(iblockdata, this.world.getMinecraftWorld(), this.position, this.world.getBlockEntity(this.position), null, nmsItem);
|
||||
+ // Paper start - improve Block#breanNaturally
|
||||
+ if (triggerEffect) {
|
||||
+ if (iblockdata.getBlock() instanceof net.minecraft.world.level.block.BaseFireBlock) {
|
||||
+ this.world.levelEvent(net.minecraft.world.level.block.LevelEvent.SOUND_EXTINGUISH_FIRE, this.position, 0);
|
||||
+ } else {
|
||||
+ this.world.levelEvent(net.minecraft.world.level.block.LevelEvent.PARTICLES_DESTROY_BLOCK, this.position, net.minecraft.world.level.block.Block.getId(iblockdata));
|
||||
+ }
|
||||
+ }
|
||||
+ if (dropExperience) block.popExperience(this.world.getMinecraftWorld(), this.position, block.getExpDrop(iblockdata, this.world.getMinecraftWorld(), this.position, nmsItem, true));
|
||||
+ // Paper end
|
||||
result = true;
|
||||
}
|
||||
|
||||
// SPIGOT-6778: Directly call setBlock instead of setTypeAndData, so that the tile entiy is not removed and custom remove logic is run.
|
||||
- return this.world.setBlock(this.position, Blocks.AIR.defaultBlockState(), 3) && result;
|
||||
+ // Paper start - improve breakNaturally
|
||||
+ boolean destroyed = this.world.removeBlock(this.position, false);
|
||||
+ if (destroyed) {
|
||||
+ block.destroy(this.world, this.position, iblockdata);
|
||||
+ }
|
||||
+ if (result) {
|
||||
+ // special cases
|
||||
+ if (block instanceof net.minecraft.world.level.block.IceBlock iceBlock) {
|
||||
+ iceBlock.afterDestroy(this.world.getMinecraftWorld(), this.position, nmsItem);
|
||||
+ } else if (block instanceof net.minecraft.world.level.block.TurtleEggBlock turtleEggBlock) {
|
||||
+ turtleEggBlock.decreaseEggs(this.world.getMinecraftWorld(), this.position, iblockdata);
|
||||
+ }
|
||||
+ }
|
||||
+ return destroyed && result;
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,66 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Sat, 25 Jan 2020 17:04:35 -0800
|
||||
Subject: [PATCH] Optimise getChunkAt calls for loaded chunks
|
||||
|
||||
bypass the need to get a player chunk, then get the either,
|
||||
then unwrap it...
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
index 369e4bf5ff52cb774f1acaf760b8bd276a0745f5..326b67c15ee3df162bf4468729c49dd98b582f02 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -254,6 +254,12 @@ public class ServerChunkCache extends ChunkSource {
|
||||
return this.getChunk(x, z, leastStatus, create);
|
||||
}, this.mainThreadProcessor).join();
|
||||
} else {
|
||||
+ // Paper start - Perf: Optimise getChunkAt calls for loaded chunks
|
||||
+ LevelChunk ifLoaded = this.getChunkAtIfLoadedMainThread(x, z);
|
||||
+ if (ifLoaded != null) {
|
||||
+ return ifLoaded;
|
||||
+ }
|
||||
+ // Paper end - Perf: Optimise getChunkAt calls for loaded chunks
|
||||
ProfilerFiller gameprofilerfiller = this.level.getProfiler();
|
||||
|
||||
gameprofilerfiller.incrementCounter("getChunk");
|
||||
@@ -300,39 +306,7 @@ public class ServerChunkCache extends ChunkSource {
|
||||
if (Thread.currentThread() != this.mainThread) {
|
||||
return null;
|
||||
} else {
|
||||
- this.level.getProfiler().incrementCounter("getChunkNow");
|
||||
- long k = ChunkPos.asLong(chunkX, chunkZ);
|
||||
-
|
||||
- for (int l = 0; l < 4; ++l) {
|
||||
- if (k == this.lastChunkPos[l] && this.lastChunkStatus[l] == ChunkStatus.FULL) {
|
||||
- ChunkAccess ichunkaccess = this.lastChunk[l];
|
||||
-
|
||||
- return ichunkaccess instanceof LevelChunk ? (LevelChunk) ichunkaccess : null;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- ChunkHolder playerchunk = this.getVisibleChunkIfPresent(k);
|
||||
-
|
||||
- if (playerchunk == null) {
|
||||
- return null;
|
||||
- } else {
|
||||
- Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure> either = (Either) playerchunk.getFutureIfPresent(ChunkStatus.FULL).getNow(null); // CraftBukkit - decompile error
|
||||
-
|
||||
- if (either == null) {
|
||||
- return null;
|
||||
- } else {
|
||||
- ChunkAccess ichunkaccess1 = (ChunkAccess) either.left().orElse(null); // CraftBukkit - decompile error
|
||||
-
|
||||
- if (ichunkaccess1 != null) {
|
||||
- this.storeInCache(k, ichunkaccess1, ChunkStatus.FULL);
|
||||
- if (ichunkaccess1 instanceof LevelChunk) {
|
||||
- return (LevelChunk) ichunkaccess1;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- return null;
|
||||
- }
|
||||
- }
|
||||
+ return this.getChunkAtIfLoadedMainThread(chunkX, chunkZ); // Paper - Perf: Optimise getChunkAt calls for loaded chunks
|
||||
}
|
||||
}
|
||||
|
|
@ -1,331 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Fri, 19 Jul 2019 03:29:14 -0700
|
||||
Subject: [PATCH] Add debug for sync chunk loads
|
||||
|
||||
This patch adds a tool to find calls to getChunkAt which would load
|
||||
chunks, however it must be enabled by setting the startup flag
|
||||
-Dpaper.debug-sync-loads=true
|
||||
|
||||
- To get a debug log for sync loads, the command is
|
||||
/paper syncloadinfo
|
||||
- To clear clear the currently stored sync load info, use
|
||||
/paper syncloadinfo clear
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java b/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..404a8fd128043527d23f22ee26f7c8c739f09089
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java
|
||||
@@ -0,0 +1,175 @@
|
||||
+package com.destroystokyo.paper.io;
|
||||
+
|
||||
+import com.google.gson.JsonArray;
|
||||
+import com.google.gson.JsonObject;
|
||||
+import com.mojang.datafixers.util.Pair;
|
||||
+import it.unimi.dsi.fastutil.longs.Long2IntMap;
|
||||
+import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
|
||||
+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
+
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.List;
|
||||
+import java.util.Map;
|
||||
+import java.util.WeakHashMap;
|
||||
+import net.minecraft.world.level.Level;
|
||||
+
|
||||
+public class SyncLoadFinder {
|
||||
+
|
||||
+ public static final boolean ENABLED = Boolean.getBoolean("paper.debug-sync-loads");
|
||||
+
|
||||
+ private static final WeakHashMap<Level, Object2ObjectOpenHashMap<ThrowableWithEquals, SyncLoadInformation>> SYNC_LOADS = new WeakHashMap<>();
|
||||
+
|
||||
+ private static final class SyncLoadInformation {
|
||||
+
|
||||
+ public int times;
|
||||
+
|
||||
+ public final Long2IntOpenHashMap coordinateTimes = new Long2IntOpenHashMap();
|
||||
+ }
|
||||
+
|
||||
+ public static void clear() {
|
||||
+ SYNC_LOADS.clear();
|
||||
+ }
|
||||
+
|
||||
+ public static void logSyncLoad(final Level world, final int chunkX, final int chunkZ) {
|
||||
+ if (!ENABLED) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ final ThrowableWithEquals stacktrace = new ThrowableWithEquals(Thread.currentThread().getStackTrace());
|
||||
+
|
||||
+ SYNC_LOADS.compute(world, (final Level keyInMap, Object2ObjectOpenHashMap<ThrowableWithEquals, SyncLoadInformation> map) -> {
|
||||
+ if (map == null) {
|
||||
+ map = new Object2ObjectOpenHashMap<>();
|
||||
+ }
|
||||
+
|
||||
+ map.compute(stacktrace, (ThrowableWithEquals keyInMap0, SyncLoadInformation valueInMap) -> {
|
||||
+ if (valueInMap == null) {
|
||||
+ valueInMap = new SyncLoadInformation();
|
||||
+ }
|
||||
+
|
||||
+ ++valueInMap.times;
|
||||
+
|
||||
+ valueInMap.coordinateTimes.compute(io.papermc.paper.util.MCUtil.getCoordinateKey(chunkX, chunkZ), (Long keyInMap1, Integer valueInMap1) -> {
|
||||
+ return valueInMap1 == null ? Integer.valueOf(1) : Integer.valueOf(valueInMap1.intValue() + 1);
|
||||
+ });
|
||||
+
|
||||
+ return valueInMap;
|
||||
+ });
|
||||
+
|
||||
+ return map;
|
||||
+ });
|
||||
+ }
|
||||
+
|
||||
+ public static JsonObject serialize() {
|
||||
+ final JsonObject ret = new JsonObject();
|
||||
+
|
||||
+ final JsonArray worldsData = new JsonArray();
|
||||
+
|
||||
+ for (final Map.Entry<Level, Object2ObjectOpenHashMap<ThrowableWithEquals, SyncLoadInformation>> entry : SYNC_LOADS.entrySet()) {
|
||||
+ final Level world = entry.getKey();
|
||||
+
|
||||
+ final JsonObject worldData = new JsonObject();
|
||||
+
|
||||
+ worldData.addProperty("name", world.getWorld().getName());
|
||||
+
|
||||
+ final List<Pair<ThrowableWithEquals, SyncLoadInformation>> data = new ArrayList<>();
|
||||
+
|
||||
+ entry.getValue().forEach((ThrowableWithEquals stacktrace, SyncLoadInformation times) -> {
|
||||
+ data.add(new Pair<>(stacktrace, times));
|
||||
+ });
|
||||
+
|
||||
+ data.sort((Pair<ThrowableWithEquals, SyncLoadInformation> pair1, Pair<ThrowableWithEquals, SyncLoadInformation> pair2) -> {
|
||||
+ return Integer.compare(pair2.getSecond().times, pair1.getSecond().times); // reverse order
|
||||
+ });
|
||||
+
|
||||
+ final JsonArray stacktraces = new JsonArray();
|
||||
+
|
||||
+ for (Pair<ThrowableWithEquals, SyncLoadInformation> pair : data) {
|
||||
+ final JsonObject stacktrace = new JsonObject();
|
||||
+
|
||||
+ stacktrace.addProperty("times", pair.getSecond().times);
|
||||
+
|
||||
+ final JsonArray traces = new JsonArray();
|
||||
+
|
||||
+ for (StackTraceElement element : pair.getFirst().stacktrace) {
|
||||
+ traces.add(String.valueOf(element));
|
||||
+ }
|
||||
+
|
||||
+ stacktrace.add("stacktrace", traces);
|
||||
+
|
||||
+ final JsonArray coordinates = new JsonArray();
|
||||
+
|
||||
+ for (Long2IntMap.Entry coordinate : pair.getSecond().coordinateTimes.long2IntEntrySet()) {
|
||||
+ final long key = coordinate.getLongKey();
|
||||
+ final int times = coordinate.getIntValue();
|
||||
+ coordinates.add("(" + io.papermc.paper.util.MCUtil.getCoordinateX(key) + "," + io.papermc.paper.util.MCUtil.getCoordinateZ(key) + "): " + times);
|
||||
+ }
|
||||
+
|
||||
+ stacktrace.add("coordinates", coordinates);
|
||||
+
|
||||
+ stacktraces.add(stacktrace);
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ worldData.add("stacktraces", stacktraces);
|
||||
+ worldsData.add(worldData);
|
||||
+ }
|
||||
+
|
||||
+ ret.add("worlds", worldsData);
|
||||
+
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ static final class ThrowableWithEquals {
|
||||
+
|
||||
+ private final StackTraceElement[] stacktrace;
|
||||
+ private final int hash;
|
||||
+
|
||||
+ public ThrowableWithEquals(final StackTraceElement[] stacktrace) {
|
||||
+ this.stacktrace = stacktrace;
|
||||
+ this.hash = ThrowableWithEquals.hash(stacktrace);
|
||||
+ }
|
||||
+
|
||||
+ public static int hash(final StackTraceElement[] stacktrace) {
|
||||
+ int hash = 0;
|
||||
+
|
||||
+ for (int i = 0; i < stacktrace.length; ++i) {
|
||||
+ hash *= 31;
|
||||
+ hash += stacktrace[i].hashCode();
|
||||
+ }
|
||||
+
|
||||
+ return hash;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int hashCode() {
|
||||
+ return this.hash;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean equals(final Object obj) {
|
||||
+ if (obj == null || obj.getClass() != this.getClass()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ final ThrowableWithEquals other = (ThrowableWithEquals)obj;
|
||||
+ final StackTraceElement[] otherStackTrace = other.stacktrace;
|
||||
+
|
||||
+ if (this.stacktrace.length != otherStackTrace.length || this.hash != other.hash) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (this == obj) {
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ for (int i = 0; i < this.stacktrace.length; ++i) {
|
||||
+ if (!this.stacktrace[i].equals(otherStackTrace[i])) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/command/PaperCommand.java b/src/main/java/io/papermc/paper/command/PaperCommand.java
|
||||
index 69ffd6ea2ce7c6d4f211c6081fcea79afd7eac6c..69d093d3450931038ac3d27d7874060d13dc2225 100644
|
||||
--- a/src/main/java/io/papermc/paper/command/PaperCommand.java
|
||||
+++ b/src/main/java/io/papermc/paper/command/PaperCommand.java
|
||||
@@ -38,6 +38,7 @@ public final class PaperCommand extends Command {
|
||||
commands.put(Set.of("reload"), new ReloadCommand());
|
||||
commands.put(Set.of("version"), new VersionCommand());
|
||||
commands.put(Set.of("dumpplugins"), new DumpPluginsCommand());
|
||||
+ commands.put(Set.of("syncloadinfo"), new SyncLoadInfoCommand());
|
||||
|
||||
return commands.entrySet().stream()
|
||||
.flatMap(entry -> entry.getKey().stream().map(s -> Map.entry(s, entry.getValue())))
|
||||
diff --git a/src/main/java/io/papermc/paper/command/subcommands/SyncLoadInfoCommand.java b/src/main/java/io/papermc/paper/command/subcommands/SyncLoadInfoCommand.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..95d6022c9cfb2e36ec5a71be6e34354027c2ec08
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/command/subcommands/SyncLoadInfoCommand.java
|
||||
@@ -0,0 +1,88 @@
|
||||
+package io.papermc.paper.command.subcommands;
|
||||
+
|
||||
+import com.destroystokyo.paper.io.SyncLoadFinder;
|
||||
+import com.google.gson.JsonObject;
|
||||
+import com.google.gson.internal.Streams;
|
||||
+import com.google.gson.stream.JsonWriter;
|
||||
+import io.papermc.paper.command.CommandUtil;
|
||||
+import io.papermc.paper.command.PaperSubcommand;
|
||||
+import java.io.File;
|
||||
+import java.io.FileOutputStream;
|
||||
+import java.io.PrintStream;
|
||||
+import java.io.StringWriter;
|
||||
+import java.nio.charset.StandardCharsets;
|
||||
+import java.time.LocalDateTime;
|
||||
+import java.time.format.DateTimeFormatter;
|
||||
+import java.util.List;
|
||||
+
|
||||
+import net.kyori.adventure.text.event.ClickEvent;
|
||||
+import net.kyori.adventure.text.event.HoverEvent;
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
+import org.bukkit.command.CommandSender;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+import static net.kyori.adventure.text.Component.text;
|
||||
+import static net.kyori.adventure.text.format.NamedTextColor.GRAY;
|
||||
+import static net.kyori.adventure.text.format.NamedTextColor.GREEN;
|
||||
+import static net.kyori.adventure.text.format.NamedTextColor.RED;
|
||||
+import static net.kyori.adventure.text.format.NamedTextColor.WHITE;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public final class SyncLoadInfoCommand implements PaperSubcommand {
|
||||
+ @Override
|
||||
+ public boolean execute(final CommandSender sender, final String subCommand, final String[] args) {
|
||||
+ this.doSyncLoadInfo(sender, args);
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public List<String> tabComplete(final CommandSender sender, final String subCommand, final String[] args) {
|
||||
+ return CommandUtil.getListMatchingLast(sender, args, "clear");
|
||||
+ }
|
||||
+
|
||||
+ private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss");
|
||||
+
|
||||
+ private void doSyncLoadInfo(final CommandSender sender, final String[] args) {
|
||||
+ if (!SyncLoadFinder.ENABLED) {
|
||||
+ String systemFlag = "-Dpaper.debug-sync-loads=true";
|
||||
+ sender.sendMessage(text().color(RED).append(text("This command requires the server startup flag '")).append(
|
||||
+ text(systemFlag, WHITE).clickEvent(ClickEvent.copyToClipboard(systemFlag))
|
||||
+ .hoverEvent(HoverEvent.showText(text("Click to copy the system flag")))).append(
|
||||
+ text("' to be set.")));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (args.length > 0 && args[0].equals("clear")) {
|
||||
+ SyncLoadFinder.clear();
|
||||
+ sender.sendMessage(text("Sync load data cleared.", GRAY));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ File file = new File(new File(new File("."), "debug"),
|
||||
+ "sync-load-info-" + FORMATTER.format(LocalDateTime.now()) + ".txt");
|
||||
+ file.getParentFile().mkdirs();
|
||||
+ sender.sendMessage(text("Writing sync load info to " + file, GREEN));
|
||||
+
|
||||
+
|
||||
+ try {
|
||||
+ final JsonObject data = SyncLoadFinder.serialize();
|
||||
+
|
||||
+ StringWriter stringWriter = new StringWriter();
|
||||
+ JsonWriter jsonWriter = new JsonWriter(stringWriter);
|
||||
+ jsonWriter.setIndent(" ");
|
||||
+ jsonWriter.setLenient(false);
|
||||
+ Streams.write(data, jsonWriter);
|
||||
+
|
||||
+ try (
|
||||
+ PrintStream out = new PrintStream(new FileOutputStream(file), false, StandardCharsets.UTF_8)
|
||||
+ ) {
|
||||
+ out.print(stringWriter);
|
||||
+ }
|
||||
+ sender.sendMessage(text("Successfully written sync load information!", GREEN));
|
||||
+ } catch (Throwable thr) {
|
||||
+ sender.sendMessage(text("Failed to write sync load information! See the console for more info.", RED));
|
||||
+ MinecraftServer.LOGGER.warn("Error occurred while dumping sync chunk load info", thr);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
index 326b67c15ee3df162bf4468729c49dd98b582f02..8a118a7b2878d3c99dadfa97e2ae58fda2b3f93b 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -282,6 +282,7 @@ public class ServerChunkCache extends ChunkSource {
|
||||
|
||||
Objects.requireNonNull(completablefuture);
|
||||
if (!completablefuture.isDone()) { // Paper
|
||||
+ com.destroystokyo.paper.io.SyncLoadFinder.logSyncLoad(this.level, x, z); // Paper - Add debug for sync chunk loads
|
||||
this.level.timings.syncChunkLoad.startTiming(); // Paper
|
||||
chunkproviderserver_b.managedBlock(completablefuture::isDone);
|
||||
this.level.timings.syncChunkLoad.stopTiming(); // Paper
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 54c0aa440cd8e7e1cedc6ef9ae963c68558b6080..4d1d84383c11ef1e83edb50be62173533b7a641b 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -415,6 +415,13 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public boolean hasChunk(int chunkX, int chunkZ) {
|
||||
+ return this.getChunkSource().getChunkAtIfLoadedImmediately(chunkX, chunkZ) != null;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
/** @deprecated */
|
||||
@Deprecated
|
||||
@VisibleForTesting
|
|
@ -1,47 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Nassim Jahnke <nassim@njahnke.dev>
|
||||
Date: Wed, 16 Mar 2022 13:58:16 +0100
|
||||
Subject: [PATCH] Improve java version check
|
||||
|
||||
Co-Authored-By: MiniDigger <admin@benndorf.dev>
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
index d8a7287849407c4756d4ebe4b55c358970320ce3..f21bff10aa56b418b1c3c3f1a40b88c4e992c26d 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
@@ -201,23 +201,27 @@ public class Main {
|
||||
return;
|
||||
}
|
||||
|
||||
+ // Paper start - Improve java version check
|
||||
+ boolean skip = Boolean.getBoolean("Paper.IgnoreJavaVersion");
|
||||
float javaVersion = Float.parseFloat(System.getProperty("java.class.version"));
|
||||
- if (javaVersion < 61.0) {
|
||||
- System.err.println("Unsupported Java detected (" + javaVersion + "). This version of Minecraft requires at least Java 17. Check your Java version with the command 'java -version'.");
|
||||
- return;
|
||||
- }
|
||||
- if (javaVersion > 66.0) {
|
||||
- System.err.println("Unsupported Java detected (" + javaVersion + "). Only up to Java 22 is supported.");
|
||||
+ boolean isOldVersion = javaVersion < 61.0;
|
||||
+ if (!skip && isOldVersion) {
|
||||
+ System.err.println("Unsupported Java detected (" + javaVersion + "). This version of Minecraft requires at least Java 17. Check your Java version with the command 'java -version'. For more info see https://docs.papermc.io/misc/java-install");
|
||||
return;
|
||||
}
|
||||
String javaVersionName = System.getProperty("java.version");
|
||||
// J2SE SDK/JRE Version String Naming Convention
|
||||
boolean isPreRelease = javaVersionName.contains("-");
|
||||
- if (isPreRelease && javaVersion == 61.0) {
|
||||
- System.err.println("Unsupported Java detected (" + javaVersionName + "). You are running an outdated, pre-release version. Only general availability versions of Java are supported. Please update your Java version.");
|
||||
+ if (!skip && isPreRelease) {
|
||||
+ System.err.println("Unsupported Java detected (" + javaVersionName + "). You are running an unsupported, non official, version. Only general availability versions of Java are supported. Please update your Java version. See https://docs.papermc.io/paper/faq#unsupported-java-detected-what-do-i-do for more information.");
|
||||
return;
|
||||
}
|
||||
|
||||
+ if (skip && (isOldVersion || isPreRelease)) {
|
||||
+ System.err.println("Unsupported Java detected ("+ javaVersionName + "), but the check was skipped. Proceed with caution! ");
|
||||
+ }
|
||||
+ // Paper end - Improve java version check
|
||||
+
|
||||
try {
|
||||
// Paper start - Handled by TerminalConsoleAppender
|
||||
/*
|
|
@ -1,26 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||
Date: Sun, 9 Feb 2020 00:19:05 -0600
|
||||
Subject: [PATCH] Add ThrownEggHatchEvent
|
||||
|
||||
Adds a new event similar to PlayerEggThrowEvent, but without the Player requirement
|
||||
(dispensers can throw eggs to hatch them, too).
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownEgg.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownEgg.java
|
||||
index 02da4d1ff3c72e8adad2f4cee449ad21dec34e02..82bb8004635865f5202578d5a6f520048e7269d5 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/projectile/ThrownEgg.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownEgg.java
|
||||
@@ -83,6 +83,13 @@ public class ThrownEgg extends ThrowableItemProjectile {
|
||||
}
|
||||
}
|
||||
// CraftBukkit end
|
||||
+ // Paper start - Add ThrownEggHatchEvent
|
||||
+ com.destroystokyo.paper.event.entity.ThrownEggHatchEvent event = new com.destroystokyo.paper.event.entity.ThrownEggHatchEvent((org.bukkit.entity.Egg) getBukkitEntity(), hatching, b0, hatchingType);
|
||||
+ event.callEvent();
|
||||
+ hatching = event.isHatching();
|
||||
+ b0 = hatching ? event.getNumHatches() : 0; // If hatching is set to false, ensure child count is 0
|
||||
+ hatchingType = event.getHatchingType();
|
||||
+ // Paper end - Add ThrownEggHatchEvent
|
||||
|
||||
for (int i = 0; i < b0; ++i) {
|
||||
Entity entitychicken = this.level().getWorld().makeEntity(new org.bukkit.Location(this.level().getWorld(), this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F), hatchingType.getEntityClass()); // CraftBukkit
|
|
@ -1,76 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Sat, 8 Feb 2020 23:26:11 -0600
|
||||
Subject: [PATCH] Entity Jump API
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.entity.LivingEntity jumping
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index b4a817e047a78723d746740c88503441625ac8e7..2a417145d9fe4d029cf3738f3320c0bcd3e025a9 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -3304,8 +3304,10 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
} else if (this.isInLava() && (!this.onGround() || d3 > d4)) {
|
||||
this.jumpInLiquid(FluidTags.LAVA);
|
||||
} else if ((this.onGround() || flag && d3 <= d4) && this.noJumpDelay == 0) {
|
||||
+ if (new com.destroystokyo.paper.event.entity.EntityJumpEvent(getBukkitLivingEntity()).callEvent()) { // Paper - Entity Jump API
|
||||
this.jumpFromGround();
|
||||
this.noJumpDelay = 10;
|
||||
+ } else { this.setJumping(false); } // Paper - Entity Jump API; setJumping(false) stops a potential loop
|
||||
}
|
||||
} else {
|
||||
this.noJumpDelay = 0;
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/Panda.java b/src/main/java/net/minecraft/world/entity/animal/Panda.java
|
||||
index 9c70f3bf7cc37a7df9d1b8c5d5f0f6264680e421..4224e8e75613b6ec0228b2757cb98140d83bc2e2 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/Panda.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/Panda.java
|
||||
@@ -528,7 +528,9 @@ public class Panda extends Animal {
|
||||
Panda entitypanda = (Panda) iterator.next();
|
||||
|
||||
if (!entitypanda.isBaby() && entitypanda.onGround() && !entitypanda.isInWater() && entitypanda.canPerformAction()) {
|
||||
+ if (new com.destroystokyo.paper.event.entity.EntityJumpEvent(getBukkitLivingEntity()).callEvent()) { // Paper - Entity Jump API
|
||||
entitypanda.jumpFromGround();
|
||||
+ } else { this.setJumping(false); } // Paper - Entity Jump API; setJumping(false) stops a potential loop
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/Ravager.java b/src/main/java/net/minecraft/world/entity/monster/Ravager.java
|
||||
index aba20a4352d8983b01ab5d329187588f68d3e405..aac60e85cd6dba7d87f4a1663c2c62952521d112 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Ravager.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Ravager.java
|
||||
@@ -167,7 +167,9 @@ public class Ravager extends Raider {
|
||||
}
|
||||
|
||||
if (!flag && this.onGround()) {
|
||||
+ if (new com.destroystokyo.paper.event.entity.EntityJumpEvent(getBukkitLivingEntity()).callEvent()) { // Paper - Entity Jump API
|
||||
this.jumpFromGround();
|
||||
+ } else { this.setJumping(false); } // Paper - Entity Jump API; setJumping(false) stops a potential loop
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
|
||||
index 5def5bccd8fce86ce015567e65fefae329819c18..29fa2231cc5d9c3ac36d508f14408d6077b6594c 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
|
||||
@@ -976,4 +976,20 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
|
||||
return org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(this.getHandle().getUsedItemHand());
|
||||
}
|
||||
// Paper end - active item API
|
||||
+
|
||||
+ // Paper start - entity jump API
|
||||
+ @Override
|
||||
+ public boolean isJumping() {
|
||||
+ return getHandle().jumping;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setJumping(boolean jumping) {
|
||||
+ getHandle().setJumping(jumping);
|
||||
+ if (jumping && getHandle() instanceof Mob) {
|
||||
+ // this is needed to actually make a mob jump
|
||||
+ ((Mob) getHandle()).getJumpControl().jump();
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - entity jump API
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Fri, 7 Feb 2020 14:36:56 -0600
|
||||
Subject: [PATCH] Add option to nerf pigmen from nether portals
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index 98db75a013905ddd38ffd26d615ad8d02d8ddd22..537461e60366580bd18e3814113ef1f8b7009b39 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -397,6 +397,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
|
||||
public void inactiveTick() { }
|
||||
// Spigot end
|
||||
protected int numCollisions = 0; // Paper - Cap entity collisions
|
||||
+ public boolean fromNetherPortal; // Paper - Add option to nerf pigmen from nether portals
|
||||
public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one
|
||||
// Paper start - Entity origin API
|
||||
@javax.annotation.Nullable
|
||||
@@ -2186,6 +2187,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
|
||||
if (spawnedViaMobSpawner) {
|
||||
nbttagcompound.putBoolean("Paper.FromMobSpawner", true);
|
||||
}
|
||||
+ if (fromNetherPortal) {
|
||||
+ nbttagcompound.putBoolean("Paper.FromNetherPortal", true);
|
||||
+ }
|
||||
// Paper end
|
||||
return nbttagcompound;
|
||||
} catch (Throwable throwable) {
|
||||
@@ -2328,6 +2332,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
|
||||
}
|
||||
|
||||
spawnedViaMobSpawner = nbt.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status
|
||||
+ fromNetherPortal = nbt.getBoolean("Paper.FromNetherPortal");
|
||||
if (nbt.contains("Paper.SpawnReason")) {
|
||||
String spawnReasonName = nbt.getString("Paper.SpawnReason");
|
||||
try {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java
|
||||
index c9ff8a3fd8d65033ce5a476e8ceaf9d1b8e2d887..2a8f97d97ae7f268da920b5e3b9719743fa9a8e0 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java
|
||||
@@ -71,6 +71,8 @@ public class NetherPortalBlock extends Block {
|
||||
|
||||
if (entity != null) {
|
||||
entity.setPortalCooldown();
|
||||
+ entity.fromNetherPortal = true; // Paper - Add option to nerf pigmen from nether portals
|
||||
+ if (world.paperConfig().entities.behavior.nerfPigmenFromNetherPortals) ((net.minecraft.world.entity.Mob) entity).aware = false; // Paper - Add option to nerf pigmen from nether portals
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,399 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Sun, 2 Feb 2020 04:00:40 -0600
|
||||
Subject: [PATCH] Make the GUI graph fancier
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/gui/GraphColor.java b/src/main/java/com/destroystokyo/paper/gui/GraphColor.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..a4e641fdcccd3efcd1a2865dc6dc28d50671b995
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/gui/GraphColor.java
|
||||
@@ -0,0 +1,44 @@
|
||||
+package com.destroystokyo.paper.gui;
|
||||
+
|
||||
+import java.awt.Color;
|
||||
+
|
||||
+public class GraphColor {
|
||||
+ private static final Color[] colorLine = new Color[101];
|
||||
+ private static final Color[] colorFill = new Color[101];
|
||||
+
|
||||
+ static {
|
||||
+ for (int i = 0; i < 101; i++) {
|
||||
+ Color color = createColor(i);
|
||||
+ colorLine[i] = new Color(color.getRed() / 2, color.getGreen() / 2, color.getBlue() / 2, 255);
|
||||
+ colorFill[i] = new Color(colorLine[i].getRed(), colorLine[i].getGreen(), colorLine[i].getBlue(), 125);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public static Color getLineColor(int percent) {
|
||||
+ return colorLine[percent];
|
||||
+ }
|
||||
+
|
||||
+ public static Color getFillColor(int percent) {
|
||||
+ return colorFill[percent];
|
||||
+ }
|
||||
+
|
||||
+ private static Color createColor(int percent) {
|
||||
+ if (percent <= 50) {
|
||||
+ return new Color(0X00FF00);
|
||||
+ }
|
||||
+
|
||||
+ int value = 510 - (int) (Math.min(Math.max(0, ((percent - 50) / 50F)), 1) * 510);
|
||||
+
|
||||
+ int red, green;
|
||||
+ if (value < 255) {
|
||||
+ red = 255;
|
||||
+ green = (int) (Math.sqrt(value) * 16);
|
||||
+ } else {
|
||||
+ green = 255;
|
||||
+ value = value - 255;
|
||||
+ red = 255 - (value * value / 255);
|
||||
+ }
|
||||
+
|
||||
+ return new Color(red, green, 0);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/gui/GraphData.java b/src/main/java/com/destroystokyo/paper/gui/GraphData.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..186fc722965e403f76b1480e1c2381fc34e29049
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/gui/GraphData.java
|
||||
@@ -0,0 +1,47 @@
|
||||
+package com.destroystokyo.paper.gui;
|
||||
+
|
||||
+import java.awt.Color;
|
||||
+
|
||||
+public class GraphData {
|
||||
+ private long total;
|
||||
+ private long free;
|
||||
+ private long max;
|
||||
+ private long usedMem;
|
||||
+ private int usedPercent;
|
||||
+
|
||||
+ public GraphData(long total, long free, long max) {
|
||||
+ this.total = total;
|
||||
+ this.free = free;
|
||||
+ this.max = max;
|
||||
+ this.usedMem = total - free;
|
||||
+ this.usedPercent = usedMem == 0 ? 0 : (int) (usedMem * 100L / max);
|
||||
+ }
|
||||
+
|
||||
+ public long getTotal() {
|
||||
+ return total;
|
||||
+ }
|
||||
+
|
||||
+ public long getFree() {
|
||||
+ return free;
|
||||
+ }
|
||||
+
|
||||
+ public long getMax() {
|
||||
+ return max;
|
||||
+ }
|
||||
+
|
||||
+ public long getUsedMem() {
|
||||
+ return usedMem;
|
||||
+ }
|
||||
+
|
||||
+ public int getUsedPercent() {
|
||||
+ return usedPercent;
|
||||
+ }
|
||||
+
|
||||
+ public Color getFillColor() {
|
||||
+ return GraphColor.getFillColor(usedPercent);
|
||||
+ }
|
||||
+
|
||||
+ public Color getLineColor() {
|
||||
+ return GraphColor.getLineColor(usedPercent);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java b/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..537bc6213545e8ff1b7b51bc4b27fd5b2a740883
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java
|
||||
@@ -0,0 +1,41 @@
|
||||
+package com.destroystokyo.paper.gui;
|
||||
+
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
+
|
||||
+import javax.swing.JPanel;
|
||||
+import javax.swing.Timer;
|
||||
+import java.awt.BorderLayout;
|
||||
+import java.awt.Dimension;
|
||||
+
|
||||
+public class GuiStatsComponent extends JPanel {
|
||||
+ private final Timer timer;
|
||||
+ private final RAMGraph ramGraph;
|
||||
+
|
||||
+ public GuiStatsComponent(MinecraftServer server) {
|
||||
+ super(new BorderLayout());
|
||||
+
|
||||
+ setOpaque(false);
|
||||
+
|
||||
+ ramGraph = new RAMGraph();
|
||||
+ RAMDetails ramDetails = new RAMDetails(server);
|
||||
+
|
||||
+ add(ramGraph, "North");
|
||||
+ add(ramDetails, "Center");
|
||||
+
|
||||
+ timer = new Timer(500, (event) -> {
|
||||
+ ramGraph.update();
|
||||
+ ramDetails.update();
|
||||
+ });
|
||||
+ timer.start();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Dimension getPreferredSize() {
|
||||
+ return new Dimension(350, 200);
|
||||
+ }
|
||||
+
|
||||
+ public void close() {
|
||||
+ timer.stop();
|
||||
+ ramGraph.stop();
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..f93373d28d741e1f8a53e07b4e328ce9c4e1657f
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java
|
||||
@@ -0,0 +1,74 @@
|
||||
+package com.destroystokyo.paper.gui;
|
||||
+
|
||||
+import net.minecraft.Util;
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
+import net.minecraft.util.TimeUtil;
|
||||
+
|
||||
+import javax.swing.DefaultListCellRenderer;
|
||||
+import javax.swing.DefaultListSelectionModel;
|
||||
+import javax.swing.JList;
|
||||
+import javax.swing.border.EmptyBorder;
|
||||
+import java.awt.Dimension;
|
||||
+import java.text.DecimalFormat;
|
||||
+import java.text.DecimalFormatSymbols;
|
||||
+import java.util.Locale;
|
||||
+import java.util.Vector;
|
||||
+
|
||||
+public class RAMDetails extends JList<String> {
|
||||
+ public static final DecimalFormat DECIMAL_FORMAT = Util.make(new DecimalFormat("########0.000"), (format)
|
||||
+ -> format.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT)));
|
||||
+
|
||||
+ private final MinecraftServer server;
|
||||
+
|
||||
+ public RAMDetails(MinecraftServer server) {
|
||||
+ this.server = server;
|
||||
+
|
||||
+ setBorder(new EmptyBorder(0, 10, 0, 0));
|
||||
+ setFixedCellHeight(20);
|
||||
+ setOpaque(false);
|
||||
+
|
||||
+ DefaultListCellRenderer renderer = new DefaultListCellRenderer();
|
||||
+ renderer.setOpaque(false);
|
||||
+ setCellRenderer(renderer);
|
||||
+
|
||||
+ setSelectionModel(new DefaultListSelectionModel() {
|
||||
+ @Override
|
||||
+ public void setAnchorSelectionIndex(final int anchorIndex) {
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setLeadAnchorNotificationEnabled(final boolean flag) {
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setLeadSelectionIndex(final int leadIndex) {
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setSelectionInterval(final int index0, final int index1) {
|
||||
+ }
|
||||
+ });
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Dimension getPreferredSize() {
|
||||
+ return new Dimension(350, 100);
|
||||
+ }
|
||||
+
|
||||
+ public void update() {
|
||||
+ GraphData data = RAMGraph.DATA.peekLast();
|
||||
+ Vector<String> vector = new Vector<>();
|
||||
+ vector.add("Memory use: " + (data.getUsedMem() / 1024L / 1024L) + " mb (" + (data.getFree() * 100L / data.getMax()) + "% free)");
|
||||
+ vector.add("Heap: " + (data.getTotal() / 1024L / 1024L) + " / " + (data.getMax() / 1024L / 1024L) + " mb");
|
||||
+ vector.add("Avg tick: " + DECIMAL_FORMAT.format((double)this.server.getAverageTickTimeNanos() / (double) TimeUtil.NANOSECONDS_PER_MILLISECOND) + " ms");
|
||||
+ setListData(vector);
|
||||
+ }
|
||||
+
|
||||
+ public double getAverage(long[] tickTimes) {
|
||||
+ long total = 0L;
|
||||
+ for (long value : tickTimes) {
|
||||
+ total += value * 1000;
|
||||
+ }
|
||||
+ return ((double) total / (double) tickTimes.length) * 1.0E-6D;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/gui/RAMGraph.java b/src/main/java/com/destroystokyo/paper/gui/RAMGraph.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..c3e54da4ab6440811aab2f9dd1e218802ac13285
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/gui/RAMGraph.java
|
||||
@@ -0,0 +1,144 @@
|
||||
+package com.destroystokyo.paper.gui;
|
||||
+
|
||||
+import javax.swing.JComponent;
|
||||
+import javax.swing.SwingUtilities;
|
||||
+import javax.swing.Timer;
|
||||
+import javax.swing.ToolTipManager;
|
||||
+import java.awt.Color;
|
||||
+import java.awt.Dimension;
|
||||
+import java.awt.Graphics;
|
||||
+import java.awt.MouseInfo;
|
||||
+import java.awt.Point;
|
||||
+import java.awt.PointerInfo;
|
||||
+import java.awt.event.MouseAdapter;
|
||||
+import java.awt.event.MouseEvent;
|
||||
+import java.text.SimpleDateFormat;
|
||||
+import java.util.Date;
|
||||
+import java.util.LinkedList;
|
||||
+import java.util.concurrent.TimeUnit;
|
||||
+
|
||||
+public class RAMGraph extends JComponent {
|
||||
+ public static final LinkedList<GraphData> DATA = new LinkedList<GraphData>() {
|
||||
+ @Override
|
||||
+ public boolean add(GraphData data) {
|
||||
+ if (size() >= 348) {
|
||||
+ remove();
|
||||
+ }
|
||||
+ return super.add(data);
|
||||
+ }
|
||||
+ };
|
||||
+
|
||||
+ static {
|
||||
+ GraphData empty = new GraphData(0, 0, 0);
|
||||
+ for (int i = 0; i < 350; i++) {
|
||||
+ DATA.add(empty);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private final Timer timer;
|
||||
+ private final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss");
|
||||
+
|
||||
+ private int currentTick;
|
||||
+
|
||||
+ public RAMGraph() {
|
||||
+ ToolTipManager.sharedInstance().setInitialDelay(0);
|
||||
+
|
||||
+ addMouseListener(new MouseAdapter() {
|
||||
+ final int defaultDismissTimeout = ToolTipManager.sharedInstance().getDismissDelay();
|
||||
+ final int dismissDelayMinutes = (int) TimeUnit.MINUTES.toMillis(10);
|
||||
+
|
||||
+ @Override
|
||||
+ public void mouseEntered(MouseEvent me) {
|
||||
+ ToolTipManager.sharedInstance().setDismissDelay(dismissDelayMinutes);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void mouseExited(MouseEvent me) {
|
||||
+ ToolTipManager.sharedInstance().setDismissDelay(defaultDismissTimeout);
|
||||
+ }
|
||||
+ });
|
||||
+
|
||||
+ timer = new Timer(50, (event) -> repaint());
|
||||
+ timer.start();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Dimension getPreferredSize() {
|
||||
+ return new Dimension(350, 110);
|
||||
+ }
|
||||
+
|
||||
+ public void update() {
|
||||
+ Runtime jvm = Runtime.getRuntime();
|
||||
+ DATA.add(new GraphData(jvm.totalMemory(), jvm.freeMemory(), jvm.maxMemory()));
|
||||
+
|
||||
+ PointerInfo pointerInfo = MouseInfo.getPointerInfo();
|
||||
+ if (pointerInfo != null) {
|
||||
+ Point point = pointerInfo.getLocation();
|
||||
+ if (point != null) {
|
||||
+ Point loc = new Point(point);
|
||||
+ SwingUtilities.convertPointFromScreen(loc, this);
|
||||
+ if (this.contains(loc)) {
|
||||
+ ToolTipManager.sharedInstance().mouseMoved(
|
||||
+ new MouseEvent(this, -1, System.currentTimeMillis(), 0, loc.x, loc.y,
|
||||
+ point.x, point.y, 0, false, 0));
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ currentTick++;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void paint(Graphics graphics) {
|
||||
+ graphics.setColor(new Color(0xFFFFFFFF));
|
||||
+ graphics.fillRect(0, 0, 350, 100);
|
||||
+
|
||||
+ graphics.setColor(new Color(0x888888));
|
||||
+ graphics.drawLine(1, 25, 348, 25);
|
||||
+ graphics.drawLine(1, 50, 348, 50);
|
||||
+ graphics.drawLine(1, 75, 348, 75);
|
||||
+
|
||||
+ int i = 0;
|
||||
+ for (GraphData data : DATA) {
|
||||
+ i++;
|
||||
+ if ((i + currentTick) % 120 == 0) {
|
||||
+ graphics.setColor(new Color(0x888888));
|
||||
+ graphics.drawLine(i, 1, i, 99);
|
||||
+ }
|
||||
+ int used = data.getUsedPercent();
|
||||
+ if (used > 0) {
|
||||
+ Color color = data.getLineColor();
|
||||
+ graphics.setColor(data.getFillColor());
|
||||
+ graphics.fillRect(i, 100 - used, 1, used);
|
||||
+ graphics.setColor(color);
|
||||
+ graphics.fillRect(i, 100 - used, 1, 1);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ graphics.setColor(new Color(0xFF000000));
|
||||
+ graphics.drawRect(0, 0, 348, 100);
|
||||
+
|
||||
+ Point m = getMousePosition();
|
||||
+ if (m != null && m.x > 0 && m.x < 348 && m.y > 0 && m.y < 100) {
|
||||
+ GraphData data = DATA.get(m.x);
|
||||
+ int used = data.getUsedPercent();
|
||||
+ graphics.setColor(new Color(0x000000));
|
||||
+ graphics.drawLine(m.x, 1, m.x, 99);
|
||||
+ graphics.drawOval(m.x - 2, 100 - used - 2, 5, 5);
|
||||
+ graphics.setColor(data.getLineColor());
|
||||
+ graphics.fillOval(m.x - 2, 100 - used - 2, 5, 5);
|
||||
+ setToolTipText(String.format("<html><body>Used: %s mb (%s%%)<br/>%s</body></html>",
|
||||
+ Math.round(data.getUsedMem() / 1024F / 1024F),
|
||||
+ used, getTime(m.x)));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public String getTime(int halfSeconds) {
|
||||
+ int millis = (348 - halfSeconds) / 2 * 1000;
|
||||
+ return TIME_FORMAT.format(new Date((System.currentTimeMillis() - millis)));
|
||||
+ }
|
||||
+
|
||||
+ public void stop() {
|
||||
+ timer.stop();
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java b/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java
|
||||
index d292fdb165436f0b9b46b32110f5e09ad0e517a1..2bbc57b4869caf690f53618d60359c5133ec62a8 100644
|
||||
--- a/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java
|
||||
+++ b/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java
|
||||
@@ -95,7 +95,7 @@ public class MinecraftServerGui extends JComponent {
|
||||
|
||||
private JComponent buildInfoPanel() {
|
||||
JPanel jpanel = new JPanel(new BorderLayout());
|
||||
- StatsComponent guistatscomponent = new StatsComponent(this.server);
|
||||
+ com.destroystokyo.paper.gui.GuiStatsComponent guistatscomponent = new com.destroystokyo.paper.gui.GuiStatsComponent(this.server); // Paper - Make GUI graph fancier
|
||||
Collection<Runnable> collection = this.finalizers; // CraftBukkit - decompile error
|
||||
|
||||
Objects.requireNonNull(guistatscomponent);
|
|
@ -1,30 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Trigary <trigary0@gmail.com>
|
||||
Date: Sun, 1 Mar 2020 22:43:24 +0100
|
||||
Subject: [PATCH] add hand to BlockMultiPlaceEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
index 449dab3d6e16b2b0fcc78c9e1b7173c822be9c53..15c9150b7e48781268babe5915dc0e906645b341 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
@@ -402,13 +402,18 @@ public class CraftEventFactory {
|
||||
}
|
||||
|
||||
org.bukkit.inventory.ItemStack item;
|
||||
+ // Paper start - add hand to BlockMultiPlaceEvent
|
||||
+ EquipmentSlot equipmentSlot;
|
||||
if (hand == InteractionHand.MAIN_HAND) {
|
||||
item = player.getInventory().getItemInMainHand();
|
||||
+ equipmentSlot = EquipmentSlot.HAND;
|
||||
} else {
|
||||
item = player.getInventory().getItemInOffHand();
|
||||
+ equipmentSlot = EquipmentSlot.OFF_HAND;
|
||||
}
|
||||
|
||||
- BlockMultiPlaceEvent event = new BlockMultiPlaceEvent(blockStates, blockClicked, item, player, canBuild);
|
||||
+ BlockMultiPlaceEvent event = new BlockMultiPlaceEvent(blockStates, blockClicked, item, player, canBuild, equipmentSlot);
|
||||
+ // Paper end
|
||||
craftServer.getPluginManager().callEvent(event);
|
||||
|
||||
return event;
|
|
@ -1,18 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Sat, 7 Mar 2020 00:07:51 +0000
|
||||
Subject: [PATCH] Validate tripwire hook placement before update
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java b/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java
|
||||
index eed36b6736a4f971022fdbce989da03f42794bb5..d9b3877257b31ca1b5acc4a47fbf5b993de69ae0 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java
|
||||
@@ -188,6 +188,7 @@ public class TripWireHookBlock extends Block {
|
||||
|
||||
TripWireHookBlock.emitState(world, pos, flag4, flag5, flag2, flag3);
|
||||
if (!flag) {
|
||||
+ if (world.getBlockState(pos).getBlock() == Blocks.TRIPWIRE_HOOK) // Paper - Validate tripwire hook placement before update
|
||||
world.setBlock(pos, (BlockState) iblockdata3.setValue(TripWireHookBlock.FACING, enumdirection), 3);
|
||||
if (flag1) {
|
||||
TripWireHookBlock.notifyNeighbors(block, world, pos, enumdirection);
|
|
@ -1,19 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||
Date: Sat, 13 Apr 2019 16:50:58 -0500
|
||||
Subject: [PATCH] Add option to allow iron golems to spawn in air
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/IronGolem.java b/src/main/java/net/minecraft/world/entity/animal/IronGolem.java
|
||||
index ce83fe0b68fcb229dd37fe07e5f21b52a60c32de..6cfe0d6c46caa122db107c607d27a2bdcd82f7a8 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/IronGolem.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/IronGolem.java
|
||||
@@ -325,7 +325,7 @@ public class IronGolem extends AbstractGolem implements NeutralMob {
|
||||
BlockPos blockposition1 = blockposition.below();
|
||||
BlockState iblockdata = world.getBlockState(blockposition1);
|
||||
|
||||
- if (!iblockdata.entityCanStandOn(world, blockposition1, this)) {
|
||||
+ if (!iblockdata.entityCanStandOn(world, blockposition1, this) && !this.level().paperConfig().entities.spawning.ironGolemsCanSpawnInAir) { // Paper - Add option to allow iron golems to spawn in air
|
||||
return false;
|
||||
} else {
|
||||
for (int i = 1; i < 3; ++i) {
|
|
@ -1,28 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zero <zero@cock.li>
|
||||
Date: Sat, 22 Feb 2020 16:10:31 -0500
|
||||
Subject: [PATCH] Configurable chance of villager zombie infection
|
||||
|
||||
This allows you to solve an issue in vanilla behavior where:
|
||||
* On easy difficulty your villagers will NEVER get infected, meaning they will always die.
|
||||
* On normal difficulty they will have a 50% of getting infected or dying.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
|
||||
index 2c8529540bf3644896f3c05d5f544bd848647807..408cbb80df72cf67e5228a76b7f267281e1752ab 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
|
||||
@@ -452,12 +452,8 @@ public class Zombie extends Monster {
|
||||
public boolean killedEntity(ServerLevel world, LivingEntity other) {
|
||||
boolean flag = super.killedEntity(world, other);
|
||||
|
||||
- if ((world.getDifficulty() == Difficulty.NORMAL || world.getDifficulty() == Difficulty.HARD) && other instanceof Villager) {
|
||||
- Villager entityvillager = (Villager) other;
|
||||
-
|
||||
- if (world.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) {
|
||||
- return flag;
|
||||
- }
|
||||
+ final double fallbackChance = world.getDifficulty() == Difficulty.HARD ? 100d : world.getDifficulty() == Difficulty.NORMAL ? 50d : 0d; // Paper - Configurable chance of villager zombie infection
|
||||
+ if (this.random.nextDouble() * 100 < world.paperConfig().entities.behavior.zombieVillagerInfectionChance.or(fallbackChance) && other instanceof Villager entityvillager) { // Paper - Configurable chance of villager zombie infection
|
||||
// CraftBukkit start
|
||||
flag = Zombie.zombifyVillager(world, entityvillager, this.blockPosition(), this.isSilent(), CreatureSpawnEvent.SpawnReason.INFECTION) == null;
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Tue, 14 Jan 2020 14:59:08 -0800
|
||||
Subject: [PATCH] Optimise Chunk#getFluid
|
||||
|
||||
Removing the try catch and generally reducing ops should make it
|
||||
faster on its own, however removing the try catch makes it
|
||||
easier to inline due to code size
|
||||
|
||||
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 82b59b7c791216aaaaaaf2972f47bd21dac7a202..5403fc4fa2ed2526d2e67c230a46dd2a75e017be 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -370,18 +370,20 @@ public class LevelChunk extends ChunkAccess {
|
||||
}
|
||||
|
||||
public FluidState getFluidState(int x, int y, int z) {
|
||||
- try {
|
||||
- int l = this.getSectionIndex(y);
|
||||
-
|
||||
- if (l >= 0 && l < this.sections.length) {
|
||||
- LevelChunkSection chunksection = this.sections[l];
|
||||
+ // Paper start - Perf: Optimise Chunk#getFluid
|
||||
+ // try { // Remove try catch
|
||||
+ int index = this.getSectionIndex(y);
|
||||
+ if (index >= 0 && index < this.sections.length) {
|
||||
+ LevelChunkSection chunksection = this.sections[index];
|
||||
|
||||
if (!chunksection.hasOnlyAir()) {
|
||||
- return chunksection.getFluidState(x & 15, y & 15, z & 15);
|
||||
+ return chunksection.states.get((y & 15) << 8 | (z & 15) << 4 | x & 15).getFluidState();
|
||||
+ // Paper end - Perf: Optimise Chunk#getFluid
|
||||
}
|
||||
}
|
||||
|
||||
return Fluids.EMPTY.defaultFluidState();
|
||||
+ /* // Paper - Perf: Optimise Chunk#getFluid
|
||||
} catch (Throwable throwable) {
|
||||
CrashReport crashreport = CrashReport.forThrowable(throwable, "Getting fluid state");
|
||||
CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block being got");
|
||||
@@ -391,6 +393,7 @@ public class LevelChunk extends ChunkAccess {
|
||||
});
|
||||
throw new ReportedException(crashreport);
|
||||
}
|
||||
+ */ // Paper - Perf: Optimise Chunk#getFluid
|
||||
}
|
||||
|
||||
// CraftBukkit start
|
||||
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 2d6daf76a56574c9727b404feb4f86347f04cbae..b606e33f8b64eaba28c008cc353d88aa45549e31 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
|
||||
@@ -43,7 +43,7 @@ public class LevelChunkSection {
|
||||
}
|
||||
|
||||
public FluidState getFluidState(int x, int y, int z) {
|
||||
- return ((BlockState) this.states.get(x, y, z)).getFluidState();
|
||||
+ return this.states.get(x, y, z).getFluidState(); // Paper - Perf: Optimise Chunk#getFluid; diff on change - we expect this to be effectively just getType(x, y, z).getFluid(). If this changes we need to check other patches that use IBlockData#getFluid.
|
||||
}
|
||||
|
||||
public void acquire() {
|
|
@ -1,19 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Wed, 2 Dec 2020 20:17:54 -0800
|
||||
Subject: [PATCH] Set spigots verbose world setting to false by def
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java
|
||||
index 81c76360e8c7389bafd61f38e6782668e8c65d27..2a787b641fec29427963ac2bdc14df60f32af2bc 100644
|
||||
--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java
|
||||
+++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java
|
||||
@@ -20,7 +20,7 @@ public class SpigotWorldConfig
|
||||
|
||||
public void init()
|
||||
{
|
||||
- this.verbose = this.getBoolean( "verbose", true );
|
||||
+ this.verbose = this.getBoolean( "verbose", false ); // Paper
|
||||
|
||||
this.log( "-------- World Settings For [" + this.worldName + "] --------" );
|
||||
SpigotConfig.readConfig( SpigotWorldConfig.class, this );
|
|
@ -1,206 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Sun, 5 Apr 2020 22:23:14 -0500
|
||||
Subject: [PATCH] Add tick times API and /mspt command
|
||||
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/command/MSPTCommand.java b/src/main/java/io/papermc/paper/command/MSPTCommand.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..8b5293b0c696ef21d0101493ffa41b60bf0bc86b
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/command/MSPTCommand.java
|
||||
@@ -0,0 +1,102 @@
|
||||
+package io.papermc.paper.command;
|
||||
+
|
||||
+import net.kyori.adventure.text.Component;
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
+import org.bukkit.Location;
|
||||
+import org.bukkit.command.Command;
|
||||
+import org.bukkit.command.CommandSender;
|
||||
+
|
||||
+import java.text.DecimalFormat;
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.Arrays;
|
||||
+import java.util.Collections;
|
||||
+import java.util.List;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+import static net.kyori.adventure.text.Component.text;
|
||||
+import static net.kyori.adventure.text.format.NamedTextColor.GOLD;
|
||||
+import static net.kyori.adventure.text.format.NamedTextColor.GRAY;
|
||||
+import static net.kyori.adventure.text.format.NamedTextColor.GREEN;
|
||||
+import static net.kyori.adventure.text.format.NamedTextColor.RED;
|
||||
+import static net.kyori.adventure.text.format.NamedTextColor.YELLOW;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public final class MSPTCommand extends Command {
|
||||
+ private static final DecimalFormat DF = new DecimalFormat("########0.0");
|
||||
+ private static final Component SLASH = text("/");
|
||||
+
|
||||
+ public MSPTCommand(final String name) {
|
||||
+ super(name);
|
||||
+ this.description = "View server tick times";
|
||||
+ this.usageMessage = "/mspt";
|
||||
+ this.setPermission("bukkit.command.mspt");
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public List<String> tabComplete(CommandSender sender, String alias, String[] args, Location location) throws IllegalArgumentException {
|
||||
+ return Collections.emptyList();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean execute(CommandSender sender, String commandLabel, String[] args) {
|
||||
+ if (!testPermission(sender)) return true;
|
||||
+
|
||||
+ MinecraftServer server = MinecraftServer.getServer();
|
||||
+
|
||||
+ List<Component> times = new ArrayList<>();
|
||||
+ times.addAll(eval(server.tickTimes5s.getTimes()));
|
||||
+ times.addAll(eval(server.tickTimes10s.getTimes()));
|
||||
+ times.addAll(eval(server.tickTimes60s.getTimes()));
|
||||
+
|
||||
+ sender.sendMessage(text().content("Server tick times ").color(GOLD)
|
||||
+ .append(text().color(YELLOW)
|
||||
+ .append(
|
||||
+ text("("),
|
||||
+ text("avg", GRAY),
|
||||
+ text("/"),
|
||||
+ text("min", GRAY),
|
||||
+ text("/"),
|
||||
+ text("max", GRAY),
|
||||
+ text(")")
|
||||
+ )
|
||||
+ ).append(
|
||||
+ text(" from last 5s"),
|
||||
+ text(",", GRAY),
|
||||
+ text(" 10s"),
|
||||
+ text(",", GRAY),
|
||||
+ text(" 1m"),
|
||||
+ text(":", YELLOW)
|
||||
+ )
|
||||
+ );
|
||||
+ sender.sendMessage(text().content("◴ ").color(GOLD)
|
||||
+ .append(text().color(GRAY)
|
||||
+ .append(
|
||||
+ times.get(0), SLASH, times.get(1), SLASH, times.get(2), text(", ", YELLOW),
|
||||
+ times.get(3), SLASH, times.get(4), SLASH, times.get(5), text(", ", YELLOW),
|
||||
+ times.get(6), SLASH, times.get(7), SLASH, times.get(8)
|
||||
+ )
|
||||
+ )
|
||||
+ );
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ private static List<Component> eval(long[] times) {
|
||||
+ long min = Integer.MAX_VALUE;
|
||||
+ long max = 0L;
|
||||
+ long total = 0L;
|
||||
+ for (long value : times) {
|
||||
+ if (value > 0L && value < min) min = value;
|
||||
+ if (value > max) max = value;
|
||||
+ total += value;
|
||||
+ }
|
||||
+ double avgD = ((double) total / (double) times.length) * 1.0E-6D;
|
||||
+ double minD = ((double) min) * 1.0E-6D;
|
||||
+ double maxD = ((double) max) * 1.0E-6D;
|
||||
+ return Arrays.asList(getColor(avgD), getColor(minD), getColor(maxD));
|
||||
+ }
|
||||
+
|
||||
+ private static Component getColor(double avg) {
|
||||
+ return text(DF.format(avg), avg >= 50 ? RED : avg >= 40 ? YELLOW : GREEN);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/command/PaperCommands.java b/src/main/java/io/papermc/paper/command/PaperCommands.java
|
||||
index 72f2e81b9905a0d57ed8e2a88578f62d5235c456..7b58b2d6297800c2dcdbf7539e5ab8e7703f39f1 100644
|
||||
--- a/src/main/java/io/papermc/paper/command/PaperCommands.java
|
||||
+++ b/src/main/java/io/papermc/paper/command/PaperCommands.java
|
||||
@@ -18,6 +18,7 @@ public final class PaperCommands {
|
||||
static {
|
||||
COMMANDS.put("paper", new PaperCommand("paper"));
|
||||
COMMANDS.put("callback", new CallbackCommand("callback"));
|
||||
+ COMMANDS.put("mspt", new MSPTCommand("mspt"));
|
||||
}
|
||||
|
||||
public static void registerCommands(final MinecraftServer server) {
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 6342b7a3c4ccad528f026384da64e973e630f030..746eeb22127d8633f1eeef1bb9c20edb7fd23e5a 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -252,6 +252,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
private int playerIdleTimeout;
|
||||
private final long[] tickTimesNanos;
|
||||
private long aggregatedTickTimesNanos;
|
||||
+ // Paper start - Add tick times API and /mspt command
|
||||
+ public final TickTimes tickTimes5s = new TickTimes(100);
|
||||
+ public final TickTimes tickTimes10s = new TickTimes(200);
|
||||
+ public final TickTimes tickTimes60s = new TickTimes(1200);
|
||||
+ // Paper end - Add tick times API and /mspt command
|
||||
@Nullable
|
||||
private KeyPair keyPair;
|
||||
@Nullable
|
||||
@@ -1402,6 +1407,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
this.smoothedTickTimeMillis = this.smoothedTickTimeMillis * 0.8F + (float) j / (float) TimeUtil.NANOSECONDS_PER_MILLISECOND * 0.19999999F;
|
||||
long l = Util.getNanos();
|
||||
|
||||
+ // Paper start - Add tick times API and /mspt command
|
||||
+ tickTimes5s.add(this.tickCount, j);
|
||||
+ tickTimes10s.add(this.tickCount, j);
|
||||
+ tickTimes60s.add(this.tickCount, j);
|
||||
+ // Paper end - Add tick times API and /mspt command
|
||||
this.logTickTime(l - i);
|
||||
this.profiler.pop();
|
||||
org.spigotmc.WatchdogThread.tick(); // Spigot
|
||||
@@ -2669,4 +2679,30 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
public static record ServerResourcePackInfo(UUID id, String url, String hash, boolean isRequired, @Nullable Component prompt) {
|
||||
|
||||
}
|
||||
+
|
||||
+ // Paper start - Add tick times API and /mspt command
|
||||
+ public static class TickTimes {
|
||||
+ private final long[] times;
|
||||
+
|
||||
+ public TickTimes(int length) {
|
||||
+ times = new long[length];
|
||||
+ }
|
||||
+
|
||||
+ void add(int index, long time) {
|
||||
+ times[index % times.length] = time;
|
||||
+ }
|
||||
+
|
||||
+ public long[] getTimes() {
|
||||
+ return times.clone();
|
||||
+ }
|
||||
+
|
||||
+ public double getAverage() {
|
||||
+ long total = 0L;
|
||||
+ for (long value : times) {
|
||||
+ total += value;
|
||||
+ }
|
||||
+ return ((double) total / (double) times.length) * 1.0E-6D;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Add tick times API and /mspt command
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index fd038c105d12c76c9e2645ad146e77b4a9cc1079..58cf5568b97e907d840099198f3c62b9d780bd0c 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -2629,6 +2629,16 @@ public final class CraftServer implements Server {
|
||||
return CraftMagicNumbers.INSTANCE;
|
||||
}
|
||||
|
||||
+ @Override
|
||||
+ public long[] getTickTimes() {
|
||||
+ return this.getServer().tickTimes5s.getTimes();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public double getAverageTickTime() {
|
||||
+ return this.getServer().tickTimes5s.getAverage();
|
||||
+ }
|
||||
+
|
||||
// Spigot start
|
||||
private final org.bukkit.Server.Spigot spigot = new org.bukkit.Server.Spigot()
|
||||
{
|
|
@ -1,22 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: JRoy <joshroy126@gmail.com>
|
||||
Date: Fri, 10 Apr 2020 21:24:12 -0400
|
||||
Subject: [PATCH] Expose MinecraftServer#isRunning
|
||||
|
||||
This allows for plugins to detect if the server is actually turning off in onDisable rather than just plugins reloading.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index 58cf5568b97e907d840099198f3c62b9d780bd0c..ae424a5cbf8868aea9e11ffd565665c50aeb780e 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -2876,5 +2876,10 @@ public final class CraftServer implements Server {
|
||||
public int getCurrentTick() {
|
||||
return net.minecraft.server.MinecraftServer.currentTick;
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isStopping() {
|
||||
+ return net.minecraft.server.MinecraftServer.getServer().hasStopped();
|
||||
+ }
|
||||
// Paper end
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Mariell Hoversholm <proximyst@proximyst.com>
|
||||
Date: Thu, 30 Apr 2020 16:56:54 +0200
|
||||
Subject: [PATCH] Add Raw Byte ItemStack Serialization
|
||||
|
||||
Serializes using NBT which is safer for server data migrations than bukkits format.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
index 82d862432d061f8f1809647d9eecfff38a6311d4..7579e076793ba90e405b3ac0db600374ee8fdcb3 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
@@ -478,6 +478,53 @@ public final class CraftMagicNumbers implements UnsafeValues {
|
||||
public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() {
|
||||
return new com.destroystokyo.paper.PaperVersionFetcher();
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public byte[] serializeItem(ItemStack item) {
|
||||
+ Preconditions.checkNotNull(item, "null cannot be serialized");
|
||||
+ Preconditions.checkArgument(item.getType() != Material.AIR, "air cannot be serialized");
|
||||
+
|
||||
+ return serializeNbtToBytes((item instanceof CraftItemStack ? ((CraftItemStack) item).handle : CraftItemStack.asNMSCopy(item)).save(new CompoundTag()));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public ItemStack deserializeItem(byte[] data) {
|
||||
+ Preconditions.checkNotNull(data, "null cannot be deserialized");
|
||||
+ Preconditions.checkArgument(data.length > 0, "cannot deserialize nothing");
|
||||
+
|
||||
+ CompoundTag compound = deserializeNbtFromBytes(data);
|
||||
+ final int dataVersion = compound.getInt("DataVersion");
|
||||
+ compound = (CompoundTag) MinecraftServer.getServer().fixerUpper.update(References.ITEM_STACK, new Dynamic<>(NbtOps.INSTANCE, compound), dataVersion, this.getDataVersion()).getValue();
|
||||
+ return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.of(compound));
|
||||
+ }
|
||||
+
|
||||
+ private byte[] serializeNbtToBytes(CompoundTag compound) {
|
||||
+ compound.putInt("DataVersion", getDataVersion());
|
||||
+ java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream();
|
||||
+ try {
|
||||
+ net.minecraft.nbt.NbtIo.writeCompressed(
|
||||
+ compound,
|
||||
+ outputStream
|
||||
+ );
|
||||
+ } catch (IOException ex) {
|
||||
+ throw new RuntimeException(ex);
|
||||
+ }
|
||||
+ return outputStream.toByteArray();
|
||||
+ }
|
||||
+
|
||||
+ private CompoundTag deserializeNbtFromBytes(byte[] data) {
|
||||
+ CompoundTag compound;
|
||||
+ try {
|
||||
+ compound = net.minecraft.nbt.NbtIo.readCompressed(
|
||||
+ new java.io.ByteArrayInputStream(data), net.minecraft.nbt.NbtAccounter.unlimitedHeap()
|
||||
+ );
|
||||
+ } catch (IOException ex) {
|
||||
+ throw new RuntimeException(ex);
|
||||
+ }
|
||||
+ int dataVersion = compound.getInt("DataVersion");
|
||||
+ Preconditions.checkArgument(dataVersion <= getDataVersion(), "Newer version! Server downgrades are not supported!");
|
||||
+ return compound;
|
||||
+ }
|
||||
// Paper end
|
||||
|
||||
/**
|
|
@ -1,96 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Phoenix616 <mail@moep.tv>
|
||||
Date: Sat, 1 Feb 2020 16:50:39 +0100
|
||||
Subject: [PATCH] Pillager patrol spawn settings and per player options
|
||||
|
||||
This adds config options for defining the spawn chance, spawn delay and
|
||||
spawn start day as well as toggles for handling the spawn delay and
|
||||
start day per player. (Based on the time played statistic)
|
||||
When not per player it will use the Vanilla mechanic of one delay per
|
||||
world and the world age for the start day.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 79a0accd8230c76d792ed3f7558e8b3ea6d2f6d1..9f0d42256d1b41242bd08939f88583e2d337ede3 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -249,6 +249,7 @@ public class ServerPlayer extends Player {
|
||||
public boolean wonGame;
|
||||
private int containerUpdateDelay; // Paper - Configurable container update tick rate
|
||||
public long loginTime; // Paper - Replace OfflinePlayer#getLastPlayed
|
||||
+ public int patrolSpawnDelay; // Paper - Pillager patrol spawn settings and per player options
|
||||
// Paper start - cancellable death event
|
||||
public boolean queueHealthUpdatePacket;
|
||||
public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket;
|
||||
diff --git a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java
|
||||
index c7aea059de151cf8ae6e660785e176586bc23ff3..1c4dafdfb3898b5efe06d66792b1b0841ec5724d 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java
|
||||
@@ -25,7 +25,7 @@ public class PatrolSpawner implements CustomSpawner {
|
||||
|
||||
@Override
|
||||
public int tick(ServerLevel world, boolean spawnMonsters, boolean spawnAnimals) {
|
||||
- if (world.paperConfig().entities.behavior.pillagerPatrols.disable) return 0; // Paper - Add option to disable pillager patrols
|
||||
+ if (world.paperConfig().entities.behavior.pillagerPatrols.disable || world.paperConfig().entities.behavior.pillagerPatrols.spawnChance == 0) return 0; // Paper - Add option to disable pillager patrols & Pillager patrol spawn settings and per player options
|
||||
if (!spawnMonsters) {
|
||||
return 0;
|
||||
} else if (!world.getGameRules().getBoolean(GameRules.RULE_DO_PATROL_SPAWNING)) {
|
||||
@@ -33,23 +33,51 @@ public class PatrolSpawner implements CustomSpawner {
|
||||
} else {
|
||||
RandomSource randomsource = world.random;
|
||||
|
||||
- --this.nextTick;
|
||||
- if (this.nextTick > 0) {
|
||||
+ // Paper start - Pillager patrol spawn settings and per player options
|
||||
+ // Random player selection moved up for per player spawning and configuration
|
||||
+ int j = world.players().size();
|
||||
+ if (j < 1) {
|
||||
return 0;
|
||||
+ }
|
||||
+
|
||||
+ net.minecraft.server.level.ServerPlayer entityhuman = world.players().get(randomsource.nextInt(j));
|
||||
+ if (entityhuman.isSpectator()) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ int patrolSpawnDelay;
|
||||
+ if (world.paperConfig().entities.behavior.pillagerPatrols.spawnDelay.perPlayer) {
|
||||
+ --entityhuman.patrolSpawnDelay;
|
||||
+ patrolSpawnDelay = entityhuman.patrolSpawnDelay;
|
||||
} else {
|
||||
- this.nextTick += 12000 + randomsource.nextInt(1200);
|
||||
- long i = world.getDayTime() / 24000L;
|
||||
+ this.nextTick--;
|
||||
+ patrolSpawnDelay = this.nextTick;
|
||||
+ }
|
||||
+
|
||||
+ if (patrolSpawnDelay > 0) {
|
||||
+ return 0;
|
||||
+ } else {
|
||||
+ long days;
|
||||
+ if (world.paperConfig().entities.behavior.pillagerPatrols.start.perPlayer) {
|
||||
+ days = entityhuman.getStats().getValue(net.minecraft.stats.Stats.CUSTOM.get(net.minecraft.stats.Stats.PLAY_TIME)) / 24000L; // PLAY_ONE_MINUTE is actually counting in ticks, a misnomer by Mojang
|
||||
+ } else {
|
||||
+ days = world.getDayTime() / 24000L;
|
||||
+ }
|
||||
+ if (world.paperConfig().entities.behavior.pillagerPatrols.spawnDelay.perPlayer) {
|
||||
+ entityhuman.patrolSpawnDelay += world.paperConfig().entities.behavior.pillagerPatrols.spawnDelay.ticks + randomsource.nextInt(1200);
|
||||
+ } else {
|
||||
+ this.nextTick += world.paperConfig().entities.behavior.pillagerPatrols.spawnDelay.ticks + randomsource.nextInt(1200);
|
||||
+ }
|
||||
|
||||
- if (i >= 5L && world.isDay()) {
|
||||
- if (randomsource.nextInt(5) != 0) {
|
||||
+ if (days >= world.paperConfig().entities.behavior.pillagerPatrols.start.day && world.isDay()) {
|
||||
+ if (randomsource.nextDouble() >= world.paperConfig().entities.behavior.pillagerPatrols.spawnChance) {
|
||||
+ // Paper end - Pillager patrol spawn settings and per player options
|
||||
return 0;
|
||||
} else {
|
||||
- int j = world.players().size();
|
||||
|
||||
if (j < 1) {
|
||||
return 0;
|
||||
} else {
|
||||
- Player entityhuman = (Player) world.players().get(randomsource.nextInt(j));
|
||||
|
||||
if (entityhuman.isSpectator()) {
|
||||
return 0;
|
|
@ -1,44 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 31 Mar 2020 03:50:42 -0400
|
||||
Subject: [PATCH] Remote Connections shouldn't hold up shutdown
|
||||
|
||||
Bugs in the connection logic appears to leave stale connections even, preventing shutdown
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
index 78775feb965d6eb98a1ff655ae44b9f0399ef9aa..28fe088d97bd5fbfcc29dcc7d2a657d54578b2be 100644
|
||||
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
@@ -390,11 +390,11 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||
}
|
||||
|
||||
if (this.rconThread != null) {
|
||||
- this.rconThread.stop();
|
||||
+ this.rconThread.stopNonBlocking(); // Paper - don't wait for remote connections
|
||||
}
|
||||
|
||||
if (this.queryThreadGs4 != null) {
|
||||
- this.queryThreadGs4.stop();
|
||||
+ // this.remoteStatusListener.stop(); // Paper - don't wait for remote connections
|
||||
}
|
||||
|
||||
System.exit(0); // CraftBukkit
|
||||
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 594fbb033b63b8c9fb8752b1fcc78f8e9f7a2a83..c12d7db2b048a327c0e8f398848cd3a9bce0ebce 100644
|
||||
--- a/src/main/java/net/minecraft/server/rcon/thread/RconThread.java
|
||||
+++ b/src/main/java/net/minecraft/server/rcon/thread/RconThread.java
|
||||
@@ -104,6 +104,14 @@ public class RconThread extends GenericThread {
|
||||
|
||||
this.clients.clear();
|
||||
}
|
||||
+ // Paper start - don't wait for remote connections
|
||||
+ public void stopNonBlocking() {
|
||||
+ this.running = false;
|
||||
+ for (RconClient client : this.clients) {
|
||||
+ client.running = false;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - don't wait for remote connections
|
||||
|
||||
private void closeSocket(ServerSocket socket) {
|
||||
LOGGER.debug("closeSocket: {}", socket);
|
|
@ -1,58 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: chickeneer <emcchickeneer@gmail.com>
|
||||
Date: Tue, 17 Mar 2020 14:18:50 -0500
|
||||
Subject: [PATCH] Do not allow bees to load chunks for beehives
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java
|
||||
index 06e990b6957a4ef48c8778bbd175d3afddf52ca3..07ecc038a1000581335b8d18c094298f2f3b100f 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/Bee.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java
|
||||
@@ -420,6 +420,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
|
||||
if (this.hivePos == null) {
|
||||
return false;
|
||||
} else {
|
||||
+ if (!this.level().isLoadedAndInBounds(this.hivePos)) return false; // Paper - Do not allow bees to load chunks for beehives
|
||||
BlockEntity tileentity = this.level().getBlockEntity(this.hivePos);
|
||||
|
||||
return tileentity instanceof BeehiveBlockEntity && ((BeehiveBlockEntity) tileentity).isFireNearby();
|
||||
@@ -453,6 +454,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
|
||||
}
|
||||
|
||||
private boolean doesHiveHaveSpace(BlockPos pos) {
|
||||
+ if (!this.level().isLoadedAndInBounds(pos)) return false; // Paper - Do not allow bees to load chunks for beehives
|
||||
BlockEntity tileentity = this.level().getBlockEntity(pos);
|
||||
|
||||
return tileentity instanceof BeehiveBlockEntity ? !((BeehiveBlockEntity) tileentity).isFull() : false;
|
||||
@@ -929,6 +931,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
|
||||
@Override
|
||||
public boolean canBeeUse() {
|
||||
if (Bee.this.hasHive() && Bee.this.wantsToEnterHive() && Bee.this.hivePos.closerToCenterThan(Bee.this.position(), 2.0D)) {
|
||||
+ if (!Bee.this.level().isLoadedAndInBounds(Bee.this.hivePos)) return false; // Paper - Do not allow bees to load chunks for beehives
|
||||
BlockEntity tileentity = Bee.this.level().getBlockEntity(Bee.this.hivePos);
|
||||
|
||||
if (tileentity instanceof BeehiveBlockEntity) {
|
||||
@@ -952,6 +955,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
+ if (!Bee.this.level().isLoadedAndInBounds(Bee.this.hivePos)) return; // Paper - Do not allow bees to load chunks for beehives
|
||||
BlockEntity tileentity = Bee.this.level().getBlockEntity(Bee.this.hivePos);
|
||||
|
||||
if (tileentity instanceof BeehiveBlockEntity) {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/Vex.java b/src/main/java/net/minecraft/world/entity/monster/Vex.java
|
||||
index 30ea3f64234fd1fda8dada3c7fb12be0730322a8..f443006c1e32feee97b32312814e2447a50c45e2 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Vex.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Vex.java
|
||||
@@ -377,7 +377,10 @@ public class Vex extends Monster implements TraceableEntity {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
BlockPos blockposition1 = blockposition.offset(Vex.this.random.nextInt(15) - 7, Vex.this.random.nextInt(11) - 5, Vex.this.random.nextInt(15) - 7);
|
||||
|
||||
- if (Vex.this.level().isEmptyBlock(blockposition1)) {
|
||||
+ // Paper start - Don't load chunks
|
||||
+ final net.minecraft.world.level.block.state.BlockState blockState = Vex.this.level().getBlockStateIfLoaded(blockposition1);
|
||||
+ if (blockState != null && blockState.isAir()) {
|
||||
+ // Paper end - Don't load chunks
|
||||
Vex.this.moveControl.setWantedPosition((double) blockposition1.getX() + 0.5D, (double) blockposition1.getY() + 0.5D, (double) blockposition1.getZ() + 0.5D, 0.25D);
|
||||
if (Vex.this.getTarget() == null) {
|
||||
Vex.this.getLookControl().setLookAt((double) blockposition1.getX() + 0.5D, (double) blockposition1.getY() + 0.5D, (double) blockposition1.getZ() + 0.5D, 180.0F, 20.0F);
|
|
@ -1,47 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Thu, 2 Apr 2020 01:42:39 -0400
|
||||
Subject: [PATCH] Prevent Double PlayerChunkMap adds crashing server
|
||||
|
||||
Suspected case would be around the technique used in .stopRiding
|
||||
Stack will identify any causer of this and warn instead of crashing.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index c69f1d970e1014f1be601e34bdd8b5fd749da339..2fba58fd5c9b17512eadacb899c59a04df5d415f 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -1452,6 +1452,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
|
||||
public void addEntity(Entity entity) {
|
||||
org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot
|
||||
+ // Paper start - ignore and warn about illegal addEntity calls instead of crashing server
|
||||
+ if (!entity.valid || entity.level() != this.level || this.entityMap.containsKey(entity.getId())) {
|
||||
+ LOGGER.error("Illegal ChunkMap::addEntity for world " + this.level.getWorld().getName()
|
||||
+ + ": " + entity + (this.entityMap.containsKey(entity.getId()) ? " ALREADY CONTAINED (This would have crashed your server)" : ""), new Throwable());
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end - ignore and warn about illegal addEntity calls instead of crashing server
|
||||
if (!(entity instanceof EnderDragonPart)) {
|
||||
EntityType<?> entitytypes = entity.getType();
|
||||
int i = entitytypes.clientTrackingRange() * 16;
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 4d1d84383c11ef1e83edb50be62173533b7a641b..9af1877321356348ad96b92ae8c5f4811bef50ac 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -2224,7 +2224,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
|
||||
public void onTrackingStart(Entity entity) {
|
||||
org.spigotmc.AsyncCatcher.catchOp("entity register"); // Spigot
|
||||
- ServerLevel.this.getChunkSource().addEntity(entity);
|
||||
+ // ServerLevel.this.getChunkSource().addEntity(entity); // Paper - ignore and warn about illegal addEntity calls instead of crashing server; moved down below valid=true
|
||||
if (entity instanceof ServerPlayer) {
|
||||
ServerPlayer entityplayer = (ServerPlayer) entity;
|
||||
|
||||
@@ -2259,6 +2259,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
entity.updateDynamicGameEventListener(DynamicGameEventListener::add);
|
||||
entity.inWorld = true; // CraftBukkit - Mark entity as in world
|
||||
entity.valid = true; // CraftBukkit
|
||||
+ ServerLevel.this.getChunkSource().addEntity(entity); // Paper - ignore and warn about illegal addEntity calls instead of crashing server
|
||||
// Paper start - Entity origin API
|
||||
if (entity.getOriginVector() == null) {
|
||||
entity.setOrigin(entity.getBukkitEntity().getLocation());
|
|
@ -1,21 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Thu, 2 Apr 2020 17:16:48 -0400
|
||||
Subject: [PATCH] Don't tick dead players
|
||||
|
||||
Causes sync chunk loads and who knows what all else.
|
||||
This is safe because Spectators are skipped in unloaded chunks too in vanilla.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 9f0d42256d1b41242bd08939f88583e2d337ede3..ca75d22e90fd879d464733813939f877ec875905 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -684,7 +684,7 @@ public class ServerPlayer extends Player {
|
||||
|
||||
public void doTick() {
|
||||
try {
|
||||
- if (!this.isSpectator() || !this.touchingUnloadedChunk()) {
|
||||
+ if (valid && !this.isSpectator() || !this.touchingUnloadedChunk()) { // Paper - don't tick dead players that are not in the world currently (pending respawn)
|
||||
super.tick();
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Thu, 2 Apr 2020 19:31:16 -0400
|
||||
Subject: [PATCH] Dead Player's shouldn't be able to move
|
||||
|
||||
This fixes a lot of game state issues where packets were delayed for processing
|
||||
due to 1.15's new queue but processed while dead.
|
||||
|
||||
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 3c3c953f05c18279d3245fe6bc8afef83cd62cd1..603e003fbd39870a0e249151885b3b8f3e120afe 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
@@ -1153,7 +1153,7 @@ public abstract class Player extends LivingEntity {
|
||||
|
||||
@Override
|
||||
protected boolean isImmobile() {
|
||||
- return super.isImmobile() || this.isSleeping();
|
||||
+ return super.isImmobile() || this.isSleeping() || this.isRemoved() || !valid; // Paper - player's who are dead or not in a world shouldn't move...
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,48 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Thu, 9 Apr 2020 21:20:33 -0400
|
||||
Subject: [PATCH] Don't move existing players to world spawn
|
||||
|
||||
This can cause a nasty server lag the spawn chunks are not kept loaded
|
||||
or they aren't finished loading yet, or if the world spawn radius is
|
||||
larger than the keep loaded range.
|
||||
|
||||
By skipping this, we avoid potential for a large spike on server start.
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.server.level.ServerPlayer fudgeSpawnLocation(Lnet/minecraft/server/level/ServerLevel;)V
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index ca75d22e90fd879d464733813939f877ec875905..04e54d2214d0ae0202490aceab54b8b10ef38229 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -337,7 +337,7 @@ public class ServerPlayer extends Player {
|
||||
this.stats = server.getPlayerList().getPlayerStats(this);
|
||||
this.advancements = server.getPlayerList().getPlayerAdvancements(this);
|
||||
this.setMaxUpStep(1.0F);
|
||||
- this.fudgeSpawnLocation(world);
|
||||
+ // this.fudgeSpawnLocation(world); // Paper - Don't move existing players to world spawn
|
||||
this.updateOptions(clientOptions);
|
||||
|
||||
this.cachedSingleHashSet = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper
|
||||
@@ -571,7 +571,7 @@ public class ServerPlayer extends Player {
|
||||
position = Vec3.atCenterOf(world.getSharedSpawnPos());
|
||||
}
|
||||
this.setLevel(world);
|
||||
- this.setPos(position);
|
||||
+ this.setPosRaw(position.x(), position.y(), position.z()); // Paper - don't register to chunks yet
|
||||
}
|
||||
this.gameMode.setLevel((ServerLevel) world);
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
index 6bd83549e2ff84b1bc993ef2be79a336ced28f67..8f23597eee06e721a25f7be3a5a65dff6a59ee55 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
@@ -227,6 +227,7 @@ public abstract class PlayerList {
|
||||
// Paper start - Entity#getEntitySpawnReason
|
||||
if (nbttagcompound == null) {
|
||||
player.spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT; // set Player SpawnReason to DEFAULT on first login
|
||||
+ player.fudgeSpawnLocation(worldserver1); // Paper - Don't move existing players to world spawn
|
||||
}
|
||||
// Paper end - Entity#getEntitySpawnReason
|
||||
player.setServerLevel(worldserver1);
|
|
@ -1,43 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Thu, 3 Mar 2016 02:02:07 -0600
|
||||
Subject: [PATCH] Optimize Pathfinding
|
||||
|
||||
Prevents pathfinding from spamming failures for things such as
|
||||
arrow attacks.
|
||||
|
||||
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 25a9f1fd69fbafab5129740e26e9741e35885ce0..e3a7eaf31ab19cc9f23a0c87649b74bb42976cb4 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
|
||||
@@ -192,9 +192,29 @@ public abstract class PathNavigation {
|
||||
return this.moveTo(this.createPath(x, y, z, 1), speed);
|
||||
}
|
||||
|
||||
+ // Paper start - Perf: Optimise pathfinding
|
||||
+ private int lastFailure = 0;
|
||||
+ private int pathfindFailures = 0;
|
||||
+ // Paper end - Perf: Optimise pathfinding
|
||||
+
|
||||
public boolean moveTo(Entity entity, double speed) {
|
||||
+ // Paper start - Perf: Optimise pathfinding
|
||||
+ if (this.pathfindFailures > 10 && this.path == null && net.minecraft.server.MinecraftServer.currentTick < this.lastFailure + 40) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Paper end - Perf: Optimise pathfinding
|
||||
Path path = this.createPath(entity, 1);
|
||||
- return path != null && this.moveTo(path, speed);
|
||||
+ // Paper start - Perf: Optimise pathfinding
|
||||
+ if (path != null && this.moveTo(path, speed)) {
|
||||
+ this.lastFailure = 0;
|
||||
+ this.pathfindFailures = 0;
|
||||
+ return true;
|
||||
+ } else {
|
||||
+ this.pathfindFailures++;
|
||||
+ this.lastFailure = net.minecraft.server.MinecraftServer.currentTick;
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Paper end - Perf: Optimise pathfinding
|
||||
}
|
||||
|
||||
public boolean moveTo(@Nullable Path path, double speed) {
|
|
@ -1,48 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Mon, 6 Apr 2020 18:35:09 -0700
|
||||
Subject: [PATCH] Reduce Either Optional allocation
|
||||
|
||||
In order to get chunk values, we shouldn't need to create
|
||||
an optional each time.
|
||||
|
||||
diff --git a/src/main/java/com/mojang/datafixers/util/Either.java b/src/main/java/com/mojang/datafixers/util/Either.java
|
||||
index de524d485fada3c3cca8c2fe6c63db0e0b33dad8..a51e8e3eafff17f4f2ff790bf96a2f0e89abca2a 100644
|
||||
--- a/src/main/java/com/mojang/datafixers/util/Either.java
|
||||
+++ b/src/main/java/com/mojang/datafixers/util/Either.java
|
||||
@@ -22,7 +22,7 @@ public abstract class Either<L, R> implements App<Either.Mu<R>, L> {
|
||||
}
|
||||
|
||||
private static final class Left<L, R> extends Either<L, R> {
|
||||
- private final L value;
|
||||
+ private final L value; private Optional<L> valueOptional; // Paper - Perf: Reduce Either Optional allocation
|
||||
|
||||
public Left(final L value) {
|
||||
this.value = value;
|
||||
@@ -51,7 +51,7 @@ public abstract class Either<L, R> implements App<Either.Mu<R>, L> {
|
||||
|
||||
@Override
|
||||
public Optional<L> left() {
|
||||
- return Optional.of(value);
|
||||
+ return this.valueOptional == null ? this.valueOptional = Optional.of(this.value) : this.valueOptional; // Paper - Perf: Reduce Either Optional allocation
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -83,7 +83,7 @@ public abstract class Either<L, R> implements App<Either.Mu<R>, L> {
|
||||
}
|
||||
|
||||
private static final class Right<L, R> extends Either<L, R> {
|
||||
- private final R value;
|
||||
+ private final R value; private Optional<R> valueOptional; // Paper - Perf: Reduce Either Optional allocation
|
||||
|
||||
public Right(final R value) {
|
||||
this.value = value;
|
||||
@@ -117,7 +117,7 @@ public abstract class Either<L, R> implements App<Either.Mu<R>, L> {
|
||||
|
||||
@Override
|
||||
public Optional<R> right() {
|
||||
- return Optional.of(value);
|
||||
+ return this.valueOptional == null ? this.valueOptional = Optional.of(this.value) : this.valueOptional; // Paper - Perf: Reduce Either Optional allocation
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,50 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Mon, 6 Apr 2020 17:39:25 -0700
|
||||
Subject: [PATCH] Reduce memory footprint of CompoundTag
|
||||
|
||||
Fastutil maps are going to have a lower memory footprint - which
|
||||
is important because we clone chunk data after reading it for safety.
|
||||
So, reduce the impact of the clone on GC.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/nbt/CompoundTag.java b/src/main/java/net/minecraft/nbt/CompoundTag.java
|
||||
index 1e2f58f2f95c558ce28706c405050c4c5701dd40..c7945686a4ee50d7a9d5f1173aa90e456f68b410 100644
|
||||
--- a/src/main/java/net/minecraft/nbt/CompoundTag.java
|
||||
+++ b/src/main/java/net/minecraft/nbt/CompoundTag.java
|
||||
@@ -49,7 +49,7 @@ public class CompoundTag implements Tag {
|
||||
|
||||
private static CompoundTag loadCompound(DataInput input, NbtAccounter tracker) throws IOException {
|
||||
tracker.accountBytes(48L);
|
||||
- Map<String, Tag> map = Maps.newHashMap();
|
||||
+ it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<String, Tag> map = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(8, 0.8f); // Paper - Reduce memory footprint of CompoundTag
|
||||
|
||||
byte b;
|
||||
while ((b = input.readByte()) != 0) {
|
||||
@@ -166,7 +166,7 @@ public class CompoundTag implements Tag {
|
||||
}
|
||||
|
||||
public CompoundTag() {
|
||||
- this(Maps.newHashMap());
|
||||
+ this(new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(8, 0.8f)); // Paper - Reduce memory footprint of CompoundTag
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -477,8 +477,16 @@ public class CompoundTag implements Tag {
|
||||
|
||||
@Override
|
||||
public CompoundTag copy() {
|
||||
- Map<String, Tag> map = Maps.newHashMap(Maps.transformValues(this.tags, Tag::copy));
|
||||
- return new CompoundTag(map);
|
||||
+ // Paper start - Reduce memory footprint of CompoundTag
|
||||
+ it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<String, Tag> ret = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(this.tags.size(), 0.8f);
|
||||
+ java.util.Iterator<java.util.Map.Entry<String, Tag>> iterator = (this.tags instanceof it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap) ? ((it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap)this.tags).object2ObjectEntrySet().fastIterator() : this.tags.entrySet().iterator();
|
||||
+ while (iterator.hasNext()) {
|
||||
+ Map.Entry<String, Tag> entry = iterator.next();
|
||||
+ ret.put(entry.getKey(), entry.getValue().copy());
|
||||
+ }
|
||||
+
|
||||
+ return new CompoundTag(ret);
|
||||
+ // Paper end - Reduce memory footprint of CompoundTag
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,50 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Mon, 13 Apr 2020 07:31:44 +0100
|
||||
Subject: [PATCH] Prevent opening inventories when frozen
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 04e54d2214d0ae0202490aceab54b8b10ef38229..3a856f28237246660665aef983e5e9fe2bac8c37 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -653,7 +653,7 @@ public class ServerPlayer extends Player {
|
||||
containerUpdateDelay = this.level().paperConfig().tickRates.containerUpdate;
|
||||
}
|
||||
// Paper end - Configurable container update tick rate
|
||||
- if (!this.level().isClientSide && !this.containerMenu.stillValid(this)) {
|
||||
+ if (!this.level().isClientSide && this.containerMenu != this.inventoryMenu && (this.isImmobile() || !this.containerMenu.stillValid(this))) { // Paper - Prevent opening inventories when frozen
|
||||
this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper - Inventory close reason
|
||||
this.containerMenu = this.inventoryMenu;
|
||||
}
|
||||
@@ -1508,7 +1508,7 @@ public class ServerPlayer extends Player {
|
||||
} else {
|
||||
// CraftBukkit start
|
||||
this.containerMenu = container;
|
||||
- this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), container.getTitle()));
|
||||
+ if (!this.isImmobile()) this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), container.getTitle())); // Paper - Prevent opening inventories when frozen
|
||||
// CraftBukkit end
|
||||
this.initMenu(container);
|
||||
return OptionalInt.of(this.containerCounter);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
|
||||
index 0886cb3367022c4ab7e4dbebafb70fc651bcb9aa..35f03bea2b1206b420ac46dfd77811fb485c5319 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
|
||||
@@ -328,7 +328,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
|
||||
if (adventure$title == null) adventure$title = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(container.getBukkitView().getTitle()); // Paper
|
||||
|
||||
//player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment
|
||||
- player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper
|
||||
+ if (!player.isImmobile()) player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - Prevent opening inventories when frozen
|
||||
player.containerMenu = container;
|
||||
player.initMenu(container);
|
||||
}
|
||||
@@ -402,7 +402,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
|
||||
net.kyori.adventure.text.Component adventure$title = inventory.title(); // Paper
|
||||
if (adventure$title == null) adventure$title = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(inventory.getTitle()); // Paper
|
||||
//player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment
|
||||
- player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper
|
||||
+ if (!player.isImmobile()) player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - Prevent opening inventories when frozen
|
||||
player.containerMenu = container;
|
||||
player.initMenu(container);
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Wed, 15 Apr 2020 17:56:07 -0700
|
||||
Subject: [PATCH] Don't run entity collision code if not needed
|
||||
|
||||
Will not run if:
|
||||
Max entity cramming is disabled and the max collisions per entity is less than or equal to 0.
|
||||
Entity#isPushable() returns false, meaning all entities will not be able to collide with this
|
||||
entity anyways.
|
||||
The entity's current team collision rule causes them to NEVER collide.
|
||||
|
||||
Co-authored-by: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index 2a417145d9fe4d029cf3738f3320c0bcd3e025a9..e8410acb2f4be966177a0ec62fc93b8fe2cc0af3 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -3419,10 +3419,24 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
if (this.level().isClientSide()) {
|
||||
this.level().getEntities(EntityTypeTest.forClass(net.minecraft.world.entity.player.Player.class), this.getBoundingBox(), EntitySelector.pushableBy(this)).forEach(this::doPush);
|
||||
} else {
|
||||
+ // Paper start - don't run getEntities if we're not going to use its result
|
||||
+ if (!this.isPushable()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ net.minecraft.world.scores.Team team = this.getTeam();
|
||||
+ if (team != null && team.getCollisionRule() == net.minecraft.world.scores.Team.CollisionRule.NEVER) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ int i = this.level().getGameRules().getInt(GameRules.RULE_MAX_ENTITY_CRAMMING);
|
||||
+ if (i <= 0 && this.level().paperConfig().collisions.maxEntityCollisions <= 0) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end - don't run getEntities if we're not going to use its result
|
||||
List<Entity> list = this.level().getEntities((Entity) this, this.getBoundingBox(), EntitySelector.pushableBy(this));
|
||||
|
||||
if (!list.isEmpty()) {
|
||||
- int i = this.level().getGameRules().getInt(GameRules.RULE_MAX_ENTITY_CRAMMING);
|
||||
+ // Paper - don't run getEntities if we're not going to use its result; moved up
|
||||
|
||||
if (i > 0 && list.size() > i - 1 && this.random.nextInt(4) == 0) {
|
||||
int j = 0;
|
|
@ -1,194 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MiniDigger <admin@benndorf.dev>
|
||||
Date: Mon, 20 Jan 2020 21:38:15 +0100
|
||||
Subject: [PATCH] Implement Player Client Options API
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.entity.player.Player DATA_PLAYER_MODE_CUSTOMISATION
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperSkinParts.java b/src/main/java/com/destroystokyo/paper/PaperSkinParts.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..b6f4400df3d8ec7e06a996de54f8cabba57885e1
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperSkinParts.java
|
||||
@@ -0,0 +1,74 @@
|
||||
+package com.destroystokyo.paper;
|
||||
+
|
||||
+import com.google.common.base.Objects;
|
||||
+
|
||||
+import java.util.StringJoiner;
|
||||
+
|
||||
+public class PaperSkinParts implements SkinParts {
|
||||
+
|
||||
+ private final int raw;
|
||||
+
|
||||
+ public PaperSkinParts(int raw) {
|
||||
+ this.raw = raw;
|
||||
+ }
|
||||
+
|
||||
+ public boolean hasCapeEnabled() {
|
||||
+ return (raw & 1) == 1;
|
||||
+ }
|
||||
+
|
||||
+ public boolean hasJacketEnabled() {
|
||||
+ return (raw >> 1 & 1) == 1;
|
||||
+ }
|
||||
+
|
||||
+ public boolean hasLeftSleeveEnabled() {
|
||||
+ return (raw >> 2 & 1) == 1;
|
||||
+ }
|
||||
+
|
||||
+ public boolean hasRightSleeveEnabled() {
|
||||
+ return (raw >> 3 & 1) == 1;
|
||||
+ }
|
||||
+
|
||||
+ public boolean hasLeftPantsEnabled() {
|
||||
+ return (raw >> 4 & 1) == 1;
|
||||
+ }
|
||||
+
|
||||
+ public boolean hasRightPantsEnabled() {
|
||||
+ return (raw >> 5 & 1) == 1;
|
||||
+ }
|
||||
+
|
||||
+ public boolean hasHatsEnabled() {
|
||||
+ return (raw >> 6 & 1) == 1;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getRaw() {
|
||||
+ return raw;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean equals(Object o) {
|
||||
+ if (this == o) return true;
|
||||
+ if (o == null || getClass() != o.getClass()) return false;
|
||||
+ PaperSkinParts that = (PaperSkinParts) o;
|
||||
+ return raw == that.raw;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int hashCode() {
|
||||
+ return Objects.hashCode(raw);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public String toString() {
|
||||
+ return new StringJoiner(", ", PaperSkinParts.class.getSimpleName() + "[", "]")
|
||||
+ .add("raw=" + raw)
|
||||
+ .add("cape=" + hasCapeEnabled())
|
||||
+ .add("jacket=" + hasJacketEnabled())
|
||||
+ .add("leftSleeve=" + hasLeftSleeveEnabled())
|
||||
+ .add("rightSleeve=" + hasRightSleeveEnabled())
|
||||
+ .add("leftPants=" + hasLeftPantsEnabled())
|
||||
+ .add("rightPants=" + hasRightPantsEnabled())
|
||||
+ .add("hats=" + hasHatsEnabled())
|
||||
+ .toString();
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 3a856f28237246660665aef983e5e9fe2bac8c37..3d7a938f72424a4f30f75563393a953cf9f11933 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -338,7 +338,7 @@ public class ServerPlayer extends Player {
|
||||
this.advancements = server.getPlayerList().getPlayerAdvancements(this);
|
||||
this.setMaxUpStep(1.0F);
|
||||
// this.fudgeSpawnLocation(world); // Paper - Don't move existing players to world spawn
|
||||
- this.updateOptions(clientOptions);
|
||||
+ this.updateOptionsNoEvents(clientOptions); // Paper - don't call options events on login
|
||||
|
||||
this.cachedSingleHashSet = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper
|
||||
|
||||
@@ -2004,7 +2004,23 @@ public class ServerPlayer extends Player {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start - Client option API
|
||||
+ private java.util.Map<com.destroystokyo.paper.ClientOption<?>, ?> getClientOptionMap(String locale, int viewDistance, com.destroystokyo.paper.ClientOption.ChatVisibility chatVisibility, boolean chatColors, com.destroystokyo.paper.PaperSkinParts skinParts, org.bukkit.inventory.MainHand mainHand, boolean allowsServerListing, boolean textFilteringEnabled) {
|
||||
+ java.util.Map<com.destroystokyo.paper.ClientOption<?>, Object> map = new java.util.HashMap<>();
|
||||
+ map.put(com.destroystokyo.paper.ClientOption.LOCALE, locale);
|
||||
+ map.put(com.destroystokyo.paper.ClientOption.VIEW_DISTANCE, viewDistance);
|
||||
+ map.put(com.destroystokyo.paper.ClientOption.CHAT_VISIBILITY, chatVisibility);
|
||||
+ map.put(com.destroystokyo.paper.ClientOption.CHAT_COLORS_ENABLED, chatColors);
|
||||
+ map.put(com.destroystokyo.paper.ClientOption.SKIN_PARTS, skinParts);
|
||||
+ map.put(com.destroystokyo.paper.ClientOption.MAIN_HAND, mainHand);
|
||||
+ map.put(com.destroystokyo.paper.ClientOption.ALLOW_SERVER_LISTINGS, allowsServerListing);
|
||||
+ map.put(com.destroystokyo.paper.ClientOption.TEXT_FILTERING_ENABLED, textFilteringEnabled);
|
||||
+ return map;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
public void updateOptions(ClientInformation clientOptions) {
|
||||
+ new com.destroystokyo.paper.event.player.PlayerClientOptionsChangeEvent(getBukkitEntity(), getClientOptionMap(clientOptions.language(), clientOptions.viewDistance(), com.destroystokyo.paper.ClientOption.ChatVisibility.valueOf(clientOptions.chatVisibility().name()), clientOptions.chatColors(), new com.destroystokyo.paper.PaperSkinParts(clientOptions.modelCustomisation()), clientOptions.mainHand() == HumanoidArm.LEFT ? MainHand.LEFT : MainHand.RIGHT, clientOptions.allowsListing(), clientOptions.textFilteringEnabled())).callEvent(); // Paper - settings event
|
||||
// CraftBukkit start
|
||||
if (this.getMainArm() != clientOptions.mainHand()) {
|
||||
PlayerChangedMainHandEvent event = new PlayerChangedMainHandEvent(this.getBukkitEntity(), this.getMainArm() == HumanoidArm.LEFT ? MainHand.LEFT : MainHand.RIGHT);
|
||||
@@ -2016,6 +2032,11 @@ public class ServerPlayer extends Player {
|
||||
this.server.server.getPluginManager().callEvent(new com.destroystokyo.paper.event.player.PlayerLocaleChangeEvent(this.getBukkitEntity(), this.language, clientOptions.language())); // Paper
|
||||
}
|
||||
// CraftBukkit end
|
||||
+ // Paper start - don't call options events on login
|
||||
+ updateOptionsNoEvents(clientOptions);
|
||||
+ }
|
||||
+ public void updateOptionsNoEvents(ClientInformation clientOptions) {
|
||||
+ // Paper end
|
||||
this.language = clientOptions.language();
|
||||
this.adventure$locale = java.util.Objects.requireNonNullElse(net.kyori.adventure.translation.Translator.parseLocale(this.language), java.util.Locale.US); // Paper
|
||||
this.requestedViewDistance = clientOptions.viewDistance();
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index 314e01920fe0302441d2cc08a0098ff8fee263e5..587689c5d4f24c3cb40218b0a1e62e7d10a94a7a 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -575,6 +575,28 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
connection.disconnect(message == null ? net.kyori.adventure.text.Component.empty() : message);
|
||||
}
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public <T> T getClientOption(com.destroystokyo.paper.ClientOption<T> type) {
|
||||
+ if (com.destroystokyo.paper.ClientOption.SKIN_PARTS == type) {
|
||||
+ return type.getType().cast(new com.destroystokyo.paper.PaperSkinParts(getHandle().getEntityData().get(net.minecraft.world.entity.player.Player.DATA_PLAYER_MODE_CUSTOMISATION)));
|
||||
+ } else if (com.destroystokyo.paper.ClientOption.CHAT_COLORS_ENABLED == type) {
|
||||
+ return type.getType().cast(getHandle().canChatInColor());
|
||||
+ } else if (com.destroystokyo.paper.ClientOption.CHAT_VISIBILITY == type) {
|
||||
+ return type.getType().cast(getHandle().getChatVisibility() == null ? com.destroystokyo.paper.ClientOption.ChatVisibility.UNKNOWN : com.destroystokyo.paper.ClientOption.ChatVisibility.valueOf(getHandle().getChatVisibility().name()));
|
||||
+ } else if (com.destroystokyo.paper.ClientOption.LOCALE == type) {
|
||||
+ return type.getType().cast(getLocale());
|
||||
+ } else if (com.destroystokyo.paper.ClientOption.MAIN_HAND == type) {
|
||||
+ return type.getType().cast(getMainHand());
|
||||
+ } else if (com.destroystokyo.paper.ClientOption.VIEW_DISTANCE == type) {
|
||||
+ return type.getType().cast(getClientViewDistance());
|
||||
+ } else if (com.destroystokyo.paper.ClientOption.ALLOW_SERVER_LISTINGS == type) {
|
||||
+ return type.getType().cast(getHandle().allowsListing());
|
||||
+ } else if (com.destroystokyo.paper.ClientOption.TEXT_FILTERING_ENABLED == type) {
|
||||
+ return type.getType().cast(getHandle().isTextFilteringEnabled());
|
||||
+ }
|
||||
+ throw new RuntimeException("Unknown settings type");
|
||||
+ }
|
||||
// Paper end
|
||||
|
||||
@Override
|
||||
diff --git a/src/test/java/io/papermc/paper/world/TranslationKeyTest.java b/src/test/java/io/papermc/paper/world/TranslationKeyTest.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..7f8b6462d2a1bbd39a870d2543bebc135f7eb45b
|
||||
--- /dev/null
|
||||
+++ b/src/test/java/io/papermc/paper/world/TranslationKeyTest.java
|
||||
@@ -0,0 +1,18 @@
|
||||
+package io.papermc.paper.world;
|
||||
+
|
||||
+import com.destroystokyo.paper.ClientOption;
|
||||
+import net.minecraft.world.entity.player.ChatVisiblity;
|
||||
+import org.bukkit.Difficulty;
|
||||
+import org.junit.jupiter.api.Assertions;
|
||||
+import org.junit.jupiter.api.Test;
|
||||
+
|
||||
+public class TranslationKeyTest {
|
||||
+
|
||||
+ @Test
|
||||
+ public void testChatVisibilityKeys() {
|
||||
+ for (ClientOption.ChatVisibility chatVisibility : ClientOption.ChatVisibility.values()) {
|
||||
+ if (chatVisibility == ClientOption.ChatVisibility.UNKNOWN) continue;
|
||||
+ Assertions.assertEquals(ChatVisiblity.valueOf(chatVisibility.name()).getKey(), chatVisibility.translationKey(), chatVisibility + "'s translation key doesn't match");
|
||||
+ }
|
||||
+ }
|
||||
+}
|
|
@ -1,23 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 18 Apr 2020 15:59:41 -0400
|
||||
Subject: [PATCH] Don't crash if player is attempted to be removed from
|
||||
untracked chunk.
|
||||
|
||||
I suspect it deals with teleporting as it uses players current x/y/z
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java
|
||||
index 76005b3c48bfa323a77781c20c63708eeaa66b2b..4e1618462840a1378dbe6492696c97544815edf2 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/DistanceManager.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/DistanceManager.java
|
||||
@@ -285,8 +285,8 @@ public abstract class DistanceManager {
|
||||
ObjectSet<ServerPlayer> objectset = (ObjectSet) this.playersPerChunk.get(i);
|
||||
if (objectset == null) return; // CraftBukkit - SPIGOT-6208
|
||||
|
||||
- objectset.remove(player);
|
||||
- if (objectset.isEmpty()) {
|
||||
+ if (objectset != null) objectset.remove(player); // Paper - some state corruption happens here, don't crash, clean up gracefully
|
||||
+ if (objectset == null || objectset.isEmpty()) { // Paper
|
||||
this.playersPerChunk.remove(i);
|
||||
this.naturalSpawnChunkCounter.update(i, Integer.MAX_VALUE, false);
|
||||
this.playerTicketManager.update(i, Integer.MAX_VALUE, false);
|
|
@ -1,105 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 19 Apr 2020 00:05:46 -0400
|
||||
Subject: [PATCH] Fire PlayerJoinEvent when Player is actually ready
|
||||
|
||||
For years, plugin developers have had to delay many things they do
|
||||
inside of the PlayerJoinEvent by 1 tick to make it actually work.
|
||||
|
||||
This all boiled down to 1 reason why: The event fired before the
|
||||
player was fully ready and joined to the world!
|
||||
|
||||
Additionally, if that player logged out on a vehicle, the event
|
||||
fired before the vehicle was even loaded, so that plugins had no
|
||||
access to the vehicle during this event either.
|
||||
|
||||
This change finally fixes this issue, fully preparing the player
|
||||
into the world as a fully ready entity, vehicle included.
|
||||
|
||||
There should be no plugins that break because of this change, but might
|
||||
improve consistency with other plugins instead.
|
||||
|
||||
For example, if 2 plugins listens to this event, and the first one
|
||||
teleported the player in the event, then the 2nd plugin actually
|
||||
would be getting a valid player!
|
||||
|
||||
This was very non deterministic. This change will ensure every plugin
|
||||
receives a deterministic result, and should no longer require 1 tick
|
||||
delays anymore.
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.server.level.ChunkMap addEntity(Lnet/minecraft/world/entity/Entity;)V
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 2fba58fd5c9b17512eadacb899c59a04df5d415f..4c1dd470ac561f61d7f49adf90d273b1f293d296 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -1459,6 +1459,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
return;
|
||||
}
|
||||
// Paper end - ignore and warn about illegal addEntity calls instead of crashing server
|
||||
+ if (entity instanceof ServerPlayer && ((ServerPlayer) entity).supressTrackerForLogin) return; // Paper - Fire PlayerJoinEvent when Player is actually ready; Delay adding to tracker until after list packets
|
||||
if (!(entity instanceof EnderDragonPart)) {
|
||||
EntityType<?> entitytypes = entity.getType();
|
||||
int i = entitytypes.clientTrackingRange() * 16;
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 3d7a938f72424a4f30f75563393a953cf9f11933..b64b20312396638b8fd596bca3794863601d2bb4 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -267,6 +267,7 @@ public class ServerPlayer extends Player {
|
||||
public double maxHealthCache;
|
||||
public boolean joining = true;
|
||||
public boolean sentListPacket = false;
|
||||
+ public boolean supressTrackerForLogin = false; // Paper - Fire PlayerJoinEvent when Player is actually ready
|
||||
public String kickLeaveMessage = null; // SPIGOT-3034: Forward leave message to PlayerQuitEvent
|
||||
// CraftBukkit end
|
||||
public boolean isRealPlayer; // Paper
|
||||
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
index 8f23597eee06e721a25f7be3a5a65dff6a59ee55..c5614cc12789fdfad3519434e115a50c12844b3b 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
@@ -296,6 +296,12 @@ public abstract class PlayerList {
|
||||
this.playersByUUID.put(player.getUUID(), player);
|
||||
// this.broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(entityplayer))); // CraftBukkit - replaced with loop below
|
||||
|
||||
+ // Paper start - Fire PlayerJoinEvent when Player is actually ready; correctly register player BEFORE PlayerJoinEvent, so the entity is valid and doesn't require tick delay hacks
|
||||
+ player.supressTrackerForLogin = true;
|
||||
+ worldserver1.addNewPlayer(player);
|
||||
+ this.server.getCustomBossEvents().onPlayerConnect(player); // see commented out section below worldserver.addPlayerJoin(entityplayer);
|
||||
+ mountSavedVehicle(player, worldserver1, nbttagcompound);
|
||||
+ // Paper end - Fire PlayerJoinEvent when Player is actually ready
|
||||
// CraftBukkit start
|
||||
CraftPlayer bukkitPlayer = player.getBukkitEntity();
|
||||
|
||||
@@ -334,6 +340,8 @@ public abstract class PlayerList {
|
||||
player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(entityplayer1)));
|
||||
}
|
||||
player.sentListPacket = true;
|
||||
+ player.supressTrackerForLogin = false; // Paper - Fire PlayerJoinEvent when Player is actually ready
|
||||
+ ((ServerLevel)player.level()).getChunkSource().chunkMap.addEntity(player); // Paper - Fire PlayerJoinEvent when Player is actually ready; track entity now
|
||||
// CraftBukkit end
|
||||
|
||||
player.getEntityData().refresh(player); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn
|
||||
@@ -356,6 +364,11 @@ public abstract class PlayerList {
|
||||
playerconnection.send(new ClientboundUpdateMobEffectPacket(player.getId(), mobeffect));
|
||||
}
|
||||
|
||||
+ // Paper start - Fire PlayerJoinEvent when Player is actually ready; move vehicle into method so it can be called above - short circuit around that code
|
||||
+ onPlayerJoinFinish(player, worldserver1, s1);
|
||||
+ }
|
||||
+ private void mountSavedVehicle(ServerPlayer player, ServerLevel worldserver1, CompoundTag nbttagcompound) {
|
||||
+ // Paper end - Fire PlayerJoinEvent when Player is actually ready
|
||||
if (nbttagcompound != null && nbttagcompound.contains("RootVehicle", 10)) {
|
||||
CompoundTag nbttagcompound1 = nbttagcompound.getCompound("RootVehicle");
|
||||
// CraftBukkit start
|
||||
@@ -404,6 +417,10 @@ public abstract class PlayerList {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start - Fire PlayerJoinEvent when Player is actually ready
|
||||
+ }
|
||||
+ public void onPlayerJoinFinish(ServerPlayer player, ServerLevel worldserver1, String s1) {
|
||||
+ // Paper end - Fire PlayerJoinEvent when Player is actually ready
|
||||
player.initInventoryMenu();
|
||||
// CraftBukkit - Moved from above, added world
|
||||
// Paper start - Configurable player collision; Add to collideRule team if needed
|
Loading…
Add table
Add a link
Reference in a new issue