fix
This commit is contained in:
Jason Penilla 2021-06-12 23:48:25 -07:00
parent 0fa2a949ae
commit 79f1d1a078
No known key found for this signature in database
GPG key ID: 0E75A301420E48F8
27 changed files with 340 additions and 481 deletions

View file

@ -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 ac572eba10a7239d71dfae060f623b076d4252ce..1ce675d0d24ceb5724f5ac2d8f671e38f2735f74 100644
--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java
+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java
@@ -132,11 +132,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(
MCUtil.toLocation(world, d3, d4, d5),
type,
- org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER
+ MCUtil.toLocation(world, blockposition)
);
if (!event.callEvent()) {
flag = true;

View file

@ -1,110 +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/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java
index 68c3f069f8f832ab3d146748348aded69b5ad823..1fecc81b25109592907623741225a6222a8c5ccc 100644
--- a/src/main/java/net/minecraft/server/MCUtil.java
+++ b/src/main/java/net/minecraft/server/MCUtil.java
@@ -7,6 +7,8 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder;
import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.ChunkPos;
@@ -514,4 +516,19 @@ public final class MCUtil {
return null;
}
}
+
+ @Nullable
+ public static Component getBaseComponentFromNbt(String key, CompoundTag compound) {
+ if (!compound.contains(key)) {
+ return null;
+ }
+ String string = compound.getString(key);
+ try {
+ return Component.Serializer.jsonToComponent(string);
+ } catch (com.google.gson.JsonParseException e) {
+ org.bukkit.Bukkit.getLogger().warning("Unable to parse " + key + " from " + compound +": " + e.getMessage());
+ }
+
+ return null;
+ }
}
diff --git a/src/main/java/net/minecraft/world/level/BaseCommandBlock.java b/src/main/java/net/minecraft/world/level/BaseCommandBlock.java
index 9ad077259563a3d960d32a59d4b6fc3cfbe3440c..00dc4cd436023b946d7005f17a7ba983a4bbdfb6 100644
--- a/src/main/java/net/minecraft/world/level/BaseCommandBlock.java
+++ b/src/main/java/net/minecraft/world/level/BaseCommandBlock.java
@@ -12,6 +12,7 @@ import net.minecraft.commands.CommandSourceStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
+import net.minecraft.server.MCUtil;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.StringUtil;
@@ -72,7 +73,7 @@ public abstract class BaseCommandBlock implements CommandSource {
this.command = tag.getString("Command");
this.successCount = tag.getInt("SuccessCount");
if (tag.contains("CustomName", 8)) {
- this.setName(Component.Serializer.fromJson(tag.getString("CustomName")));
+ this.setName(MCUtil.getBaseComponentFromNbt("CustomName", tag)); // Paper - Catch ParseException
}
if (tag.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 2e3ec85e7bd1c375db0662dba2617d8924dbd2a6..2c885be67b9c992b96f5caf78130d46abb455ceb 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
@@ -9,6 +9,7 @@ import net.minecraft.nbt.ListTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
+import net.minecraft.server.MCUtil;
import net.minecraft.world.Nameable;
import net.minecraft.world.item.DyeColor;
import net.minecraft.world.item.ItemStack;
@@ -70,7 +71,7 @@ public class BannerBlockEntity extends BlockEntity implements Nameable {
public void load(BlockState state, CompoundTag tag) {
super.load(state, tag);
if (tag.contains("CustomName", 8)) {
- this.name = Component.Serializer.fromJson(tag.getString("CustomName"));
+ this.name = MCUtil.getBaseComponentFromNbt("CustomName", tag); // Paper - Catch ParseException
}
if (this.hasLevel()) {
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 a7358274fe367a113b304a5ce332b8dcf721b7af..2b420109e9bed184aaa4ffbcee666b4c325c5a28 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
@@ -4,6 +4,7 @@ import javax.annotation.Nullable;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
+import net.minecraft.server.MCUtil;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.Container;
@@ -30,7 +31,7 @@ public abstract class BaseContainerBlockEntity extends BlockEntity implements Co
super.load(state, tag);
this.lockKey = LockCode.fromTag(tag);
if (tag.contains("CustomName", 8)) {
- this.name = Component.Serializer.fromJson(tag.getString("CustomName"));
+ this.name = MCUtil.getBaseComponentFromNbt("CustomName", tag); // Paper - Catch ParseException
}
}

View file

@ -1,18 +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/AgableMob.java b/src/main/java/net/minecraft/world/entity/AgableMob.java
index d7c19e5607bcf92c874b3656c2742f4c84dceb12..354311dc541588212a2eacba38e60c7e34aa4c2b 100644
--- a/src/main/java/net/minecraft/world/entity/AgableMob.java
+++ b/src/main/java/net/minecraft/world/entity/AgableMob.java
@@ -82,6 +82,7 @@ public abstract class AgableMob extends PathfinderMob {
}
public void ageUp(int age, boolean overGrow) {
+ if (ageLocked) return; // Paper - GH-1459
int j = this.getAge();
int k = j;

View file

@ -1,35 +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/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
index 62621562137cba4804f0465c58d25ca2786328e5..7178b37f7978c7e9031a22726005c5099fd78fe0 100644
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
@@ -281,6 +281,11 @@ public class PaperConfig {
authenticationServersDownKickMessage = Strings.emptyToNull(getString("messages.kick.authentication-servers-down", authenticationServersDownKickMessage));
}
+ public static String connectionThrottleKickMessage = "Connection throttled! Please wait before reconnecting.";
+ private static void connectionThrottleKickMessage() {
+ connectionThrottleKickMessage = getString("messages.kick.connection-throttle", connectionThrottleKickMessage);
+ }
+
private static void savePlayerData() {
Object val = config.get("settings.save-player-data");
if (val instanceof Boolean) {
diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
index 45c9dc9c2a580a5cd57fd4e891fbaa2b1336f5c5..6f98be2b9b00f71dd041e7511c70166fdecf0749 100644
--- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
@@ -50,7 +50,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL
synchronized (throttleTracker) {
if (throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - throttleTracker.get(address) < connectionThrottle) {
throttleTracker.put(address, currentTime);
- TranslatableComponent chatmessage = new TranslatableComponent("Connection throttled! Please wait before reconnecting.");
+ TranslatableComponent chatmessage = new TranslatableComponent(com.destroystokyo.paper.PaperConfig.connectionThrottleKickMessage); // Paper - Configurable connection throttle kick message
this.connection.send(new ClientboundLoginDisconnectPacket(chatmessage));
this.connection.disconnect(chatmessage);
return;

View file

@ -1,184 +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 45cbdcfc131bbc0e2bf23cc30a572df72eecd51c..49e5a86c223f1b28ce7da6ced276b2f880777856 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,42 @@ 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
+ getAndRemove.put( "org/bukkit/".concat( "craftbukkit/libs/it/unimi/dsi/fastutil/" ), "org/bukkit/".concat( "craftbukkit/libs/" ) ); // Remap fastutil to our location
+
+ if ( Boolean.getBoolean( "debug.rewriteForIde" ) )
+ {
+ // unversion incoming calls for pre-relocate debug work
+ final String NMS_REVISION_PACKAGE = "v1_16_R3/";
+
+ getAndRemove.put( "net/minecraft/".concat( "server/" + NMS_REVISION_PACKAGE ), NMS_REVISION_PACKAGE );
+ 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 +173,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 )
@@ -270,6 +384,14 @@ public class Commodore
return;
}
+ // Paper start - Rewrite plugins
+ owner = getOriginalOrRewrite( owner) ;
+ if (desc != null)
+ {
+ desc = getOriginalOrRewrite(desc);
+ }
+ // Paper end
+
if ( modern )
{
if ( owner.equals( "org/bukkit/Material" ) )

View file

@ -1,52 +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
diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java
index f3690ea49cf90c816b8b3554b47d6f2d9dfbe016..29a2eeee9f2011ed6fcc44f19041f616decfdb38 100644
--- a/src/main/java/net/minecraft/world/entity/Mob.java
+++ b/src/main/java/net/minecraft/world/entity/Mob.java
@@ -1595,6 +1595,7 @@ public abstract class Mob extends LivingEntity {
}
+ public boolean isInDaylight() { return this.isSunBurnTick(); } // Paper - OBFHELPER
protected boolean isSunBurnTick() {
if (this.level.isDay() && !this.level.isClientSide) {
float f = this.getBrightness();
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 57a2af56b53567371fdb6d0a55866e1e4e37cf3b..7b5abccac9793811bd56340c8f9d23806e832365 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -847,6 +847,13 @@ public class CraftWorld 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 b5fe55a77c8558cf2ea32689ff57911530df75f9..1e3a0851c75d8067d2699f00bb3f6621d1d739d8 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java
@@ -77,4 +77,11 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob {
public long getSeed() {
return getHandle().lootTableSeed;
}
+
+ // Paper start
+ @Override
+ public boolean isInDaylight() {
+ return getHandle().isInDaylight();
+ }
+ // Paper end
}

View file

@ -1,150 +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
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 4584fad16a65f06e77e97a0804d88dbe83f7c5c1..c8680e795deeb68e0662eac7c760a103d1c767b4 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;
+ protected BlockPos blockPos;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 c54f4b83b9f2fdb15ddb363be0a179a05eb3693b..42b636c4ebb6eb83c8a9f3f5f9a766d37d065dc3 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Turtle.java
@@ -14,6 +14,7 @@ import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.network.syncher.SynchedEntityData;
+import net.minecraft.server.MCUtil;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvent;
@@ -93,7 +94,7 @@ public class Turtle extends Animal {
this.entityData.set(Turtle.HOME_POS, pos);
}
- private BlockPos getHomePos() {
+ public BlockPos getHomePos() { // Paper - public
return (BlockPos) this.entityData.get(Turtle.HOME_POS);
}
@@ -109,31 +110,37 @@ public class Turtle extends Animal {
return (Boolean) this.entityData.get(Turtle.HAS_EGG);
}
- private void setHasEgg(boolean hasEgg) {
+ public void setHasEgg(boolean hasEgg) { // Paper
this.entityData.set(Turtle.HAS_EGG, hasEgg);
}
+ public final boolean isDigging() { return this.isLayingEgg(); } // Paper - OBFHELPER
public boolean isLayingEgg() {
return (Boolean) this.entityData.get(Turtle.LAYING_EGG);
}
+ public final void setDigging(boolean digging) { this.setLayingEgg(digging); } // Paper - OBFHELPER
private void setLayingEgg(boolean diggingSand) {
this.layEggCounter = diggingSand ? 1 : 0;
this.entityData.set(Turtle.LAYING_EGG, diggingSand);
}
+ public final boolean isGoingHome() { return this.isGoingHome(); } // Paper - OBFHELPER
private boolean isGoingHome() {
return (Boolean) this.entityData.get(Turtle.GOING_HOME);
}
+ public final void setGoingHome(boolean goingHome) { this.setGoingHome(goingHome); } // Paper - OBFHELPER
private void setGoingHome(boolean landBound) {
this.entityData.set(Turtle.GOING_HOME, landBound);
}
+ public final boolean isTravelling() { return this.isTravelling(); } // Paper - OBFHELPER
private boolean isTravelling() {
return (Boolean) this.entityData.get(Turtle.TRAVELLING);
}
+ public final void setTravelling(boolean travelling) { this.setTravelling(travelling); } // Paper - OBFHELPER
private void setTravelling(boolean travelling) {
this.entityData.set(Turtle.TRAVELLING, travelling);
}
@@ -500,14 +507,17 @@ public class Turtle extends Animal {
if (!this.turtle.isInWater() && this.isReachedTarget()) {
if (this.turtle.layEggCounter < 1) {
- this.turtle.setLayingEgg(true);
+ this.turtle.setDigging(new com.destroystokyo.paper.event.entity.TurtleStartDiggingEvent((org.bukkit.entity.Turtle) this.turtle.getBukkitEntity(), MCUtil.toLocation(this.turtle.level, this.getTargetPosition())).callEvent()); // Paper
} else if (this.turtle.layEggCounter > 200) {
Level world = this.turtle.level;
// CraftBukkit start
- 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)).isCancelled()) {
+ // 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(), 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())).isCancelled()) {
world.playSound((Player) null, blockposition, SoundEvents.TURTLE_LAY_EGG, SoundSource.BLOCKS, 0.3F, 0.9F + world.random.nextFloat() * 0.2F);
- world.setBlock(this.blockPos.above(), (BlockState) Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, this.turtle.random.nextInt(4) + 1), 3);
+ world.setBlock(this.blockPos.above(), (BlockState) Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, layEggEvent.getEggCount()), 3);
}
// CraftBukkit end
this.turtle.setHasEgg(false);
@@ -636,7 +646,7 @@ public class Turtle extends Animal {
@Override
public boolean canUse() {
- return this.turtle.isBaby() ? false : (this.turtle.hasEgg() ? true : (this.turtle.getRandom().nextInt(700) != 0 ? false : !this.turtle.getHomePos().closerThan((Position) this.turtle.position(), 64.0D)));
+ return this.turtle.isBaby() ? false : (this.turtle.hasEgg() ? true : (this.turtle.getRandom().nextInt(700) != 0 ? false : !this.turtle.getHomePos().closerThan((Position) 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 ed08089f21c8958fc9fc7e6e73a2b6ff9108242c..e50f6051baf34981707adce56ab2d3e1f341fb4c 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java
@@ -24,4 +24,36 @@ public class CraftTurtle extends CraftAnimals implements Turtle {
public EntityType getType() {
return EntityType.TURTLE;
}
+
+ // Paper start
+ @Override
+ public org.bukkit.Location getHome() {
+ return net.minecraft.server.MCUtil.toLocation(getHandle().level, getHandle().getHomePos());
+ }
+
+ @Override
+ public void setHome(org.bukkit.Location location) {
+ getHandle().setHomePos(net.minecraft.server.MCUtil.toBlockPosition(location));
+ }
+
+ @Override
+ public boolean isGoingHome() {
+ return getHandle().isGoingHome();
+ }
+
+ @Override
+ public boolean isDigging() {
+ return getHandle().isDigging();
+ }
+
+ @Override
+ public boolean hasEgg() {
+ return getHandle().hasEgg();
+ }
+
+ @Override
+ public void setHasEgg(boolean hasEgg) {
+ getHandle().setHasEgg(hasEgg);
+ }
+ // Paper end
}

View file

@ -1,36 +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 d1dd173c11d751b15c3afd4309e386931fd9cf8d..d385fb6eee5000951c350b6ced5669dc3dcce725 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
@@ -44,7 +44,18 @@ public abstract class Projectile extends Entity {
@Nullable
public Entity getOwner() {
- return this.ownerUUID != null && this.level instanceof ServerLevel ? ((ServerLevel) this.level).getEntity(this.ownerUUID) : (this.ownerNetworkId != 0 ? this.level.getEntity(this.ownerNetworkId) : null);
+ // Paper start - MC-50319 - shooter might be in another world (arrows through portals)
+ Entity entity = this.ownerUUID != null && this.level instanceof ServerLevel ? ((ServerLevel) this.level).getEntity(this.ownerUUID) : (this.ownerNetworkId != 0 ? this.level.getEntity(this.ownerNetworkId) : null);
+ if (entity == null) {
+ for (ServerLevel world : level.getServer().getAllLevels()) {
+ entity = world.getEntity(this.ownerUUID);
+ if (entity != null) {
+ break;
+ }
+ }
+ }
+ return entity;
+ // Paper end
}
@Override

View file

@ -1,99 +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 75419c866641ab654349cde6ca3fbdef701dd8d9..92139b271eb6c305787662ef8c7d221fb42296f7 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -1818,14 +1818,58 @@ public class ServerPlayer extends Player implements ContainerListener {
}
public void setCamera(Entity entity) {
+ // Paper start - Add PlayerStartSpectatingEntityEvent and PlayerStopSpectatingEntity Event and improve implementation
Entity entity1 = this.getCamera();
- this.camera = (Entity) (entity == null ? this : entity);
- if (entity1 != this.camera) {
- this.connection.send(new ClientboundSetCameraPacket(this.camera));
- this.connection.a(this.camera.getX(), this.camera.getY(), this.camera.getZ(), this.yRot, this.xRot, TeleportCause.SPECTATE); // CraftBukkit
+ if (entity == null) {
+ entity = this;
}
+ if (entity1 == entity) return; // new spec target is the current spec target
+
+ if (entity == 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;
+ }
+ }
+ // Validate
+ if (entity != this) {
+ if (entity.removed || entity.shouldBeRemoved || !entity.valid || entity.level == null) {
+ MinecraftServer.LOGGER.info("Blocking player " + this.toString() + " from spectating invalid entity " + entity.toString());
+ return;
+ }
+ if (this.isImmobile()) {
+ // use debug: clients might maliciously spam this
+ MinecraftServer.LOGGER.debug("Blocking frozen player " + this.toString() + " from spectating entity " + entity.toString());
+ return;
+ }
+ }
+
+ this.camera = entity; // only set after validating state
+
+ if (entity != this) {
+ // Make sure we're in the right place
+ this.ejectPassengers(); // teleport can fail if we have passengers...
+ this.getBukkitEntity().teleport(new Location(entity.getCommandSenderWorld().getWorld(), entity.getX(), entity.getY(), entity.getZ(), this.yRot, this.xRot), TeleportCause.SPECTATE); // Correctly handle cross-world entities from api calls by using CB teleport
+
+ // Make sure we're tracking the entity before sending
+ ChunkMap.TrackedEntity tracker = ((ServerLevel)entity.level).getChunkSource().chunkMap.entityMap.get(entity.getId());
+ if (tracker != null) { // dumb plugins...
+ tracker.updatePlayer(this);
+ }
+ } else {
+ this.connection.teleport(this.camera.getX(), this.camera.getY(), this.camera.getZ(), this.yRot, this.xRot, TeleportCause.SPECTATE); // CraftBukkit
+ }
+ this.connection.send(new ClientboundSetCameraPacket(entity));
+ // Paper end
}
@Override
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 900c9b1106a153bc386f6c3d9c11226f8ac69f86..4fd8d775790c037e82f9b0d29ed0eccf03c2dc66 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -1353,6 +1353,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener {
}
// CraftBukkit start - Delegate to teleport(Location)
+ public final void teleport(double d0, double d1, double d2, float f, float f1, PlayerTeleportEvent.TeleportCause cause) { this.a(d0, d1, d2, f, f1, cause); } // Paper - OBFHELPER
public void a(double d0, double d1, double d2, float f, float f1, PlayerTeleportEvent.TeleportCause cause) {
this.a(d0, d1, d2, f, f1, Collections.<ClientboundPlayerPositionPacket.RelativeArgument>emptySet(), cause);
}

View file

@ -1,303 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Andrew Steinborn <git@steinborn.me>
Date: Mon, 8 Oct 2018 14:36:14 -0400
Subject: [PATCH] Add Velocity IP Forwarding Support
While Velocity supports BungeeCord-style IP forwarding, it is not secure. Users
have a lot of problems setting up firewalls or setting up plugins like IPWhitelist.
Further, the BungeeCord IP forwarding protocol still retains essentially its original
form, when there is brand new support for custom login plugin messages in 1.13.
Velocity's modern IP forwarding uses an HMAC-SHA256 code to ensure authenticity
of messages, is packed into a binary format that is smaller than BungeeCord's
forwarding, and is integrated into the Minecraft login process by using the 1.13
login plugin message packet.
diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
index 7178b37f7978c7e9031a22726005c5099fd78fe0..3139c194f9b1bc3510d51a81f13ae43d00a3dc29 100644
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
@@ -8,6 +8,7 @@ import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
+import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -252,7 +253,7 @@ public class PaperConfig {
}
public static boolean isProxyOnlineMode() {
- return Bukkit.getOnlineMode() || (SpigotConfig.bungee && bungeeOnlineMode);
+ return Bukkit.getOnlineMode() || (SpigotConfig.bungee && bungeeOnlineMode) || (velocitySupport && velocityOnlineMode);
}
public static int packetInSpamThreshold = 300;
@@ -324,4 +325,18 @@ public class PaperConfig {
}
tabSpamLimit = getInt("settings.spam-limiter.tab-spam-limit", tabSpamLimit);
}
+
+ public static boolean velocitySupport;
+ public static boolean velocityOnlineMode;
+ public static byte[] velocitySecretKey;
+ private static void velocitySupport() {
+ velocitySupport = getBoolean("settings.velocity-support.enabled", false);
+ velocityOnlineMode = getBoolean("settings.velocity-support.online-mode", false);
+ String secret = getString("settings.velocity-support.secret", "");
+ if (velocitySupport && secret.isEmpty()) {
+ fatal("Velocity support is enabled, but no secret key was specified. A secret key is required!");
+ } else {
+ velocitySecretKey = secret.getBytes(StandardCharsets.UTF_8);
+ }
+ }
}
diff --git a/src/main/java/com/destroystokyo/paper/proxy/VelocityProxy.java b/src/main/java/com/destroystokyo/paper/proxy/VelocityProxy.java
new file mode 100644
index 0000000000000000000000000000000000000000..5490ddb9f2ff1fc3e6088e703c246a06594076bc
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/proxy/VelocityProxy.java
@@ -0,0 +1,66 @@
+package com.destroystokyo.paper.proxy;
+
+import com.destroystokyo.paper.PaperConfig;
+import com.google.common.net.InetAddresses;
+import com.mojang.authlib.GameProfile;
+import com.mojang.authlib.properties.Property;
+import java.net.InetAddress;
+import java.security.InvalidKeyException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import net.minecraft.network.FriendlyByteBuf;
+import net.minecraft.resources.ResourceLocation;
+
+public class VelocityProxy {
+ private static final int SUPPORTED_FORWARDING_VERSION = 1;
+ public static final ResourceLocation PLAYER_INFO_CHANNEL = new ResourceLocation("velocity", "player_info");
+
+ public static boolean checkIntegrity(final FriendlyByteBuf buf) {
+ final byte[] signature = new byte[32];
+ buf.readBytes(signature);
+
+ final byte[] data = new byte[buf.readableBytes()];
+ buf.getBytes(buf.readerIndex(), data);
+
+ try {
+ final Mac mac = Mac.getInstance("HmacSHA256");
+ mac.init(new SecretKeySpec(PaperConfig.velocitySecretKey, "HmacSHA256"));
+ final byte[] mySignature = mac.doFinal(data);
+ if (!MessageDigest.isEqual(signature, mySignature)) {
+ return false;
+ }
+ } catch (final InvalidKeyException | NoSuchAlgorithmException e) {
+ throw new AssertionError(e);
+ }
+
+ int version = buf.readVarInt();
+ if (version != SUPPORTED_FORWARDING_VERSION) {
+ throw new IllegalStateException("Unsupported forwarding version " + version + ", wanted " + SUPPORTED_FORWARDING_VERSION);
+ }
+
+ return true;
+ }
+
+ public static InetAddress readAddress(final FriendlyByteBuf buf) {
+ return InetAddresses.forString(buf.readUTF(Short.MAX_VALUE));
+ }
+
+ public static GameProfile createProfile(final FriendlyByteBuf buf) {
+ final GameProfile profile = new GameProfile(buf.readUUID(), buf.readUTF(16));
+ readProperties(buf, profile);
+ return profile;
+ }
+
+ private static void readProperties(final FriendlyByteBuf buf, final GameProfile profile) {
+ final int properties = buf.readVarInt();
+ for (int i1 = 0; i1 < properties; i1++) {
+ final String name = buf.readUTF(Short.MAX_VALUE);
+ final String value = buf.readUTF(Short.MAX_VALUE);
+ final String signature = buf.readBoolean() ? buf.readUTF(Short.MAX_VALUE) : null;
+ profile.getProperties().put(name, new Property(name, value, signature));
+ }
+ }
+}
diff --git a/src/main/java/net/minecraft/network/FriendlyByteBuf.java b/src/main/java/net/minecraft/network/FriendlyByteBuf.java
index 10f1e3d761af83507bf71a00092641e22d0c8049..a295845409824b930992426451ef26856d6e7c36 100644
--- a/src/main/java/net/minecraft/network/FriendlyByteBuf.java
+++ b/src/main/java/net/minecraft/network/FriendlyByteBuf.java
@@ -191,6 +191,7 @@ public class FriendlyByteBuf extends ByteBuf {
return this.writeVarInt(oenum.ordinal());
}
+ public int readVarInt() { return readVarInt(); } // Paper - OBFHELPER
public int readVarInt() {
int i = 0;
int j = 0;
@@ -231,6 +232,7 @@ public class FriendlyByteBuf extends ByteBuf {
return this;
}
+ public UUID readUUID() { return readUUID(); } // Paper - OBFHELPER
public UUID readUUID() {
return new UUID(this.readLong(), this.readLong());
}
@@ -358,6 +360,7 @@ public class FriendlyByteBuf extends ByteBuf {
}
}
+ public String readUTF(int maxLength) { return this.readUtf(maxLength); } // Paper - OBFHELPER
public String readUtf(int i) {
int j = this.readVarInt();
diff --git a/src/main/java/net/minecraft/network/protocol/login/ClientboundCustomQueryPacket.java b/src/main/java/net/minecraft/network/protocol/login/ClientboundCustomQueryPacket.java
index 8a0301cc4a411c4f9384331d68794ca73b797f5f..88a63635d73983afe58406c66f4ea81cd823c627 100644
--- a/src/main/java/net/minecraft/network/protocol/login/ClientboundCustomQueryPacket.java
+++ b/src/main/java/net/minecraft/network/protocol/login/ClientboundCustomQueryPacket.java
@@ -13,6 +13,14 @@ public class ClientboundCustomQueryPacket implements Packet<ClientLoginPacketLis
public ClientboundCustomQueryPacket() {}
+ // Paper start
+ public ClientboundCustomQueryPacket(int id, ResourceLocation channel, FriendlyByteBuf buf) {
+ this.transactionId = id;
+ this.identifier = channel;
+ this.data = buf;
+ }
+ // Paper end
+
@Override
public void read(FriendlyByteBuf buf) throws IOException {
this.transactionId = buf.readVarInt();
diff --git a/src/main/java/net/minecraft/network/protocol/login/ServerboundCustomQueryPacket.java b/src/main/java/net/minecraft/network/protocol/login/ServerboundCustomQueryPacket.java
index ed5c62d121c69e91da9fd5f91ccf9abd665a3b40..790edd9f5a2527f5f715e2e2bec0b454cf0a2ce7 100644
--- a/src/main/java/net/minecraft/network/protocol/login/ServerboundCustomQueryPacket.java
+++ b/src/main/java/net/minecraft/network/protocol/login/ServerboundCustomQueryPacket.java
@@ -6,8 +6,8 @@ import net.minecraft.network.protocol.Packet;
public class ServerboundCustomQueryPacket implements Packet<ServerLoginPacketListener> {
- private int transactionId;
- private FriendlyByteBuf data;
+ private int transactionId; public int getId() { return transactionId; } // Paper - OBFHELPER
+ private FriendlyByteBuf data; public FriendlyByteBuf getBuf() { return data; } // Paper - OBFHELPER
public ServerboundCustomQueryPacket() {}
diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
index 0aa3a154d68f00edcc09b947a24b2b59b1e135e6..22d6f41001977917ec75046252cbf7157b92396d 100644
--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
@@ -18,9 +18,11 @@ import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import net.minecraft.DefaultUncaughtExceptionHandler;
import net.minecraft.network.Connection;
+import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.chat.TranslatableComponent;
+import net.minecraft.network.protocol.login.ClientboundCustomQueryPacket;
import net.minecraft.network.protocol.login.ClientboundGameProfilePacket;
import net.minecraft.network.protocol.login.ClientboundHelloPacket;
import net.minecraft.network.protocol.login.ClientboundLoginCompressionPacket;
@@ -43,6 +45,7 @@ import org.bukkit.craftbukkit.util.Waitable;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import org.bukkit.event.player.PlayerPreLoginEvent;
// CraftBukkit end
+import io.netty.buffer.Unpooled; // Paper
public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener {
@@ -59,6 +62,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener
private SecretKey secretKey;
private ServerPlayer delayedAcceptPlayer;
public String hostname = ""; // CraftBukkit - add field
+ private int velocityLoginMessageId = -1; // Paper - Velocity support
public ServerLoginPacketListenerImpl(MinecraftServer server, Connection connection) {
this.state = ServerLoginPacketListenerImpl.State.HELLO;
@@ -211,6 +215,14 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener
this.state = ServerLoginPacketListenerImpl.State.KEY;
this.connection.send(new ClientboundHelloPacket("", this.server.getKeyPair().getPublic().getEncoded(), this.nonce));
} else {
+ // Paper start - Velocity support
+ if (com.destroystokyo.paper.PaperConfig.velocitySupport) {
+ this.velocityLoginMessageId = java.util.concurrent.ThreadLocalRandom.current().nextInt();
+ ClientboundCustomQueryPacket packet1 = new ClientboundCustomQueryPacket(this.velocityLoginMessageId, com.destroystokyo.paper.proxy.VelocityProxy.PLAYER_INFO_CHANNEL, new FriendlyByteBuf(Unpooled.EMPTY_BUFFER));
+ this.connection.send(packet1);
+ return;
+ }
+ // Paper end
// Spigot start
// Paper start - Cache authenticator threads
authenticatorPool.execute(new Runnable() {
@@ -312,6 +324,12 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener
public class LoginHandler {
public void fireEvents() throws Exception {
+ // Paper start - Velocity support
+ if (ServerLoginPacketListenerImpl.this.velocityLoginMessageId == -1 && com.destroystokyo.paper.PaperConfig.velocitySupport) {
+ disconnect("This server requires you to connect with Velocity.");
+ return;
+ }
+ // Paper end
String playerName = gameProfile.getName();
java.net.InetAddress address = ((java.net.InetSocketAddress) connection.getRemoteAddress()).getAddress();
java.util.UUID uniqueId = gameProfile.getId();
@@ -359,6 +377,40 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener
// Spigot end
public void handleCustomQueryPacket(ServerboundCustomQueryPacket packet) {
+ // Paper start - Velocity support
+ if (com.destroystokyo.paper.PaperConfig.velocitySupport && packet.getId() == this.velocityLoginMessageId) {
+ FriendlyByteBuf buf = packet.getBuf();
+ if (buf == null) {
+ this.disconnect("This server requires you to connect with Velocity.");
+ return;
+ }
+
+ if (!com.destroystokyo.paper.proxy.VelocityProxy.checkIntegrity(buf)) {
+ this.disconnect("Unable to verify player details");
+ return;
+ }
+
+ java.net.SocketAddress listening = this.connection.getRemoteAddress();
+ int port = 0;
+ if (listening instanceof java.net.InetSocketAddress) {
+ port = ((java.net.InetSocketAddress) listening).getPort();
+ }
+ this.connection.address = new java.net.InetSocketAddress(com.destroystokyo.paper.proxy.VelocityProxy.readAddress(buf), port);
+
+ this.setGameProfile(com.destroystokyo.paper.proxy.VelocityProxy.createProfile(buf));
+
+ // Proceed with login
+ authenticatorPool.execute(() -> {
+ try {
+ new LoginHandler().fireEvents();
+ } catch (Exception ex) {
+ disconnect("Failed to verify username!");
+ server.server.getLogger().log(java.util.logging.Level.WARNING, "Exception verifying " + gameProfile.getName(), ex);
+ }
+ });
+ return;
+ }
+ // Paper end
this.disconnect(new TranslatableComponent("multiplayer.disconnect.unexpected_query_response"));
}
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 5e36d705c56384f507fd85f704eae634379a27f1..c06b35f114a8d243198b66c44ef57d8c2b201361 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -680,7 +680,7 @@ public final class CraftServer implements Server {
@Override
public long getConnectionThrottle() {
// Spigot Start - Automatically set connection throttle for bungee configurations
- if (org.spigotmc.SpigotConfig.bungee) {
+ if (org.spigotmc.SpigotConfig.bungee || com.destroystokyo.paper.PaperConfig.velocitySupport) { // Paper - Velocity support
return -1;
} else {
return this.configuration.getInt("settings.connection-throttle");

View file

@ -1,150 +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
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 a37ee32b46aa87be6e3eeca2892b4e7294fd1aef..bc9380782c2afba359852542837e7154c4c6cf8b 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Witch.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Witch.java
@@ -1,5 +1,8 @@
package net.minecraft.world.entity.monster;
+// Paper start
+import com.destroystokyo.paper.event.entity.WitchReadyPotionEvent;
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
@@ -49,7 +52,7 @@ public class Witch extends Raider implements RangedAttackMob {
private static final UUID SPEED_MODIFIER_DRINKING_UUID = UUID.fromString("5CD17E52-A79A-43D3-A529-90FDE04B181E");
private static final AttributeModifier SPEED_MODIFIER_DRINKING = new AttributeModifier(Witch.SPEED_MODIFIER_DRINKING_UUID, "Drinking speed penalty", -0.25D, AttributeModifier.Operation.ADDITION);
private static final EntityDataAccessor<Boolean> DATA_USING_ITEM = SynchedEntityData.defineId(Witch.class, EntityDataSerializers.BOOLEAN);
- private int usingTime;
+ private int usingTime; public int getPotionUseTimeLeft() { return usingTime; } public void setPotionUseTimeLeft(int timeLeft) { usingTime = timeLeft; } // Paper - OBFHELPER
private NearestHealableRaiderTargetGoal<Raider> healRaidersGoal;
private NearestAttackableWitchTargetGoal<Player> attackPlayersGoal;
@@ -95,10 +98,12 @@ public class Witch extends Raider implements RangedAttackMob {
return SoundEvents.WITCH_DEATH;
}
+ public void setDrinkingPotion(boolean drinkingPotion) { setUsingItem(drinkingPotion); } // Paper - OBFHELPER
public void setUsingItem(boolean drinking) {
this.getEntityData().set(Witch.DATA_USING_ITEM, drinking);
}
+ public boolean isDrinkingPotion() { return isDrinkingPotion(); } // Paper - OBFHELPER
public boolean isDrinkingPotion() {
return (Boolean) this.getEntityData().get(Witch.DATA_USING_ITEM);
}
@@ -157,21 +162,24 @@ 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);
+// 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.setSlot(EnumItemSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack));
+// // Paper end
+// this.bq = this.getItemInMainHand().k();
+// this.v(true);
+// if (!this.isSilent()) {
+// this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_WITCH_DRINK, this.getSoundCategory(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F);
+// }
+//
+// AttributeModifiable attributemodifiable = this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED);
+//
+// attributemodifiable.removeModifier(EntityWitch.bo);
+// attributemodifiable.b(EntityWitch.bo);
// 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 +191,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 d4eeb071dbbfca3ecea256228853bcb5c11f49ee..bb40b5af0f2a6a971f78350394099e3a48d5d04a 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java
@@ -3,6 +3,13 @@ package org.bukkit.craftbukkit.entity;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.entity.EntityType;
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) {
@@ -23,4 +30,28 @@ public class CraftWitch extends CraftRaider implements Witch, com.destroystokyo.
public EntityType getType() {
return EntityType.WITCH;
}
+
+ // Paper start
+ public boolean isDrinkingPotion() {
+ return getHandle().isDrinkingPotion();
+ }
+
+ public int getPotionUseTimeLeft() {
+ return getHandle().getPotionUseTimeLeft();
+ }
+
+ @Override
+ public void setPotionUseTimeLeft(int ticks) {
+ getHandle().setPotionUseTimeLeft(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
}

View file

@ -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 cc9cd34f77e1f568572f312655fb2fe8e83bd733..0addfd6a1421fc99840d9229bad3ba04e524317b 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Drowned.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Drowned.java
@@ -82,7 +82,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 ( 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(5, new NearestAttackableTargetGoal<>(this, Turtle.class, 10, true, false, Turtle.BABY_ON_LAND_SELECTOR));
}

View file

@ -1,38 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <Blake.Galbreath@GMail.com>
Date: Fri, 12 Oct 2018 01:37:22 -0500
Subject: [PATCH] Here's Johnny!
diff --git a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java
index a41f61daf6cbbb13d0b86cdbad8a4cae00368653..623de661f3b56062792e3a7dbc508637aa58aca5 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java
@@ -51,7 +51,7 @@ public class Vindicator extends AbstractIllager {
private static final Predicate<Difficulty> DOOR_BREAKING_PREDICATE = (enumdifficulty) -> {
return enumdifficulty == Difficulty.NORMAL || enumdifficulty == Difficulty.HARD;
};
- private boolean isJohnny;
+ private boolean isJohnny; public boolean isJohnny() { return isJohnny; } public void setJohnny(boolean johnny) { isJohnny = johnny; } // Paper - OBFHELPER
public Vindicator(EntityType<? extends Vindicator> type, Level world) {
super(type, world);
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java
index 3c5994e9862e5caa257ee6a21f8fba2df39c98c5..6c1569340317f7bed39eaf6e858d602234993eb3 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java
@@ -24,4 +24,14 @@ public class CraftVindicator extends CraftIllager implements Vindicator {
public EntityType getType() {
return EntityType.VINDICATOR;
}
+
+ // Paper start
+ public boolean isJohnny() {
+ return getHandle().isJohnny();
+ }
+
+ public void setJohnny(boolean johnny) {
+ getHandle().setJohnny(johnny);
+ }
+ // Paper end
}

View file

@ -1,64 +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/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
index f280dbff4a09bc611a9ca565c6d697d08801f53b..fbf3ccfb347a5ba6e895339e9576629d940d1aa4 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -396,4 +396,9 @@ public class PaperWorldConfig {
waterOverLavaFlowSpeed = getInt("water-over-lava-flow-speed", 5);
log("Water over lava flow speed: " + waterOverLavaFlowSpeed);
}
+
+ public boolean preventMovingIntoUnloadedChunks = false;
+ private void preventMovingIntoUnloadedChunks() {
+ preventMovingIntoUnloadedChunks = getBoolean("prevent-moving-into-unloaded-chunks", false);
+ }
}
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 4fd8d775790c037e82f9b0d29ed0eccf03c2dc66..b5593300516fad767f603084aca4abcda4424db3 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -541,6 +541,13 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener {
}
speed *= 2f; // TODO: Get the speed of the vehicle instead of the player
+ // Paper start - Prevent moving into unloaded chunks
+ if (player.level.paperConfig.preventMovingIntoUnloadedChunks && worldserver.getChunkIfLoadedImmediately((int) Math.floor(packet.getX()) >> 4, (int) Math.floor(packet.getZ()) >> 4) == null) {
+ 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! {},{},{}", entity.getName().getString(), this.player.getName().getString(), d6, d7, d8);
@@ -1139,9 +1146,9 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener {
double d1 = this.player.getY();
double d2 = this.player.getZ();
double d3 = this.player.getY();
- double d4 = packet.getX(this.player.getX());
+ double d4 = packet.getX(this.player.getX());double toX = d4; // Paper - OBFHELPER
double d5 = packet.getY(this.player.getY());
- double d6 = packet.getZ(this.player.getZ());
+ double d6 = packet.getZ(this.player.getZ());double toZ = d6; // Paper - OBFHELPER
float f = packet.getYRot(this.player.yRot);
float f1 = packet.getXRot(this.player.xRot);
double d7 = d4 - this.firstGoodX;
@@ -1180,6 +1187,12 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener {
} else {
speed = player.abilities.walkingSpeed * 10f;
}
+ // Paper start - Prevent moving into unloaded chunks
+ if (player.level.paperConfig.preventMovingIntoUnloadedChunks && (this.player.getX() != toX || this.player.getZ() != toZ) && !worldserver.hasChunk((int) Math.floor(toX) >> 4, (int) Math.floor(toZ) >> 4)) {
+ this.internalTeleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.yRot, this.player.xRot, Collections.emptySet());
+ return;
+ }
+ // Paper end
if (!this.player.isChangingDimension() && (!this.player.getLevel().getGameRules().getBoolean(GameRules.RULE_DISABLE_ELYTRA_MOVEMENT_CHECK) || !this.player.isFallFlying())) {
float f2 = this.player.isFallFlying() ? 300.0F : 100.0F;

View file

@ -1,187 +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/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index c5d6235a132818dfc78105e9d03d0687f697bb00..d106118dbf4fb270f8526e40a767dd4c563a333f 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -1503,6 +1503,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s
return this.calculateViewVector(pitch - 90.0F, yaw);
}
+ public final Vec3 getEyePosition(float partialTicks) { return getEyePosition(partialTicks); } // Paper - OBFHELPER
public final Vec3 getEyePosition(float tickDelta) {
if (tickDelta == 1.0F) {
return new Vec3(this.getX(), this.getEyeY(), this.getZ());
@@ -2153,6 +2154,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s
return this.getPassengers().size() < 1;
}
+ public final float getCollisionBorderSize() { return getPickRadius(); } // Paper - OBFHELPER
public float getPickRadius() {
return 0.0F;
}
diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java
index e92a8c4c49c452e1f3f0c06398f2a74e3432262f..d3640975c5a33b4911428760691215905b987385 100644
--- a/src/main/java/net/minecraft/world/entity/EntitySelector.java
+++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java
@@ -22,6 +22,7 @@ public final class EntitySelector {
public static final Predicate<Entity> NO_CREATIVE_OR_SPECTATOR = (entity) -> {
return !(entity instanceof Player) || !entity.isSpectator() && !((Player) entity).isCreative();
};
+ public static Predicate<Entity> canAITarget() { return ATTACK_ALLOWED; } // Paper - OBFHELPER
public static final Predicate<Entity> ATTACK_ALLOWED = (entity) -> {
return !(entity instanceof Player) || !entity.isSpectator() && !((Player) entity).isCreative() && entity.level.getDifficulty() != Difficulty.PEACEFUL;
};
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index 29d4ed42e5d763639a50d849ef274c4d848bc9c9..046a05925739005080af35c4be984303b575bf68 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -108,6 +108,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;
@@ -3657,6 +3658,37 @@ public abstract class LivingEntity extends Entity {
return level.clip(raytrace);
}
+ public 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 = level.getEntities(this, getBoundingBox().expand(direction.x * maxDistance, direction.y * maxDistance, direction.z * maxDistance).inflate(1.0D, 1.0D, 1.0D), EntitySelector.canAITarget().and(Entity::isPickable));
+
+ double distance = 0.0D;
+ EntityHitResult result = null;
+
+ for (Entity entity : entityList) {
+ AABB aabb = entity.getBoundingBox().grow((double) entity.getCollisionBorderSize());
+ Optional<Vec3> rayTraceResult = aabb.calculateIntercept(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 = level.paperConfig.shieldBlockingDelay;
public int getShieldBlockingDelay() {
diff --git a/src/main/java/net/minecraft/world/phys/AABB.java b/src/main/java/net/minecraft/world/phys/AABB.java
index 983d0495ec35128ca3ef68566ada065bc4b21efc..143a160a7577e9e34d34a9f3b900db03d3f297af 100644
--- a/src/main/java/net/minecraft/world/phys/AABB.java
+++ b/src/main/java/net/minecraft/world/phys/AABB.java
@@ -116,6 +116,7 @@ public class AABB {
return this.expandTowards(scale.x, scale.y, scale.z);
}
+ public final AABB expand(double x, double y, double z) { return expandTowards(x, y, z); } // Paper - OBFHELPER
public AABB expandTowards(double x, double y, double z) {
double d3 = this.minX;
double d4 = this.minY;
@@ -145,6 +146,12 @@ public class AABB {
return new AABB(d3, d4, d5, d6, d7, d8);
}
+ // Paper start
+ public AABB grow(double d0) {
+ return inflate(d0, d0, d0);
+ }
+ // Paper end
+
public AABB inflate(double x, double y, double z) {
double d3 = this.minX - x;
double d4 = this.minY - y;
@@ -204,6 +211,7 @@ public class AABB {
return this.minX < maxX && this.maxX > minX && this.minY < maxY && this.maxY > minY && this.minZ < maxZ && this.maxZ > minZ;
}
+ public final boolean contains(Vec3 vec3d) { return contains(vec3d); } // Paper - OBFHELPER
public boolean contains(Vec3 vec) {
return this.contains(vec.x, vec.y, vec.z);
}
@@ -237,6 +245,7 @@ public class AABB {
return this.inflate(-value);
}
+ public final Optional<Vec3> calculateIntercept(Vec3 vec3d, Vec3 vec3d1) { return clip(vec3d, vec3d1); } // Paper - OBFHELPER
public Optional<Vec3> clip(Vec3 min, Vec3 max) {
double[] adouble = new double[]{1.0D};
double d0 = max.x - min.x;
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
index 7e3a215f1592bed9f35e22076d9e35a5a49a430e..a01bd035846df0e2e28dc55e2ef2f5f35b83f905 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
@@ -1,6 +1,7 @@
package org.bukkit.craftbukkit.entity;
import com.destroystokyo.paper.block.TargetBlockInfo;
+import com.destroystokyo.paper.entity.TargetEntityInfo;
import com.google.common.base.Preconditions;
import com.google.common.collect.Sets;
import java.util.ArrayList;
@@ -30,8 +31,11 @@ import net.minecraft.world.entity.projectile.ThrownEgg;
import net.minecraft.world.entity.projectile.ThrownEnderpearl;
import net.minecraft.world.entity.projectile.ThrownExperienceBottle;
import net.minecraft.world.entity.projectile.ThrownTrident;
+import net.minecraft.world.level.ClipContext;
import net.minecraft.world.phys.BlockHitResult;
+import net.minecraft.world.phys.EntityHitResult;
import net.minecraft.world.phys.HitResult;
+import net.minecraft.world.phys.Vec3;
import org.apache.commons.lang.Validate;
import org.bukkit.FluidCollisionMode;
import org.bukkit.Location;
@@ -215,6 +219,33 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
new TargetBlockInfo(CraftBlock.at(getHandle().level, ((BlockHitResult)rayTrace).getBlockPos()),
MCUtil.toBukkitBlockFace(((BlockHitResult)rayTrace).getDirection()));
}
+
+ public Entity getTargetEntity(int maxDistance, boolean ignoreBlocks) {
+ EntityHitResult rayTrace = rayTraceEntity(maxDistance, ignoreBlocks);
+ return rayTrace == null ? null : rayTrace.getEntity().getBukkitEntity();
+ }
+
+ public TargetEntityInfo getTargetEntityInfo(int maxDistance, boolean ignoreBlocks) {
+ 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));
+ }
+
+ public EntityHitResult rayTraceEntity(int maxDistance, boolean ignoreBlocks) {
+ EntityHitResult rayTrace = getHandle().getTargetEntity(maxDistance);
+ if (rayTrace == null) {
+ return null;
+ }
+ if (!ignoreBlocks) {
+ HitResult rayTraceBlocks = getHandle().getRayTrace(maxDistance, ClipContext.Fluid.NONE);
+ if (rayTraceBlocks != null) {
+ Vec3 eye = getHandle().getEyePosition(1.0F);
+ if (eye.distanceToSqr(rayTraceBlocks.getLocation()) <= eye.distanceToSqr(rayTrace.getLocation())) {
+ return null;
+ }
+ }
+ }
+ return rayTrace;
+ }
// Paper end
@Override