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> <dependency>
<groupId>org.yaml</groupId> <groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId> <artifactId>snakeyaml</artifactId>
<version>1.15</version> <version>1.30</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -1166,4 +1166,10 @@ public final class Bukkit {
{ {
return server.spigot(); 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(); 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_IDLE,
VILLAGER_NO, VILLAGER_NO,
VILLAGER_YES, 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) { 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) { } else if (permissionMessage.length() != 0) {
for (String line : permissionMessage.replace("<permission>", permission).split("\n")) { for (String line : permissionMessage.replace("<permission>", permission).split("\n")) {
target.sendMessage(line); target.sendMessage(line);

View File

@ -2,6 +2,7 @@ package org.bukkit.entity;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import net.md_5.bungee.api.chat.BaseComponent;
import org.bukkit.Achievement; import org.bukkit.Achievement;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.Effect; import org.bukkit.Effect;
@ -1203,6 +1204,14 @@ public interface Player extends HumanEntity, Conversable, CommandSender, Offline
// Paper - Undeprecate // Paper - Undeprecate
public void resetTitle(); 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 // TacoSpigot start
/** /**
* Request that the player's client download and switch resource packs. * 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 { public abstract class MapRenderer {
private boolean drawCursors = true; // KigPaper
private boolean contextual; private boolean contextual;
/** /**
@ -53,4 +54,20 @@ public abstract class MapRenderer {
*/ */
abstract public void render(MapView map, MapCanvas canvas, Player player); 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> <artifactId>velocity-native</artifactId>
<version>1.1.0-SNAPSHOT</version> <version>1.1.0-SNAPSHOT</version>
</dependency> </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> </dependencies>
<!-- required until fixed plexus-compiler-eclipse is deployed --> <!-- required until fixed plexus-compiler-eclipse is deployed -->
@ -144,7 +154,7 @@
<!-- PaperSpigot - Repo for gitdescribe --> <!-- PaperSpigot - Repo for gitdescribe -->
<pluginRepository> <pluginRepository>
<id>destroystokyo</id> <id>destroystokyo</id>
<url>https://ci.destroystokyo.com/plugin/repository/everything/</url> <url>https://papermc.io/repo/repository/maven-public/</url>
</pluginRepository> </pluginRepository>
</pluginRepositories> </pluginRepositories>

View File

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

View File

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

View File

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

View File

@ -10,7 +10,6 @@ import org.apache.logging.log4j.Logger;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.Iterator; import java.util.Iterator;
@ -54,7 +53,7 @@ public class ThreadingManager {
while((this.nbtFiles.isActive()) && !this.cachedThreadPool.isTerminated()) { while((this.nbtFiles.isActive()) && !this.cachedThreadPool.isTerminated()) {
try { try {
this.cachedThreadPool.awaitTermination(10, TimeUnit.SECONDS); 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) {} } catch(InterruptedException e) {}
} }
if(!this.cachedThreadPool.isTerminated()) { if(!this.cachedThreadPool.isTerminated()) {
@ -65,7 +64,7 @@ public class ThreadingManager {
e.printStackTrace(); e.printStackTrace();
} }
if(this.cachedThreadPoolFactory.getActiveCount() > 0) { 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(); Queue<WeakReference<Thread>> queue = this.cachedThreadPoolFactory.getThreadList();
Iterator<WeakReference<Thread>> iter = null; Iterator<WeakReference<Thread>> iter = null;
if(queue != 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(tickTime > 45.0F) {
if(timerDelay > 40) { if(timerDelay > 40) {
timerDelay--; 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); 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) { protected void a(BiomeBase biomebase) {
this.a(); this.a();
if (this.b.nextInt(5) == 0) { if (this.b.nextInt(5) == 0) {

View File

@ -4,6 +4,7 @@ import java.util.Iterator;
import java.util.Random; import java.util.Random;
import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit
import org.bukkit.event.block.BlockPhysicsEvent;
public class BlockCactus extends Block { 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) { public void doPhysics(World world, BlockPosition blockposition, IBlockData iblockdata, Block block) {
if (!this.e(world, blockposition)) { 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) { private IBlockData e(World world, BlockPosition blockposition, IBlockData iblockdata) {
iblockdata = this.a(world, blockposition, blockposition, iblockdata); // Migot start
ArrayList arraylist = Lists.newArrayList(this.R); 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(); Iterator iterator = arraylist.iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {

View File

@ -50,6 +50,19 @@ public class Chunk {
private int v; private int v;
private ConcurrentLinkedQueue<BlockPosition> w; private ConcurrentLinkedQueue<BlockPosition> w;
protected gnu.trove.map.hash.TObjectIntHashMap<Class> entityCount = new gnu.trove.map.hash.TObjectIntHashMap<Class>(); // Spigot 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 // PaperSpigot start - Asynchronous light updates
public AtomicInteger pendingLightUpdates = new AtomicInteger(); public AtomicInteger pendingLightUpdates = new AtomicInteger();
public long lightUpdateTime; public long lightUpdateTime;
@ -1061,7 +1074,7 @@ public class Chunk {
if (this.r && this.world.getTime() != this.lastSaved || this.q) { if (this.r && this.world.getTime() != this.lastSaved || this.q) {
return true; 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; return true;
} }

View File

@ -36,13 +36,27 @@ public class ChunkProviderServer implements IChunkProvider {
public LongSet unloadQueue = new LongArraySet(); // CraftBukkit - LongHashSet // TacoSpigot - LongHashSet -> HashArraySet public LongSet unloadQueue = new LongArraySet(); // CraftBukkit - LongHashSet // TacoSpigot - LongHashSet -> HashArraySet
public Chunk emptyChunk; public Chunk emptyChunk;
public IChunkProvider chunkProvider; public IChunkProvider chunkProvider;
private IChunkLoader chunkLoader; public IChunkLoader chunkLoader; // KigPaper - private -> public
public boolean forceChunkLoad = false; // CraftBukkit - true -> false 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 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; 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) { 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.world = worldserver;
this.chunkLoader = ichunkloader; this.chunkLoader = ichunkloader;
this.chunkProvider = ichunkprovider; this.chunkProvider = ichunkprovider;
@ -347,7 +361,7 @@ public class ChunkProviderServer implements IChunkProvider {
this.saveChunk(chunk); this.saveChunk(chunk);
chunk.f(false); chunk.f(false);
++i; ++i;
if (i == 24 && !flag && false) { // Spigot if (i == 24 && !flag) {
return false; return false;
} }
} }
@ -381,6 +395,7 @@ public class ChunkProviderServer implements IChunkProvider {
if (!event.isCancelled()) { if (!event.isCancelled()) {
if (chunk != null) { if (chunk != null) {
chunk.markAsUnloaded(); // Migot
chunk.removeEntities(); chunk.removeEntities();
this.saveChunk(chunk); this.saveChunk(chunk);
this.saveChunkNOP(chunk); this.saveChunkNOP(chunk);

View File

@ -17,8 +17,10 @@ import org.apache.logging.log4j.Logger;
public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
private static final Logger a = LogManager.getLogger(); private static final Logger a = LogManager.getLogger();
private Map<ChunkCoordIntPair, NBTTagCompound> b = new ConcurrentHashMap(); // KigPaper start - make public
private Set<ChunkCoordIntPair> c = Collections.newSetFromMap(new ConcurrentHashMap()); public Map<ChunkCoordIntPair, NBTTagCompound> b = new ConcurrentHashMap();
public Set<ChunkCoordIntPair> c = Collections.newSetFromMap(new ConcurrentHashMap());
// KigPaper end
private final File d; private final File d;
private boolean e = false; private boolean e = false;
@ -29,6 +31,14 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
// CraftBukkit start // CraftBukkit start
public boolean chunkExists(World world, int i, int j) { public boolean chunkExists(World world, int i, int j) {
ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(i, 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.c.contains(chunkcoordintpair)) {
if (this.b.containsKey(chunkcoordintpair)) { if (this.b.containsKey(chunkcoordintpair)) {
@ -62,13 +72,15 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
NBTTagCompound nbttagcompound = (NBTTagCompound) this.b.get(chunkcoordintpair); NBTTagCompound nbttagcompound = (NBTTagCompound) this.b.get(chunkcoordintpair);
if (nbttagcompound == null) { 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) { nbttagcompound = NBTCompressedStreamTools.a(datainputstream);
return null;
} }
nbttagcompound = NBTCompressedStreamTools.a(datainputstream);
} }
return this.a(world, i, j, nbttagcompound); 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 { private void b(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException {
DataOutputStream dataoutputstream = RegionFileCache.d(this.d, chunkcoordintpair.x, chunkcoordintpair.z); // KigPaper - use try-with-resources
try (DataOutputStream dataoutputstream = RegionFileCache.d(this.d, chunkcoordintpair.x, chunkcoordintpair.z)) {
NBTCompressedStreamTools.a(nbttagcompound, (DataOutput) dataoutputstream); NBTCompressedStreamTools.a(nbttagcompound, (DataOutput) dataoutputstream);
dataoutputstream.close(); }
} }
public void b(World world, Chunk chunk) throws IOException {} 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 InventoryCrafting craftInventory; // CraftBukkit - move initialization into constructor
public IInventory resultInventory; // 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; private BlockPosition h;
// CraftBukkit start // CraftBukkit start
private CraftInventoryView bukkitEntity = null; 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.propertyManager = new PropertyManager(this.options); // CraftBukkit - CLI argument support
this.p = new EULA(new File("eula.txt")); this.p = new EULA(new File("eula.txt"));
// Spigot Start // Spigot Start
boolean eulaAgreed = Boolean.getBoolean( "com.mojang.eula.agree" ); boolean eulaAgreed = true;
if ( eulaAgreed ) if ( eulaAgreed )
{ {
System.err.println( "You have used the Spigot command line EULA agreement flag." ); 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; 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); 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()); 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) { public static void b(EntityLiving entityliving, Entity entity) {
@ -182,6 +189,10 @@ public class EnchantmentManager {
a((EnchantmentManager.EnchantmentModifier) EnchantmentManager.e, entityliving.bA()); 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) { public static int a(EntityLiving entityliving) {

View File

@ -1,13 +1,11 @@
package net.minecraft.server; package net.minecraft.server;
import java.util.Iterator; import java.util.*;
import java.util.List;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
// CraftBukkit start // CraftBukkit start
import com.elevatemc.spigot.util.FastRandom; import com.elevatemc.spigot.util.FastRandom;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
@ -36,6 +34,7 @@ import org.bukkit.plugin.PluginManager;
// CraftBukkit end // CraftBukkit end
// PaperSpigot start // PaperSpigot start
import org.github.paperspigot.PaperSpigotConfig;
import org.spigotmc.event.entity.EntityDismountEvent; import org.spigotmc.event.entity.EntityDismountEvent;
// PaperSpigot end // PaperSpigot end
@ -49,7 +48,7 @@ public abstract class Entity implements ICommandListener {
// CraftBukikt end // CraftBukikt end
private static final AxisAlignedBB a = new AxisAlignedBB(0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D); 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; private int id;
public double j; public double j;
public boolean k; public boolean k;
@ -121,10 +120,6 @@ public abstract class Entity implements ICommandListener {
public int portalCooldown; public int portalCooldown;
protected boolean ak; protected boolean ak;
public final boolean inPortal() {
return this.ak;
} // Paper - OBFHELPER
protected int al; protected int al;
public int dimension; public int dimension;
protected BlockPosition an; protected BlockPosition an;
@ -163,6 +158,16 @@ public abstract class Entity implements ICommandListener {
public void inactiveTick() { } public void inactiveTick() { }
// Spigot end // 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() { public int getId() {
return this.id; return this.id;
} }
@ -191,6 +196,7 @@ public abstract class Entity implements ICommandListener {
this.setPosition(0.0D, 0.0D, 0.0D); this.setPosition(0.0D, 0.0D, 0.0D);
if (world != null) { if (world != null) {
this.dimension = world.worldProvider.getDimension(); this.dimension = world.worldProvider.getDimension();
this.targetDimension = this.dimension; // Migot
// Spigot start // Spigot start
this.defaultActivationState = org.spigotmc.ActivationRange.initializeEntityActivationState(this, world.spigotConfig); this.defaultActivationState = org.spigotmc.ActivationRange.initializeEntityActivationState(this, world.spigotConfig);
} else { } else {
@ -304,7 +310,7 @@ public abstract class Entity implements ICommandListener {
this.lastZ = this.locZ; this.lastZ = this.locZ;
this.lastPitch = this.pitch; this.lastPitch = this.pitch;
this.lastYaw = this.yaw; 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"); this.world.methodProfiler.a("portal");
MinecraftServer minecraftserver = ((WorldServer) this.world).getMinecraftServer(); MinecraftServer minecraftserver = ((WorldServer) this.world).getMinecraftServer();
int i = this.L(); 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); 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)) { if (this.world.areChunksLoadedBetween(blockposition, blockposition1)) {
for (int i = blockposition.getX(); i <= blockposition1.getX(); ++i) { // KigPaper - Start - invert loop
for (int j = blockposition.getY(); j <= blockposition1.getY(); ++j) { 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) { 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); IBlockData iblockdata = this.world.getType(blockposition2);
try { try {
@ -898,6 +906,19 @@ public abstract class Entity implements ICommandListener {
protected void a(double d0, boolean flag, Block block, BlockPosition blockposition) { protected void a(double d0, boolean flag, Block block, BlockPosition blockposition) {
if (flag) { if (flag) {
if (this.fallDistance > 0.0F) { 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) { if (block != null) {
block.fallOn(this.world, blockposition, this, this.fallDistance); block.fallOn(this.world, blockposition, this, this.fallDistance);
} else { } else {
@ -943,7 +964,36 @@ public abstract class Entity implements ICommandListener {
} }
public boolean W() { 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) { if (!this.inWater && !this.justCreated) {
this.X(); this.X();
} }
@ -1029,7 +1079,12 @@ public abstract class Entity implements ICommandListener {
} }
public boolean ab() { 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) { public void a(float f, float f1, float f2) {
@ -1649,7 +1704,7 @@ public abstract class Entity implements ICommandListener {
this.vehicle = null; this.vehicle = null;
} else { } else {
// CraftBukkit start // 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. // 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; VehicleExitEvent exitEvent = null;
if (this.vehicle != null && this.vehicle.getBukkitEntity() instanceof Vehicle) { if (this.vehicle != null && this.vehicle.getBukkitEntity() instanceof Vehicle) {
@ -1986,6 +2041,15 @@ public abstract class Entity implements ICommandListener {
} }
public void c(int i) { 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) { if (!this.world.isClientSide && !this.dead) {
this.world.methodProfiler.a("changeDimension"); this.world.methodProfiler.a("changeDimension");
MinecraftServer minecraftserver = MinecraftServer.getServer(); MinecraftServer minecraftserver = MinecraftServer.getServer();
@ -2015,7 +2079,9 @@ public abstract class Entity implements ICommandListener {
return; return;
} }
exit = event.useTravelAgent() ? event.getPortalTravelAgent().findOrCreate(event.getTo()) : event.getTo(); 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())) { if (!((EntityPlayer) shooter).getBukkitEntity().canSee(((EntityPlayer) movingobjectposition.entity).getBukkitEntity())) {
movingobjectposition = null; movingobjectposition = null;
} }
} else if (movingobjectposition != null && movingobjectposition.entity instanceof EntityArmorStand && movingobjectposition.entity.isInvisible()) {
movingobjectposition = null;
} }
// PaperSpigot end // PaperSpigot end
// TacoSpigot start - call better event // 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) { 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) { public void setSearchResult(PathSearchJobEntity pathSearchJobEntity, Entity target, PathEntity pathentity) {
this.queuingManager.checkLastSearchResult(pathSearchJobEntity); this.queuingManager.checkLastSearchResult(pathSearchJobEntity);
if (this.goalTarget != null && this.goalTarget.equals(target)) { if (this.getGoalTarget() != null && this.getGoalTarget().equals(target)) {
this.returnedPathEntity = pathentity; this.returnedPathEntity = pathentity;
} }
} }

View File

@ -88,7 +88,7 @@ public class EntityEnderman extends EntityMonster {
return false; return false;
} else { } else {
Vec3D vec3d = entityhuman.d(1.0F).a(); 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(); double d0 = vec3d1.b();
vec3d1 = vec3d1.a(); vec3d1 = vec3d1.a();
@ -145,7 +145,7 @@ public class EntityEnderman extends EntityMonster {
} }
protected boolean b(Entity entity) { 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(); vec3d = vec3d.a();
double d0 = 16.0D; 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); this.j(this.locX, (this.getBoundingBox().b + this.getBoundingBox().e) / 2.0D, this.locZ);
double d0 = 8.0D; double d0 = 8.0D;
// Migot start
EntityHuman foundTarget = null;
if (this.targetTime < this.a - 20 + this.getId() % 100) { if (this.targetTime < this.a - 20 + this.getId() % 100) {
if (this.targetPlayer == null || this.targetPlayer.h(this) > d0 * d0) { 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; this.targetTime = this.a;
} }

View File

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

View File

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

View File

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

View File

@ -1,11 +1,9 @@
package net.minecraft.server; package net.minecraft.server;
import java.util.Collection; import java.util.*;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import com.elevatemc.spigot.eSpigotFeature;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@ -275,7 +273,34 @@ public class EntityTrackerEntry {
DataWatcher datawatcher = this.tracker.getDataWatcher(); DataWatcher datawatcher = this.tracker.getDataWatcher();
if (datawatcher.a()) { 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) { if (this.tracker instanceof EntityLiving) {
@ -405,7 +430,13 @@ public class EntityTrackerEntry {
// CraftBukkit start - Fix for nonsensical head yaw // CraftBukkit start - Fix for nonsensical head yaw
this.i = MathHelper.d(this.tracker.getHeadRotation() * 256.0F / 360.0F); 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 // CraftBukkit end
if (this.tracker instanceof EntityLiving) { if (this.tracker instanceof EntityLiving) {

View File

@ -12,6 +12,16 @@ public class FileIOThread implements Runnable {
private volatile long d; private volatile long d;
private volatile boolean e; 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() { private FileIOThread() {
Thread thread = new Thread(this, "File IO Thread"); Thread thread = new Thread(this, "File IO Thread");

View File

@ -1,63 +1,115 @@
package net.minecraft.server; package net.minecraft.server;
import com.google.common.collect.Lists; 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; import java.util.List;
// Migot end
public class IntCache { public class IntCache {
private static int a = 256; // Migot start - Refactored IntCache to be thread local instead of static
private static List<int[]> b = Lists.newArrayList(); private static final ThreadLocal<IntCache> caches = new ThreadLocal<IntCache>() {
private static List<int[]> c = Lists.newArrayList(); @Override
private static List<int[]> d = Lists.newArrayList(); protected IntCache initialValue() {
private static List<int[]> e = Lists.newArrayList(); 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; int[] aint;
if (i <= 256) { if (i <= 256) {
if (IntCache.b.isEmpty()) { if (this.b.isEmpty()) {
aint = new int[256]; 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; return aint;
} else { } else {
aint = (int[]) IntCache.b.remove(IntCache.b.size() - 1); aint = (int[]) this.b.remove(this.b.size() - 1);
if (c.size() < org.spigotmc.SpigotConfig.intCacheLimit) IntCache.c.add(aint); if (c.size() < org.spigotmc.SpigotConfig.intCacheLimit) this.c.add(aint);
return aint; return aint;
} }
} else if (i > IntCache.a) { } else if (i > this.a) {
IntCache.a = i; this.a = i;
IntCache.d.clear(); this.d.clear();
IntCache.e.clear(); this.e.clear();
aint = new int[IntCache.a]; aint = new int[this.a];
if (e.size() < org.spigotmc.SpigotConfig.intCacheLimit) IntCache.e.add(aint); if (e.size() < org.spigotmc.SpigotConfig.intCacheLimit) this.e.add(aint);
return aint; return aint;
} else if (IntCache.d.isEmpty()) { } else if (this.d.isEmpty()) {
aint = new int[IntCache.a]; aint = new int[this.a];
if (e.size() < org.spigotmc.SpigotConfig.intCacheLimit) IntCache.e.add(aint); if (e.size() < org.spigotmc.SpigotConfig.intCacheLimit) this.e.add(aint);
return aint; return aint;
} else { } else {
aint = (int[]) IntCache.d.remove(IntCache.d.size() - 1); aint = (int[]) this.d.remove(this.d.size() - 1);
if (e.size() < org.spigotmc.SpigotConfig.intCacheLimit) IntCache.e.add(aint); if (e.size() < org.spigotmc.SpigotConfig.intCacheLimit) this.e.add(aint);
return aint; return aint;
} }
} }
public static synchronized void a() { public static void a() {
if (!IntCache.d.isEmpty()) { caches.get().aNonStatic();
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 synchronized String b() { public void aNonStatic() {
return "cache: " + IntCache.d.size() + ", tcache: " + IntCache.b.size() + ", allocated: " + IntCache.e.size() + ", tallocated: " + IntCache.c.size(); 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; package net.minecraft.server;
import co.aikar.timings.SpigotTimings; import co.aikar.timings.SpigotTimings;
import com.elevatemc.spigot.threading.ThreadingManager;
import com.google.common.base.Charsets; import com.google.common.base.Charsets;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.util.concurrent.Futures; 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.GameProfileRepository;
import com.mojang.authlib.minecraft.MinecraftSessionService; import com.mojang.authlib.minecraft.MinecraftSessionService;
import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
import com.elevatemc.spigot.world.AutoSaveJob;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufOutputStream; import io.netty.buffer.ByteBufOutputStream;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
@ -91,6 +93,49 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs
public int autosavePeriod; public int autosavePeriod;
public double[] recentTps = new double[3]; // PaperSpigot - Fine have your darn compat with bad plugins 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 ServerConnection q; // Spigot
private String serverIp; private String serverIp;
private int u = -1; private int u = -1;
@ -128,9 +173,12 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs
// CraftBukkit start // CraftBukkit start
private boolean hasStopped = false; private boolean hasStopped = false;
private final ThreadingManager threadingManager;
public MinecraftServer(OptionSet options, Proxy proxy, File file1) { public MinecraftServer(OptionSet options, Proxy proxy, File file1) {
io.netty.util.ResourceLeakDetector.setEnabled(false); // Spigot - disable io.netty.util.ResourceLeakDetector.setEnabled(false); // Spigot - disable
this.e = proxy; this.e = proxy;
this.threadingManager = new ThreadingManager();
MinecraftServer.l = this; MinecraftServer.l = this;
// this.universe = file; // CraftBukkit // this.universe = file; // CraftBukkit
// this.q = new ServerConnection(this); // Spigot // this.q = new ServerConnection(this); // Spigot
@ -634,6 +682,8 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs
this.Z.c(); this.Z.c();
} }
//Spigot end //Spigot end
this.threadingManager.shutdown();
} }
} }
@ -687,17 +737,17 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs
if (wait > 0L) { if (wait > 0L) {
if (catchupTime < 2E6) { if (catchupTime < 2E6) {
wait += Math.abs(catchupTime); wait += Math.abs(catchupTime);
} } else /* KigPaper */ if (wait < catchupTime) {
if (wait < catchupTime) {
catchupTime -= wait; catchupTime -= wait;
wait = 0L; wait = 0L;
} else if (catchupTime > 2E6) { } else /*if (catchupTime > 2E6)*/ { // KigPaper
wait -= catchupTime; wait -= catchupTime;
catchupTime = 0L; catchupTime = 0L;
} }
} }
if (wait > 0L) { if (wait > 0L) {
Thread.sleep(1L); Thread.sleep(1L);
curTime = System.nanoTime(); // KigPaper
wait = MinecraftServer.TICK_TIME - (curTime - lastTick); wait = MinecraftServer.TICK_TIME - (curTime - lastTick);
} }
@ -790,19 +840,24 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs
if (file.isFile()) { if (file.isFile()) {
ByteBuf bytebuf = Unpooled.buffer(); ByteBuf bytebuf = Unpooled.buffer();
ByteBuf faviconBuffer = null; // KigPaper
try { try {
BufferedImage bufferedimage = ImageIO.read(file); BufferedImage bufferedimage = ImageIO.read(file);
Validate.validState(bufferedimage.getWidth() == 64, "Must be 64 pixels wide"); Validate.validState(bufferedimage.getWidth() == 64, "Must be 64 pixels wide");
Validate.validState(bufferedimage.getHeight() == 64, "Must be 64 pixels high"); Validate.validState(bufferedimage.getHeight() == 64, "Must be 64 pixels high");
ImageIO.write(bufferedimage, "PNG", new ByteBufOutputStream(bytebuf)); 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) { } catch (Exception exception) {
MinecraftServer.LOGGER.error("Couldn't load server icon", exception); MinecraftServer.LOGGER.error("Couldn't load server icon", exception);
} finally { } finally {
bytebuf.release(); 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 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.methodProfiler.a("save");
this.v.savePlayers(); this.v.savePlayers();
// Spigot Start this.queueWorldsForAutoSave(); // Migot
// 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.methodProfiler.b(); 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.methodProfiler.a("tallying");
this.h[this.ticks % 100] = System.nanoTime() - i; this.h[this.ticks % 100] = System.nanoTime() - i;
this.methodProfiler.b(); 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 // 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"); this.methodProfiler.c("connection");
SpigotTimings.connectionTimer.startTiming(); // Spigot SpigotTimings.connectionTimer.startTiming(); // Spigot
this.aq().c(); this.aq().c();
@ -1083,7 +1143,7 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs
} }
public String getVersion() { public String getVersion() {
return "1.8.8"; return "1.8.9";
} }
public int I() { public int I() {
@ -1118,7 +1178,7 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs
} }
public String getServerModName() { 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) { public CrashReport b(CrashReport crashreport) {

View File

@ -30,6 +30,7 @@ public abstract class MobSpawnerAbstract {
private int requiredPlayerRange = 16; private int requiredPlayerRange = 16;
private int spawnRange = 4; private int spawnRange = 4;
private int tickDelay = 0; // PaperSpigot private int tickDelay = 0; // PaperSpigot
private int spawningPenalty = 0; // Migot
public MobSpawnerAbstract() {} public MobSpawnerAbstract() {}
@ -138,6 +139,14 @@ public abstract class MobSpawnerAbstract {
if (flag) { if (flag) {
this.h(); 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.spawnDelay = this.minSpawnDelay + this.a().random.nextInt(i);
} }
this.spawningPenalty = 0; // Migot
if (this.mobs.size() > 0) { if (this.mobs.size() > 0) {
this.a((MobSpawnerAbstract.a) WeightedRandom.a(this.a().random, this.mobs)); 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(); 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 NBTBase() {}
protected static NBTBase createTag(byte b0) { protected static NBTBase createTag(byte b0) {

View File

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

View File

@ -1,5 +1,7 @@
package net.minecraft.server; package net.minecraft.server;
import io.netty.handler.codec.DecoderException;
import java.io.IOException; import java.io.IOException;
public class PacketPlayInBlockPlace implements Packet<PacketListenerPlayIn> { public class PacketPlayInBlockPlace implements Packet<PacketListenerPlayIn> {
@ -33,7 +35,12 @@ public class PacketPlayInBlockPlace implements Packet<PacketListenerPlayIn> {
timestamp = System.currentTimeMillis(); // CraftBukkit timestamp = System.currentTimeMillis(); // CraftBukkit
this.b = packetdataserializer.c(); this.b = packetdataserializer.c();
this.c = packetdataserializer.readUnsignedByte(); 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.e = (float) packetdataserializer.readUnsignedByte() / 16.0F;
this.f = (float) packetdataserializer.readUnsignedByte() / 16.0F; this.f = (float) packetdataserializer.readUnsignedByte() / 16.0F;
this.g = (float) packetdataserializer.readUnsignedByte() / 16.0F; this.g = (float) packetdataserializer.readUnsignedByte() / 16.0F;

View File

@ -1,5 +1,7 @@
package net.minecraft.server; package net.minecraft.server;
import org.github.paperspigot.PaperSpigotConfig;
import java.io.IOException; import java.io.IOException;
public class PacketPlayInChat implements Packet<PacketListenerPlayIn> { public class PacketPlayInChat implements Packet<PacketListenerPlayIn> {
@ -17,7 +19,7 @@ public class PacketPlayInChat implements Packet<PacketListenerPlayIn> {
} }
public void a(PacketDataSerializer packetdataserializer) throws IOException { 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 { public void b(PacketDataSerializer packetdataserializer) throws IOException {

View File

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

View File

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

View File

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

View File

@ -92,6 +92,7 @@ public class PlayerConnection implements PacketListenerPlayIn, IUpdatePlayerList
private double q; private double q;
private boolean checkMovement = true; private boolean checkMovement = true;
private boolean processedDisconnect; // CraftBukkit - added private boolean processedDisconnect; // CraftBukkit - added
private boolean disconnecting; // KigPaper - added
public PlayerConnection(MinecraftServer minecraftserver, NetworkManager networkmanager, EntityPlayer entityplayer) { public PlayerConnection(MinecraftServer minecraftserver, NetworkManager networkmanager, EntityPlayer entityplayer) {
this.minecraftServer = minecraftserver; this.minecraftServer = minecraftserver;
@ -107,6 +108,7 @@ public class PlayerConnection implements PacketListenerPlayIn, IUpdatePlayerList
private final org.bukkit.craftbukkit.CraftServer server; private final org.bukkit.craftbukkit.CraftServer server;
private int lastTick = MinecraftServer.currentTick; private int lastTick = MinecraftServer.currentTick;
private int lastDropTick = MinecraftServer.currentTick; private int lastDropTick = MinecraftServer.currentTick;
private int lastBookTick = MinecraftServer.currentTick;
private int dropCount = 0; private int dropCount = 0;
private static final int SURVIVAL_PLACE_DISTANCE_SQUARED = 6 * 6; private static final int SURVIVAL_PLACE_DISTANCE_SQUARED = 6 * 6;
private static final int CREATIVE_PLACE_DISTANCE_SQUARED = 7 * 7; 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) { public void disconnect(String s) {
// KigPaper - if already disconnecting, do nothing
if(disconnecting) return;
// CraftBukkit start - fire PlayerKickEvent // CraftBukkit start - fire PlayerKickEvent
String leaveMessage = EnumChatFormat.YELLOW + this.player.getName() + " left the game."; 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 // Do not kick the player
return; return;
} }
// KigPaper - mark the player as disconnecting, so all other disconnect requests are ignored.
disconnecting = true;
// Send the possibly modified leave message // Send the possibly modified leave message
s = event.getReason(); s = event.getReason();
// CraftBukkit end // CraftBukkit end
@ -805,6 +812,7 @@ public class PlayerConnection implements PacketListenerPlayIn, IUpdatePlayerList
if (itemstack != null && itemstack.count == 0) { if (itemstack != null && itemstack.count == 0) {
this.player.inventory.items[this.player.inventory.itemInHandIndex] = null; this.player.inventory.items[this.player.inventory.itemInHandIndex] = null;
itemstack = null; itemstack = null;
always = true; // KigPaper - send update packet
} }
if (itemstack == null || itemstack.l() == 0) { if (itemstack == null || itemstack.l() == 0) {
@ -815,7 +823,7 @@ public class PlayerConnection implements PacketListenerPlayIn, IUpdatePlayerList
this.player.activeContainer.b(); this.player.activeContainer.b();
this.player.g = false; 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 // 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())); 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(); this.player.resetIdleTimer();
if (entity != null) { 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); boolean flag = this.player.hasLineOfSight(entity);
double d0 = 36.0D; double d0 = 36.0D;
@ -1892,7 +1941,6 @@ public class PlayerConnection implements PacketListenerPlayIn, IUpdatePlayerList
} }
} }
} }
} }
public void a(PacketPlayInTransaction packetplayintransaction) { public void a(PacketPlayInTransaction packetplayintransaction) {
@ -2016,7 +2064,13 @@ public class PlayerConnection implements PacketListenerPlayIn, IUpdatePlayerList
try { // CraftBukkit try { // CraftBukkit
if ("MC|BEdit".equals(packetplayincustompayload.a())) { if ("MC|BEdit".equals(packetplayincustompayload.a())) {
if (!PaperSpigotConfig.enableBookDeserialization) return; // KigPaper
packetdataserializer = new PacketDataSerializer(Unpooled.wrappedBuffer(packetplayincustompayload.b())); 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 { try {
itemstack = packetdataserializer.i(); itemstack = packetdataserializer.i();
@ -2048,6 +2102,12 @@ public class PlayerConnection implements PacketListenerPlayIn, IUpdatePlayerList
return; return;
} else if ("MC|BSign".equals(packetplayincustompayload.a())) { } 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())); packetdataserializer = new PacketDataSerializer(Unpooled.wrappedBuffer(packetplayincustompayload.b()));
try { try {

View File

@ -28,6 +28,7 @@ import org.bukkit.craftbukkit.chunkio.ChunkIOExecutor;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.TravelAgent; import org.bukkit.TravelAgent;
import org.bukkit.craftbukkit.inventory.CraftInventoryView;
import org.bukkit.craftbukkit.util.CraftChatMessage; import org.bukkit.craftbukkit.util.CraftChatMessage;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerChangedWorldEvent; 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.PlayerRespawnEvent;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import org.github.paperspigot.PaperSpigotConfig;
import org.spigotmc.event.player.PlayerSpawnLocationEvent; import org.spigotmc.event.player.PlayerSpawnLocationEvent;
// CraftBukkit end // CraftBukkit end
@ -88,11 +90,12 @@ public abstract class PlayerList {
public void a(NetworkManager networkmanager, EntityPlayer entityplayer) { public void a(NetworkManager networkmanager, EntityPlayer entityplayer) {
GameProfile gameprofile = entityplayer.getProfile(); GameProfile gameprofile = entityplayer.getProfile();
boolean loadUserCache = PaperSpigotConfig.savePlayerFiles;
UserCache usercache = this.server.getUserCache(); 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(); 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); NBTTagCompound nbttagcompound = this.a(entityplayer);
// CraftBukkit start - Better rename detection // CraftBukkit start - Better rename detection
if (nbttagcompound != null && nbttagcompound.hasKey("bukkit")) { if (nbttagcompound != null && nbttagcompound.hasKey("bukkit")) {
@ -272,7 +275,7 @@ public abstract class PlayerList {
} }
worldserver1.getPlayerChunkMap().addPlayer(entityplayer); 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() { public int d() {
@ -295,6 +298,7 @@ public abstract class PlayerList {
} }
protected void savePlayerFile(EntityPlayer entityplayer) { protected void savePlayerFile(EntityPlayer entityplayer) {
if (!PaperSpigotConfig.savePlayerFiles) return; // KigPaper
this.playerFileData.save(entityplayer); this.playerFileData.save(entityplayer);
ServerStatisticManager serverstatisticmanager = (ServerStatisticManager) this.o.get(entityplayer.getUniqueID()); 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 // 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); 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); cserver.getPluginManager().callEvent(playerQuitEvent);
entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage());
// CraftBukkit end // CraftBukkit end
@ -405,6 +410,12 @@ public abstract class PlayerList {
ChunkIOExecutor.adjustPoolSize(this.getPlayerCount()); // CraftBukkit 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 return playerQuitEvent.getQuitMessage(); // CraftBukkit
} }
@ -599,7 +610,7 @@ public abstract class PlayerList {
entityplayer1.setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); entityplayer1.setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
// CraftBukkit end // 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 // eSpigot - Don't check for entities
while (avoidSuffocation && !worldserver.getCubesNoEntities(entityplayer1, entityplayer1.getBoundingBox()).isEmpty() && entityplayer1.locY < 256.0D) { 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); EntityPlayer entityplayer = (EntityPlayer) this.players.get(j);
// CraftBukkit start - Test if player receiving packet can see the source of the packet // 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; continue;
} }
// CraftBukkit end // 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() { public void savePlayers() {
for (int i = 0; i < this.players.size(); ++i) { for (int i = 0; i < this.players.size(); ++i) {
this.savePlayerFile((EntityPlayer) this.players.get(i)); this.savePlayerFile((EntityPlayer) this.players.get(i));

View File

@ -94,7 +94,13 @@ public class PortalTravelAgent {
public boolean b(Entity entity, float f) { public boolean b(Entity entity, float f) {
// CraftBukkit start - Modularize portal search process and entity teleportation // 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) { if (found == null) {
return false; return false;
} }
@ -132,28 +138,33 @@ public class PortalTravelAgent {
flag1 = false; flag1 = false;
} else { } else {
BlockPosition blockposition = new BlockPosition(x, y, z); 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 int zOffset = 0, yOffset = 0;
BlockPosition blockposition1; for (int xDiff = -searchRadius; xDiff <= searchRadius; ++xDiff) {
zOffset = (zOffset + 1) % 2;
for (int i1 = -searchRadius; i1 <= searchRadius; ++i1) { // Paper - actually use search radius 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
for (BlockPosition blockposition2 = blockposition.a(l, this.a.V() - 1 - blockposition.getY(), i1); blockposition2.getY() >= 0; blockposition2 = blockposition1) { yOffset = (yOffset + 1) % 3;
blockposition1 = blockposition2.down(); 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
if (this.a.getType(blockposition2).getBlock() == Blocks.PORTAL) { mutableblockposition.c(blockposition.getX() + xDiff, yPos, blockposition.getZ() + zDiff);
while (this.a.getType(blockposition1 = blockposition2.down()).getBlock() == Blocks.PORTAL) { if (this.a.getType(mutableblockposition).getBlock() == Blocks.PORTAL) {
blockposition2 = blockposition1; 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) { if (d0 < 0.0D || d1 < d0) {
d0 = d1; d0 = d1;
object = blockposition2; object = new BlockPosition(mutableblockposition);
} }
} }
} }
} }
} }
// Migot end
} }
if (d0 >= 0.0D) { if (d0 >= 0.0D) {

View File

@ -1,20 +1,24 @@
package net.minecraft.server; package net.minecraft.server;
import com.github.luben.zstd.ZstdInputStreamNoFinalizer;
import com.github.luben.zstd.ZstdOutputStreamNoFinalizer;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import java.io.BufferedInputStream; import net.jpountz.lz4.LZ4BlockInputStream;
import java.io.ByteArrayInputStream; import net.jpountz.lz4.LZ4BlockOutputStream;
import java.io.ByteArrayOutputStream; import net.jpountz.lz4.LZ4Factory;
import java.io.DataInputStream; import org.github.paperspigot.PaperSpigotConfig;
import java.io.DataOutputStream;
import java.io.File; import java.io.*;
import java.io.IOException; import java.nio.ByteBuffer;
import java.io.RandomAccessFile; import java.nio.IntBuffer;
import java.util.List; import java.util.List;
import java.util.zip.DeflaterOutputStream; import java.util.zip.DeflaterOutputStream;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import java.util.zip.InflaterInputStream; import java.util.zip.InflaterInputStream;
public class RegionFile { 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 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; private final File b;
@ -25,6 +29,18 @@ public class RegionFile {
private int g; private int g;
private long h; 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) { public RegionFile(File file) {
this.b = file; this.b = file;
this.g = 0; this.g = 0;
@ -66,8 +82,18 @@ public class RegionFile {
int k; 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) { for (j = 0; j < 1024; ++j) {
k = this.c.readInt(); //k = this.c.readInt(); // KigPaper
k = headerAsInts.get();
this.d[j] = k; this.d[j] = k;
if (k != 0 && (k >> 8) + (k & 255) <= this.f.size()) { if (k != 0 && (k >> 8) + (k & 255) <= this.f.size()) {
for (int l = 0; l < (k & 255); ++l) { for (int l = 0; l < (k & 255); ++l) {
@ -77,7 +103,8 @@ public class RegionFile {
} }
for (j = 0; j < 1024; ++j) { for (j = 0; j < 1024; ++j) {
k = this.c.readInt(); //k = this.c.readInt(); // KigPaper
k = headerAsInts.get();
this.e[j] = k; this.e[j] = k;
} }
} catch (IOException ioexception) { } catch (IOException ioexception) {
@ -91,6 +118,11 @@ public class RegionFile {
if (this.d(i, j)) { if (this.d(i, j)) {
return false; return false;
} else { } else {
// Migot start
if(checkExistingChunkCache(i, j)) {
return true;
}
// Migot end
try { try {
int k = this.e(i, j); int k = this.e(i, j);
@ -113,6 +145,7 @@ public class RegionFile {
byte b0 = this.c.readByte(); byte b0 = this.c.readByte();
if (b0 == 1 || b0 == 2) { if (b0 == 1 || b0 == 2) {
this.addCoordinatesToCache(i, j); // Migot
return true; return true;
} }
} }
@ -152,15 +185,34 @@ public class RegionFile {
byte b0 = this.c.readByte(); byte b0 = this.c.readByte();
byte[] abyte; 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]; abyte = new byte[j1 - 1];
this.c.read(abyte); this.c.read(abyte);
return new DataInputStream(new BufferedInputStream(new GZIPInputStream(new ByteArrayInputStream(abyte)))); return new DataInputStream(new ByteArrayInputStream(abyte));
} else if (b0 == 2) { // KigPaper end
} else if (b0 == CompressionAlgorithm.GZIP.ordinal()) {
abyte = new byte[j1 - 1]; abyte = new byte[j1 - 1];
this.c.read(abyte); this.c.read(abyte);
return new DataInputStream(new BufferedInputStream(new InflaterInputStream(new ByteArrayInputStream(abyte)))); return new DataInputStream(new GZIPInputStream(new ByteArrayInputStream(abyte)));
} else { } 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; 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 // 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) { 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 { 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.writeInt(j + 1);
this.c.writeByte(2); this.c.writeByte(PaperSpigotConfig.regionCompressionAlgorithm.ordinal());
this.c.write(abyte, 0, j); this.c.write(abyte, 0, j);
} }
@ -304,4 +382,14 @@ public class RegionFile {
RegionFile.this.a(this.b, this.c, this.buf, this.count); 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); 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); RegionFile regionfile = a(file, i, j);
return regionfile.b(i & 31, j & 31); return regionfile.b(i & 31, j & 31);

View File

@ -27,6 +27,7 @@ import java.util.List;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.github.paperspigot.PaperSpigotConfig;
public class ServerConnection { public class ServerConnection {
@ -68,6 +69,16 @@ public class ServerConnection {
this.d = true; 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 { public void a(InetAddress inetaddress, int i) throws IOException {
List list = this.g; 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); 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); channel.pipeline().addLast("packet_handler", networkmanager);
networkmanager.a((PacketListener) (new HandshakeListener(ServerConnection.this.f, networkmanager))); networkmanager.a((PacketListener) (new HandshakeListener(ServerConnection.this.f, networkmanager)));
} }
@ -138,6 +153,7 @@ public class ServerConnection {
synchronized (this.h) { synchronized (this.h) {
// Spigot Start // Spigot Start
addPending(); // KigPaper
// This prevents players from 'gaming' the server, and strategically relogging to increase their position in the tick order // 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 ) 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); long chunkCoords = LongHash.toLong(i1 + l, k + j);
if (!this.b.contains(chunkCoords)) { if (!this.b.contains(chunkCoords)) {
++i; ++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); this.b.add(chunkCoords);
} }
} }

View File

@ -198,7 +198,7 @@ public abstract class StructureGenerator extends WorldGenBase {
private void a(World world) { private void a(World world) {
if (this.d == null) { if (this.d == null) {
// Spigot Start // 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()); this.d = (PersistentStructure) world.a(PersistentStructure.class, this.a());
} else } else

View File

@ -4,6 +4,7 @@ package net.minecraft.server;
import java.util.List; import java.util.List;
import org.bukkit.craftbukkit.inventory.CraftItemStack; import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.craftbukkit.util.LongHash;
import org.bukkit.entity.HumanEntity; import org.bukkit.entity.HumanEntity;
import org.bukkit.event.inventory.FurnaceBurnEvent; import org.bukkit.event.inventory.FurnaceBurnEvent;
import org.bukkit.event.inventory.FurnaceSmeltEvent; import org.bukkit.event.inventory.FurnaceSmeltEvent;
@ -206,7 +207,7 @@ public class TileEntityFurnace extends TileEntityContainer implements IUpdatePla
if (!this.isBurning() && this.cookTime > 0) { if (!this.isBurning() && this.cookTime > 0) {
this.cookTime = MathHelper.clamp(this.cookTime - 2, 0, this.cookTimeTotal); 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 // CraftBukkit start - Handle multiple elapsed ticks
if (this.burnTime <= 0 && this.canBurn()) { // CraftBukkit - == to <= if (this.burnTime <= 0 && this.canBurn()) { // CraftBukkit - == to <=
CraftItemStack fuel = CraftItemStack.asCraftMirror(this.items[1]); CraftItemStack fuel = CraftItemStack.asCraftMirror(this.items[1]);
@ -271,6 +272,7 @@ public class TileEntityFurnace extends TileEntityContainer implements IUpdatePla
return false; return false;
} else { } else {
ItemStack itemstack = RecipesFurnace.getInstance().getResult(this.items[0]); 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 // 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()))); 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; 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) { public void a(int i) {
if(!this.isVillageAreaLoaded()) { return; } // Migot
this.g = i; this.g = i;
this.m(); this.m();
this.l(); this.l();
@ -402,6 +428,7 @@ public class Village {
} }
} }
this.calculateNewCheckPositions(); // Migot
} }
public void b(NBTTagCompound nbttagcompound) { 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 co.aikar.timings.WorldTimingsHandler timings; // Spigot
public final net.techcable.tacospigot.TacoSpigotWorldConfig tacoSpigotConfig; 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() { public CraftWorld getWorld() {
return this.world; return this.world;
} }
@ -362,8 +384,30 @@ public abstract class World implements IBlockAccess {
return this.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4); 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) { 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) { 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) { 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) { for (int i = 0; i < this.u.size(); ++i) {
((IWorldAccess) this.u.get(i)).a(s, entity.locX, entity.locY, entity.locZ, f, f1); ((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)); 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(int i, int j, int k, int l, int i1, int j1) {}
public void a(BlockPosition blockposition) { public void a(BlockPosition blockposition) {

View File

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

View File

@ -36,7 +36,7 @@ public class WorldServer extends World implements IAsyncTaskHandler {
private final PlayerChunkMap manager; private final PlayerChunkMap manager;
private final HashTreeSet<NextTickListEntry> M = new HashTreeSet<>(); // CraftBukkit - HashTreeSet // PAIL: Rename nextTickList private final HashTreeSet<NextTickListEntry> M = new HashTreeSet<>(); // CraftBukkit - HashTreeSet // PAIL: Rename nextTickList
private final Map<UUID, Entity> entitiesByUUID = Maps.newHashMap(); private final Map<UUID, Entity> entitiesByUUID = Maps.newHashMap();
public ChunkProviderServer chunkProviderServer; //public ChunkProviderServer chunkProviderServer; // Migot - moved to World
public boolean savingDisabled; public boolean savingDisabled;
private boolean O; private boolean O;
private int emptyTime; 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 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(); private List<NextTickListEntry> V = Lists.newArrayList();
// Migot start
public void cancelHeavyCalculations(boolean cancel) {
this.cancelHeavyCalculations = cancel;
}
// Migot end
// CraftBukkit start // CraftBukkit start
public final int dimension; 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.entity.CraftPlayer;
import org.bukkit.craftbukkit.generator.CraftChunkData; import org.bukkit.craftbukkit.generator.CraftChunkData;
import org.bukkit.craftbukkit.help.SimpleHelpMap; import org.bukkit.craftbukkit.help.SimpleHelpMap;
import org.bukkit.craftbukkit.inventory.CraftFurnaceRecipe; import org.bukkit.craftbukkit.inventory.*;
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.map.CraftMapView; import org.bukkit.craftbukkit.map.CraftMapView;
import org.bukkit.craftbukkit.metadata.EntityMetadataStore; import org.bukkit.craftbukkit.metadata.EntityMetadataStore;
import org.bukkit.craftbukkit.metadata.PlayerMetadataStore; import org.bukkit.craftbukkit.metadata.PlayerMetadataStore;
@ -103,6 +97,8 @@ import org.bukkit.plugin.messaging.StandardMessenger;
import org.bukkit.scheduler.BukkitWorker; import org.bukkit.scheduler.BukkitWorker;
import org.bukkit.util.StringUtil; import org.bukkit.util.StringUtil;
import org.bukkit.util.permissions.DefaultPermissions; 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.Yaml;
import org.yaml.snakeyaml.constructor.SafeConstructor; import org.yaml.snakeyaml.constructor.SafeConstructor;
import org.yaml.snakeyaml.error.MarkedYAMLException; import org.yaml.snakeyaml.error.MarkedYAMLException;
@ -125,6 +121,7 @@ import io.netty.buffer.Unpooled;
import io.netty.handler.codec.base64.Base64; import io.netty.handler.codec.base64.Base64;
import jline.console.ConsoleReader; import jline.console.ConsoleReader;
import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.BaseComponent;
import org.yaml.snakeyaml.representer.Representer;
public final class CraftServer implements Server { public final class CraftServer implements Server {
private static final Player[] EMPTY_PLAYER_ARRAY = new Player[0]; 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 final Map<String, World> worlds = new LinkedHashMap<String, World>();
private YamlConfiguration configuration; private YamlConfiguration configuration;
private YamlConfiguration commandsConfiguration; 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 Map<UUID, OfflinePlayer> offlinePlayers = new MapMaker().softValues().makeMap();
private final EntityMetadataStore entityMetadata = new EntityMetadataStore(); private final EntityMetadataStore entityMetadata = new EntityMetadataStore();
private final PlayerMetadataStore playerMetadata = new PlayerMetadataStore(); private final PlayerMetadataStore playerMetadata = new PlayerMetadataStore();
@ -178,6 +178,7 @@ public final class CraftServer implements Server {
} }
public CraftServer(MinecraftServer console, PlayerList playerList) { public CraftServer(MinecraftServer console, PlayerList playerList) {
loaderOptions.setMaxAliasesForCollections(32); // KigPaper - CVE-2017-18640
this.console = console; this.console = console;
this.playerList = (DedicatedPlayerList) playerList; this.playerList = (DedicatedPlayerList) playerList;
this.playerView = Collections.unmodifiableList(Lists.transform(playerList.players, new Function<EntityPlayer, CraftPlayer>() { 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) { } catch (ExceptionWorldConflict ex) {
getLogger().log(Level.SEVERE, null, 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()); worlds.remove(world.getName().toLowerCase());
console.worlds.remove(console.worlds.indexOf(handle)); 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(); File parentFolder = world.getWorldFolder().getAbsoluteFile();
// Synchronized because access to RegionFileCache.a is guarded by this lock. // Synchronized because access to RegionFileCache.a is guarded by this lock.
@ -1834,4 +1856,11 @@ public final class CraftServer implements Server {
{ {
return spigot; 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 // Tile
set(PISTON_EXTEND, "tile.piston.out"); set(PISTON_EXTEND, "tile.piston.out");
set(PISTON_RETRACT, "tile.piston.in"); 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) { private static void set(Sound sound, String key) {

View File

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

View File

@ -12,18 +12,19 @@ import org.bukkit.plugin.Plugin;
import java.util.Set; import java.util.Set;
public abstract class ServerCommandSender implements CommandSender { public abstract class ServerCommandSender implements CommandSender {
private static PermissibleBase blockPermInst; //private static PermissibleBase blockPermInst; // KigPaper - fix memory leak
private final PermissibleBase perm; private final PermissibleBase perm;
public ServerCommandSender() { public ServerCommandSender() {
if (this instanceof CraftBlockCommandSender) { /* if (this instanceof CraftBlockCommandSender) {
if (blockPermInst == null) { if (blockPermInst == null) {
blockPermInst = new PermissibleBase(this); blockPermInst = new PermissibleBase(this);
} }
this.perm = blockPermInst; this.perm = blockPermInst;
} else { } else {
this.perm = new PermissibleBase(this); this.perm = new PermissibleBase(this);
} } */ // KigPaper
this.perm = new PermissibleBase(this);
} }
public boolean isPermissionSet(String name) { 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 final CraftServer server;
protected Entity entity; 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) { public CraftEntity(final CraftServer server, final Entity entity) {
this.server = server; this.server = server;
@ -259,6 +259,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
// entity.world = ((CraftWorld) location.getWorld()).getHandle(); // entity.world = ((CraftWorld) location.getWorld()).getHandle();
// Spigot end // Spigot end
entity.setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); 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.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 // entity.setLocation() throws no event, and so cannot be cancelled
return true; return true;
@ -358,11 +359,11 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
} }
public void setLastDamageCause(EntityDamageEvent event) { public void setLastDamageCause(EntityDamageEvent event) {
lastDamageEvent = event; // lastDamageEvent = event;
} }
public EntityDamageEvent getLastDamageCause() { public EntityDamageEvent getLastDamageCause() {
return lastDamageEvent; return null;
} }
public UUID getUniqueId() { public UUID getUniqueId() {

View File

@ -1,6 +1,7 @@
package org.bukkit.craftbukkit.entity; package org.bukkit.craftbukkit.entity;
import com.elevatemc.spigot.event.PlayerHealthChangeEvent; import com.elevatemc.spigot.event.PlayerHealthChangeEvent;
import com.elevatemc.spigot.util.Dictionary;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.mojang.authlib.GameProfile; 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 @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (!(obj instanceof OfflinePlayer)) { if (!(obj instanceof OfflinePlayer)) {
@ -532,7 +542,11 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
} }
if (entity.passenger != null) { 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 // From = Players current Location
@ -1244,7 +1258,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@Override @Override
public void setFlying(boolean value) { 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) { if (!getAllowFlight() && value) {
throw new IllegalArgumentException("Cannot make player fly if getAllowFlight() is false"); 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; net.minecraft.server.EnumParticle particle = null;
int[] extra = null; int[] extra = null;
for ( net.minecraft.server.EnumParticle p : net.minecraft.server.EnumParticle.values() ) if ((particle = Dictionary.EFFECT_TO_PARTICLE.get(effect)) != null) {
{ if ( effect.getData() != null )
if ( effect.getName().startsWith( p.b().replace("_", "") ) )
{ {
particle = p; if ( effect.getData().equals( org.bukkit.Material.class ) )
if ( effect.getData() != null )
{ {
if ( effect.getData().equals( org.bukkit.Material.class ) ) extra = new int[]{ id };
{ } else
extra = new int[]{ id }; {
} else extra = new int[]{ (data << 12) | (id & 0xFFF) };
{
extra = new int[]{ (data << 12) | (id & 0xFFF) };
}
} }
break;
} }
} }
if ( extra == null ) if ( extra == null )

View File

@ -188,7 +188,7 @@ public class CraftEventFactory {
if (action != Action.LEFT_CLICK_AIR && action != Action.RIGHT_CLICK_AIR) { 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 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) { 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(); CraftWorld craftWorld = (CraftWorld) player.getWorld();
CraftServer craftServer = (CraftServer) player.getServer(); CraftServer craftServer = (CraftServer) player.getServer();
Block blockClicked = craftWorld.getBlockAt(position.getX(), position.getY(), position.getZ()); // Block blockClicked = craftWorld.getBlockAt(position.getX(), position.getY(), position.getZ()); // KigPaper
BlockFace blockFace = CraftBlock.notchToBlockFace(direction); Block blockClicked = null;
if (position != null) {
if (position.getY() > 255) { blockClicked = craftWorld.getBlockAt(position.getX(), position.getY(), position.getZ());
blockClicked = null; } else {
switch (action) { switch (action) {
case LEFT_CLICK_BLOCK: case LEFT_CLICK_BLOCK:
action = Action.LEFT_CLICK_AIR; 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) { if (itemInHand.getType() == Material.AIR || itemInHand.getAmount() == 0) {
itemInHand = null; itemInHand = null;
} }
@ -532,7 +534,8 @@ public class CraftEventFactory {
} else if (source == DamageSource.FALL) { } else if (source == DamageSource.FALL) {
cause = DamageCause.FALL; cause = DamageCause.FALL;
} else if (source == DamageSource.GENERIC) { } 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) { 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 BOOK_PAGES = new ItemMetaKey("pages");
static final ItemMetaKey RESOLVED = new ItemMetaKey("resolved"); static final ItemMetaKey RESOLVED = new ItemMetaKey("resolved");
static final ItemMetaKey GENERATION = new ItemMetaKey("generation"); static final ItemMetaKey GENERATION = new ItemMetaKey("generation");
static final int MAX_PAGE_LENGTH = Short.MAX_VALUE; // TODO: Check me static final int MAX_PAGES = 50;
static final int MAX_TITLE_LENGTH = 0xffff; static final int MAX_PAGE_LENGTH = 256;
static final int MAX_TITLE_LENGTH = 16;
protected String title; protected String title;
protected String author; protected String author;
@ -61,11 +63,11 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta {
super(tag); super(tag);
if (tag.hasKey(BOOK_TITLE.NBT)) { 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)) { 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; boolean resolved = false;
@ -80,6 +82,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta {
if (tag.hasKey(BOOK_PAGES.NBT) && handlePages) { if (tag.hasKey(BOOK_PAGES.NBT) && handlePages) {
NBTTagList pages = tag.getList(BOOK_PAGES.NBT, 8); 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++) { for (int i = 0; i < pages.size(); i++) {
String page = pages.getString(i); String page = pages.getString(i);
if (resolved) { if (resolved) {
@ -90,7 +93,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta {
// Ignore and treat as an old book // 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)); setTitle(SerializableMeta.getString(map, BOOK_TITLE.BUKKIT, true));
Iterable<?> pages = SerializableMeta.getObject(Iterable.class, map, BOOK_PAGES.BUKKIT, true); Iterable<?> pages = SerializableMeta.getObject(Iterable.class, map, BOOK_PAGES.BUKKIT, true);
// KigPaper start - limit pages
if(pages != null) { if(pages != null) {
int count = 0;
for (Object page : pages) { for (Object page : pages) {
if (count++ > MAX_PAGES) break;
if (page instanceof String) { if (page instanceof String) {
addPage((String) page); addPage((String) page);
} }
} }
} }
// KigPaper end
generation = SerializableMeta.getObject(Integer.class, map, GENERATION.BUKKIT, true); 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) { public void addPage(final String... pages) {
for (String page : pages) { for (String page : pages) {
if (this.pages.size() >= MAX_PAGES) {
return;
}
if (page == null) { if (page == null) {
page = ""; page = "";
} else if (page.length() > MAX_PAGE_LENGTH) { } 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]); this.pages.add(CraftChatMessage.fromString(page, true)[0]);

View File

@ -35,15 +35,17 @@ public class CraftMapRenderer extends MapRenderer {
cursors.removeCursor(cursors.getCursor(0)); cursors.removeCursor(cursors.getCursor(0));
} }
for (UUID key : worldMap.decorations.keySet()) { // Spigot string -> uuid. if (getDrawCursors()) {
// If this cursor is for a player check visibility with vanish system for (UUID key : worldMap.decorations.keySet()) { // Spigot string -> uuid.
Player other = Bukkit.getPlayer(key); // Spigot // If this cursor is for a player check visibility with vanish system
if (other != null && !player.canSee(other)) { Player other = Bukkit.getPlayer(key); // Spigot
continue; 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> { public class WorldMetadataStore extends MetadataStoreBase<World> implements MetadataStore<World> {
/** /**
* Generates a unique metadata key for a {@link World} object based on the world UID. * 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 world the world
* @param metadataKey The name identifying the metadata value * @param metadataKey The name identifying the metadata value
* @return a unique metadata key * @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. * <li>Changing the period on a task is delicate.
* Any future task needs to notify waiting threads. * 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}. * 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. * <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> * 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> * <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); 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(); 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 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 class StringMessage {
private static final Map<Character, EnumChatFormat> formatMap; 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 { static {
Builder<Character, EnumChatFormat> builder = ImmutableMap.builder(); 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.Item;
import net.minecraft.server.Items; import net.minecraft.server.Items;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.RegionFile;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
@ -227,4 +228,41 @@ public class PaperSpigotConfig
private static void saveEmptyScoreboardTeams() { private static void saveEmptyScoreboardTeams() {
saveEmptyScoreboardTeams = getBoolean("save-empty-scoreboard-teams", false); 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. * These entities are excluded from Activation range checks.
* *
* @param entity * @param entity
* @param world * @param config
* @return boolean If it should always tick. * @return boolean If it should always tick.
*/ */
public static boolean initializeEntityActivationState(Entity entity, SpigotWorldConfig config) 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 { private void postPlugin(final boolean isPing) throws IOException {
// Server software specific section // 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 boolean onlineMode = Bukkit.getServer().getOnlineMode(); // TRUE if online mode is enabled
String pluginVersion = (Metrics.class.getPackage().getImplementationVersion() != null) ? Metrics.class.getPackage().getImplementationVersion() : "unknown"; String pluginVersion = (Metrics.class.getPackage().getImplementationVersion() != null) ? Metrics.class.getPackage().getImplementationVersion() : "unknown";
String serverVersion = Bukkit.getVersion(); String serverVersion = Bukkit.getVersion();

View File

@ -191,10 +191,15 @@ public class SpigotWorldConfig
} }
public boolean saveStructureInfo; public boolean saveStructureInfo;
public boolean saveMineshaftStructureInfo; // Migot
private void structureInfo() private void structureInfo()
{ {
saveStructureInfo = getBoolean( "save-structure-info", true ); saveStructureInfo = getBoolean( "save-structure-info", true );
log( "Structure Info Saving: " + saveStructureInfo ); log( "Structure Info Saving: " + saveStructureInfo );
// Migot start
saveMineshaftStructureInfo = getBoolean( "save-mineshaft-structure-info", false);
log( "Mineshaft Structure Info Saving: " + saveMineshaftStructureInfo );
// Migot end
if ( !saveStructureInfo ) if ( !saveStructureInfo )
{ {
log( "*** WARNING *** You have selected to NOT save structure info. This may cause structures such as fortresses to not spawn mobs!" ); 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(); Logger log = Bukkit.getServer().getLogger();
log.log( Level.SEVERE, "The server has stopped responding!" ); log.log( Level.SEVERE, "The server has stopped responding!" );
log.log( Level.SEVERE, "Please report this to PaperSpigot directly!" ); log.log( Level.SEVERE, "This is all alf's fault." );
log.log( Level.SEVERE, "Be sure to include ALL relevant console errors and Minecraft crash reports" ); log.log( Level.SEVERE, "Version: " + Bukkit.getServer().getVersion() );
log.log( Level.SEVERE, "PaperSpigot version: " + Bukkit.getServer().getVersion() );
// //
if(net.minecraft.server.World.haveWeSilencedAPhysicsCrash) 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;
}
}