Merge remote-tracking branch 'leaf/dev/1.17' into dev/1.17
This commit is contained in:
commit
5e9c53b5b7
30 changed files with 672 additions and 1483 deletions
3771
patches/server/0257-Asynchronous-chunk-IO-and-loading.patch
Normal file
3771
patches/server/0257-Asynchronous-chunk-IO-and-loading.patch
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,90 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Mon, 3 Sep 2018 18:20:03 -0500
|
||||
Subject: [PATCH] Add ray tracing methods to LivingEntity
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java
|
||||
index 49fd3486a6c595749f33bbe1c1bec0454e4725c5..5c290f263fc2b643987c96ea75729bf1ff493760 100644
|
||||
--- a/src/main/java/net/minecraft/server/MCUtil.java
|
||||
+++ b/src/main/java/net/minecraft/server/MCUtil.java
|
||||
@@ -482,6 +482,18 @@ public final class MCUtil {
|
||||
return getNMSWorld(entity.getWorld());
|
||||
}
|
||||
|
||||
+ public static ClipContext.Fluid getNMSFluidCollisionOption(com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode) {
|
||||
+ switch (fluidMode) {
|
||||
+ case NEVER:
|
||||
+ return ClipContext.Fluid.NONE;
|
||||
+ case SOURCE_ONLY:
|
||||
+ return ClipContext.Fluid.SOURCE_ONLY;
|
||||
+ case ALWAYS:
|
||||
+ return ClipContext.Fluid.ANY;
|
||||
+ }
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
public static BlockFace toBukkitBlockFace(Direction enumDirection) {
|
||||
switch (enumDirection) {
|
||||
case DOWN:
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index acf6f04fa229fb0850217ff3d50bf3b8c16cafdf..773c1e0ed3e10157c968d84b19947d99bb01371a 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -3686,6 +3686,23 @@ public abstract class LivingEntity extends Entity {
|
||||
}
|
||||
|
||||
// Paper start
|
||||
+ public HitResult getRayTrace(int maxDistance) {
|
||||
+ return getRayTrace(maxDistance, ClipContext.Fluid.NONE);
|
||||
+ }
|
||||
+
|
||||
+ public HitResult getRayTrace(int maxDistance, ClipContext.Fluid fluidCollisionOption) {
|
||||
+ if (maxDistance < 1 || maxDistance > 120) {
|
||||
+ throw new IllegalArgumentException("maxDistance must be between 1-120");
|
||||
+ }
|
||||
+
|
||||
+ Vec3 start = new Vec3(getX(), getY() + getEyeHeight(), getZ());
|
||||
+ org.bukkit.util.Vector dir = getBukkitEntity().getLocation().getDirection().multiply(maxDistance);
|
||||
+ Vec3 end = new Vec3(start.x + dir.getX(), start.y + dir.getY(), start.z + dir.getZ());
|
||||
+ ClipContext raytrace = new ClipContext(start, end, ClipContext.Block.OUTLINE, fluidCollisionOption, this);
|
||||
+
|
||||
+ return level.clip(raytrace);
|
||||
+ }
|
||||
+
|
||||
public int shieldBlockingDelay = level.paperConfig.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 5194da5a141718390a317d75b31205f951cec7a2..cb4c15d17ea3f22e6baa73ba6ce2a18e34ac4b00 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
|
||||
@@ -190,6 +190,28 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
|
||||
return blocks.get(0);
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public Block getTargetBlock(int maxDistance, com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode) {
|
||||
+ net.minecraft.world.phys.HitResult rayTrace = getHandle().getRayTrace(maxDistance, net.minecraft.server.MCUtil.getNMSFluidCollisionOption(fluidMode));
|
||||
+ return !(rayTrace instanceof net.minecraft.world.phys.BlockHitResult) ? null : org.bukkit.craftbukkit.block.CraftBlock.at(getHandle().level, ((net.minecraft.world.phys.BlockHitResult)rayTrace).getBlockPos());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public org.bukkit.block.BlockFace getTargetBlockFace(int maxDistance, com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode) {
|
||||
+ net.minecraft.world.phys.HitResult rayTrace = getHandle().getRayTrace(maxDistance, net.minecraft.server.MCUtil.getNMSFluidCollisionOption(fluidMode));
|
||||
+ return !(rayTrace instanceof net.minecraft.world.phys.BlockHitResult) ? null : net.minecraft.server.MCUtil.toBukkitBlockFace(((net.minecraft.world.phys.BlockHitResult)rayTrace).getDirection());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public com.destroystokyo.paper.block.TargetBlockInfo getTargetBlockInfo(int maxDistance, com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode) {
|
||||
+ net.minecraft.world.phys.HitResult rayTrace = getHandle().getRayTrace(maxDistance, net.minecraft.server.MCUtil.getNMSFluidCollisionOption(fluidMode));
|
||||
+ return !(rayTrace instanceof net.minecraft.world.phys.BlockHitResult) ? null :
|
||||
+ new com.destroystokyo.paper.block.TargetBlockInfo(org.bukkit.craftbukkit.block.CraftBlock.at(getHandle().level, ((net.minecraft.world.phys.BlockHitResult)rayTrace).getBlockPos()),
|
||||
+ net.minecraft.server.MCUtil.toBukkitBlockFace(((net.minecraft.world.phys.BlockHitResult)rayTrace).getDirection()));
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public List<Block> getLastTwoTargetBlocks(Set<Material> transparent, int maxDistance) {
|
||||
return this.getLineOfSight(transparent, maxDistance, 2);
|
|
@ -0,0 +1,32 @@
|
|||
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 f8155d7edb4e13c2ec5ed832231f02ee6eff3f35..91dc9e3b02462211a6964204f5409fbae98027e6 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -2199,6 +2199,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
connection.send(new net.minecraft.network.protocol.game.ClientboundOpenBookPacket(net.minecraft.world.InteractionHand.MAIN_HAND));
|
||||
connection.send(new net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket(0, slot, inventory.getSelected()));
|
||||
}
|
||||
+
|
||||
+ @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
|
376
patches/server/0260-Improve-death-events.patch
Normal file
376
patches/server/0260-Improve-death-events.patch
Normal file
|
@ -0,0 +1,376 @@
|
|||
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.
|
||||
|
||||
TODO 1.17: this needs to be checked (actually get off your lazy ass and cancel the events) for the following entities,
|
||||
maybe more (please check patch overrides for drops for more):
|
||||
- players, armor stands, foxes, chested donkeys/llamas
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 171500918c8ee248689909ae97230eb18adc33e5..44385d07b2deedffd95bcc428d9d8d3f785143db 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -218,6 +218,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;
|
||||
@@ -751,6 +755,15 @@ public class ServerPlayer extends Player {
|
||||
Component defaultMessage = this.getCombatTracker().getDeathMessage();
|
||||
|
||||
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) {
|
||||
@@ -898,8 +911,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 773c1e0ed3e10157c968d84b19947d99bb01371a..fd0c307a4b340661ba9aff9ae4e0055c139a1ebd 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -261,6 +261,7 @@ public abstract class LivingEntity extends Entity {
|
||||
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() {
|
||||
@@ -1446,13 +1447,12 @@ public abstract class LivingEntity extends Entity {
|
||||
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);
|
||||
@@ -1601,7 +1601,7 @@ public abstract class LivingEntity extends Entity {
|
||||
if (!this.isRemoved() && !this.dead) {
|
||||
Entity entity = source.getEntity();
|
||||
LivingEntity entityliving = this.getKillCredit();
|
||||
-
|
||||
+ /* // Paper - move down to make death event cancellable - this is the runKillTrigger below
|
||||
if (this.deathScore >= 0 && entityliving != null) {
|
||||
entityliving.awardKillScore(this, this.deathScore, source);
|
||||
}
|
||||
@@ -1609,20 +1609,43 @@ public abstract class LivingEntity extends Entity {
|
||||
if (this.isSleeping()) {
|
||||
this.stopSleeping();
|
||||
}
|
||||
+ */ // Paper - move down to make death event cancellable - this is the runKillTrigger below
|
||||
+
|
||||
|
||||
this.dead = true;
|
||||
- this.getCombatTracker().recheckStatus();
|
||||
+ // Paper - moved into if below
|
||||
if (this.level instanceof ServerLevel) {
|
||||
if (entity != null) {
|
||||
- entity.killed((ServerLevel) this.level, this);
|
||||
+ // Paper - move below into if for onKill
|
||||
}
|
||||
|
||||
- this.dropAllDeathLoot(source);
|
||||
+ // Paper start
|
||||
+ org.bukkit.event.entity.EntityDeathEvent deathEvent = this.dropAllDeathLoot(source);
|
||||
+ if (deathEvent == null || !deathEvent.isCancelled()) {
|
||||
+ if (this.deathScore >= 0 && entityliving != null) {
|
||||
+ entityliving.awardKillScore(this, this.deathScore, source);
|
||||
+ }
|
||||
+
|
||||
+ if (this.isSleeping()) {
|
||||
+ this.stopSleeping();
|
||||
+ }
|
||||
+
|
||||
+ this.getCombatTracker().recheckStatus();
|
||||
+ if (entity != null) {
|
||||
+ entity.killed((ServerLevel) this.level, this);
|
||||
+ }
|
||||
+ } else {
|
||||
+ this.dead = false;
|
||||
+ this.setHealth((float) deathEvent.getReviveHealth());
|
||||
+ }
|
||||
+ // Paper end
|
||||
this.createWitherRose(entityliving);
|
||||
}
|
||||
|
||||
+ if (this.dead) { // Paper
|
||||
this.level.broadcastEntityEvent(this, (byte) 3);
|
||||
this.setPose(Pose.DYING);
|
||||
+ } // Paper
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1630,7 +1653,7 @@ public abstract class LivingEntity extends Entity {
|
||||
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();
|
||||
@@ -1658,7 +1681,7 @@ public abstract class LivingEntity extends Entity {
|
||||
}
|
||||
}
|
||||
|
||||
- protected void dropAllDeathLoot(DamageSource source) {
|
||||
+ protected org.bukkit.event.entity.EntityDeathEvent dropAllDeathLoot(DamageSource source) { // Paper
|
||||
Entity entity = source.getEntity();
|
||||
int i;
|
||||
|
||||
@@ -1676,15 +1699,18 @@ public abstract class LivingEntity extends Entity {
|
||||
this.dropCustomDeathLoot(source, i, flag);
|
||||
}
|
||||
// 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() {
|
||||
@@ -1762,8 +1788,9 @@ public abstract class LivingEntity extends Entity {
|
||||
return SoundEvents.GENERIC_HURT;
|
||||
}
|
||||
|
||||
+
|
||||
@Nullable
|
||||
- protected SoundEvent getDeathSound() {
|
||||
+ public final SoundEvent getDeathSoundPublic() { return this.getDeathSound(); } protected SoundEvent getDeathSound() { // Paper - provide PUBLIC accessor, overrides are hell to deal with
|
||||
return SoundEvents.GENERIC_DEATH;
|
||||
}
|
||||
|
||||
@@ -2477,7 +2504,7 @@ public abstract class LivingEntity extends Entity {
|
||||
|
||||
}
|
||||
|
||||
- protected float getSoundVolume() {
|
||||
+ public final float getSoundVolumePublic() { return this.getSoundVolume(); } protected float getSoundVolume() { // Paper - provide PUBLIC accessor, overrides are hell
|
||||
return 1.0F;
|
||||
}
|
||||
|
||||
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 c1cdb1905536bda76f34ad3fc796996443839767..31f4e4a93ea5fd3ffe7e60dff2e2a9642b51daa2 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/Fox.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/Fox.java
|
||||
@@ -691,15 +691,25 @@ public class Fox extends Animal {
|
||||
}
|
||||
|
||||
@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 224eca7d20cf4b890a6bc1b314d566e02e716762..7281eb294ddd178ba742088d3c61bf3d529ff0c4 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
|
||||
@@ -68,11 +68,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 4adde11daa5ca97a2bf9c164c43c5c011a89b33d..cb9969d768b13863722aad3dc5daad3c10bb264a 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
|
||||
@@ -755,7 +755,8 @@ public class ArmorStand extends LivingEntity {
|
||||
|
||||
@Override
|
||||
public void kill() {
|
||||
- org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, drops); // CraftBukkit - call event
|
||||
+ 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
|
||||
this.remove(Entity.RemovalReason.KILLED);
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index 91dc9e3b02462211a6964204f5409fbae98027e6..22032108fdaed14663a9d7e0b6757eef5237c4dd 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -1849,7 +1849,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
}
|
||||
|
||||
public void sendHealthUpdate() {
|
||||
- this.getHandle().connection.send(new ClientboundSetHealthPacket(this.getScaledHealth(), this.getHandle().getFoodData().getFoodLevel(), this.getHandle().getFoodData().getSaturationLevel()));
|
||||
+ // Paper start - cancellable death event
|
||||
+ ClientboundSetHealthPacket packet = new ClientboundSetHealthPacket(this.getScaledHealth(), this.getHandle().getFoodData().getFoodLevel(), this.getHandle().getFoodData().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 a81fc5212648056766824113b372a7c772c19e5a..f0c3255e0b4e1ecf4a54213c6458c92a7389b134 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
@@ -770,9 +770,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()) {
|
||||
@@ -788,8 +795,15 @@ public class CraftEventFactory {
|
||||
CraftPlayer entity = victim.getBukkitEntity();
|
||||
PlayerDeathEvent event = new PlayerDeathEvent(entity, drops, victim.getExpReward(), 0, deathMessage, stringDeathMessage); // Paper - Adventure
|
||||
event.setKeepInventory(keepInventory);
|
||||
+ 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();
|
||||
@@ -806,6 +820,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.getDeathSoundPublic();
|
||||
+ event.setDeathSound(soundEffect != null ? org.bukkit.craftbukkit.CraftSound.getBukkit(soundEffect) : null);
|
||||
+ event.setDeathSoundCategory(org.bukkit.SoundCategory.valueOf(victim.getSoundSource().name()));
|
||||
+ event.setDeathSoundVolume(victim.getSoundVolumePublic());
|
||||
+ 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
|
||||
*/
|
|
@ -0,0 +1,31 @@
|
|||
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 8b3cf3b882ea6c0d48df8b551f4b85b87b889c58..dd4deb08eb3ed15a156269a11d3d43abfd61fe5b 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
@@ -339,6 +339,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
|
||||
for (BlockState blockstate : blocks) {
|
||||
blockstate.update(true, false);
|
||||
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 f2c9755c2b55bee2a0b981313e1fcd1f8ab5e3d8..52de9852f87d346714a950b60a0004d386ac10f0 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
|
||||
@@ -239,7 +239,7 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement
|
||||
// CraftBukkit start
|
||||
@Override
|
||||
public boolean onlyOpCanSetNbt() {
|
||||
- return true;
|
||||
+ return false; // Paper
|
||||
}
|
||||
// CraftBukkit end
|
||||
}
|
289
patches/server/0262-Mob-Pathfinding-API.patch
Normal file
289
patches/server/0262-Mob-Pathfinding-API.patch
Normal file
|
@ -0,0 +1,289 @@
|
|||
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
|
||||
|
||||
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..92d1bb8b9cdb9eb0c04574c0b6ba5acdca9fb377
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java
|
||||
@@ -0,0 +1,139 @@
|
||||
+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 final net.minecraft.world.entity.Mob entity;
|
||||
+
|
||||
+ public PaperPathfinder(net.minecraft.world.entity.Mob entity) {
|
||||
+ this.entity = entity;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Mob getEntity() {
|
||||
+ return entity.getBukkitMob();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void stopPathfinding() {
|
||||
+ entity.getNavigation().stopPathfinding();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean hasPath() {
|
||||
+ return entity.getNavigation().getPathEntity() != null;
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ @Override
|
||||
+ public PathResult getCurrentPath() {
|
||||
+ Path path = entity.getNavigation().getPathEntity();
|
||||
+ return path != null ? new PaperPathResult(path) : null;
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ @Override
|
||||
+ public PathResult findPath(Location loc) {
|
||||
+ Validate.notNull(loc, "Location can not be null");
|
||||
+ Path path = entity.getNavigation().calculateDestination(loc.getX(), loc.getY(), loc.getZ());
|
||||
+ 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().calculateDestination(((CraftLivingEntity) target).getHandle());
|
||||
+ 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().setDestination(pathEntity, speed);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean canOpenDoors() {
|
||||
+ return entity.getNavigation().getPathfinder().getPathfinder().shouldOpenDoors();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setCanOpenDoors(boolean canOpenDoors) {
|
||||
+ entity.getNavigation().getPathfinder().getPathfinder().setShouldOpenDoors(canOpenDoors);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean canPassDoors() {
|
||||
+ return entity.getNavigation().getPathfinder().getPathfinder().shouldPassDoors();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setCanPassDoors(boolean canPassDoors) {
|
||||
+ entity.getNavigation().getPathfinder().getPathfinder().setShouldPassDoors(canPassDoors);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean canFloat() {
|
||||
+ return entity.getNavigation().getPathfinder().getPathfinder().shouldFloat();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setCanFloat(boolean canFloat) {
|
||||
+ entity.getNavigation().getPathfinder().getPathfinder().setShouldFloat(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.getFinalPoint();
|
||||
+ return point != null ? toLoc(point) : null;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public List<Location> getPoints() {
|
||||
+ List<Location> points = new ArrayList<>();
|
||||
+ for (Node point : path.getPoints()) {
|
||||
+ points.add(toLoc(point));
|
||||
+ }
|
||||
+ return points;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getNextPointIndex() {
|
||||
+ return path.getNextIndex();
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ @Override
|
||||
+ public Location getNextPoint() {
|
||||
+ if (!path.hasNext()) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ return toLoc(path.getPoints().get(path.getNextIndex()));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private Location toLoc(Node point) {
|
||||
+ return new Location(entity.level.getWorld(), point.getX(), point.getY(), point.getZ());
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java
|
||||
index 8212aab2884c2a894bc981850e483ce31814c708..69edca1ef95c37b11fe3f793e6a8f8a674bd7f6f 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java
|
||||
@@ -93,7 +93,7 @@ public abstract class PathNavigation {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
- public final Path createPath(double x, double y, double z, int distance) {
|
||||
+ public final Path calculateDestination(double d0, double d1, double d2) { return createPath(d0, d1, d2, 0); } public final Path createPath(double x, double y, double z, int distance) { // Paper - OBFHELPER
|
||||
return this.createPath(new BlockPos(x, y, z), distance);
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ public abstract class PathNavigation {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
- public Path createPath(Entity entity, int distance) {
|
||||
+ public final Path calculateDestination(Entity entity) { return createPath(entity, 0); } public Path createPath(Entity entity, int distance) {
|
||||
return this.createPath(ImmutableSet.of(entity.blockPosition()), entity, 16, true, distance); // Paper
|
||||
}
|
||||
|
||||
@@ -195,6 +195,7 @@ public abstract class PathNavigation {
|
||||
return path != null && this.moveTo(path, speed);
|
||||
}
|
||||
|
||||
+ public boolean setDestination(@Nullable Path pathentity, double speed) { return moveTo(pathentity, speed); } // Paper - OBFHELPER
|
||||
public boolean moveTo(@Nullable Path path, double speed) {
|
||||
if (path == null) {
|
||||
this.path = null;
|
||||
@@ -221,7 +222,7 @@ public abstract class PathNavigation {
|
||||
}
|
||||
}
|
||||
|
||||
- @Nullable
|
||||
+ @Nullable public Path getPathEntity() { return getPath(); } @Nullable // Paper - OBFHELPER
|
||||
public Path getPath() {
|
||||
return this.path;
|
||||
}
|
||||
@@ -335,6 +336,7 @@ public abstract class PathNavigation {
|
||||
return !this.isDone();
|
||||
}
|
||||
|
||||
+ public void stopPathfinding() { stop(); } // Paper - OBFHELPER
|
||||
public void stop() {
|
||||
this.path = null;
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/pathfinder/Node.java b/src/main/java/net/minecraft/world/level/pathfinder/Node.java
|
||||
index d7a86444d0e76154319c409317fc5ac9c54403a8..328f050ae68e0b42690f05e5995fb2711b8cf46d 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/pathfinder/Node.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/pathfinder/Node.java
|
||||
@@ -6,9 +6,9 @@ import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class Node {
|
||||
- public final int x;
|
||||
- public final int y;
|
||||
- public final int z;
|
||||
+ public final int x; public final int getX() { return x; } // Paper - OBFHELPER
|
||||
+ public final int y; public final int getY() { return y; } // Paper - OBFHELPER
|
||||
+ public final int z; public final int getZ() { return z; } // Paper - OBFHELPER
|
||||
private final int hash;
|
||||
public int heapIdx = -1;
|
||||
public float g;
|
||||
diff --git a/src/main/java/net/minecraft/world/level/pathfinder/NodeEvaluator.java b/src/main/java/net/minecraft/world/level/pathfinder/NodeEvaluator.java
|
||||
index 72ca8adb9fa65588c6b1e19be2dc27a36c0146a6..e5bfd9ade1a49e11afd4a49784a0874654945709 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/pathfinder/NodeEvaluator.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/pathfinder/NodeEvaluator.java
|
||||
@@ -15,9 +15,9 @@ public abstract class NodeEvaluator {
|
||||
protected int entityWidth;
|
||||
protected int entityHeight;
|
||||
protected int entityDepth;
|
||||
- protected boolean canPassDoors;
|
||||
- protected boolean canOpenDoors;
|
||||
- protected boolean canFloat;
|
||||
+ protected boolean canPassDoors; public boolean shouldPassDoors() { return canPassDoors; } public void setShouldPassDoors(boolean b) { canPassDoors = b; } // Paper - obfhelper
|
||||
+ protected boolean canOpenDoors; public boolean shouldOpenDoors() { return canOpenDoors; } public void setShouldOpenDoors(boolean b) { canOpenDoors = b; } // Paper - obfhelper
|
||||
+ protected boolean canFloat; public boolean shouldFloat() { return canFloat; } public void setShouldFloat(boolean b) { canFloat = b; } // Paper - obfhelper
|
||||
|
||||
public void prepare(PathNavigationRegion cachedWorld, Mob entity) {
|
||||
this.level = cachedWorld;
|
||||
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 6928c415e328dd7cff2e9ec553bc4faa1ff8facf..e95312e5b0f0200178cbe1a61b3629dfeac55b4a 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/pathfinder/Path.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/pathfinder/Path.java
|
||||
@@ -12,14 +12,15 @@ import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class Path {
|
||||
- private final List<Node> nodes;
|
||||
+ private final List<Node> nodes; public List<Node> getPoints() { return nodes; } // Paper - OBFHELPER
|
||||
private Node[] openSet = new Node[0];
|
||||
private Node[] closedSet = new Node[0];
|
||||
private Set<Target> targetNodes;
|
||||
- private int nextNodeIndex;
|
||||
+ private int nextNodeIndex; public int getNextIndex() { return this.nextNodeIndex; } // Paper - OBFHELPER
|
||||
private final BlockPos target;
|
||||
private final float distToTarget;
|
||||
private final boolean reached;
|
||||
+ public boolean hasNext() { return getNextIndex() < getPoints().size(); } // Paper
|
||||
|
||||
public Path(List<Node> nodes, BlockPos target, boolean reachesTarget) {
|
||||
this.nodes = nodes;
|
||||
@@ -41,7 +42,7 @@ public class Path {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
- public Node getEndNode() {
|
||||
+ public Node getFinalPoint() { return getEndNode(); } @Nullable public Node getEndNode() { // Paper - OBFHELPER
|
||||
return !this.nodes.isEmpty() ? this.nodes.get(this.nodes.size() - 1) : null;
|
||||
}
|
||||
|
||||
@@ -88,7 +89,7 @@ public class Path {
|
||||
return this.getEntityPosAtNode(entity, this.nextNodeIndex);
|
||||
}
|
||||
|
||||
- public BlockPos getNextNodePos() {
|
||||
+ public BlockPos getNext() { return getNextNodePos(); } public BlockPos getNextNodePos() { // Paper - OBFHELPER
|
||||
return this.nodes.get(this.nextNodeIndex).asBlockPos();
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java
|
||||
index 71872fdfafca82cf745eecee4bf984726d49f5a4..9c9fa83615cd06539ce5e4e3d4feaa69f65b7931 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java
|
||||
@@ -11,8 +11,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) {
|
||||
net.minecraft.world.entity.Mob entity = this.getHandle();
|
|
@ -0,0 +1,75 @@
|
|||
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 21e2ffc105b7b573b19c826a5877ed726156e692..6e3e873efa1f50f53cb6503bde8a981f9cefd006 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/material/FlowingFluid.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/material/FlowingFluid.java
|
||||
@@ -176,7 +176,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.getTypeIfLoaded(blockposition1); // Paper
|
||||
+ if (iblockdata1 == null) continue; // Paper
|
||||
|
||||
if (this.canSpreadTo(world, pos, blockState, enumdirection, blockposition1, iblockdata1, world.getFluidState(blockposition1), fluid1.getType())) {
|
||||
// CraftBukkit start
|
||||
@@ -203,7 +204,8 @@ 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.getTypeIfLoaded(blockposition1); // Paper
|
||||
+ if (iblockdata1 == null) continue; // Paper
|
||||
FluidState fluid = iblockdata1.getFluidState();
|
||||
|
||||
if (fluid.getType().isSame((Fluid) this) && this.canPassThroughWall(enumdirection, (BlockGetter) world, pos, state, blockposition1, iblockdata1)) {
|
||||
@@ -320,11 +322,18 @@ public abstract class FlowingFluid extends Fluid {
|
||||
if (enumdirection1 != enumdirection) {
|
||||
BlockPos blockposition2 = blockposition.relative(enumdirection1);
|
||||
short short0 = FlowingFluid.getCacheKey(blockposition1, blockposition2);
|
||||
- Pair<BlockState, FluidState> pair = (Pair) short2objectmap.computeIfAbsent(short0, (k) -> {
|
||||
- BlockState iblockdata1 = world.getBlockState(blockposition2);
|
||||
+ // Paper start - avoid loading chunks
|
||||
+ Pair<BlockState, FluidState> pair = short2objectmap.get(short0);
|
||||
+ if (pair == null) {
|
||||
+ BlockState iblockdatax = world.getTypeIfLoaded(blockposition2);
|
||||
+ if (iblockdatax == null) {
|
||||
+ continue;
|
||||
+ }
|
||||
|
||||
- return Pair.of(iblockdata1, iblockdata1.getFluidState());
|
||||
- });
|
||||
+ pair = Pair.of(iblockdatax, iblockdatax.getFluidState());
|
||||
+ short2objectmap.put(short0, pair);
|
||||
+ }
|
||||
+ // Paper end
|
||||
BlockState iblockdata1 = (BlockState) pair.getFirst();
|
||||
FluidState fluid = (FluidState) pair.getSecond();
|
||||
|
||||
@@ -396,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, (j) -> {
|
||||
- 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.getTypeIfLoaded(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);
|
|
@ -0,0 +1,416 @@
|
|||
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/net/minecraft/commands/arguments/blocks/BlockStateParser.java b/src/main/java/net/minecraft/commands/arguments/blocks/BlockStateParser.java
|
||||
index 30c3b24af7efebecc21d190ab89817468bdbee22..147fc3f7648a519441eec7ef1048fd18ea595d98 100644
|
||||
--- a/src/main/java/net/minecraft/commands/arguments/blocks/BlockStateParser.java
|
||||
+++ b/src/main/java/net/minecraft/commands/arguments/blocks/BlockStateParser.java
|
||||
@@ -63,7 +63,7 @@ public class BlockStateParser {
|
||||
private final boolean forTesting;
|
||||
private final Map<Property<?>, Comparable<?>> properties = Maps.newLinkedHashMap(); // CraftBukkit - stable
|
||||
private final Map<String, String> vagueProperties = Maps.newHashMap();
|
||||
- private ResourceLocation id = new ResourceLocation("");
|
||||
+ private ResourceLocation id = new ResourceLocation(""); public final ResourceLocation getBlockKey() { return this.id; } // Paper - OBFHELPER
|
||||
private StateDefinition<Block, BlockState> definition;
|
||||
private BlockState state;
|
||||
@Nullable
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
|
||||
index 4ad6fd7e110f949f0bd859331ed6a5109ade3008..6252c3934d72b0d5e6809842bdd26d344cab98c6 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:
|
||||
*
|
||||
@@ -267,6 +273,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;
|
||||
@@ -280,6 +290,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();
|
||||
@@ -317,6 +331,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());
|
||||
|
||||
@@ -380,6 +403,31 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
this.persistentDataContainer.put(key, compound.get(key));
|
||||
}
|
||||
}
|
||||
+ // 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) {
|
||||
@@ -518,6 +566,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.decodeBase64(internal));
|
||||
@@ -646,6 +722,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());
|
||||
@@ -662,6 +755,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;
|
||||
@@ -745,7 +853,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
|
||||
@@ -1169,7 +1277,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
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1204,6 +1316,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;
|
||||
}
|
||||
|
||||
@@ -1228,6 +1344,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);
|
||||
@@ -1285,6 +1409,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()) {
|
||||
@@ -1449,6 +1590,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,
|
||||
@@ -1477,4 +1620,147 @@ 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) {
|
||||
+ Validate.notNull(canDestroy, "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) {
|
||||
+ Validate.notNull(canPlaceOn, "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) {
|
||||
+ Validate.notNull(canDestroy, "Cannot replace with null collection!");
|
||||
+ Validate.isTrue(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) {
|
||||
+ Validate.notNull(canPlaceOn, "Cannot replace with null collection!");
|
||||
+ Validate.isTrue(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) == '#';
|
||||
+ net.minecraft.commands.arguments.blocks.BlockStateParser blockParser = new net.minecraft.commands.arguments.blocks.BlockStateParser(new com.mojang.brigadier.StringReader(raw), true);
|
||||
+ try {
|
||||
+ blockParser = blockParser.parse(false);
|
||||
+ } catch (com.mojang.brigadier.exceptions.CommandSyntaxException e) {
|
||||
+ e.printStackTrace();
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ net.minecraft.resources.ResourceLocation key;
|
||||
+ if (isTag) {
|
||||
+ key = blockParser.getTag();
|
||||
+ } else {
|
||||
+ key = blockParser.getBlockKey();
|
||||
+ }
|
||||
+
|
||||
+ 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
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
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 b255eed15cfc7282167a9bed01653b34bb8d13f1..ac5779319081a6894373877067edf958da8a9cf5 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
|
||||
@@ -133,7 +133,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.getTypeIfLoaded(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()};
|
||||
@@ -143,7 +145,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.getTypeIfLoaded(blockposition1); // Paper
|
||||
+ if (block2 != null && block2.is(this.blockToRemove)) { // Paper
|
||||
return blockposition1;
|
||||
}
|
||||
}
|
||||
@@ -154,7 +157,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();
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
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 9c079d32e81cabfa7b8b28e3e8d5741d8d951d79..30ba1e3cb75d994770b006b9dfd6669000a9c1a4 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
||||
@@ -188,9 +188,9 @@ public final class NaturalSpawner {
|
||||
StructureFeatureManager structuremanager = world.structureFeatureManager();
|
||||
ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator();
|
||||
int i = pos.getY();
|
||||
- BlockState iblockdata = chunk.getBlockState(pos);
|
||||
+ BlockState iblockdata = world.getTypeIfLoadedAndInBounds(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;
|
||||
@@ -219,7 +219,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, (BlockPos) blockposition_mutableblockposition);
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue