Fixed tickloop + minehq optimizations
This commit is contained in:
parent
23e68a05f9
commit
1d1ba70ae9
|
@ -15,6 +15,7 @@ repositories {
|
|||
maven(url = "https://oss.sonatype.org/content/groups/public")
|
||||
maven(url = "https://hub.spigotmc.org/nexus/content/groups/public")
|
||||
maven(url = "https://repo.velocitypowered.com/snapshots/")
|
||||
maven(url = "https://repo.viaversion.com")
|
||||
}
|
||||
|
||||
val minecraftVersion = "1_8_R3"
|
||||
|
|
|
@ -101,6 +101,18 @@ public class eSpigotConfig
|
|||
fixSprintEatExploit = getBoolean( "settings.fix-sprint-eat-exploit", true );
|
||||
}
|
||||
|
||||
public static boolean reduceArmorDamage;
|
||||
private static void reduceArmorDamage()
|
||||
{
|
||||
reduceArmorDamage = getBoolean( "settings.reduce-armor-damage", false );
|
||||
}
|
||||
|
||||
public static boolean slowerSaturationLoss;
|
||||
private static void slowerSaturationLoss()
|
||||
{
|
||||
slowerSaturationLoss = getBoolean( "settings.slower-saturation-loss", true );
|
||||
}
|
||||
|
||||
public static boolean fixBouncingArrows;
|
||||
private static void fixBouncingArrows()
|
||||
{
|
||||
|
|
|
@ -16,26 +16,6 @@ public class MinecraftPipeline extends ChannelInitializer<SocketChannel>
|
|||
}
|
||||
|
||||
protected void initChannel(SocketChannel channel) {
|
||||
ChannelConfig config = channel.config();
|
||||
try {
|
||||
config.setOption(ChannelOption.SO_KEEPALIVE, true);
|
||||
} catch (Exception ignored) {}
|
||||
try {
|
||||
config.setOption(ChannelOption.TCP_NODELAY, true);
|
||||
} catch (Exception ignored) {}
|
||||
try {
|
||||
config.setOption(ChannelOption.TCP_FASTOPEN, 1);
|
||||
} catch (Exception ignored) {}
|
||||
try {
|
||||
config.setOption(ChannelOption.TCP_FASTOPEN_CONNECT, true);
|
||||
} catch (Exception ignored) {}
|
||||
try {
|
||||
config.setOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
|
||||
} catch (Exception ignored) {}
|
||||
try {
|
||||
config.setOption(ChannelOption.IP_TOS, 0x18);
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
if(PaperSpigotConfig.nettyReadTimeout) channel.pipeline().addLast("timeout", new ReadTimeoutHandler(30));
|
||||
|
||||
channel.pipeline()
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
package com.elevatemc.spigot.tickloop;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.locks.LockSupport;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public abstract class IAsyncHandler<R extends Runnable> implements Executor {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private final String name;
|
||||
private final Queue<R> pendingRunnables = new ConcurrentLinkedQueue<>();
|
||||
private int terminateCount;
|
||||
|
||||
protected IAsyncHandler(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
protected abstract R packUpRunnable(Runnable runnable);
|
||||
|
||||
protected abstract boolean shouldRun(R task);
|
||||
|
||||
public boolean isMainThread() {
|
||||
return Thread.currentThread() == this.getMainThread();
|
||||
}
|
||||
|
||||
protected abstract Thread getMainThread();
|
||||
|
||||
protected boolean executables() {
|
||||
return !this.isMainThread();
|
||||
}
|
||||
|
||||
public int getPendingRunnables() {
|
||||
return this.pendingRunnables.size();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public <V> CompletableFuture<V> submit(Supplier<V> task) {
|
||||
return this.executables() ? CompletableFuture.supplyAsync(task, this)
|
||||
: CompletableFuture.completedFuture(task.get());
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> submitAsync(Runnable runnable) {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
runnable.run();
|
||||
return null;
|
||||
}, this);
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> submit(Runnable task) {
|
||||
if (this.executables()) {
|
||||
return this.submitAsync(task);
|
||||
} else {
|
||||
task.run();
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
}
|
||||
|
||||
public void performBlocking(Runnable runnable) {
|
||||
if (!this.isMainThread()) {
|
||||
this.submitAsync(runnable).join();
|
||||
} else {
|
||||
runnable.run();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void call(R runnable) {
|
||||
this.pendingRunnables.add(runnable);
|
||||
LockSupport.unpark(this.getMainThread());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Runnable runnable) {
|
||||
if (this.executables()) {
|
||||
this.call(this.packUpRunnable(runnable));
|
||||
} else {
|
||||
runnable.run();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected void clearAllRunnable() {
|
||||
this.pendingRunnables.clear();
|
||||
}
|
||||
|
||||
public void runAllRunnable() {
|
||||
while (this.drawRunnable()) {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean drawRunnable() {
|
||||
R runnable = this.pendingRunnables.peek();
|
||||
if (runnable == null) {
|
||||
return false;
|
||||
} else if (this.terminateCount == 0 && !this.shouldRun(runnable)) {
|
||||
return false;
|
||||
} else {
|
||||
this.doRunnable(this.pendingRunnables.remove());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public void controlTerminate(BooleanSupplier stopCondition) {
|
||||
++this.terminateCount;
|
||||
|
||||
try {
|
||||
while (!stopCondition.getAsBoolean()) {
|
||||
if (!this.drawRunnable()) {
|
||||
this.waitForRuns();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
--this.terminateCount;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected void waitForRuns() {
|
||||
Thread.yield();
|
||||
LockSupport.parkNanos("waiting for tasks", 100000L);
|
||||
}
|
||||
|
||||
protected void doRunnable(R task) {
|
||||
try {
|
||||
task.run();
|
||||
} catch (Exception e) {
|
||||
if (e.getCause() instanceof ThreadDeath) throw e;
|
||||
LOGGER.fatal("Error executing task on {}", this.getName(), e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package com.elevatemc.spigot.tickloop;
|
||||
|
||||
public abstract class ReentrantIAsyncHandler<R extends Runnable> extends IAsyncHandler<R> {
|
||||
|
||||
private int count;
|
||||
|
||||
public ReentrantIAsyncHandler(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean executables() {
|
||||
return this.runningTask() || super.executables();
|
||||
}
|
||||
|
||||
protected boolean runningTask() {
|
||||
return this.count != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doRunnable(R task) {
|
||||
++this.count;
|
||||
try {
|
||||
super.doRunnable(task);
|
||||
} finally {
|
||||
--this.count;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.elevatemc.spigot.tickloop;
|
||||
|
||||
public class TasksPerTick implements Runnable {
|
||||
private final int tick;
|
||||
private final Runnable task;
|
||||
|
||||
public TasksPerTick(int creationTicks, Runnable task) {
|
||||
this.tick = creationTicks;
|
||||
this.task = task;
|
||||
}
|
||||
|
||||
public int getTick() {
|
||||
return tick;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
task.run();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,225 @@
|
|||
package com.elevatemc.spigot.util;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Lists;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
import net.jafama.FastMath;
|
||||
import net.minecraft.server.EntityHuman;
|
||||
import net.minecraft.server.EntityPlayer;
|
||||
import net.minecraft.server.MathHelper;
|
||||
import net.minecraft.server.Packet;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class PlayerMap {
|
||||
|
||||
private static final int CHUNK_BITS = 5;
|
||||
|
||||
private static long xzToKey(long x, long z) {
|
||||
return (x << 32) + z - Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
private final Long2ObjectOpenHashMap<List<EntityPlayer>> map = new Long2ObjectOpenHashMap<>();
|
||||
|
||||
public void add(EntityPlayer player) {
|
||||
int x = MathHelper.floor(player.locX) >> CHUNK_BITS;
|
||||
int z = MathHelper.floor(player.locZ) >> CHUNK_BITS;
|
||||
long key = xzToKey(x, z);
|
||||
|
||||
List<EntityPlayer> list = map.get(key);
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
map.put(key, list);
|
||||
}
|
||||
|
||||
list.add(player);
|
||||
|
||||
player.playerMapX = x;
|
||||
player.playerMapZ = z;
|
||||
}
|
||||
|
||||
public void move(EntityPlayer player) {
|
||||
int x = MathHelper.floor(player.locX) >> CHUNK_BITS;
|
||||
int z = MathHelper.floor(player.locZ) >> CHUNK_BITS;
|
||||
|
||||
// did we move?
|
||||
if (x == player.playerMapX && z == player.playerMapZ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// do remove
|
||||
long key = xzToKey(player.playerMapX, player.playerMapZ);
|
||||
List<EntityPlayer> list = map.get(key);
|
||||
list.remove(player);
|
||||
if (list.isEmpty()) {
|
||||
map.remove(key);
|
||||
}
|
||||
|
||||
// do add
|
||||
key = xzToKey(x, z);
|
||||
list = map.get(key);
|
||||
if (list == null) {
|
||||
list = new ArrayList<EntityPlayer>();
|
||||
map.put(key, list);
|
||||
}
|
||||
list.add(player);
|
||||
player.playerMapX = x;
|
||||
player.playerMapZ = z;
|
||||
}
|
||||
|
||||
public void remove(EntityPlayer player) {
|
||||
long key = xzToKey(player.playerMapX, player.playerMapZ);
|
||||
List<EntityPlayer> list = map.get(key);
|
||||
if (list == null) {
|
||||
// player has not yet been added to this playermap, this happens when teleporting to another world during PlayerJoinEvent
|
||||
return;
|
||||
}
|
||||
list.remove(player);
|
||||
if (list.isEmpty()) {
|
||||
map.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
public EntityPlayer getNearestPlayer(double x, double y, double z, double distance) {
|
||||
double bestDistanceSqrd = -1.0;
|
||||
EntityPlayer bestPlayer = null;
|
||||
|
||||
for (int chunkX = MathHelper.floor(x - distance) >> CHUNK_BITS; chunkX <= MathHelper.floor(x + distance) >> CHUNK_BITS; chunkX++) {
|
||||
for (int chunkZ = MathHelper.floor(z - distance) >> CHUNK_BITS; chunkZ <= MathHelper.floor(z + distance) >> CHUNK_BITS; chunkZ++) {
|
||||
List<EntityPlayer> players = map.get(xzToKey(chunkX, chunkZ));
|
||||
if (players != null) {
|
||||
for (EntityPlayer player : players) {
|
||||
double playerDistSqrd = player.e(x, y, z);
|
||||
if (playerDistSqrd < distance * distance && (bestDistanceSqrd == -1.0 || playerDistSqrd < bestDistanceSqrd)) {
|
||||
bestDistanceSqrd = playerDistSqrd;
|
||||
bestPlayer = player;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return bestPlayer;
|
||||
}
|
||||
|
||||
public EntityPlayer getNearbyPlayer(double x, double y, double z, double distance, boolean respectSpawningApi) {
|
||||
double bestDistanceSqrd = -1.0;
|
||||
EntityPlayer bestPlayer = null;
|
||||
|
||||
for (int chunkX = MathHelper.floor(x - distance) >> CHUNK_BITS; chunkX <= MathHelper.floor(x + distance) >> CHUNK_BITS; chunkX++) {
|
||||
for (int chunkZ = MathHelper.floor(z - distance) >> CHUNK_BITS; chunkZ <= MathHelper.floor(z + distance) >> CHUNK_BITS; chunkZ++) {
|
||||
List<EntityPlayer> players = map.get(xzToKey(chunkX, chunkZ));
|
||||
if (players != null) {
|
||||
for (EntityPlayer player : players) {
|
||||
if (player != null && !player.dead && (!respectSpawningApi || player.affectsSpawning)) {
|
||||
double playerDistSqrd = player.e(x, y, z);
|
||||
if (playerDistSqrd < distance * distance && (bestDistanceSqrd == -1.0 || playerDistSqrd < bestDistanceSqrd)) {
|
||||
bestDistanceSqrd = playerDistSqrd;
|
||||
bestPlayer = player;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bestPlayer;
|
||||
}
|
||||
|
||||
public List<EntityPlayer> getNearbyPlayersIgnoreHeight(double x, double y, double z, double distance) {
|
||||
List<EntityPlayer> toReturn = null;
|
||||
|
||||
for (int chunkX = MathHelper.floor(x - distance) >> CHUNK_BITS; chunkX <= MathHelper.floor(x + distance) >> CHUNK_BITS; chunkX++) {
|
||||
for (int chunkZ = MathHelper.floor(z - distance) >> CHUNK_BITS; chunkZ <= MathHelper.floor(z + distance) >> CHUNK_BITS; chunkZ++) {
|
||||
List<EntityPlayer> players = map.get(xzToKey(chunkX, chunkZ));
|
||||
if (players != null) {
|
||||
for (EntityPlayer player : players) {
|
||||
if (player != null && !player.dead && FastMath.abs(player.locX - x) <= distance && FastMath.abs(player.locZ - z) <= distance) {
|
||||
if (toReturn == null) {
|
||||
toReturn = Lists.newArrayList();
|
||||
}
|
||||
|
||||
toReturn.add(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return toReturn == null ? Collections.emptyList() : toReturn;
|
||||
}
|
||||
|
||||
public EntityPlayer getNearestAttackablePlayer(double x, double y, double z, double maxXZ, double maxY, Function<EntityHuman, Double> visibility) {
|
||||
return getNearestAttackablePlayer(x, y, z, maxXZ, maxY, visibility, null);
|
||||
}
|
||||
|
||||
public EntityPlayer getNearestAttackablePlayer(double x, double y, double z, double maxXZ, double maxY, Function<EntityHuman, Double> visibility, Predicate<EntityHuman> condition) {
|
||||
double bestDistanceSqrd = -1.0;
|
||||
EntityPlayer bestPlayer = null;
|
||||
|
||||
for (int chunkX = MathHelper.floor(x - maxXZ) >> CHUNK_BITS; chunkX <= MathHelper.floor(x + maxXZ) >> CHUNK_BITS; chunkX++) {
|
||||
for (int chunkZ = MathHelper.floor(z - maxXZ) >> CHUNK_BITS; chunkZ <= MathHelper.floor(z + maxXZ) >> CHUNK_BITS; chunkZ++) {
|
||||
List<EntityPlayer> players = map.get(xzToKey(chunkX, chunkZ));
|
||||
if (players != null) {
|
||||
for (EntityPlayer player : players) {
|
||||
if (!player.abilities.isInvulnerable && player.isAlive() && (condition == null || condition.apply(player))) {
|
||||
double dx = player.locX - x;
|
||||
double dz = player.locZ - z;
|
||||
double playerDistSqrd = dx * dx + dz * dz;
|
||||
double dy = FastMath.abs(player.locY - y);
|
||||
double distForPlayer = maxXZ;
|
||||
|
||||
if (player.isSneaking()) {
|
||||
distForPlayer *= 0.8;
|
||||
}
|
||||
|
||||
if (visibility != null) {
|
||||
Double v = visibility.apply(player);
|
||||
if (v != null) {
|
||||
distForPlayer *= v;
|
||||
}
|
||||
}
|
||||
|
||||
// mojang mistake squaring maxY?
|
||||
if ((maxY < 0.0 || dy < maxY * maxY) && playerDistSqrd < distForPlayer * distForPlayer && (bestDistanceSqrd == -1.0 || playerDistSqrd < bestDistanceSqrd)) {
|
||||
bestDistanceSqrd = playerDistSqrd;
|
||||
bestPlayer = player;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bestPlayer;
|
||||
}
|
||||
|
||||
public void sendPacketNearby(EntityPlayer source, double x, double y, double z, double distance, Packet packet) {
|
||||
for (int chunkX = MathHelper.floor(x - distance) >> CHUNK_BITS; chunkX <= MathHelper.floor(x + distance) >> CHUNK_BITS; chunkX++) {
|
||||
for (int chunkZ = MathHelper.floor(z - distance) >> CHUNK_BITS; chunkZ <= MathHelper.floor(z + distance) >> CHUNK_BITS; chunkZ++) {
|
||||
List<EntityPlayer> players = map.get(xzToKey(chunkX, chunkZ));
|
||||
if (players != null) {
|
||||
for (EntityPlayer player : players) {
|
||||
// don't send self
|
||||
if (player == source) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// bukkit visibility api
|
||||
if (source != null && !player.getBukkitEntity().canSee(source.getBukkitEntity())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
double playerDistSqrd = player.e(x, y, z);
|
||||
if (playerDistSqrd < distance * distance) {
|
||||
player.playerConnection.sendPacket(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -117,11 +117,11 @@ public abstract class BiomeBase {
|
|||
this.id = i;
|
||||
BiomeBase.biomes[i] = this;
|
||||
this.as = this.a();
|
||||
this.au.add(new BiomeMeta(EntitySheep.class, 12, 4, 4));
|
||||
this.au.add(new BiomeMeta(EntitySheep.class, 6, 4, 4)); // MineHQ - less sheep
|
||||
this.au.add(new BiomeMeta(EntityRabbit.class, 10, 3, 3));
|
||||
this.au.add(new BiomeMeta(EntityPig.class, 10, 4, 4));
|
||||
this.au.add(new BiomeMeta(EntityChicken.class, 10, 4, 4));
|
||||
this.au.add(new BiomeMeta(EntityCow.class, 8, 4, 4));
|
||||
this.au.add(new BiomeMeta(EntityCow.class, 14, 4, 4)); // MineHQ - more cows
|
||||
this.at.add(new BiomeMeta(EntitySpider.class, 100, 4, 4));
|
||||
this.at.add(new BiomeMeta(EntityZombie.class, 100, 4, 4));
|
||||
this.at.add(new BiomeMeta(EntitySkeleton.class, 100, 4, 4));
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
package net.minecraft.server;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
import org.bukkit.craftbukkit.util.LongHash;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class BiomeCache {
|
||||
|
||||
private final WorldChunkManager a;
|
||||
private long b;
|
||||
private LongHashMap<BiomeCache.BiomeCacheBlock> c = new LongHashMap();
|
||||
private Long2ObjectMap<BiomeCacheBlock> c = new Long2ObjectOpenHashMap();
|
||||
private List<BiomeCache.BiomeCacheBlock> d = Lists.newArrayList();
|
||||
|
||||
public BiomeCache(WorldChunkManager worldchunkmanager) {
|
||||
|
@ -17,8 +21,10 @@ public class BiomeCache {
|
|||
public BiomeCache.BiomeCacheBlock a(int i, int j) {
|
||||
i >>= 4;
|
||||
j >>= 4;
|
||||
long k = (long) i & 4294967295L | ((long) j & 4294967295L) << 32;
|
||||
BiomeCache.BiomeCacheBlock biomecache_biomecacheblock = (BiomeCache.BiomeCacheBlock) this.c.getEntry(k);
|
||||
// MineHQ start
|
||||
long k = LongHash.toLong(i, j);
|
||||
BiomeCacheBlock biomecache_biomecacheblock = (BiomeCacheBlock) this.c.get(k);
|
||||
// MineHQ end
|
||||
|
||||
if (biomecache_biomecacheblock == null) {
|
||||
biomecache_biomecacheblock = new BiomeCache.BiomeCacheBlock(i, j);
|
||||
|
@ -49,7 +55,7 @@ public class BiomeCache {
|
|||
|
||||
if (l > 30000L || l < 0L) {
|
||||
this.d.remove(k--);
|
||||
long i1 = (long) biomecache_biomecacheblock.c & 4294967295L | ((long) biomecache_biomecacheblock.d & 4294967295L) << 32;
|
||||
long i1 = LongHash.toLong(biomecache_biomecacheblock.c, biomecache_biomecacheblock.d); // MineHQ
|
||||
|
||||
this.c.remove(i1);
|
||||
}
|
||||
|
|
|
@ -68,7 +68,14 @@ public class ChunkProviderServer implements IChunkProvider {
|
|||
// CraftBukkit end
|
||||
}
|
||||
|
||||
public void queueUnload(int i, int j) {
|
||||
// MineHQ start
|
||||
public void queueUnload(int x, int z) {
|
||||
queueUnload(x, z, false);
|
||||
}
|
||||
|
||||
public void queueUnload(int i, int j, boolean checked) {
|
||||
if (!checked && this.world.getPlayerChunkMap().isChunkInUse(i, j)) return;
|
||||
// MineHQ end
|
||||
long key = LongHash.toLong(i, j); // IonSpigot - Only create key once
|
||||
// PaperSpigot start - Asynchronous lighting updates
|
||||
Chunk chunk = chunks.get(key); // IonSpigot
|
||||
|
|
|
@ -37,8 +37,10 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer
|
|||
private boolean s;
|
||||
|
||||
// CraftBukkit start - Signature changed
|
||||
public DedicatedServer(joptsimple.OptionSet options) {
|
||||
super(options, Proxy.NO_PROXY, DedicatedServer.a);
|
||||
// PandaSpigot start - Modern tick loop
|
||||
public DedicatedServer(joptsimple.OptionSet options, Thread serverThread) {
|
||||
super(options, Proxy.NO_PROXY, DedicatedServer.a, serverThread);
|
||||
// PandaSpigot end
|
||||
// CraftBukkit end
|
||||
Thread thread = new Thread("Server Infinisleeper") {
|
||||
{
|
||||
|
|
|
@ -395,6 +395,7 @@ public abstract class EntityHuman extends EntityLiving {
|
|||
double d0 = this.locX;
|
||||
double d1 = this.locY;
|
||||
double d2 = this.locZ;
|
||||
World world = this.world;
|
||||
float f = this.yaw;
|
||||
float f1 = this.pitch;
|
||||
|
||||
|
@ -1413,7 +1414,10 @@ public abstract class EntityHuman extends EntityLiving {
|
|||
super.g(f, f1);
|
||||
}
|
||||
|
||||
this.checkMovement(this.locX - d0, this.locY - d1, this.locZ - d2);
|
||||
// Kohi - don't check if world changed
|
||||
if (this.world == world) {
|
||||
this.checkMovement(this.locX - d0, this.locY - d1, this.locZ - d2);
|
||||
}
|
||||
}
|
||||
|
||||
public float bI() {
|
||||
|
|
|
@ -1740,6 +1740,7 @@ public abstract class EntityLiving extends Entity {
|
|||
break;
|
||||
} // Spigot
|
||||
Entity entity = (Entity) o;
|
||||
if (entity instanceof EntityPlayer) continue; // MineHQ - players don't get pushed
|
||||
|
||||
// TODO better check now?
|
||||
// CraftBukkit start - Only handle mob (non-player) collisions every other tick
|
||||
|
|
|
@ -91,6 +91,10 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
|
|||
}
|
||||
// Spigot end
|
||||
|
||||
// MineHQ start
|
||||
public int playerMapX;
|
||||
public int playerMapZ;
|
||||
// MineHQ end
|
||||
public EntityPlayer(MinecraftServer minecraftserver, WorldServer worldserver, GameProfile gameprofile, PlayerInteractManager playerinteractmanager) {
|
||||
super(worldserver, gameprofile);
|
||||
this.viewDistance = world.spigotConfig.viewDistance; // PaperSpigot - Player view distance API
|
||||
|
@ -671,6 +675,15 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
|
|||
if (this.vehicle != entity1) { // CraftBukkit
|
||||
this.playerConnection.sendPacket(new PacketPlayOutAttachEntity(0, this, this.vehicle));
|
||||
this.playerConnection.a(this.locX, this.locY, this.locZ, this.yaw, this.pitch);
|
||||
// MineHQ start
|
||||
if (this.vehicle instanceof EntityLiving) {
|
||||
AttributeMapServer attributemapserver = (AttributeMapServer) ((EntityLiving) this.vehicle).getAttributeMap();
|
||||
Collection collection = attributemapserver.c();
|
||||
if (!collection.isEmpty()) {
|
||||
this.playerConnection.sendPacket(new PacketPlayOutUpdateAttributes(this.vehicle.getId(), collection));
|
||||
}
|
||||
}
|
||||
// MineHQ end
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -261,7 +261,11 @@ public class EntityTrackerEntry {
|
|||
}
|
||||
|
||||
if (!cancelled) {
|
||||
this.broadcastIncludingSelf(new PacketPlayOutEntityVelocity(this.tracker));
|
||||
if (this.tracker instanceof EntityPlayer) {
|
||||
((EntityPlayer) this.tracker).playerConnection.sendPacket(new PacketPlayOutEntityVelocity(this.tracker));
|
||||
} else if (this.tracker instanceof EntityArrow || this.tracker instanceof EntityProjectile) {
|
||||
this.broadcast(new PacketPlayOutEntityVelocity(this.tracker));
|
||||
}
|
||||
}
|
||||
// CraftBukkit end
|
||||
this.tracker.velocityChanged = false;
|
||||
|
@ -303,15 +307,21 @@ public class EntityTrackerEntry {
|
|||
|
||||
if (this.tracker instanceof EntityLiving) {
|
||||
AttributeMapServer attributemapserver = (AttributeMapServer) ((EntityLiving) this.tracker).getAttributeMap();
|
||||
Set set = attributemapserver.getAttributes();
|
||||
Set<AttributeInstance> set = attributemapserver.getAttributes();
|
||||
|
||||
if (!set.isEmpty()) {
|
||||
// CraftBukkit start - Send scaled max health
|
||||
if (this.tracker instanceof EntityPlayer) {
|
||||
((EntityPlayer) this.tracker).getBukkitEntity().injectScaledMaxHealth(set, false);
|
||||
((EntityPlayer) this.tracker).playerConnection.sendPacket(new PacketPlayOutUpdateAttributes(this.tracker.getId(), set)); // MineHQ
|
||||
}
|
||||
// CraftBukkit end
|
||||
this.broadcastIncludingSelf(new PacketPlayOutUpdateAttributes(this.tracker.getId(), set));
|
||||
// MineHQ start
|
||||
// this.broadcastIncludingSelf(new PacketPlayOutUpdateAttributes(this.tracker.getId(), set)); // CraftBukkit
|
||||
if (this.tracker.passenger instanceof EntityPlayer) {
|
||||
((EntityPlayer) this.tracker.passenger).playerConnection.sendPacket(new PacketPlayOutUpdateAttributes(this.tracker.getId(), set));
|
||||
}
|
||||
// MineHQ end
|
||||
}
|
||||
|
||||
set.clear();
|
||||
|
@ -375,6 +385,8 @@ public class EntityTrackerEntry {
|
|||
entityplayer.playerConnection.sendPacket(new PacketPlayOutUpdateEntityNBT(this.tracker.getId(), nbttagcompound));
|
||||
}
|
||||
|
||||
// MineHQ start
|
||||
/*
|
||||
if (this.tracker instanceof EntityLiving) {
|
||||
AttributeMapServer attributemapserver = (AttributeMapServer) ((EntityLiving) this.tracker).getAttributeMap();
|
||||
Collection collection = attributemapserver.c();
|
||||
|
@ -389,6 +401,8 @@ public class EntityTrackerEntry {
|
|||
entityplayer.playerConnection.sendPacket(new PacketPlayOutUpdateAttributes(this.tracker.getId(), collection));
|
||||
}
|
||||
}
|
||||
*/
|
||||
// MineHQ end
|
||||
|
||||
this.j = this.tracker.motX;
|
||||
this.k = this.tracker.motY;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package net.minecraft.server;
|
||||
|
||||
import com.elevatemc.spigot.config.eSpigotConfig;
|
||||
|
||||
public class FoodMetaData {
|
||||
|
||||
public int foodLevel = 20;
|
||||
|
@ -44,7 +46,7 @@ public class FoodMetaData {
|
|||
if (this.exhaustionLevel > 4.0F) {
|
||||
this.exhaustionLevel -= 4.0F;
|
||||
if (this.saturationLevel > 0.0F) {
|
||||
this.saturationLevel = Math.max(this.saturationLevel - 1.0F, 0.0F);
|
||||
this.saturationLevel = Math.max(this.saturationLevel - (eSpigotConfig.slowerSaturationLoss ? 0.5F : 1.0F), 0.0F); // ElevateMC slower saturation loss
|
||||
} else if (enumdifficulty != EnumDifficulty.PEACEFUL) {
|
||||
// CraftBukkit start
|
||||
org.bukkit.event.entity.FoodLevelChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callFoodLevelChangeEvent(entityhuman, Math.max(this.foodLevel - 1, 0));
|
||||
|
|
|
@ -2,6 +2,8 @@ package net.minecraft.server;
|
|||
|
||||
import co.aikar.timings.SpigotTimings;
|
||||
import com.elevatemc.spigot.threading.ThreadingManager;
|
||||
import com.elevatemc.spigot.tickloop.ReentrantIAsyncHandler;
|
||||
import com.elevatemc.spigot.tickloop.TasksPerTick;
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
|
@ -43,7 +45,7 @@ import java.util.concurrent.Executors;
|
|||
import java.util.concurrent.FutureTask;
|
||||
// CraftBukkit end
|
||||
|
||||
public abstract class MinecraftServer implements Runnable, ICommandListener, IAsyncTaskHandler, IMojangStatistics {
|
||||
public abstract class MinecraftServer extends ReentrantIAsyncHandler<TasksPerTick> implements ICommandListener, IAsyncTaskHandler, IMojangStatistics { // PandaSpigot - Modern tick loop
|
||||
|
||||
public static final Logger LOGGER = LogManager.getLogger();
|
||||
public static final File a = new File("usercache.json");
|
||||
|
@ -176,8 +178,38 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs
|
|||
|
||||
private final ThreadingManager threadingManager;
|
||||
|
||||
public MinecraftServer(OptionSet options, Proxy proxy, File file1) {
|
||||
// PandaSpigot start - Modern tick loop
|
||||
private long nextTickTime;
|
||||
private long delayedTasksMaxNextTickTime;
|
||||
private boolean mayHaveDelayedTasks;
|
||||
private boolean forceTicks;
|
||||
private volatile boolean isReady;
|
||||
private long lastOverloadWarning;
|
||||
public long serverStartTime;
|
||||
public volatile Thread shutdownThread;
|
||||
private long lastTick = 0;
|
||||
private long catchupTime = 0;
|
||||
public static <S extends MinecraftServer> S spin(java.util.function.Function<Thread, S> serverFactory) {
|
||||
java.util.concurrent.atomic.AtomicReference<S> reference = new java.util.concurrent.atomic.AtomicReference<>();
|
||||
Thread thread = new Thread(() -> reference.get().run(), "Server thread");
|
||||
|
||||
thread.setUncaughtExceptionHandler((thread1, throwable) -> MinecraftServer.LOGGER.error(throwable));
|
||||
S server = serverFactory.apply(thread);
|
||||
|
||||
reference.set(server);
|
||||
thread.setPriority(Thread.NORM_PRIORITY + 2);
|
||||
thread.start();
|
||||
return server;
|
||||
}
|
||||
|
||||
public MinecraftServer(OptionSet options, Proxy proxy, File file1, Thread thread) {
|
||||
super("Server");
|
||||
io.netty.util.ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.DISABLED); // [Nacho-0040] Change deprecated Netty parameter // Spigot - disable
|
||||
this.nextTickTime = getMillis();
|
||||
this.primaryThread = thread;
|
||||
this.serverThread = thread;
|
||||
// PandaSpigot end
|
||||
|
||||
this.e = proxy;
|
||||
this.threadingManager = new ThreadingManager();
|
||||
MinecraftServer.l = this;
|
||||
|
@ -216,8 +248,8 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs
|
|||
*/ // PandaSpigot
|
||||
Runtime.getRuntime().addShutdownHook(new org.bukkit.craftbukkit.util.ServerShutdownThread(this));
|
||||
|
||||
this.serverThread = primaryThread = new Thread(this, "Server thread"); // Moved from main
|
||||
serverThread.setPriority(10); // Set main thread priority to highest (10)
|
||||
//this.serverThread = primaryThread = new Thread(this, "Server thread"); // Moved from main // PandaSpigot - comment out; we assign above
|
||||
// serverThread.setPriority(10); // Set main thread priority to highest (10)
|
||||
}
|
||||
|
||||
public static void main(final OptionSet options) { // CraftBukkit - replaces main(String[] astring)
|
||||
|
@ -304,6 +336,7 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs
|
|||
});
|
||||
*/
|
||||
|
||||
/* // PandaSpigot start - comment out
|
||||
DedicatedServer dedicatedserver = new DedicatedServer(options);
|
||||
|
||||
if (options.has("port")) {
|
||||
|
@ -323,6 +356,7 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs
|
|||
|
||||
dedicatedserver.primaryThread.start();
|
||||
// CraftBukkit end
|
||||
*/ // PandaSpigot end
|
||||
} catch (Exception exception) {
|
||||
MinecraftServer.LOGGER.fatal("Failed to start the minecraft server", exception);
|
||||
}
|
||||
|
@ -671,10 +705,18 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs
|
|||
this.isRunning = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
// PandaSpigot start - Modern tick loop
|
||||
public static long getMillis() {
|
||||
return getNanos() / 1000000L;
|
||||
}
|
||||
public static long getNanos() {
|
||||
return System.nanoTime();
|
||||
}
|
||||
// PandaSpigot end
|
||||
public void run() {
|
||||
AffinityLock affinityLock = null;
|
||||
try (final AffinityLock lock = AffinityLock.acquireLock()) {
|
||||
this.serverStartTime = getNanos();
|
||||
if (this.init()) {
|
||||
// eSpigot start - Thread affinity
|
||||
MinecraftServer.LOGGER.info("[eSpigot] Locked main thread. CPU: " + lock.cpuId());
|
||||
|
@ -683,7 +725,7 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs
|
|||
// eSpigot end
|
||||
|
||||
this.ab = az();
|
||||
long i = 0L;
|
||||
//long i = 0L; // PandaSpigot - comment out; not used
|
||||
|
||||
this.r.setMOTD(new ChatComponentText(this.motd));
|
||||
this.r.setServerInfo(new ServerPing.ServerData("1.8.8", 47));
|
||||
|
@ -692,36 +734,21 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs
|
|||
// Spigot start
|
||||
// PaperSpigot start - Further improve tick loop
|
||||
Arrays.fill(recentTps, 20);
|
||||
long start = System.nanoTime(), lastTick = start - TICK_TIME, nextTick = start + MinecraftServer.TICK_TIME, catchupTime = 0, curTime, wait, tickSection = start;
|
||||
// PandaSpigot start - Modern tick loop
|
||||
long start = System.nanoTime(), curTime, tickSection = start;
|
||||
lastTick = start - TICK_TIME;
|
||||
// PandaSpigot end
|
||||
// PaperSpigot end
|
||||
while (this.isRunning) {
|
||||
curTime = System.nanoTime();
|
||||
if (nextTick > curTime) {
|
||||
Thread.sleep(1L);
|
||||
continue;
|
||||
// PandaSpigot start - Modern tick loop
|
||||
long i = ((curTime = System.nanoTime()) / (1000L * 1000L)) - this.nextTickTime; // Paper
|
||||
if (i > 5000L && this.nextTickTime - this.lastOverloadWarning >= 30000L) { // CraftBukkit
|
||||
long j = i / 50L;
|
||||
if (this.server.getWarnOnOverload()) // CraftBukkit
|
||||
MinecraftServer.LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", i, j);
|
||||
this.nextTickTime += j * 50L;
|
||||
this.lastOverloadWarning = this.nextTickTime;
|
||||
}
|
||||
// PaperSpigot start - Further improve tick loop
|
||||
wait = MinecraftServer.TICK_TIME - (curTime - lastTick);
|
||||
if (wait > 0L) {
|
||||
if (catchupTime < 2E6) {
|
||||
wait += Math.abs(catchupTime);
|
||||
} else /* KigPaper */ if (wait < catchupTime) {
|
||||
catchupTime -= wait;
|
||||
wait = 0L;
|
||||
} else /*if (catchupTime > 2E6)*/ { // KigPaper
|
||||
wait -= catchupTime;
|
||||
catchupTime = 0L;
|
||||
}
|
||||
}
|
||||
if (wait > 0L) {
|
||||
Thread.sleep(1L);
|
||||
curTime = System.nanoTime(); // KigPaper
|
||||
wait = MinecraftServer.TICK_TIME - (curTime - lastTick);
|
||||
}
|
||||
|
||||
nextTick = curTime + (MinecraftServer.TICK_TIME - catchupTime);
|
||||
catchupTime = Math.min(MinecraftServer.MAX_CATCHUP_BUFFER, catchupTime - wait);
|
||||
|
||||
if (++MinecraftServer.currentTick % MinecraftServer.SAMPLE_INTERVAL == 0) {
|
||||
long diff = curTime - tickSection;
|
||||
double currentTps = 1E9 / diff * MinecraftServer.SAMPLE_INTERVAL;
|
||||
|
@ -738,13 +765,16 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs
|
|||
}
|
||||
lastTick = curTime;
|
||||
|
||||
|
||||
long start2 = System.nanoTime();
|
||||
|
||||
this.A();
|
||||
this.Q = true;
|
||||
|
||||
lastTickTime = System.nanoTime() - start2;
|
||||
this.nextTickTime += 50L;
|
||||
this.methodProfiler.a("tick");
|
||||
this.A(this::haveTime);
|
||||
this.methodProfiler.c("nextTickWait");
|
||||
this.mayHaveDelayedTasks = true;
|
||||
this.delayedTasksMaxNextTickTime = Math.max(getMillis() + 50L, this.nextTickTime);
|
||||
this.waitUntilNextTick();
|
||||
this.methodProfiler.b();
|
||||
this.isReady = true;
|
||||
// PandaSpigot end
|
||||
}
|
||||
// Spigot end
|
||||
} else {
|
||||
|
@ -802,6 +832,62 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs
|
|||
|
||||
}
|
||||
|
||||
// PandaSpigot start - Modern tick loop
|
||||
private boolean haveTime() {
|
||||
if (isOversleep) return canOversleep();
|
||||
return this.forceTicks || this.runningTask() || getMillis() < (this.mayHaveDelayedTasks ? this.delayedTasksMaxNextTickTime : this.nextTickTime);
|
||||
}
|
||||
|
||||
boolean isOversleep = false;
|
||||
private boolean canOversleep() {
|
||||
return this.mayHaveDelayedTasks && getMillis() < this.delayedTasksMaxNextTickTime;
|
||||
}
|
||||
|
||||
private boolean canSleepForTickNoOversleep() {
|
||||
return this.forceTicks || this.runningTask() || getMillis() < this.nextTickTime;
|
||||
}
|
||||
|
||||
private void executeModerately() {
|
||||
this.runAllRunnable();
|
||||
java.util.concurrent.locks.LockSupport.parkNanos("executing tasks", 1000L);
|
||||
}
|
||||
|
||||
protected void waitUntilNextTick() {
|
||||
this.controlTerminate(() -> !this.canSleepForTickNoOversleep());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TasksPerTick packUpRunnable(Runnable runnable) {
|
||||
// anything that does try to post to main during watchdog crash, run on watchdog
|
||||
if (this.hasStopped && Thread.currentThread().equals(shutdownThread)) {
|
||||
runnable.run();
|
||||
runnable = () -> {};
|
||||
}
|
||||
return new TasksPerTick(this.ticks, runnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldRun(TasksPerTick task) {
|
||||
return task.getTick() + 3 < this.ticks || this.haveTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawRunnable() {
|
||||
boolean flag = this.pollTaskInternal();
|
||||
|
||||
this.mayHaveDelayedTasks = flag;
|
||||
return flag;
|
||||
}
|
||||
|
||||
private boolean pollTaskInternal() {
|
||||
return super.drawRunnable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Thread getMainThread() {
|
||||
return serverThread;
|
||||
}
|
||||
// PandaSpigot end
|
||||
private void a(ServerPing serverping) {
|
||||
File file = this.d("server-icon.png");
|
||||
|
||||
|
@ -841,9 +927,14 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs
|
|||
protected void z() {
|
||||
}
|
||||
|
||||
protected void A() throws ExceptionWorldConflict { // CraftBukkit - added throws
|
||||
// PandaSpigot start - Modern tick loop
|
||||
protected void A(java.util.function.BooleanSupplier shouldKeepTicking) throws ExceptionWorldConflict { // CraftBukkit - added throws
|
||||
co.aikar.timings.TimingsManager.FULL_SERVER_TICK.startTiming(); // Spigot
|
||||
long i = System.nanoTime();
|
||||
isOversleep = true;
|
||||
this.controlTerminate(() -> !this.canOversleep());
|
||||
isOversleep = false;
|
||||
// PandaSpigot end
|
||||
|
||||
++this.ticks;
|
||||
if (this.T) {
|
||||
|
@ -886,6 +977,10 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs
|
|||
ThreadingManager.checkTickTime(tickTime);
|
||||
// Migot end
|
||||
|
||||
// PandaSpigot start - Modern tick loop
|
||||
long endTime = System.nanoTime();
|
||||
long remaining = (TICK_TIME - (endTime - lastTick)) - catchupTime;
|
||||
// PandaSpigot end
|
||||
this.methodProfiler.a("tallying");
|
||||
this.h[this.ticks % 100] = System.nanoTime() - i;
|
||||
this.methodProfiler.b();
|
||||
|
|
|
@ -21,6 +21,8 @@ public class PathfinderGoalRandomStroll extends PathfinderGoal {
|
|||
}
|
||||
|
||||
public boolean a() {
|
||||
// MineHQ start - disable RandomStroll AI
|
||||
/*
|
||||
if (!this.g) {
|
||||
if (this.a.bh() >= 100) {
|
||||
return false;
|
||||
|
@ -41,6 +43,9 @@ public class PathfinderGoalRandomStroll extends PathfinderGoal {
|
|||
this.g = false;
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
return false;
|
||||
// MineHQ end
|
||||
}
|
||||
|
||||
public boolean b() {
|
||||
|
|
|
@ -21,8 +21,8 @@ public class PlayerChunkMap {
|
|||
private final WorldServer world;
|
||||
private final List<EntityPlayer> managedPlayers = Lists.newArrayList();
|
||||
private final LongHashMap<PlayerChunkMap.PlayerChunk> d = new LongHashMap();
|
||||
private final Queue<PlayerChunkMap.PlayerChunk> e = new java.util.concurrent.ConcurrentLinkedQueue<>(); // CraftBukkit ArrayList -> ConcurrentLinkedQueue
|
||||
private final Queue<PlayerChunkMap.PlayerChunk> f = new java.util.concurrent.ConcurrentLinkedQueue<>(); // CraftBukkit ArrayList -> ConcurrentLinkedQueue
|
||||
private final List<PlayerChunk> e = new ArrayList<>(); // Kohi - use arraylist as in vanilla
|
||||
// private final Queue f = new java.util.concurrent.ConcurrentLinkedQueue(); // Kohi - this is pointless
|
||||
private int g;
|
||||
private long h;
|
||||
private final int[][] i = new int[][] { { 1, 0}, { 0, 1}, { -1, 0}, { 0, -1}};
|
||||
|
@ -40,8 +40,8 @@ public class PlayerChunkMap {
|
|||
public void flush() {
|
||||
long i = this.world.getTime();
|
||||
int j;
|
||||
PlayerChunkMap.PlayerChunk playerchunkmap_playerchunk;
|
||||
|
||||
/* Kohi - removed PlayerChunkMap.f
|
||||
if (i - this.h > 8000L) {
|
||||
this.h = i;
|
||||
|
||||
|
@ -59,9 +59,16 @@ public class PlayerChunkMap {
|
|||
iterator.remove();
|
||||
// CraftBukkit end
|
||||
}
|
||||
}
|
||||
} */
|
||||
|
||||
// this.e.clear(); //CraftBukkit - Removals are already covered
|
||||
for (PlayerChunk playerchunk : this.e) {
|
||||
playerchunk.b();
|
||||
}
|
||||
|
||||
this.e.clear();
|
||||
// MineHQ start - chunk GC handles this
|
||||
/*
|
||||
if (this.managedPlayers.isEmpty()) {
|
||||
if (!wasNotEmpty) return; // CraftBukkit - Only do unload when we go from non-empty to empty
|
||||
WorldProvider worldprovider = this.world.worldProvider;
|
||||
|
@ -75,6 +82,8 @@ public class PlayerChunkMap {
|
|||
wasNotEmpty = true;
|
||||
}
|
||||
// CraftBukkit end
|
||||
*/
|
||||
// MineHQ end
|
||||
|
||||
}
|
||||
|
||||
|
@ -91,7 +100,7 @@ public class PlayerChunkMap {
|
|||
if (playerchunkmap_playerchunk == null && flag) {
|
||||
playerchunkmap_playerchunk = new PlayerChunkMap.PlayerChunk(i, j);
|
||||
this.d.put(k, playerchunkmap_playerchunk);
|
||||
this.f.add(playerchunkmap_playerchunk);
|
||||
// this.f.add(playerchunkmap_playerchunk);
|
||||
}
|
||||
|
||||
return playerchunkmap_playerchunk;
|
||||
|
@ -108,6 +117,7 @@ public class PlayerChunkMap {
|
|||
// CraftBukkit end
|
||||
|
||||
public void flagDirty(BlockPosition blockposition) {
|
||||
org.spigotmc.AsyncCatcher.catchOp("PlayerChunkMap.flagDirty");
|
||||
int i = blockposition.getX() >> 4;
|
||||
int j = blockposition.getZ() >> 4;
|
||||
PlayerChunkMap.PlayerChunk playerchunkmap_playerchunk = this.a(i, j, false);
|
||||
|
@ -119,8 +129,10 @@ public class PlayerChunkMap {
|
|||
}
|
||||
|
||||
public void addPlayer(EntityPlayer entityplayer) {
|
||||
int i = (int) entityplayer.locX >> 4;
|
||||
int j = (int) entityplayer.locZ >> 4;
|
||||
// Poweruser start
|
||||
int i = MathHelper.floor(entityplayer.locX) >> 4;
|
||||
int j = MathHelper.floor(entityplayer.locZ) >> 4;
|
||||
// Poweruser end
|
||||
|
||||
entityplayer.d = entityplayer.locX;
|
||||
entityplayer.e = entityplayer.locZ;
|
||||
|
@ -150,8 +162,10 @@ public class PlayerChunkMap {
|
|||
ArrayList arraylist = Lists.newArrayList(entityplayer.chunkCoordIntPairQueue);
|
||||
int i = 0;
|
||||
int j = entityplayer.viewDistance; // PaperSpigot - Player view distance API
|
||||
int k = (int) entityplayer.locX >> 4;
|
||||
int l = (int) entityplayer.locZ >> 4;
|
||||
// Poweruser start
|
||||
int k = MathHelper.floor(entityplayer.locX) >> 4;
|
||||
int l = MathHelper.floor(entityplayer.locZ) >> 4;
|
||||
// Poweruser end
|
||||
int i1 = 0;
|
||||
int j1 = 0;
|
||||
ChunkCoordIntPair chunkcoordintpair = this.a(k, l, true).location;
|
||||
|
@ -192,8 +206,10 @@ public class PlayerChunkMap {
|
|||
}
|
||||
|
||||
public void removePlayer(EntityPlayer entityplayer) {
|
||||
int i = (int) entityplayer.d >> 4;
|
||||
int j = (int) entityplayer.e >> 4;
|
||||
// Poweruser start
|
||||
int i = MathHelper.floor(entityplayer.d) >> 4;
|
||||
int j = MathHelper.floor(entityplayer.e) >> 4;
|
||||
// Poweruser end
|
||||
|
||||
// PaperSpigot start - Player view distance API
|
||||
for (int k = i - entityplayer.viewDistance; k <= i + entityplayer.viewDistance; ++k) {
|
||||
|
@ -218,15 +234,19 @@ public class PlayerChunkMap {
|
|||
}
|
||||
|
||||
public void movePlayer(EntityPlayer entityplayer) {
|
||||
int i = (int) entityplayer.locX >> 4;
|
||||
int j = (int) entityplayer.locZ >> 4;
|
||||
// Poweruser start
|
||||
int i = MathHelper.floor(entityplayer.locX) >> 4;
|
||||
int j = MathHelper.floor(entityplayer.locZ) >> 4;
|
||||
// Poweruser end
|
||||
double d0 = entityplayer.d - entityplayer.locX;
|
||||
double d1 = entityplayer.e - entityplayer.locZ;
|
||||
double d2 = d0 * d0 + d1 * d1;
|
||||
|
||||
if (d2 >= 64.0D) {
|
||||
int k = (int) entityplayer.d >> 4;
|
||||
int l = (int) entityplayer.e >> 4;
|
||||
// Poweruser start
|
||||
int k = MathHelper.floor(entityplayer.d) >> 4;
|
||||
int l = MathHelper.floor(entityplayer.e) >> 4;
|
||||
// Poweruser end
|
||||
int i1 = entityplayer.viewDistance; // PaperSpigot - Player view distance API
|
||||
int j1 = i - k;
|
||||
int k1 = j - l;
|
||||
|
@ -277,12 +297,13 @@ public class PlayerChunkMap {
|
|||
i = MathHelper.clamp(i, 3, 32);
|
||||
if (i != this.g) {
|
||||
int j = i - this.g;
|
||||
ArrayList arraylist = Lists.newArrayList(this.managedPlayers);
|
||||
List<EntityPlayer> arraylist = Lists.newArrayList(this.managedPlayers);
|
||||
|
||||
for (Object o : arraylist) {
|
||||
EntityPlayer entityplayer = (EntityPlayer) o;
|
||||
int k = (int) entityplayer.locX >> 4;
|
||||
int l = (int) entityplayer.locZ >> 4;
|
||||
for (EntityPlayer entityplayer : arraylist) {
|
||||
// Poweruser start
|
||||
int k = MathHelper.floor(entityplayer.locX) >> 4;
|
||||
int l = MathHelper.floor(entityplayer.locZ) >> 4;
|
||||
// Poweruser end
|
||||
int i1;
|
||||
int j1;
|
||||
|
||||
|
@ -315,8 +336,8 @@ public class PlayerChunkMap {
|
|||
public void updateViewDistance(EntityPlayer player, int viewDistance) {
|
||||
viewDistance = MathHelper.clamp(viewDistance, 3, 32);
|
||||
if (viewDistance != player.viewDistance) {
|
||||
int cx = (int) player.locX >> 4;
|
||||
int cz = (int) player.locZ >> 4;
|
||||
int cx = MathHelper.floor(player.locX) >> 4;
|
||||
int cz = MathHelper.floor(player.locZ) >> 4;
|
||||
|
||||
if (viewDistance - player.viewDistance > 0) {
|
||||
for (int x = cx - viewDistance; x <= cx + viewDistance; ++x) {
|
||||
|
@ -415,7 +436,7 @@ public class PlayerChunkMap {
|
|||
ChunkIOExecutor.dropQueuedChunkLoad(PlayerChunkMap.this.a(), this.location.x, this.location.z, this.loadedRunnable);
|
||||
long i = (long) this.location.x + 2147483647L | (long) this.location.z + 2147483647L << 32;
|
||||
PlayerChunkMap.this.d.remove(i);
|
||||
PlayerChunkMap.this.f.remove(this);
|
||||
// PlayerChunkMap.this.f.remove(this); Kohi
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -435,7 +456,7 @@ public class PlayerChunkMap {
|
|||
|
||||
this.a(chunk);
|
||||
PlayerChunkMap.this.d.remove(i);
|
||||
PlayerChunkMap.this.f.remove(this);
|
||||
// PlayerChunkMap.this.f.remove(this); // Kohi
|
||||
if (this.dirtyCount > 0) {
|
||||
PlayerChunkMap.this.e.remove(this);
|
||||
}
|
||||
|
@ -559,8 +580,10 @@ public class PlayerChunkMap {
|
|||
private int z;
|
||||
|
||||
public ChunkCoordComparator (EntityPlayer entityplayer) {
|
||||
x = (int) entityplayer.locX >> 4;
|
||||
z = (int) entityplayer.locZ >> 4;
|
||||
// Poweruser start
|
||||
x = MathHelper.floor(entityplayer.locX) >> 4;
|
||||
z = MathHelper.floor(entityplayer.locZ) >> 4;
|
||||
// Poweruser end
|
||||
}
|
||||
|
||||
public int compare(ChunkCoordIntPair a, ChunkCoordIntPair b) {
|
||||
|
|
|
@ -463,9 +463,8 @@ public class PlayerConnection implements PacketListenerPlayIn, IUpdatePlayerList
|
|||
this.player.checkMovement(this.player.locX - d0, this.player.locY - d1, this.player.locZ - d2);
|
||||
if (!this.player.noclip) {
|
||||
boolean flag2 = worldserver.getCubes(this.player, this.player.getBoundingBox().shrink(f4, f4, f4)).isEmpty();
|
||||
boolean rayTraceCollision = delta > 0.3 && worldserver.rayTrace(new Vec3D(this.o, this.p + 1.0, this.q), new Vec3D(d1, d2 + 1.0, d3), false, true, false) != null;
|
||||
|
||||
if (flag && (flag1 || !flag2 || rayTraceCollision) && !this.player.isSleeping()) {
|
||||
if (flag && (flag1 || !flag2) && !this.player.isSleeping()) {
|
||||
this.a(this.o, this.p, this.q, f2, f3);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import java.util.concurrent.Callable;
|
|||
// CraftBukkit start
|
||||
import java.util.List;
|
||||
|
||||
import com.elevatemc.spigot.config.eSpigotConfig;
|
||||
import org.bukkit.craftbukkit.entity.CraftHumanEntity;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
// CraftBukkit end
|
||||
|
@ -478,7 +479,7 @@ public class PlayerInventory implements IInventory {
|
|||
}
|
||||
|
||||
public void a(float f) {
|
||||
f /= 4.0F;
|
||||
f /= eSpigotConfig.reduceArmorDamage ? 8.0F : 4.0F; // MineHQ
|
||||
if (f < 1.0F) {
|
||||
f = 1.0F;
|
||||
}
|
||||
|
|
|
@ -346,6 +346,7 @@ public abstract class PlayerList {
|
|||
|
||||
public void d(EntityPlayer entityplayer) {
|
||||
entityplayer.u().getPlayerChunkMap().movePlayer(entityplayer);
|
||||
entityplayer.world.playerMap.move(entityplayer); // MineHQ
|
||||
}
|
||||
|
||||
public String disconnect(EntityPlayer entityplayer) { // CraftBukkit - return string
|
||||
|
|
|
@ -6,6 +6,7 @@ import com.velocitypowered.natives.util.Natives; // Paper
|
|||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.*;
|
||||
import io.netty.channel.epoll.Epoll;
|
||||
import io.netty.channel.epoll.EpollChannelOption;
|
||||
import io.netty.channel.epoll.EpollEventLoopGroup;
|
||||
import io.netty.channel.epoll.EpollServerSocketChannel;
|
||||
import io.netty.channel.kqueue.KQueue;
|
||||
|
@ -135,14 +136,20 @@ public class ServerConnection {
|
|||
LOGGER.info("Using " + Natives.cipher.getLoadedVariant() + " cipher from Velocity.");
|
||||
// Paper/Nacho end
|
||||
|
||||
this.listeningChannels.add(((new ServerBootstrap() // Nacho - deobfuscate listeningChannels
|
||||
.channel(channel))
|
||||
ServerBootstrap bootstrap = new ServerBootstrap() // Nacho - deobfuscate listeningChannels
|
||||
.channel(channel)
|
||||
.childOption(ChannelOption.WRITE_BUFFER_WATER_MARK, SERVER_WRITE_MARK)
|
||||
.childHandler(new MinecraftPipeline(this))
|
||||
.childOption(ChannelOption.TCP_NODELAY, true)
|
||||
.childOption(ChannelOption.IP_TOS, 0x18)
|
||||
.group(boss, worker)
|
||||
.localAddress(ip))
|
||||
.bind()
|
||||
.syncUninterruptibly());
|
||||
.localAddress(ip);
|
||||
|
||||
if (server.ai()) {
|
||||
bootstrap.option(ChannelOption.TCP_FASTOPEN, 3);
|
||||
}
|
||||
|
||||
this.listeningChannels.add(bootstrap.bind().syncUninterruptibly());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package net.minecraft.server;
|
|||
|
||||
import com.elevatemc.spigot.config.eSpigotConfig;
|
||||
import com.elevatemc.spigot.util.OptimizedWorldTileEntitySet;
|
||||
import com.elevatemc.spigot.util.PlayerMap;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
@ -272,6 +273,7 @@ public abstract class World implements IBlockAccess {
|
|||
return this;
|
||||
}
|
||||
|
||||
public final PlayerMap playerMap = new PlayerMap(); // MineHQ
|
||||
public BiomeBase getBiome(final BlockPosition blockposition) {
|
||||
if (this.isLoaded(blockposition)) {
|
||||
Chunk chunk = this.getChunkAtWorldCoords(blockposition);
|
||||
|
@ -1247,6 +1249,7 @@ public abstract class World implements IBlockAccess {
|
|||
EntityHuman entityhuman = (EntityHuman) entity;
|
||||
|
||||
this.players.add(entityhuman);
|
||||
this.playerMap.add((EntityPlayer) entityhuman); // MineHQ
|
||||
this.everyoneSleeping();
|
||||
}
|
||||
|
||||
|
@ -1285,6 +1288,7 @@ public abstract class World implements IBlockAccess {
|
|||
entity.die();
|
||||
if (entity instanceof EntityHuman) {
|
||||
this.players.remove(entity);
|
||||
this.playerMap.remove((EntityPlayer) entity); // MineHQ
|
||||
// Spigot start
|
||||
for ( Object o : worldMaps.c )
|
||||
{
|
||||
|
@ -1314,6 +1318,7 @@ public abstract class World implements IBlockAccess {
|
|||
entity.die();
|
||||
if (entity instanceof EntityHuman) {
|
||||
this.players.remove(entity);
|
||||
this.playerMap.remove((EntityPlayer) entity); // MineHQ
|
||||
this.worldMaps.removeTrackedPlayer((EntityHuman) entity); // FlamePaper - Minetick fix memory leaks
|
||||
this.everyoneSleeping();
|
||||
}
|
||||
|
@ -1408,7 +1413,7 @@ public abstract class World implements IBlockAccess {
|
|||
{
|
||||
block = chunk.getBlockData( blockposition );
|
||||
}
|
||||
if ( block != null )
|
||||
if ( block != null && block != Blocks.AIR) // MineHQ
|
||||
{
|
||||
// PaperSpigot start - FallingBlocks and TNT collide with specific non-collidable blocks
|
||||
Block b = block.getBlock();
|
||||
|
@ -1510,7 +1515,7 @@ public abstract class World implements IBlockAccess {
|
|||
} else {
|
||||
block = chunk.getBlockData(blockposition);
|
||||
}
|
||||
if (block != null) {
|
||||
if (block != null && block != Blocks.AIR) { // MineHQ
|
||||
// PaperSpigot start - FallingBlocks and TNT collide with specific non-collidable blocks
|
||||
Block b = block.getBlock();
|
||||
if (entity.world.paperSpigotConfig.fallingBlocksCollideWithSigns && (entity instanceof EntityTNTPrimed || entity instanceof EntityFallingBlock) && (b instanceof BlockSign || b instanceof BlockFenceGate || b instanceof BlockTorch || b instanceof BlockButtonAbstract || b instanceof BlockLever || b instanceof BlockTripwireHook || b instanceof BlockTripwire || b instanceof BlockChest || b instanceof BlockSlowSand || b instanceof BlockBed || b instanceof BlockEnderChest || b instanceof BlockEnchantmentTable || b instanceof BlockBrewingStand)) {
|
||||
|
@ -1575,7 +1580,7 @@ public abstract class World implements IBlockAccess {
|
|||
iblockdata = Blocks.BEDROCK.getBlockData();
|
||||
}
|
||||
|
||||
iblockdata.getBlock().a(this, blockposition_mutableblockposition, iblockdata, axisalignedbb, arraylist, null);
|
||||
if (iblockdata != Blocks.AIR.getBlockData()) iblockdata.getBlock().a(this, blockposition_mutableblockposition, iblockdata, axisalignedbb, arraylist, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3233,6 +3238,11 @@ public abstract class World implements IBlockAccess {
|
|||
}
|
||||
|
||||
public EntityHuman findNearbyPlayer(double d0, double d1, double d2, double d3) {
|
||||
// MineHQ start
|
||||
if (0 <= d3 && d3 <= 64) {
|
||||
return this.playerMap.getNearestPlayer(d0, d1, d2, d3);
|
||||
}
|
||||
// MineHQ end
|
||||
double d4 = -1.0D;
|
||||
EntityHuman entityhuman = null;
|
||||
|
||||
|
@ -3278,6 +3288,11 @@ public abstract class World implements IBlockAccess {
|
|||
}
|
||||
|
||||
public EntityHuman findNearbyPlayerWhoAffectsSpawning(double d0, double d1, double d2, double d3) {
|
||||
// MineHQ start
|
||||
if (0 <= d3 && d3 <= 64.0) {
|
||||
return this.playerMap.getNearbyPlayer(d0, d1, d2, d3, true);
|
||||
}
|
||||
// MineHQ end
|
||||
double d4 = -1.0D;
|
||||
EntityHuman entityhuman = null;
|
||||
|
||||
|
|
|
@ -30,13 +30,13 @@ public class WorldManager implements IWorldAccess {
|
|||
|
||||
public void a(EntityHuman entityhuman, String s, double d0, double d1, double d2, float f, float f1) {
|
||||
// CraftBukkit - this.world.dimension
|
||||
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.world.playerMap.sendPacketNearby((EntityPlayer) entityhuman, d0, d1, d2, f > 1.0F ? (double) (16.0F * f) : 16.0D, 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));
|
||||
this.world.playerMap.sendPacketNearby((EntityPlayer) entityhuman, d0, d1, d2, f > 1.0F ? (double) (16.0F * f) : 16.0D, new PacketPlayOutNamedSoundEffect(s, d0, d1, d2, f, f1));
|
||||
}
|
||||
// KigPaper end
|
||||
|
||||
|
@ -52,7 +52,7 @@ public class WorldManager implements IWorldAccess {
|
|||
|
||||
public void a(EntityHuman entityhuman, int i, BlockPosition blockposition, int j) {
|
||||
// CraftBukkit - this.world.dimension
|
||||
this.a.getPlayerList().sendPacketNearby(entityhuman, blockposition.getX(), blockposition.getY(), blockposition.getZ(), 64.0D, this.world.dimension, new PacketPlayOutWorldEvent(i, blockposition, j, false));
|
||||
this.world.playerMap.sendPacketNearby((EntityPlayer) entityhuman, blockposition.getX(), blockposition.getY(), blockposition.getZ(), 64.0D, new PacketPlayOutWorldEvent(i, blockposition, j, false));
|
||||
}
|
||||
|
||||
public void a(int i, BlockPosition blockposition, int j) {
|
||||
|
@ -60,7 +60,7 @@ public class WorldManager implements IWorldAccess {
|
|||
}
|
||||
|
||||
public void b(int i, BlockPosition blockposition, int j) {
|
||||
Iterator iterator = this.a.getPlayerList().v().iterator();
|
||||
/* Iterator iterator = this.world.players.iterator();; // MineHQ
|
||||
|
||||
// CraftBukkit start
|
||||
EntityHuman entityhuman = null;
|
||||
|
@ -72,7 +72,7 @@ public class WorldManager implements IWorldAccess {
|
|||
while (iterator.hasNext()) {
|
||||
EntityPlayer entityplayer = (EntityPlayer) iterator.next();
|
||||
|
||||
if (entityplayer != null && entityplayer.world == this.world && entityplayer.getId() != i) {
|
||||
if (entityplayer != null && entityplayer.getId() != i) { // MineHQ
|
||||
double d0 = (double) blockposition.getX() - entityplayer.locX;
|
||||
double d1 = (double) blockposition.getY() - entityplayer.locY;
|
||||
double d2 = (double) blockposition.getZ() - entityplayer.locZ;
|
||||
|
@ -90,7 +90,11 @@ public class WorldManager implements IWorldAccess {
|
|||
// SportPaper end
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} */
|
||||
// MineHQ start - PlayerMap
|
||||
Entity entity = world.a(i);
|
||||
EntityPlayer player = entity instanceof EntityPlayer ? (EntityPlayer) entity : null;
|
||||
this.world.playerMap.sendPacketNearby(player, blockposition.getX(), blockposition.getY(), blockposition.getZ(), 32.0D, new PacketPlayOutBlockBreakAnimation(i, blockposition, j));
|
||||
// MineHQ end
|
||||
}
|
||||
}
|
||||
|
|
|
@ -258,18 +258,18 @@ public class CraftWorld implements World {
|
|||
|
||||
public boolean unloadChunkRequest(int x, int z, boolean safe) {
|
||||
org.spigotmc.AsyncCatcher.catchOp( "chunk unload"); // Spigot
|
||||
if (safe && isChunkInUse(x, z)) {
|
||||
if (isChunkInUse(x, z)) { // MineHQ - never unload in-use chunks
|
||||
return false;
|
||||
}
|
||||
|
||||
world.chunkProviderServer.queueUnload(x, z);
|
||||
world.chunkProviderServer.queueUnload(x, z, true); // MineHQ
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean unloadChunk(int x, int z, boolean save, boolean safe) {
|
||||
org.spigotmc.AsyncCatcher.catchOp( "chunk unload"); // Spigot
|
||||
if (safe && isChunkInUse(x, z)) {
|
||||
if (isChunkInUse(x, z)) { // MineHQ - never unload in-use chunks
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ import java.util.logging.Level;
|
|||
import java.util.logging.Logger;
|
||||
import joptsimple.OptionParser;
|
||||
import joptsimple.OptionSet;
|
||||
import net.minecraft.server.DedicatedServer;
|
||||
import net.minecraft.server.DispenserRegistry;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
|
||||
import org.apache.commons.lang3.JavaVersion;
|
||||
|
@ -214,7 +216,30 @@ public class Main {
|
|||
// Spigot End
|
||||
System.setProperty("library.jansi.version", "eSpigot"); // PandaSpigot - set meaningless jansi version to prevent git builds from crashing on Windows
|
||||
System.out.println("Starting the spigot, please wait...");
|
||||
MinecraftServer.main(options);
|
||||
// PandaSpigot start - Modern tick loop
|
||||
DispenserRegistry.c();
|
||||
OptionSet finalOptions = options;
|
||||
|
||||
DedicatedServer server = MinecraftServer.spin(thread -> {
|
||||
DedicatedServer dedicatedserver = new DedicatedServer(finalOptions, thread);
|
||||
|
||||
if (finalOptions.has("port")) {
|
||||
int port = (Integer) finalOptions.valueOf("port");
|
||||
if (port > 0) {
|
||||
dedicatedserver.setPort(port);
|
||||
}
|
||||
}
|
||||
|
||||
if (finalOptions.has("universe")) {
|
||||
dedicatedserver.universe = (File) finalOptions.valueOf("universe");
|
||||
}
|
||||
|
||||
if (finalOptions.has("world")) {
|
||||
dedicatedserver.setWorld((String) finalOptions.valueOf("world"));
|
||||
}
|
||||
return dedicatedserver;
|
||||
});
|
||||
// PandaSpigot end - Modern tick loop
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
|
|
|
@ -550,6 +550,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
|||
}
|
||||
}
|
||||
|
||||
// MineHQ start - don't allow excessive teleports
|
||||
int locationChunkX = location.getBlockX() >> 4;
|
||||
int locationChunkZ = location.getBlockZ() >> 4;
|
||||
|
||||
if (46340 <= Math.abs(locationChunkX) || 46340 <= Math.abs(locationChunkZ)) {
|
||||
throw new IllegalArgumentException("Invalid teleportation destination for " + this.getName() + "! Offending location: " + location.toString());
|
||||
}
|
||||
// MineHQ end
|
||||
|
||||
// From = Players current Location
|
||||
Location from = this.getLocation();
|
||||
// To = Players new Location if Teleport is Successful
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
package org.bukkit.craftbukkit.inventory;
|
||||
|
||||
import net.minecraft.server.EntityPlayer;
|
||||
import net.minecraft.server.PacketPlayOutHeldItemSlot;
|
||||
import net.minecraft.server.PacketPlayOutSetSlot;
|
||||
import net.minecraft.server.PlayerInventory;
|
||||
import net.minecraft.server.*;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.inventory.EntityEquipment;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.inventory.PlayerInventory, EntityEquipment {
|
||||
public CraftInventoryPlayer(net.minecraft.server.PlayerInventory inventory) {
|
||||
super(inventory);
|
||||
|
@ -213,4 +213,40 @@ public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.i
|
|||
public void setBootsDropChance(float chance) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
// MineHQ start
|
||||
@Override
|
||||
public HashMap<Integer, ItemStack> addItem(ItemStack... items) {
|
||||
HashMap<Integer, ItemStack> leftover = super.addItem(items);
|
||||
this.updatePlayerInventory();
|
||||
return leftover;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(Material material) {
|
||||
super.remove(material);
|
||||
this.updatePlayerInventory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashMap<Integer, ItemStack> removeItem(ItemStack... items) {
|
||||
HashMap<Integer, ItemStack> leftover = super.removeItem(items);
|
||||
this.updatePlayerInventory();
|
||||
return leftover;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(ItemStack item) {
|
||||
super.remove(item);
|
||||
this.updatePlayerInventory();
|
||||
}
|
||||
|
||||
private void updatePlayerInventory() {
|
||||
EntityHuman human = this.getInventory().player;
|
||||
if (human instanceof EntityPlayer) {
|
||||
EntityPlayer player = (EntityPlayer) human;
|
||||
player.updateInventory(player.defaultContainer);
|
||||
}
|
||||
}
|
||||
// MineHQ end
|
||||
}
|
||||
|
|
|
@ -76,9 +76,11 @@ public class CraftScheduler implements BukkitScheduler {
|
|||
final ConcurrentHashMap<Integer, CraftTask> runners = new ConcurrentHashMap<Integer, CraftTask>(); // Paper
|
||||
volatile int currentTick = -1; // Paper
|
||||
//private final Executor executor = Executors.newCachedThreadPool(new com.google.common.util.concurrent.ThreadFactoryBuilder().setNameFormat("Craft Scheduler Thread - %1$d").build()); // Spigot // Paper - moved to AsyncScheduler
|
||||
// MineHQ start - nope
|
||||
private CraftAsyncDebugger debugHead = new CraftAsyncDebugger(-1, null, null) {@Override StringBuilder debugTo(StringBuilder string) {return string;}};
|
||||
private CraftAsyncDebugger debugTail = debugHead;
|
||||
private static final int RECENT_TICKS;
|
||||
// MineHQ end
|
||||
|
||||
static {
|
||||
RECENT_TICKS = 30;
|
||||
|
@ -427,7 +429,7 @@ public class CraftScheduler implements BukkitScheduler {
|
|||
}
|
||||
parsePending();
|
||||
} else {
|
||||
debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass()));
|
||||
// debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); // MineHQ - nope
|
||||
task.getOwner().getLogger().log(Level.SEVERE, "Unexpected Async Task in the Sync Scheduler. Report this to Paper"); // Paper
|
||||
// We don't need to parse pending
|
||||
// (async tasks must live with race-conditions if they attempt to cancel between these few lines of code)
|
||||
|
@ -442,7 +444,7 @@ public class CraftScheduler implements BukkitScheduler {
|
|||
}
|
||||
pending.addAll(temp);
|
||||
temp.clear();
|
||||
debugHead = debugHead.getNextHead(currentTick);
|
||||
// debugHead = debugHead.getNextHead(currentTick); // MineHQ - nope
|
||||
}
|
||||
|
||||
protected void addTask(final CraftTask task) {
|
||||
|
@ -505,10 +507,15 @@ public class CraftScheduler implements BukkitScheduler {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
// MineHQ start
|
||||
return "";
|
||||
/*
|
||||
int debugTick = currentTick;
|
||||
StringBuilder string = new StringBuilder("Recent tasks from ").append(debugTick - RECENT_TICKS).append('-').append(debugTick).append('{');
|
||||
debugHead.debugTo(string);
|
||||
return string.append('}').toString();
|
||||
*/
|
||||
// MineHQ end
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
|
|
|
@ -122,16 +122,16 @@ public class ActivationRange
|
|||
int k = MathHelper.floor( maxBB.c / 16.0D );
|
||||
int l = MathHelper.floor( maxBB.f / 16.0D );
|
||||
|
||||
Chunk chunk = null; // MineHQ
|
||||
for ( int i1 = i; i1 <= j; ++i1 )
|
||||
{
|
||||
for ( int j1 = k; j1 <= l; ++j1 )
|
||||
{
|
||||
Chunk chunk = world.getChunkIfLoaded( i1, j1 ); // SportPaper - remove double chunk lookup
|
||||
|
||||
if ( chunk != null )
|
||||
{
|
||||
activateChunkEntities( chunk );
|
||||
// MineHQ start
|
||||
if ((chunk = world.getChunkIfLoaded(i1, j1)) != null) {
|
||||
activateChunkEntities(chunk);
|
||||
}
|
||||
// MineHQ end
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
<TimeBasedTriggeringPolicy />
|
||||
<OnStartupTriggeringPolicy />
|
||||
</Policies>
|
||||
<DefaultRolloverStrategy max="999"/>
|
||||
</RollingRandomAccessFile>
|
||||
</Appenders>
|
||||
<Loggers>
|
||||
|
|
Loading…
Reference in New Issue