So MANY PATCHES

This commit is contained in:
beaness 2022-06-23 22:42:53 +02:00
parent c829d884d8
commit c518d8dd6d
83 changed files with 2151 additions and 433 deletions

View File

@ -89,7 +89,7 @@
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.15</version>
<version>1.30</version>
<scope>compile</scope>
</dependency>
<dependency>

View File

@ -1166,4 +1166,10 @@ public final class Bukkit {
{
return server.spigot();
}
// KigPaper start
public static String getPermissionMessage() {
return server.getPermissionMessage();
}
// KigPaper end
}

View File

@ -1007,4 +1007,11 @@ public interface Server extends PluginMessageRecipient {
}
Spigot spigot();
// KigPaper start
/**
* @return the server's no permission message
*/
String getPermissionMessage();
// KigPaper end
}

View File

@ -208,4 +208,17 @@ public enum Sound {
VILLAGER_IDLE,
VILLAGER_NO,
VILLAGER_YES,
// KigPaper start - Guardian sounds
GUARDIAN_IDLE,
GUARDIAN_IDLE_LAND,
GUARDIAN_IDLE_ELDER,
GUARDIAN_HIT,
GUARDIAN_HIT_LAND,
GUARDIAN_HIT_ELDER,
GUARDIAN_DEATH,
GUARDIAN_DEATH_LAND,
GUARDIAN_DEATH_ELDER,
GUARDIAN_FLOP,
GUARDIAN_CURSE
// KigPaper end
}

View File

@ -198,7 +198,7 @@ public abstract class Command {
}
if (permissionMessage == null) {
target.sendMessage(ChatColor.RED + "I'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is in error.");
target.sendMessage(Bukkit.getServer().getPermissionMessage());
} else if (permissionMessage.length() != 0) {
for (String line : permissionMessage.replace("<permission>", permission).split("\n")) {
target.sendMessage(line);

View File

@ -2,6 +2,7 @@ package org.bukkit.entity;
import java.net.InetSocketAddress;
import net.md_5.bungee.api.chat.BaseComponent;
import org.bukkit.Achievement;
import org.bukkit.ChatColor;
import org.bukkit.Effect;
@ -1203,6 +1204,14 @@ public interface Player extends HumanEntity, Conversable, CommandSender, Offline
// Paper - Undeprecate
public void resetTitle();
// KigPaper start
/**
+ * Sends a message to the player's actionbar.
+ * @param message the message to send
+ */
void sendActionbarMessage(BaseComponent... message);
// KigPaper end
// TacoSpigot start
/**
* Request that the player's client download and switch resource packs.

View File

@ -7,6 +7,7 @@ import org.bukkit.entity.Player;
*/
public abstract class MapRenderer {
private boolean drawCursors = true; // KigPaper
private boolean contextual;
/**
@ -53,4 +54,20 @@ public abstract class MapRenderer {
*/
abstract public void render(MapView map, MapCanvas canvas, Player player);
// KigPaper start
/**
* Returns whether this renderer should draw cursors. Implementors should respect this choice.
*/
public boolean getDrawCursors() {
return drawCursors;
}
/**
* Sets whether to draw cursors
* @param drawCursors whether this renderer should draw cursors
*/
public void setDrawCursors(boolean drawCursors) {
this.drawCursors = drawCursors;
}
// KigPaper end
}

View File

@ -133,6 +133,16 @@
<artifactId>velocity-native</artifactId>
<version>1.1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.lz4</groupId>
<artifactId>lz4-java</artifactId>
<version>1.8.0</version>
</dependency>
<dependency>
<groupId>com.github.luben</groupId>
<artifactId>zstd-jni</artifactId>
<version>1.5.2-3</version>
</dependency>
</dependencies>
<!-- required until fixed plexus-compiler-eclipse is deployed -->
@ -144,7 +154,7 @@
<!-- PaperSpigot - Repo for gitdescribe -->
<pluginRepository>
<id>destroystokyo</id>
<url>https://ci.destroystokyo.com/plugin/repository/everything/</url>
<url>https://papermc.io/repo/repository/maven-public/</url>
</pluginRepository>
</pluginRepositories>

View File

@ -6,6 +6,8 @@ import com.elevatemc.spigot.handler.MovementHandler;
import com.elevatemc.spigot.handler.PacketHandler;
import com.elevatemc.spigot.util.YamlConfig;
import net.minecraft.server.MinecraftServer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import com.elevatemc.spigot.knockback.KnockbackHandler;
@ -13,14 +15,11 @@ import org.bukkit.craftbukkit.CraftServer;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.*;
public class eSpigot {
private final Set<PacketHandler> packetHandlers = new HashSet<>();
private final Set<MovementHandler> movementHandlers = new HashSet<>();
public static final ScheduledExecutorService EXECUTOR_SERVICE =

View File

@ -11,7 +11,8 @@ public enum eSpigotFeature {
NATURAL_MOB_SPAWNING(false),
SHOW_HIDDEN_PLAYERS_IN_TAB(true),
MOB_AI(false),
FIX_SPRINT_EAT_EXPLOIT(true);
FIX_SPRINT_EAT_EXPLOIT(true),
OBFUSCATE_HEALTH(true);
private boolean enabled;

View File

@ -13,7 +13,7 @@ public class NamePriorityThreadFactory implements ThreadFactory {
private final int priority;
private int idCounter = 0;
private String name = "gSpigotThread";
private String name = "eSpigotThread";
private boolean isDaemon = false;
private Queue<WeakReference<Thread>> createdThreadList;

View File

@ -10,7 +10,6 @@ import org.apache.logging.log4j.Logger;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.ref.WeakReference;
import java.util.ArrayDeque;
import java.util.Iterator;
@ -54,7 +53,7 @@ public class ThreadingManager {
while((this.nbtFiles.isActive()) && !this.cachedThreadPool.isTerminated()) {
try {
this.cachedThreadPool.awaitTermination(10, TimeUnit.SECONDS);
log.warn("gSpigot is still waiting for NBT files to be written to disk. " + this.nbtFiles.getTaskCount() + " to go...");
log.warn("eSpigot is still waiting for NBT files to be written to disk. " + this.nbtFiles.getTaskCount() + " to go...");
} catch(InterruptedException e) {}
}
if(!this.cachedThreadPool.isTerminated()) {
@ -65,7 +64,7 @@ public class ThreadingManager {
e.printStackTrace();
}
if(this.cachedThreadPoolFactory.getActiveCount() > 0) {
log.warn("gSpigot is still waiting for " + this.cachedThreadPoolFactory.getActiveCount() + " async threads to finish.");
log.warn("eSpigot is still waiting for " + this.cachedThreadPoolFactory.getActiveCount() + " async threads to finish.");
Queue<WeakReference<Thread>> queue = this.cachedThreadPoolFactory.getThreadList();
Iterator<WeakReference<Thread>> iter = null;
if(queue != null) {
@ -177,7 +176,7 @@ public class ThreadingManager {
}
}
private static boolean checkTickTime(float tickTime) {
public static boolean checkTickTime(float tickTime) {
if(tickTime > 45.0F) {
if(timerDelay > 40) {
timerDelay--;

View File

@ -0,0 +1,25 @@
// KigPaper
package com.elevatemc.spigot.util;
import net.minecraft.server.EnumParticle;
import org.bukkit.Effect;
import java.util.EnumMap;
public class Dictionary {
public static final EnumMap<Effect, EnumParticle> EFFECT_TO_PARTICLE = new EnumMap<>(Effect.class);
static {
String tmp;
for (EnumParticle p : EnumParticle.values()) {
tmp = p.b().replace("_", "");
for (Effect e : Effect.values()) {
// This is pretty much the original code, but we only call it once / effect & matching particle
if (e.getName() != null && e.getName().startsWith(tmp)) {
EFFECT_TO_PARTICLE.put(e, p);
break;
}
}
}
}
}

View File

@ -0,0 +1,63 @@
package com.elevatemc.spigot.world;
import co.aikar.timings.SpigotTimings;
import org.bukkit.Bukkit;
import org.bukkit.event.world.WorldSaveEvent;
import net.minecraft.server.ExceptionWorldConflict;
import net.minecraft.server.FileIOThread;
import net.minecraft.server.IProgressUpdate;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.RegionFileCache;
import net.minecraft.server.WorldServer;
public class AutoSaveJob {
public enum JobDetail {
WORLD_SAVE,
WORLD_SAVEEVENT,
}
private WorldServer worldserver;
private JobDetail jobDetail;
public AutoSaveJob(JobDetail detail, WorldServer worldserver) {
this.jobDetail = detail;
this.worldserver = worldserver;
}
/**
*
* @return true if the job shall be removed from the autosave queue
* @throws ExceptionWorldConflict
*/
public boolean process() throws ExceptionWorldConflict {
if(this.isJob(JobDetail.WORLD_SAVE) && this.worldserver != null) {
SpigotTimings.worldSaveTimer.startTiming();
MinecraftServer.getServer().info("[AutoSave] Saving world " + this.worldserver.getWorld().getName());
this.worldserver.save(true, (IProgressUpdate) null);
FileIOThread.a().setNoDelay(true);
SpigotTimings.worldSaveTimer.stopTiming();
} else if(this.isJob(JobDetail.WORLD_SAVEEVENT) && this.worldserver != null) {
if(FileIOThread.a().isDone()) {
SpigotTimings.worldSaveTimer.startTiming();
FileIOThread.a().setNoDelay(false);
RegionFileCache.a();
Bukkit.getPluginManager().callEvent(new WorldSaveEvent(this.worldserver.getWorld()));
SpigotTimings.worldSaveTimer.stopTiming();
} else {
return false;
}
}
this.worldserver = null;
return true;
}
private boolean isJob(JobDetail detail) {
if(this.jobDetail != null) {
return this.jobDetail.equals(detail);
}
return false;
}
}

View File

@ -0,0 +1,413 @@
package net.minecraft.server;
import java.util.Random;
public class BiomeDecorator {
protected World a;
protected Random b;
protected BlockPosition c;
protected CustomWorldSettingsFinal d;
protected WorldGenerator e = new WorldGenClay(4);
protected WorldGenerator f;
protected WorldGenerator g;
protected WorldGenerator h;
protected WorldGenerator i;
protected WorldGenerator j;
protected WorldGenerator k;
protected WorldGenerator l;
protected WorldGenerator m;
protected WorldGenerator n;
protected WorldGenerator o;
protected WorldGenerator p;
protected WorldGenerator q;
protected WorldGenerator r;
protected WorldGenFlowers s;
protected WorldGenerator t;
protected WorldGenerator u;
protected WorldGenerator v;
protected WorldGenerator w;
protected WorldGenerator x;
protected WorldGenerator y;
protected int z;
protected int A;
protected int B;
protected int C;
protected int D;
protected int E;
protected int F;
protected int G;
protected int H;
protected int I;
protected int J;
protected int K;
public boolean L;
public BiomeDecorator() {
this.f = new WorldGenSand(Blocks.SAND, 7);
this.g = new WorldGenSand(Blocks.GRAVEL, 6);
this.s = new WorldGenFlowers(Blocks.YELLOW_FLOWER, BlockFlowers.EnumFlowerVarient.DANDELION);
this.t = new WorldGenMushrooms(Blocks.BROWN_MUSHROOM);
this.u = new WorldGenMushrooms(Blocks.RED_MUSHROOM);
this.v = new WorldGenHugeMushroom();
this.w = new WorldGenReed();
this.x = new WorldGenCactus();
this.y = new WorldGenWaterLily();
this.B = 2;
this.C = 1;
this.H = 1;
this.I = 3;
this.J = 1;
this.L = true;
}
// Migot start
protected BiomeDecorator createShallowCopy() {
return new BiomeDecorator(this);
}
protected BiomeDecorator(BiomeDecorator decorator) {
this.f = decorator.f;
this.g = decorator.g;
this.s = decorator.s;
this.t = decorator.t;
this.u = decorator.u;
this.v = decorator.v;
this.w = decorator.w;
this.x = decorator.x;
this.y = decorator.y;
this.z = decorator.z;
this.A = decorator.A;
this.B = decorator.B;
this.C = decorator.C;
this.D = decorator.D;
this.E = decorator.E;
this.F = decorator.F;
this.G = decorator.G;
this.H = decorator.H;
this.I = decorator.I;
this.J = decorator.J;
this.K = decorator.K;
this.L = decorator.L;
}
// Migot end
public void a(World world, Random random, BiomeBase biomebase, BlockPosition blockposition) {
if (this.a != null) {
// Migot start
BiomeDecorator decorator = this.createShallowCopy();
decorator.a = world;
String s = world.getWorldData().getGeneratorOptions();
if (s != null) {
decorator.d = CustomWorldSettingsFinal.CustomWorldSettings.a(s).b();
} else {
decorator.d = CustomWorldSettingsFinal.CustomWorldSettings.a("").b();
}
decorator.b = random;
decorator.c = blockposition;
decorator.h = new WorldGenMinable(Blocks.DIRT.getBlockData(), decorator.d.I);
decorator.i = new WorldGenMinable(Blocks.GRAVEL.getBlockData(), decorator.d.M);
decorator.j = new WorldGenMinable(Blocks.STONE.getBlockData().set(BlockStone.VARIANT, BlockStone.EnumStoneVariant.GRANITE), decorator.d.Q);
decorator.k = new WorldGenMinable(Blocks.STONE.getBlockData().set(BlockStone.VARIANT, BlockStone.EnumStoneVariant.DIORITE), decorator.d.U);
decorator.l = new WorldGenMinable(Blocks.STONE.getBlockData().set(BlockStone.VARIANT, BlockStone.EnumStoneVariant.ANDESITE), decorator.d.Y);
decorator.m = new WorldGenMinable(Blocks.COAL_ORE.getBlockData(), decorator.d.ac);
decorator.n = new WorldGenMinable(Blocks.IRON_ORE.getBlockData(), decorator.d.ag);
decorator.o = new WorldGenMinable(Blocks.GOLD_ORE.getBlockData(), decorator.d.ak);
decorator.p = new WorldGenMinable(Blocks.REDSTONE_ORE.getBlockData(), decorator.d.ao);
decorator.q = new WorldGenMinable(Blocks.DIAMOND_ORE.getBlockData(), decorator.d.as);
decorator.r = new WorldGenMinable(Blocks.LAPIS_ORE.getBlockData(), decorator.d.aw);
decorator.a(biomebase);
decorator.a = null;
decorator.b = null;
// Migot end
} else {
this.a = world;
String s = world.getWorldData().getGeneratorOptions();
if (s != null) {
this.d = CustomWorldSettingsFinal.CustomWorldSettings.a(s).b();
} else {
this.d = CustomWorldSettingsFinal.CustomWorldSettings.a("").b();
}
this.b = random;
this.c = blockposition;
this.h = new WorldGenMinable(Blocks.DIRT.getBlockData(), this.d.I);
this.i = new WorldGenMinable(Blocks.GRAVEL.getBlockData(), this.d.M);
this.j = new WorldGenMinable(Blocks.STONE.getBlockData().set(BlockStone.VARIANT, BlockStone.EnumStoneVariant.GRANITE), this.d.Q);
this.k = new WorldGenMinable(Blocks.STONE.getBlockData().set(BlockStone.VARIANT, BlockStone.EnumStoneVariant.DIORITE), this.d.U);
this.l = new WorldGenMinable(Blocks.STONE.getBlockData().set(BlockStone.VARIANT, BlockStone.EnumStoneVariant.ANDESITE), this.d.Y);
this.m = new WorldGenMinable(Blocks.COAL_ORE.getBlockData(), this.d.ac);
this.n = new WorldGenMinable(Blocks.IRON_ORE.getBlockData(), this.d.ag);
this.o = new WorldGenMinable(Blocks.GOLD_ORE.getBlockData(), this.d.ak);
this.p = new WorldGenMinable(Blocks.REDSTONE_ORE.getBlockData(), this.d.ao);
this.q = new WorldGenMinable(Blocks.DIAMOND_ORE.getBlockData(), this.d.as);
this.r = new WorldGenMinable(Blocks.LAPIS_ORE.getBlockData(), this.d.aw);
this.a(biomebase);
this.a = null;
this.b = null;
}
}
protected void a(BiomeBase biomebase) {
this.a();
int i;
int j;
int k;
for (i = 0; i < this.I; ++i) {
j = this.b.nextInt(16) + 8;
k = this.b.nextInt(16) + 8;
this.f.generate(this.a, this.b, this.a.r(this.c.a(j, 0, k)));
}
for (i = 0; i < this.J; ++i) {
j = this.b.nextInt(16) + 8;
k = this.b.nextInt(16) + 8;
this.e.generate(this.a, this.b, this.a.r(this.c.a(j, 0, k)));
}
for (i = 0; i < this.H; ++i) {
j = this.b.nextInt(16) + 8;
k = this.b.nextInt(16) + 8;
this.g.generate(this.a, this.b, this.a.r(this.c.a(j, 0, k)));
}
i = this.A;
if (this.b.nextInt(10) == 0) {
++i;
}
int l;
BlockPosition blockposition;
for (j = 0; j < i; ++j) {
k = this.b.nextInt(16) + 8;
l = this.b.nextInt(16) + 8;
WorldGenTreeAbstract worldgentreeabstract = biomebase.a(this.b);
worldgentreeabstract.e();
blockposition = this.a.getHighestBlockYAt(this.c.a(k, 0, l));
if (worldgentreeabstract.generate(this.a, this.b, blockposition)) {
worldgentreeabstract.a(this.a, this.b, blockposition);
}
}
for (j = 0; j < this.K; ++j) {
k = this.b.nextInt(16) + 8;
l = this.b.nextInt(16) + 8;
this.v.generate(this.a, this.b, this.a.getHighestBlockYAt(this.c.a(k, 0, l)));
}
BlockPosition blockposition1;
int i1;
int j1;
for (j = 0; j < this.B; ++j) {
k = this.b.nextInt(16) + 8;
l = this.b.nextInt(16) + 8;
i1 = this.a.getHighestBlockYAt(this.c.a(k, 0, l)).getY() + 32;
if (i1 > 0) {
j1 = this.b.nextInt(i1);
blockposition1 = this.c.a(k, j1, l);
BlockFlowers.EnumFlowerVarient blockflowers_enumflowervarient = biomebase.a(this.b, blockposition1);
BlockFlowers blockflowers = blockflowers_enumflowervarient.a().a();
if (blockflowers.getMaterial() != Material.AIR) {
this.s.a(blockflowers, blockflowers_enumflowervarient);
this.s.generate(this.a, this.b, blockposition1);
}
}
}
for (j = 0; j < this.C; ++j) {
k = this.b.nextInt(16) + 8;
l = this.b.nextInt(16) + 8;
i1 = this.a.getHighestBlockYAt(this.c.a(k, 0, l)).getY() * 2;
if (i1 > 0) {
j1 = this.b.nextInt(i1);
biomebase.b(this.b).generate(this.a, this.b, this.c.a(k, j1, l));
}
}
for (j = 0; j < this.D; ++j) {
k = this.b.nextInt(16) + 8;
l = this.b.nextInt(16) + 8;
i1 = this.a.getHighestBlockYAt(this.c.a(k, 0, l)).getY() * 2;
if (i1 > 0) {
j1 = this.b.nextInt(i1);
(new WorldGenDeadBush()).generate(this.a, this.b, this.c.a(k, j1, l));
}
}
for (j = 0; j < this.z; ++j) {
k = this.b.nextInt(16) + 8;
l = this.b.nextInt(16) + 8;
i1 = this.a.getHighestBlockYAt(this.c.a(k, 0, l)).getY() * 2;
if (i1 > 0) {
j1 = this.b.nextInt(i1);
BlockPosition blockposition2;
for (blockposition1 = this.c.a(k, j1, l); blockposition1.getY() > 0; blockposition1 = blockposition2) {
blockposition2 = blockposition1.down();
if (!this.a.isEmpty(blockposition2)) {
break;
}
}
this.y.generate(this.a, this.b, blockposition1);
}
}
for (j = 0; j < this.E; ++j) {
if (this.b.nextInt(4) == 0) {
k = this.b.nextInt(16) + 8;
l = this.b.nextInt(16) + 8;
BlockPosition blockposition3 = this.a.getHighestBlockYAt(this.c.a(k, 0, l));
this.t.generate(this.a, this.b, blockposition3);
}
if (this.b.nextInt(8) == 0) {
k = this.b.nextInt(16) + 8;
l = this.b.nextInt(16) + 8;
i1 = this.a.getHighestBlockYAt(this.c.a(k, 0, l)).getY() * 2;
if (i1 > 0) {
j1 = this.b.nextInt(i1);
blockposition1 = this.c.a(k, j1, l);
this.u.generate(this.a, this.b, blockposition1);
}
}
}
if (this.b.nextInt(4) == 0) {
j = this.b.nextInt(16) + 8;
k = this.b.nextInt(16) + 8;
l = this.a.getHighestBlockYAt(this.c.a(j, 0, k)).getY() * 2;
if (l > 0) {
i1 = this.b.nextInt(l);
this.t.generate(this.a, this.b, this.c.a(j, i1, k));
}
}
if (this.b.nextInt(8) == 0) {
j = this.b.nextInt(16) + 8;
k = this.b.nextInt(16) + 8;
l = this.a.getHighestBlockYAt(this.c.a(j, 0, k)).getY() * 2;
if (l > 0) {
i1 = this.b.nextInt(l);
this.u.generate(this.a, this.b, this.c.a(j, i1, k));
}
}
for (j = 0; j < this.F; ++j) {
k = this.b.nextInt(16) + 8;
l = this.b.nextInt(16) + 8;
i1 = this.a.getHighestBlockYAt(this.c.a(k, 0, l)).getY() * 2;
if (i1 > 0) {
j1 = this.b.nextInt(i1);
this.w.generate(this.a, this.b, this.c.a(k, j1, l));
}
}
for (j = 0; j < 10; ++j) {
k = this.b.nextInt(16) + 8;
l = this.b.nextInt(16) + 8;
i1 = this.a.getHighestBlockYAt(this.c.a(k, 0, l)).getY() * 2;
if (i1 > 0) {
j1 = this.b.nextInt(i1);
this.w.generate(this.a, this.b, this.c.a(k, j1, l));
}
}
if (this.b.nextInt(32) == 0) {
j = this.b.nextInt(16) + 8;
k = this.b.nextInt(16) + 8;
l = this.a.getHighestBlockYAt(this.c.a(j, 0, k)).getY() * 2;
if (l > 0) {
i1 = this.b.nextInt(l);
(new WorldGenPumpkin()).generate(this.a, this.b, this.c.a(j, i1, k));
}
}
for (j = 0; j < this.G; ++j) {
k = this.b.nextInt(16) + 8;
l = this.b.nextInt(16) + 8;
i1 = this.a.getHighestBlockYAt(this.c.a(k, 0, l)).getY() * 2;
if (i1 > 0) {
j1 = this.b.nextInt(i1);
this.x.generate(this.a, this.b, this.c.a(k, j1, l));
}
}
if (this.L) {
for (j = 0; j < 50; ++j) {
k = this.b.nextInt(16) + 8;
l = this.b.nextInt(16) + 8;
i1 = this.b.nextInt(248) + 8;
if (i1 > 0) {
j1 = this.b.nextInt(i1);
blockposition1 = this.c.a(k, j1, l);
(new WorldGenLiquids(Blocks.FLOWING_WATER)).generate(this.a, this.b, blockposition1);
}
}
for (j = 0; j < 20; ++j) {
k = this.b.nextInt(16) + 8;
l = this.b.nextInt(16) + 8;
i1 = this.b.nextInt(this.b.nextInt(this.b.nextInt(240) + 8) + 8);
blockposition = this.c.a(k, i1, l);
(new WorldGenLiquids(Blocks.FLOWING_LAVA)).generate(this.a, this.b, blockposition);
}
}
}
protected void a(int i, WorldGenerator worldgenerator, int j, int k) {
int l;
if (k < j) {
l = j;
j = k;
k = l;
} else if (k == j) {
if (j < 255) {
++k;
} else {
--j;
}
}
for (l = 0; l < i; ++l) {
BlockPosition blockposition = this.c.a(this.b.nextInt(16), this.b.nextInt(k - j) + j, this.b.nextInt(16));
worldgenerator.generate(this.a, this.b, blockposition);
}
}
protected void b(int i, WorldGenerator worldgenerator, int j, int k) {
for (int l = 0; l < i; ++l) {
BlockPosition blockposition = this.c.a(this.b.nextInt(16), this.b.nextInt(k) + this.b.nextInt(k) + j - k, this.b.nextInt(16));
worldgenerator.generate(this.a, this.b, blockposition);
}
}
protected void a() {
this.a(this.d.J, this.h, this.d.K, this.d.L);
this.a(this.d.N, this.i, this.d.O, this.d.P);
this.a(this.d.V, this.k, this.d.W, this.d.X);
this.a(this.d.R, this.j, this.d.S, this.d.T);
this.a(this.d.Z, this.l, this.d.aa, this.d.ab);
this.a(this.d.ad, this.m, this.d.ae, this.d.af);
this.a(this.d.ah, this.n, this.d.ai, this.d.aj);
this.a(this.d.al, this.o, this.d.am, this.d.an);
this.a(this.d.ap, this.p, this.d.aq, this.d.ar);
this.a(this.d.at, this.q, this.d.au, this.d.av);
this.b(this.d.ax, this.r, this.d.ay, this.d.az);
}
}

View File

@ -8,6 +8,18 @@ public class BiomeTheEndDecorator extends BiomeDecorator {
this.M = new WorldGenEnder(Blocks.END_STONE);
}
// Migot start
public BiomeTheEndDecorator(BiomeTheEndDecorator decorator) {
super(decorator);
this.M = decorator.M;
}
@Override
protected BiomeDecorator createShallowCopy() {
return new BiomeTheEndDecorator(this);
}
// Migot end
protected void a(BiomeBase biomebase) {
this.a();
if (this.b.nextInt(5) == 0) {

View File

@ -4,6 +4,7 @@ import java.util.Iterator;
import java.util.Random;
import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit
import org.bukkit.event.block.BlockPhysicsEvent;
public class BlockCactus extends Block {
@ -64,7 +65,10 @@ public class BlockCactus extends Block {
public void doPhysics(World world, BlockPosition blockposition, IBlockData iblockdata, Block block) {
if (!this.e(world, blockposition)) {
world.setAir(blockposition, true);
org.bukkit.block.Block bukkit = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ());
BlockPhysicsEvent event = new BlockPhysicsEvent(bukkit, bukkit.getTypeId());
world.getServer().getPluginManager().callEvent(event);
if(!event.isCancelled()) world.setAir(blockposition, true);
}
}

View File

@ -64,10 +64,16 @@ public class BlockRedstoneWire extends Block {
}
private IBlockData e(World world, BlockPosition blockposition, IBlockData iblockdata) {
iblockdata = this.a(world, blockposition, blockposition, iblockdata);
ArrayList arraylist = Lists.newArrayList(this.R);
// Migot start
ArrayList arraylist;
synchronized(this.R) {
iblockdata = this.a(world, blockposition, blockposition, iblockdata);
arraylist = Lists.newArrayList(this.R);
this.R.clear();
}
// Migot end
this.R.clear();
Iterator iterator = arraylist.iterator();
while (iterator.hasNext()) {

View File

@ -50,6 +50,19 @@ public class Chunk {
private int v;
private ConcurrentLinkedQueue<BlockPosition> w;
protected gnu.trove.map.hash.TObjectIntHashMap<Class> entityCount = new gnu.trove.map.hash.TObjectIntHashMap<Class>(); // Spigot
// Migot start
private boolean unloaded = false;
public boolean wasUnloaded() {
return this.unloaded;
}
public void markAsUnloaded() {
this.unloaded = true;
}
// Migot end
// PaperSpigot start - Asynchronous light updates
public AtomicInteger pendingLightUpdates = new AtomicInteger();
public long lightUpdateTime;
@ -1061,7 +1074,7 @@ public class Chunk {
if (this.r && this.world.getTime() != this.lastSaved || this.q) {
return true;
}
} else if (this.r && this.world.getTime() >= this.lastSaved + MinecraftServer.getServer().autosavePeriod * 4) { // Spigot - Only save if we've passed 2 auto save intervals without modification
} else if (this.r && this.world.getTime() >= 600L) {
return true;
}

View File

@ -36,13 +36,27 @@ public class ChunkProviderServer implements IChunkProvider {
public LongSet unloadQueue = new LongArraySet(); // CraftBukkit - LongHashSet // TacoSpigot - LongHashSet -> HashArraySet
public Chunk emptyChunk;
public IChunkProvider chunkProvider;
private IChunkLoader chunkLoader;
public IChunkLoader chunkLoader; // KigPaper - private -> public
public boolean forceChunkLoad = false; // CraftBukkit - true -> false
public Long2ObjectMap<Chunk> chunks = new Long2ObjectOpenHashMap<Chunk>(4096, 0.5f); // TacoSpigot - use trove Long2ObjectOpenHashMap instead of craftbukkit implementation (using inital capacity and load factor chosen by Amaranth in an old impl)
public WorldServer world;
// Migot start
private ChunkRegionLoader checkedRegionLoader = null;
public boolean doesChunkExist(int x, int z) {
if(this.checkedRegionLoader == null && this.chunkLoader instanceof ChunkRegionLoader) {
this.checkedRegionLoader = (ChunkRegionLoader) this.chunkLoader;
}
if(this.checkedRegionLoader != null) {
return this.checkedRegionLoader.chunkExists(this.world, x, z);
}
return false;
}
// Migot end
public ChunkProviderServer(WorldServer worldserver, IChunkLoader ichunkloader, IChunkProvider ichunkprovider) {
this.emptyChunk = new EmptyChunk(worldserver, 0, 0);
this.emptyChunk = new EmptyChunk(worldserver, Integer.MIN_VALUE, Integer.MIN_VALUE); // Migot
this.world = worldserver;
this.chunkLoader = ichunkloader;
this.chunkProvider = ichunkprovider;
@ -347,7 +361,7 @@ public class ChunkProviderServer implements IChunkProvider {
this.saveChunk(chunk);
chunk.f(false);
++i;
if (i == 24 && !flag && false) { // Spigot
if (i == 24 && !flag) {
return false;
}
}
@ -381,6 +395,7 @@ public class ChunkProviderServer implements IChunkProvider {
if (!event.isCancelled()) {
if (chunk != null) {
chunk.markAsUnloaded(); // Migot
chunk.removeEntities();
this.saveChunk(chunk);
this.saveChunkNOP(chunk);

View File

@ -17,8 +17,10 @@ import org.apache.logging.log4j.Logger;
public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
private static final Logger a = LogManager.getLogger();
private Map<ChunkCoordIntPair, NBTTagCompound> b = new ConcurrentHashMap();
private Set<ChunkCoordIntPair> c = Collections.newSetFromMap(new ConcurrentHashMap());
// KigPaper start - make public
public Map<ChunkCoordIntPair, NBTTagCompound> b = new ConcurrentHashMap();
public Set<ChunkCoordIntPair> c = Collections.newSetFromMap(new ConcurrentHashMap());
// KigPaper end
private final File d;
private boolean e = false;
@ -29,6 +31,14 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
// CraftBukkit start
public boolean chunkExists(World world, int i, int j) {
ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(i, j);
// Migot start
return this.chunkExists(world, chunkcoordintpair);
}
public boolean chunkExists(World world, ChunkCoordIntPair chunkcoordintpair) {
int i = chunkcoordintpair.x;
int j = chunkcoordintpair.z;
// Migot end
if (this.c.contains(chunkcoordintpair)) {
if (this.b.containsKey(chunkcoordintpair)) {
@ -62,13 +72,15 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
NBTTagCompound nbttagcompound = (NBTTagCompound) this.b.get(chunkcoordintpair);
if (nbttagcompound == null) {
DataInputStream datainputstream = RegionFileCache.c(this.d, i, j);
// KigPaper - use try-with-resources
// While this is always a ByteArrayInputStream (which does nothing on close), this is not something to be relied upon.
try (DataInputStream datainputstream = RegionFileCache.c(this.d, i, j)) {
if (datainputstream == null) {
return null;
}
if (datainputstream == null) {
return null;
nbttagcompound = NBTCompressedStreamTools.a(datainputstream);
}
nbttagcompound = NBTCompressedStreamTools.a(datainputstream);
}
return this.a(world, i, j, nbttagcompound);
@ -175,10 +187,10 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
}
private void b(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException {
DataOutputStream dataoutputstream = RegionFileCache.d(this.d, chunkcoordintpair.x, chunkcoordintpair.z);
NBTCompressedStreamTools.a(nbttagcompound, (DataOutput) dataoutputstream);
dataoutputstream.close();
// KigPaper - use try-with-resources
try (DataOutputStream dataoutputstream = RegionFileCache.d(this.d, chunkcoordintpair.x, chunkcoordintpair.z)) {
NBTCompressedStreamTools.a(nbttagcompound, (DataOutput) dataoutputstream);
}
}
public void b(World world, Chunk chunk) throws IOException {}

View File

@ -9,7 +9,7 @@ public class ContainerWorkbench extends Container {
public InventoryCrafting craftInventory; // CraftBukkit - move initialization into constructor
public IInventory resultInventory; // CraftBukkit - move initialization into constructor
private World g;
public World g; // KigPaper - make public
private BlockPosition h;
// CraftBukkit start
private CraftInventoryView bukkitEntity = null;

View File

@ -124,7 +124,7 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer
this.propertyManager = new PropertyManager(this.options); // CraftBukkit - CLI argument support
this.p = new EULA(new File("eula.txt"));
// Spigot Start
boolean eulaAgreed = Boolean.getBoolean( "com.mojang.eula.agree" );
boolean eulaAgreed = true;
if ( eulaAgreed )
{
System.err.println( "You have used the Spigot command line EULA agreement flag." );

View File

@ -148,6 +148,9 @@ public class EnchantmentManager {
EnchantmentManager.b.a = 0;
}
// KigPaper start
EnchantmentManager.b.b = null;
// KigPaper end
return (EnchantmentManager.b.a + 1 >> 1) + EnchantmentManager.a.nextInt((EnchantmentManager.b.a >> 1) + 1);
}
@ -169,6 +172,10 @@ public class EnchantmentManager {
a((EnchantmentManager.EnchantmentModifier) EnchantmentManager.d, entityliving.bA());
}
// KigPaper start
EnchantmentManager.d.a = null;
EnchantmentManager.d.b = null;
// KigPaper end
}
public static void b(EntityLiving entityliving, Entity entity) {
@ -182,6 +189,10 @@ public class EnchantmentManager {
a((EnchantmentManager.EnchantmentModifier) EnchantmentManager.e, entityliving.bA());
}
// KigPaper start
EnchantmentManager.e.a = null;
EnchantmentManager.e.b = null;
// KigPaper end
}
public static int a(EntityLiving entityliving) {

View File

@ -1,13 +1,11 @@
package net.minecraft.server;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.UUID;
import java.util.*;
import java.util.concurrent.Callable;
// CraftBukkit start
import com.elevatemc.spigot.util.FastRandom;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.LogManager;
import org.bukkit.Bukkit;
import org.bukkit.Location;
@ -36,6 +34,7 @@ import org.bukkit.plugin.PluginManager;
// CraftBukkit end
// PaperSpigot start
import org.github.paperspigot.PaperSpigotConfig;
import org.spigotmc.event.entity.EntityDismountEvent;
// PaperSpigot end
@ -49,7 +48,7 @@ public abstract class Entity implements ICommandListener {
// CraftBukikt end
private static final AxisAlignedBB a = new AxisAlignedBB(0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D);
private static int entityCount;
private static int entityCount = 1;
private int id;
public double j;
public boolean k;
@ -121,10 +120,6 @@ public abstract class Entity implements ICommandListener {
public int portalCooldown;
protected boolean ak;
public final boolean inPortal() {
return this.ak;
} // Paper - OBFHELPER
protected int al;
public int dimension;
protected BlockPosition an;
@ -163,6 +158,16 @@ public abstract class Entity implements ICommandListener {
public void inactiveTick() { }
// Spigot end
// Migot start
private int targetDimension;
private boolean isInLava;
private int lastLavaCheck = Integer.MIN_VALUE;
public int getTargetDimension() {
return this.targetDimension;
}
// Migot end
public int getId() {
return this.id;
}
@ -191,6 +196,7 @@ public abstract class Entity implements ICommandListener {
this.setPosition(0.0D, 0.0D, 0.0D);
if (world != null) {
this.dimension = world.worldProvider.getDimension();
this.targetDimension = this.dimension; // Migot
// Spigot start
this.defaultActivationState = org.spigotmc.ActivationRange.initializeEntityActivationState(this, world.spigotConfig);
} else {
@ -304,7 +310,7 @@ public abstract class Entity implements ICommandListener {
this.lastZ = this.locZ;
this.lastPitch = this.pitch;
this.lastYaw = this.yaw;
if (!this.world.isClientSide && this.world instanceof WorldServer) {
if (!this.world.isClientSide && this.world instanceof WorldServer && !(this instanceof EntityProjectile) && !(this instanceof EntityArrow) && !(this instanceof EntityFireball)) { // Migot
this.world.methodProfiler.a("portal");
MinecraftServer minecraftserver = ((WorldServer) this.world).getMinecraftServer();
int i = this.L();
@ -842,10 +848,12 @@ public abstract class Entity implements ICommandListener {
BlockPosition blockposition1 = new BlockPosition(this.getBoundingBox().d - 0.001D, this.getBoundingBox().e - 0.001D, this.getBoundingBox().f - 0.001D);
if (this.world.areChunksLoadedBetween(blockposition, blockposition1)) {
for (int i = blockposition.getX(); i <= blockposition1.getX(); ++i) {
for (int j = blockposition.getY(); j <= blockposition1.getY(); ++j) {
// KigPaper - Start - invert loop
for (int i = blockposition1.getY(); i >= blockposition.getY(); --i) {
// KigPaper - End
for (int j = blockposition.getX(); j <= blockposition1.getX(); ++j) {
for (int k = blockposition.getZ(); k <= blockposition1.getZ(); ++k) {
BlockPosition blockposition2 = new BlockPosition(i, j, k);
BlockPosition blockposition2 = new BlockPosition(j, i, k);
IBlockData iblockdata = this.world.getType(blockposition2);
try {
@ -898,6 +906,19 @@ public abstract class Entity implements ICommandListener {
protected void a(double d0, boolean flag, Block block, BlockPosition blockposition) {
if (flag) {
if (this.fallDistance > 0.0F) {
// KigPaper start - run again if we need accurate detection at high falling speeds
if (PaperSpigotConfig.accurateBlockCollisions) {
try {
this.checkBlockCollisions();
} catch (Throwable throwable) {
CrashReport crashreport = CrashReport.a(throwable, "Checking entity block collision");
CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Entity being checked for collision");
this.appendEntityCrashDetails(crashreportsystemdetails);
throw new ReportedException(crashreport);
}
}
// KigPaper end
if (block != null) {
block.fallOn(this.world, blockposition, this, this.fallDistance);
} else {
@ -943,7 +964,36 @@ public abstract class Entity implements ICommandListener {
}
public boolean W() {
if (this.world.a(this.getBoundingBox().grow(0.0D, -0.4000000059604645D, 0.0D).shrink(0.001D, 0.001D, 0.001D), Material.WATER, this)) {
AxisAlignedBB boundingBox = this.getBoundingBox();
// KigPaper start
if (PaperSpigotConfig.accurateBlockCollisions && this instanceof EntityPlayer) {
// Account for vertical speed in minY
AxisAlignedBB tmp = new AxisAlignedBB(boundingBox.a, boundingBox.b + this.motY / 2, boundingBox.c, boundingBox.d, boundingBox.e, boundingBox.f);
boolean useTmp = true;
int tmpX = MathHelper.floor(tmp.a);
int tmpMaxX = MathHelper.floor(tmp.d);
int tmpY = MathHelper.floor(tmp.b);
int tmpMaxY = MathHelper.floor(tmp.e);
int tmpZ = MathHelper.floor(tmp.c);
int tmpMaxZ = MathHelper.floor(tmp.f);
BlockPosition.MutableBlockPosition blockPosition = new BlockPosition.MutableBlockPosition();
Block block;
for (int x = tmpX; x <= tmpMaxX; ++x) {
for (int y = tmpY; y <= tmpMaxY; ++y) {
for (int z = tmpZ; z <= tmpMaxZ; ++z) {
block = world.getType(blockPosition.c(x, y, z)).getBlock();
if (block.getMaterial().isSolid() || world.getType(blockPosition.c(x, Math.max(y - 1, 0), z)).getBlock().getMaterial().isSolid()) {
useTmp = false;
}
}
}
}
if (useTmp) boundingBox = tmp;
}
// KigPaper end
if (this.world.a(boundingBox.grow(0.0D, -0.4000000059604645D, 0.0D).shrink(0.001D, 0.001D, 0.001D), Material.WATER, this)) {
if (!this.inWater && !this.justCreated) {
this.X();
}
@ -1029,7 +1079,12 @@ public abstract class Entity implements ICommandListener {
}
public boolean ab() {
return this.world.a(this.getBoundingBox().grow(-0.10000000149011612D, -0.4000000059604645D, -0.10000000149011612D), Material.LAVA);
int currentTick = MinecraftServer.currentTick;
if (this.lastLavaCheck != currentTick) {
this.lastLavaCheck = currentTick;
this.isInLava = this.world.a(this.getBoundingBox().grow(-0.10000000149011612D, -0.4000000059604645D, -0.10000000149011612D), Material.LAVA);
}
return this.isInLava;
}
public void a(float f, float f1, float f2) {
@ -1649,7 +1704,7 @@ public abstract class Entity implements ICommandListener {
this.vehicle = null;
} else {
// CraftBukkit start
if ((this.bukkitEntity instanceof LivingEntity) && (entity.getBukkitEntity() instanceof Vehicle) && entity.world.isChunkLoaded((int) entity.locX >> 4, (int) entity.locZ >> 4, true)) {
if ((this.bukkitEntity instanceof LivingEntity) && (entity.getBukkitEntity() instanceof Vehicle) && entity.world.isChunkLoaded(MathHelper.floor(entity.locX) >> 4, MathHelper.floor(entity.locZ) >> 4, true)) { // Migot - fix rounding error
// It's possible to move from one vehicle to another. We need to check if they're already in a vehicle, and fire an exit event if they are.
VehicleExitEvent exitEvent = null;
if (this.vehicle != null && this.vehicle.getBukkitEntity() instanceof Vehicle) {
@ -1986,6 +2041,15 @@ public abstract class Entity implements ICommandListener {
}
public void c(int i) {
// Migot start - Entities will be queued and teleported after all worlds have been ticked
if(i != this.dimension) {
this.targetDimension = i;
this.world.queueEntityForDimensionChange(this);
}
}
public void changeDimension(int i) {
// Migot end
if (!this.world.isClientSide && !this.dead) {
this.world.methodProfiler.a("changeDimension");
MinecraftServer minecraftserver = MinecraftServer.getServer();
@ -2015,7 +2079,9 @@ public abstract class Entity implements ICommandListener {
return;
}
exit = event.useTravelAgent() ? event.getPortalTravelAgent().findOrCreate(event.getTo()) : event.getTo();
this.teleportTo(exit, true);
if(exit != null) { // Migot
this.teleportTo(exit, true);
}
}
}

View File

@ -231,6 +231,8 @@ public class EntityArrow extends Entity implements IProjectile {
if (!((EntityPlayer) shooter).getBukkitEntity().canSee(((EntityPlayer) movingobjectposition.entity).getBukkitEntity())) {
movingobjectposition = null;
}
} else if (movingobjectposition != null && movingobjectposition.entity instanceof EntityArmorStand && movingobjectposition.entity.isInvisible()) {
movingobjectposition = null;
}
// PaperSpigot end
// TacoSpigot start - call better event
@ -290,7 +292,9 @@ public class EntityArrow extends Entity implements IProjectile {
}
if (this.shooter != null && movingobjectposition.entity != this.shooter && movingobjectposition.entity instanceof EntityHuman && this.shooter instanceof EntityPlayer) {
((EntityPlayer) this.shooter).playerConnection.sendPacket(new PacketPlayOutGameStateChange(6, 0.0F));
EntityPlayer shooter = (EntityPlayer) this.shooter;
shooter.p(movingobjectposition.entity); // KigPaper - set attacked entity (used for wolf pathfinding)
shooter.playerConnection.sendPacket(new PacketPlayOutGameStateChange(6, 0.0F));
}
}

View File

@ -43,7 +43,7 @@ public abstract class EntityCreature extends EntityInsentient {
public void setSearchResult(PathSearchJobEntity pathSearchJobEntity, Entity target, PathEntity pathentity) {
this.queuingManager.checkLastSearchResult(pathSearchJobEntity);
if (this.goalTarget != null && this.goalTarget.equals(target)) {
if (this.getGoalTarget() != null && this.getGoalTarget().equals(target)) {
this.returnedPathEntity = pathentity;
}
}

View File

@ -88,7 +88,7 @@ public class EntityEnderman extends EntityMonster {
return false;
} else {
Vec3D vec3d = entityhuman.d(1.0F).a();
Vec3D vec3d1 = new Vec3D(this.locX - entityhuman.locX, this.getBoundingBox().b + (double) (this.length / 2.0F) - (entityhuman.locY + (double) entityhuman.getHeadHeight()), this.locZ - entityhuman.locZ);
Vec3D vec3d1 = new Vec3D(this.locX - entityhuman.locX, (this.locY + (double) this.getHeadHeight()) - (entityhuman.locY + (double) entityhuman.getHeadHeight()), this.locZ - entityhuman.locZ); // Migot
double d0 = vec3d1.b();
vec3d1 = vec3d1.a();
@ -145,7 +145,7 @@ public class EntityEnderman extends EntityMonster {
}
protected boolean b(Entity entity) {
Vec3D vec3d = new Vec3D(this.locX - entity.locX, this.getBoundingBox().b + (double) (this.length / 2.0F) - entity.locY + (double) entity.getHeadHeight(), this.locZ - entity.locZ);
Vec3D vec3d = new Vec3D(this.locX - entity.locX, this.locY + (double) this.getHeadHeight() - entity.locY + (double) entity.getHeadHeight(), this.locZ - entity.locZ); // Migot
vec3d = vec3d.a();
double d0 = 16.0D;

View File

@ -59,11 +59,28 @@ public class EntityExperienceOrb extends Entity {
this.j(this.locX, (this.getBoundingBox().b + this.getBoundingBox().e) / 2.0D, this.locZ);
double d0 = 8.0D;
// Migot start
EntityHuman foundTarget = null;
if (this.targetTime < this.a - 20 + this.getId() % 100) {
if (this.targetPlayer == null || this.targetPlayer.h(this) > d0 * d0) {
this.targetPlayer = this.world.findNearbyPlayer(this, d0);
foundTarget = this.world.findNearbyPlayer(this, d0);
if(foundTarget == null) {
this.targetPlayer = foundTarget;
} else if(foundTarget != null && !foundTarget.equals(this.targetPlayer)) {
// CraftBukkit start
EntityTargetEvent event = CraftEventFactory.callEntityTargetEvent(this, foundTarget, EntityTargetEvent.TargetReason.CLOSEST_PLAYER);
Entity target = event.getTarget() == null ? null : ((org.bukkit.craftbukkit.entity.CraftEntity) event.getTarget()).getHandle();
if(!event.isCancelled()) {
if(target == null) {
this.targetPlayer = null;
} else if(target instanceof EntityHuman) {
this.targetPlayer = (EntityHuman) target;
}
}
// CraftBukkit end
}
}
// Migot end
this.targetTime = this.a;
}

View File

@ -192,6 +192,8 @@ public class EntityFishingHook extends Entity {
if (!((EntityPlayer) owner).getBukkitEntity().canSee(((EntityPlayer) movingobjectposition.entity).getBukkitEntity())) {
movingobjectposition = null;
}
} else if (movingobjectposition != null && movingobjectposition.entity instanceof EntityArmorStand && movingobjectposition.entity.isInvisible()) {
movingobjectposition = null;
}
// PaperSpigot end
@ -360,9 +362,6 @@ public class EntityFishingHook extends Entity {
this.motY *= (double) f2;
this.motZ *= (double) f2;
this.setPosition(this.locX, this.locY, this.locZ);
if (inPortal()) {
die();
}
}
}
}

View File

@ -1,5 +1,6 @@
package net.minecraft.server;
import java.lang.ref.WeakReference;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
@ -25,7 +26,7 @@ public abstract class EntityInsentient extends EntityLiving {
private Navigation navigation;
public PathfinderGoalSelector goalSelector;
public PathfinderGoalSelector targetSelector;
public EntityLiving goalTarget;
private WeakReference<EntityLiving> goalTarget; // KigPaper - wrap in WeakReference
private EntitySenses bk;
private ItemStack[] equipment = new ItemStack[5];
public float[] dropChances = new float[5];
@ -86,7 +87,7 @@ public abstract class EntityInsentient extends EntityLiving {
}
public EntityLiving getGoalTarget() {
return this.goalTarget;
return this.goalTarget == null ? null : this.goalTarget.get(); // KigPaper - WeakReference
}
public void setGoalTarget(EntityLiving entityliving) {
@ -119,7 +120,7 @@ public abstract class EntityInsentient extends EntityLiving {
entityliving = null;
}
}
this.goalTarget = entityliving;
this.goalTarget = new WeakReference<>(entityliving); // KigPaper - WeakReference
// CraftBukkit end
}
@ -277,6 +278,11 @@ public abstract class EntityInsentient extends EntityLiving {
nbttagcompound.set("Leash", nbttagcompound1);
}
// Migot start
else if (this.bq != null) {
nbttagcompound.set("Leash", this.bq);
}
// Migot end
if (this.ce()) {
nbttagcompound.setBoolean("NoAI", this.ce());
@ -889,11 +895,12 @@ public abstract class EntityInsentient extends EntityLiving {
EntityLiving entityliving = (EntityLiving) iterator.next();
if (entityliving.getUniqueID().equals(uuid)) {
this.bp = entityliving;
this.setLeashHolder(entityliving, true); // Migot
break;
}
}
} else if (this.bq.hasKeyOfType("X", 99) && this.bq.hasKeyOfType("Y", 99) && this.bq.hasKeyOfType("Z", 99)) {
}
if (this.bp == null && this.bq.hasKeyOfType("X", 99) && this.bq.hasKeyOfType("Y", 99) && this.bq.hasKeyOfType("Z", 99)) { // Migot
BlockPosition blockposition = new BlockPosition(this.bq.getInt("X"), this.bq.getInt("Y"), this.bq.getInt("Z"));
EntityLeash entityleash = EntityLeash.b(this.world, blockposition);
@ -901,8 +908,9 @@ public abstract class EntityInsentient extends EntityLiving {
entityleash = EntityLeash.a(this.world, blockposition);
}
this.bp = entityleash;
} else {
this.setLeashHolder(entityleash, true); // Migot
}
if (this.bp == null) { // Migot
this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit
this.unleash(false, true);
}

View File

@ -17,6 +17,7 @@ import com.google.common.collect.Lists;
import org.bukkit.craftbukkit.event.CraftEventFactory;
import org.bukkit.craftbukkit.util.CraftPotionUtil;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Vehicle;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageModifier;
@ -1786,7 +1787,10 @@ public abstract class EntityLiving extends Entity {
// CraftBukkit end
// PaperSpigot start - make dismountEvent cancellable
EntityDismountEvent dismountEvent = new EntityDismountEvent(this.getBukkitEntity(), this.vehicle.getBukkitEntity()); // Spigot
Bukkit.getPluginManager().callEvent(dismountEvent);
// KigPaper - only trigger EntityDismountEvent if the dismount was triggered by sneaking
if(!(this.bukkitEntity instanceof Player) || ((Player) this.bukkitEntity).isSneaking()) {
Bukkit.getPluginManager().callEvent(dismountEvent);
}
if (dismountEvent.isCancelled()) return;
// PaperSpigot end

View File

@ -523,6 +523,12 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
}
public void c(int i) {
// Migot Start
super.c(i);
}
public void changeDimension(int i) {
// Migot end
// PaperSpigot start - Allow configurable end portal credits
boolean endPortal = this.dimension == 1 && i == 1;
if (endPortal) {
@ -532,7 +538,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
this.viewingCredits = true;
this.playerConnection.sendPacket(new PacketPlayOutGameStateChange(4, 0.0F));
}
// PaperSpigot end
// PaperSpigot end
} else {
if (this.dimension == 0 && i == 1) {
this.b((Statistic) AchievementList.C);
@ -563,7 +569,6 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
this.bN = -1;
}
// PaperSpigot end
}
public boolean a(EntityPlayer entityplayer) {

View File

@ -158,6 +158,8 @@ public abstract class EntityProjectile extends Entity implements IProjectile {
if (!((EntityPlayer) shooter).getBukkitEntity().canSee(((EntityPlayer) movingobjectposition.entity).getBukkitEntity())) {
movingobjectposition = null;
}
} else if (movingobjectposition != null && movingobjectposition.entity instanceof EntityArmorStand && movingobjectposition.entity.isInvisible()) {
movingobjectposition = null;
}
// PaperSpigot end

View File

@ -1,11 +1,9 @@
package net.minecraft.server;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import com.elevatemc.spigot.eSpigotFeature;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -275,7 +273,34 @@ public class EntityTrackerEntry {
DataWatcher datawatcher = this.tracker.getDataWatcher();
if (datawatcher.a()) {
this.broadcastIncludingSelf(new PacketPlayOutEntityMetadata(this.tracker.getId(), datawatcher, false));
if (eSpigotFeature.OBFUSCATE_HEALTH.isEnabled()) {
List<DataWatcher.WatchableObject> changedMetadata = datawatcher.b();
Iterator<DataWatcher.WatchableObject> iter = changedMetadata.iterator();
boolean found = false;
while (iter.hasNext()) {
DataWatcher.WatchableObject watchable = iter.next();
if (watchable.a() == 6) {
iter.remove();
found = true;
}
}
if (found) {
changedMetadata.add(new DataWatcher.WatchableObject(3, 6, 1.0F));
}
PacketPlayOutEntityMetadata metadataPacket = new PacketPlayOutEntityMetadata(this.tracker.getId(), changedMetadata);
// Beanes - Broadcast the modified metadata packet to everyone
this.broadcast(metadataPacket);
// Beanes - Send the correct metadata packet to the player
if (this.tracker instanceof EntityPlayer)
((EntityPlayer) this.tracker).playerConnection.sendPacket(new PacketPlayOutEntityMetadata(this.tracker.getId(), datawatcher, false));
} else {
this.broadcastIncludingSelf(new PacketPlayOutEntityMetadata(this.tracker.getId(), datawatcher, false));
}
}
if (this.tracker instanceof EntityLiving) {
@ -405,7 +430,13 @@ public class EntityTrackerEntry {
// CraftBukkit start - Fix for nonsensical head yaw
this.i = MathHelper.d(this.tracker.getHeadRotation() * 256.0F / 360.0F);
this.broadcast(new PacketPlayOutEntityHeadRotation(this.tracker, (byte) i));
// KigPaper
if (this.tracker instanceof EntityLiving) {
this.i = MathHelper.d(this.tracker.getHeadRotation() * 256.0F / 360.0F);
// CraftBukkit what the fuck were you thinking?
//this.broadcast(new PacketPlayOutEntityHeadRotation(this.tracker, (byte) i)); // KigPaper
entityplayer.playerConnection.sendPacket(new PacketPlayOutEntityHeadRotation(this.tracker, (byte) i));
}
// CraftBukkit end
if (this.tracker instanceof EntityLiving) {

View File

@ -12,6 +12,16 @@ public class FileIOThread implements Runnable {
private volatile long d;
private volatile boolean e;
// Migot start
public boolean isDone() {
return this.c == this.d;
}
public void setNoDelay(boolean active) {
this.e = active;
}
// Migot end
private FileIOThread() {
Thread thread = new Thread(this, "File IO Thread");

View File

@ -1,63 +1,115 @@
package net.minecraft.server;
import com.google.common.collect.Lists;
// Migot start
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
// Migot end
public class IntCache {
private static int a = 256;
private static List<int[]> b = Lists.newArrayList();
private static List<int[]> c = Lists.newArrayList();
private static List<int[]> d = Lists.newArrayList();
private static List<int[]> e = Lists.newArrayList();
// Migot start - Refactored IntCache to be thread local instead of static
private static final ThreadLocal<IntCache> caches = new ThreadLocal<IntCache>() {
@Override
protected IntCache initialValue() {
IntCache cache = new IntCache();
synchronized(allCaches) {
allCaches.add(new WeakReference<IntCache>(cache));
}
return new IntCache();
}
};
public static synchronized int[] a(int i) {
private static List<WeakReference<IntCache>> allCaches = new ArrayList<WeakReference<IntCache>>();
private int a = 256;
private List<int[]> b = Lists.newArrayList();
private List<int[]> c = Lists.newArrayList();
private List<int[]> d = Lists.newArrayList();
private List<int[]> e = Lists.newArrayList();
public static int[] a(int i) {
return caches.get().aNonStatic(i);
}
public int[] aNonStatic(int i) {
int[] aint;
if (i <= 256) {
if (IntCache.b.isEmpty()) {
if (this.b.isEmpty()) {
aint = new int[256];
if (c.size() < org.spigotmc.SpigotConfig.intCacheLimit) IntCache.c.add(aint);
if (c.size() < org.spigotmc.SpigotConfig.intCacheLimit) this.c.add(aint);
return aint;
} else {
aint = (int[]) IntCache.b.remove(IntCache.b.size() - 1);
if (c.size() < org.spigotmc.SpigotConfig.intCacheLimit) IntCache.c.add(aint);
aint = (int[]) this.b.remove(this.b.size() - 1);
if (c.size() < org.spigotmc.SpigotConfig.intCacheLimit) this.c.add(aint);
return aint;
}
} else if (i > IntCache.a) {
IntCache.a = i;
IntCache.d.clear();
IntCache.e.clear();
aint = new int[IntCache.a];
if (e.size() < org.spigotmc.SpigotConfig.intCacheLimit) IntCache.e.add(aint);
} else if (i > this.a) {
this.a = i;
this.d.clear();
this.e.clear();
aint = new int[this.a];
if (e.size() < org.spigotmc.SpigotConfig.intCacheLimit) this.e.add(aint);
return aint;
} else if (IntCache.d.isEmpty()) {
aint = new int[IntCache.a];
if (e.size() < org.spigotmc.SpigotConfig.intCacheLimit) IntCache.e.add(aint);
} else if (this.d.isEmpty()) {
aint = new int[this.a];
if (e.size() < org.spigotmc.SpigotConfig.intCacheLimit) this.e.add(aint);
return aint;
} else {
aint = (int[]) IntCache.d.remove(IntCache.d.size() - 1);
if (e.size() < org.spigotmc.SpigotConfig.intCacheLimit) IntCache.e.add(aint);
aint = (int[]) this.d.remove(this.d.size() - 1);
if (e.size() < org.spigotmc.SpigotConfig.intCacheLimit) this.e.add(aint);
return aint;
}
}
public static synchronized void a() {
if (!IntCache.d.isEmpty()) {
IntCache.d.remove(IntCache.d.size() - 1);
}
if (!IntCache.b.isEmpty()) {
IntCache.b.remove(IntCache.b.size() - 1);
}
IntCache.d.addAll(IntCache.e);
IntCache.b.addAll(IntCache.c);
IntCache.e.clear();
IntCache.c.clear();
public static void a() {
caches.get().aNonStatic();
}
public static synchronized String b() {
return "cache: " + IntCache.d.size() + ", tcache: " + IntCache.b.size() + ", allocated: " + IntCache.e.size() + ", tallocated: " + IntCache.c.size();
public void aNonStatic() {
if (!this.d.isEmpty()) {
this.d.remove(this.d.size() - 1);
}
if (!this.b.isEmpty()) {
this.b.remove(this.b.size() - 1);
}
this.d.addAll(this.e);
this.b.addAll(this.c);
this.e.clear();
this.c.clear();
}
public static String b() {
int cache = 0;
int tcache = 0;
int allocated = 0;
int tallocated = 0;
int numberOfCaches;
synchronized(allCaches) {
numberOfCaches = allCaches.size();
Iterator<WeakReference<IntCache>> iter = allCaches.iterator();
while(iter.hasNext()) {
WeakReference<IntCache> reference = iter.next();
IntCache intcache = reference.get();
if(intcache != null) {
cache += intcache.d.size();
tcache += intcache.b.size();
allocated += intcache.e.size();
tallocated += intcache.c.size();
} else {
iter.remove();
}
}
}
return String.valueOf(numberOfCaches) + " IntCaches. In Total => cache: " + cache + ", tcache: " + tcache + ", allocated: " + allocated + ", tallocated: " + tallocated;
}
// Migot end
}

View File

@ -1,6 +1,7 @@
package net.minecraft.server;
import co.aikar.timings.SpigotTimings;
import com.elevatemc.spigot.threading.ThreadingManager;
import com.google.common.base.Charsets;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.Futures;
@ -10,6 +11,7 @@ import com.mojang.authlib.GameProfile;
import com.mojang.authlib.GameProfileRepository;
import com.mojang.authlib.minecraft.MinecraftSessionService;
import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
import com.elevatemc.spigot.world.AutoSaveJob;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufOutputStream;
import io.netty.buffer.Unpooled;
@ -91,6 +93,49 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs
public int autosavePeriod;
public double[] recentTps = new double[3]; // PaperSpigot - Fine have your darn compat with bad plugins
// Migot start
private LinkedList<AutoSaveJob> autoSaveWorlds = new LinkedList<AutoSaveJob>();
private int autoSaveDelay = 0;
private boolean autoSaveOrdered = false;
private void queueWorldsForAutoSave() {
if (!this.N) {
this.autoSaveWorlds.clear();
for (int j = 0; j < this.worlds.size(); ++j) {
WorldServer worldserver = this.worlds.get(j);
if(worldserver != null) {
this.autoSaveWorlds.add(new AutoSaveJob(AutoSaveJob.JobDetail.WORLD_SAVE, worldserver));
this.autoSaveWorlds.add(new AutoSaveJob(AutoSaveJob.JobDetail.WORLD_SAVEEVENT, worldserver));
}
}
int queuesize = this.autoSaveWorlds.size() / 2;
this.autoSaveDelay = 0;
this.autoSaveOrdered = true;
this.info("[AutoSave] " + queuesize + " worlds - Starting ...");
}
}
private void autoSaveNextWorld() throws ExceptionWorldConflict {
if(!this.autoSaveWorlds.isEmpty()) {
if(this.autoSaveDelay++ > 20) { // delay of 1 seconds between checks of the auto-save job queue
this.autoSaveDelay = 0;
if(this.autoSaveWorlds.getFirst().process()) {
this.autoSaveWorlds.removeFirst();
}
}
} else if(this.autoSaveOrdered){
this.info("[AutoSave] Done.");
this.autoSaveOrdered = false;
}
}
public void cancelHeavyCalculationsForAllWorlds(boolean cancel) {
for(WorldServer ws: this.worlds) {
ws.cancelHeavyCalculations(cancel);
}
}
// Migot end
private ServerConnection q; // Spigot
private String serverIp;
private int u = -1;
@ -128,9 +173,12 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs
// CraftBukkit start
private boolean hasStopped = false;
private final ThreadingManager threadingManager;
public MinecraftServer(OptionSet options, Proxy proxy, File file1) {
io.netty.util.ResourceLeakDetector.setEnabled(false); // Spigot - disable
this.e = proxy;
this.threadingManager = new ThreadingManager();
MinecraftServer.l = this;
// this.universe = file; // CraftBukkit
// this.q = new ServerConnection(this); // Spigot
@ -634,6 +682,8 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs
this.Z.c();
}
//Spigot end
this.threadingManager.shutdown();
}
}
@ -687,17 +737,17 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs
if (wait > 0L) {
if (catchupTime < 2E6) {
wait += Math.abs(catchupTime);
}
if (wait < catchupTime) {
} else /* KigPaper */ if (wait < catchupTime) {
catchupTime -= wait;
wait = 0L;
} else if (catchupTime > 2E6) {
} else /*if (catchupTime > 2E6)*/ { // KigPaper
wait -= catchupTime;
catchupTime = 0L;
}
}
if (wait > 0L) {
Thread.sleep(1L);
curTime = System.nanoTime(); // KigPaper
wait = MinecraftServer.TICK_TIME - (curTime - lastTick);
}
@ -790,19 +840,24 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs
if (file.isFile()) {
ByteBuf bytebuf = Unpooled.buffer();
ByteBuf faviconBuffer = null; // KigPaper
try {
BufferedImage bufferedimage = ImageIO.read(file);
Validate.validState(bufferedimage.getWidth() == 64, "Must be 64 pixels wide");
Validate.validState(bufferedimage.getHeight() == 64, "Must be 64 pixels high");
ImageIO.write(bufferedimage, "PNG", new ByteBufOutputStream(bytebuf));
ByteBuf bytebuf1 = Base64.encode(bytebuf);
//ByteBuf bytebuf1 = Base64.encode(bytebuf); // KigPaper
faviconBuffer = Base64.encode(bytebuf);
serverping.setFavicon("data:image/png;base64," + bytebuf1.toString(Charsets.UTF_8));
serverping.setFavicon("data:image/png;base64," + faviconBuffer.toString(Charsets.UTF_8));
} catch (Exception exception) {
MinecraftServer.LOGGER.error("Couldn't load server icon", exception);
} finally {
bytebuf.release();
// KigPaper start
if(faviconBuffer != null) faviconBuffer.release();
// KigPaper end
}
}
@ -846,24 +901,23 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs
}
if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit
SpigotTimings.worldSaveTimer.startTiming(); // Spigot
//SpigotTimings.worldSaveTimer.startTiming(); // Spigot // Migot - moved to com.elevatemc.spigot.world.AutoSaveJob
this.methodProfiler.a("save");
this.v.savePlayers();
// Spigot Start
// We replace this with saving each individual world as this.saveChunks(...) is broken,
// and causes the main thread to sleep for random amounts of time depending on chunk activity
// Also pass flag to only save modified chunks
server.playerCommandState = true;
for (World world : worlds) {
world.getWorld().save(false);
}
server.playerCommandState = false;
// this.saveChunks(true);
// Spigot End
this.queueWorldsForAutoSave(); // Migot
this.methodProfiler.b();
SpigotTimings.worldSaveTimer.stopTiming(); // Spigot
//SpigotTimings.worldSaveTimer.stopTiming(); // Spigot // Migot - moved to com.elevatemc.spigot.world.AutoSaveJob
}
// Migot start
if(this.autoSaveOrdered) {
this.autoSaveNextWorld();
}
long tickTime = System.nanoTime() - i;
ThreadingManager.checkTickTime(tickTime);
// Migot end
this.methodProfiler.a("tallying");
this.h[this.ticks % 100] = System.nanoTime() - i;
this.methodProfiler.b();
@ -1013,6 +1067,12 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs
// this.i[i][this.ticks % 100] = System.nanoTime() - j; // CraftBukkit
}
// Migot start
for(i = 0; i < this.worlds.size(); ++i) {
this.worlds.get(i).processDimensionChangeQueue();
}
// Migot end
this.methodProfiler.c("connection");
SpigotTimings.connectionTimer.startTiming(); // Spigot
this.aq().c();
@ -1083,7 +1143,7 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs
}
public String getVersion() {
return "1.8.8";
return "1.8.9";
}
public int I() {
@ -1118,7 +1178,7 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs
}
public String getServerModName() {
return "TacoSpigot"; // TacoSpigot - TacoSpigot // PaperSpigot - PaperSpigot > // Spigot - Spigot > // CraftBukkit - cb > vanilla!
return "eSpigot"; // eSpigot - eSpigot // TacoSpigot - TacoSpigot // PaperSpigot - PaperSpigot > // Spigot - Spigot > // CraftBukkit - cb > vanilla!
}
public CrashReport b(CrashReport crashreport) {

View File

@ -30,6 +30,7 @@ public abstract class MobSpawnerAbstract {
private int requiredPlayerRange = 16;
private int spawnRange = 4;
private int tickDelay = 0; // PaperSpigot
private int spawningPenalty = 0; // Migot
public MobSpawnerAbstract() {}
@ -138,6 +139,14 @@ public abstract class MobSpawnerAbstract {
if (flag) {
this.h();
}
// Migot start
else {
this.spawnDelay += this.spawningPenalty;
if(this.spawningPenalty < 40) {
this.spawningPenalty++;
}
}
// Migot end
}
}
@ -238,6 +247,8 @@ public abstract class MobSpawnerAbstract {
this.spawnDelay = this.minSpawnDelay + this.a().random.nextInt(i);
}
this.spawningPenalty = 0; // Migot
if (this.mobs.size() > 0) {
this.a((MobSpawnerAbstract.a) WeightedRandom.a(this.a().random, this.mobs));
}

View File

@ -16,6 +16,21 @@ public abstract class NBTBase {
public abstract byte getTypeId();
// Migot start
protected static java.util.concurrent.ConcurrentHashMap<String, String> storedStrings = new java.util.concurrent.ConcurrentHashMap<String, String>(16, 0.75f, 2);
public static String getStoredString(String name, boolean store) {
String str = storedStrings.get(name);
if(str == null) {
if(store) {
storedStrings.put(name, name);
}
str = name;
}
return str;
}
// Migot end
protected NBTBase() {}
protected static NBTBase createTag(byte b0) {

View File

@ -1,5 +1,6 @@
package net.minecraft.server;
import com.google.common.collect.Maps;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
@ -10,42 +11,46 @@ import java.util.Map.Entry;
import java.util.concurrent.Callable;
public class NBTTagCompound extends NBTBase {
private it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<String, NBTBase> map = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(8, 0.8f); // Paper - reduce memory footprint of NBTTagCompound
public NBTTagCompound() {
}
public NBTTagCompound() {}
public NBTTagCompound(it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<String, NBTBase> map)
{
this.map = map;
}
void write(DataOutput var1) throws IOException {
Iterator var2 = this.map.keySet().iterator();
void write(DataOutput dataoutput) throws IOException {
Iterator iterator = this.map.keySet().iterator();
while(var2.hasNext()) {
String var3 = (String)var2.next();
NBTBase var4 = (NBTBase)this.map.get(var3);
a(var3, var4, var1);
while (iterator.hasNext()) {
String s = (String) iterator.next();
NBTBase nbtbase = (NBTBase) this.map.get(s);
a(s, nbtbase, dataoutput);
}
var1.writeByte(0);
dataoutput.writeByte(0);
}
void load(DataInput var1, int var2, NBTReadLimiter var3) throws IOException {
var3.a(384L);
if (var2 > 512) {
void load(DataInput datainput, int i, NBTReadLimiter nbtreadlimiter) throws IOException {
nbtreadlimiter.a(384L);
if (i > 512) {
throw new RuntimeException("Tried to read NBT tag with too high complexity, depth > 512");
} else {
this.map.clear();
byte var4;
while((var4 = a(var1, var3)) != 0) {
String var5 = b(var1, var3);
var3.a((long)(224 + 16 * var5.length()));
NBTBase var6 = a(var4, var5, var1, var2 + 1, var3);
if (this.map.put(var5, var6) != null) {
var3.a(288L);
byte b0;
while ((b0 = a(datainput, nbtreadlimiter)) != 0) {
String s = getStoredString(b(datainput, nbtreadlimiter), true); // Migot
nbtreadlimiter.a((long) (224 + 16 * s.length()));
NBTBase nbtbase = a(b0, s, datainput, i + 1, nbtreadlimiter);
if (this.map.put(s, nbtbase) != null) {
nbtreadlimiter.a(288L);
}
}
@ -57,214 +62,228 @@ public class NBTTagCompound extends NBTBase {
}
public byte getTypeId() {
return 10;
return (byte) 10;
}
public void set(String var1, NBTBase var2) {
this.map.put(var1, var2);
public void set(String s, NBTBase nbtbase) {
this.map.put(s, nbtbase);
}
public void setByte(String var1, byte var2) {
this.map.put(var1, new NBTTagByte(var2));
public void setByte(String s, byte b0) {
this.map.put(s, new NBTTagByte(b0));
}
public void setShort(String var1, short var2) {
this.map.put(var1, new NBTTagShort(var2));
public void setShort(String s, short short0) {
this.map.put(s, new NBTTagShort(short0));
}
public void setInt(String var1, int var2) {
this.map.put(var1, new NBTTagInt(var2));
public void setInt(String s, int i) {
this.map.put(s, new NBTTagInt(i));
}
public void setLong(String var1, long var2) {
this.map.put(var1, new NBTTagLong(var2));
public void setLong(String s, long i) {
this.map.put(s, new NBTTagLong(i));
}
public void setFloat(String var1, float var2) {
this.map.put(var1, new NBTTagFloat(var2));
public void setFloat(String s, float f) {
this.map.put(s, new NBTTagFloat(f));
}
public void setDouble(String var1, double var2) {
this.map.put(var1, new NBTTagDouble(var2));
public void setDouble(String s, double d0) {
this.map.put(s, new NBTTagDouble(d0));
}
public void setString(String var1, String var2) {
this.map.put(var1, new NBTTagString(var2));
public void setString(String s, String s1) {
this.map.put(s, new NBTTagString(s1));
}
public void setByteArray(String var1, byte[] var2) {
this.map.put(var1, new NBTTagByteArray(var2));
public void setByteArray(String s, byte[] abyte) {
this.map.put(s, new NBTTagByteArray(abyte));
}
public void setIntArray(String var1, int[] var2) {
this.map.put(var1, new NBTTagIntArray(var2));
public void setIntArray(String s, int[] aint) {
this.map.put(s, new NBTTagIntArray(aint));
}
public void setBoolean(String var1, boolean var2) {
this.setByte(var1, (byte)(var2 ? 1 : 0));
public void setBoolean(String s, boolean flag) {
this.setByte(s, (byte) (flag ? 1 : 0));
}
public NBTBase get(String var1) {
return (NBTBase)this.map.get(var1);
public NBTBase get(String s) {
return (NBTBase) this.map.get(s);
}
public byte b(String var1) {
NBTBase var2 = (NBTBase)this.map.get(var1);
return var2 != null ? var2.getTypeId() : 0;
public byte b(String s) {
NBTBase nbtbase = (NBTBase) this.map.get(s);
return nbtbase != null ? nbtbase.getTypeId() : 0;
}
public boolean hasKey(String var1) {
return this.map.containsKey(var1);
public boolean hasKey(String s) {
return this.map.containsKey(s);
}
public boolean hasKeyOfType(String var1, int var2) {
byte var3 = this.b(var1);
if (var3 == var2) {
public boolean hasKeyOfType(String s, int i) {
byte b0 = this.b(s);
if (b0 == i) {
return true;
} else if (var2 != 99) {
if (var3 > 0) {
} else if (i != 99) {
if (b0 > 0) {
;
}
return false;
} else {
return var3 == 1 || var3 == 2 || var3 == 3 || var3 == 4 || var3 == 5 || var3 == 6;
return b0 == 1 || b0 == 2 || b0 == 3 || b0 == 4 || b0 == 5 || b0 == 6;
}
}
public byte getByte(String var1) {
public byte getByte(String s) {
try {
return !this.hasKeyOfType(var1, 99) ? 0 : ((NBTNumber)this.map.get(var1)).f();
} catch (ClassCastException var3) {
return !this.hasKeyOfType(s, 99) ? 0 : ((NBTBase.NBTNumber) this.map.get(s)).f();
} catch (ClassCastException classcastexception) {
return (byte) 0;
}
}
public short getShort(String s) {
try {
return !this.hasKeyOfType(s, 99) ? 0 : ((NBTBase.NBTNumber) this.map.get(s)).e();
} catch (ClassCastException classcastexception) {
return (short) 0;
}
}
public int getInt(String s) {
try {
return !this.hasKeyOfType(s, 99) ? 0 : ((NBTBase.NBTNumber) this.map.get(s)).d();
} catch (ClassCastException classcastexception) {
return 0;
}
}
public short getShort(String var1) {
public long getLong(String s) {
try {
return !this.hasKeyOfType(var1, 99) ? 0 : ((NBTNumber)this.map.get(var1)).e();
} catch (ClassCastException var3) {
return 0;
}
}
public int getInt(String var1) {
try {
return !this.hasKeyOfType(var1, 99) ? 0 : ((NBTNumber)this.map.get(var1)).d();
} catch (ClassCastException var3) {
return 0;
}
}
public long getLong(String var1) {
try {
return !this.hasKeyOfType(var1, 99) ? 0L : ((NBTNumber)this.map.get(var1)).c();
} catch (ClassCastException var3) {
return !this.hasKeyOfType(s, 99) ? 0L : ((NBTBase.NBTNumber) this.map.get(s)).c();
} catch (ClassCastException classcastexception) {
return 0L;
}
}
public float getFloat(String var1) {
public float getFloat(String s) {
try {
return !this.hasKeyOfType(var1, 99) ? 0.0F : ((NBTNumber)this.map.get(var1)).h();
} catch (ClassCastException var3) {
return !this.hasKeyOfType(s, 99) ? 0.0F : ((NBTBase.NBTNumber) this.map.get(s)).h();
} catch (ClassCastException classcastexception) {
return 0.0F;
}
}
public double getDouble(String var1) {
public double getDouble(String s) {
try {
return !this.hasKeyOfType(var1, 99) ? 0.0D : ((NBTNumber)this.map.get(var1)).g();
} catch (ClassCastException var3) {
return !this.hasKeyOfType(s, 99) ? 0.0D : ((NBTBase.NBTNumber) this.map.get(s)).g();
} catch (ClassCastException classcastexception) {
return 0.0D;
}
}
public String getString(String var1) {
public String getString(String s) {
try {
return !this.hasKeyOfType(var1, 8) ? "" : ((NBTBase)this.map.get(var1)).a_();
} catch (ClassCastException var3) {
return !this.hasKeyOfType(s, 8) ? "" : ((NBTBase) this.map.get(s)).a_();
} catch (ClassCastException classcastexception) {
return "";
}
}
public byte[] getByteArray(String var1) {
public byte[] getByteArray(String s) {
try {
return !this.hasKeyOfType(var1, 7) ? new byte[0] : ((NBTTagByteArray)this.map.get(var1)).c();
} catch (ClassCastException var3) {
throw new ReportedException(this.a(var1, 7, var3));
return !this.hasKeyOfType(s, 7) ? new byte[0] : ((NBTTagByteArray) this.map.get(s)).c();
} catch (ClassCastException classcastexception) {
throw new ReportedException(this.a(s, 7, classcastexception));
}
}
public int[] getIntArray(String var1) {
public int[] getIntArray(String s) {
try {
return !this.hasKeyOfType(var1, 11) ? new int[0] : ((NBTTagIntArray)this.map.get(var1)).c();
} catch (ClassCastException var3) {
throw new ReportedException(this.a(var1, 11, var3));
return !this.hasKeyOfType(s, 11) ? new int[0] : ((NBTTagIntArray) this.map.get(s)).c();
} catch (ClassCastException classcastexception) {
throw new ReportedException(this.a(s, 11, classcastexception));
}
}
public NBTTagCompound getCompound(String var1) {
public NBTTagCompound getCompound(String s) {
try {
return !this.hasKeyOfType(var1, 10) ? new NBTTagCompound() : (NBTTagCompound)this.map.get(var1);
} catch (ClassCastException var3) {
throw new ReportedException(this.a(var1, 10, var3));
return !this.hasKeyOfType(s, 10) ? new NBTTagCompound() : (NBTTagCompound) this.map.get(s);
} catch (ClassCastException classcastexception) {
throw new ReportedException(this.a(s, 10, classcastexception));
}
}
public NBTTagList getList(String var1, int var2) {
public NBTTagList getList(String s, int i) {
try {
if (this.b(var1) != 9) {
if (this.b(s) != 9) {
return new NBTTagList();
} else {
NBTTagList var3 = (NBTTagList)this.map.get(var1);
return var3.size() > 0 && var3.f() != var2 ? new NBTTagList() : var3;
NBTTagList nbttaglist = (NBTTagList) this.map.get(s);
return nbttaglist.size() > 0 && nbttaglist.f() != i ? new NBTTagList() : nbttaglist;
}
} catch (ClassCastException var4) {
throw new ReportedException(this.a(var1, 9, var4));
} catch (ClassCastException classcastexception) {
throw new ReportedException(this.a(s, 9, classcastexception));
}
}
public boolean getBoolean(String var1) {
return this.getByte(var1) != 0;
public boolean getBoolean(String s) {
return this.getByte(s) != 0;
}
public void remove(String var1) {
this.map.remove(var1);
public void remove(String s) {
this.map.remove(s);
}
public String toString() {
StringBuilder var1 = new StringBuilder("{");
StringBuilder stringbuilder = new StringBuilder("{");
Entry var3;
for(Iterator var2 = this.map.entrySet().iterator(); var2.hasNext(); var1.append((String)var3.getKey()).append(':').append(var3.getValue())) {
var3 = (Entry)var2.next();
if (var1.length() != 1) {
var1.append(',');
Entry entry;
for (Iterator iterator = this.map.entrySet().iterator(); iterator.hasNext(); stringbuilder.append((String) entry.getKey()).append(':').append(entry.getValue())) {
entry = (Entry) iterator.next();
if (stringbuilder.length() != 1) {
stringbuilder.append(',');
}
}
return var1.append('}').toString();
return stringbuilder.append('}').toString();
}
public boolean isEmpty() {
return this.map.isEmpty();
}
private CrashReport a(final String var1, final int var2, ClassCastException var3) {
CrashReport var4 = CrashReport.a(var3, "Reading NBT data");
CrashReportSystemDetails var5 = var4.a("Corrupt NBT tag", 1);
var5.a("Tag type found", new Callable<String>() {
public String call() throws Exception {
return NBTBase.a[((NBTBase)NBTTagCompound.this.map.get(var1)).getTypeId()];
private CrashReport a(final String s, final int i, ClassCastException classcastexception) {
CrashReport crashreport = CrashReport.a(classcastexception, "Reading NBT data");
CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Corrupt NBT tag", 1);
crashreportsystemdetails.a("Tag type found", new Callable() {
public String a() throws Exception {
return NBTBase.a[((NBTBase) NBTTagCompound.this.map.get(s)).getTypeId()];
}
public Object call() throws Exception {
return this.a();
}
});
var5.a("Tag type expected", new Callable<String>() {
public String call() throws Exception {
return NBTBase.a[var2];
crashreportsystemdetails.a("Tag type expected", new Callable() {
public String a() throws Exception {
return NBTBase.a[i];
}
public Object call() throws Exception {
return this.a();
}
});
var5.a("Tag name", var1);
return var4;
crashreportsystemdetails.a("Tag name", (Object) s);
return crashreport;
}
public NBTBase clone() {
@ -278,10 +297,12 @@ public class NBTTagCompound extends NBTBase {
return new NBTTagCompound(ret);
}
public boolean equals(Object var1) {
if (super.equals(var1)) {
NBTTagCompound var2 = (NBTTagCompound)var1;
return this.map.entrySet().equals(var2.map.entrySet());
public boolean equals(Object object) {
if (super.equals(object)) {
NBTTagCompound nbttagcompound = (NBTTagCompound) object;
return this.map.entrySet().equals(nbttagcompound.map.entrySet());
} else {
return false;
}
@ -291,54 +312,57 @@ public class NBTTagCompound extends NBTBase {
return super.hashCode() ^ this.map.hashCode();
}
private static void a(String var0, NBTBase var1, DataOutput var2) throws IOException {
var2.writeByte(var1.getTypeId());
if (var1.getTypeId() != 0) {
var2.writeUTF(var0);
var1.write(var2);
private static void a(String s, NBTBase nbtbase, DataOutput dataoutput) throws IOException {
dataoutput.writeByte(nbtbase.getTypeId());
if (nbtbase.getTypeId() != 0) {
dataoutput.writeUTF(s);
nbtbase.write(dataoutput);
}
}
private static byte a(DataInput var0, NBTReadLimiter var1) throws IOException {
return var0.readByte();
private static byte a(DataInput datainput, NBTReadLimiter nbtreadlimiter) throws IOException {
return datainput.readByte();
}
private static String b(DataInput var0, NBTReadLimiter var1) throws IOException {
return var0.readUTF();
private static String b(DataInput datainput, NBTReadLimiter nbtreadlimiter) throws IOException {
return datainput.readUTF();
}
static NBTBase a(byte var0, String var1, DataInput var2, int var3, NBTReadLimiter var4) throws IOException {
NBTBase var5 = NBTBase.createTag(var0);
static NBTBase a(byte b0, String s, DataInput datainput, int i, NBTReadLimiter nbtreadlimiter) throws IOException {
NBTBase nbtbase = NBTBase.createTag(b0);
try {
var5.load(var2, var3, var4);
return var5;
} catch (IOException var9) {
CrashReport var7 = CrashReport.a(var9, "Loading NBT data");
CrashReportSystemDetails var8 = var7.a("NBT Tag");
var8.a("Tag name", var1);
var8.a("Tag type", var0);
throw new ReportedException(var7);
nbtbase.load(datainput, i, nbtreadlimiter);
return nbtbase;
} catch (IOException ioexception) {
CrashReport crashreport = CrashReport.a(ioexception, "Loading NBT data");
CrashReportSystemDetails crashreportsystemdetails = crashreport.a("NBT Tag");
crashreportsystemdetails.a("Tag name", (Object) s);
crashreportsystemdetails.a("Tag type", (Object) Byte.valueOf(b0));
throw new ReportedException(crashreport);
}
}
public void a(NBTTagCompound var1) {
Iterator var2 = var1.map.keySet().iterator();
public void a(NBTTagCompound nbttagcompound) {
Iterator iterator = nbttagcompound.map.keySet().iterator();
while(var2.hasNext()) {
String var3 = (String)var2.next();
NBTBase var4 = (NBTBase)var1.map.get(var3);
if (var4.getTypeId() == 10) {
if (this.hasKeyOfType(var3, 10)) {
NBTTagCompound var5 = this.getCompound(var3);
var5.a((NBTTagCompound)var4);
while (iterator.hasNext()) {
String s = (String) iterator.next();
NBTBase nbtbase = (NBTBase) nbttagcompound.map.get(s);
if (nbtbase.getTypeId() == 10) {
if (this.hasKeyOfType(s, 10)) {
NBTTagCompound nbttagcompound1 = this.getCompound(s);
nbttagcompound1.a((NBTTagCompound) nbtbase);
} else {
this.set(var3, var4.clone());
this.set(s, nbtbase.clone());
}
} else {
this.set(var3, var4.clone());
this.set(s, nbtbase.clone());
}
}
}
}
}

View File

@ -0,0 +1,65 @@
package net.minecraft.server;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class NBTTagString extends NBTBase {
private String data;
public NBTTagString() {
this.data = "";
}
public NBTTagString(String s) {
this.data = s;
if (s == null) {
throw new IllegalArgumentException("Empty string not allowed");
}
}
void write(DataOutput dataoutput) throws IOException {
dataoutput.writeUTF(this.data);
}
void load(DataInput datainput, int i, NBTReadLimiter nbtreadlimiter) throws IOException {
nbtreadlimiter.a(288L);
this.data = getStoredString(datainput.readUTF(), true); // Migot
nbtreadlimiter.a((long) (16 * this.data.length()));
}
public byte getTypeId() {
return (byte) 8;
}
public String toString() {
return "\"" + this.data.replace("\"", "\\\"") + "\"";
}
public NBTBase clone() {
return new NBTTagString(this.data);
}
public boolean isEmpty() {
return this.data.isEmpty();
}
public boolean equals(Object object) {
if (!super.equals(object)) {
return false;
} else {
NBTTagString nbttagstring = (NBTTagString) object;
return this.data == null && nbttagstring.data == null || this.data != null && this.data.equals(nbttagstring.data);
}
}
public int hashCode() {
return super.hashCode() ^ this.data.hashCode();
}
public String a_() {
return this.data;
}
}

View File

@ -387,6 +387,7 @@ public class NetworkManager extends SimpleChannelInboundHandler<Packet> {
}
public void close(IChatBaseComponent ichatbasecomponent) {
this.i.clear(); // KigPaper
// Spigot Start
this.preparing = false;
// Spigot End

View File

@ -249,6 +249,28 @@ public class PacketDataSerializer extends ByteBuf {
}
}
// KigPaper start
public String readCappedString(int maxLength) {
int toRead = this.e();
if (toRead > maxLength * 4) {
throw new DecoderException("The received encoded string buffer length is longer than maximum allowed (" + toRead + " > " + maxLength * 4 + ")");
} else if (toRead < 0) {
throw new DecoderException("The received encoded string buffer length is less than zero! Weird string!");
} else {
int len = Math.min(toRead, maxLength);
String s = new String(this.readBytes(len).array(), Charsets.UTF_8);
int remaining = toRead - len;
if (remaining > 0) {
this.skipBytes(remaining);
}
return s;
}
}
// KigPaper end
public PacketDataSerializer a(String s) {
byte[] abyte = s.getBytes(Charsets.UTF_8);

View File

@ -1,5 +1,7 @@
package net.minecraft.server;
import io.netty.handler.codec.DecoderException;
import java.io.IOException;
public class PacketPlayInBlockPlace implements Packet<PacketListenerPlayIn> {
@ -33,7 +35,12 @@ public class PacketPlayInBlockPlace implements Packet<PacketListenerPlayIn> {
timestamp = System.currentTimeMillis(); // CraftBukkit
this.b = packetdataserializer.c();
this.c = packetdataserializer.readUnsignedByte();
this.d = packetdataserializer.i();
// KigPaper start - don't parse itemstack
// this.d = packetdataserializer.i();
// Consume everything and leave 3 bytes at the end
if (packetdataserializer.readableBytes() < 3) throw new DecoderException("Expected 3 facing bytes");
packetdataserializer.skipBytes(packetdataserializer.readableBytes() - 3);
// KigPaper end
this.e = (float) packetdataserializer.readUnsignedByte() / 16.0F;
this.f = (float) packetdataserializer.readUnsignedByte() / 16.0F;
this.g = (float) packetdataserializer.readUnsignedByte() / 16.0F;

View File

@ -1,5 +1,7 @@
package net.minecraft.server;
import org.github.paperspigot.PaperSpigotConfig;
import java.io.IOException;
public class PacketPlayInChat implements Packet<PacketListenerPlayIn> {
@ -17,7 +19,7 @@ public class PacketPlayInChat implements Packet<PacketListenerPlayIn> {
}
public void a(PacketDataSerializer packetdataserializer) throws IOException {
this.a = packetdataserializer.c(100);
this.a = PaperSpigotConfig.kickChatMessageLength ? packetdataserializer.c(100) : packetdataserializer.readCappedString(100); // KigPaper
}
public void b(PacketDataSerializer packetdataserializer) throws IOException {

View File

@ -5,6 +5,7 @@ import lombok.Getter;
import lombok.Setter;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
@Getter
@ -13,6 +14,7 @@ public class PacketPlayOutEntityMetadata implements Packet<PacketListenerPlayOut
public int a;
public List<DataWatcher.WatchableObject> b;
private boolean found = false; // MineHQ
public PacketPlayOutEntityMetadata() {}
@ -23,7 +25,11 @@ public class PacketPlayOutEntityMetadata implements Packet<PacketListenerPlayOut
} else {
this.b = datawatcher.b();
}
}
public PacketPlayOutEntityMetadata(int i, List<DataWatcher.WatchableObject> list) {
this.a = i;
this.b = list;
}
public void a(PacketDataSerializer packetdataserializer) throws IOException {
@ -39,5 +45,4 @@ public class PacketPlayOutEntityMetadata implements Packet<PacketListenerPlayOut
public void a(PacketListenerPlayOut packetlistenerplayout) {
packetlistenerplayout.a(this);
}
}

View File

@ -3,7 +3,7 @@ package net.minecraft.server;
public class PathfinderGoalSwell extends PathfinderGoal {
EntityCreeper a;
EntityLiving b;
//EntityLiving b; // KigPaper
public PathfinderGoalSwell(EntityCreeper entitycreeper) {
this.a = entitycreeper;
@ -18,19 +18,21 @@ public class PathfinderGoalSwell extends PathfinderGoal {
public void c() {
this.a.getNavigation().n();
this.b = this.a.getGoalTarget();
// this.b = this.a.getGoalTarget(); // KigPaper
}
public void d() {
this.b = null;
//this.b = null; // KigPaper
}
public void e() {
if (this.b == null) {
// KigPaper - use Entity GoalTarget
EntityLiving target = this.a.getGoalTarget();
if (target == null) {
this.a.a(-1);
} else if (this.a.h(this.b) > 49.0D) {
} else if (this.a.h(target) > 49.0D) {
this.a.a(-1);
} else if (!this.a.getEntitySenses().a(this.b)) {
} else if (!this.a.getEntitySenses().a(target)) {
this.a.a(-1);
} else {
this.a.a(1);

View File

@ -1,5 +1,6 @@
package net.minecraft.server;
import com.elevatemc.spigot.threading.ThreadingManager;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import java.io.DataInputStream;
@ -96,10 +97,15 @@ public class PersistentCollection {
NBTTagCompound nbttagcompound1 = new NBTTagCompound();
nbttagcompound1.set("data", nbttagcompound);
// Migot start
/*
FileOutputStream fileoutputstream = new FileOutputStream(file);
NBTCompressedStreamTools.a(nbttagcompound1, (OutputStream) fileoutputstream);
fileoutputstream.close();
*/
ThreadingManager.saveNBTFileStatic((NBTTagCompound) (nbttagcompound1.clone()), file);
// Migot end
}
} catch (Exception exception) {
exception.printStackTrace();

View File

@ -92,6 +92,7 @@ public class PlayerConnection implements PacketListenerPlayIn, IUpdatePlayerList
private double q;
private boolean checkMovement = true;
private boolean processedDisconnect; // CraftBukkit - added
private boolean disconnecting; // KigPaper - added
public PlayerConnection(MinecraftServer minecraftserver, NetworkManager networkmanager, EntityPlayer entityplayer) {
this.minecraftServer = minecraftserver;
@ -107,6 +108,7 @@ public class PlayerConnection implements PacketListenerPlayIn, IUpdatePlayerList
private final org.bukkit.craftbukkit.CraftServer server;
private int lastTick = MinecraftServer.currentTick;
private int lastDropTick = MinecraftServer.currentTick;
private int lastBookTick = MinecraftServer.currentTick;
private int dropCount = 0;
private static final int SURVIVAL_PLACE_DISTANCE_SQUARED = 6 * 6;
private static final int CREATIVE_PLACE_DISTANCE_SQUARED = 7 * 7;
@ -163,6 +165,8 @@ public class PlayerConnection implements PacketListenerPlayIn, IUpdatePlayerList
}
public void disconnect(String s) {
// KigPaper - if already disconnecting, do nothing
if(disconnecting) return;
// CraftBukkit start - fire PlayerKickEvent
String leaveMessage = EnumChatFormat.YELLOW + this.player.getName() + " left the game.";
@ -176,6 +180,9 @@ public class PlayerConnection implements PacketListenerPlayIn, IUpdatePlayerList
// Do not kick the player
return;
}
// KigPaper - mark the player as disconnecting, so all other disconnect requests are ignored.
disconnecting = true;
// Send the possibly modified leave message
s = event.getReason();
// CraftBukkit end
@ -805,6 +812,7 @@ public class PlayerConnection implements PacketListenerPlayIn, IUpdatePlayerList
if (itemstack != null && itemstack.count == 0) {
this.player.inventory.items[this.player.inventory.itemInHandIndex] = null;
itemstack = null;
always = true; // KigPaper - send update packet
}
if (itemstack == null || itemstack.l() == 0) {
@ -815,7 +823,7 @@ public class PlayerConnection implements PacketListenerPlayIn, IUpdatePlayerList
this.player.activeContainer.b();
this.player.g = false;
// CraftBukkit - TODO CHECK IF NEEDED -- new if structure might not need 'always'. Kept it in for now, but may be able to remove in future
if (!ItemStack.matches(this.player.inventory.getItemInHand(), packetplayinblockplace.getItemStack()) || always) {
if (!ItemStack.matches(this.player.inventory.getItemInHand(), itemstack) || always) { // KigPaper - use saved itemstack instead of stack from packet
this.sendPacket(new PacketPlayOutSetSlot(this.player.activeContainer.windowId, slot.rawSlotIndex, this.player.inventory.getItemInHand()));
}
}
@ -1357,6 +1365,47 @@ public class PlayerConnection implements PacketListenerPlayIn, IUpdatePlayerList
this.player.resetIdleTimer();
if (entity != null) {
// KigPaper start - allow hitting the vehicle when hitboxes collide / allow the player to hit others if they are being ridden by something
if(PaperSpigotConfig.betterVehicleHitboxes) {
if (entity instanceof EntityPlayer && entity.vehicle != null && !((EntityPlayer) entity).collidesWithEntities) {
// Allow hitting the vehicle when hitboxes collide
// Ray trace to see if the player should hit the vehicle instead
double maxDist = 3.0;
Vec3D look = player.ap();
Vec3D eyePos = new Vec3D(player.locX, player.locY + player.getBukkitEntity().getEyeHeight(), player.locZ);
Vec3D maxDistLook = eyePos.add(look.a * maxDist, look.b * maxDist, look.c * maxDist);
Entity vehicle = entity.vehicle;
List<Entity> collisions = worldserver.a(player, player.getBoundingBox()
.a(look.a * maxDist, look.b * maxDist, look.c * maxDist) // add coords
.grow(1D, 1D, 1D), e -> e == vehicle); // Only check for the vehicle
for (Entity match : collisions) {
AxisAlignedBB expandedHitbox = match.getBoundingBox().grow(0.1D, 0.1D, 0.1D); // Hit box is collision box + 0.1
if (expandedHitbox.a(eyePos) || expandedHitbox.a(eyePos, maxDistLook) != null) {
entity = match;
break;
}
}
} else if (entity == player.passenger) { // player hit passenger
// Allow the player to hit others if they are being ridden by something
// Ray trace to see if the player should hit someone else instead
double maxDist = 3.0;
Vec3D look = player.ap();
Vec3D eyePos = new Vec3D(player.locX, player.locY + player.getBukkitEntity().getEyeHeight(), player.locZ);
Vec3D maxDistLook = eyePos.add(look.a * maxDist, look.b * maxDist, look.c * maxDist);
Entity passenger = entity.passenger;
List<Entity> collisions = worldserver.a(player, player.getBoundingBox()
.a(look.a * maxDist, look.b * maxDist, look.c * maxDist) // add coords
.grow(1D, 1D, 1D), e -> e != passenger); // Don't include passenger
for (Entity match : collisions) {
AxisAlignedBB expandedHitbox = match.getBoundingBox().grow(0.1D, 0.1D, 0.1D); // Hit box is collision box + 0.1
if (expandedHitbox.a(eyePos) || expandedHitbox.a(eyePos, maxDistLook) != null) {
entity = match;
break;
}
}
}
}
// KigPaper end
boolean flag = this.player.hasLineOfSight(entity);
double d0 = 36.0D;
@ -1892,7 +1941,6 @@ public class PlayerConnection implements PacketListenerPlayIn, IUpdatePlayerList
}
}
}
}
public void a(PacketPlayInTransaction packetplayintransaction) {
@ -2016,7 +2064,13 @@ public class PlayerConnection implements PacketListenerPlayIn, IUpdatePlayerList
try { // CraftBukkit
if ("MC|BEdit".equals(packetplayincustompayload.a())) {
if (!PaperSpigotConfig.enableBookDeserialization) return; // KigPaper
packetdataserializer = new PacketDataSerializer(Unpooled.wrappedBuffer(packetplayincustompayload.b()));
if (this.lastBookTick + 20 > MinecraftServer.currentTick) {
this.disconnect("Book edited too quickly! (Attempted server crash?)");
return;
}
this.lastBookTick = MinecraftServer.currentTick;
try {
itemstack = packetdataserializer.i();
@ -2048,6 +2102,12 @@ public class PlayerConnection implements PacketListenerPlayIn, IUpdatePlayerList
return;
} else if ("MC|BSign".equals(packetplayincustompayload.a())) {
if (!PaperSpigotConfig.enableBookDeserialization) return; // KigPaper
if (this.lastBookTick + 20 > MinecraftServer.currentTick) {
this.disconnect("Book edited too quickly! (Attempted server crash?)");
return;
}
this.lastBookTick = MinecraftServer.currentTick;
packetdataserializer = new PacketDataSerializer(Unpooled.wrappedBuffer(packetplayincustompayload.b()));
try {

View File

@ -28,6 +28,7 @@ import org.bukkit.craftbukkit.chunkio.ChunkIOExecutor;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.TravelAgent;
import org.bukkit.craftbukkit.inventory.CraftInventoryView;
import org.bukkit.craftbukkit.util.CraftChatMessage;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerChangedWorldEvent;
@ -38,6 +39,7 @@ import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.util.Vector;
import org.github.paperspigot.PaperSpigotConfig;
import org.spigotmc.event.player.PlayerSpawnLocationEvent;
// CraftBukkit end
@ -88,11 +90,12 @@ public abstract class PlayerList {
public void a(NetworkManager networkmanager, EntityPlayer entityplayer) {
GameProfile gameprofile = entityplayer.getProfile();
boolean loadUserCache = PaperSpigotConfig.savePlayerFiles;
UserCache usercache = this.server.getUserCache();
GameProfile gameprofile1 = usercache.a(gameprofile.getId());
GameProfile gameprofile1 = loadUserCache ? usercache.a(gameprofile.getId()) : null; // KigPaper - only load if savePlayerFiles is enabled
String s = gameprofile1 == null ? gameprofile.getName() : gameprofile1.getName();
usercache.a(gameprofile);
if (loadUserCache) usercache.a(gameprofile); // KigPaper - only save if savePlayerFiles is enabled
NBTTagCompound nbttagcompound = this.a(entityplayer);
// CraftBukkit start - Better rename detection
if (nbttagcompound != null && nbttagcompound.hasKey("bukkit")) {
@ -272,7 +275,7 @@ public abstract class PlayerList {
}
worldserver1.getPlayerChunkMap().addPlayer(entityplayer);
worldserver1.chunkProviderServer.getChunkAt((int) entityplayer.locX >> 4, (int) entityplayer.locZ >> 4);
worldserver1.chunkProviderServer.getChunkAt(MathHelper.floor(entityplayer.locX) >> 4, MathHelper.floor(entityplayer.locZ) >> 4); // Migot - fix rounding error
}
public int d() {
@ -295,6 +298,7 @@ public abstract class PlayerList {
}
protected void savePlayerFile(EntityPlayer entityplayer) {
if (!PaperSpigotConfig.savePlayerFiles) return; // KigPaper
this.playerFileData.save(entityplayer);
ServerStatisticManager serverstatisticmanager = (ServerStatisticManager) this.o.get(entityplayer.getUniqueID());
@ -362,7 +366,8 @@ public abstract class PlayerList {
// CraftBukkit start - Quitting must be before we do final save of data, in case plugins need to modify it
org.bukkit.craftbukkit.event.CraftEventFactory.handleInventoryCloseEvent(entityplayer);
PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), "\u00A7e" + entityplayer.getName() + " left the game.");
Player bukkit = cserver.getPlayer(entityplayer); // KigPaper
PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(bukkit, "\u00A7e" + entityplayer.getName() + " left the game.");
cserver.getPluginManager().callEvent(playerQuitEvent);
entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage());
// CraftBukkit end
@ -405,6 +410,12 @@ public abstract class PlayerList {
ChunkIOExecutor.adjustPoolSize(this.getPlayerCount()); // CraftBukkit
// KigPaper start - fix memory leak
CraftingManager craftingManager = CraftingManager.getInstance();
CraftInventoryView lastView = (CraftInventoryView) craftingManager.lastCraftView;
if (lastView != null && lastView.getHandle() instanceof ContainerPlayer && lastView.getPlayer() == bukkit) craftingManager.lastCraftView = null;
// KigPaper end
return playerQuitEvent.getQuitMessage(); // CraftBukkit
}
@ -599,7 +610,7 @@ public abstract class PlayerList {
entityplayer1.setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
// CraftBukkit end
worldserver.chunkProviderServer.getChunkAt((int) entityplayer1.locX >> 4, (int) entityplayer1.locZ >> 4);
worldserver.chunkProviderServer.getChunkAt(MathHelper.floor(entityplayer1.locX) >> 4, MathHelper.floor(entityplayer1.locZ) >> 4); // Migot - fix rounding error
// eSpigot - Don't check for entities
while (avoidSuffocation && !worldserver.getCubesNoEntities(entityplayer1, entityplayer1.getBoundingBox()).isEmpty() && entityplayer1.locY < 256.0D) {
@ -1060,7 +1071,7 @@ public abstract class PlayerList {
EntityPlayer entityplayer = (EntityPlayer) this.players.get(j);
// CraftBukkit start - Test if player receiving packet can see the source of the packet
if (entityhuman != null && entityhuman instanceof EntityPlayer && !entityplayer.getBukkitEntity().canSee(((EntityPlayer) entityhuman).getBukkitEntity())) {
if (entityhuman != null && entityplayer != entityhuman && entityhuman instanceof EntityPlayer && !entityplayer.getBukkitEntity().canSee(((EntityPlayer) entityhuman).getBukkitEntity())) {
continue;
}
// CraftBukkit end
@ -1078,6 +1089,31 @@ public abstract class PlayerList {
}
// KigPaper start
public void sendPacketNearbyIncludingSelf(EntityHuman entityhuman, double d0, double d1, double d2, double d3, int i, Packet packet) {
for (int j = 0; j < this.players.size(); ++j) {
EntityPlayer entityplayer = (EntityPlayer) this.players.get(j);
// CraftBukkit start - Test if player receiving packet can see the source of the packet
if (entityhuman != null && entityplayer != entityhuman && entityhuman instanceof EntityPlayer && !entityplayer.getBukkitEntity().canSee(((EntityPlayer) entityhuman).getBukkitEntity())) {
continue;
}
// CraftBukkit end
if (entityplayer.dimension == i) {
double d4 = d0 - entityplayer.locX;
double d5 = d1 - entityplayer.locY;
double d6 = d2 - entityplayer.locZ;
if (d4 * d4 + d5 * d5 + d6 * d6 < d3 * d3) {
entityplayer.playerConnection.sendPacket(packet);
}
}
}
}
// KigPaper end
public void savePlayers() {
for (int i = 0; i < this.players.size(); ++i) {
this.savePlayerFile((EntityPlayer) this.players.get(i));

View File

@ -94,7 +94,13 @@ public class PortalTravelAgent {
public boolean b(Entity entity, float f) {
// CraftBukkit start - Modularize portal search process and entity teleportation
BlockPosition found = this.findPortal(entity.locX, entity.locY, entity.locZ, 128);
// Migot start
BlockPosition found = this.findPortal(entity.locX, entity.locY, entity.locZ, 10);
if (found == null) {
found = this.findPortal(entity.locX, entity.locY, entity.locZ, 128);
}
// Migot end
if (found == null) {
return false;
}
@ -132,28 +138,33 @@ public class PortalTravelAgent {
flag1 = false;
} else {
BlockPosition blockposition = new BlockPosition(x, y, z);
// Migot start
BlockPosition.MutableBlockPosition mutableblockposition = new BlockPosition.MutableBlockPosition();
for (int l = -searchRadius; l <= searchRadius; ++l) { // Paper - actually use search radius
BlockPosition blockposition1;
for (int i1 = -searchRadius; i1 <= searchRadius; ++i1) { // Paper - actually use search radius
for (BlockPosition blockposition2 = blockposition.a(l, this.a.V() - 1 - blockposition.getY(), i1); blockposition2.getY() >= 0; blockposition2 = blockposition1) {
blockposition1 = blockposition2.down();
if (this.a.getType(blockposition2).getBlock() == Blocks.PORTAL) {
while (this.a.getType(blockposition1 = blockposition2.down()).getBlock() == Blocks.PORTAL) {
blockposition2 = blockposition1;
int zOffset = 0, yOffset = 0;
for (int xDiff = -searchRadius; xDiff <= searchRadius; ++xDiff) {
zOffset = (zOffset + 1) % 2;
for (int zDiff = -searchRadius + zOffset; zDiff <= searchRadius; zDiff = zDiff + 2) { // skipping every 2nd block in z direction and alternating from row to row in x direction
yOffset = (yOffset + 1) % 3;
for (int yPos = this.a.V() - (1 + yOffset) ; yPos >= 0; yPos = yPos - 3) { // checking only every 3rd block in y direction and alternating in height in each column
mutableblockposition.c(blockposition.getX() + xDiff, yPos, blockposition.getZ() + zDiff);
if (this.a.getType(mutableblockposition).getBlock() == Blocks.PORTAL) {
int lowestCorrectHeight = mutableblockposition.getY();
while (this.a.getType(mutableblockposition.c(mutableblockposition.getX(), mutableblockposition.getY() - 1, mutableblockposition.getZ())).getBlock() == Blocks.PORTAL) {
lowestCorrectHeight = mutableblockposition.getY();
}
double d1 = blockposition2.i(blockposition);
double d1 = mutableblockposition.c(mutableblockposition.getX(), lowestCorrectHeight, mutableblockposition.getZ()).i(blockposition);
if (d0 < 0.0D || d1 < d0) {
d0 = d1;
object = blockposition2;
object = new BlockPosition(mutableblockposition);
}
}
}
}
}
// Migot end
}
if (d0 >= 0.0D) {

View File

@ -1,20 +1,24 @@
package net.minecraft.server;
import com.github.luben.zstd.ZstdInputStreamNoFinalizer;
import com.github.luben.zstd.ZstdOutputStreamNoFinalizer;
import com.google.common.collect.Lists;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import net.jpountz.lz4.LZ4BlockInputStream;
import net.jpountz.lz4.LZ4BlockOutputStream;
import net.jpountz.lz4.LZ4Factory;
import org.github.paperspigot.PaperSpigotConfig;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.List;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import java.util.zip.InflaterInputStream;
public class RegionFile {
private static final LZ4Factory lz4Factory = LZ4Factory.fastestJavaInstance(); // KigPaper
private static final byte[] a = new byte[4096]; // Spigot - note: if this ever changes to not be 4096 bytes, update constructor! // PAIL: empty 4k block
private final File b;
@ -25,6 +29,18 @@ public class RegionFile {
private int g;
private long h;
// Migot start
private boolean[] existingChunkCache = new boolean[1024];
private boolean checkExistingChunkCache(int i, int j) {
return this.existingChunkCache[i + j * 32];
}
private void addCoordinatesToCache(int i, int j) {
this.existingChunkCache[i + j * 32] = true;
}
// Migot end
public RegionFile(File file) {
this.b = file;
this.g = 0;
@ -66,8 +82,18 @@ public class RegionFile {
int k;
// KigPaper start - Paper-0098
ByteBuffer header = ByteBuffer.allocate(8192);
while (header.hasRemaining()) {
if (this.c.getChannel().read(header) == -1) throw new EOFException();
}
header.clear();
IntBuffer headerAsInts = header.asIntBuffer();
// KigPaper end
for (j = 0; j < 1024; ++j) {
k = this.c.readInt();
//k = this.c.readInt(); // KigPaper
k = headerAsInts.get();
this.d[j] = k;
if (k != 0 && (k >> 8) + (k & 255) <= this.f.size()) {
for (int l = 0; l < (k & 255); ++l) {
@ -77,7 +103,8 @@ public class RegionFile {
}
for (j = 0; j < 1024; ++j) {
k = this.c.readInt();
//k = this.c.readInt(); // KigPaper
k = headerAsInts.get();
this.e[j] = k;
}
} catch (IOException ioexception) {
@ -91,6 +118,11 @@ public class RegionFile {
if (this.d(i, j)) {
return false;
} else {
// Migot start
if(checkExistingChunkCache(i, j)) {
return true;
}
// Migot end
try {
int k = this.e(i, j);
@ -113,6 +145,7 @@ public class RegionFile {
byte b0 = this.c.readByte();
if (b0 == 1 || b0 == 2) {
this.addCoordinatesToCache(i, j); // Migot
return true;
}
}
@ -152,15 +185,34 @@ public class RegionFile {
byte b0 = this.c.readByte();
byte[] abyte;
if (b0 == 1) {
// KigPaper - add additional compression algorithms, and remove usage of BufferedInputStreams (as they're buffering a byte array)
if (b0 == CompressionAlgorithm.NONE.ordinal()) {
// KigPaper start - add no decompression
abyte = new byte[j1 - 1];
this.c.read(abyte);
return new DataInputStream(new BufferedInputStream(new GZIPInputStream(new ByteArrayInputStream(abyte))));
} else if (b0 == 2) {
return new DataInputStream(new ByteArrayInputStream(abyte));
// KigPaper end
} else if (b0 == CompressionAlgorithm.GZIP.ordinal()) {
abyte = new byte[j1 - 1];
this.c.read(abyte);
return new DataInputStream(new BufferedInputStream(new InflaterInputStream(new ByteArrayInputStream(abyte))));
} else {
return new DataInputStream(new GZIPInputStream(new ByteArrayInputStream(abyte)));
} else if (b0 == CompressionAlgorithm.ZLIB.ordinal()) {
abyte = new byte[j1 - 1];
this.c.read(abyte);
return new DataInputStream(new InflaterInputStream(new ByteArrayInputStream(abyte)));
} else if (b0 == CompressionAlgorithm.LZ4.ordinal()) {
// KigPaper start - add LZ4 decompression
abyte = new byte[j1 - 1];
this.c.read(abyte);
return new DataInputStream(new LZ4BlockInputStream(new ByteArrayInputStream(abyte), lz4Factory.fastDecompressor()));
// KigPaper end
} else if (b0 == CompressionAlgorithm.ZSTD.ordinal()) {
// KigPaper start - add Zstandard decompression
abyte = new byte[j1 - 1];
this.c.read(abyte);
return new DataInputStream(new ZstdInputStreamNoFinalizer(new ByteArrayInputStream(abyte)));
}else {
return null;
}
}
@ -172,9 +224,35 @@ public class RegionFile {
}
}
public DataOutputStream b(int i, int j) { // PAIL: getChunkOutputStream
public DataOutputStream b(int i, int j) throws IOException { // PAIL: getChunkOutputStream // KigPaper - add throws
// PAIL: isInvalidRegion
return this.d(i, j) ? null : new DataOutputStream(new java.io.BufferedOutputStream(new DeflaterOutputStream(new RegionFile.ChunkBuffer(i, j)))); // Spigot - use a BufferedOutputStream to greatly improve file write performance
if (this.d(i, j)) {
return null;
}
// KigPaper start - add alternative compression algorithms
ChunkBuffer buffer = new RegionFile.ChunkBuffer(i, j);
OutputStream stream;
switch (PaperSpigotConfig.regionCompressionAlgorithm) {
case NONE:
stream = buffer;
break;
case GZIP:
stream = new GZIPOutputStream(buffer); // Normally not supported by the Notchian server
break;
case ZLIB:
stream = new DeflaterOutputStream(buffer);
break;
case LZ4:
stream = new LZ4BlockOutputStream(buffer, 65536, lz4Factory.fastCompressor());
break;
case ZSTD:
stream = new ZstdOutputStreamNoFinalizer(buffer);
break;
default:
throw new UnsupportedEncodingException("invalid compression algorithm");
}
return new DataOutputStream(new BufferedOutputStream(stream));
// KigPaper end
}
protected synchronized void a(int i, int j, byte[] abyte, int k) {
@ -252,9 +330,9 @@ public class RegionFile {
}
private void a(int i, byte[] abyte, int j) throws IOException {
this.c.seek((long) (i * 4096));
this.c.seek(i * 4096L);
this.c.writeInt(j + 1);
this.c.writeByte(2);
this.c.writeByte(PaperSpigotConfig.regionCompressionAlgorithm.ordinal());
this.c.write(abyte, 0, j);
}
@ -304,4 +382,14 @@ public class RegionFile {
RegionFile.this.a(this.b, this.c, this.buf, this.count);
}
}
// KigPaper start
public enum CompressionAlgorithm {
NONE,
GZIP,
ZLIB,
LZ4, // KigPaper
ZSTD // KigPaper
}
// KigPaper end
}

View File

@ -65,7 +65,7 @@ public class RegionFileCache {
return regionfile.a(i & 31, j & 31);
}
public static DataOutputStream d(File file, int i, int j) {
public static DataOutputStream d(File file, int i, int j) throws IOException { // KigPaper - add throws
RegionFile regionfile = a(file, i, j);
return regionfile.b(i & 31, j & 31);

View File

@ -27,6 +27,7 @@ import java.util.List;
import java.util.concurrent.Callable;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.github.paperspigot.PaperSpigotConfig;
public class ServerConnection {
@ -68,6 +69,16 @@ public class ServerConnection {
this.d = true;
}
// KigPaper start - Paper-0117 by Aikar
private final List<NetworkManager> pending = Collections.synchronizedList(Lists.newArrayList());
private void addPending() {
synchronized (pending) {
this.h.addAll(pending);
pending.clear();
}
}
// KigPaper end
public void a(InetAddress inetaddress, int i) throws IOException {
List list = this.g;
@ -98,10 +109,14 @@ public class ServerConnection {
;
}
channel.pipeline().addLast("timeout", new ReadTimeoutHandler(30)).addLast("legacy_query", new LegacyPingHandler(ServerConnection.this)).addLast("splitter", new PacketSplitter()).addLast("decoder", new PacketDecoder(EnumProtocolDirection.SERVERBOUND)).addLast("prepender", new PacketPrepender()).addLast("encoder", new PacketEncoder(EnumProtocolDirection.CLIENTBOUND));
// KigPaper start
if(PaperSpigotConfig.nettyReadTimeout) channel.pipeline().addLast("timeout", new ReadTimeoutHandler(30));
// KigPaper end
channel.pipeline().addLast("legacy_query", new LegacyPingHandler(ServerConnection.this)).addLast("splitter", new PacketSplitter()).addLast("decoder", new PacketDecoder(EnumProtocolDirection.SERVERBOUND)).addLast("prepender", new PacketPrepender()).addLast("encoder", new PacketEncoder(EnumProtocolDirection.CLIENTBOUND));
NetworkManager networkmanager = new NetworkManager(EnumProtocolDirection.SERVERBOUND);
ServerConnection.this.h.add(networkmanager);
//ServerConnection.this.h.add(networkmanager);
pending.add(networkmanager); // KigPaper
channel.pipeline().addLast("packet_handler", networkmanager);
networkmanager.a((PacketListener) (new HandshakeListener(ServerConnection.this.f, networkmanager)));
}
@ -138,6 +153,7 @@ public class ServerConnection {
synchronized (this.h) {
// Spigot Start
addPending(); // KigPaper
// This prevents players from 'gaming' the server, and strategically relogging to increase their position in the tick order
if ( org.spigotmc.SpigotConfig.playerShuffle > 0 && MinecraftServer.currentTick % org.spigotmc.SpigotConfig.playerShuffle == 0 )
{

View File

@ -81,7 +81,7 @@ public final class SpawnerCreature {
long chunkCoords = LongHash.toLong(i1 + l, k + j);
if (!this.b.contains(chunkCoords)) {
++i;
if (!flag3 && worldserver.getWorldBorder().isInBounds(i1 + l, k + j)) {
if (!flag3 && worldserver.isChunkLoaded(i1 + l, k + j, true) && worldserver.getWorldBorder().isInBounds(i1 + l, k + j)) { // Migot
this.b.add(chunkCoords);
}
}

View File

@ -198,7 +198,7 @@ public abstract class StructureGenerator extends WorldGenBase {
private void a(World world) {
if (this.d == null) {
// Spigot Start
if ( world.spigotConfig.saveStructureInfo && !this.a().equals( "Mineshaft" ) )
if ( world.spigotConfig.saveStructureInfo && ( !this.a().equals( "Mineshaft" ) || world.spigotConfig.saveMineshaftStructureInfo ) ) // Migot
{
this.d = (PersistentStructure) world.a(PersistentStructure.class, this.a());
} else

View File

@ -4,6 +4,7 @@ package net.minecraft.server;
import java.util.List;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.craftbukkit.util.LongHash;
import org.bukkit.entity.HumanEntity;
import org.bukkit.event.inventory.FurnaceBurnEvent;
import org.bukkit.event.inventory.FurnaceSmeltEvent;
@ -206,7 +207,7 @@ public class TileEntityFurnace extends TileEntityContainer implements IUpdatePla
if (!this.isBurning() && this.cookTime > 0) {
this.cookTime = MathHelper.clamp(this.cookTime - 2, 0, this.cookTimeTotal);
}
} else {
} else if (this.items[1] != null && this.items[1].getItem() != Items.BUCKET) { // Migot
// CraftBukkit start - Handle multiple elapsed ticks
if (this.burnTime <= 0 && this.canBurn()) { // CraftBukkit - == to <=
CraftItemStack fuel = CraftItemStack.asCraftMirror(this.items[1]);
@ -271,6 +272,7 @@ public class TileEntityFurnace extends TileEntityContainer implements IUpdatePla
return false;
} else {
ItemStack itemstack = RecipesFurnace.getInstance().getResult(this.items[0]);
if(!this.world.isLoaded(this.position) || ((WorldServer) this.world).chunkProviderServer.unloadQueue.contains(LongHash.toLong(this.position.getX() >> 4, this.position.getZ() >> 4))) { return false; } // Migot
// CraftBukkit - consider resultant count instead of current count
return itemstack == null ? false : (this.items[2] == null ? true : (!this.items[2].doMaterialsMatch(itemstack) ? false : (this.items[2].count + itemstack.count <= this.getMaxStackSize() && this.items[2].count < this.items[2].getMaxStackSize() ? true : this.items[2].count + itemstack.count <= itemstack.getMaxStackSize())));

View File

@ -41,7 +41,33 @@ public class Village {
this.a = world;
}
// Migot start
private BlockPosition[] positions = null;
private void calculateNewCheckPositions() {
if(this.d == null || this.d.equals(BlockPosition.ZERO)) {
this.positions = null;
} else {
this.positions = new BlockPosition[] { this.d.a(-this.e, 0, -this.e),
this.d.a(-this.e, 0, this.e),
this.d.a(this.e, 0, -this.e),
this.d.a(this.e, 0, this.e),
this.d};
}
}
public boolean isVillageAreaLoaded() {
for(int i = 0; this.positions != null && i < this.positions.length; i++) {
if(this.a.isLoaded(this.positions[i])) {
return true;
}
}
return false;
}
// Migot end
public void a(int i) {
if(!this.isVillageAreaLoaded()) { return; } // Migot
this.g = i;
this.m();
this.l();
@ -402,6 +428,7 @@ public class Village {
}
}
this.calculateNewCheckPositions(); // Migot
}
public void b(NBTTagCompound nbttagcompound) {

View File

@ -170,6 +170,28 @@ public abstract class World implements IBlockAccess {
public final co.aikar.timings.WorldTimingsHandler timings; // Spigot
public final net.techcable.tacospigot.TacoSpigotWorldConfig tacoSpigotConfig;
// Migot start
private Chunk dummyChunk = new EmptyChunk(this, Integer.MIN_VALUE, Integer.MIN_VALUE);
private Chunk lastChunkAccessed = dummyChunk;
final Object chunkLock = new Object();
public ChunkProviderServer chunkProviderServer; // moved here from WorldServer
protected boolean cancelHeavyCalculations = false;
private List<Entity> dimensionChangeQueue = java.util.Collections.synchronizedList(new ArrayList<Entity>());
public void queueEntityForDimensionChange(Entity entity) {
this.dimensionChangeQueue.add(entity);
}
public void processDimensionChangeQueue() {
Iterator<Entity> iter = this.dimensionChangeQueue.iterator();
while(iter.hasNext()) {
Entity entity = iter.next();
entity.changeDimension(entity.getTargetDimension());
iter.remove();
}
}
// Migot end
public CraftWorld getWorld() {
return this.world;
}
@ -362,8 +384,30 @@ public abstract class World implements IBlockAccess {
return this.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4);
}
// Migot start
private void cacheLastChunkAccess(Chunk foundChunk) {
this.lastChunkAccessed = ((foundChunk == null || foundChunk.isEmpty() || foundChunk.wasUnloaded()) ? this.dummyChunk : foundChunk);
}
// Migot end
public Chunk getChunkAt(int i, int j) {
return this.chunkProvider.getOrCreateChunk(i, j);
// Migot start
Chunk last = this.lastChunkAccessed;
if(last.a(i,j) && !last.wasUnloaded()) {
return last;
} else {
Chunk result = null;
if(this.chunkProviderServer.isChunkLoaded(i, j)) {
result = this.chunkProviderServer.getChunkAt(i, j);
} else {
synchronized (this.chunkLock) {
result = this.chunkProvider.getOrCreateChunk(i, j);
}
}
this.cacheLastChunkAccess(result);
return result;
}
// Migot end
}
public boolean setTypeAndData(BlockPosition blockposition, IBlockData iblockdata, int i) {
@ -1013,7 +1057,23 @@ public abstract class World implements IBlockAccess {
}
}
// KigPaper start
public void playSoundIncludingSelf(EntityHuman entityhuman, String s, float f, float f1) {
for (IWorldAccess worldAccess : this.u) {
if (worldAccess instanceof WorldManager) {
((WorldManager) worldAccess).broadcastPacketIncludingSelf(entityhuman, s, entityhuman.locX, entityhuman.locY, entityhuman.locZ, f, f1);
}
}
}
// KigPaper end
public void makeSound(Entity entity, String s, float f, float f1) {
// KigPaper start - respect visibility for players
if (entity instanceof EntityHuman) {
this.playSoundIncludingSelf((EntityHuman) entity, s, f, f1);
return;
}
// KigPaper end
for (int i = 0; i < this.u.size(); ++i) {
((IWorldAccess) this.u.get(i)).a(s, entity.locX, entity.locY, entity.locZ, f, f1);
}

View File

@ -33,6 +33,13 @@ public class WorldManager implements IWorldAccess {
this.a.getPlayerList().sendPacketNearby(entityhuman, d0, d1, d2, f > 1.0F ? (double) (16.0F * f) : 16.0D, this.world.dimension, new PacketPlayOutNamedSoundEffect(s, d0, d1, d2, f, f1));
}
// KigPaper start
public void broadcastPacketIncludingSelf(EntityHuman entityhuman, String s, double d0, double d1, double d2, float f, float f1) {
// CraftBukkit - this.world.dimension
this.a.getPlayerList().sendPacketNearbyIncludingSelf(entityhuman, d0, d1, d2, f > 1.0F ? (double) (16.0F * f) : 16.0D, this.world.dimension, new PacketPlayOutNamedSoundEffect(s, d0, d1, d2, f, f1));
}
// KigPaper end
public void a(int i, int j, int k, int l, int i1, int j1) {}
public void a(BlockPosition blockposition) {

View File

@ -15,6 +15,7 @@ import org.apache.logging.log4j.Logger;
import java.util.UUID;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.github.paperspigot.PaperSpigotConfig;
// CraftBukkit end
public class WorldNBTStorage implements IDataManager, IPlayerFileData {
@ -196,13 +197,15 @@ public class WorldNBTStorage implements IDataManager, IPlayerFileData {
}
public NBTTagCompound load(EntityHuman entityhuman) {
if (!PaperSpigotConfig.savePlayerFiles) return null; // KigPaper
NBTTagCompound nbttagcompound = null;
try {
File file = new File(this.playerDir, entityhuman.getUniqueID().toString() + ".dat");
// Spigot Start
boolean usingWrongFile = false;
if ( org.bukkit.Bukkit.getOnlineMode() && !file.exists() ) // PaperSpigot - Check online mode first
boolean normalFile = file.exists() && file.isFile(); // KigPaper
if ( org.bukkit.Bukkit.getOnlineMode() && !normalFile ) // PaperSpigot - Check online mode first
{
file = new File( this.playerDir, UUID.nameUUIDFromBytes( ( "OfflinePlayer:" + entityhuman.getName() ).getBytes( "UTF-8" ) ).toString() + ".dat");
if ( file.exists() )
@ -213,7 +216,7 @@ public class WorldNBTStorage implements IDataManager, IPlayerFileData {
}
// Spigot End
if (file.exists() && file.isFile()) {
if (normalFile) { // KigPaper
nbttagcompound = NBTCompressedStreamTools.a((InputStream) (new FileInputStream(file)));
}
// Spigot Start

View File

@ -36,7 +36,7 @@ public class WorldServer extends World implements IAsyncTaskHandler {
private final PlayerChunkMap manager;
private final HashTreeSet<NextTickListEntry> M = new HashTreeSet<>(); // CraftBukkit - HashTreeSet // PAIL: Rename nextTickList
private final Map<UUID, Entity> entitiesByUUID = Maps.newHashMap();
public ChunkProviderServer chunkProviderServer;
//public ChunkProviderServer chunkProviderServer; // Migot - moved to World
public boolean savingDisabled;
private boolean O;
private int emptyTime;
@ -48,6 +48,12 @@ public class WorldServer extends World implements IAsyncTaskHandler {
private static final List<StructurePieceTreasure> U = Lists.newArrayList(new StructurePieceTreasure[] { new StructurePieceTreasure(Items.STICK, 0, 1, 3, 10), new StructurePieceTreasure(Item.getItemOf(Blocks.PLANKS), 0, 1, 3, 10), new StructurePieceTreasure(Item.getItemOf(Blocks.LOG), 0, 1, 3, 10), new StructurePieceTreasure(Items.STONE_AXE, 0, 1, 1, 3), new StructurePieceTreasure(Items.WOODEN_AXE, 0, 1, 1, 5), new StructurePieceTreasure(Items.STONE_PICKAXE, 0, 1, 1, 3), new StructurePieceTreasure(Items.WOODEN_PICKAXE, 0, 1, 1, 5), new StructurePieceTreasure(Items.APPLE, 0, 2, 3, 5), new StructurePieceTreasure(Items.BREAD, 0, 2, 3, 3), new StructurePieceTreasure(Item.getItemOf(Blocks.LOG2), 0, 1, 3, 10)});
private List<NextTickListEntry> V = Lists.newArrayList();
// Migot start
public void cancelHeavyCalculations(boolean cancel) {
this.cancelHeavyCalculations = cancel;
}
// Migot end
// CraftBukkit start
public final int dimension;

View File

@ -52,13 +52,7 @@ import org.bukkit.craftbukkit.command.VanillaCommandWrapper;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.craftbukkit.generator.CraftChunkData;
import org.bukkit.craftbukkit.help.SimpleHelpMap;
import org.bukkit.craftbukkit.inventory.CraftFurnaceRecipe;
import org.bukkit.craftbukkit.inventory.CraftInventoryCustom;
import org.bukkit.craftbukkit.inventory.CraftItemFactory;
import org.bukkit.craftbukkit.inventory.CraftRecipe;
import org.bukkit.craftbukkit.inventory.CraftShapedRecipe;
import org.bukkit.craftbukkit.inventory.CraftShapelessRecipe;
import org.bukkit.craftbukkit.inventory.RecipeIterator;
import org.bukkit.craftbukkit.inventory.*;
import org.bukkit.craftbukkit.map.CraftMapView;
import org.bukkit.craftbukkit.metadata.EntityMetadataStore;
import org.bukkit.craftbukkit.metadata.PlayerMetadataStore;
@ -103,6 +97,8 @@ import org.bukkit.plugin.messaging.StandardMessenger;
import org.bukkit.scheduler.BukkitWorker;
import org.bukkit.util.StringUtil;
import org.bukkit.util.permissions.DefaultPermissions;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.SafeConstructor;
import org.yaml.snakeyaml.error.MarkedYAMLException;
@ -125,6 +121,7 @@ import io.netty.buffer.Unpooled;
import io.netty.handler.codec.base64.Base64;
import jline.console.ConsoleReader;
import net.md_5.bungee.api.chat.BaseComponent;
import org.yaml.snakeyaml.representer.Representer;
public final class CraftServer implements Server {
private static final Player[] EMPTY_PLAYER_ARRAY = new Player[0];
@ -143,7 +140,10 @@ public final class CraftServer implements Server {
private final Map<String, World> worlds = new LinkedHashMap<String, World>();
private YamlConfiguration configuration;
private YamlConfiguration commandsConfiguration;
private final Yaml yaml = new Yaml(new SafeConstructor());
// KigPaper start - CVE-2017-18640
private final LoaderOptions loaderOptions = new LoaderOptions();
private final Yaml yaml = new Yaml(new SafeConstructor(), new Representer(), new DumperOptions(), loaderOptions);
// KigPaper end
private final Map<UUID, OfflinePlayer> offlinePlayers = new MapMaker().softValues().makeMap();
private final EntityMetadataStore entityMetadata = new EntityMetadataStore();
private final PlayerMetadataStore playerMetadata = new PlayerMetadataStore();
@ -178,6 +178,7 @@ public final class CraftServer implements Server {
}
public CraftServer(MinecraftServer console, PlayerList playerList) {
loaderOptions.setMaxAliasesForCollections(32); // KigPaper - CVE-2017-18640
this.console = console;
this.playerList = (DedicatedPlayerList) playerList;
this.playerView = Collections.unmodifiableList(Lists.transform(playerList.players, new Function<EntityPlayer, CraftPlayer>() {
@ -1005,11 +1006,32 @@ public final class CraftServer implements Server {
} catch (ExceptionWorldConflict ex) {
getLogger().log(Level.SEVERE, null, ex);
}
} else { // KigPaper start
ChunkProviderServer cps = handle.chunkProviderServer;
ChunkRegionLoader loader = (ChunkRegionLoader) cps.chunkLoader;
loader.b.clear();
loader.c.clear();
try {
FileIOThread.a().b();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
cps.chunkLoader = null;
cps.chunkProvider = null;
cps.chunks.clear();
// KigPaper end
}
worlds.remove(world.getName().toLowerCase());
console.worlds.remove(console.worlds.indexOf(handle));
// KigPaper start - fix memory leak
CraftingManager craftingManager = CraftingManager.getInstance();
CraftInventoryView lastView = (CraftInventoryView) craftingManager.lastCraftView;
if (lastView != null && lastView.getHandle() instanceof ContainerWorkbench
&& ((ContainerWorkbench) lastView.getHandle()).g == handle) craftingManager.lastCraftView = null;
// KigPaper end
File parentFolder = world.getWorldFolder().getAbsoluteFile();
// Synchronized because access to RegionFileCache.a is guarded by this lock.
@ -1834,4 +1856,11 @@ public final class CraftServer implements Server {
{
return spigot;
}
// KigPaper start
@Override
public String getPermissionMessage() {
return configuration.getString("settings.permission-message", ChatColor.RED + "I'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is in error.");
}
// KigPaper end
}

View File

@ -216,6 +216,19 @@ public class CraftSound {
// Tile
set(PISTON_EXTEND, "tile.piston.out");
set(PISTON_RETRACT, "tile.piston.in");
// KigPaper start - Guardian sounds
set(GUARDIAN_IDLE, "mob.guardian.idle");
set(GUARDIAN_IDLE_LAND, "mob.guardian.land.idle");
set(GUARDIAN_IDLE_ELDER, "mob.guardian.elder.idle");
set(GUARDIAN_HIT, "mob.guardian.hit");
set(GUARDIAN_HIT_LAND, "mob.guardian.land.hit");
set(GUARDIAN_HIT_ELDER, "mob.guardian.elder.hit");
set(GUARDIAN_DEATH, "mob.guardian.death");
set(GUARDIAN_DEATH_LAND, "mob.guardian.land.death");
set(GUARDIAN_DEATH_ELDER, "mob.guardian.elder.death");
set(GUARDIAN_FLOP, "mob.guardian.flop");
set(GUARDIAN_CURSE, "mob.guardian.curse");
// KigPaper end
}
private static void set(Sound sound, String key) {

View File

@ -44,7 +44,12 @@ public class CraftTravelAgent extends PortalTravelAgent implements TravelAgent {
@Override
public Location findPortal(Location location) {
PortalTravelAgent pta = ((CraftWorld) location.getWorld()).getHandle().getTravelAgent();
BlockPosition found = pta.findPortal(location.getX(), location.getY(), location.getZ(), this.getSearchRadius());
// Migot start
BlockPosition found = pta.findPortal(location.getX(), location.getY(), location.getZ(), 10);
if (found == null) {
found = pta.findPortal(location.getX(), location.getY(), location.getZ(), this.getSearchRadius());
}
// Migot end
return found != null ? new Location(location.getWorld(), found.getX(), found.getY(), found.getZ(), location.getYaw(), location.getPitch()) : null;
}

View File

@ -1,5 +1,6 @@
package org.bukkit.craftbukkit;
import com.elevatemc.spigot.util.Dictionary;
import com.google.common.base.Preconditions;
import java.io.File;
import java.util.ArrayList;
@ -35,6 +36,7 @@ import org.bukkit.craftbukkit.block.CraftBlockState;
import org.bukkit.craftbukkit.entity.*;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.craftbukkit.metadata.BlockMetadataStore;
import org.bukkit.craftbukkit.metadata.SpecializedBlockMetadataStore;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.craftbukkit.util.LongHash;
import org.bukkit.entity.*;
@ -51,6 +53,7 @@ import org.bukkit.event.world.SpawnChangeEvent;
import org.bukkit.generator.BlockPopulator;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.inventory.ItemStack;
import org.bukkit.metadata.MetadataStore;
import org.bukkit.metadata.MetadataValue;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.messaging.StandardMessenger;
@ -65,7 +68,10 @@ public class CraftWorld implements World {
private final CraftServer server = (CraftServer) Bukkit.getServer();
private final ChunkGenerator generator;
private final List<BlockPopulator> populators = new ArrayList<BlockPopulator>();
private final BlockMetadataStore blockMetadata = new BlockMetadataStore(this);
// KigPaper start
//private final BlockMetadataStore blockMetadata = new BlockMetadataStore(this);
private final MetadataStore<Block> blockMetadata = new SpecializedBlockMetadataStore(this);
// KigPaper end
private int monsterSpawn = -1;
private int animalSpawn = -1;
private int waterAnimalSpawn = -1;
@ -235,6 +241,7 @@ public class CraftWorld implements World {
save = true;
}
chunk.markAsUnloaded(); // Migot
chunk.removeEntities(); // Always remove entities - even if discarding, need to get them out of world table
if (save && !(chunk instanceof EmptyChunk)) {
@ -787,17 +794,12 @@ public class CraftWorld implements World {
}
public void save() {
// Spigot start
save(true);
}
public void save(boolean forceSave) {
// Spigot end
this.server.checkSaveState();
try {
boolean oldSave = world.savingDisabled;
world.savingDisabled = false;
world.save(forceSave, null); // Spigot
world.save(true, null); // Spigot
world.savingDisabled = oldSave;
} catch (ExceptionWorldConflict ex) {
@ -821,7 +823,7 @@ public class CraftWorld implements World {
return Difficulty.getByValue(this.getHandle().getDifficulty().ordinal());
}
public BlockMetadataStore getBlockMetadata() {
public MetadataStore<Block> getBlockMetadata() { // KigPaper - change type
return blockMetadata;
}
@ -1457,22 +1459,16 @@ public class CraftWorld implements World {
{
net.minecraft.server.EnumParticle particle = null;
int[] extra = null;
for ( net.minecraft.server.EnumParticle p : net.minecraft.server.EnumParticle.values() )
{
if ( effect.getName().startsWith( p.b().replace("_", "") ) )
if ((particle = Dictionary.EFFECT_TO_PARTICLE.get(effect)) != null) {
if ( effect.getData() != null )
{
particle = p;
if ( effect.getData() != null )
if ( effect.getData().equals( Material.class ) )
{
if ( effect.getData().equals( org.bukkit.Material.class ) )
{
extra = new int[]{ id };
} else
{
extra = new int[]{ (data << 12) | (id & 0xFFF) };
}
extra = new int[]{ id };
} else
{
extra = new int[]{ (data << 12) | (id & 0xFFF) };
}
break;
}
}
if ( extra == null )

View File

@ -12,18 +12,19 @@ import org.bukkit.plugin.Plugin;
import java.util.Set;
public abstract class ServerCommandSender implements CommandSender {
private static PermissibleBase blockPermInst;
//private static PermissibleBase blockPermInst; // KigPaper - fix memory leak
private final PermissibleBase perm;
public ServerCommandSender() {
if (this instanceof CraftBlockCommandSender) {
/* if (this instanceof CraftBlockCommandSender) {
if (blockPermInst == null) {
blockPermInst = new PermissibleBase(this);
}
this.perm = blockPermInst;
} else {
this.perm = new PermissibleBase(this);
}
} */ // KigPaper
this.perm = new PermissibleBase(this);
}
public boolean isPermissionSet(String name) {

View File

@ -43,7 +43,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
protected final CraftServer server;
protected Entity entity;
private EntityDamageEvent lastDamageEvent;
//private EntityDamageEvent lastDamageEvent; // KigPaper - this is almost never used and only leads to memory leaks
public CraftEntity(final CraftServer server, final Entity entity) {
this.server = server;
@ -259,6 +259,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
// entity.world = ((CraftWorld) location.getWorld()).getHandle();
// Spigot end
entity.setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
entity.f(location.getYaw()); // KigPaper - update head yaw to keep consistency with /tp
entity.world.entityJoinedWorld(entity, false); // PaperSpigot - Fix issues with entities not being switched to their new chunk
// entity.setLocation() throws no event, and so cannot be cancelled
return true;
@ -358,11 +359,11 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
}
public void setLastDamageCause(EntityDamageEvent event) {
lastDamageEvent = event;
// lastDamageEvent = event;
}
public EntityDamageEvent getLastDamageCause() {
return lastDamageEvent;
return null;
}
public UUID getUniqueId() {

View File

@ -1,6 +1,7 @@
package org.bukkit.craftbukkit.entity;
import com.elevatemc.spigot.event.PlayerHealthChangeEvent;
import com.elevatemc.spigot.util.Dictionary;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableSet;
import com.mojang.authlib.GameProfile;
@ -289,6 +290,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
}
}
@Override
public void sendActionbarMessage(BaseComponent... message) {
if(getHandle().playerConnection == null) return;
PacketPlayOutChat packet = new PacketPlayOutChat(null, (byte) 2);
packet.components = message;
getHandle().playerConnection.sendPacket(packet);
}
// KigPaper end
@Override
public boolean equals(Object obj) {
if (!(obj instanceof OfflinePlayer)) {
@ -532,7 +542,11 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
}
if (entity.passenger != null) {
return false;
// KigPaper - only cancel if not unknown
// if a PlayerMoveEvent is cancelled using setTo and the player has a passenger, the event won't set the user back.
if (cause != PlayerTeleportEvent.TeleportCause.UNKNOWN) {
return false;
}
}
// From = Players current Location
@ -1244,7 +1258,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@Override
public void setFlying(boolean value) {
boolean needsUpdate = getHandle().abilities.canFly != value; // PaperSpigot - Only refresh abilities if needed
boolean needsUpdate = getHandle().abilities.isFlying != value; // PaperSpigot - Only refresh abilities if needed
if (!getAllowFlight() && value) {
throw new IllegalArgumentException("Cannot make player fly if getAllowFlight() is false");
}
@ -1508,22 +1522,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
{
net.minecraft.server.EnumParticle particle = null;
int[] extra = null;
for ( net.minecraft.server.EnumParticle p : net.minecraft.server.EnumParticle.values() )
{
if ( effect.getName().startsWith( p.b().replace("_", "") ) )
if ((particle = Dictionary.EFFECT_TO_PARTICLE.get(effect)) != null) {
if ( effect.getData() != null )
{
particle = p;
if ( effect.getData() != null )
if ( effect.getData().equals( org.bukkit.Material.class ) )
{
if ( effect.getData().equals( org.bukkit.Material.class ) )
{
extra = new int[]{ id };
} else
{
extra = new int[]{ (data << 12) | (id & 0xFFF) };
}
extra = new int[]{ id };
} else
{
extra = new int[]{ (data << 12) | (id & 0xFFF) };
}
break;
}
}
if ( extra == null )

View File

@ -188,7 +188,7 @@ public class CraftEventFactory {
if (action != Action.LEFT_CLICK_AIR && action != Action.RIGHT_CLICK_AIR) {
throw new IllegalArgumentException(String.format("%s performing %s with %s", who, action, itemstack)); // Spigot
}
return callPlayerInteractEvent(who, action, new BlockPosition(0, 256, 0), EnumDirection.SOUTH, itemstack);
return callPlayerInteractEvent(who, action, /*new BlockPosition(0, 256, 0) KigPaper */ null, EnumDirection.SOUTH, itemstack);
}
public static PlayerInteractEvent callPlayerInteractEvent(EntityHuman who, Action action, BlockPosition position, EnumDirection direction, ItemStack itemstack) {
@ -202,11 +202,11 @@ public class CraftEventFactory {
CraftWorld craftWorld = (CraftWorld) player.getWorld();
CraftServer craftServer = (CraftServer) player.getServer();
Block blockClicked = craftWorld.getBlockAt(position.getX(), position.getY(), position.getZ());
BlockFace blockFace = CraftBlock.notchToBlockFace(direction);
if (position.getY() > 255) {
blockClicked = null;
// Block blockClicked = craftWorld.getBlockAt(position.getX(), position.getY(), position.getZ()); // KigPaper
Block blockClicked = null;
if (position != null) {
blockClicked = craftWorld.getBlockAt(position.getX(), position.getY(), position.getZ());
} else {
switch (action) {
case LEFT_CLICK_BLOCK:
action = Action.LEFT_CLICK_AIR;
@ -217,6 +217,8 @@ public class CraftEventFactory {
}
}
BlockFace blockFace = CraftBlock.notchToBlockFace(direction); // KigPaper - moved down
if (itemInHand.getType() == Material.AIR || itemInHand.getAmount() == 0) {
itemInHand = null;
}
@ -532,7 +534,8 @@ public class CraftEventFactory {
} else if (source == DamageSource.FALL) {
cause = DamageCause.FALL;
} else if (source == DamageSource.GENERIC) {
return new EntityDamageEvent(entity.getBukkitEntity(), null, modifiers, modifierFunctions);
//return new EntityDamageEvent(entity.getBukkitEntity(), null, modifiers, modifierFunctions);
cause = DamageCause.CUSTOM; // KigPaper
}
if (cause != null) {

View File

@ -33,8 +33,10 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta {
static final ItemMetaKey BOOK_PAGES = new ItemMetaKey("pages");
static final ItemMetaKey RESOLVED = new ItemMetaKey("resolved");
static final ItemMetaKey GENERATION = new ItemMetaKey("generation");
static final int MAX_PAGE_LENGTH = Short.MAX_VALUE; // TODO: Check me
static final int MAX_TITLE_LENGTH = 0xffff;
static final int MAX_PAGES = 50;
static final int MAX_PAGE_LENGTH = 256;
static final int MAX_TITLE_LENGTH = 16;
protected String title;
protected String author;
@ -61,11 +63,11 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta {
super(tag);
if (tag.hasKey(BOOK_TITLE.NBT)) {
this.title = limit( tag.getString(BOOK_TITLE.NBT), 1024 ); // Spigot
this.title = limit( tag.getString(BOOK_TITLE.NBT), 32 ); // Spigot // KigPaper - tighter limits
}
if (tag.hasKey(BOOK_AUTHOR.NBT)) {
this.author = limit( tag.getString(BOOK_AUTHOR.NBT), 1024 ); // Spigot
this.author = limit( tag.getString(BOOK_AUTHOR.NBT), 16 ); // Spigot // KigPaper - tighter limits
}
boolean resolved = false;
@ -80,6 +82,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta {
if (tag.hasKey(BOOK_PAGES.NBT) && handlePages) {
NBTTagList pages = tag.getList(BOOK_PAGES.NBT, 8);
if (pages.size() > MAX_PAGES) return; // KigPaper - limit pages
for (int i = 0; i < pages.size(); i++) {
String page = pages.getString(i);
if (resolved) {
@ -90,7 +93,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta {
// Ignore and treat as an old book
}
}
addPage( limit( page, 2048 ) ); // Spigot
addPage( limit( page, MAX_PAGE_LENGTH ) ); // Spigot // KigPaper - tighter limits
}
}
}
@ -103,13 +106,17 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta {
setTitle(SerializableMeta.getString(map, BOOK_TITLE.BUKKIT, true));
Iterable<?> pages = SerializableMeta.getObject(Iterable.class, map, BOOK_PAGES.BUKKIT, true);
// KigPaper start - limit pages
if(pages != null) {
int count = 0;
for (Object page : pages) {
if (count++ > MAX_PAGES) break;
if (page instanceof String) {
addPage((String) page);
}
}
}
// KigPaper end
generation = SerializableMeta.getObject(Integer.class, map, GENERATION.BUKKIT, true);
}
@ -225,10 +232,14 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta {
public void addPage(final String... pages) {
for (String page : pages) {
if (this.pages.size() >= MAX_PAGES) {
return;
}
if (page == null) {
page = "";
} else if (page.length() > MAX_PAGE_LENGTH) {
page = page.substring(0, MAX_PAGE_LENGTH);
//page = page.substring(0, MAX_PAGE_LENGTH);
return; // KigPaper
}
this.pages.add(CraftChatMessage.fromString(page, true)[0]);

View File

@ -35,15 +35,17 @@ public class CraftMapRenderer extends MapRenderer {
cursors.removeCursor(cursors.getCursor(0));
}
for (UUID key : worldMap.decorations.keySet()) { // Spigot string -> uuid.
// If this cursor is for a player check visibility with vanish system
Player other = Bukkit.getPlayer(key); // Spigot
if (other != null && !player.canSee(other)) {
continue;
if (getDrawCursors()) {
for (UUID key : worldMap.decorations.keySet()) { // Spigot string -> uuid.
// If this cursor is for a player check visibility with vanish system
Player other = Bukkit.getPlayer(key); // Spigot
if (other != null && !player.canSee(other)) {
continue;
}
MapIcon decoration = (MapIcon) worldMap.decorations.get(key);
cursors.addCursor(decoration.getX(), decoration.getY(), (byte) (decoration.getRotation() & 15), decoration.getType());
}
MapIcon decoration = (MapIcon) worldMap.decorations.get(key);
cursors.addCursor(decoration.getX(), decoration.getY(), (byte) (decoration.getRotation() & 15), decoration.getType());
}
}

View File

@ -0,0 +1,175 @@
package org.bukkit.craftbukkit.metadata;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.metadata.MetadataStore;
import org.bukkit.metadata.MetadataValue;
import org.bukkit.plugin.Plugin;
import java.util.*;
/**
* An alternative to {@link BlockMetadataStore} that uses specialized collections and bit-packing for faster
* operations and a lower memory footprint.
*
* <p>This can be a drop-in replacement, though keep in mind methods will throw an {@link IllegalArgumentException}
* if invalid block coordinates are provided.
*/
public class SpecializedBlockMetadataStore implements MetadataStore<Block> {
// Allows storing 25 bits (up to 33,554,432 - MC supports up to 30,000,000) sign
private static final int MASK_26_BITS = 0b111_111_111_111_111_111_111_111_11;
private final Map<StoreKey, Map<Plugin, MetadataValue>> metadata = new HashMap<>();
private final World owningWorld;
// Cached key used for (synchronized) lookups, saves allocations.
// The key stored inside is usually cleared after use, so that the reference doesn't live too long.
private final StoreKey cachedKey = new StoreKey(null, 0);
public SpecializedBlockMetadataStore(World owningWorld) {
this.owningWorld = owningWorld;
}
@Override
public synchronized List<MetadataValue> getMetadata(Block block, String metadataKey) {
Preconditions.checkArgument(block.getWorld() == owningWorld, "block is from another world");
List<MetadataValue> list = Collections.emptyList();
Map<Plugin, MetadataValue> pluginMetadata = getEntry(metadataKey, block);
if (pluginMetadata == null) {
return list;
}
list = ImmutableList.copyOf(pluginMetadata.values());
return list;
}
@Override
public synchronized boolean hasMetadata(Block block, String metadataKey) {
Preconditions.checkArgument(block.getWorld() == owningWorld, "block is from another world");
Map<Plugin, MetadataValue> pluginMetadata = getEntry(metadataKey, block);
return pluginMetadata != null && !pluginMetadata.isEmpty();
}
@Override
public synchronized void removeMetadata(Block block, String metadataKey, Plugin owningPlugin) {
Preconditions.checkArgument(block.getWorld() == owningWorld, "block is from another world");
Preconditions.checkNotNull(owningPlugin, "plugin is null");
long id = getBlockId(block);
Map<Plugin, MetadataValue> pluginMetadata = getEntry(metadataKey, id);
if (pluginMetadata == null) {
return;
}
// Clear empty entries
if (pluginMetadata.remove(owningPlugin) != null && pluginMetadata.isEmpty()) {
StoreKey key = getCachedKey(metadataKey, id);
this.metadata.remove(key);
key.metadataKey = null;
}
}
@Override
public synchronized void setMetadata(Block block, String metadataKey, MetadataValue newMetadataValue) {
Preconditions.checkArgument(block.getWorld() == owningWorld, "block is from another world");
Preconditions.checkNotNull(newMetadataValue, "value is null");
Plugin owningPlugin = newMetadataValue.getOwningPlugin();
Preconditions.checkNotNull(owningPlugin, "plugin is null");
Map<Plugin, MetadataValue> entry = metadata.computeIfAbsent(new StoreKey(metadataKey, getBlockId(block)),
k -> new WeakHashMap<>(1));
entry.put(owningPlugin, newMetadataValue);
}
@Override
public synchronized void invalidateAll(Plugin owningPlugin) {
Preconditions.checkNotNull(owningPlugin, "plugin is null");
for (Map<Plugin, MetadataValue> values : metadata.values()) {
MetadataValue value = values.get(owningPlugin);
if (value != null) {
value.invalidate();
}
}
}
private Map<Plugin, MetadataValue> getEntry(String key, Block block) {
return getEntry(key, getBlockId(block));
}
private Map<Plugin, MetadataValue> getEntry(String key, long id) {
StoreKey storeKey = getCachedKey(key, id);
Map<Plugin, MetadataValue> ret = metadata.get(storeKey);
storeKey.metadataKey = null;
return ret;
}
private StoreKey getCachedKey(String metadataKey, long id) {
cachedKey.block = id;
cachedKey.metadataKey = metadataKey;
return cachedKey;
}
static long getBlockId(Block block) {
int x = block.getX();
int y = block.getY();
int z = block.getZ();
Preconditions.checkArgument(x >= -30_000_000 && x <= 30_000_000,
"block X out of range");
Preconditions.checkArgument(y >= 0 && y <= 255, "block Y out of range");
Preconditions.checkArgument(z >= -30_000_000 && z <= 30_000_000,
"block Z out of range");
// X (26 bits) + Y (8 bits) + Z (26 bits)
return ((long) (x & MASK_26_BITS) << 34) | ((long) (y & 0xFF) << 26) | (z & MASK_26_BITS);
}
/**
* Used for tests.
*/
static Location toLocation(World world, long id) {
int x = (int) (id >> 34);
int y = (int) ((id >> 26) & 0xFF);
int z = (int) id;
// Restore sign
if ((x & (1 << 25)) > 0) {
x |= ~MASK_26_BITS;
} else {
x &= MASK_26_BITS;
}
if ((z & (1 << 25)) > 0) {
z |= ~MASK_26_BITS;
} else {
z &= MASK_26_BITS;
}
return new Location(world, x, y, z);
}
private static class StoreKey {
private String metadataKey;
private long block;
private StoreKey(String metadataKey, long block) {
this.metadataKey = metadataKey;
this.block = block;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
StoreKey storeKey = (StoreKey) o;
return block == storeKey.block && Objects.equal(metadataKey, storeKey.metadataKey);
}
@Override
public int hashCode() {
return Objects.hashCode(metadataKey, block);
}
}
}

View File

@ -10,7 +10,7 @@ import org.bukkit.metadata.MetadataStoreBase;
public class WorldMetadataStore extends MetadataStoreBase<World> implements MetadataStore<World> {
/**
* Generates a unique metadata key for a {@link World} object based on the world UID.
* @see WorldMetadataStore#disambiguate(Object, String)
* @see WorldMetadataStore#disambiguate(World, String)
* @param world the world
* @param metadataKey The name identifying the metadata value
* @return a unique metadata key

View File

@ -32,7 +32,7 @@ import org.bukkit.scheduler.BukkitWorker;
* <li>Changing the period on a task is delicate.
* Any future task needs to notify waiting threads.
* Async tasks must be synchronized to make sure that any thread that's finishing will remove itself from {@link #runners}.
* Another utility method is provided for this, {@link #cancelTask(CraftTask)}</li>
* Another utility method is provided for this, {@link #cancelTask(int)}</li>
* <li>{@link #runners} provides a moderately up-to-date view of active tasks.
* If the linked head to tail set is read, all remaining tasks that were active at the time execution started will be located in runners.</li>
* <li>Async tasks are responsible for removing themselves from runners</li>
@ -47,7 +47,7 @@ public class CraftScheduler implements BukkitScheduler {
*/
private final AtomicInteger ids = new AtomicInteger(1);
/**
* Current head of linked-list. This reference is always stale, {@link CraftTask#next} is the live reference.
* Current head of linked-list. This reference is always stale, {@code CraftTask#next} is the live reference.
*/
private volatile CraftTask head = new CraftTask();
/**

View File

@ -22,7 +22,8 @@ public final class CraftChatMessage {
private static final Pattern LINK_PATTERN = Pattern.compile("((?:(?:https?):\\/\\/)?(?:[-\\w_\\.]{2,}\\.[a-z]{2,4}.*?(?=[\\.\\?!,;:]?(?:[" + String.valueOf(org.bukkit.ChatColor.COLOR_CHAR) + " \\n]|$))))");
private static class StringMessage {
private static final Map<Character, EnumChatFormat> formatMap;
private static final Pattern INCREMENTAL_PATTERN = Pattern.compile("(" + String.valueOf(org.bukkit.ChatColor.COLOR_CHAR) + "[0-9a-fk-or])|(\\n)|((?:(?:https?):\\/\\/)?(?:[-\\w_\\.]{2,}\\.[a-z]{2,4}.*?(?=[\\.\\?!,;:]?(?:[" + String.valueOf(org.bukkit.ChatColor.COLOR_CHAR) + " \\n]|$))))", Pattern.CASE_INSENSITIVE);
//private static final Pattern INCREMENTAL_PATTERN = Pattern.compile("(" + String.valueOf(org.bukkit.ChatColor.COLOR_CHAR) + "[0-9a-fk-or])|(\\n)|((?:(?:https?):\\/\\/)?(?:[-\\w_\\.]{2,}\\.[a-z]{2,4}.*?(?=[\\.\\?!,;:]?(?:[" + String.valueOf(org.bukkit.ChatColor.COLOR_CHAR) + " \\n]|$))))", Pattern.CASE_INSENSITIVE);
private static final Pattern INCREMENTAL_PATTERN = Pattern.compile("(§[0-9a-fk-or])|(\\n)|(https?://[^\\s/$.?#].[^\\s§]*)", Pattern.CASE_INSENSITIVE); // KigPaper - better regex
static {
Builder<Character, EnumChatFormat> builder = ImmutableMap.builder();

View File

@ -13,6 +13,7 @@ import java.util.logging.Level;
import net.minecraft.server.Item;
import net.minecraft.server.Items;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.RegionFile;
import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.Material;
@ -227,4 +228,41 @@ public class PaperSpigotConfig
private static void saveEmptyScoreboardTeams() {
saveEmptyScoreboardTeams = getBoolean("save-empty-scoreboard-teams", false);
}
// KigPaper start
public static boolean betterVehicleHitboxes;
private static void betterVehicleHitboxes() {
betterVehicleHitboxes = getBoolean("better-vehicle-hitboxes", true);
}
public static boolean nettyReadTimeout;
private static void nettyReadTimeout() {
nettyReadTimeout = getBoolean("netty-read-timeout", true);
}
public static boolean savePlayerFiles;
private static void savePlayerFiles() {
savePlayerFiles = getBoolean("save-player-files", true);
}
public static boolean enableBookDeserialization;
private static void enableBookDeserialization() {
enableBookDeserialization = getBoolean("enable-book-deserialization", false);
}
public static boolean accurateBlockCollisions;
private static void accurateBlockCollisions() {
accurateBlockCollisions = getBoolean("accurate-block-collisions", true);
}
public static RegionFile.CompressionAlgorithm regionCompressionAlgorithm;
private static void regionCompressionAlgorithm() {
regionCompressionAlgorithm = RegionFile.CompressionAlgorithm.valueOf(getString("region-compression-algo", "ZLIB").toUpperCase(Locale.ROOT));
}
public static boolean kickChatMessageLength;
private static void kickChatMessageLength() {
kickChatMessageLength = getBoolean("kick-chat-message-length", false);
}
// KigPaper end
}

View File

@ -67,7 +67,7 @@ public class ActivationRange
* These entities are excluded from Activation range checks.
*
* @param entity
* @param world
* @param config
* @return boolean If it should always tick.
*/
public static boolean initializeEntityActivationState(Entity entity, SpigotWorldConfig config)

View File

@ -344,7 +344,7 @@ public class Metrics {
*/
private void postPlugin(final boolean isPing) throws IOException {
// Server software specific section
String pluginName = "TacoSpigot"; // PaperSpigot - We need some usage data // TacoSpigot - its *my* usage data
String pluginName = "eSpigot"; // PaperSpigot - We need some usage data // TacoSpigot - its *my* usage data // eSpigot
boolean onlineMode = Bukkit.getServer().getOnlineMode(); // TRUE if online mode is enabled
String pluginVersion = (Metrics.class.getPackage().getImplementationVersion() != null) ? Metrics.class.getPackage().getImplementationVersion() : "unknown";
String serverVersion = Bukkit.getVersion();

View File

@ -191,10 +191,15 @@ public class SpigotWorldConfig
}
public boolean saveStructureInfo;
public boolean saveMineshaftStructureInfo; // Migot
private void structureInfo()
{
saveStructureInfo = getBoolean( "save-structure-info", true );
log( "Structure Info Saving: " + saveStructureInfo );
// Migot start
saveMineshaftStructureInfo = getBoolean( "save-mineshaft-structure-info", false);
log( "Mineshaft Structure Info Saving: " + saveMineshaftStructureInfo );
// Migot end
if ( !saveStructureInfo )
{
log( "*** WARNING *** You have selected to NOT save structure info. This may cause structures such as fortresses to not spawn mobs!" );

View File

@ -56,9 +56,8 @@ public class WatchdogThread extends Thread
{
Logger log = Bukkit.getServer().getLogger();
log.log( Level.SEVERE, "The server has stopped responding!" );
log.log( Level.SEVERE, "Please report this to PaperSpigot directly!" );
log.log( Level.SEVERE, "Be sure to include ALL relevant console errors and Minecraft crash reports" );
log.log( Level.SEVERE, "PaperSpigot version: " + Bukkit.getServer().getVersion() );
log.log( Level.SEVERE, "This is all alf's fault." );
log.log( Level.SEVERE, "Version: " + Bukkit.getServer().getVersion() );
//
if(net.minecraft.server.World.haveWeSilencedAPhysicsCrash)
{

View File

@ -0,0 +1,62 @@
package org.bukkit.craftbukkit.metadata;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.metadata.MetadataStore;
import org.bukkit.metadata.MetadataValue;
import org.bukkit.plugin.Plugin;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
import java.util.List;
public class BlockMetadataTest {
@Test
public void oldNewComparison() {
MetadataStore<Block> oldStore = new BlockMetadataStore(null);
MetadataStore<Block> newStore = new SpecializedBlockMetadataStore(null);
Plugin plugin = Mockito.mock(Plugin.class);
for (int x = 2, y = 0, z = 2, i = 0; i < 20; i++, x += 300, z += 200, y += 10) {
Block block = makeBlock(i % 2 == 0 ? x : -x, y, i % 2 == 0 ? z : -z);
MetadataValue value = new FixedMetadataValue(plugin, i);
oldStore.setMetadata(block, "test", value);
oldStore.setMetadata(block, "test" + i, value);
newStore.setMetadata(block, "test", value);
newStore.setMetadata(block, "test" + i, value);
Assert.assertTrue(newStore.hasMetadata(block, "test"));
Assert.assertTrue(newStore.hasMetadata(block, "test" + i));
List<MetadataValue> test = newStore.getMetadata(block, "test");
Assert.assertEquals(test, oldStore.getMetadata(block, "test"));
Assert.assertTrue("value in newStore[\"test\"]", test.contains(value));
List<MetadataValue> indexTest = newStore.getMetadata(block, "test" + i);
Assert.assertEquals(indexTest, oldStore.getMetadata(block, "test" + i));
Assert.assertTrue("value in newStore[\"test\" + i]", indexTest.contains(value));
}
}
@Test
public void compareIds() {
for (int x = 3, y = 1, z = 2, i = 0; i < 20; i++, x += 300, z += 200, y += 10) {
Block block = makeBlock(i % 2 == 0 ? x : -x, y, i % 2 == 0 ? z : -z);
Location location = new Location(null, block.getX(), block.getY(), block.getZ());
Assert.assertEquals(location, SpecializedBlockMetadataStore.toLocation(null,
SpecializedBlockMetadataStore.getBlockId(block)));
}
}
private static Block makeBlock(int x, int y, int z) {
Block block = Mockito.mock(Block.class);
Mockito.when(block.getX()).thenReturn(x);
Mockito.when(block.getY()).thenReturn(y);
Mockito.when(block.getZ()).thenReturn(z);
return block;
}
}