Allow for custom chunk/entity view distance and compression threshold without recompiling the server.

This commit is contained in:
themode 2020-10-25 16:48:14 +01:00
parent 424e99e2d8
commit 1b7613d977
14 changed files with 204 additions and 96 deletions

View File

@ -90,9 +90,6 @@ public class MinecraftServer {
public static final int THREAD_COUNT_PARALLEL_CHUNK_SAVING = 4; public static final int THREAD_COUNT_PARALLEL_CHUNK_SAVING = 4;
// Config // Config
public static final int CHUNK_VIEW_DISTANCE = 10;
public static final int ENTITY_VIEW_DISTANCE = 5;
public static final int COMPRESSION_THRESHOLD = 256;
// Can be modified at performance cost when increased // Can be modified at performance cost when increased
public static final int TICK_PER_SECOND = 20; public static final int TICK_PER_SECOND = 20;
private static final int MS_TO_SEC = 1000; private static final int MS_TO_SEC = 1000;
@ -137,6 +134,11 @@ public class MinecraftServer {
private static MinecraftServer minecraftServer; private static MinecraftServer minecraftServer;
// Data // Data
private static boolean started;
private static int chunkViewDistance = 10;
private static int entityViewDistance = 5;
private static int compressionThreshold = 256;
private static ResponseDataConsumer responseDataConsumer; private static ResponseDataConsumer responseDataConsumer;
private static String brandName = "Minestom"; private static String brandName = "Minestom";
private static Difficulty difficulty = Difficulty.NORMAL; private static Difficulty difficulty = Difficulty.NORMAL;
@ -392,6 +394,81 @@ public class MinecraftServer {
return connectionManager; return connectionManager;
} }
/**
* Gets if the server is up and running.
*
* @return true if the server is started
*/
public static boolean isStarted() {
return started;
}
/**
* Gets the chunk view distance of the server.
*
* @return the chunk view distance
*/
public static int getChunkViewDistance() {
return chunkViewDistance;
}
/**
* Changes the chunk view distance of the server.
* <p>
* WARNING: this need to be called before {@link #start(String, int, ResponseDataConsumer)}.
*
* @param chunkViewDistance the new chunk view distance
* @throws IllegalStateException if this is called after the server started
*/
public static void setChunkViewDistance(int chunkViewDistance) {
Check.stateCondition(started, "The chunk view distance cannot be changed after the server has been started.");
MinecraftServer.chunkViewDistance = chunkViewDistance;
}
/**
* Gets the entity view distance of the server.
*
* @return the entity view distance
*/
public static int getEntityViewDistance() {
return entityViewDistance;
}
/**
* Changes the entity view distance of the server.
* <p>
* WARNING: this need to be called before {@link #start(String, int, ResponseDataConsumer)}.
*
* @param entityViewDistance the new entity view distance
* @throws IllegalStateException if this is called after the server started
*/
public static void setEntityViewDistance(int entityViewDistance) {
Check.stateCondition(started, "The entity view distance cannot be changed after the server has been started.");
MinecraftServer.entityViewDistance = entityViewDistance;
}
/**
* Gets the compression threshold of the server.
*
* @return the compression threshold, 0 means that compression is disabled
*/
public static int getCompressionThreshold() {
return compressionThreshold;
}
/**
* Changes the compression threshold of the server.
* <p>
* WARNING: this need to be called before {@link #start(String, int, ResponseDataConsumer)}.
*
* @param compressionThreshold the new compression threshold, 0 to disable compression
* @throws IllegalStateException if this is called after the server started
*/
public static void setCompressionThreshold(int compressionThreshold) {
Check.stateCondition(started, "The compression threshold cannot be changed after the server has been started.");
MinecraftServer.compressionThreshold = compressionThreshold;
}
/** /**
* Gets the consumer executed to show server-list data. * Gets the consumer executed to show server-list data.
* *
@ -485,6 +562,8 @@ public class MinecraftServer {
LOGGER.info("Extensions loaded in " + (t1 + System.nanoTime()) / 1_000_000D + "ms"); LOGGER.info("Extensions loaded in " + (t1 + System.nanoTime()) / 1_000_000D + "ms");
LOGGER.info("Minestom server started successfully."); LOGGER.info("Minestom server started successfully.");
MinecraftServer.started = true;
} }
/** /**

View File

@ -1032,8 +1032,9 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
((Player) this).onChunkChange(newChunk); // Refresh loaded chunk ((Player) this).onChunkChange(newChunk); // Refresh loaded chunk
// Refresh entity viewable list // Refresh entity viewable list
final long[] lastVisibleChunksEntity = ChunkUtils.getChunksInRange(new Position(16 * lastChunk.getChunkX(), 0, 16 * lastChunk.getChunkZ()), MinecraftServer.ENTITY_VIEW_DISTANCE); final int entityViewDistance = MinecraftServer.getEntityViewDistance();
final long[] updatedVisibleChunksEntity = ChunkUtils.getChunksInRange(new Position(16 * newChunk.getChunkX(), 0, 16 * newChunk.getChunkZ()), MinecraftServer.ENTITY_VIEW_DISTANCE); final long[] lastVisibleChunksEntity = ChunkUtils.getChunksInRange(new Position(16 * lastChunk.getChunkX(), 0, 16 * lastChunk.getChunkZ()), entityViewDistance);
final long[] updatedVisibleChunksEntity = ChunkUtils.getChunksInRange(new Position(16 * newChunk.getChunkX(), 0, 16 * newChunk.getChunkZ()), entityViewDistance);
// Remove from previous chunks // Remove from previous chunks
final int[] oldChunksEntity = ArrayUtils.getDifferencesBetweenArray(lastVisibleChunksEntity, updatedVisibleChunksEntity); final int[] oldChunksEntity = ArrayUtils.getDifferencesBetweenArray(lastVisibleChunksEntity, updatedVisibleChunksEntity);

View File

@ -195,7 +195,7 @@ public class Player extends LivingEntity implements CommandSender {
joinGamePacket.dimensionType = dimensionType; joinGamePacket.dimensionType = dimensionType;
joinGamePacket.maxPlayers = 0; // Unused joinGamePacket.maxPlayers = 0; // Unused
joinGamePacket.levelType = levelType; joinGamePacket.levelType = levelType;
joinGamePacket.viewDistance = MinecraftServer.CHUNK_VIEW_DISTANCE; joinGamePacket.viewDistance = MinecraftServer.getChunkViewDistance();
joinGamePacket.reducedDebugInfo = false; joinGamePacket.reducedDebugInfo = false;
playerConnection.sendPacket(joinGamePacket); playerConnection.sendPacket(joinGamePacket);
@ -2124,11 +2124,11 @@ public class Player extends LivingEntity implements CommandSender {
/** /**
* @return the chunk range of the viewers, * @return the chunk range of the viewers,
* which is {@link MinecraftServer#CHUNK_VIEW_DISTANCE} or {@link PlayerSettings#getViewDistance()} * which is {@link MinecraftServer#getChunkViewDistance()} or {@link PlayerSettings#getViewDistance()}
* based on which one is the lowest * based on which one is the lowest
*/ */
public int getChunkRange() { public int getChunkRange() {
final int serverRange = MinecraftServer.CHUNK_VIEW_DISTANCE; final int serverRange = MinecraftServer.getChunkViewDistance();
final int playerRange = getSettings().viewDistance; final int playerRange = getSettings().viewDistance;
if (playerRange == 0) { if (playerRange == 0) {
return serverRange; // Didn't receive settings packet yet (is the case on login) return serverRange; // Didn't receive settings packet yet (is the case on login)

View File

@ -2,6 +2,7 @@ package net.minestom.server.extras.mojangAuth;
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.jetbrains.annotations.Nullable;
import javax.crypto.*; import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.IvParameterSpec;
@ -10,83 +11,86 @@ import java.io.UnsupportedEncodingException;
import java.security.*; import java.security.*;
public class MojangCrypt { public class MojangCrypt {
private static final Logger LOGGER = LogManager.getLogger(); private static final Logger LOGGER = LogManager.getLogger();
public static KeyPair generateKeyPair() { @Nullable
try { public static KeyPair generateKeyPair() {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); try {
keyGen.initialize(1024); KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
return keyGen.generateKeyPair(); keyGen.initialize(1024);
} catch (NoSuchAlgorithmException e) { return keyGen.generateKeyPair();
e.printStackTrace(); } catch (NoSuchAlgorithmException e) {
LOGGER.error("Key pair generation failed!"); e.printStackTrace();
return null; LOGGER.error("Key pair generation failed!");
} return null;
} }
}
public static byte[] digestData(String data, PublicKey publicKey, SecretKey secretKey) { @Nullable
try { public static byte[] digestData(String data, PublicKey publicKey, SecretKey secretKey) {
return digestData("SHA-1", data.getBytes("ISO_8859_1"), secretKey.getEncoded(), publicKey.getEncoded()); try {
} catch (UnsupportedEncodingException e) { return digestData("SHA-1", data.getBytes("ISO_8859_1"), secretKey.getEncoded(), publicKey.getEncoded());
e.printStackTrace(); } catch (UnsupportedEncodingException e) {
return null; e.printStackTrace();
} return null;
} }
}
private static byte[] digestData(String algorithm, byte[]... data) { @Nullable
try { private static byte[] digestData(String algorithm, byte[]... data) {
MessageDigest digest = MessageDigest.getInstance(algorithm); try {
MessageDigest digest = MessageDigest.getInstance(algorithm);
for(byte[] bytes : data) { for (byte[] bytes : data) {
digest.update(bytes); digest.update(bytes);
} }
return digest.digest(); return digest.digest();
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
e.printStackTrace(); e.printStackTrace();
return null; return null;
} }
} }
public static SecretKey decryptByteToSecretKey(PrivateKey privateKey, byte[] bytes) { public static SecretKey decryptByteToSecretKey(PrivateKey privateKey, byte[] bytes) {
return new SecretKeySpec(decryptUsingKey(privateKey, bytes), "AES"); return new SecretKeySpec(decryptUsingKey(privateKey, bytes), "AES");
} }
public static byte[] decryptUsingKey(Key key, byte[] bytes) { public static byte[] decryptUsingKey(Key key, byte[] bytes) {
return cipherData(2, key, bytes); return cipherData(2, key, bytes);
} }
private static byte[] cipherData(int mode, Key key, byte[] data) { private static byte[] cipherData(int mode, Key key, byte[] data) {
try { try {
return setupCipher(mode, key.getAlgorithm(), key).doFinal(data); return setupCipher(mode, key.getAlgorithm(), key).doFinal(data);
} catch (IllegalBlockSizeException | BadPaddingException var4) { } catch (IllegalBlockSizeException | BadPaddingException var4) {
var4.printStackTrace(); var4.printStackTrace();
} }
LOGGER.error("Cipher data failed!"); LOGGER.error("Cipher data failed!");
return null; return null;
} }
private static Cipher setupCipher(int mode, String transformation, Key key) { private static Cipher setupCipher(int mode, String transformation, Key key) {
try { try {
Cipher cipher4 = Cipher.getInstance(transformation); Cipher cipher4 = Cipher.getInstance(transformation);
cipher4.init(mode, key); cipher4.init(mode, key);
return cipher4; return cipher4;
} catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException var4) { } catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException var4) {
var4.printStackTrace(); var4.printStackTrace();
} }
LOGGER.error("Cipher creation failed!"); LOGGER.error("Cipher creation failed!");
return null; return null;
} }
public static Cipher getCipher(int mode, Key key) { public static Cipher getCipher(int mode, Key key) {
try { try {
Cipher cipher3 = Cipher.getInstance("AES/CFB8/NoPadding"); Cipher cipher3 = Cipher.getInstance("AES/CFB8/NoPadding");
cipher3.init(mode, key, new IvParameterSpec(key.getEncoded())); cipher3.init(mode, key, new IvParameterSpec(key.getEncoded()));
return cipher3; return cipher3;
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
} }

View File

@ -824,7 +824,8 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
} }
AddEntityToInstanceEvent event = new AddEntityToInstanceEvent(this, entity); AddEntityToInstanceEvent event = new AddEntityToInstanceEvent(this, entity);
callCancellableEvent(AddEntityToInstanceEvent.class, event, () -> { callCancellableEvent(AddEntityToInstanceEvent.class, event, () -> {
final long[] visibleChunksEntity = ChunkUtils.getChunksInRange(entity.getPosition(), MinecraftServer.ENTITY_VIEW_DISTANCE); final Position entityPosition = entity.getPosition();
final long[] visibleChunksEntity = ChunkUtils.getChunksInRange(entityPosition, MinecraftServer.getEntityViewDistance());
final boolean isPlayer = entity instanceof Player; final boolean isPlayer = entity instanceof Player;
if (isPlayer) { if (isPlayer) {
@ -846,7 +847,6 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
}); });
} }
final Position entityPosition = entity.getPosition();
final Chunk chunk = getChunkAt(entityPosition); final Chunk chunk = getChunkAt(entityPosition);
Check.notNull(chunk, "You tried to spawn an entity in an unloaded chunk, " + entityPosition); Check.notNull(chunk, "You tried to spawn an entity in an unloaded chunk, " + entityPosition);
addEntityToChunk(entity, chunk); addEntityToChunk(entity, chunk);

View File

@ -216,7 +216,7 @@ public final class ConnectionManager {
* Adds a new {@link Player} in the players list. * Adds a new {@link Player} in the players list.
* Is currently used at * Is currently used at
* {@link LoginStartPacket#process(PlayerConnection)} * {@link LoginStartPacket#process(PlayerConnection)}
* and in {@link FakePlayer#initPlayer(UUID, String, Consumer)} * and in {@link FakePlayer#initPlayer(UUID, String, Consumer)}.
* *
* @param player the player to add * @param player the player to add
*/ */

View File

@ -3,15 +3,16 @@ package net.minestom.server.network.packet.client;
import net.minestom.server.MinecraftServer; import net.minestom.server.MinecraftServer;
import net.minestom.server.network.ConnectionManager; import net.minestom.server.network.ConnectionManager;
import net.minestom.server.network.player.PlayerConnection; import net.minestom.server.network.player.PlayerConnection;
import org.jetbrains.annotations.NotNull;
public interface ClientPreplayPacket extends ClientPacket { public interface ClientPreplayPacket extends ClientPacket {
ConnectionManager CONNECTION_MANAGER = MinecraftServer.getConnectionManager(); ConnectionManager CONNECTION_MANAGER = MinecraftServer.getConnectionManager();
/** /**
* Called when this packet is received * Called when the packet is received.
* *
* @param connection the connection who sent the packet * @param connection the connection who sent the packet
*/ */
void process(PlayerConnection connection); void process(@NotNull PlayerConnection connection);
} }

View File

@ -9,6 +9,7 @@ import net.minestom.server.network.packet.server.login.LoginDisconnect;
import net.minestom.server.network.player.NettyPlayerConnection; import net.minestom.server.network.player.NettyPlayerConnection;
import net.minestom.server.network.player.PlayerConnection; import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.utils.binary.BinaryReader; import net.minestom.server.utils.binary.BinaryReader;
import org.jetbrains.annotations.NotNull;
public class HandshakePacket implements ClientPreplayPacket { public class HandshakePacket implements ClientPreplayPacket {
@ -31,7 +32,7 @@ public class HandshakePacket implements ClientPreplayPacket {
} }
@Override @Override
public void process(PlayerConnection connection) { public void process(@NotNull PlayerConnection connection) {
switch (nextState) { switch (nextState) {
case 1: case 1:
connection.setConnectionState(ConnectionState.STATUS); connection.setConnectionState(ConnectionState.STATUS);

View File

@ -11,6 +11,7 @@ import net.minestom.server.network.packet.server.login.LoginSuccessPacket;
import net.minestom.server.network.player.NettyPlayerConnection; import net.minestom.server.network.player.NettyPlayerConnection;
import net.minestom.server.network.player.PlayerConnection; import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.utils.binary.BinaryReader; import net.minestom.server.utils.binary.BinaryReader;
import org.jetbrains.annotations.NotNull;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
import java.math.BigInteger; import java.math.BigInteger;
@ -20,28 +21,45 @@ import java.util.concurrent.atomic.AtomicInteger;
public class EncryptionResponsePacket implements ClientPreplayPacket { public class EncryptionResponsePacket implements ClientPreplayPacket {
private final static String THREAD_NAME = "Mojang Auth Thread"; private final static String THREAD_NAME = "Mojang Auth Thread";
private static AtomicInteger UNIQUE_THREAD_ID = new AtomicInteger(0); private static final AtomicInteger UNIQUE_THREAD_ID = new AtomicInteger(0);
private byte[] sharedSecret; private byte[] sharedSecret;
private byte[] verifyToken; private byte[] verifyToken;
@Override @Override
public void process(PlayerConnection connection) { public void process(@NotNull PlayerConnection connection) {
// Encryption is only support for netty connection
if (!(connection instanceof NettyPlayerConnection)) {
return;
}
new Thread(THREAD_NAME + " #" + UNIQUE_THREAD_ID.incrementAndGet()) { new Thread(THREAD_NAME + " #" + UNIQUE_THREAD_ID.incrementAndGet()) {
public void run() { public void run() {
try { try {
if (!Arrays.equals(connection.getNonce(), getNonce())) { if (!Arrays.equals(connection.getNonce(), getNonce())) {
System.out.println(connection.getLoginUsername() + " tried to login with an invalid nonce!"); MinecraftServer.getLOGGER().error(connection.getLoginUsername() + " tried to login with an invalid nonce!");
return; return;
} }
if (!connection.getLoginUsername().isEmpty()) { if (!connection.getLoginUsername().isEmpty()) {
final String string3 = new BigInteger(MojangCrypt.digestData("", MinecraftServer.getKeyPair().getPublic(), getSecretKey())).toString(16); final NettyPlayerConnection nettyConnection = (NettyPlayerConnection) connection;
final GameProfile gameProfile = MinecraftServer.getSessionService().hasJoinedServer(new GameProfile(null, connection.getLoginUsername()), string3);
((NettyPlayerConnection) connection).setEncryptionKey(getSecretKey());
final int threshold = MinecraftServer.COMPRESSION_THRESHOLD;
if (threshold > 0 && connection instanceof NettyPlayerConnection) { final byte[] digestedData = MojangCrypt.digestData("", MinecraftServer.getKeyPair().getPublic(), getSecretKey());
((NettyPlayerConnection) connection).enableCompression(threshold);
if (digestedData == null) {
// Incorrect key, probably because of the client
MinecraftServer.getLOGGER().error("Connection " + nettyConnection.getRemoteAddress() + " failed initializing encryption.");
connection.disconnect();
return;
}
final String string3 = new BigInteger(digestedData).toString(16);
final GameProfile gameProfile = MinecraftServer.getSessionService().hasJoinedServer(new GameProfile(null, connection.getLoginUsername()), string3);
nettyConnection.setEncryptionKey(getSecretKey());
final int threshold = MinecraftServer.getCompressionThreshold();
if (threshold > 0) {
nettyConnection.enableCompression(threshold);
} }
LoginSuccessPacket loginSuccessPacket = new LoginSuccessPacket(gameProfile.getId(), gameProfile.getName()); LoginSuccessPacket loginSuccessPacket = new LoginSuccessPacket(gameProfile.getId(), gameProfile.getName());

View File

@ -12,6 +12,7 @@ import net.minestom.server.network.packet.server.login.LoginSuccessPacket;
import net.minestom.server.network.player.NettyPlayerConnection; import net.minestom.server.network.player.NettyPlayerConnection;
import net.minestom.server.network.player.PlayerConnection; import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.utils.binary.BinaryReader; import net.minestom.server.utils.binary.BinaryReader;
import org.jetbrains.annotations.NotNull;
import java.util.UUID; import java.util.UUID;
@ -23,7 +24,7 @@ public class LoginStartPacket implements ClientPreplayPacket {
public String username; public String username;
@Override @Override
public void process(PlayerConnection connection) { public void process(@NotNull PlayerConnection connection) {
if (MojangAuth.isUsingMojangAuth()) { if (MojangAuth.isUsingMojangAuth()) {
if (CONNECTION_MANAGER.getPlayer(username) != null) { if (CONNECTION_MANAGER.getPlayer(username) != null) {
connection.sendPacket(new LoginDisconnect(ALREADY_CONNECTED_JSON)); connection.sendPacket(new LoginDisconnect(ALREADY_CONNECTED_JSON));
@ -38,7 +39,7 @@ public class LoginStartPacket implements ClientPreplayPacket {
} else { } else {
final UUID playerUuid = CONNECTION_MANAGER.getPlayerConnectionUuid(connection, username); final UUID playerUuid = CONNECTION_MANAGER.getPlayerConnectionUuid(connection, username);
final int threshold = MinecraftServer.COMPRESSION_THRESHOLD; final int threshold = MinecraftServer.getCompressionThreshold();
if (threshold > 0 && connection instanceof NettyPlayerConnection) { if (threshold > 0 && connection instanceof NettyPlayerConnection) {
((NettyPlayerConnection) connection).enableCompression(threshold); ((NettyPlayerConnection) connection).enableCompression(threshold);

View File

@ -3,13 +3,14 @@ package net.minestom.server.network.packet.client.status;
import net.minestom.server.network.packet.client.ClientPreplayPacket; import net.minestom.server.network.packet.client.ClientPreplayPacket;
import net.minestom.server.network.player.PlayerConnection; import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.utils.binary.BinaryReader; import net.minestom.server.utils.binary.BinaryReader;
import org.jetbrains.annotations.NotNull;
public class LegacyServerListPingPacket implements ClientPreplayPacket { public class LegacyServerListPingPacket implements ClientPreplayPacket {
private byte payload; private byte payload;
@Override @Override
public void process(PlayerConnection connection) { public void process(@NotNull PlayerConnection connection) {
} }

View File

@ -4,13 +4,14 @@ import net.minestom.server.network.packet.client.ClientPreplayPacket;
import net.minestom.server.network.packet.server.status.PongPacket; import net.minestom.server.network.packet.server.status.PongPacket;
import net.minestom.server.network.player.PlayerConnection; import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.utils.binary.BinaryReader; import net.minestom.server.utils.binary.BinaryReader;
import org.jetbrains.annotations.NotNull;
public class PingPacket implements ClientPreplayPacket { public class PingPacket implements ClientPreplayPacket {
private long number; private long number;
@Override @Override
public void process(PlayerConnection connection) { public void process(@NotNull PlayerConnection connection) {
PongPacket pongPacket = new PongPacket(number); PongPacket pongPacket = new PongPacket(number);
connection.sendPacket(pongPacket); connection.sendPacket(pongPacket);
connection.disconnect(); connection.disconnect();

View File

@ -7,11 +7,12 @@ import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.ping.ResponseData; import net.minestom.server.ping.ResponseData;
import net.minestom.server.ping.ResponseDataConsumer; import net.minestom.server.ping.ResponseDataConsumer;
import net.minestom.server.utils.binary.BinaryReader; import net.minestom.server.utils.binary.BinaryReader;
import org.jetbrains.annotations.NotNull;
public class StatusRequestPacket implements ClientPreplayPacket { public class StatusRequestPacket implements ClientPreplayPacket {
@Override @Override
public void process(PlayerConnection connection) { public void process(@NotNull PlayerConnection connection) {
ResponseDataConsumer consumer = MinecraftServer.getResponseDataConsumer(); ResponseDataConsumer consumer = MinecraftServer.getResponseDataConsumer();
ResponseData responseData = new ResponseData(); ResponseData responseData = new ResponseData();

View File

@ -23,7 +23,7 @@ public final class EntityUtils {
final Chunk chunk = ent1.getInstance().getChunkAt(ent1.getPosition()); final Chunk chunk = ent1.getInstance().getChunkAt(ent1.getPosition());
long[] visibleChunksEntity = ChunkUtils.getChunksInRange(ent2.getPosition(), MinecraftServer.ENTITY_VIEW_DISTANCE); final long[] visibleChunksEntity = ChunkUtils.getChunksInRange(ent2.getPosition(), MinecraftServer.getEntityViewDistance());
for (long visibleChunk : visibleChunksEntity) { for (long visibleChunk : visibleChunksEntity) {
final int chunkX = ChunkUtils.getChunkCoordX(visibleChunk); final int chunkX = ChunkUtils.getChunkCoordX(visibleChunk);
final int chunkZ = ChunkUtils.getChunkCoordZ(visibleChunk); final int chunkZ = ChunkUtils.getChunkCoordZ(visibleChunk);