some more work
This commit is contained in:
parent
a27262375c
commit
ef6a41195d
56 changed files with 225 additions and 223 deletions
|
@ -1,32 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Tue, 4 Sep 2018 15:02:00 -0500
|
||||
Subject: [PATCH] Expose attack cooldown methods for Player
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index 240f90460ddddf8168b7bc661a55fe7e5c94c67d..b5e85e664dda27c1fb342e47d901909742aec67d 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -2827,6 +2827,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
|
||||
return this.adventure$pointers;
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public float getCooldownPeriod() {
|
||||
+ return getHandle().getCurrentItemAttackStrengthDelay();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public float getCooledAttackStrength(float adjustTicks) {
|
||||
+ return getHandle().getAttackStrengthScale(adjustTicks);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void resetCooldown() {
|
||||
+ getHandle().resetAttackStrengthTicker();
|
||||
+ }
|
||||
// Paper end
|
||||
// Spigot start
|
||||
private final Player.Spigot spigot = new Player.Spigot()
|
|
@ -1,482 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Phoenix616 <mail@moep.tv>
|
||||
Date: Tue, 21 Aug 2018 01:39:35 +0100
|
||||
Subject: [PATCH] Improve death events
|
||||
|
||||
This adds the ability to cancel the death events and to modify the sound
|
||||
an entity makes when dying. (In cases were no sound should it will be
|
||||
called with shouldPlaySound set to false allowing unsilencing of silent
|
||||
entities)
|
||||
|
||||
It makes handling of entity deaths a lot nicer as you no longer need
|
||||
to listen on the damage event and calculate if the entity dies yourself
|
||||
to cancel the death which has the benefit of also receiving the dropped
|
||||
items and experience which is otherwise only properly possible by using
|
||||
internal code.
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.entity.LivingEntity getDeathSound()Lnet/minecraft/sounds/SoundEvent;
|
||||
public net.minecraft.world.entity.LivingEntity getSoundVolume()F
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index bd7b8ede44a5971b034ffb75fbddbadda8f42702..41e0b2826bae59e48fef7e35caeb3ce6e46031ea 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -243,6 +243,10 @@ public class ServerPlayer extends Player {
|
||||
public int latency;
|
||||
public boolean wonGame;
|
||||
private int containerUpdateDelay; // Paper
|
||||
+ // Paper start - cancellable death event
|
||||
+ public boolean queueHealthUpdatePacket = false;
|
||||
+ public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket;
|
||||
+ // Paper end
|
||||
|
||||
// CraftBukkit start
|
||||
public String displayName;
|
||||
@@ -872,6 +876,15 @@ public class ServerPlayer extends Player {
|
||||
String deathmessage = defaultMessage.getString();
|
||||
this.keepLevel = keepInventory; // SPIGOT-2222: pre-set keepLevel
|
||||
org.bukkit.event.entity.PlayerDeathEvent event = CraftEventFactory.callPlayerDeathEvent(this, loot, PaperAdventure.asAdventure(defaultMessage), defaultMessage.getString(), keepInventory); // Paper - Adventure
|
||||
+ // Paper start - cancellable death event
|
||||
+ if (event.isCancelled()) {
|
||||
+ // make compatible with plugins that might have already set the health in an event listener
|
||||
+ if (this.getHealth() <= 0) {
|
||||
+ this.setHealth((float) event.getReviveHealth());
|
||||
+ }
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
// SPIGOT-943 - only call if they have an inventory open
|
||||
if (this.containerMenu != this.inventoryMenu) {
|
||||
@@ -1023,8 +1036,17 @@ public class ServerPlayer extends Player {
|
||||
}
|
||||
}
|
||||
}
|
||||
-
|
||||
- return super.hurt(source, amount);
|
||||
+ // Paper start - cancellable death events
|
||||
+ //return super.hurt(source, amount);
|
||||
+ this.queueHealthUpdatePacket = true;
|
||||
+ boolean damaged = super.hurt(source, amount);
|
||||
+ this.queueHealthUpdatePacket = false;
|
||||
+ if (this.queuedHealthUpdatePacket != null) {
|
||||
+ this.connection.send(this.queuedHealthUpdatePacket);
|
||||
+ this.queuedHealthUpdatePacket = null;
|
||||
+ }
|
||||
+ return damaged;
|
||||
+ // Paper end
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index c995c8ac6785e5f8951013f3a37127573351c2c7..d84375984c67a8ad2790efc1c584f7e2f995633e 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -260,6 +260,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
public Set<UUID> collidableExemptions = new HashSet<>();
|
||||
public boolean bukkitPickUpLoot;
|
||||
public org.bukkit.craftbukkit.entity.CraftLivingEntity getBukkitLivingEntity() { return (org.bukkit.craftbukkit.entity.CraftLivingEntity) super.getBukkitEntity(); } // Paper
|
||||
+ public boolean silentDeath = false; // Paper - mark entity as dying silently for cancellable death event
|
||||
|
||||
@Override
|
||||
public float getBukkitYaw() {
|
||||
@@ -1494,13 +1495,12 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
if (knockbackCancelled) this.level().broadcastEntityEvent(this, (byte) 2); // Paper - Disable explosion knockback
|
||||
if (this.isDeadOrDying()) {
|
||||
if (!this.checkTotemDeathProtection(source)) {
|
||||
- SoundEvent soundeffect = this.getDeathSound();
|
||||
-
|
||||
- if (flag1 && soundeffect != null) {
|
||||
- this.playSound(soundeffect, this.getSoundVolume(), this.getVoicePitch());
|
||||
- }
|
||||
+ // Paper start - moved into CraftEventFactory event caller for cancellable death event
|
||||
+ this.silentDeath = !flag1; // mark entity as dying silently
|
||||
+ // Paper end
|
||||
|
||||
this.die(source);
|
||||
+ this.silentDeath = false; // Paper - cancellable death event - reset to default
|
||||
}
|
||||
} else if (flag1) {
|
||||
this.playHurtSound(source);
|
||||
@@ -1652,7 +1652,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
if (!this.isRemoved() && !this.dead) {
|
||||
Entity entity = damageSource.getEntity();
|
||||
LivingEntity entityliving = this.getKillCredit();
|
||||
-
|
||||
+ /* // Paper - move down to make death event cancellable - this is the awardKillScore below
|
||||
if (this.deathScore >= 0 && entityliving != null) {
|
||||
entityliving.awardKillScore(this, this.deathScore, damageSource);
|
||||
}
|
||||
@@ -1664,24 +1664,59 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
if (!this.level().isClientSide && this.hasCustomName()) {
|
||||
if (org.spigotmc.SpigotConfig.logNamedDeaths) LivingEntity.LOGGER.info("Named entity {} died: {}", this, this.getCombatTracker().getDeathMessage().getString()); // Spigot
|
||||
}
|
||||
+ */ // Paper - move down to make death event cancellable - this is the awardKillScore below
|
||||
|
||||
this.dead = true;
|
||||
- this.getCombatTracker().recheckStatus();
|
||||
+ // Paper - moved into if below
|
||||
Level world = this.level();
|
||||
|
||||
if (world instanceof ServerLevel) {
|
||||
ServerLevel worldserver = (ServerLevel) world;
|
||||
+ // Paper - move below into if for onKill
|
||||
+
|
||||
+ // Paper start
|
||||
+ org.bukkit.event.entity.EntityDeathEvent deathEvent = this.dropAllDeathLoot(damageSource);
|
||||
+ if (deathEvent == null || !deathEvent.isCancelled()) {
|
||||
+ if (this.deathScore >= 0 && entityliving != null) {
|
||||
+ entityliving.awardKillScore(this, this.deathScore, damageSource);
|
||||
+ }
|
||||
+ // Paper start - clear equipment if event is not cancelled
|
||||
+ if (this instanceof Mob) {
|
||||
+ for (EquipmentSlot slot : this.clearedEquipmentSlots) {
|
||||
+ this.setItemSlot(slot, ItemStack.EMPTY);
|
||||
+ }
|
||||
+ this.clearedEquipmentSlots.clear();
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
- if (entity == null || entity.killedEntity(worldserver, this)) {
|
||||
+ if (this.isSleeping()) {
|
||||
+ this.stopSleeping();
|
||||
+ }
|
||||
+
|
||||
+ if (!this.level().isClientSide && this.hasCustomName()) {
|
||||
+ if (org.spigotmc.SpigotConfig.logNamedDeaths) LivingEntity.LOGGER.info("Named entity {} died: {}", this, this.getCombatTracker().getDeathMessage().getString()); // Spigot
|
||||
+ }
|
||||
+
|
||||
+ this.getCombatTracker().recheckStatus();
|
||||
+ if (entity != null) {
|
||||
+ entity.killedEntity((ServerLevel) this.level(), this);
|
||||
+ }
|
||||
this.gameEvent(GameEvent.ENTITY_DIE);
|
||||
- this.dropAllDeathLoot(damageSource);
|
||||
- this.createWitherRose(entityliving);
|
||||
+ } else {
|
||||
+ this.dead = false;
|
||||
+ this.setHealth((float) deathEvent.getReviveHealth());
|
||||
}
|
||||
|
||||
- this.level().broadcastEntityEvent(this, (byte) 3);
|
||||
+ // Paper end
|
||||
+ this.createWitherRose(entityliving);
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ if (this.dead) { // Paper
|
||||
+ this.level().broadcastEntityEvent(this, (byte) 3);
|
||||
this.setPose(Pose.DYING);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1689,7 +1724,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
if (!this.level().isClientSide) {
|
||||
boolean flag = false;
|
||||
|
||||
- if (adversary instanceof WitherBoss) {
|
||||
+ if (this.dead && adversary instanceof WitherBoss) { // Paper
|
||||
if (this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
|
||||
BlockPos blockposition = this.blockPosition();
|
||||
BlockState iblockdata = Blocks.WITHER_ROSE.defaultBlockState();
|
||||
@@ -1718,7 +1753,11 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
}
|
||||
}
|
||||
|
||||
- protected void dropAllDeathLoot(DamageSource source) {
|
||||
+ // Paper start
|
||||
+ protected boolean clearEquipmentSlots = true;
|
||||
+ protected Set<EquipmentSlot> clearedEquipmentSlots = new java.util.HashSet<>();
|
||||
+ protected org.bukkit.event.entity.EntityDeathEvent dropAllDeathLoot(DamageSource source) {
|
||||
+ // Paper end
|
||||
Entity entity = source.getEntity();
|
||||
int i;
|
||||
|
||||
@@ -1733,18 +1772,27 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
this.dropEquipment(); // CraftBukkit - from below
|
||||
if (this.shouldDropLoot() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
|
||||
this.dropFromLootTable(source, flag);
|
||||
+ // Paper start
|
||||
+ final boolean prev = this.clearEquipmentSlots;
|
||||
+ this.clearEquipmentSlots = false;
|
||||
+ this.clearedEquipmentSlots.clear();
|
||||
+ // Paper end
|
||||
this.dropCustomDeathLoot(source, i, flag);
|
||||
+ this.clearEquipmentSlots = prev; // Paper
|
||||
}
|
||||
// CraftBukkit start - Call death event
|
||||
- CraftEventFactory.callEntityDeathEvent(this, this.drops);
|
||||
+ org.bukkit.event.entity.EntityDeathEvent deathEvent = CraftEventFactory.callEntityDeathEvent(this, this.drops); // Paper
|
||||
+ this.postDeathDropItems(deathEvent); // Paper
|
||||
this.drops = new ArrayList<>();
|
||||
// CraftBukkit end
|
||||
|
||||
// this.dropInventory();// CraftBukkit - moved up
|
||||
this.dropExperience();
|
||||
+ return deathEvent; // Paper
|
||||
}
|
||||
|
||||
protected void dropEquipment() {}
|
||||
+ protected void postDeathDropItems(org.bukkit.event.entity.EntityDeathEvent event) {} // Paper - method for post death logic that cannot be ran before the event is potentially cancelled
|
||||
|
||||
// CraftBukkit start
|
||||
public int getExpReward() {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java
|
||||
index 2fc099e2fb17073f3ab4ac5e868b1c583bf8a594..3081c1370a0854f07214cbc50b06cbb005d171fb 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Mob.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Mob.java
|
||||
@@ -1068,7 +1068,13 @@ public abstract class Mob extends LivingEntity implements Targeting {
|
||||
}
|
||||
|
||||
this.spawnAtLocation(itemstack);
|
||||
+ if (this.clearEquipmentSlots) { // Paper
|
||||
this.setItemSlot(enumitemslot, ItemStack.EMPTY);
|
||||
+ // Paper start
|
||||
+ } else {
|
||||
+ this.clearedEquipmentSlots.add(enumitemslot);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/Fox.java b/src/main/java/net/minecraft/world/entity/animal/Fox.java
|
||||
index 44b6d232d940d4020fa7664e48a483c20959dde0..24ae11d300d0856350f185f03552ba592f3d218a 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/Fox.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/Fox.java
|
||||
@@ -706,15 +706,25 @@ public class Fox extends Animal implements VariantHolder<Fox.Type> {
|
||||
}
|
||||
|
||||
@Override
|
||||
- protected void dropAllDeathLoot(DamageSource source) {
|
||||
- ItemStack itemstack = this.getItemBySlot(EquipmentSlot.MAINHAND);
|
||||
+ // Paper start - Cancellable death event
|
||||
+ protected org.bukkit.event.entity.EntityDeathEvent dropAllDeathLoot(DamageSource source) {
|
||||
+ ItemStack itemstack = this.getItemBySlot(EquipmentSlot.MAINHAND).copy(); // Paper - modified by supercall
|
||||
+
|
||||
+ org.bukkit.event.entity.EntityDeathEvent deathEvent = super.dropAllDeathLoot(source);
|
||||
+
|
||||
+ // Below is code to drop
|
||||
+
|
||||
+ if (deathEvent == null || deathEvent.isCancelled()) {
|
||||
+ return deathEvent;
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
if (!itemstack.isEmpty()) {
|
||||
this.spawnAtLocation(itemstack);
|
||||
this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY);
|
||||
}
|
||||
|
||||
- super.dropAllDeathLoot(source);
|
||||
+ return deathEvent; // Paper
|
||||
}
|
||||
|
||||
public static boolean isPathClear(Fox fox, LivingEntity chasedEntity) {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java
|
||||
index ebe207e2c4d8b7e125fec8a5182fe4882c9339e3..8ac82d3efc0f6d8ff40226e4f8084435c136eba4 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java
|
||||
@@ -69,11 +69,19 @@ public abstract class AbstractChestedHorse extends AbstractHorse {
|
||||
this.spawnAtLocation(Blocks.CHEST);
|
||||
}
|
||||
|
||||
- this.setChest(false);
|
||||
+ //this.setCarryingChest(false); // Paper - moved to post death logic
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ protected void postDeathDropItems(org.bukkit.event.entity.EntityDeathEvent event) {
|
||||
+ if (this.hasChest() && (event == null || !event.isCancelled())) {
|
||||
+ this.setChest(false);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public void addAdditionalSaveData(CompoundTag nbt) {
|
||||
super.addAdditionalSaveData(nbt);
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
|
||||
index 719f68f96e58ddcdd3592131c691d21263c81915..a35a0952ce8e1fc42e92734786d531c7e10b34d7 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
|
||||
@@ -491,8 +491,10 @@ public class ArmorStand extends LivingEntity {
|
||||
}
|
||||
// CraftBukkit end
|
||||
if (source.is(DamageTypeTags.IS_EXPLOSION)) {
|
||||
- this.brokenByAnything(source);
|
||||
- this.kill();
|
||||
+ // Paper start - avoid duplicate event call
|
||||
+ org.bukkit.event.entity.EntityDeathEvent event = this.brokenByAnything(source);
|
||||
+ if (!event.isCancelled()) this.kill(false);
|
||||
+ // Paper end
|
||||
return false;
|
||||
} else if (source.is(DamageTypeTags.IGNITES_ARMOR_STANDS)) {
|
||||
if (this.isOnFire()) {
|
||||
@@ -536,9 +538,9 @@ public class ArmorStand extends LivingEntity {
|
||||
this.gameEvent(GameEvent.ENTITY_DAMAGE, source.getEntity());
|
||||
this.lastHit = i;
|
||||
} else {
|
||||
- this.brokenByPlayer(source);
|
||||
+ org.bukkit.event.entity.EntityDeathEvent event = this.brokenByPlayer(source); // Paper
|
||||
this.showBreakingParticles();
|
||||
- this.discard(); // CraftBukkit - SPIGOT-4890: remain as this.discard() since above damagesource method will call death event
|
||||
+ if (!event.isCancelled()) this.kill(false); // Paper - we still need to kill to follow vanilla logic (emit the game event etc...)
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -590,8 +592,10 @@ public class ArmorStand extends LivingEntity {
|
||||
|
||||
f1 -= amount;
|
||||
if (f1 <= 0.5F) {
|
||||
- this.brokenByAnything(damageSource);
|
||||
- this.kill();
|
||||
+ // Paper start - avoid duplicate event call
|
||||
+ org.bukkit.event.entity.EntityDeathEvent event = this.brokenByAnything(damageSource);
|
||||
+ if (!event.isCancelled()) this.kill(false);
|
||||
+ // Paper end
|
||||
} else {
|
||||
this.setHealth(f1);
|
||||
this.gameEvent(GameEvent.ENTITY_DAMAGE, damageSource.getEntity());
|
||||
@@ -599,7 +603,7 @@ public class ArmorStand extends LivingEntity {
|
||||
|
||||
}
|
||||
|
||||
- private void brokenByPlayer(DamageSource damageSource) {
|
||||
+ private org.bukkit.event.entity.EntityDeathEvent brokenByPlayer(DamageSource damageSource) { // Paper
|
||||
ItemStack itemstack = new ItemStack(Items.ARMOR_STAND);
|
||||
|
||||
if (this.hasCustomName()) {
|
||||
@@ -607,10 +611,10 @@ public class ArmorStand extends LivingEntity {
|
||||
}
|
||||
|
||||
drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops
|
||||
- this.brokenByAnything(damageSource);
|
||||
+ return this.brokenByAnything(damageSource); // Paper
|
||||
}
|
||||
|
||||
- private void brokenByAnything(DamageSource damageSource) {
|
||||
+ private org.bukkit.event.entity.EntityDeathEvent brokenByAnything(DamageSource damageSource) { // Paper
|
||||
this.playBrokenSound();
|
||||
// this.dropAllDeathLoot(damagesource); // CraftBukkit - moved down
|
||||
|
||||
@@ -632,7 +636,7 @@ public class ArmorStand extends LivingEntity {
|
||||
this.armorItems.set(i, ItemStack.EMPTY);
|
||||
}
|
||||
}
|
||||
- this.dropAllDeathLoot(damageSource); // CraftBukkit - moved from above
|
||||
+ return this.dropAllDeathLoot(damageSource); // CraftBukkit - moved from above // Paper
|
||||
|
||||
}
|
||||
|
||||
@@ -764,7 +768,16 @@ public class ArmorStand extends LivingEntity {
|
||||
|
||||
@Override
|
||||
public void kill() {
|
||||
- org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, drops); // CraftBukkit - call event
|
||||
+ // Paper start
|
||||
+ kill(true);
|
||||
+ }
|
||||
+
|
||||
+ public void kill(boolean callEvent) {
|
||||
+ if (callEvent) {
|
||||
+ // Paper end
|
||||
+ org.bukkit.event.entity.EntityDeathEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, drops); // CraftBukkit - call event // Paper - make cancellable
|
||||
+ if (event.isCancelled()) return; // Paper - make cancellable
|
||||
+ } // Paper
|
||||
this.remove(Entity.RemovalReason.KILLED);
|
||||
this.gameEvent(GameEvent.ENTITY_DIE);
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index b5e85e664dda27c1fb342e47d901909742aec67d..1c09e955e34380b99572cc5950806417ac10bfc8 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -2327,7 +2327,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
@Override
|
||||
public void sendHealthUpdate() {
|
||||
FoodData foodData = this.getHandle().getFoodData();
|
||||
- this.sendHealthUpdate(this.getScaledHealth(), foodData.getFoodLevel(), foodData.getSaturationLevel());
|
||||
+ // Paper start - cancellable death event
|
||||
+ ClientboundSetHealthPacket packet = new ClientboundSetHealthPacket(this.getScaledHealth(), foodData.getFoodLevel(), foodData.getSaturationLevel());
|
||||
+ if (this.getHandle().queueHealthUpdatePacket) {
|
||||
+ this.getHandle().queuedHealthUpdatePacket = packet;
|
||||
+ } else {
|
||||
+ this.getHandle().connection.send(packet);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
public void injectScaledMaxHealth(Collection<AttributeInstance> collection, boolean force) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
index 53af54ffecd7fdb20588d75a8c32003cb89a75b1..eaca76dfec9cbe3cbb9972a0c9cf30599816fcda 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
@@ -863,9 +863,16 @@ public class CraftEventFactory {
|
||||
public static EntityDeathEvent callEntityDeathEvent(net.minecraft.world.entity.LivingEntity victim, List<org.bukkit.inventory.ItemStack> drops) {
|
||||
CraftLivingEntity entity = (CraftLivingEntity) victim.getBukkitEntity();
|
||||
EntityDeathEvent event = new EntityDeathEvent(entity, drops, victim.getExpReward());
|
||||
+ populateFields(victim, event); // Paper - make cancellable
|
||||
CraftWorld world = (CraftWorld) entity.getWorld();
|
||||
Bukkit.getServer().getPluginManager().callEvent(event);
|
||||
|
||||
+ // Paper start - make cancellable
|
||||
+ if (event.isCancelled()) {
|
||||
+ return event;
|
||||
+ }
|
||||
+ playDeathSound(victim, event);
|
||||
+ // Paper end
|
||||
victim.expToDrop = event.getDroppedExp();
|
||||
|
||||
for (org.bukkit.inventory.ItemStack stack : event.getDrops()) {
|
||||
@@ -882,8 +889,15 @@ public class CraftEventFactory {
|
||||
PlayerDeathEvent event = new PlayerDeathEvent(entity, drops, victim.getExpReward(), 0, deathMessage, stringDeathMessage); // Paper - Adventure
|
||||
event.setKeepInventory(keepInventory);
|
||||
event.setKeepLevel(victim.keepLevel); // SPIGOT-2222: pre-set keepLevel
|
||||
+ populateFields(victim, event); // Paper - make cancellable
|
||||
org.bukkit.World world = entity.getWorld();
|
||||
Bukkit.getServer().getPluginManager().callEvent(event);
|
||||
+ // Paper start - make cancellable
|
||||
+ if (event.isCancelled()) {
|
||||
+ return event;
|
||||
+ }
|
||||
+ playDeathSound(victim, event);
|
||||
+ // Paper end
|
||||
|
||||
victim.keepLevel = event.getKeepLevel();
|
||||
victim.newLevel = event.getNewLevel();
|
||||
@@ -900,6 +914,31 @@ public class CraftEventFactory {
|
||||
return event;
|
||||
}
|
||||
|
||||
+ // Paper start - helper methods for making death event cancellable
|
||||
+ // Add information to death event
|
||||
+ private static void populateFields(net.minecraft.world.entity.LivingEntity victim, EntityDeathEvent event) {
|
||||
+ event.setReviveHealth(event.getEntity().getAttribute(org.bukkit.attribute.Attribute.GENERIC_MAX_HEALTH).getValue());
|
||||
+ event.setShouldPlayDeathSound(!victim.silentDeath && !victim.isSilent());
|
||||
+ net.minecraft.sounds.SoundEvent soundEffect = victim.getDeathSound();
|
||||
+ event.setDeathSound(soundEffect != null ? org.bukkit.craftbukkit.CraftSound.getBukkit(soundEffect) : null);
|
||||
+ event.setDeathSoundCategory(org.bukkit.SoundCategory.valueOf(victim.getSoundSource().name()));
|
||||
+ event.setDeathSoundVolume(victim.getSoundVolume());
|
||||
+ event.setDeathSoundPitch(victim.getVoicePitch());
|
||||
+ }
|
||||
+
|
||||
+ // Play death sound manually
|
||||
+ private static void playDeathSound(net.minecraft.world.entity.LivingEntity victim, EntityDeathEvent event) {
|
||||
+ if (event.shouldPlayDeathSound() && event.getDeathSound() != null && event.getDeathSoundCategory() != null) {
|
||||
+ net.minecraft.world.entity.player.Player source = victim instanceof net.minecraft.world.entity.player.Player ? (net.minecraft.world.entity.player.Player) victim : null;
|
||||
+ double x = event.getEntity().getLocation().getX();
|
||||
+ double y = event.getEntity().getLocation().getY();
|
||||
+ double z = event.getEntity().getLocation().getZ();
|
||||
+ net.minecraft.sounds.SoundEvent soundEffect = org.bukkit.craftbukkit.CraftSound.getSoundEffect(event.getDeathSound());
|
||||
+ net.minecraft.sounds.SoundSource soundCategory = net.minecraft.sounds.SoundSource.valueOf(event.getDeathSoundCategory().name());
|
||||
+ victim.level().playSound(source, x, y, z, soundEffect, soundCategory, event.getDeathSoundVolume(), event.getDeathSoundPitch());
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
/**
|
||||
* Server methods
|
||||
*/
|
|
@ -1,31 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Sat, 8 Sep 2018 18:43:31 -0500
|
||||
Subject: [PATCH] Allow chests to be placed with NBT data
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
index c33660718c0ea281d7bcdb15df0568d4d46547e2..0caf3eeb7984e842f7a0bdfed3021d0b231a0dd0 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
@@ -381,6 +381,7 @@ public final class ItemStack {
|
||||
enuminteractionresult = InteractionResult.FAIL; // cancel placement
|
||||
// PAIL: Remove this when MC-99075 fixed
|
||||
placeEvent.getPlayer().updateInventory();
|
||||
+ world.capturedTileEntities.clear(); // Paper - clear out tile entities as chests and such will pop loot
|
||||
// revert back all captured blocks
|
||||
world.preventPoiUpdated = true; // CraftBukkit - SPIGOT-5710
|
||||
for (BlockState blockstate : blocks) {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java
|
||||
index d4f5af759bbb6208432ad7b5002af5455dc7958c..a71414397bd45ee7bcacfeef0041d80dfa25f114 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java
|
||||
@@ -237,7 +237,7 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement
|
||||
// CraftBukkit start
|
||||
@Override
|
||||
public boolean onlyOpCanSetNbt() {
|
||||
- return true;
|
||||
+ return false; // Paper
|
||||
}
|
||||
// CraftBukkit end
|
||||
}
|
|
@ -1,204 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 9 Sep 2018 13:30:00 -0400
|
||||
Subject: [PATCH] Mob Pathfinding API
|
||||
|
||||
Implements Pathfinding API for mobs
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.entity.ai.navigation.PathNavigation pathFinder
|
||||
public net.minecraft.world.level.pathfinder.PathFinder nodeEvaluator
|
||||
public net.minecraft.world.level.pathfinder.Path nodes
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java b/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..064712e7b27a200b29c72076a82f4f5611fa507f
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java
|
||||
@@ -0,0 +1,143 @@
|
||||
+package com.destroystokyo.paper.entity;
|
||||
+
|
||||
+import org.apache.commons.lang.Validate;
|
||||
+import org.bukkit.Location;
|
||||
+import org.bukkit.craftbukkit.entity.CraftLivingEntity;
|
||||
+import org.bukkit.entity.LivingEntity;
|
||||
+import org.bukkit.entity.Mob;
|
||||
+import javax.annotation.Nonnull;
|
||||
+import javax.annotation.Nullable;
|
||||
+import net.minecraft.world.level.pathfinder.Node;
|
||||
+import net.minecraft.world.level.pathfinder.Path;
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.List;
|
||||
+
|
||||
+public class PaperPathfinder implements com.destroystokyo.paper.entity.Pathfinder {
|
||||
+
|
||||
+ private net.minecraft.world.entity.Mob entity;
|
||||
+
|
||||
+ public PaperPathfinder(net.minecraft.world.entity.Mob entity) {
|
||||
+ this.entity = entity;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Mob getEntity() {
|
||||
+ return entity.getBukkitMob();
|
||||
+ }
|
||||
+
|
||||
+ public void setHandle(net.minecraft.world.entity.Mob entity) {
|
||||
+ this.entity = entity;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void stopPathfinding() {
|
||||
+ entity.getNavigation().stop();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean hasPath() {
|
||||
+ return entity.getNavigation().getPath() != null && !entity.getNavigation().getPath().isDone();
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ @Override
|
||||
+ public PathResult getCurrentPath() {
|
||||
+ Path path = entity.getNavigation().getPath();
|
||||
+ return path != null && !path.isDone() ? new PaperPathResult(path) : null;
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ @Override
|
||||
+ public PathResult findPath(Location loc) {
|
||||
+ Validate.notNull(loc, "Location can not be null");
|
||||
+ Path path = entity.getNavigation().createPath(loc.getX(), loc.getY(), loc.getZ(), 0);
|
||||
+ return path != null ? new PaperPathResult(path) : null;
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ @Override
|
||||
+ public PathResult findPath(LivingEntity target) {
|
||||
+ Validate.notNull(target, "Target can not be null");
|
||||
+ Path path = entity.getNavigation().createPath(((CraftLivingEntity) target).getHandle(), 0);
|
||||
+ return path != null ? new PaperPathResult(path) : null;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean moveTo(@Nonnull PathResult path, double speed) {
|
||||
+ Validate.notNull(path, "PathResult can not be null");
|
||||
+ Path pathEntity = ((PaperPathResult) path).path;
|
||||
+ return entity.getNavigation().moveTo(pathEntity, speed);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean canOpenDoors() {
|
||||
+ return entity.getNavigation().pathFinder.nodeEvaluator.canOpenDoors();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setCanOpenDoors(boolean canOpenDoors) {
|
||||
+ entity.getNavigation().pathFinder.nodeEvaluator.setCanOpenDoors(canOpenDoors);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean canPassDoors() {
|
||||
+ return entity.getNavigation().pathFinder.nodeEvaluator.canPassDoors();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setCanPassDoors(boolean canPassDoors) {
|
||||
+ entity.getNavigation().pathFinder.nodeEvaluator.setCanPassDoors(canPassDoors);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean canFloat() {
|
||||
+ return entity.getNavigation().pathFinder.nodeEvaluator.canFloat();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setCanFloat(boolean canFloat) {
|
||||
+ entity.getNavigation().pathFinder.nodeEvaluator.setCanFloat(canFloat);
|
||||
+ }
|
||||
+
|
||||
+ public class PaperPathResult implements com.destroystokyo.paper.entity.PaperPathfinder.PathResult {
|
||||
+
|
||||
+ private final Path path;
|
||||
+ PaperPathResult(Path path) {
|
||||
+ this.path = path;
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ @Override
|
||||
+ public Location getFinalPoint() {
|
||||
+ Node point = path.getEndNode();
|
||||
+ return point != null ? toLoc(point) : null;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public List<Location> getPoints() {
|
||||
+ List<Location> points = new ArrayList<>();
|
||||
+ for (Node point : path.nodes) {
|
||||
+ points.add(toLoc(point));
|
||||
+ }
|
||||
+ return points;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getNextPointIndex() {
|
||||
+ return path.getNextNodeIndex();
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ @Override
|
||||
+ public Location getNextPoint() {
|
||||
+ if (!path.hasNext()) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ return toLoc(path.nodes.get(path.getNextNodeIndex()));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private Location toLoc(Node point) {
|
||||
+ return new Location(entity.level().getWorld(), point.x, point.y, point.z);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/pathfinder/Path.java b/src/main/java/net/minecraft/world/level/pathfinder/Path.java
|
||||
index 4ad2ac8d1e9111933fa58c47442fa1f5e8173fd3..2a335f277bd0e4b8ad0f60d8226eb8aaa80a871f 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/pathfinder/Path.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/pathfinder/Path.java
|
||||
@@ -21,6 +21,7 @@ public class Path {
|
||||
private final BlockPos target;
|
||||
private final float distToTarget;
|
||||
private final boolean reached;
|
||||
+ public boolean hasNext() { return getNextNodeIndex() < this.nodes.size(); } // Paper
|
||||
|
||||
public Path(List<Node> nodes, BlockPos target, boolean reachesTarget) {
|
||||
this.nodes = nodes;
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java
|
||||
index 659ccb6532506b2a8c9feb55dc5aee962f6da795..f36713771598ac5afdae5d94db10a5790949611d 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java
|
||||
@@ -15,8 +15,11 @@ import org.bukkit.loot.LootTable;
|
||||
public abstract class CraftMob extends CraftLivingEntity implements Mob {
|
||||
public CraftMob(CraftServer server, net.minecraft.world.entity.Mob entity) {
|
||||
super(server, entity);
|
||||
+ paperPathfinder = new com.destroystokyo.paper.entity.PaperPathfinder(entity); // Paper
|
||||
}
|
||||
|
||||
+ private final com.destroystokyo.paper.entity.PaperPathfinder paperPathfinder; // Paper
|
||||
+ @Override public com.destroystokyo.paper.entity.Pathfinder getPathfinder() { return paperPathfinder; } // Paper
|
||||
@Override
|
||||
public void setTarget(LivingEntity target) {
|
||||
Preconditions.checkState(!this.getHandle().generation, "Cannot set target during world generation");
|
||||
@@ -57,6 +60,14 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob {
|
||||
return (net.minecraft.world.entity.Mob) entity;
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public void setHandle(net.minecraft.world.entity.Entity entity) {
|
||||
+ super.setHandle(entity);
|
||||
+ paperPathfinder.setHandle(getHandle());
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CraftMob";
|
|
@ -1,402 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Mark Vainomaa <mikroskeem@mikroskeem.eu>
|
||||
Date: Wed, 12 Sep 2018 18:53:55 +0300
|
||||
Subject: [PATCH] Implement an API for CanPlaceOn and CanDestroy NBT values
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
|
||||
index 8ada3a7c5539293d4e2c1a5b83e00fc2542f10ff..d7102d83bb781b6cf296cf9c637f8270f4ee8b14 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
|
||||
@@ -83,6 +83,12 @@ import org.bukkit.persistence.PersistentDataContainer;
|
||||
import static org.spigotmc.ValidateUtils.*;
|
||||
// Spigot end
|
||||
|
||||
+// Paper start
|
||||
+import com.destroystokyo.paper.Namespaced;
|
||||
+import com.destroystokyo.paper.NamespacedTag;
|
||||
+import java.util.Collections;
|
||||
+// Paper end
|
||||
+
|
||||
/**
|
||||
* Children must include the following:
|
||||
*
|
||||
@@ -271,6 +277,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
@Specific(Specific.To.NBT)
|
||||
static final ItemMetaKey BLOCK_DATA = new ItemMetaKey("BlockStateTag");
|
||||
static final ItemMetaKey BUKKIT_CUSTOM_TAG = new ItemMetaKey("PublicBukkitValues");
|
||||
+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values
|
||||
+ static final ItemMetaKey CAN_DESTROY = new ItemMetaKey("CanDestroy");
|
||||
+ static final ItemMetaKey CAN_PLACE_ON = new ItemMetaKey("CanPlaceOn");
|
||||
+ // Paper end
|
||||
|
||||
// We store the raw original JSON representation of all text data. See SPIGOT-5063, SPIGOT-5656, SPIGOT-5304
|
||||
private String displayName;
|
||||
@@ -284,6 +294,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
private int hideFlag;
|
||||
private boolean unbreakable;
|
||||
private int damage;
|
||||
+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values
|
||||
+ private Set<Namespaced> placeableKeys = Sets.newHashSet();
|
||||
+ private Set<Namespaced> destroyableKeys = Sets.newHashSet();
|
||||
+ // Paper end
|
||||
|
||||
private static final Set<String> HANDLED_TAGS = Sets.newHashSet();
|
||||
private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry();
|
||||
@@ -321,6 +335,15 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
this.hideFlag = meta.hideFlag;
|
||||
this.unbreakable = meta.unbreakable;
|
||||
this.damage = meta.damage;
|
||||
+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values
|
||||
+ if (meta.hasPlaceableKeys()) {
|
||||
+ this.placeableKeys = new java.util.HashSet<>(meta.placeableKeys);
|
||||
+ }
|
||||
+
|
||||
+ if (meta.hasDestroyableKeys()) {
|
||||
+ this.destroyableKeys = new java.util.HashSet<>(meta.destroyableKeys);
|
||||
+ }
|
||||
+ // Paper end
|
||||
this.unhandledTags.putAll(meta.unhandledTags);
|
||||
this.persistentDataContainer.putAll(meta.persistentDataContainer.getRaw());
|
||||
|
||||
@@ -384,6 +407,31 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
this.persistentDataContainer.put(key, compound.get(key).copy());
|
||||
}
|
||||
}
|
||||
+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values
|
||||
+ if (tag.contains(CAN_DESTROY.NBT)) {
|
||||
+ ListTag list = tag.getList(CAN_DESTROY.NBT, CraftMagicNumbers.NBT.TAG_STRING);
|
||||
+ for (int i = 0; i < list.size(); i++) {
|
||||
+ Namespaced namespaced = this.deserializeNamespaced(list.getString(i));
|
||||
+ if (namespaced == null) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ this.destroyableKeys.add(namespaced);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (tag.contains(CAN_PLACE_ON.NBT)) {
|
||||
+ ListTag list = tag.getList(CAN_PLACE_ON.NBT, CraftMagicNumbers.NBT.TAG_STRING);
|
||||
+ for (int i = 0; i < list.size(); i++) {
|
||||
+ Namespaced namespaced = this.deserializeNamespaced(list.getString(i));
|
||||
+ if (namespaced == null) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ this.placeableKeys.add(namespaced);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
Set<String> keys = tag.getAllKeys();
|
||||
for (String key : keys) {
|
||||
@@ -522,6 +570,34 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
this.setDamage(damage);
|
||||
}
|
||||
|
||||
+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values
|
||||
+ Iterable<?> canPlaceOnSerialized = SerializableMeta.getObject(Iterable.class, map, CAN_PLACE_ON.BUKKIT, true);
|
||||
+ if (canPlaceOnSerialized != null) {
|
||||
+ for (Object canPlaceOnElement : canPlaceOnSerialized) {
|
||||
+ String canPlaceOnRaw = (String) canPlaceOnElement;
|
||||
+ Namespaced value = this.deserializeNamespaced(canPlaceOnRaw);
|
||||
+ if (value == null) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ this.placeableKeys.add(value);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ Iterable<?> canDestroySerialized = SerializableMeta.getObject(Iterable.class, map, CAN_DESTROY.BUKKIT, true);
|
||||
+ if (canDestroySerialized != null) {
|
||||
+ for (Object canDestroyElement : canDestroySerialized) {
|
||||
+ String canDestroyRaw = (String) canDestroyElement;
|
||||
+ Namespaced value = this.deserializeNamespaced(canDestroyRaw);
|
||||
+ if (value == null) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ this.destroyableKeys.add(value);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
String internal = SerializableMeta.getString(map, "internal", true);
|
||||
if (internal != null) {
|
||||
ByteArrayInputStream buf = new ByteArrayInputStream(Base64.getDecoder().decode(internal));
|
||||
@@ -650,6 +726,23 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
if (this.hasDamage()) {
|
||||
itemTag.putInt(DAMAGE.NBT, damage);
|
||||
}
|
||||
+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values
|
||||
+ if (hasPlaceableKeys()) {
|
||||
+ List<String> items = this.placeableKeys.stream()
|
||||
+ .map(this::serializeNamespaced)
|
||||
+ .collect(java.util.stream.Collectors.toList());
|
||||
+
|
||||
+ itemTag.put(CAN_PLACE_ON.NBT, createNonComponentStringList(items));
|
||||
+ }
|
||||
+
|
||||
+ if (hasDestroyableKeys()) {
|
||||
+ List<String> items = this.destroyableKeys.stream()
|
||||
+ .map(this::serializeNamespaced)
|
||||
+ .collect(java.util.stream.Collectors.toList());
|
||||
+
|
||||
+ itemTag.put(CAN_DESTROY.NBT, createNonComponentStringList(items));
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
for (Map.Entry<String, Tag> e : this.unhandledTags.entrySet()) {
|
||||
itemTag.put(e.getKey(), e.getValue());
|
||||
@@ -666,6 +759,21 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ static ListTag createNonComponentStringList(List<String> list) {
|
||||
+ if (list == null || list.isEmpty()) {
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ ListTag tagList = new ListTag();
|
||||
+ for (String value : list) {
|
||||
+ tagList.add(StringTag.valueOf(value)); // Paper - NBTTagString.of(String str)
|
||||
+ }
|
||||
+
|
||||
+ return tagList;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
ListTag createStringList(List<String> list) {
|
||||
if (list == null) {
|
||||
return null;
|
||||
@@ -749,7 +857,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
|
||||
@Overridden
|
||||
boolean isEmpty() {
|
||||
- return !(this.hasDisplayName() || this.hasLocalizedName() || this.hasEnchants() || (this.lore != null) || this.hasCustomModelData() || this.hasBlockData() || this.hasRepairCost() || !this.unhandledTags.isEmpty() || !this.persistentDataContainer.isEmpty() || this.hideFlag != 0 || this.isUnbreakable() || this.hasDamage() || this.hasAttributeModifiers());
|
||||
+ return !(this.hasDisplayName() || this.hasLocalizedName() || this.hasEnchants() || (this.lore != null) || this.hasCustomModelData() || this.hasBlockData() || this.hasRepairCost() || !this.unhandledTags.isEmpty() || !this.persistentDataContainer.isEmpty() || this.hideFlag != 0 || this.isUnbreakable() || this.hasDamage() || this.hasAttributeModifiers() || this.hasPlaceableKeys() || this.hasDestroyableKeys()); // Paper - Implement an API for CanPlaceOn and CanDestroy NBT values
|
||||
}
|
||||
|
||||
// Paper start
|
||||
@@ -1181,7 +1289,11 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
&& (this.hideFlag == that.hideFlag)
|
||||
&& (this.isUnbreakable() == that.isUnbreakable())
|
||||
&& (this.hasDamage() ? that.hasDamage() && this.damage == that.damage : !that.hasDamage())
|
||||
- && (this.version == that.version);
|
||||
+ && (this.version == that.version)
|
||||
+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values
|
||||
+ && (this.hasPlaceableKeys() ? that.hasPlaceableKeys() && this.placeableKeys.equals(that.placeableKeys) : !that.hasPlaceableKeys())
|
||||
+ && (this.hasDestroyableKeys() ? that.hasDestroyableKeys() && this.destroyableKeys.equals(that.destroyableKeys) : !that.hasDestroyableKeys());
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1216,6 +1328,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
hash = 61 * hash + (this.hasDamage() ? this.damage : 0);
|
||||
hash = 61 * hash + (this.hasAttributeModifiers() ? this.attributeModifiers.hashCode() : 0);
|
||||
hash = 61 * hash + this.version;
|
||||
+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values
|
||||
+ hash = 61 * hash + (this.hasPlaceableKeys() ? this.placeableKeys.hashCode() : 0);
|
||||
+ hash = 61 * hash + (this.hasDestroyableKeys() ? this.destroyableKeys.hashCode() : 0);
|
||||
+ // Paper end
|
||||
return hash;
|
||||
}
|
||||
|
||||
@@ -1240,6 +1356,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
clone.unbreakable = this.unbreakable;
|
||||
clone.damage = this.damage;
|
||||
clone.version = this.version;
|
||||
+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values
|
||||
+ if (this.placeableKeys != null) {
|
||||
+ clone.placeableKeys = Sets.newHashSet(this.placeableKeys);
|
||||
+ }
|
||||
+ if (this.destroyableKeys != null) {
|
||||
+ clone.destroyableKeys = Sets.newHashSet(this.destroyableKeys);
|
||||
+ }
|
||||
+ // Paper end
|
||||
return clone;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new Error(e);
|
||||
@@ -1297,6 +1421,23 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
builder.put(DAMAGE.BUKKIT, damage);
|
||||
}
|
||||
|
||||
+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values
|
||||
+ if (this.hasPlaceableKeys()) {
|
||||
+ List<String> cerealPlaceable = this.placeableKeys.stream()
|
||||
+ .map(this::serializeNamespaced)
|
||||
+ .collect(java.util.stream.Collectors.toList());
|
||||
+
|
||||
+ builder.put(CAN_PLACE_ON.BUKKIT, cerealPlaceable);
|
||||
+ }
|
||||
+
|
||||
+ if (this.hasDestroyableKeys()) {
|
||||
+ List<String> cerealDestroyable = this.destroyableKeys.stream()
|
||||
+ .map(this::serializeNamespaced)
|
||||
+ .collect(java.util.stream.Collectors.toList());
|
||||
+
|
||||
+ builder.put(CAN_DESTROY.BUKKIT, cerealDestroyable);
|
||||
+ }
|
||||
+ // Paper end
|
||||
final Map<String, Tag> internalTags = new HashMap<String, Tag>(this.unhandledTags);
|
||||
this.serializeInternal(internalTags);
|
||||
if (!internalTags.isEmpty()) {
|
||||
@@ -1469,6 +1610,8 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
CraftMetaArmorStand.SHOW_ARMS.NBT,
|
||||
CraftMetaArmorStand.SMALL.NBT,
|
||||
CraftMetaArmorStand.MARKER.NBT,
|
||||
+ CAN_DESTROY.NBT,
|
||||
+ CAN_PLACE_ON.NBT,
|
||||
// Paper end
|
||||
CraftMetaCompass.LODESTONE_DIMENSION.NBT,
|
||||
CraftMetaCompass.LODESTONE_POS.NBT,
|
||||
@@ -1498,4 +1641,146 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
}
|
||||
// Paper end
|
||||
|
||||
+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values
|
||||
+ @Override
|
||||
+ @SuppressWarnings("deprecation")
|
||||
+ public Set<Material> getCanDestroy() {
|
||||
+ return !hasDestroyableKeys() ? Collections.emptySet() : legacyGetMatsFromKeys(this.destroyableKeys);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ @SuppressWarnings("deprecation")
|
||||
+ public void setCanDestroy(Set<Material> canDestroy) {
|
||||
+ Preconditions.checkArgument(canDestroy != null, "Cannot replace with null set!");
|
||||
+ legacyClearAndReplaceKeys(this.destroyableKeys, canDestroy);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ @SuppressWarnings("deprecation")
|
||||
+ public Set<Material> getCanPlaceOn() {
|
||||
+ return !hasPlaceableKeys() ? Collections.emptySet() : legacyGetMatsFromKeys(this.placeableKeys);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ @SuppressWarnings("deprecation")
|
||||
+ public void setCanPlaceOn(Set<Material> canPlaceOn) {
|
||||
+ Preconditions.checkArgument(canPlaceOn != null, "Cannot replace with null set!");
|
||||
+ legacyClearAndReplaceKeys(this.placeableKeys, canPlaceOn);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Set<Namespaced> getDestroyableKeys() {
|
||||
+ return !hasDestroyableKeys() ? Collections.emptySet() : Sets.newHashSet(this.destroyableKeys);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setDestroyableKeys(Collection<Namespaced> canDestroy) {
|
||||
+ Preconditions.checkArgument(canDestroy != null, "Cannot replace with null collection!");
|
||||
+ Preconditions.checkArgument(ofAcceptableType(canDestroy), "Can only use NamespacedKey or NamespacedTag objects!");
|
||||
+ this.destroyableKeys.clear();
|
||||
+ this.destroyableKeys.addAll(canDestroy);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Set<Namespaced> getPlaceableKeys() {
|
||||
+ return !hasPlaceableKeys() ? Collections.emptySet() : Sets.newHashSet(this.placeableKeys);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setPlaceableKeys(Collection<Namespaced> canPlaceOn) {
|
||||
+ Preconditions.checkArgument(canPlaceOn != null, "Cannot replace with null collection!");
|
||||
+ Preconditions.checkArgument(ofAcceptableType(canPlaceOn), "Can only use NamespacedKey or NamespacedTag objects!");
|
||||
+ this.placeableKeys.clear();
|
||||
+ this.placeableKeys.addAll(canPlaceOn);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean hasPlaceableKeys() {
|
||||
+ return this.placeableKeys != null && !this.placeableKeys.isEmpty();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean hasDestroyableKeys() {
|
||||
+ return this.destroyableKeys != null && !this.destroyableKeys.isEmpty();
|
||||
+ }
|
||||
+
|
||||
+ @Deprecated
|
||||
+ private void legacyClearAndReplaceKeys(Collection<Namespaced> toUpdate, Collection<Material> beingSet) {
|
||||
+ if (beingSet.stream().anyMatch(Material::isLegacy)) {
|
||||
+ throw new IllegalArgumentException("Set must not contain any legacy materials!");
|
||||
+ }
|
||||
+
|
||||
+ toUpdate.clear();
|
||||
+ toUpdate.addAll(beingSet.stream().map(Material::getKey).collect(java.util.stream.Collectors.toSet()));
|
||||
+ }
|
||||
+
|
||||
+ @Deprecated
|
||||
+ private Set<Material> legacyGetMatsFromKeys(Collection<Namespaced> names) {
|
||||
+ Set<Material> mats = Sets.newHashSet();
|
||||
+ for (Namespaced key : names) {
|
||||
+ if (!(key instanceof org.bukkit.NamespacedKey)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ Material material = Material.matchMaterial(key.toString(), false);
|
||||
+ if (material != null) {
|
||||
+ mats.add(material);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return mats;
|
||||
+ }
|
||||
+
|
||||
+ private @Nullable Namespaced deserializeNamespaced(String raw) {
|
||||
+ boolean isTag = raw.length() > 0 && raw.codePointAt(0) == '#';
|
||||
+ com.mojang.datafixers.util.Either<net.minecraft.commands.arguments.blocks.BlockStateParser.BlockResult, net.minecraft.commands.arguments.blocks.BlockStateParser.TagResult> result;
|
||||
+ try {
|
||||
+ result = net.minecraft.commands.arguments.blocks.BlockStateParser.parseForTesting(net.minecraft.core.registries.BuiltInRegistries.BLOCK.asLookup(), raw, false);
|
||||
+ } catch (com.mojang.brigadier.exceptions.CommandSyntaxException e) {
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ net.minecraft.resources.ResourceLocation key = null;
|
||||
+ if (isTag && result.right().isPresent() && result.right().get().tag() instanceof net.minecraft.core.HolderSet.Named<net.minecraft.world.level.block.Block> namedSet) {
|
||||
+ key = namedSet.key().location();
|
||||
+ } else if (result.left().isPresent()) {
|
||||
+ key = net.minecraft.core.registries.BuiltInRegistries.BLOCK.getKey(result.left().get().blockState().getBlock());
|
||||
+ }
|
||||
+
|
||||
+ if (key == null) {
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ // don't DC the player if something slips through somehow
|
||||
+ Namespaced resource = null;
|
||||
+ try {
|
||||
+ if (isTag) {
|
||||
+ resource = new NamespacedTag(key.getNamespace(), key.getPath());
|
||||
+ } else {
|
||||
+ resource = CraftNamespacedKey.fromMinecraft(key);
|
||||
+ }
|
||||
+ } catch (IllegalArgumentException ex) {
|
||||
+ org.bukkit.Bukkit.getLogger().warning("Namespaced resource does not validate: " + key.toString());
|
||||
+ ex.printStackTrace();
|
||||
+ }
|
||||
+
|
||||
+ return resource;
|
||||
+ }
|
||||
+
|
||||
+ private @Nonnull String serializeNamespaced(Namespaced resource) {
|
||||
+ return resource.toString();
|
||||
+ }
|
||||
+
|
||||
+ // not a fan of this
|
||||
+ private boolean ofAcceptableType(Collection<Namespaced> namespacedResources) {
|
||||
+
|
||||
+ for (Namespaced resource : namespacedResources) {
|
||||
+ if (!(resource instanceof org.bukkit.NamespacedKey || resource instanceof com.destroystokyo.paper.NamespacedTag)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 10 Sep 2018 23:56:36 -0400
|
||||
Subject: [PATCH] Prevent Mob AI Rules from Loading Chunks
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java
|
||||
index e3d070d46729c023d594699619a4b3f8658edbce..509317a26c79f453335df1c19dc4c9ec570046af 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java
|
||||
@@ -126,7 +126,9 @@ public class RemoveBlockGoal extends MoveToBlockGoal {
|
||||
|
||||
@Nullable
|
||||
private BlockPos getPosWithBlock(BlockPos pos, BlockGetter world) {
|
||||
- if (world.getBlockState(pos).is(this.blockToRemove)) {
|
||||
+ net.minecraft.world.level.block.state.BlockState block = world.getBlockStateIfLoaded(pos); // Paper
|
||||
+ if (block == null) return null; // Paper
|
||||
+ if (block.is(this.blockToRemove)) { // Paper
|
||||
return pos;
|
||||
} else {
|
||||
BlockPos[] ablockposition = new BlockPos[]{pos.below(), pos.west(), pos.east(), pos.north(), pos.south(), pos.below().below()};
|
||||
@@ -136,7 +138,8 @@ public class RemoveBlockGoal extends MoveToBlockGoal {
|
||||
for (int j = 0; j < i; ++j) {
|
||||
BlockPos blockposition1 = ablockposition1[j];
|
||||
|
||||
- if (world.getBlockState(blockposition1).is(this.blockToRemove)) {
|
||||
+ net.minecraft.world.level.block.state.BlockState block2 = world.getBlockStateIfLoaded(blockposition1); // Paper
|
||||
+ if (block2 != null && block2.is(this.blockToRemove)) { // Paper
|
||||
return blockposition1;
|
||||
}
|
||||
}
|
||||
@@ -147,7 +150,7 @@ public class RemoveBlockGoal extends MoveToBlockGoal {
|
||||
|
||||
@Override
|
||||
protected boolean isValidTarget(LevelReader world, BlockPos pos) {
|
||||
- ChunkAccess ichunkaccess = world.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ()), ChunkStatus.FULL, false);
|
||||
+ ChunkAccess ichunkaccess = world.getChunkIfLoadedImmediately(pos.getX() >> 4, pos.getZ() >> 4); // Paper
|
||||
|
||||
return ichunkaccess == null ? false : ichunkaccess.getBlockState(pos).is(this.blockToRemove) && ichunkaccess.getBlockState(pos.above()).isAir() && ichunkaccess.getBlockState(pos.above(2)).isAir();
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 12 Sep 2018 21:12:57 -0400
|
||||
Subject: [PATCH] Prevent mob spawning from loading/generating chunks
|
||||
|
||||
also prevents if out of world border bounds
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
||||
index 6ac513d3044fab1cb1ca0b0c7e85ff871d49d572..2503d4691e47083a9d99a38c4ed3f50a2374821a 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
||||
@@ -170,9 +170,9 @@ public final class NaturalSpawner {
|
||||
StructureManager structuremanager = world.structureManager();
|
||||
ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator();
|
||||
int i = pos.getY();
|
||||
- BlockState iblockdata = chunk.getBlockState(pos);
|
||||
+ BlockState iblockdata = world.getBlockStateIfLoadedAndInBounds(pos); // Paper - don't load chunks for mob spawn
|
||||
|
||||
- if (!iblockdata.isRedstoneConductor(chunk, pos)) {
|
||||
+ if (iblockdata != null && !iblockdata.isRedstoneConductor(chunk, pos)) { // Paper - don't load chunks for mob spawn
|
||||
BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos();
|
||||
int j = 0;
|
||||
int k = 0;
|
||||
@@ -201,7 +201,7 @@ public final class NaturalSpawner {
|
||||
if (entityhuman != null) {
|
||||
double d2 = entityhuman.distanceToSqr(d0, (double) i, d1);
|
||||
|
||||
- if (NaturalSpawner.isRightDistanceToPlayerAndSpawnPoint(world, chunk, blockposition_mutableblockposition, d2)) {
|
||||
+ if (world.isLoadedAndInBounds(blockposition_mutableblockposition) && NaturalSpawner.isRightDistanceToPlayerAndSpawnPoint(world, chunk, blockposition_mutableblockposition, d2)) { // Paper - don't load chunks for mob spawn
|
||||
if (biomesettingsmobs_c == null) {
|
||||
Optional<MobSpawnSettings.SpawnerData> optional = NaturalSpawner.getRandomSpawnMobAt(world, structuremanager, chunkgenerator, group, world.random, blockposition_mutableblockposition);
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tassu <git@tassu.me>
|
||||
Date: Thu, 13 Sep 2018 08:45:21 +0300
|
||||
Subject: [PATCH] Implement furnace cook speed multiplier API
|
||||
|
||||
Signed-off-by: Tassu <git@tassu.me>
|
||||
|
||||
Fixed an issue where a furnace's cook-speed multiplier rounds down
|
||||
to the nearest Integer when updating its current cook time.
|
||||
|
||||
Modified by: Eric Su <ericsu@alumni.usc.edu>
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
||||
index d56a64b058d8848e405e33d9884a61ea952a8f71..40dc29288a13ae9c1f8b0434922fdb5c7d02daa9 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
||||
@@ -77,11 +77,13 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
|
||||
protected NonNullList<ItemStack> items;
|
||||
public int litTime;
|
||||
int litDuration;
|
||||
+ public double cookSpeedMultiplier = 1.0; // Paper - cook speed multiplier API
|
||||
public int cookingProgress;
|
||||
public int cookingTotalTime;
|
||||
protected final ContainerData dataAccess;
|
||||
public final Object2IntOpenHashMap<ResourceLocation> recipesUsed;
|
||||
private final RecipeManager.CachedCheck<Container, ? extends AbstractCookingRecipe> quickCheck;
|
||||
+ public final RecipeType<? extends AbstractCookingRecipe> recipeType; // Paper
|
||||
|
||||
protected AbstractFurnaceBlockEntity(BlockEntityType<?> blockEntityType, BlockPos pos, BlockState state, RecipeType<? extends AbstractCookingRecipe> recipeType) {
|
||||
super(blockEntityType, pos, state);
|
||||
@@ -128,6 +130,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
|
||||
};
|
||||
this.recipesUsed = new Object2IntOpenHashMap();
|
||||
this.quickCheck = RecipeManager.createCheck((RecipeType<AbstractCookingRecipe>) recipeType); // CraftBukkit - decompile error // Eclipse fail
|
||||
+ this.recipeType = recipeType; // Paper
|
||||
}
|
||||
|
||||
public static Map<Item, Integer> getFuel() {
|
||||
@@ -280,6 +283,11 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
|
||||
this.recipesUsed.put(new ResourceLocation(s), nbttagcompound1.getInt(s));
|
||||
}
|
||||
|
||||
+ // Paper start - cook speed API
|
||||
+ if (nbt.contains("Paper.CookSpeedMultiplier")) {
|
||||
+ this.cookSpeedMultiplier = nbt.getDouble("Paper.CookSpeedMultiplier");
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -288,6 +296,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
|
||||
nbt.putShort("BurnTime", (short) this.litTime);
|
||||
nbt.putShort("CookTime", (short) this.cookingProgress);
|
||||
nbt.putShort("CookTimeTotal", (short) this.cookingTotalTime);
|
||||
+ nbt.putDouble("Paper.CookSpeedMultiplier", this.cookSpeedMultiplier); // Paper - cook speed multiplier API
|
||||
ContainerHelper.saveAllItems(nbt, this.items);
|
||||
CompoundTag nbttagcompound1 = new CompoundTag();
|
||||
|
||||
@@ -359,7 +368,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
|
||||
CraftItemStack source = CraftItemStack.asCraftMirror(blockEntity.items.get(0));
|
||||
CookingRecipe<?> recipe = (CookingRecipe<?>) irecipe.toBukkitRecipe();
|
||||
|
||||
- FurnaceStartSmeltEvent event = new FurnaceStartSmeltEvent(CraftBlock.at(world, pos), source, recipe);
|
||||
+ FurnaceStartSmeltEvent event = new FurnaceStartSmeltEvent(CraftBlock.at(world, pos), source, recipe, AbstractFurnaceBlockEntity.getTotalCookTime(world, blockEntity.recipeType, blockEntity, blockEntity.cookSpeedMultiplier)); // Paper - cook speed multiplier API
|
||||
world.getCraftServer().getPluginManager().callEvent(event);
|
||||
|
||||
blockEntity.cookingTotalTime = event.getTotalCookTime();
|
||||
@@ -367,9 +376,9 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
|
||||
// CraftBukkit end
|
||||
|
||||
++blockEntity.cookingProgress;
|
||||
- if (blockEntity.cookingProgress == blockEntity.cookingTotalTime) {
|
||||
+ if (blockEntity.cookingProgress >= blockEntity.cookingTotalTime) { // Paper - cook speed multiplier API
|
||||
blockEntity.cookingProgress = 0;
|
||||
- blockEntity.cookingTotalTime = AbstractFurnaceBlockEntity.getTotalCookTime(world, blockEntity);
|
||||
+ blockEntity.cookingTotalTime = AbstractFurnaceBlockEntity.getTotalCookTime(world, blockEntity.recipeType, blockEntity, blockEntity.cookSpeedMultiplier); // Paper
|
||||
if (AbstractFurnaceBlockEntity.burn(blockEntity.level, blockEntity.worldPosition, world.registryAccess(), irecipe, blockEntity.items, i)) { // CraftBukkit
|
||||
blockEntity.setRecipeUsed(irecipe);
|
||||
}
|
||||
@@ -469,9 +478,13 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
|
||||
}
|
||||
}
|
||||
|
||||
- private static int getTotalCookTime(Level world, AbstractFurnaceBlockEntity furnace) {
|
||||
- return (world != null) ? (Integer) furnace.quickCheck.getRecipeFor(furnace, world).map(AbstractCookingRecipe::getCookingTime).orElse(200) : 200; // CraftBukkit - SPIGOT-4302
|
||||
+ // Paper start
|
||||
+ public static int getTotalCookTime(@Nullable Level world, RecipeType<? extends AbstractCookingRecipe> recipeType, AbstractFurnaceBlockEntity furnace, double cookSpeedMultiplier) {
|
||||
+ /* Scale the recipe's cooking time to the current cookSpeedMultiplier */
|
||||
+ int cookTime = world != null ? furnace.quickCheck.getRecipeFor(furnace, world).map(AbstractCookingRecipe::getCookingTime).orElse(200) : (net.minecraft.server.MinecraftServer.getServer().getRecipeManager().getRecipeFor(recipeType, furnace, world /* passing a null level here is safe. world is only used for map extending recipes which won't happen here */).map(AbstractCookingRecipe::getCookingTime).orElse(200));
|
||||
+ return (int) Math.ceil (cookTime / cookSpeedMultiplier);
|
||||
}
|
||||
+ // Paper end
|
||||
|
||||
public static boolean isFuel(ItemStack stack) {
|
||||
return AbstractFurnaceBlockEntity.getFuel().containsKey(stack.getItem());
|
||||
@@ -540,7 +553,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
|
||||
}
|
||||
|
||||
if (slot == 0 && !flag) {
|
||||
- this.cookingTotalTime = AbstractFurnaceBlockEntity.getTotalCookTime(this.level, this);
|
||||
+ this.cookingTotalTime = AbstractFurnaceBlockEntity.getTotalCookTime(this.level, this.recipeType, this, this.cookSpeedMultiplier); // Paper
|
||||
this.cookingProgress = 0;
|
||||
this.setChanged();
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java b/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java
|
||||
index facf95a44b5d3a63fda156c6afc8cabe50b21d32..3da4616c904d47bbecae0d4cb6970496fbec9a8b 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java
|
||||
@@ -78,4 +78,20 @@ public abstract class CraftFurnace<T extends AbstractFurnaceBlockEntity> extends
|
||||
|
||||
return recipesUsed.build();
|
||||
}
|
||||
+
|
||||
+ // Paper start - cook speed multiplier API
|
||||
+ @Override
|
||||
+ public double getCookSpeedMultiplier() {
|
||||
+ return this.getSnapshot().cookSpeedMultiplier;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setCookSpeedMultiplier(double multiplier) {
|
||||
+ com.google.common.base.Preconditions.checkArgument(multiplier >= 0, "Furnace speed multiplier cannot be negative");
|
||||
+ com.google.common.base.Preconditions.checkArgument(multiplier <= 200, "Furnace speed multiplier cannot more than 200");
|
||||
+ T snapshot = this.getSnapshot();
|
||||
+ snapshot.cookSpeedMultiplier = multiplier;
|
||||
+ snapshot.cookingTotalTime = AbstractFurnaceBlockEntity.getTotalCookTime(this.isPlaced() ? this.world.getHandle() : null, snapshot.recipeType, snapshot, snapshot.cookSpeedMultiplier); // Update the snapshot's current total cook time to scale with the newly set multiplier
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Sun, 23 Sep 2018 20:59:53 -0500
|
||||
Subject: [PATCH] Honor EntityAgeable.ageLock
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/AgeableMob.java b/src/main/java/net/minecraft/world/entity/AgeableMob.java
|
||||
index be5e603d505566feac61cc7e591d35ce483a92df..2061d7ae62c1335c87aa67fd0cc004c42e34e3a7 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/AgeableMob.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/AgeableMob.java
|
||||
@@ -85,6 +85,7 @@ public abstract class AgeableMob extends PathfinderMob {
|
||||
}
|
||||
|
||||
public void ageUp(int age, boolean overGrow) {
|
||||
+ if (this.ageLocked) return; // Paper - GH-1459
|
||||
int j = this.getAge();
|
||||
int k = j;
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java
|
||||
index bd70aa9448a429f813f494c02d09432532985152..ea63802f2644bc2b5b3b0c72d7d09813cb68139d 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java
|
||||
@@ -299,6 +299,7 @@ public class BeehiveBlockEntity extends BlockEntity {
|
||||
}
|
||||
|
||||
private static void setBeeReleaseData(int ticks, Bee bee) {
|
||||
+ if (!bee.ageLocked) { // Paper - respect age lock
|
||||
int j = bee.getAge();
|
||||
|
||||
if (j < 0) {
|
||||
@@ -306,6 +307,7 @@ public class BeehiveBlockEntity extends BlockEntity {
|
||||
} else if (j > 0) {
|
||||
bee.setAge(Math.max(0, j - ticks));
|
||||
}
|
||||
+ } // Paper - respect age lock
|
||||
|
||||
bee.setInLoveTime(Math.max(0, bee.getInLoveTime() - ticks));
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Tue, 2 Oct 2018 09:57:50 +0100
|
||||
Subject: [PATCH] Configurable connection throttle kick message
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
|
||||
index a3b610cb1ed97a635677bc46ccdf0463c9918585..94b062874ef9d4935a7ad2c7b45b2e6b786eaa81 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
|
||||
@@ -51,7 +51,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL
|
||||
synchronized (ServerHandshakePacketListenerImpl.throttleTracker) {
|
||||
if (ServerHandshakePacketListenerImpl.throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - ServerHandshakePacketListenerImpl.throttleTracker.get(address) < connectionThrottle) {
|
||||
ServerHandshakePacketListenerImpl.throttleTracker.put(address, currentTime);
|
||||
- MutableComponent chatmessage = Component.literal("Connection throttled! Please wait before reconnecting.");
|
||||
+ Component chatmessage = io.papermc.paper.adventure.PaperAdventure.asVanilla(io.papermc.paper.configuration.GlobalConfiguration.get().messages.kick.connectionThrottle); // Paper - Configurable connection throttle kick message
|
||||
this.connection.send(new ClientboundLoginDisconnectPacket(chatmessage));
|
||||
this.connection.disconnect(chatmessage);
|
||||
return;
|
|
@ -1,76 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 10 Sep 2018 23:36:16 -0400
|
||||
Subject: [PATCH] Prevent chunk loading from Fluid Flowing
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/material/FlowingFluid.java b/src/main/java/net/minecraft/world/level/material/FlowingFluid.java
|
||||
index fbf699e777d45db3dcf1606d34f509ca1a5bbb7a..c694b16be7c276fbf34aed2fd2aa6d6b79625561 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/material/FlowingFluid.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/material/FlowingFluid.java
|
||||
@@ -175,7 +175,8 @@ public abstract class FlowingFluid extends Fluid {
|
||||
Direction enumdirection = (Direction) entry.getKey();
|
||||
FluidState fluid1 = (FluidState) entry.getValue();
|
||||
BlockPos blockposition1 = pos.relative(enumdirection);
|
||||
- BlockState iblockdata1 = world.getBlockState(blockposition1);
|
||||
+ BlockState iblockdata1 = world.getBlockStateIfLoaded(blockposition1); // Paper
|
||||
+ if (iblockdata1 == null) continue; // Paper
|
||||
|
||||
if (this.canSpreadTo(world, pos, blockState, enumdirection, blockposition1, iblockdata1, world.getFluidState(blockposition1), fluid1.getType())) {
|
||||
// CraftBukkit start
|
||||
@@ -202,7 +203,9 @@ public abstract class FlowingFluid extends Fluid {
|
||||
while (iterator.hasNext()) {
|
||||
Direction enumdirection = (Direction) iterator.next();
|
||||
BlockPos blockposition1 = pos.relative(enumdirection);
|
||||
- BlockState iblockdata1 = world.getBlockState(blockposition1);
|
||||
+
|
||||
+ BlockState iblockdata1 = world.getBlockStateIfLoaded(blockposition1); // Paper
|
||||
+ if (iblockdata1 == null) continue; // Paper
|
||||
FluidState fluid = iblockdata1.getFluidState();
|
||||
|
||||
if (fluid.getType().isSame(this) && this.canPassThroughWall(enumdirection, world, pos, state, blockposition1, iblockdata1)) {
|
||||
@@ -319,11 +322,18 @@ public abstract class FlowingFluid extends Fluid {
|
||||
if (enumdirection1 != direction) {
|
||||
BlockPos blockposition2 = pos.relative(enumdirection1);
|
||||
short short0 = FlowingFluid.getCacheKey(fromPos, blockposition2);
|
||||
- Pair<BlockState, FluidState> pair = (Pair) stateCache.computeIfAbsent(short0, (short1) -> {
|
||||
- BlockState iblockdata1 = world.getBlockState(blockposition2);
|
||||
+ // Paper start - avoid loading chunks
|
||||
+ Pair<BlockState, FluidState> pair = stateCache.get(short0);
|
||||
+ if (pair == null) {
|
||||
+ BlockState iblockdatax = world.getBlockStateIfLoaded(blockposition2);
|
||||
+ if (iblockdatax == null) {
|
||||
+ continue;
|
||||
+ }
|
||||
|
||||
- return Pair.of(iblockdata1, iblockdata1.getFluidState());
|
||||
- });
|
||||
+ pair = Pair.of(iblockdatax, iblockdatax.getFluidState());
|
||||
+ stateCache.put(short0, pair);
|
||||
+ }
|
||||
+ // Paper end
|
||||
BlockState iblockdata1 = (BlockState) pair.getFirst();
|
||||
FluidState fluid = (FluidState) pair.getSecond();
|
||||
|
||||
@@ -395,11 +405,16 @@ public abstract class FlowingFluid extends Fluid {
|
||||
Direction enumdirection = (Direction) iterator.next();
|
||||
BlockPos blockposition1 = pos.relative(enumdirection);
|
||||
short short0 = FlowingFluid.getCacheKey(pos, blockposition1);
|
||||
- Pair<BlockState, FluidState> pair = (Pair) short2objectmap.computeIfAbsent(short0, (short1) -> {
|
||||
- BlockState iblockdata1 = world.getBlockState(blockposition1);
|
||||
-
|
||||
- return Pair.of(iblockdata1, iblockdata1.getFluidState());
|
||||
- });
|
||||
+ // Paper start
|
||||
+ Pair pair = (Pair) short2objectmap.get(short0);
|
||||
+ if (pair == null) {
|
||||
+ BlockState iblockdatax = world.getBlockStateIfLoaded(blockposition1);
|
||||
+ if (iblockdatax == null) continue;
|
||||
+
|
||||
+ pair = Pair.of(iblockdatax, iblockdatax.getFluidState());
|
||||
+ short2objectmap.put(short0, pair);
|
||||
+ }
|
||||
+ // Paper end
|
||||
BlockState iblockdata1 = (BlockState) pair.getFirst();
|
||||
FluidState fluid = (FluidState) pair.getSecond();
|
||||
FluidState fluid1 = this.getNewLiquid(world, blockposition1, iblockdata1);
|
|
@ -1,194 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach@zachbr.io>
|
||||
Date: Wed, 3 Oct 2018 20:09:18 -0400
|
||||
Subject: [PATCH] Hook into CB plugin rewrites
|
||||
|
||||
Allows us to do fun stuff like rewrite the OBC util fastutil location to
|
||||
our own relocation. Also lets us rewrite NMS calls for when we're
|
||||
debugging in an IDE pre-relocate.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java
|
||||
index 48cdd483c25825571043800f3cfa41a4d723f649..fe5d3b60ad740b7f1cce040f9c8d96ac51245ef6 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java
|
||||
@@ -6,7 +6,9 @@ import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Enumeration;
|
||||
+import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
+import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
@@ -20,10 +22,15 @@ import org.bukkit.plugin.AuthorNagException;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
+import org.objectweb.asm.FieldVisitor;
|
||||
+import org.objectweb.asm.Handle;
|
||||
+import org.objectweb.asm.Label;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
|
||||
+import javax.annotation.Nonnull;
|
||||
+
|
||||
/**
|
||||
* This file is imported from Commodore.
|
||||
*
|
||||
@@ -46,6 +53,41 @@ public class Commodore
|
||||
"org/bukkit/inventory/ItemStack (I)V setTypeId"
|
||||
) );
|
||||
|
||||
+ // Paper start - Plugin rewrites
|
||||
+ private static final Map<String, String> SEARCH_AND_REMOVE = initReplacementsMap();
|
||||
+ private static Map<String, String> initReplacementsMap()
|
||||
+ {
|
||||
+ Map<String, String> getAndRemove = new HashMap<>();
|
||||
+ // Be wary of maven shade's relocations
|
||||
+
|
||||
+ final java.util.jar.Manifest manifest = io.papermc.paper.util.JarManifests.manifest(Commodore.class);
|
||||
+ if ( Boolean.getBoolean( "debug.rewriteForIde" ) && manifest != null)
|
||||
+ {
|
||||
+ // unversion incoming calls for pre-relocate debug work
|
||||
+ final String NMS_REVISION_PACKAGE = "v" + manifest.getMainAttributes().getValue("CraftBukkit-Package-Version") + "/";
|
||||
+
|
||||
+ getAndRemove.put( "org/bukkit/".concat( "craftbukkit/" + NMS_REVISION_PACKAGE ), NMS_REVISION_PACKAGE );
|
||||
+ }
|
||||
+
|
||||
+ return getAndRemove;
|
||||
+ }
|
||||
+
|
||||
+ @Nonnull
|
||||
+ private static String getOriginalOrRewrite(@Nonnull String original)
|
||||
+ {
|
||||
+ String rewrite = null;
|
||||
+ for ( Map.Entry<String, String> entry : SEARCH_AND_REMOVE.entrySet() )
|
||||
+ {
|
||||
+ if ( original.contains( entry.getKey() ) )
|
||||
+ {
|
||||
+ rewrite = original.replace( entry.getValue(), "" );
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return rewrite != null ? rewrite : original;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
public static void main(String[] args)
|
||||
{
|
||||
OptionParser parser = new OptionParser();
|
||||
@@ -130,15 +172,86 @@ public class Commodore
|
||||
|
||||
cr.accept( new ClassVisitor( Opcodes.ASM9, cw )
|
||||
{
|
||||
+ // Paper start - Rewrite plugins
|
||||
+ @Override
|
||||
+ public FieldVisitor visitField(int access, String name, String desc, String signature, Object value)
|
||||
+ {
|
||||
+ desc = getOriginalOrRewrite( desc );
|
||||
+ if ( signature != null ) {
|
||||
+ signature = getOriginalOrRewrite( signature );
|
||||
+ }
|
||||
+
|
||||
+ return super.visitField( access, name, desc, signature, value) ;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions)
|
||||
{
|
||||
return new MethodVisitor( api, super.visitMethod( access, name, desc, signature, exceptions ) )
|
||||
{
|
||||
+ // Paper start - Plugin rewrites
|
||||
+ @Override
|
||||
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bootstrapMethodHandle, Object... bootstrapMethodArguments)
|
||||
+ {
|
||||
+ // Paper start - Rewrite plugins
|
||||
+ name = getOriginalOrRewrite( name );
|
||||
+ if ( desc != null )
|
||||
+ {
|
||||
+ desc = getOriginalOrRewrite( desc );
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
+ super.visitInvokeDynamicInsn( name, desc, bootstrapMethodHandle, bootstrapMethodArguments );
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void visitTypeInsn(int opcode, String type)
|
||||
+ {
|
||||
+ type = getOriginalOrRewrite( type );
|
||||
+
|
||||
+ super.visitTypeInsn( opcode, type );
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
|
||||
+ for ( int i = 0; i < local.length; i++ )
|
||||
+ {
|
||||
+ if ( !( local[i] instanceof String ) ) { continue; }
|
||||
+
|
||||
+ local[i] = getOriginalOrRewrite( (String) local[i] );
|
||||
+ }
|
||||
+
|
||||
+ for ( int i = 0; i < stack.length; i++ )
|
||||
+ {
|
||||
+ if ( !( stack[i] instanceof String ) ) { continue; }
|
||||
+
|
||||
+ stack[i] = getOriginalOrRewrite( (String) stack[i] );
|
||||
+ }
|
||||
+
|
||||
+ super.visitFrame( type, nLocal, local, nStack, stack );
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index)
|
||||
+ {
|
||||
+ descriptor = getOriginalOrRewrite( descriptor );
|
||||
+
|
||||
+ super.visitLocalVariable( name, descriptor, signature, start, end, index );
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
@Override
|
||||
public void visitFieldInsn(int opcode, String owner, String name, String desc)
|
||||
{
|
||||
+ // Paper start - Rewrite plugins
|
||||
+ owner = getOriginalOrRewrite( owner );
|
||||
+ if ( desc != null )
|
||||
+ {
|
||||
+ desc = getOriginalOrRewrite( desc );
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
if ( owner.equals( "org/bukkit/block/Biome" ) )
|
||||
{
|
||||
switch ( name )
|
||||
@@ -330,6 +443,11 @@ public class Commodore
|
||||
}
|
||||
|
||||
// Paper start - Rewrite plugins
|
||||
+ owner = getOriginalOrRewrite( owner) ;
|
||||
+ if (desc != null)
|
||||
+ {
|
||||
+ desc = getOriginalOrRewrite(desc);
|
||||
+ }
|
||||
if ((owner.equals("org/bukkit/OfflinePlayer") || owner.equals("org/bukkit/entity/Player")) && name.equals("getPlayerProfile") && desc.equals("()Lorg/bukkit/profile/PlayerProfile;")) {
|
||||
super.visitMethodInsn(opcode, owner, name, "()Lcom/destroystokyo/paper/profile/PlayerProfile;", itf);
|
||||
return;
|
||||
@@ -424,6 +542,13 @@ public class Commodore
|
||||
@Override
|
||||
public void visitLdcInsn(Object value)
|
||||
{
|
||||
+ // Paper start
|
||||
+ if (value instanceof Type type) {
|
||||
+ if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
|
||||
+ value = Type.getType(getOriginalOrRewrite(type.getDescriptor()));
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
if ( value instanceof String && ( (String) value ).equals( "com.mysql.jdbc.Driver" ) )
|
||||
{
|
||||
super.visitLdcInsn( "com.mysql.cj.jdbc.Driver" );
|
|
@ -1,29 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Phoenix616 <mail@moep.tv>
|
||||
Date: Tue, 18 Sep 2018 23:53:23 +0100
|
||||
Subject: [PATCH] PreSpawnerSpawnEvent
|
||||
|
||||
This adds a separate event before an entity is spawned by a spawner
|
||||
which contains the location of the spawner too similarly to how the
|
||||
SpawnerSpawnEvent gets called instead of the CreatureSpawnEvent for
|
||||
spawners.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java
|
||||
index fc7719d12b5f6011aec2e41a36b4bacd77672b6d..a9be524edb03c51300bc45d424fcf87c7491a8c0 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java
|
||||
@@ -134,11 +134,11 @@ public abstract class BaseSpawner {
|
||||
|
||||
org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(key);
|
||||
if (type != null) {
|
||||
- com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event;
|
||||
- event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent(
|
||||
+ com.destroystokyo.paper.event.entity.PreSpawnerSpawnEvent event;
|
||||
+ event = new com.destroystokyo.paper.event.entity.PreSpawnerSpawnEvent(
|
||||
io.papermc.paper.util.MCUtil.toLocation(world, d0, d1, d2),
|
||||
type,
|
||||
- org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER
|
||||
+ io.papermc.paper.util.MCUtil.toLocation(world, pos)
|
||||
);
|
||||
if (!event.callEvent()) {
|
||||
flag = true;
|
|
@ -1,108 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Sat, 22 Sep 2018 00:33:08 -0500
|
||||
Subject: [PATCH] Add LivingEntity#getTargetEntity
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index d84375984c67a8ad2790efc1c584f7e2f995633e..f800b3e4debcd141a75de9e6025a87e81cee083c 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -116,6 +116,7 @@ import net.minecraft.world.level.storage.loot.LootTable;
|
||||
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets;
|
||||
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
+import net.minecraft.world.phys.EntityHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraft.world.scores.PlayerTeam;
|
||||
@@ -3833,6 +3834,38 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
return this.level().clip(raytrace);
|
||||
}
|
||||
|
||||
+ public @Nullable EntityHitResult getTargetEntity(int maxDistance) {
|
||||
+ if (maxDistance < 1 || maxDistance > 120) {
|
||||
+ throw new IllegalArgumentException("maxDistance must be between 1-120");
|
||||
+ }
|
||||
+
|
||||
+ Vec3 start = this.getEyePosition(1.0F);
|
||||
+ Vec3 direction = this.getLookAngle();
|
||||
+ Vec3 end = start.add(direction.x * maxDistance, direction.y * maxDistance, direction.z * maxDistance);
|
||||
+
|
||||
+ List<Entity> entityList = this.level().getEntities(this, getBoundingBox().expandTowards(direction.x * maxDistance, direction.y * maxDistance, direction.z * maxDistance).inflate(1.0D, 1.0D, 1.0D), EntitySelector.NO_SPECTATORS.and(Entity::isPickable));
|
||||
+
|
||||
+ double distance = 0.0D;
|
||||
+ EntityHitResult result = null;
|
||||
+
|
||||
+ for (Entity entity : entityList) {
|
||||
+ final double inflationAmount = (double) entity.getPickRadius();
|
||||
+ AABB aabb = entity.getBoundingBox().inflate(inflationAmount, inflationAmount, inflationAmount);
|
||||
+ Optional<Vec3> rayTraceResult = aabb.clip(start, end);
|
||||
+
|
||||
+ if (rayTraceResult.isPresent()) {
|
||||
+ Vec3 rayTrace = rayTraceResult.get();
|
||||
+ double distanceTo = start.distanceToSqr(rayTrace);
|
||||
+ if (distanceTo < distance || distance == 0.0D) {
|
||||
+ result = new EntityHitResult(entity, rayTrace);
|
||||
+ distance = distanceTo;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return result;
|
||||
+ }
|
||||
+
|
||||
public int shieldBlockingDelay = this.level().paperConfig().misc.shieldBlockingDelay;
|
||||
|
||||
public int getShieldBlockingDelay() {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
|
||||
index 0707329670292551d966afe30818f17d079fcb3b..2913ad431b09a75106115257729960f8ba1637f4 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.bukkit.craftbukkit.entity;
|
||||
|
||||
+import com.destroystokyo.paper.entity.TargetEntityInfo;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.Sets;
|
||||
import java.util.ArrayList;
|
||||
@@ -226,6 +227,39 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
+
|
||||
+ public Entity getTargetEntity(int maxDistance, boolean ignoreBlocks) {
|
||||
+ net.minecraft.world.phys.EntityHitResult rayTrace = rayTraceEntity(maxDistance, ignoreBlocks);
|
||||
+ return rayTrace == null ? null : rayTrace.getEntity().getBukkitEntity();
|
||||
+ }
|
||||
+
|
||||
+ public TargetEntityInfo getTargetEntityInfo(int maxDistance, boolean ignoreBlocks) {
|
||||
+ net.minecraft.world.phys.EntityHitResult rayTrace = rayTraceEntity(maxDistance, ignoreBlocks);
|
||||
+ return rayTrace == null ? null : new TargetEntityInfo(rayTrace.getEntity().getBukkitEntity(), new org.bukkit.util.Vector(rayTrace.getLocation().x, rayTrace.getLocation().y, rayTrace.getLocation().z));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public RayTraceResult rayTraceEntities(int maxDistance, boolean ignoreBlocks) {
|
||||
+ net.minecraft.world.phys.EntityHitResult rayTrace = this.rayTraceEntity(maxDistance, ignoreBlocks);
|
||||
+ return rayTrace == null ? null : new org.bukkit.util.RayTraceResult(org.bukkit.craftbukkit.util.CraftVector.toBukkit(rayTrace.getLocation()), rayTrace.getEntity().getBukkitEntity());
|
||||
+ }
|
||||
+
|
||||
+ public net.minecraft.world.phys.EntityHitResult rayTraceEntity(int maxDistance, boolean ignoreBlocks) {
|
||||
+ net.minecraft.world.phys.EntityHitResult rayTrace = getHandle().getTargetEntity(maxDistance);
|
||||
+ if (rayTrace == null) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ if (!ignoreBlocks) {
|
||||
+ net.minecraft.world.phys.HitResult rayTraceBlocks = getHandle().getRayTrace(maxDistance, net.minecraft.world.level.ClipContext.Fluid.NONE);
|
||||
+ if (rayTraceBlocks != null) {
|
||||
+ net.minecraft.world.phys.Vec3 eye = getHandle().getEyePosition(1.0F);
|
||||
+ if (eye.distanceToSqr(rayTraceBlocks.getLocation()) <= eye.distanceToSqr(rayTrace.getLocation())) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return rayTrace;
|
||||
+ }
|
||||
// Paper end
|
||||
|
||||
@Override
|
|
@ -1,42 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Sun, 7 Oct 2018 00:54:21 -0500
|
||||
Subject: [PATCH] Add sun related API
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.entity.Mob isSunBurnTick()Z
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
index 57f9324aa73be4fcbb9668ef7be6b6e64d57800e..be17e1a4afc2fd5490a59aa7bcb199fb61643d35 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
@@ -692,6 +692,13 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public boolean isDayTime() {
|
||||
+ return getHandle().isDay();
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public long getGameTime() {
|
||||
return world.levelData.getGameTime();
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java
|
||||
index f36713771598ac5afdae5d94db10a5790949611d..c92f7f31c3bf96f22fb1d2e783b14b80512448a0 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java
|
||||
@@ -93,4 +93,11 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob {
|
||||
public long getSeed() {
|
||||
return this.getHandle().lootTableSeed;
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public boolean isInDaylight() {
|
||||
+ return getHandle().isSunBurnTick();
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
|
@ -1,114 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach.brown@destroystokyo.com>
|
||||
Date: Sat, 22 Sep 2018 15:56:59 -0400
|
||||
Subject: [PATCH] Catch JsonParseException in Entity and TE names
|
||||
|
||||
As a result, data that no longer parses correctly will not crash the server
|
||||
instead just logging the exception and continuing (and in most cases should
|
||||
fix the data)
|
||||
|
||||
Player data is fixed pretty much immediately but some block data (like
|
||||
Shulkers) may need to be changed in order for it to re-save properly
|
||||
|
||||
No more crashing though.
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/util/MCUtil.java b/src/main/java/io/papermc/paper/util/MCUtil.java
|
||||
index 82a1a87822e3fc323b92e1aa30ddb0cdb351d89c..c69088a2ec374b2d236fec61e267f42afa2967b1 100644
|
||||
--- a/src/main/java/io/papermc/paper/util/MCUtil.java
|
||||
+++ b/src/main/java/io/papermc/paper/util/MCUtil.java
|
||||
@@ -18,6 +18,8 @@ import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
+import net.minecraft.nbt.CompoundTag;
|
||||
+import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ChunkHolder;
|
||||
import net.minecraft.server.level.ChunkMap;
|
||||
import net.minecraft.server.level.DistanceManager;
|
||||
@@ -551,6 +553,21 @@ public final class MCUtil {
|
||||
}
|
||||
}
|
||||
|
||||
+ @Nullable
|
||||
+ public static Component getBaseComponentFromNbt(String key, CompoundTag compound) {
|
||||
+ if (!compound.contains(key)) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ String string = compound.getString(key);
|
||||
+ try {
|
||||
+ return Component.Serializer.fromJson(string);
|
||||
+ } catch (com.google.gson.JsonParseException e) {
|
||||
+ org.bukkit.Bukkit.getLogger().warning("Unable to parse " + key + " from " + compound +": " + e.getMessage());
|
||||
+ }
|
||||
+
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
public static ChunkStatus getChunkStatus(ChunkHolder chunk) {
|
||||
return chunk.getChunkHolderStatus();
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/BaseCommandBlock.java b/src/main/java/net/minecraft/world/level/BaseCommandBlock.java
|
||||
index 7f1efe0d9bc059a86166e8e3c5ef4ad23217f6a7..9c7b7434ccd64668eb5d7bb61d03a9cb4105ea6e 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/BaseCommandBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/BaseCommandBlock.java
|
||||
@@ -72,7 +72,7 @@ public abstract class BaseCommandBlock implements CommandSource {
|
||||
this.command = nbt.getString("Command");
|
||||
this.successCount = nbt.getInt("SuccessCount");
|
||||
if (nbt.contains("CustomName", 8)) {
|
||||
- this.setName(Component.Serializer.fromJson(nbt.getString("CustomName")));
|
||||
+ this.setName(io.papermc.paper.util.MCUtil.getBaseComponentFromNbt("CustomName", nbt)); // Paper - Catch ParseException
|
||||
}
|
||||
|
||||
if (nbt.contains("TrackOutput", 1)) {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BannerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BannerBlockEntity.java
|
||||
index 6b983e3e867bdd8cdffaf4575bbf67ad96b57ec7..66e2137f9379e885294f2b9f67f7e35296792770 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/BannerBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/BannerBlockEntity.java
|
||||
@@ -98,7 +98,7 @@ public class BannerBlockEntity extends BlockEntity implements Nameable {
|
||||
public void load(CompoundTag nbt) {
|
||||
super.load(nbt);
|
||||
if (nbt.contains("CustomName", 8)) {
|
||||
- this.name = Component.Serializer.fromJson(nbt.getString("CustomName"));
|
||||
+ this.name = io.papermc.paper.util.MCUtil.getBaseComponentFromNbt("CustomName", nbt); // Paper - Catch ParseException
|
||||
}
|
||||
|
||||
this.itemPatterns = nbt.getList("Patterns", 10);
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
|
||||
index e85022b31f2bc2783e88f5ba4c5173ac8a096c96..f1acd19432877a833f0d4339f9de4830a0f7b890 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
|
||||
@@ -31,7 +31,7 @@ public abstract class BaseContainerBlockEntity extends BlockEntity implements Co
|
||||
super.load(nbt);
|
||||
this.lockKey = LockCode.fromTag(nbt);
|
||||
if (nbt.contains("CustomName", 8)) {
|
||||
- this.name = Component.Serializer.fromJson(nbt.getString("CustomName"));
|
||||
+ this.name = io.papermc.paper.util.MCUtil.getBaseComponentFromNbt("CustomName", nbt); // Paper - Catch ParseException
|
||||
}
|
||||
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
|
||||
index 8b79df496e1fad57e8c5c0aa97d0d84ab0deed1e..154e4652a93b50e9b26c93531a4e854601ed75e1 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
|
||||
@@ -367,7 +367,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name
|
||||
this.levels = nbt.getInt("Levels"); // SPIGOT-5053, use where available
|
||||
// CraftBukkit end
|
||||
if (nbt.contains("CustomName", 8)) {
|
||||
- this.name = Component.Serializer.fromJson(nbt.getString("CustomName"));
|
||||
+ this.name = io.papermc.paper.util.MCUtil.getBaseComponentFromNbt("CustomName", nbt); // Paper - Catch ParseException
|
||||
}
|
||||
|
||||
this.lockKey = LockCode.fromTag(nbt);
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/EnchantmentTableBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/EnchantmentTableBlockEntity.java
|
||||
index 3a8bdb788b07b0a8cda3d4b872ede52ca9a005c4..65e1381bb2d10bd212463feb602c60f8fdb9ade1 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/EnchantmentTableBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/EnchantmentTableBlockEntity.java
|
||||
@@ -42,7 +42,7 @@ public class EnchantmentTableBlockEntity extends BlockEntity implements Nameable
|
||||
public void load(CompoundTag nbt) {
|
||||
super.load(nbt);
|
||||
if (nbt.contains("CustomName", 8)) {
|
||||
- this.name = Component.Serializer.fromJson(nbt.getString("CustomName"));
|
||||
+ this.name = io.papermc.paper.util.MCUtil.getBaseComponentFromNbt("CustomName", nbt); // Paper - Catch ParseException
|
||||
}
|
||||
|
||||
}
|
|
@ -1,97 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Sat, 29 Sep 2018 16:08:23 -0500
|
||||
Subject: [PATCH] Turtle API
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.entity.animal.Turtle getHomePos()Lnet/minecraft/core/BlockPos;
|
||||
public net.minecraft.world.entity.animal.Turtle setHasEgg(Z)V
|
||||
public net.minecraft.world.entity.animal.Turtle isGoingHome()Z
|
||||
public net.minecraft.world.entity.animal.Turtle setGoingHome(Z)V
|
||||
public net.minecraft.world.entity.animal.Turtle isTravelling()Z
|
||||
public net.minecraft.world.entity.animal.Turtle setTravelling(Z)V
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java
|
||||
index 60e291abb3ebdf8676c13a2138d8eb436d033fa2..d27e5f9dac4703b839ab8444f6b54bf54d58af86 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java
|
||||
@@ -14,7 +14,7 @@ public abstract class MoveToBlockGoal extends Goal {
|
||||
protected int nextStartTick;
|
||||
protected int tryTicks;
|
||||
private int maxStayTicks;
|
||||
- protected BlockPos blockPos = BlockPos.ZERO;
|
||||
+ protected BlockPos blockPos = BlockPos.ZERO; @Deprecated public final BlockPos getTargetPosition() { return this.blockPos; } // Paper - OBFHELPER
|
||||
private boolean reachedTarget;
|
||||
private final int searchRange;
|
||||
private final int verticalSearchRange;
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/Turtle.java b/src/main/java/net/minecraft/world/entity/animal/Turtle.java
|
||||
index 3a3f5e567fdefad6887e42c8e9147194ae0c4d89..fd6ce6e8a3a7c889276e06fb427e0d17ed093149 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/Turtle.java
|
||||
@@ -487,14 +487,18 @@ public class Turtle extends Animal {
|
||||
|
||||
if (!this.turtle.isInWater() && this.isReachedTarget()) {
|
||||
if (this.turtle.layEggCounter < 1) {
|
||||
- this.turtle.setLayingEgg(true);
|
||||
+ this.turtle.setLayingEgg(new com.destroystokyo.paper.event.entity.TurtleStartDiggingEvent((org.bukkit.entity.Turtle) this.turtle.getBukkitEntity(), io.papermc.paper.util.MCUtil.toLocation(this.turtle.level(), this.getTargetPosition())).callEvent()); // Paper
|
||||
} else if (this.turtle.layEggCounter > this.adjustedTickDelay(200)) {
|
||||
Level world = this.turtle.level();
|
||||
|
||||
- if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.turtle, this.blockPos.above(), (BlockState) Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, this.turtle.random.nextInt(4) + 1))) { // CraftBukkit
|
||||
+ // CraftBukkit start
|
||||
+ // Paper start
|
||||
+ int eggCount = this.turtle.random.nextInt(4) + 1;
|
||||
+ com.destroystokyo.paper.event.entity.TurtleLayEggEvent layEggEvent = new com.destroystokyo.paper.event.entity.TurtleLayEggEvent((org.bukkit.entity.Turtle) this.turtle.getBukkitEntity(), io.papermc.paper.util.MCUtil.toLocation(this.turtle.level(), this.blockPos.above()), eggCount);
|
||||
+ if (layEggEvent.callEvent() && org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.turtle, this.blockPos.above(), Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, layEggEvent.getEggCount()))) {
|
||||
world.playSound((Player) null, blockposition, SoundEvents.TURTLE_LAY_EGG, SoundSource.BLOCKS, 0.3F, 0.9F + world.random.nextFloat() * 0.2F);
|
||||
BlockPos blockposition1 = this.blockPos.above();
|
||||
- BlockState iblockdata = (BlockState) Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, this.turtle.random.nextInt(4) + 1);
|
||||
+ BlockState iblockdata = (BlockState) Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, layEggEvent.getEggCount()); // Paper
|
||||
|
||||
world.setBlock(blockposition1, iblockdata, 3);
|
||||
world.gameEvent(GameEvent.BLOCK_PLACE, blockposition1, GameEvent.Context.of(this.turtle, iblockdata));
|
||||
@@ -564,7 +568,7 @@ public class Turtle extends Animal {
|
||||
|
||||
@Override
|
||||
public boolean canUse() {
|
||||
- return this.turtle.isBaby() ? false : (this.turtle.hasEgg() ? true : (this.turtle.getRandom().nextInt(reducedTickDelay(700)) != 0 ? false : !this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 64.0D)));
|
||||
+ return this.turtle.isBaby() ? false : (this.turtle.hasEgg() ? true : (this.turtle.getRandom().nextInt(reducedTickDelay(700)) != 0 ? false : !this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 64.0D))) && new com.destroystokyo.paper.event.entity.TurtleGoHomeEvent((org.bukkit.entity.Turtle) this.turtle.getBukkitEntity()).callEvent(); // Paper
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java
|
||||
index fac0317ff945db991e761ac8973f0d3d41ade26b..d44e6f4bb682d18c1497eee9fb2802f2bda6e840 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java
|
||||
@@ -28,4 +28,31 @@ public class CraftTurtle extends CraftAnimals implements Turtle {
|
||||
public boolean isLayingEgg() {
|
||||
return this.getHandle().isLayingEgg();
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public org.bukkit.Location getHome() {
|
||||
+ return io.papermc.paper.util.MCUtil.toLocation(this.getHandle().level(), this.getHandle().getHomePos());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setHome(org.bukkit.Location location) {
|
||||
+ this.getHandle().setHomePos(io.papermc.paper.util.MCUtil.toBlockPosition(location));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isGoingHome() {
|
||||
+ return this.getHandle().isGoingHome();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isDigging() {
|
||||
+ return this.getHandle().isLayingEgg();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setHasEgg(boolean hasEgg) {
|
||||
+ this.getHandle().setHasEgg(hasEgg);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Caleb Bassham <caleb.bassham@gmail.com>
|
||||
Date: Fri, 28 Sep 2018 02:32:19 -0500
|
||||
Subject: [PATCH] Call player spectator target events and improve
|
||||
implementation
|
||||
|
||||
Use a proper teleport for teleporting to entities in different
|
||||
worlds.
|
||||
|
||||
Implementation improvements authored by Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Validate that the target entity is valid and deny spectate
|
||||
requests from frozen players.
|
||||
|
||||
Also, make sure the entity is spawned to the client before
|
||||
sending the camera packet. If the entity isn't spawned clientside
|
||||
when it receives the camera packet, then the client will not
|
||||
spectate the target entity.
|
||||
|
||||
Co-authored-by: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 41e0b2826bae59e48fef7e35caeb3ce6e46031ea..040f93638d3c71fb8f23301b8903e7cfda980e5d 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -1978,6 +1978,19 @@ public class ServerPlayer extends Player {
|
||||
|
||||
this.camera = (Entity) (entity == null ? this : entity);
|
||||
if (entity1 != this.camera) {
|
||||
+ // Paper start - Add PlayerStartSpectatingEntityEvent and PlayerStopSpectatingEntity Event
|
||||
+ if (this.camera == this) {
|
||||
+ com.destroystokyo.paper.event.player.PlayerStopSpectatingEntityEvent playerStopSpectatingEntityEvent = new com.destroystokyo.paper.event.player.PlayerStopSpectatingEntityEvent(this.getBukkitEntity(), entity1.getBukkitEntity());
|
||||
+ if (!playerStopSpectatingEntityEvent.callEvent()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ } else {
|
||||
+ com.destroystokyo.paper.event.player.PlayerStartSpectatingEntityEvent playerStartSpectatingEntityEvent = new com.destroystokyo.paper.event.player.PlayerStartSpectatingEntityEvent(this.getBukkitEntity(), entity1.getBukkitEntity(), entity.getBukkitEntity());
|
||||
+ if (!playerStartSpectatingEntityEvent.callEvent()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
Level world = this.camera.level();
|
||||
|
||||
if (world instanceof ServerLevel) {
|
||||
@@ -1993,7 +2006,6 @@ public class ServerPlayer extends Player {
|
||||
this.connection.send(new ClientboundSetCameraPacket(this.camera));
|
||||
this.connection.resetPosition();
|
||||
}
|
||||
-
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,35 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 17 Oct 2018 19:17:27 -0400
|
||||
Subject: [PATCH] MC-50319: Check other worlds for shooter of projectiles
|
||||
|
||||
Say a player shoots an arrow through a nether portal, the game
|
||||
would lose the shooter for determining things such as Player Kills,
|
||||
because the entity is in another world.
|
||||
|
||||
If the projectile fails to find the shooter in the current world, check
|
||||
other worlds.
|
||||
|
||||
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 f49dd279ba9e8970f116f956466feb072c4f8420..e5da57b35cd82ee7b4e844cfe74289a71d38779a 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
|
||||
@@ -60,6 +60,18 @@ public abstract class Projectile extends Entity implements TraceableEntity {
|
||||
return this.cachedOwner;
|
||||
} else if (this.ownerUUID != null && this.level() instanceof ServerLevel) {
|
||||
this.cachedOwner = ((ServerLevel) this.level()).getEntity(this.ownerUUID);
|
||||
+ // Paper start - check all worlds
|
||||
+ if (this.cachedOwner == null) {
|
||||
+ for (final ServerLevel level : this.level().getServer().getAllLevels()) {
|
||||
+ if (level == this.level()) continue;
|
||||
+ final Entity entity = level.getEntity(this.ownerUUID);
|
||||
+ if (entity != null) {
|
||||
+ this.cachedOwner = entity;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
return this.cachedOwner;
|
||||
} else {
|
||||
return null;
|
|
@ -1,103 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Fri, 12 Oct 2018 14:10:46 -0500
|
||||
Subject: [PATCH] Add more Witch API
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.entity.monster.Witch usingTime
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/Witch.java b/src/main/java/net/minecraft/world/entity/monster/Witch.java
|
||||
index df024c3108df807772fc487f5c59004a59938bf2..701f6bf1d558cf0ec4bc1abb9e1f66d96ea5a6c9 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Witch.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Witch.java
|
||||
@@ -157,21 +157,11 @@ public class Witch extends Raider implements RangedAttackMob {
|
||||
}
|
||||
|
||||
if (potionregistry != null) {
|
||||
- // Paper start
|
||||
ItemStack potion = PotionUtils.setPotion(new ItemStack(Items.POTION), potionregistry);
|
||||
- org.bukkit.inventory.ItemStack bukkitStack = com.destroystokyo.paper.event.entity.WitchReadyPotionEvent.process((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion));
|
||||
- this.setItemSlot(EquipmentSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack));
|
||||
+ // Paper start - logic moved into setDrinkingPotion, copy exact impl into the method and then comment out
|
||||
+ this.setDrinkingPotion(potion);
|
||||
// Paper end
|
||||
- this.usingTime = this.getMainHandItem().getUseDuration();
|
||||
- this.setUsingItem(true);
|
||||
- if (!this.isSilent()) {
|
||||
- this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.WITCH_DRINK, this.getSoundSource(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F);
|
||||
- }
|
||||
-
|
||||
- AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED);
|
||||
|
||||
- attributemodifiable.removeModifier(Witch.SPEED_MODIFIER_DRINKING);
|
||||
- attributemodifiable.addTransientModifier(Witch.SPEED_MODIFIER_DRINKING);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,6 +173,24 @@ public class Witch extends Raider implements RangedAttackMob {
|
||||
super.aiStep();
|
||||
}
|
||||
|
||||
+ // Paper start - moved to its own method
|
||||
+ public void setDrinkingPotion(ItemStack potion) {
|
||||
+ org.bukkit.inventory.ItemStack bukkitStack = com.destroystokyo.paper.event.entity.WitchReadyPotionEvent.process((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion));
|
||||
+ this.setItemSlot(EquipmentSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack));
|
||||
+ // Paper end
|
||||
+ this.usingTime = this.getMainHandItem().getUseDuration();
|
||||
+ this.setUsingItem(true);
|
||||
+ if (!this.isSilent()) {
|
||||
+ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.WITCH_DRINK, this.getSoundSource(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F);
|
||||
+ }
|
||||
+
|
||||
+ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED);
|
||||
+
|
||||
+ attributemodifiable.removeModifier(Witch.SPEED_MODIFIER_DRINKING);
|
||||
+ attributemodifiable.addTransientModifier(Witch.SPEED_MODIFIER_DRINKING);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public SoundEvent getCelebrateSound() {
|
||||
return SoundEvents.WITCH_CELEBRATE;
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java
|
||||
index 5024a102fe71d7013bc809bb4140763bd4c466e7..0acb96ae2102ab6af4b5610254ab3a1408ed9822 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java
|
||||
@@ -2,6 +2,13 @@ package org.bukkit.craftbukkit.entity;
|
||||
|
||||
import org.bukkit.craftbukkit.CraftServer;
|
||||
import org.bukkit.entity.Witch;
|
||||
+// Paper start
|
||||
+import com.destroystokyo.paper.entity.CraftRangedEntity;
|
||||
+import com.google.common.base.Preconditions;
|
||||
+import org.bukkit.Material;
|
||||
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
+import org.bukkit.inventory.ItemStack;
|
||||
+// Paper end
|
||||
|
||||
public class CraftWitch extends CraftRaider implements Witch, com.destroystokyo.paper.entity.CraftRangedEntity<net.minecraft.world.entity.monster.Witch> { // Paper
|
||||
public CraftWitch(CraftServer server, net.minecraft.world.entity.monster.Witch entity) {
|
||||
@@ -22,4 +29,23 @@ public class CraftWitch extends CraftRaider implements Witch, com.destroystokyo.
|
||||
public boolean isDrinkingPotion() {
|
||||
return this.getHandle().isDrinkingPotion();
|
||||
}
|
||||
+ // Paper start
|
||||
+ public int getPotionUseTimeLeft() {
|
||||
+ return getHandle().usingTime;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setPotionUseTimeLeft(int ticks) {
|
||||
+ getHandle().usingTime = ticks;
|
||||
+ }
|
||||
+
|
||||
+ public ItemStack getDrinkingPotion() {
|
||||
+ return CraftItemStack.asCraftMirror(getHandle().getMainHandItem());
|
||||
+ }
|
||||
+
|
||||
+ public void setDrinkingPotion(ItemStack potion) {
|
||||
+ Preconditions.checkArgument(potion == null || potion.getType().isEmpty() || potion.getType() == Material.POTION, "must be potion, air, or null");
|
||||
+ getHandle().setDrinkingPotion(CraftItemStack.asNMSCopy(potion));
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Wed, 10 Oct 2018 21:22:44 -0500
|
||||
Subject: [PATCH] Check Drowned for Villager Aggression Config
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/Drowned.java b/src/main/java/net/minecraft/world/entity/monster/Drowned.java
|
||||
index 3e4fde2736feb03af2116cd218358845cd8f99d8..991d728db2a3b64316fc2102cf3aee470327a62e 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Drowned.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Drowned.java
|
||||
@@ -78,7 +78,7 @@ public class Drowned extends Zombie implements RangedAttackMob {
|
||||
this.goalSelector.addGoal(7, new RandomStrollGoal(this, 1.0D));
|
||||
this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Drowned.class})).setAlertOthers(ZombifiedPiglin.class));
|
||||
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::okTarget));
|
||||
- this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false));
|
||||
+ if (this.level().spigotConfig.zombieAggressiveTowardsVillager) this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)); // Paper
|
||||
this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true));
|
||||
this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Axolotl.class, true, false));
|
||||
this.targetSelector.addGoal(5, new NearestAttackableTargetGoal<>(this, Turtle.class, 10, true, false, Turtle.BABY_ON_LAND_SELECTOR));
|
|
@ -1,67 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Gabriele C <sgdc3.mail@gmail.com>
|
||||
Date: Mon, 22 Oct 2018 17:34:10 +0200
|
||||
Subject: [PATCH] Add option to prevent players from moving into unloaded
|
||||
chunks #1551
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 9092a04f7a98f022c9a9bfe5310643b4b89ce2e7..585376aecc7329975a5d3e6b7c091f5b14daebd2 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -569,9 +569,9 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
||||
double d0 = entity.getX();
|
||||
double d1 = entity.getY();
|
||||
double d2 = entity.getZ();
|
||||
- double d3 = ServerGamePacketListenerImpl.clampHorizontal(packet.getX());
|
||||
- double d4 = ServerGamePacketListenerImpl.clampVertical(packet.getY());
|
||||
- double d5 = ServerGamePacketListenerImpl.clampHorizontal(packet.getZ());
|
||||
+ double d3 = ServerGamePacketListenerImpl.clampHorizontal(packet.getX()); final double toX = d3; // Paper - OBFHELPER
|
||||
+ double d4 = ServerGamePacketListenerImpl.clampVertical(packet.getY()); final double toY = d4; // Paper - OBFHELPER
|
||||
+ double d5 = ServerGamePacketListenerImpl.clampHorizontal(packet.getZ()); final double toZ = d5; // Paper - OBFHELPER
|
||||
float f = Mth.wrapDegrees(packet.getYRot());
|
||||
float f1 = Mth.wrapDegrees(packet.getXRot());
|
||||
double d6 = d3 - this.vehicleFirstGoodX;
|
||||
@@ -606,6 +606,16 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
||||
}
|
||||
speed *= 2f; // TODO: Get the speed of the vehicle instead of the player
|
||||
|
||||
+ // Paper start - Prevent moving into unloaded chunks
|
||||
+ if (this.player.level().paperConfig().chunks.preventMovingIntoUnloadedChunks && (
|
||||
+ !worldserver.areChunksLoadedForMove(this.player.getBoundingBox().expandTowards(new Vec3(toX, toY, toZ).subtract(this.player.position()))) ||
|
||||
+ !worldserver.areChunksLoadedForMove(entity.getBoundingBox().expandTowards(new Vec3(toX, toY, toZ).subtract(entity.position())))
|
||||
+ )) {
|
||||
+ this.connection.send(new ClientboundMoveVehiclePacket(entity));
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
if (d10 - d9 > Math.max(100.0D, Math.pow((double) (org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) i * speed), 2)) && !this.isSingleplayerOwner()) {
|
||||
// CraftBukkit end
|
||||
ServerGamePacketListenerImpl.LOGGER.warn("{} (vehicle of {}) moved too quickly! {},{},{}", new Object[]{entity.getName().getString(), this.player.getName().getString(), d6, d7, d8});
|
||||
@@ -1259,9 +1269,9 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
||||
this.allowedPlayerTicks = 20; // CraftBukkit
|
||||
} else {
|
||||
this.awaitingTeleportTime = this.tickCount;
|
||||
- double d0 = ServerGamePacketListenerImpl.clampHorizontal(packet.getX(this.player.getX()));
|
||||
- double d1 = ServerGamePacketListenerImpl.clampVertical(packet.getY(this.player.getY()));
|
||||
- double d2 = ServerGamePacketListenerImpl.clampHorizontal(packet.getZ(this.player.getZ()));
|
||||
+ double d0 = ServerGamePacketListenerImpl.clampHorizontal(packet.getX(this.player.getX())); final double toX = d0; // Paper - OBFHELPER
|
||||
+ double d1 = ServerGamePacketListenerImpl.clampVertical(packet.getY(this.player.getY())); final double toY = d1;
|
||||
+ double d2 = ServerGamePacketListenerImpl.clampHorizontal(packet.getZ(this.player.getZ())); final double toZ = d2; // Paper - OBFHELPER
|
||||
float f = Mth.wrapDegrees(packet.getYRot(this.player.getYRot()));
|
||||
float f1 = Mth.wrapDegrees(packet.getXRot(this.player.getXRot()));
|
||||
|
||||
@@ -1316,6 +1326,12 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
||||
} else {
|
||||
speed = this.player.getAbilities().walkingSpeed * 10f;
|
||||
}
|
||||
+ // Paper start - Prevent moving into unloaded chunks
|
||||
+ if (this.player.level().paperConfig().chunks.preventMovingIntoUnloadedChunks && (this.player.getX() != toX || this.player.getZ() != toZ) && !worldserver.areChunksLoadedForMove(this.player.getBoundingBox().expandTowards(new Vec3(toX, toY, toZ).subtract(this.player.position())))) {
|
||||
+ this.internalTeleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.getYRot(), this.player.getXRot(), Collections.emptySet());
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
if (!this.player.isChangingDimension() && (!this.player.level().getGameRules().getBoolean(GameRules.RULE_DISABLE_ELYTRA_MOVEMENT_CHECK) || !this.player.isFallFlying())) {
|
||||
float f2 = this.player.isFallFlying() ? 300.0F : 100.0F;
|
|
@ -1,18 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: GreenMeanie <GreenMeanieMC@gmail.com>
|
||||
Date: Sat, 20 Oct 2018 22:34:02 -0400
|
||||
Subject: [PATCH] Reset players airTicks on respawn
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 040f93638d3c71fb8f23301b8903e7cfda980e5d..715314de7a92a8e06f82c6bff5fe74e3b23044f8 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -2454,6 +2454,7 @@ public class ServerPlayer extends Player {
|
||||
|
||||
this.setHealth(this.getMaxHealth());
|
||||
this.stopUsingItem(); // CraftBukkit - SPIGOT-6682: Clear active item on reset
|
||||
+ this.setAirSupply(this.getMaxAirSupply()); // Paper
|
||||
this.setRemainingFireTicks(0);
|
||||
this.fallDistance = 0;
|
||||
this.foodData = new FoodData(this);
|
|
@ -1,33 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 23 Oct 2018 20:25:05 -0400
|
||||
Subject: [PATCH] Don't sleep after profile lookups if not needed
|
||||
|
||||
Mojang was sleeping even if we had no more requests to go after
|
||||
the current one finished, resulting in 100ms lost per profile lookup
|
||||
|
||||
diff --git a/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java b/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java
|
||||
index cc38e909d1fa83206fa09666599d853a6e89ef36..c48a40155108b6bae18073638a0ba12649344261 100644
|
||||
--- a/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java
|
||||
+++ b/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java
|
||||
@@ -43,6 +43,7 @@ public class YggdrasilGameProfileRepository implements GameProfileRepository {
|
||||
}
|
||||
|
||||
final int page = 0;
|
||||
+ boolean hasRequested = false; // Paper
|
||||
|
||||
for (final List<String> request : Iterables.partition(criteria, ENTRIES_PER_PAGE)) {
|
||||
int failCount = 0;
|
||||
@@ -68,6 +69,12 @@ public class YggdrasilGameProfileRepository implements GameProfileRepository {
|
||||
LOGGER.debug("Couldn't find profile {}", name);
|
||||
callback.onProfileLookupFailed(new GameProfile(null, name), new ProfileNotFoundException("Server did not find the requested profile"));
|
||||
}
|
||||
+ // Paper start
|
||||
+ if (!hasRequested) {
|
||||
+ hasRequested = true;
|
||||
+ continue;
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
try {
|
||||
Thread.sleep(DELAY_BETWEEN_PAGES);
|
|
@ -1,92 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 23 Oct 2018 23:14:38 -0400
|
||||
Subject: [PATCH] Improve Server Thread Pool and Thread Priorities
|
||||
|
||||
Use a simple executor since Fork join is a much more complex pool
|
||||
type and we are not using its capabilities.
|
||||
|
||||
Set thread priorities so main thread has above normal priority over
|
||||
server threads
|
||||
|
||||
Allow usage of a single thread executor by not using ForkJoin so single core CPU's.
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.Util onThreadException(Ljava/lang/Thread;Ljava/lang/Throwable;)V
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/util/ServerWorkerThread.java b/src/main/java/io/papermc/paper/util/ServerWorkerThread.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..b60f59cf5cc8eb84a6055b7861857dece7f2501b
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/util/ServerWorkerThread.java
|
||||
@@ -0,0 +1,14 @@
|
||||
+package io.papermc.paper.util;
|
||||
+
|
||||
+import java.util.concurrent.atomic.AtomicInteger;
|
||||
+import net.minecraft.Util;
|
||||
+
|
||||
+public class ServerWorkerThread extends Thread {
|
||||
+ private static final AtomicInteger threadId = new AtomicInteger(1);
|
||||
+ public ServerWorkerThread(Runnable target, String poolName, int prioritityModifier) {
|
||||
+ super(target, "Worker-" + poolName + "-" + threadId.getAndIncrement());
|
||||
+ setPriority(Thread.NORM_PRIORITY+prioritityModifier); // Deprioritize over main
|
||||
+ this.setDaemon(true);
|
||||
+ this.setUncaughtExceptionHandler(Util::onThreadException);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java
|
||||
index 0f05d26248d8c999048a88796df227a6a1e3755f..7354711e194ab58b11b68f447c1fc795fe611a65 100644
|
||||
--- a/src/main/java/net/minecraft/Util.java
|
||||
+++ b/src/main/java/net/minecraft/Util.java
|
||||
@@ -81,7 +81,7 @@ public class Util {
|
||||
private static final int DEFAULT_MAX_THREADS = 255;
|
||||
private static final String MAX_THREADS_SYSTEM_PROPERTY = "max.bg.threads";
|
||||
private static final AtomicInteger WORKER_COUNT = new AtomicInteger(1);
|
||||
- private static final ExecutorService BACKGROUND_EXECUTOR = makeExecutor("Main");
|
||||
+ private static final ExecutorService BACKGROUND_EXECUTOR = makeExecutor("Main", -1); // Paper - add -1 priority
|
||||
// Paper start - don't submit BLOCKING PROFILE LOOKUPS to the world gen thread
|
||||
public static final ExecutorService PROFILE_EXECUTOR = Executors.newFixedThreadPool(2, new java.util.concurrent.ThreadFactory() {
|
||||
|
||||
@@ -144,14 +144,18 @@ public class Util {
|
||||
return FILENAME_DATE_TIME_FORMATTER.format(ZonedDateTime.now());
|
||||
}
|
||||
|
||||
- private static ExecutorService makeExecutor(String name) {
|
||||
- int i = Mth.clamp(Runtime.getRuntime().availableProcessors() - 1, 1, getMaxThreads());
|
||||
+ private static ExecutorService makeExecutor(String s, int priorityModifier) { // Paper - add priority
|
||||
+ // Paper start - use simpler thread pool that allows 1 thread
|
||||
+ int i = Math.min(8, Math.max(Runtime.getRuntime().availableProcessors() - 2, 1));
|
||||
+ i = Integer.getInteger("Paper.WorkerThreadCount", i);
|
||||
ExecutorService executorService;
|
||||
+
|
||||
if (i <= 0) {
|
||||
executorService = MoreExecutors.newDirectExecutorService();
|
||||
} else {
|
||||
- executorService = new ForkJoinPool(i, (forkJoinPool) -> {
|
||||
- ForkJoinWorkerThread forkJoinWorkerThread = new ForkJoinWorkerThread(forkJoinPool) {
|
||||
+ executorService = new java.util.concurrent.ThreadPoolExecutor(i, i,0L, TimeUnit.MILLISECONDS, new java.util.concurrent.LinkedBlockingQueue<Runnable>(), target -> new io.papermc.paper.util.ServerWorkerThread(target, s, priorityModifier));
|
||||
+ }
|
||||
+ /*
|
||||
@Override
|
||||
protected void onTermination(Throwable throwable) {
|
||||
if (throwable != null) {
|
||||
@@ -167,6 +171,7 @@ public class Util {
|
||||
return forkJoinWorkerThread;
|
||||
}, Util::onThreadException, true);
|
||||
}
|
||||
+ }*/ // Paper end
|
||||
|
||||
return executorService;
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index d05f776204a720084a583c6d6dfe47936761b6e3..e5ab15722fe640d4766b9a24fb82b1d60f15a241 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -311,6 +311,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
thread.setUncaughtExceptionHandler((thread1, throwable) -> {
|
||||
MinecraftServer.LOGGER.error("Uncaught exception in server thread", throwable);
|
||||
});
|
||||
+ thread.setPriority(Thread.NORM_PRIORITY+2); // Paper - boost priority
|
||||
if (Runtime.getRuntime().availableProcessors() > 4) {
|
||||
thread.setPriority(8);
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Fri, 2 Nov 2018 23:11:51 -0400
|
||||
Subject: [PATCH] Optimize World Time Updates
|
||||
|
||||
Splits time updates into incremental updates as well as does
|
||||
the updates per world, so that we can re-use the same packet
|
||||
object for every player unless they have per-player time enabled.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index e5ab15722fe640d4766b9a24fb82b1d60f15a241..1a74b7c252d16e5ab2c303e6e96c62e78ef9311c 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1386,12 +1386,24 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
|
||||
MinecraftTimings.timeUpdateTimer.startTiming(); // Spigot // Paper
|
||||
// Send time updates to everyone, it will get the right time from the world the player is in.
|
||||
- if (this.tickCount % 20 == 0) {
|
||||
- for (int i = 0; i < this.getPlayerList().players.size(); ++i) {
|
||||
- ServerPlayer entityplayer = (ServerPlayer) this.getPlayerList().players.get(i);
|
||||
- entityplayer.connection.send(new ClientboundSetTimePacket(entityplayer.level().getGameTime(), entityplayer.getPlayerTime(), entityplayer.level().getGameRules().getBoolean(GameRules.RULE_DAYLIGHT))); // Add support for per player time
|
||||
+ // Paper start - optimize time updates
|
||||
+ for (final ServerLevel level : this.getAllLevels()) {
|
||||
+ final boolean doDaylight = level.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT);
|
||||
+ final long dayTime = level.getDayTime();
|
||||
+ long worldTime = level.getGameTime();
|
||||
+ final ClientboundSetTimePacket worldPacket = new ClientboundSetTimePacket(worldTime, dayTime, doDaylight);
|
||||
+ for (Player entityhuman : level.players()) {
|
||||
+ if (!(entityhuman instanceof ServerPlayer) || (tickCount + entityhuman.getId()) % 20 != 0) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ ServerPlayer entityplayer = (ServerPlayer) entityhuman;
|
||||
+ long playerTime = entityplayer.getPlayerTime();
|
||||
+ ClientboundSetTimePacket packet = (playerTime == dayTime) ? worldPacket :
|
||||
+ new ClientboundSetTimePacket(worldTime, playerTime, doDaylight);
|
||||
+ entityplayer.connection.send(packet); // Add support for per player time
|
||||
}
|
||||
}
|
||||
+ // Paper end
|
||||
MinecraftTimings.timeUpdateTimer.stopTiming(); // Spigot // Paper
|
||||
|
||||
while (iterator.hasNext()) {
|
|
@ -1,356 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Mon, 5 Nov 2018 04:23:51 +0000
|
||||
Subject: [PATCH] Restore custom InventoryHolder support
|
||||
|
||||
Upstream removed the ability to consistently use a custom InventoryHolder,
|
||||
However, the implementation does not use an InventoryHolder in any form
|
||||
outside of custom inventories.
|
||||
|
||||
== AT ==
|
||||
public-f net.minecraft.world.inventory.AbstractContainerMenu dataSlots
|
||||
public-f net.minecraft.world.inventory.AbstractContainerMenu remoteDataSlots
|
||||
|
||||
Co-authored-by: Shane Freeder <theboyetronic@gmail.com>
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/inventory/PaperInventoryCustomHolderContainer.java b/src/main/java/io/papermc/paper/inventory/PaperInventoryCustomHolderContainer.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..224d4b2cc45b0d02230a76caee9c88573a448b4c
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/inventory/PaperInventoryCustomHolderContainer.java
|
||||
@@ -0,0 +1,141 @@
|
||||
+package io.papermc.paper.inventory;
|
||||
+
|
||||
+import io.papermc.paper.adventure.PaperAdventure;
|
||||
+import net.kyori.adventure.text.Component;
|
||||
+import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
+import net.minecraft.world.Container;
|
||||
+import net.minecraft.world.entity.player.Player;
|
||||
+import net.minecraft.world.item.ItemStack;
|
||||
+import net.minecraft.world.level.block.entity.BaseContainerBlockEntity;
|
||||
+import org.bukkit.Location;
|
||||
+import org.bukkit.craftbukkit.entity.CraftHumanEntity;
|
||||
+import org.bukkit.entity.HumanEntity;
|
||||
+import org.bukkit.event.inventory.InventoryType;
|
||||
+import org.bukkit.inventory.InventoryHolder;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+import java.util.List;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public final class PaperInventoryCustomHolderContainer implements Container {
|
||||
+
|
||||
+ private final InventoryHolder owner;
|
||||
+ private final Container delegate;
|
||||
+ private final InventoryType type;
|
||||
+ private final String title;
|
||||
+ private final Component adventure$title;
|
||||
+
|
||||
+ public PaperInventoryCustomHolderContainer(InventoryHolder owner, Container delegate, InventoryType type) {
|
||||
+ this.owner = owner;
|
||||
+ this.delegate = delegate;
|
||||
+ this.type = type;
|
||||
+ @Nullable Component adventure$title = null;
|
||||
+ if (delegate instanceof BaseContainerBlockEntity blockEntity) {
|
||||
+ adventure$title = blockEntity.getCustomName() != null ? PaperAdventure.asAdventure(blockEntity.getCustomName()) : null;
|
||||
+ }
|
||||
+ if (adventure$title == null) {
|
||||
+ adventure$title = type.defaultTitle();
|
||||
+ }
|
||||
+ this.adventure$title = adventure$title;
|
||||
+ this.title = LegacyComponentSerializer.legacySection().serialize(this.adventure$title);
|
||||
+ }
|
||||
+
|
||||
+ public Component title() {
|
||||
+ return this.adventure$title;
|
||||
+ }
|
||||
+
|
||||
+ public String getTitle() {
|
||||
+ return this.title;
|
||||
+ }
|
||||
+
|
||||
+ public InventoryType getType() {
|
||||
+ return this.type;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getContainerSize() {
|
||||
+ return this.delegate.getContainerSize();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isEmpty() {
|
||||
+ return this.delegate.isEmpty();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public ItemStack getItem(int slot) {
|
||||
+ return this.delegate.getItem(slot);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public ItemStack removeItem(int slot, int amount) {
|
||||
+ return this.delegate.removeItem(slot, amount);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public ItemStack removeItemNoUpdate(int slot) {
|
||||
+ return this.delegate.removeItemNoUpdate(slot);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setItem(int slot, ItemStack stack) {
|
||||
+ this.delegate.setItem(slot, stack);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getMaxStackSize() {
|
||||
+ return this.delegate.getMaxStackSize();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setChanged() {
|
||||
+ this.delegate.setChanged();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean stillValid(Player player) {
|
||||
+ return this.delegate.stillValid(player);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public List<ItemStack> getContents() {
|
||||
+ return this.delegate.getContents();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onOpen(CraftHumanEntity who) {
|
||||
+ this.delegate.onOpen(who);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onClose(CraftHumanEntity who) {
|
||||
+ this.delegate.onClose(who);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public List<HumanEntity> getViewers() {
|
||||
+ return this.delegate.getViewers();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public InventoryHolder getOwner() {
|
||||
+ return this.owner;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setMaxStackSize(int size) {
|
||||
+ this.delegate.setMaxStackSize(size);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Location getLocation() {
|
||||
+ return this.delegate.getLocation();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void clearContent() {
|
||||
+ this.delegate.clearContent();
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java
|
||||
index 1b526fff47e5a3d9a5325c73966dd2bf3dbbdc19..633e6f4922ccaf59979a22885162f42c65bf628a 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java
|
||||
@@ -49,7 +49,7 @@ public class CraftContainer extends AbstractContainerMenu {
|
||||
public CraftContainer(final Inventory inventory, final Player player, int id) {
|
||||
this(new InventoryView() {
|
||||
|
||||
- private final String originalTitle = (inventory instanceof CraftInventoryCustom) ? ((CraftInventoryCustom.MinecraftInventory) ((CraftInventory) inventory).getInventory()).getTitle() : inventory.getType().getDefaultTitle();
|
||||
+ private final String originalTitle = inventory instanceof CraftInventoryCustom ? ((CraftInventoryCustom) inventory).getTitle() : inventory.getType().getDefaultTitle(); // Paper
|
||||
private String title = this.originalTitle;
|
||||
|
||||
@Override
|
||||
@@ -75,7 +75,7 @@ public class CraftContainer extends AbstractContainerMenu {
|
||||
// Paper start
|
||||
@Override
|
||||
public net.kyori.adventure.text.Component title() {
|
||||
- return inventory instanceof CraftInventoryCustom ? ((CraftInventoryCustom.MinecraftInventory) ((CraftInventory) inventory).getInventory()).title() : net.kyori.adventure.text.Component.text(inventory.getType().getDefaultTitle());
|
||||
+ return inventory instanceof CraftInventoryCustom custom ? custom.title() : inventory.getType().defaultTitle(); // Paper
|
||||
}
|
||||
// Paper end
|
||||
|
||||
@@ -247,6 +247,10 @@ public class CraftContainer extends AbstractContainerMenu {
|
||||
this.lastSlots = delegate.lastSlots;
|
||||
this.slots = delegate.slots;
|
||||
this.remoteSlots = delegate.remoteSlots;
|
||||
+ // Paper start - copy data slots for InventoryView#set/getProperty
|
||||
+ this.dataSlots = delegate.dataSlots;
|
||||
+ this.remoteDataSlots = delegate.remoteDataSlots;
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
// SPIGOT-4598 - we should still delegate the shift click handler
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
|
||||
index e97c7809fa6572695377e5ca63bf86e5515ef531..c064022d248ff3e0b52c0e815ab90527f9132fb7 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
|
||||
@@ -492,6 +492,10 @@ public class CraftInventory implements Inventory {
|
||||
return InventoryType.BREWING;
|
||||
} else if (this.inventory instanceof CraftInventoryCustom.MinecraftInventory) {
|
||||
return ((CraftInventoryCustom.MinecraftInventory) this.inventory).getType();
|
||||
+ // Paper start
|
||||
+ } else if (this.inventory instanceof io.papermc.paper.inventory.PaperInventoryCustomHolderContainer holderContainer) {
|
||||
+ return holderContainer.getType();
|
||||
+ // Paper end
|
||||
} else if (this.inventory instanceof PlayerEnderChestContainer) {
|
||||
return InventoryType.ENDER_CHEST;
|
||||
} else if (this.inventory instanceof MerchantContainer) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java
|
||||
index fc0e1212022d1aa3506699b60ef338196eb54eba..da1c1fe0faf6819b15a81d6ad53370948e5f984f 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java
|
||||
@@ -15,6 +15,11 @@ import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
|
||||
public class CraftInventoryCustom extends CraftInventory {
|
||||
+ // Paper start
|
||||
+ public CraftInventoryCustom(InventoryHolder owner, InventoryType type, Container delegate) {
|
||||
+ super(new io.papermc.paper.inventory.PaperInventoryCustomHolderContainer(owner, delegate, type));
|
||||
+ }
|
||||
+ // Paper end
|
||||
public CraftInventoryCustom(InventoryHolder owner, InventoryType type) {
|
||||
super(new MinecraftInventory(owner, type));
|
||||
}
|
||||
@@ -42,6 +47,27 @@ public class CraftInventoryCustom extends CraftInventory {
|
||||
public CraftInventoryCustom(InventoryHolder owner, int size, String title) {
|
||||
super(new MinecraftInventory(owner, size, title));
|
||||
}
|
||||
+ // Paper start
|
||||
+ public String getTitle() {
|
||||
+ if (this.inventory instanceof MinecraftInventory minecraftInventory) {
|
||||
+ return minecraftInventory.getTitle();
|
||||
+ } else if (this.inventory instanceof io.papermc.paper.inventory.PaperInventoryCustomHolderContainer customHolderContainer) {
|
||||
+ return customHolderContainer.getTitle();
|
||||
+ } else {
|
||||
+ throw new UnsupportedOperationException(this.inventory.getClass() + " isn't a recognized Container type here");
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public net.kyori.adventure.text.Component title() {
|
||||
+ if (this.inventory instanceof MinecraftInventory minecraftInventory) {
|
||||
+ return minecraftInventory.title();
|
||||
+ } else if (this.inventory instanceof io.papermc.paper.inventory.PaperInventoryCustomHolderContainer customHolderContainer) {
|
||||
+ return customHolderContainer.title();
|
||||
+ } else {
|
||||
+ throw new UnsupportedOperationException(this.inventory.getClass() + " isn't a recognized Container type here");
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
static class MinecraftInventory implements Container {
|
||||
private final NonNullList<ItemStack> items;
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java
|
||||
index 7a7f3f53aef601f124d474d9890e23d87dd96900..54e61b9b058bee2167461aaaf828ed7a00949c29 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java
|
||||
@@ -28,7 +28,7 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat
|
||||
|
||||
@Override
|
||||
public Inventory createInventory(InventoryHolder holder, InventoryType type) {
|
||||
- return this.getInventory(this.getTileEntity());
|
||||
+ return this.getInventory(holder, type, this.getTileEntity()); // Paper
|
||||
}
|
||||
|
||||
// Paper start
|
||||
@@ -39,7 +39,7 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat
|
||||
((RandomizableContainerBlockEntity) te).setCustomName(io.papermc.paper.adventure.PaperAdventure.asVanilla(title));
|
||||
}
|
||||
|
||||
- return getInventory(te);
|
||||
+ return this.getInventory(owner, type, te); // Paper
|
||||
}
|
||||
// Paper end
|
||||
|
||||
@@ -50,10 +50,18 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat
|
||||
((RandomizableContainerBlockEntity) te).setCustomName(CraftChatMessage.fromStringOrNull(title));
|
||||
}
|
||||
|
||||
- return this.getInventory(te);
|
||||
+ return this.getInventory(holder, type, te); // Paper
|
||||
}
|
||||
|
||||
+ @Deprecated // Paper - use getInventory with owner and type
|
||||
public Inventory getInventory(Container tileEntity) {
|
||||
+ // Paper start
|
||||
+ return this.getInventory(null, null, tileEntity);
|
||||
+ }
|
||||
+
|
||||
+ public Inventory getInventory(InventoryHolder owner, InventoryType type, Container tileEntity) { // Paper
|
||||
+ if (owner != null) return new org.bukkit.craftbukkit.inventory.CraftInventoryCustom(owner, type, tileEntity); // Paper
|
||||
+ // Paper end
|
||||
return new CraftInventory(tileEntity);
|
||||
}
|
||||
|
||||
@@ -70,7 +78,7 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat
|
||||
public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) {
|
||||
Container tileEntity = getTileEntity();
|
||||
((AbstractFurnaceBlockEntity) tileEntity).setCustomName(io.papermc.paper.adventure.PaperAdventure.asVanilla(title));
|
||||
- return getInventory(tileEntity);
|
||||
+ return this.getInventory(owner, type, tileEntity); // Paper
|
||||
}
|
||||
// Paper end
|
||||
|
||||
@@ -78,11 +86,19 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat
|
||||
public Inventory createInventory(InventoryHolder owner, InventoryType type, String title) {
|
||||
Container tileEntity = this.getTileEntity();
|
||||
((AbstractFurnaceBlockEntity) tileEntity).setCustomName(CraftChatMessage.fromStringOrNull(title));
|
||||
- return this.getInventory(tileEntity);
|
||||
+ return this.getInventory(owner, type, tileEntity); // Paper
|
||||
}
|
||||
|
||||
@Override
|
||||
public Inventory getInventory(Container tileEntity) {
|
||||
+ // Paper start
|
||||
+ return getInventory(null, null, tileEntity);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Inventory getInventory(InventoryHolder owner, InventoryType type, net.minecraft.world.Container tileEntity) { // Paper
|
||||
+ if (owner != null) return new org.bukkit.craftbukkit.inventory.CraftInventoryCustom(owner, type, tileEntity); // Paper
|
||||
+ // Paper end
|
||||
return new CraftInventoryFurnace((AbstractFurnaceBlockEntity) tileEntity);
|
||||
}
|
||||
}
|
||||
@@ -102,7 +118,7 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat
|
||||
if (tileEntity instanceof BrewingStandBlockEntity) {
|
||||
((BrewingStandBlockEntity) tileEntity).setCustomName(io.papermc.paper.adventure.PaperAdventure.asVanilla(title));
|
||||
}
|
||||
- return getInventory(tileEntity);
|
||||
+ return this.getInventory(owner, type, tileEntity); // Paper
|
||||
}
|
||||
// Paper end
|
||||
|
||||
@@ -113,11 +129,19 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat
|
||||
if (tileEntity instanceof BrewingStandBlockEntity) {
|
||||
((BrewingStandBlockEntity) tileEntity).setCustomName(CraftChatMessage.fromStringOrNull(title));
|
||||
}
|
||||
- return this.getInventory(tileEntity);
|
||||
+ return this.getInventory(holder, type, tileEntity); // Paper
|
||||
}
|
||||
|
||||
@Override
|
||||
public Inventory getInventory(Container tileEntity) {
|
||||
+ // Paper start
|
||||
+ return getInventory(null, null, tileEntity);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Inventory getInventory(InventoryHolder owner, InventoryType type, net.minecraft.world.Container tileEntity) { // Paper
|
||||
+ if (owner != null) return new org.bukkit.craftbukkit.inventory.CraftInventoryCustom(owner, type, tileEntity); // Paper
|
||||
+ // Paper end
|
||||
return new CraftInventoryBrewer(tileEntity);
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Thu, 8 Nov 2018 21:33:09 -0500
|
||||
Subject: [PATCH] Use Vanilla Minecart Speeds
|
||||
|
||||
CraftBukkit changed the values on flying speed, restore back to vanilla
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java
|
||||
index 700db80055d93274aeccbe4a57a1a98f261442fb..c2a18a8e52f897bc96227854646e53e4dc189362 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java
|
||||
@@ -104,9 +104,9 @@ public abstract class AbstractMinecart extends Entity {
|
||||
private double derailedX = 0.5;
|
||||
private double derailedY = 0.5;
|
||||
private double derailedZ = 0.5;
|
||||
- private double flyingX = 0.95;
|
||||
- private double flyingY = 0.95;
|
||||
- private double flyingZ = 0.95;
|
||||
+ private double flyingX = 0.949999988079071D; // Paper - restore vanilla precision
|
||||
+ private double flyingY = 0.949999988079071D; // Paper - restore vanilla precision
|
||||
+ private double flyingZ = 0.949999988079071D; // Paper - restore vanilla precision
|
||||
public double maxSpeed = 0.4D;
|
||||
// CraftBukkit end
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Sat, 10 Nov 2018 05:15:21 +0000
|
||||
Subject: [PATCH] Fix SpongeAbsortEvent handling
|
||||
|
||||
Only process drops when the block is actually going to be removed
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/SpongeBlock.java b/src/main/java/net/minecraft/world/level/block/SpongeBlock.java
|
||||
index 305803d54058c0bd48808d3b2dec8b474d9c2591..4bce895268542531598a01a1bccd8ac1ed703b7d 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/SpongeBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/SpongeBlock.java
|
||||
@@ -124,7 +124,11 @@ public class SpongeBlock extends Block {
|
||||
} else if (iblockdata.is(Blocks.KELP) || iblockdata.is(Blocks.KELP_PLANT) || iblockdata.is(Blocks.SEAGRASS) || iblockdata.is(Blocks.TALL_SEAGRASS)) {
|
||||
BlockEntity tileentity = iblockdata.hasBlockEntity() ? world.getBlockEntity(blockposition1) : null;
|
||||
|
||||
+ // Paper start
|
||||
+ if (block.getHandle().isAir()) {
|
||||
dropResources(iblockdata, world, blockposition1, tileentity);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
}
|
||||
world.setBlock(blockposition1, block.getHandle(), block.getFlag());
|
|
@ -1,77 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Sun, 11 Nov 2018 21:01:09 +0000
|
||||
Subject: [PATCH] Don't allow digging into unloaded chunks
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
index 7adf7d1248680e591638298f13f5ae88788f5e4c..bdf11a98614c9c12d3112f437651be81d0d9872a 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
@@ -119,8 +119,8 @@ public class ServerPlayerGameMode {
|
||||
BlockState iblockdata;
|
||||
|
||||
if (this.hasDelayedDestroy) {
|
||||
- iblockdata = this.level.getBlockState(this.delayedDestroyPos);
|
||||
- if (iblockdata.isAir()) {
|
||||
+ iblockdata = this.level.getBlockStateIfLoaded(this.delayedDestroyPos); // Paper
|
||||
+ if (iblockdata == null || iblockdata.isAir()) { // Paper
|
||||
this.hasDelayedDestroy = false;
|
||||
} else {
|
||||
float f = this.incrementDestroyProgress(iblockdata, this.delayedDestroyPos, this.delayedTickStart);
|
||||
@@ -131,7 +131,13 @@ public class ServerPlayerGameMode {
|
||||
}
|
||||
}
|
||||
} else if (this.isDestroyingBlock) {
|
||||
- iblockdata = this.level.getBlockState(this.destroyPos);
|
||||
+ // Paper start - don't want to do same logic as above, return instead
|
||||
+ iblockdata = this.level.getBlockStateIfLoaded(this.destroyPos);
|
||||
+ if (iblockdata == null) {
|
||||
+ this.isDestroyingBlock = false;
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end
|
||||
if (iblockdata.isAir()) {
|
||||
this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1);
|
||||
this.lastSentState = -1;
|
||||
@@ -160,6 +166,7 @@ public class ServerPlayerGameMode {
|
||||
|
||||
public void handleBlockBreakAction(BlockPos pos, ServerboundPlayerActionPacket.Action action, Direction direction, int worldHeight, int sequence) {
|
||||
if (this.player.getEyePosition().distanceToSqr(Vec3.atCenterOf(pos)) > ServerGamePacketListenerImpl.MAX_INTERACTION_DISTANCE) {
|
||||
+ if (true) return; // Paper - Don't notify if unreasonably far away
|
||||
this.debugLogging(pos, false, sequence, "too far");
|
||||
} else if (pos.getY() >= worldHeight) {
|
||||
this.player.connection.send(new ClientboundBlockUpdatePacket(pos, this.level.getBlockState(pos)));
|
||||
@@ -304,10 +311,12 @@ public class ServerPlayerGameMode {
|
||||
this.debugLogging(pos, true, sequence, "stopped destroying");
|
||||
} else if (action == ServerboundPlayerActionPacket.Action.ABORT_DESTROY_BLOCK) {
|
||||
this.isDestroyingBlock = false;
|
||||
- if (!Objects.equals(this.destroyPos, pos)) {
|
||||
+ if (!Objects.equals(this.destroyPos, pos) && !BlockPos.ZERO.equals(this.destroyPos)) { // Paper
|
||||
ServerPlayerGameMode.LOGGER.debug("Mismatch in destroy block pos: {} {}", this.destroyPos, pos); // CraftBukkit - SPIGOT-5457 sent by client when interact event cancelled
|
||||
- this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1);
|
||||
- this.debugLogging(pos, true, sequence, "aborted mismatched destroying");
|
||||
+ BlockState type = this.level.getBlockStateIfLoaded(this.destroyPos); // Paper - don't load unloaded chunks for stale records here
|
||||
+ if (type != null) this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1);
|
||||
+ if (type != null) this.debugLogging(pos, true, sequence, "aborted mismatched destroying");
|
||||
+ this.destroyPos = BlockPos.ZERO; // Paper
|
||||
}
|
||||
|
||||
this.level.destroyBlockProgress(this.player.getId(), pos, -1);
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 585376aecc7329975a5d3e6b7c091f5b14daebd2..9f87d35fb20b63b01252dc844ca3a584c16c7129 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -1664,6 +1664,12 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
||||
case START_DESTROY_BLOCK:
|
||||
case ABORT_DESTROY_BLOCK:
|
||||
case STOP_DESTROY_BLOCK:
|
||||
+ // Paper start - Don't allow digging in unloaded chunks
|
||||
+ if (this.player.level().getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) == null) {
|
||||
+ this.player.connection.ackBlockChangesUpTo(packet.getSequence());
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end - Don't allow digging in unloaded chunks
|
||||
this.player.gameMode.handleBlockBreakAction(blockposition, packetplayinblockdig_enumplayerdigtype, packet.getDirection(), this.player.level().getMaxBuildHeight(), packet.getSequence());
|
||||
this.player.connection.ackBlockChangesUpTo(packet.getSequence());
|
||||
return;
|
|
@ -1,40 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Sun, 18 Nov 2018 19:49:56 +0000
|
||||
Subject: [PATCH] Make the default permission message configurable
|
||||
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/command/PaperCommand.java b/src/main/java/io/papermc/paper/command/PaperCommand.java
|
||||
index 0dd48e4098191c8b6e29945d62bc473e9f3a1e77..ae51993e0de706cb62c96795ca9de7663893a5bf 100644
|
||||
--- a/src/main/java/io/papermc/paper/command/PaperCommand.java
|
||||
+++ b/src/main/java/io/papermc/paper/command/PaperCommand.java
|
||||
@@ -75,7 +75,7 @@ public final class PaperCommand extends Command {
|
||||
if (sender.hasPermission(BASE_PERM + permission) || sender.hasPermission("bukkit.command.paper")) {
|
||||
return true;
|
||||
}
|
||||
- sender.sendMessage(text("I'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is in error.", RED));
|
||||
+ sender.sendMessage(Bukkit.permissionMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index 2e64d43cdc25135fadb759ea503b26104b881968..4926f9f5eaf13b339ce2c2385faf9f4afba3d029 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -2705,6 +2705,16 @@ public final class CraftServer implements Server {
|
||||
return io.papermc.paper.configuration.GlobalConfiguration.get().commands.suggestPlayerNamesWhenNullTabCompletions;
|
||||
}
|
||||
|
||||
+ @Override
|
||||
+ public String getPermissionMessage() {
|
||||
+ return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacyAmpersand().serialize(io.papermc.paper.configuration.GlobalConfiguration.get().messages.noPermission);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public net.kyori.adventure.text.Component permissionMessage() {
|
||||
+ return io.papermc.paper.configuration.GlobalConfiguration.get().messages.noPermission;
|
||||
+ }
|
||||
+
|
||||
@Override
|
||||
public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nonnull UUID uuid) {
|
||||
return createProfile(uuid, null);
|
|
@ -1,29 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 26 Nov 2018 19:21:58 -0500
|
||||
Subject: [PATCH] Prevent rayTrace from loading chunks
|
||||
|
||||
ray tracing into an unloaded chunk should be treated as a miss
|
||||
this saves a ton of lag for when AI tries to raytrace near unloaded chunks.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/BlockGetter.java b/src/main/java/net/minecraft/world/level/BlockGetter.java
|
||||
index 3b31a1927aaed7fffc1b4f4bcefc12120d66af3d..24073d4d7c45d501c2baec2d8c8b49f60fb76e65 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/BlockGetter.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/BlockGetter.java
|
||||
@@ -83,7 +83,15 @@ public interface BlockGetter extends LevelHeightAccessor {
|
||||
|
||||
// CraftBukkit start - moved block handling into separate method for use by Block#rayTrace
|
||||
default BlockHitResult clip(ClipContext raytrace1, BlockPos blockposition) {
|
||||
- BlockState iblockdata = this.getBlockState(blockposition);
|
||||
+ // Paper start - Prevent raytrace from loading chunks
|
||||
+ BlockState iblockdata = this.getBlockStateIfLoaded(blockposition);
|
||||
+ if (iblockdata == null) {
|
||||
+ // copied the last function parameter (listed below)
|
||||
+ Vec3 vec3d = raytrace1.getFrom().subtract(raytrace1.getTo());
|
||||
+
|
||||
+ return BlockHitResult.miss(raytrace1.getTo(), Direction.getNearest(vec3d.x, vec3d.y, vec3d.z), BlockPos.containing(raytrace1.getTo()));
|
||||
+ }
|
||||
+ // Paper end
|
||||
FluidState fluid = this.getFluidState(blockposition);
|
||||
Vec3 vec3d = raytrace1.getFrom();
|
||||
Vec3 vec3d1 = raytrace1.getTo();
|
|
@ -1,127 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 27 Nov 2018 21:18:06 -0500
|
||||
Subject: [PATCH] Handle Large Packets disconnecting client
|
||||
|
||||
If a players inventory is too big to send in a single packet,
|
||||
split the inventory set into multiple packets instead.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
|
||||
index 7065d8e2b0782f1dbaf9932db9201b94ae455a31..f5106ed464d496420ac575b09d6c9a7dfeb87bec 100644
|
||||
--- a/src/main/java/net/minecraft/network/Connection.java
|
||||
+++ b/src/main/java/net/minecraft/network/Connection.java
|
||||
@@ -158,6 +158,18 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
}
|
||||
|
||||
public void exceptionCaught(ChannelHandlerContext channelhandlercontext, Throwable throwable) {
|
||||
+ // Paper start
|
||||
+ if (throwable instanceof io.netty.handler.codec.EncoderException && throwable.getCause() instanceof PacketEncoder.PacketTooLargeException packetTooLargeException) {
|
||||
+ if (packetTooLargeException.getPacket().packetTooLarge(this)) {
|
||||
+ return;
|
||||
+ } else if (packetTooLargeException.getPacket().isSkippable()) {
|
||||
+ Connection.LOGGER.debug("Skipping packet due to errors", throwable.getCause());
|
||||
+ return;
|
||||
+ } else {
|
||||
+ throwable = throwable.getCause();
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
if (throwable instanceof SkipPacketException) {
|
||||
Connection.LOGGER.debug("Skipping packet due to errors", throwable.getCause());
|
||||
} else {
|
||||
diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/java/net/minecraft/network/PacketEncoder.java
|
||||
index 42828edf81bd475b673a9d143f79c0d0711f14f5..fbfadeb83719b81f42724e79c59e92ed88fdece7 100644
|
||||
--- a/src/main/java/net/minecraft/network/PacketEncoder.java
|
||||
+++ b/src/main/java/net/minecraft/network/PacketEncoder.java
|
||||
@@ -40,7 +40,7 @@ public class PacketEncoder extends MessageToByteEncoder<Packet<?>> {
|
||||
int j = friendlyByteBuf.writerIndex();
|
||||
packet.write(friendlyByteBuf);
|
||||
int k = friendlyByteBuf.writerIndex() - j;
|
||||
- if (k > 8388608) {
|
||||
+ if (false && k > 8388608) { // Paper - disable
|
||||
throw new IllegalArgumentException("Packet too big (is " + k + ", should be less than 8388608): " + packet);
|
||||
} else {
|
||||
int l = channelHandlerContext.channel().attr(Connection.ATTRIBUTE_PROTOCOL).get().getId();
|
||||
@@ -54,7 +54,31 @@ public class PacketEncoder extends MessageToByteEncoder<Packet<?>> {
|
||||
throw var10;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ int packetLength = friendlyByteBuf.readableBytes();
|
||||
+ if (packetLength > MAX_PACKET_SIZE) {
|
||||
+ throw new PacketTooLargeException(packet, packetLength);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ private static int MAX_PACKET_SIZE = 8388608;
|
||||
+
|
||||
+ public static class PacketTooLargeException extends RuntimeException {
|
||||
+ private final Packet<?> packet;
|
||||
+
|
||||
+ PacketTooLargeException(Packet<?> packet, int packetLength) {
|
||||
+ super("PacketTooLarge - " + packet.getClass().getSimpleName() + " is " + packetLength + ". Max is " + MAX_PACKET_SIZE);
|
||||
+ this.packet = packet;
|
||||
+ }
|
||||
+
|
||||
+ public Packet<?> getPacket() {
|
||||
+ return packet;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java
|
||||
index 10c1f2d8a92f848c3f2be9d1d06fd254978e6dcc..74bfe0d3942259c45702b099efdc4e101a4e3022 100644
|
||||
--- a/src/main/java/net/minecraft/network/protocol/Packet.java
|
||||
+++ b/src/main/java/net/minecraft/network/protocol/Packet.java
|
||||
@@ -8,6 +8,12 @@ public interface Packet<T extends PacketListener> {
|
||||
|
||||
void handle(T listener);
|
||||
|
||||
+ // Paper start
|
||||
+ default boolean packetTooLarge(net.minecraft.network.Connection manager) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
default boolean isSkippable() {
|
||||
return false;
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java
|
||||
index 0e076173033278587df2b5dfbd01cc9005651eb5..dbd8b9b09b82c1b75e8be9dc7416d9f0863c8c87 100644
|
||||
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java
|
||||
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java
|
||||
@@ -31,6 +31,16 @@ public class ClientboundContainerSetContentPacket implements Packet<ClientGamePa
|
||||
this.carriedItem = buf.readItem();
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public boolean packetTooLarge(net.minecraft.network.Connection manager) {
|
||||
+ for (int i = 0 ; i < this.items.size() ; i++) {
|
||||
+ manager.send(new ClientboundContainerSetSlotPacket(this.containerId, this.stateId, i, this.items.get(i)));
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public void write(FriendlyByteBuf buf) {
|
||||
buf.writeByte(this.containerId);
|
||||
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
|
||||
index 932cca4d957c1fc212b7a514ea23e8dc7ab5b9d9..f47eeb70661661610ef1a96dd9da67785825c126 100644
|
||||
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
|
||||
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
|
||||
@@ -50,7 +50,7 @@ public class ClientboundLevelChunkPacketData {
|
||||
throw new RuntimeException("Can't read heightmap in packet for [" + x + ", " + z + "]");
|
||||
} else {
|
||||
int i = buf.readVarInt();
|
||||
- if (i > 2097152) {
|
||||
+ if (i > 2097152) { // Paper - diff on change - if this changes, update PacketEncoder
|
||||
throw new RuntimeException("Chunk Packet trying to allocate too much memory on read.");
|
||||
} else {
|
||||
this.buffer = new byte[i];
|
|
@ -1,113 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Thu, 15 Nov 2018 13:38:37 +0000
|
||||
Subject: [PATCH] force entity dismount during teleportation
|
||||
|
||||
Entities must be dismounted before teleportation in order to avoid
|
||||
multiple issues in the server with regards to teleportation, shamefully,
|
||||
too many plugins rely on the events firing, which means that not firing
|
||||
these events caues more issues than it solves;
|
||||
|
||||
In order to counteract this, Entity dismount/exit vehicle events have
|
||||
been modified to supress cancellation (and has a method to allow plugins
|
||||
to check if this has been set), noting that cancellation will be silently
|
||||
surpressed given that plugins are not expecting this event to not be cancellable.
|
||||
|
||||
This is a far from ideal scenario, however: given the current state of this
|
||||
event and other alternatives causing issues elsewhere, I believe that
|
||||
this is going to be the best soultion all around.
|
||||
|
||||
Improvements/suggestions welcome!
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index 7ca89b1a5bbeefd8622cb0f93e0235abcefbc033..dee47ff97e4f08154866d7628c3588a42f9892b9 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -2564,11 +2564,16 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
||||
}
|
||||
|
||||
public void removeVehicle() {
|
||||
+ // Paper start
|
||||
+ stopRiding(false);
|
||||
+ }
|
||||
+ public void stopRiding(boolean suppressCancellation) {
|
||||
+ // Paper end
|
||||
if (this.vehicle != null) {
|
||||
Entity entity = this.vehicle;
|
||||
|
||||
this.vehicle = null;
|
||||
- if (!entity.removePassenger(this)) this.vehicle = entity; // CraftBukkit
|
||||
+ if (!entity.removePassenger(this, suppressCancellation)) this.vehicle = entity; // CraftBukkit // Paper
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2599,7 +2604,10 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
||||
}
|
||||
}
|
||||
|
||||
- protected boolean removePassenger(Entity entity) { // CraftBukkit
|
||||
+ // Paper start
|
||||
+ protected boolean removePassenger(Entity entity) { return removePassenger(entity, false);}
|
||||
+ protected boolean removePassenger(Entity entity, boolean suppressCancellation) { // CraftBukkit
|
||||
+ // Paper end
|
||||
if (entity.getVehicle() == this) {
|
||||
throw new IllegalStateException("Use x.stopRiding(y), not y.removePassenger(x)");
|
||||
} else {
|
||||
@@ -2609,7 +2617,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
||||
if (this.getBukkitEntity() instanceof Vehicle && entity.getBukkitEntity() instanceof LivingEntity) {
|
||||
VehicleExitEvent event = new VehicleExitEvent(
|
||||
(Vehicle) this.getBukkitEntity(),
|
||||
- (LivingEntity) entity.getBukkitEntity()
|
||||
+ (LivingEntity) entity.getBukkitEntity(), !suppressCancellation // Paper
|
||||
);
|
||||
// Suppress during worldgen
|
||||
if (this.valid) {
|
||||
@@ -2623,7 +2631,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
||||
}
|
||||
// CraftBukkit end
|
||||
// Spigot start
|
||||
- org.spigotmc.event.entity.EntityDismountEvent event = new org.spigotmc.event.entity.EntityDismountEvent(entity.getBukkitEntity(), this.getBukkitEntity());
|
||||
+ org.spigotmc.event.entity.EntityDismountEvent event = new org.spigotmc.event.entity.EntityDismountEvent(entity.getBukkitEntity(), this.getBukkitEntity(), !suppressCancellation); // Paper
|
||||
// Suppress during worldgen
|
||||
if (this.valid) {
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index f800b3e4debcd141a75de9e6025a87e81cee083c..965c5724eb4927f017123c791c4a721c59b6db15 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -3438,9 +3438,15 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
|
||||
@Override
|
||||
public void stopRiding() {
|
||||
+ // Paper start
|
||||
+ stopRiding(false);
|
||||
+ }
|
||||
+ @Override
|
||||
+ public void stopRiding(boolean suppressCancellation) {
|
||||
+ // Paper end
|
||||
Entity entity = this.getVehicle();
|
||||
|
||||
- super.stopRiding();
|
||||
+ super.stopRiding(suppressCancellation); // Paper - suppress
|
||||
if (entity != null && entity != this.getVehicle() && !this.level().isClientSide) {
|
||||
this.dismountVehicle(entity);
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
index c7bcbc3f0542a74c30e29bded3bfc0e94daeab25..078986fb32eeecacc954ad6719e981ed8b3a2350 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
@@ -1148,7 +1148,13 @@ public abstract class Player extends LivingEntity {
|
||||
|
||||
@Override
|
||||
public void removeVehicle() {
|
||||
- super.removeVehicle();
|
||||
+ // Paper start
|
||||
+ stopRiding(false);
|
||||
+ }
|
||||
+ @Override
|
||||
+ public void stopRiding(boolean suppressCancellation) {
|
||||
+ // Paper end
|
||||
+ super.stopRiding(suppressCancellation); // Paper - suppress
|
||||
this.boardingCooldown = 0;
|
||||
}
|
||||
|
|
@ -1,117 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Sun, 7 Oct 2018 04:29:59 -0500
|
||||
Subject: [PATCH] Add more Zombie API
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.entity.monster.Zombie isSunSensitive()Z
|
||||
|
||||
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 86dc8bdfdc4eabef2266f3409366b373fb0ae13d..fed8b065172f40a2a5c251f46303fc4d72c9653a 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
|
||||
@@ -95,6 +95,7 @@ public class Zombie extends Monster {
|
||||
private int inWaterTime;
|
||||
public int conversionTime;
|
||||
private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field
|
||||
+ private boolean shouldBurnInDay = true; // Paper
|
||||
|
||||
public Zombie(EntityType<? extends Zombie> type, Level world) {
|
||||
super(type, world);
|
||||
@@ -263,6 +264,12 @@ public class Zombie extends Monster {
|
||||
super.aiStep();
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ public void stopDrowning() {
|
||||
+ this.conversionTime = -1;
|
||||
+ this.getEntityData().set(Zombie.DATA_DROWNED_CONVERSION_ID, false);
|
||||
+ }
|
||||
+ // Paper end
|
||||
public void startUnderWaterConversion(int ticksUntilWaterConversion) {
|
||||
this.lastTick = MinecraftServer.currentTick; // CraftBukkit
|
||||
this.conversionTime = ticksUntilWaterConversion;
|
||||
@@ -292,9 +299,15 @@ public class Zombie extends Monster {
|
||||
}
|
||||
|
||||
public boolean isSunSensitive() {
|
||||
- return true;
|
||||
+ return this.shouldBurnInDay; // Paper - use api value instead
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ public void setShouldBurnInDay(boolean shouldBurnInDay) {
|
||||
+ this.shouldBurnInDay = shouldBurnInDay;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public boolean hurt(DamageSource source, float amount) {
|
||||
if (!super.hurt(source, amount)) {
|
||||
@@ -414,6 +427,7 @@ public class Zombie extends Monster {
|
||||
nbt.putBoolean("CanBreakDoors", this.canBreakDoors());
|
||||
nbt.putInt("InWaterTime", this.isInWater() ? this.inWaterTime : -1);
|
||||
nbt.putInt("DrownedConversionTime", this.isUnderWaterConverting() ? this.conversionTime : -1);
|
||||
+ nbt.putBoolean("Paper.ShouldBurnInDay", this.shouldBurnInDay); // Paper
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -425,6 +439,11 @@ public class Zombie extends Monster {
|
||||
if (nbt.contains("DrownedConversionTime", 99) && nbt.getInt("DrownedConversionTime") > -1) {
|
||||
this.startUnderWaterConversion(nbt.getInt("DrownedConversionTime"));
|
||||
}
|
||||
+ // Paper start
|
||||
+ if (nbt.contains("Paper.ShouldBurnInDay")) {
|
||||
+ this.shouldBurnInDay = nbt.getBoolean("Paper.ShouldBurnInDay");
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java
|
||||
index 47ee56a5623e0ebd4263ef9b9b92434a26a08311..1e303c3686e2fe4e05efe5a630dd2c1cb0f9edea 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java
|
||||
@@ -87,6 +87,42 @@ public class CraftZombie extends CraftMonster implements Zombie {
|
||||
@Override
|
||||
public void setAgeLock(boolean b) {
|
||||
}
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public boolean isDrowning() {
|
||||
+ return getHandle().isUnderWaterConverting();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void startDrowning(int drownedConversionTime) {
|
||||
+ getHandle().startUnderWaterConversion(drownedConversionTime);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void stopDrowning() {
|
||||
+ getHandle().stopDrowning();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean shouldBurnInDay() {
|
||||
+ return getHandle().isSunSensitive();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isArmsRaised() {
|
||||
+ return getHandle().isAggressive();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setArmsRaised(final boolean raised) {
|
||||
+ getHandle().setAggressive(raised);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setShouldBurnInDay(boolean shouldBurnInDay) {
|
||||
+ getHandle().setShouldBurnInDay(shouldBurnInDay);
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
@Override
|
||||
public boolean getAgeLock() {
|
|
@ -1,57 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Fri, 16 Nov 2018 23:08:50 -0500
|
||||
Subject: [PATCH] Book Size Limits
|
||||
|
||||
Puts some limits on the size of books.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 9f87d35fb20b63b01252dc844ca3a584c16c7129..c5b682d08ab270d153eb600afe9a21bfa1305072 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -1126,6 +1126,45 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
||||
|
||||
@Override
|
||||
public void handleEditBook(ServerboundEditBookPacket packet) {
|
||||
+ // Paper start
|
||||
+ if (!this.cserver.isPrimaryThread()) {
|
||||
+ List<String> pageList = packet.getPages();
|
||||
+ long byteTotal = 0;
|
||||
+ int maxBookPageSize = io.papermc.paper.configuration.GlobalConfiguration.get().itemValidation.bookSize.pageMax;
|
||||
+ double multiplier = Math.max(0.3D, Math.min(1D, io.papermc.paper.configuration.GlobalConfiguration.get().itemValidation.bookSize.totalMultiplier));
|
||||
+ long byteAllowed = maxBookPageSize;
|
||||
+ for (String testString : pageList) {
|
||||
+ int byteLength = testString.getBytes(java.nio.charset.StandardCharsets.UTF_8).length;
|
||||
+ if (byteLength > 256 * 4) {
|
||||
+ ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send a book with with a page too large!");
|
||||
+ server.scheduleOnMain(() -> this.disconnect("Book too large!"));
|
||||
+ return;
|
||||
+ }
|
||||
+ byteTotal += byteLength;
|
||||
+ int length = testString.length();
|
||||
+ int multibytes = 0;
|
||||
+ if (byteLength != length) {
|
||||
+ for (char c : testString.toCharArray()) {
|
||||
+ if (c > 127) {
|
||||
+ multibytes++;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ byteAllowed += (maxBookPageSize * Math.min(1, Math.max(0.1D, (double) length / 255D))) * multiplier;
|
||||
+
|
||||
+ if (multibytes > 1) {
|
||||
+ // penalize MB
|
||||
+ byteAllowed -= multibytes;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (byteTotal > byteAllowed) {
|
||||
+ ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send too large of a book. Book Size: " + byteTotal + " - Allowed: "+ byteAllowed + " - Pages: " + pageList.size());
|
||||
+ server.scheduleOnMain(() -> this.disconnect("Book too large!"));
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
// CraftBukkit start
|
||||
if (this.lastBookTick + 20 > MinecraftServer.currentTick) {
|
||||
this.disconnect("Book edited too quickly!");
|
|
@ -1,71 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Sun, 7 Oct 2018 12:05:28 -0700
|
||||
Subject: [PATCH] Add PlayerConnectionCloseEvent
|
||||
|
||||
This event is invoked when a player has disconnected. It is guaranteed that,
|
||||
if the server is in online-mode, that the provided uuid and username have been
|
||||
validated.
|
||||
|
||||
The event is invoked for players who have not yet logged into the world, whereas
|
||||
PlayerQuitEvent is only invoked on players who have logged into the world.
|
||||
|
||||
The event is invoked for players who have already logged into the world,
|
||||
although whether or not the player exists in the world at the time of
|
||||
firing is undefined. (That is, whether the plugin can retrieve a Player object
|
||||
using the event parameters is undefined). However, it is guaranteed that this
|
||||
event is invoked AFTER PlayerQuitEvent, if the player has already logged into
|
||||
the world.
|
||||
|
||||
This event is guaranteed to never fire unless AsyncPlayerPreLoginEvent has
|
||||
been called beforehand, and this event may not be called in parallel with
|
||||
AsyncPlayerPreLoginEvent for the same connection.
|
||||
|
||||
Cancelling the AsyncPlayerPreLoginEvent guarantees the corresponding
|
||||
PlayerConnectionCloseEvent is never called.
|
||||
|
||||
The event may be invoked asynchronously or synchronously. As it stands,
|
||||
it is never invoked asynchronously. However, plugins should check
|
||||
Event#isAsynchronous to be future-proof.
|
||||
|
||||
On purpose, the deprecated PlayerPreLoginEvent event is left out of the
|
||||
API spec for this event. Plugins should not be using that event, and
|
||||
how PlayerPreLoginEvent interacts with PlayerConnectionCloseEvent
|
||||
is undefined.
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.server.network.ServerLoginPacketListenerImpl$State
|
||||
public net.minecraft.server.network.ServerLoginPacketListenerImpl state
|
||||
public net.minecraft.server.network.ServerLoginPacketListenerImpl gameProfile
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
|
||||
index f5106ed464d496420ac575b09d6c9a7dfeb87bec..b293ac99e436b02c9ef30994a394bcc53ebbf2f9 100644
|
||||
--- a/src/main/java/net/minecraft/network/Connection.java
|
||||
+++ b/src/main/java/net/minecraft/network/Connection.java
|
||||
@@ -509,6 +509,26 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
this.getPacketListener().onDisconnect(Component.translatable("multiplayer.disconnect.generic"));
|
||||
}
|
||||
this.queue.clear(); // Free up packet queue.
|
||||
+ // Paper start - Add PlayerConnectionCloseEvent
|
||||
+ final PacketListener packetListener = this.getPacketListener();
|
||||
+ if (packetListener instanceof net.minecraft.server.network.ServerGamePacketListenerImpl) {
|
||||
+ /* Player was logged in */
|
||||
+ final net.minecraft.server.network.ServerGamePacketListenerImpl playerConnection = (net.minecraft.server.network.ServerGamePacketListenerImpl) packetListener;
|
||||
+ new com.destroystokyo.paper.event.player.PlayerConnectionCloseEvent(playerConnection.player.getUUID(),
|
||||
+ playerConnection.player.getScoreboardName(), ((java.net.InetSocketAddress)address).getAddress(), false).callEvent();
|
||||
+ } else if (packetListener instanceof net.minecraft.server.network.ServerLoginPacketListenerImpl) {
|
||||
+ /* Player is login stage */
|
||||
+ final net.minecraft.server.network.ServerLoginPacketListenerImpl loginListener = (net.minecraft.server.network.ServerLoginPacketListenerImpl) packetListener;
|
||||
+ switch (loginListener.state) {
|
||||
+ case READY_TO_ACCEPT:
|
||||
+ case DELAY_ACCEPT:
|
||||
+ case ACCEPTED:
|
||||
+ final com.mojang.authlib.GameProfile profile = loginListener.gameProfile; /* Should be non-null at this stage */
|
||||
+ new com.destroystokyo.paper.event.player.PlayerConnectionCloseEvent(profile.getId(), profile.getName(),
|
||||
+ ((java.net.InetSocketAddress)address).getAddress(), false).callEvent();
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Tue, 18 Dec 2018 02:15:08 +0000
|
||||
Subject: [PATCH] Prevent Enderman from loading chunks
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java
|
||||
index 06a0a06f3f4ed20f151ddac35ae7d56852e191ae..f7ad34f38d26ab08bb5dd788bc70ba01b53fc1a1 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java
|
||||
@@ -510,7 +510,8 @@ public class EnderMan extends Monster implements NeutralMob {
|
||||
int j = Mth.floor(this.enderman.getY() + randomsource.nextDouble() * 2.0D);
|
||||
int k = Mth.floor(this.enderman.getZ() - 1.0D + randomsource.nextDouble() * 2.0D);
|
||||
BlockPos blockposition = new BlockPos(i, j, k);
|
||||
- BlockState iblockdata = world.getBlockState(blockposition);
|
||||
+ BlockState iblockdata = world.getBlockStateIfLoaded(blockposition); // Paper
|
||||
+ if (iblockdata == null) return; // Paper
|
||||
BlockPos blockposition1 = blockposition.below();
|
||||
BlockState iblockdata1 = world.getBlockState(blockposition1);
|
||||
BlockState iblockdata2 = this.enderman.getCarriedBlock();
|
||||
@@ -554,7 +555,8 @@ public class EnderMan extends Monster implements NeutralMob {
|
||||
int j = Mth.floor(this.enderman.getY() + randomsource.nextDouble() * 3.0D);
|
||||
int k = Mth.floor(this.enderman.getZ() - 2.0D + randomsource.nextDouble() * 4.0D);
|
||||
BlockPos blockposition = new BlockPos(i, j, k);
|
||||
- BlockState iblockdata = world.getBlockState(blockposition);
|
||||
+ BlockState iblockdata = world.getBlockStateIfLoaded(blockposition); // Paper
|
||||
+ if (iblockdata == null) return; // Paper
|
||||
Vec3 vec3d = new Vec3((double) this.enderman.getBlockX() + 0.5D, (double) j + 0.5D, (double) this.enderman.getBlockZ() + 0.5D);
|
||||
Vec3 vec3d1 = new Vec3((double) i + 0.5D, (double) j + 0.5D, (double) k + 0.5D);
|
||||
BlockHitResult movingobjectpositionblock = world.clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this.enderman));
|
|
@ -1,164 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach@zachbr.io>
|
||||
Date: Wed, 2 Jan 2019 00:35:43 -0600
|
||||
Subject: [PATCH] Add APIs to replace OfflinePlayer#getLastPlayed
|
||||
|
||||
Currently OfflinePlayer#getLastPlayed could more accurately be described
|
||||
as "OfflinePlayer#getLastTimeTheirDataWasSaved".
|
||||
|
||||
The API doc says it should return the last time the server "witnessed"
|
||||
the player, whilst also saying it should return the last time they
|
||||
logged in. The current implementation does neither.
|
||||
|
||||
Given this interesting contradiction in the API documentation and the
|
||||
current defacto implementation, I've elected to deprecate (with no
|
||||
intent to remove) and replace it with two new methods, clearly named and
|
||||
documented as to their purpose.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 715314de7a92a8e06f82c6bff5fe74e3b23044f8..b59ad5f0cc12082db0c885b29d88c526a4029e22 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -243,6 +243,7 @@ public class ServerPlayer extends Player {
|
||||
public int latency;
|
||||
public boolean wonGame;
|
||||
private int containerUpdateDelay; // Paper
|
||||
+ public long loginTime; // Paper
|
||||
// Paper start - cancellable death event
|
||||
public boolean queueHealthUpdatePacket = false;
|
||||
public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket;
|
||||
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
index 2bccba03bb12cf17a82c1e54c2bb10535b7c8964..5657493e215a17f3132f9d411424875160fda6d9 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
@@ -189,6 +189,7 @@ public abstract class PlayerList {
|
||||
|
||||
public void placeNewPlayer(Connection connection, ServerPlayer player) {
|
||||
player.isRealPlayer = true; // Paper
|
||||
+ player.loginTime = System.currentTimeMillis(); // Paper
|
||||
GameProfile gameprofile = player.getGameProfile();
|
||||
GameProfileCache usercache = this.server.getProfileCache();
|
||||
String s;
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
|
||||
index aac78c13361b19efa7b43a0c95458390f1ba8340..f572a74b85df36a6da76b78ec29d807273867537 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
|
||||
@@ -261,6 +261,61 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa
|
||||
return this.getData() != null;
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public long getLastLogin() {
|
||||
+ Player player = getPlayer();
|
||||
+ if (player != null) return player.getLastLogin();
|
||||
+
|
||||
+ CompoundTag data = getPaperData();
|
||||
+
|
||||
+ if (data != null) {
|
||||
+ if (data.contains("LastLogin")) {
|
||||
+ return data.getLong("LastLogin");
|
||||
+ } else {
|
||||
+ // if the player file cannot provide accurate data, this is probably the closest we can approximate
|
||||
+ File file = getDataFile();
|
||||
+ return file.lastModified();
|
||||
+ }
|
||||
+ } else {
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public long getLastSeen() {
|
||||
+ Player player = getPlayer();
|
||||
+ if (player != null) return player.getLastSeen();
|
||||
+
|
||||
+ CompoundTag data = getPaperData();
|
||||
+
|
||||
+ if (data != null) {
|
||||
+ if (data.contains("LastSeen")) {
|
||||
+ return data.getLong("LastSeen");
|
||||
+ } else {
|
||||
+ // if the player file cannot provide accurate data, this is probably the closest we can approximate
|
||||
+ File file = getDataFile();
|
||||
+ return file.lastModified();
|
||||
+ }
|
||||
+ } else {
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private CompoundTag getPaperData() {
|
||||
+ CompoundTag result = getData();
|
||||
+
|
||||
+ if (result != null) {
|
||||
+ if (!result.contains("Paper")) {
|
||||
+ result.put("Paper", new CompoundTag());
|
||||
+ }
|
||||
+ result = result.getCompound("Paper");
|
||||
+ }
|
||||
+
|
||||
+ return result;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public Location getLastDeathLocation() {
|
||||
if (this.getData().contains("LastDeathLocation", 10)) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index 1c09e955e34380b99572cc5950806417ac10bfc8..a9f80c019f5a127d9273833608917c59748ae867 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -193,6 +193,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
private org.bukkit.event.player.PlayerResourcePackStatusEvent.Status resourcePackStatus;
|
||||
private String resourcePackHash;
|
||||
private static final boolean DISABLE_CHANNEL_LIMIT = System.getProperty("paper.disableChannelLimit") != null; // Paper - add a flag to disable the channel limit
|
||||
+ private long lastSaveTime;
|
||||
// Paper end
|
||||
|
||||
public CraftPlayer(CraftServer server, ServerPlayer entity) {
|
||||
@@ -1950,6 +1951,18 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
this.firstPlayed = firstPlayed;
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public long getLastLogin() {
|
||||
+ return getHandle().loginTime;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public long getLastSeen() {
|
||||
+ return isOnline() ? System.currentTimeMillis() : this.lastSaveTime;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
public void readExtraData(CompoundTag nbttagcompound) {
|
||||
this.hasPlayedBefore = true;
|
||||
if (nbttagcompound.contains("bukkit")) {
|
||||
@@ -1972,6 +1985,8 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
}
|
||||
|
||||
public void setExtraData(CompoundTag nbttagcompound) {
|
||||
+ this.lastSaveTime = System.currentTimeMillis(); // Paper
|
||||
+
|
||||
if (!nbttagcompound.contains("bukkit")) {
|
||||
nbttagcompound.put("bukkit", new CompoundTag());
|
||||
}
|
||||
@@ -1986,6 +2001,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
data.putLong("firstPlayed", this.getFirstPlayed());
|
||||
data.putLong("lastPlayed", System.currentTimeMillis());
|
||||
data.putString("lastKnownName", handle.getScoreboardName());
|
||||
+
|
||||
+ // Paper start - persist for use in offline save data
|
||||
+ if (!nbttagcompound.contains("Paper")) {
|
||||
+ nbttagcompound.put("Paper", new CompoundTag());
|
||||
+ }
|
||||
+
|
||||
+ CompoundTag paper = nbttagcompound.getCompound("Paper");
|
||||
+ paper.putLong("LastLogin", handle.loginTime);
|
||||
+ paper.putLong("LastSeen", System.currentTimeMillis());
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,24 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: connorhartley <vectrixu+gh@gmail.com>
|
||||
Date: Mon, 7 Jan 2019 14:43:48 -0600
|
||||
Subject: [PATCH] Workaround for vehicle tracking issue on disconnect
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index b59ad5f0cc12082db0c885b29d88c526a4029e22..d29e13aa7bbfbab54f8a3d73279891d65e957d7e 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -1644,6 +1644,13 @@ public class ServerPlayer extends Player {
|
||||
public void disconnect() {
|
||||
this.disconnected = true;
|
||||
this.ejectPassengers();
|
||||
+
|
||||
+ // Paper start - Workaround an issue where the vehicle doesn't track the passenger disconnection dismount.
|
||||
+ if (this.isPassenger() && this.getVehicle() instanceof ServerPlayer) {
|
||||
+ this.stopRiding();
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
if (this.isSleeping()) {
|
||||
this.stopSleepInBed(true, false);
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach@zachbr.io>
|
||||
Date: Mon, 4 Feb 2019 23:33:24 -0500
|
||||
Subject: [PATCH] Block Entity#remove from being called on Players
|
||||
|
||||
This doesn't result in the same behavior as other entities and causes
|
||||
several problems. Anyone ever complain about the "Cannot send chat
|
||||
message" thing? That's one of the issues this causes, among others.
|
||||
|
||||
If a plugin developer can come up with a valid reason to call this on a
|
||||
Player we will look at limiting the scope of this change. It appears to
|
||||
be unintentional in the few cases we've seen so far.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index a9f80c019f5a127d9273833608917c59748ae867..08404472a89192fb0cbae0192793c4c4ae63a9bb 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -2874,6 +2874,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
public void resetCooldown() {
|
||||
getHandle().resetAttackStrengthTicker();
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public void remove() {
|
||||
+ if (this.getHandle().getClass().equals(ServerPlayer.class)) { // special case for NMS plugins inheriting
|
||||
+ throw new UnsupportedOperationException("Calling Entity#remove on players produces undefined (bad) behavior");
|
||||
+ } else {
|
||||
+ super.remove();
|
||||
+ }
|
||||
+ }
|
||||
// Paper end
|
||||
// Spigot start
|
||||
private final Player.Spigot spigot = new Player.Spigot()
|
|
@ -1,47 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 6 Feb 2019 00:20:33 -0500
|
||||
Subject: [PATCH] BlockDestroyEvent
|
||||
|
||||
Adds an event for when the server is going to destroy a current block,
|
||||
potentially causing it to drop. This event can be cancelled to avoid
|
||||
the block destruction, such as preventing signs from popping when
|
||||
floating in the air.
|
||||
|
||||
This can replace many uses of BlockPhysicsEvent
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
||||
index 18234d71eba7d2a2874f3e5c9628d82970acc033..b3a0f4dd651dda29d2064b629da67378c00a6a78 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/Level.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
||||
@@ -30,6 +30,7 @@ import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
+import io.papermc.paper.util.MCUtil;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.FullChunkStatus;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
@@ -666,8 +667,21 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
return false;
|
||||
} else {
|
||||
FluidState fluid = this.getFluidState(pos);
|
||||
+ // Paper start - while the above setAir method is named same and looks very similar
|
||||
+ // they are NOT used with same intent and the above should not fire this event. The above method is more of a BlockSetToAirEvent,
|
||||
+ // it doesn't imply destruction of a block that plays a sound effect / drops an item.
|
||||
+ boolean playEffect = true;
|
||||
+ if (com.destroystokyo.paper.event.block.BlockDestroyEvent.getHandlerList().getRegisteredListeners().length > 0) {
|
||||
+ com.destroystokyo.paper.event.block.BlockDestroyEvent event = new com.destroystokyo.paper.event.block.BlockDestroyEvent(MCUtil.toBukkitBlock(this, pos), fluid.createLegacyBlock().createCraftBlockData(), drop);
|
||||
+ if (!event.callEvent()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ playEffect = event.playEffect();
|
||||
+ drop = event.willDrop();
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
- if (!(iblockdata.getBlock() instanceof BaseFireBlock)) {
|
||||
+ if (playEffect && !(iblockdata.getBlock() instanceof BaseFireBlock)) { // Paper
|
||||
this.levelEvent(2001, pos, Block.getId(iblockdata));
|
||||
}
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Callahan <mr.callahhh@gmail.com>
|
||||
Date: Wed, 8 Apr 2020 02:42:14 -0500
|
||||
Subject: [PATCH] Async command map building
|
||||
|
||||
This adds a custom pool inorder to make sure that they are closed
|
||||
without much though, as it doesn't matter if the client is not sent
|
||||
commands if the server is restarting. Using the default async pool caused issues to arise
|
||||
due to the shutdown logic generally being much later.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java
|
||||
index e3394864e29357fec036f9e616472aeab95d035e..b7f1569c662df13f278fc704cabec0400ba7c382 100644
|
||||
--- a/src/main/java/net/minecraft/commands/Commands.java
|
||||
+++ b/src/main/java/net/minecraft/commands/Commands.java
|
||||
@@ -398,6 +398,24 @@ public class Commands {
|
||||
if ( org.spigotmc.SpigotConfig.tabComplete < 0 ) return; // Spigot
|
||||
// CraftBukkit start
|
||||
// Register Vanilla commands into builtRoot as before
|
||||
+ // Paper start - Async command map building
|
||||
+ COMMAND_SENDING_POOL.execute(() -> {
|
||||
+ this.sendAsync(player);
|
||||
+ });
|
||||
+ }
|
||||
+
|
||||
+ public static final java.util.concurrent.ThreadPoolExecutor COMMAND_SENDING_POOL = new java.util.concurrent.ThreadPoolExecutor(
|
||||
+ 0, 2, 60L, java.util.concurrent.TimeUnit.SECONDS,
|
||||
+ new java.util.concurrent.LinkedBlockingQueue<>(),
|
||||
+ new com.google.common.util.concurrent.ThreadFactoryBuilder()
|
||||
+ .setNameFormat("Paper Async Command Builder Thread Pool - %1$d")
|
||||
+ .setUncaughtExceptionHandler(new net.minecraft.DefaultUncaughtExceptionHandlerWithName(net.minecraft.server.MinecraftServer.LOGGER))
|
||||
+ .build(),
|
||||
+ new java.util.concurrent.ThreadPoolExecutor.DiscardPolicy()
|
||||
+ );
|
||||
+
|
||||
+ private void sendAsync(ServerPlayer player) {
|
||||
+ // Paper end - Async command map building
|
||||
Map<CommandNode<CommandSourceStack>, CommandNode<SharedSuggestionProvider>> map = Maps.newIdentityHashMap(); // Use identity to prevent aliasing issues
|
||||
RootCommandNode vanillaRoot = new RootCommandNode();
|
||||
|
||||
@@ -415,7 +433,14 @@ public class Commands {
|
||||
for (CommandNode node : rootcommandnode.getChildren()) {
|
||||
bukkit.add(node.getName());
|
||||
}
|
||||
+ // Paper start - Async command map building
|
||||
+ net.minecraft.server.MinecraftServer.getServer().execute(() -> {
|
||||
+ runSync(player, bukkit, rootcommandnode);
|
||||
+ });
|
||||
+ }
|
||||
|
||||
+ private void runSync(ServerPlayer player, Collection<String> bukkit, RootCommandNode<SharedSuggestionProvider> rootcommandnode) {
|
||||
+ // Paper end - Async command map building
|
||||
PlayerCommandSendEvent event = new PlayerCommandSendEvent(player.getBukkitEntity(), new LinkedHashSet<>(bukkit));
|
||||
event.getPlayer().getServer().getPluginManager().callEvent(event);
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 1a74b7c252d16e5ab2c303e6e96c62e78ef9311c..d84ed437e91a620c294533ddcb098cc11bc16c1f 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -895,6 +895,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
}
|
||||
|
||||
MinecraftServer.LOGGER.info("Stopping server");
|
||||
+ Commands.COMMAND_SENDING_POOL.shutdownNow(); // Paper - Shutdown and don't bother finishing
|
||||
MinecraftTimings.stopServer(); // Paper
|
||||
// CraftBukkit start
|
||||
if (this.server != null) {
|
Loading…
Add table
Add a link
Reference in a new issue