This commit is contained in:
Felix Cravic 2020-07-23 07:36:49 +02:00
parent 01cb95c9b2
commit 5c1e6e7572
32 changed files with 434 additions and 334 deletions

View File

@ -52,6 +52,11 @@ public class CommandManager {
consoleThread.start();
}
/**
* Stop the console responsive for the console commands processing
* <p>
* WARNING: it cannot be re-run later
*/
public void stopConsoleThread() {
running = false;
}
@ -334,7 +339,7 @@ public class CommandManager {
}
if (lastNodes != null) {
int[] children = ArrayUtils.toArray(argChildren);
final int[] children = ArrayUtils.toArray(argChildren);
lastNodes.forEach(n -> n.children = children);
}
@ -347,7 +352,7 @@ public class CommandManager {
if (isLast) {
// Last argument doesn't have children
int[] children = new int[0];
final int[] children = new int[0];
argumentNodes.forEach(node -> node.children = children);
} else {
// Create children list which will be filled during next iteration
@ -357,7 +362,7 @@ public class CommandManager {
}
}
int[] children = ArrayUtils.toArray(cmdChildren);
final int[] children = ArrayUtils.toArray(cmdChildren);
//System.out.println("test " + children.length + " : " + children[0]);
literalNode.children = children;
if (children.length > 0) {

View File

@ -70,6 +70,8 @@ public final class DataManager {
}
/**
* Get the data type associated with a class
*
* @param clazz the data class
* @param <T> the data type
* @return the {@link DataType} associated to the class

View File

@ -1,10 +1,15 @@
package net.minestom.server.event;
/**
* Represent an event which can be cancelled
*/
public class CancellableEvent extends Event {
private boolean cancelled;
/**
* Get if the event will be cancelled or not
*
* @return true if the event should be cancelled, false otherwise
*/
public boolean isCancelled() {
@ -12,6 +17,8 @@ public class CancellableEvent extends Event {
}
/**
* Mark the event as cancelled or not
*
* @param cancel true if the event should be cancelled, false otherwise
*/
public void setCancelled(boolean cancel) {

View File

@ -102,7 +102,7 @@ public final class Chunk implements Viewable {
}
private void setBlock(int x, int y, int z, short blockId, short customId, Data data, UpdateConsumer updateConsumer) {
int index = getBlockIndex(x, y, z);
final int index = getBlockIndex(x, y, z);
if (blockId != 0
|| (blockId == 0 && customId != 0 && updateConsumer != null)) { // Allow custom air block for update purpose, refused if no update consumer has been found
this.blocksId[index] = blockId;
@ -149,7 +149,7 @@ public final class Chunk implements Viewable {
}
public void setBlockData(int x, int y, int z, Data data) {
int index = getBlockIndex(x, y, z);
final int index = getBlockIndex(x, y, z);
if (data != null) {
this.blocksData.put(index, data);
} else {
@ -158,39 +158,39 @@ public final class Chunk implements Viewable {
}
public short getBlockId(int x, int y, int z) {
int index = getBlockIndex(x, y, z);
final int index = getBlockIndex(x, y, z);
if (!MathUtils.isBetween(index, 0, blocksId.length)) {
return 0; // TODO: custom invalid block
}
short id = blocksId[index];
final short id = blocksId[index];
return id;
}
public short getCustomBlockId(int x, int y, int z) {
int index = getBlockIndex(x, y, z);
final int index = getBlockIndex(x, y, z);
if (!MathUtils.isBetween(index, 0, blocksId.length)) {
return 0; // TODO: custom invalid block
}
short id = customBlocksId[index];
final short id = customBlocksId[index];
return id;
}
public CustomBlock getCustomBlock(int x, int y, int z) {
int index = getBlockIndex(x, y, z);
final int index = getBlockIndex(x, y, z);
if (!MathUtils.isBetween(index, 0, blocksId.length)) {
return null; // TODO: custom invalid block
}
short id = customBlocksId[index];
final short id = customBlocksId[index];
return id != 0 ? BLOCK_MANAGER.getCustomBlock(id) : null;
}
protected CustomBlock getCustomBlock(int index) {
int[] pos = ChunkUtils.indexToChunkPosition(index);
final int[] pos = ChunkUtils.indexToChunkPosition(index);
return getCustomBlock(pos[0], pos[1], pos[2]);
}
protected void refreshBlockValue(int x, int y, int z, short blockId, short customId) {
int blockIndex = getBlockIndex(x, y, z);
final int blockIndex = getBlockIndex(x, y, z);
if (!MathUtils.isBetween(blockIndex, 0, blocksId.length)) {
return;
}
@ -200,7 +200,7 @@ public final class Chunk implements Viewable {
}
protected void refreshBlockId(int x, int y, int z, short blockId) {
int blockIndex = getBlockIndex(x, y, z);
final int blockIndex = getBlockIndex(x, y, z);
if (!MathUtils.isBetween(blockIndex, 0, blocksId.length)) {
return;
}
@ -209,13 +209,13 @@ public final class Chunk implements Viewable {
}
protected void refreshBlockValue(int x, int y, int z, short blockId) {
CustomBlock customBlock = getCustomBlock(x, y, z);
short customBlockId = customBlock == null ? 0 : customBlock.getCustomBlockId();
final CustomBlock customBlock = getCustomBlock(x, y, z);
final short customBlockId = customBlock == null ? 0 : customBlock.getCustomBlockId();
refreshBlockValue(x, y, z, blockId, customBlockId);
}
public Data getData(int x, int y, int z) {
int index = getBlockIndex(x, y, z);
final int index = getBlockIndex(x, y, z);
return getData(index);
}
@ -243,12 +243,12 @@ public final class Chunk implements Viewable {
this.updatableBlocksLastUpdate.put(index, time); // Refresh last update time
final int[] blockPos = ChunkUtils.indexToPosition(index, chunkX, chunkZ);
int x = blockPos[0];
int y = blockPos[1];
int z = blockPos[2];
final int x = blockPos[0];
final int y = blockPos[1];
final int z = blockPos[2];
BlockPosition blockPosition = new BlockPosition(x, y, z);
Data data = getData(index);
final BlockPosition blockPosition = new BlockPosition(x, y, z);
final Data data = getData(index);
customBlock.update(instance, blockPosition, data);
}
}
@ -270,7 +270,7 @@ public final class Chunk implements Viewable {
}
private boolean isBlockEntity(short blockId) {
Block block = Block.fromId(blockId);
final Block block = Block.fromId(blockId);
return block.hasBlockEntity();
}
@ -294,16 +294,15 @@ public final class Chunk implements Viewable {
for (byte x = 0; x < CHUNK_SIZE_X; x++) {
for (short y = 0; y < CHUNK_SIZE_Y; y++) {
for (byte z = 0; z < CHUNK_SIZE_Z; z++) {
int index = getBlockIndex(x, y, z);
final int index = getBlockIndex(x, y, z);
short blockId = blocksId[index];
short customBlockId = customBlocksId[index];
final short blockId = blocksId[index];
final short customBlockId = customBlocksId[index];
if (blockId == 0 && customBlockId == 0)
continue;
Data data = blocksData.get(index);
boolean hasData = data != null;
final Data data = blocksData.get(index);
// Chunk coordinates
dos.writeInt(x);
@ -315,10 +314,10 @@ public final class Chunk implements Viewable {
dos.writeShort(customBlockId);
// Data
hasData = (data != null && (data instanceof SerializableData)) && hasData;
final boolean hasData = (data != null && (data instanceof SerializableData));
dos.writeBoolean(hasData);
if (hasData) {
byte[] d = ((SerializableData) data).getSerializedData();
final byte[] d = ((SerializableData) data).getSerializedData();
dos.writeInt(d.length);
dos.write(d);
}
@ -326,7 +325,7 @@ public final class Chunk implements Viewable {
}
}
byte[] result = output.toByteArray();
final byte[] result = output.toByteArray();
return result;
}
@ -359,7 +358,7 @@ public final class Chunk implements Viewable {
// Write the packet in the current thread
public void refreshDataPacket() {
ByteBuf buffer = PacketUtils.writePacket(getFreshFullDataPacket());
final ByteBuf buffer = PacketUtils.writePacket(getFreshFullDataPacket());
setFullDataPacket(buffer);
}
@ -389,7 +388,7 @@ public final class Chunk implements Viewable {
// UNSAFE
@Override
public boolean addViewer(Player player) {
boolean result = this.viewers.add(player);
final boolean result = this.viewers.add(player);
PlayerChunkLoadEvent playerChunkLoadEvent = new PlayerChunkLoadEvent(player, chunkX, chunkZ);
player.callEvent(PlayerChunkLoadEvent.class, playerChunkLoadEvent);
@ -399,7 +398,7 @@ public final class Chunk implements Viewable {
// UNSAFE
@Override
public boolean removeViewer(Player player) {
boolean result = this.viewers.remove(player);
final boolean result = this.viewers.remove(player);
PlayerChunkUnloadEvent playerChunkUnloadEvent = new PlayerChunkUnloadEvent(player, chunkX, chunkZ);
player.callEvent(PlayerChunkUnloadEvent.class, playerChunkUnloadEvent);

View File

@ -42,6 +42,7 @@ public abstract class Explosion {
/**
* Prepares the list of blocks that will be broken. Also pushes and damage entities affected by this explosion
*
* @param instance instance to perform this explosion in
* @return list of blocks that will be broken.
*/
@ -49,6 +50,7 @@ public abstract class Explosion {
/**
* Performs the explosion and send the corresponding packet
*
* @param instance instance to perform this explosion in
*/
public void apply(Instance instance) {
@ -62,16 +64,16 @@ public abstract class Explosion {
packet.playerMotionY = 0.0f; // TODO: figure out why this is here
packet.playerMotionZ = 0.0f; // TODO: figure out why this is here
packet.records = new byte[3*blocks.size()];
packet.records = new byte[3 * blocks.size()];
for (int i = 0; i < blocks.size(); i++) {
BlockPosition pos = blocks.get(i);
final BlockPosition pos = blocks.get(i);
instance.setBlock(pos, Block.AIR);
byte x = (byte) (pos.getX()-Math.floor(getCenterX()));
byte y = (byte) (pos.getY()-Math.floor(getCenterY()));
byte z = (byte) (pos.getZ()-Math.floor(getCenterZ()));
packet.records[i*3+0] = x;
packet.records[i*3+1] = y;
packet.records[i*3+2] = z;
final byte x = (byte) (pos.getX() - Math.floor(getCenterX()));
final byte y = (byte) (pos.getY() - Math.floor(getCenterY()));
final byte z = (byte) (pos.getZ() - Math.floor(getCenterZ()));
packet.records[i * 3 + 0] = x;
packet.records[i * 3 + 1] = y;
packet.records[i * 3 + 2] = z;
}
postExplosion(instance, blocks, packet);
@ -85,20 +87,24 @@ public abstract class Explosion {
/**
* Called after removing blocks and preparing the packet, but before sending it.
*
* @param instance the instance in which the explosion occurs
* @param blocks the block positions returned by prepare
* @param packet the explosion packet to sent to the client. Be careful with what you're doing.
* It is initialized with the center and radius of the explosion. The positions in 'blocks' are also
* stored in the packet before this call, but you are free to modify 'records' to modify the blocks sent to the client.
* Just be careful, you might just crash the server or the client. Or you're lucky, both at the same time.
* @param blocks the block positions returned by prepare
* @param packet the explosion packet to sent to the client. Be careful with what you're doing.
* It is initialized with the center and radius of the explosion. The positions in 'blocks' are also
* stored in the packet before this call, but you are free to modify 'records' to modify the blocks sent to the client.
* Just be careful, you might just crash the server or the client. Or you're lucky, both at the same time.
*/
protected void postExplosion(Instance instance, List<BlockPosition> blocks, ExplosionPacket packet) {}
protected void postExplosion(Instance instance, List<BlockPosition> blocks, ExplosionPacket packet) {
}
/**
* Called after sending the explosion packet. Can be used to (re)set blocks that have been destroyed.
* This is necessary to do after the packet being sent, because the client sets the positions received to air.
*
* @param instance the instance in which the explosion occurs
* @param blocks the block positions returned by prepare
* @param blocks the block positions returned by prepare
*/
protected void postSend(Instance instance, List<BlockPosition> blocks) {}
protected void postSend(Instance instance, List<BlockPosition> blocks) {
}
}

View File

@ -7,10 +7,11 @@ public interface ExplosionSupplier {
/**
* Creates a new explosion
* @param centerX center of the explosion
* @param centerY center of the explosion
* @param centerZ center of the explosion
* @param strength strength of the explosion
*
* @param centerX center of the explosion
* @param centerY center of the explosion
* @param centerZ center of the explosion
* @param strength strength of the explosion
* @param additionalData data passed via {@link Instance#explode)}. Can be null
* @return Explosion object representing the algorithm to use
*/

View File

@ -267,7 +267,7 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
}
protected void sendChunkUpdate(Collection<Player> players, Chunk chunk) {
ByteBuf chunkData = chunk.getFullDataPacket();
final ByteBuf chunkData = chunk.getFullDataPacket();
players.forEach(player -> {
if (!PlayerUtils.isNettyClient(player))
return;
@ -471,14 +471,14 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
}
public void loadChunk(Position position, Consumer<Chunk> callback) {
int chunkX = ChunkUtils.getChunkCoordinate((int) position.getX());
int chunkZ = ChunkUtils.getChunkCoordinate((int) position.getZ());
final int chunkX = ChunkUtils.getChunkCoordinate((int) position.getX());
final int chunkZ = ChunkUtils.getChunkCoordinate((int) position.getZ());
loadChunk(chunkX, chunkZ, callback);
}
public void loadOptionalChunk(Position position, Consumer<Chunk> callback) {
int chunkX = ChunkUtils.getChunkCoordinate((int) position.getX());
int chunkZ = ChunkUtils.getChunkCoordinate((int) position.getZ());
final int chunkX = ChunkUtils.getChunkCoordinate((int) position.getX());
final int chunkZ = ChunkUtils.getChunkCoordinate((int) position.getZ());
loadOptionalChunk(chunkX, chunkZ, callback);
}
@ -487,8 +487,8 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
}
public short getBlockId(int x, int y, int z) {
Chunk chunk = getChunkAt(x, z);
Check.notNull(chunk, "The chunk at " + x + ": " + z + " is not loaded");
final Chunk chunk = getChunkAt(x, z);
Check.notNull(chunk, "The chunk at " + x + ":" + z + " is not loaded");
return chunk.getBlockId(x, y, z);
}
@ -501,8 +501,8 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
}
public CustomBlock getCustomBlock(int x, int y, int z) {
Chunk chunk = getChunkAt(x, z);
Check.notNull(chunk, "The chunk at " + x + ": " + z + " is not loaded");
final Chunk chunk = getChunkAt(x, z);
Check.notNull(chunk, "The chunk at " + x + ":" + z + " is not loaded");
return chunk.getCustomBlock(x, y, z);
}
@ -520,13 +520,13 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
blockActionPacket.actionParam = actionParam;
blockActionPacket.blockId = block.getBlockId();
Chunk chunk = getChunkAt(blockPosition);
final Chunk chunk = getChunkAt(blockPosition);
chunk.sendPacketToViewers(blockActionPacket);
}
public Data getBlockData(int x, int y, int z) {
Chunk chunk = getChunkAt(x, z);
Check.notNull(chunk, "The chunk at " + x + ": " + z + " is not loaded");
final Chunk chunk = getChunkAt(x, z);
Check.notNull(chunk, "The chunk at " + x + ":" + z + " is not loaded");
return chunk.getData(x, (byte) y, z);
}
@ -535,8 +535,8 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
}
public Chunk getChunkAt(double x, double z) {
int chunkX = ChunkUtils.getChunkCoordinate((int) x);
int chunkZ = ChunkUtils.getChunkCoordinate((int) z);
final int chunkX = ChunkUtils.getChunkCoordinate((int) x);
final int chunkZ = ChunkUtils.getChunkCoordinate((int) z);
return getChunk(chunkX, chunkZ);
}
@ -609,17 +609,17 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
* @param entity the entity to add
*/
public void addEntity(Entity entity) {
Instance lastInstance = entity.getInstance();
final Instance lastInstance = entity.getInstance();
if (lastInstance != null && lastInstance != this) {
lastInstance.removeEntity(entity); // If entity is in another instance, remove it from there and add it to this
}
AddEntityToInstanceEvent event = new AddEntityToInstanceEvent(this, entity);
callCancellableEvent(AddEntityToInstanceEvent.class, event, () -> {
long[] visibleChunksEntity = ChunkUtils.getChunksInRange(entity.getPosition(), MinecraftServer.ENTITY_VIEW_DISTANCE);
boolean isPlayer = entity instanceof Player;
final long[] visibleChunksEntity = ChunkUtils.getChunksInRange(entity.getPosition(), MinecraftServer.ENTITY_VIEW_DISTANCE);
final boolean isPlayer = entity instanceof Player;
if (isPlayer) {
Player player = (Player) entity;
final Player player = (Player) entity;
sendChunks(player);
getWorldBorder().init(player);
}
@ -638,7 +638,7 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
});
}
Chunk chunk = getChunkAt(entity.getPosition());
final Chunk chunk = getChunkAt(entity.getPosition());
addEntityToChunk(entity, chunk);
});
}
@ -651,7 +651,7 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
* @param entity the entity to remove
*/
public void removeEntity(Entity entity) {
Instance entityInstance = entity.getInstance();
final Instance entityInstance = entity.getInstance();
if (entityInstance == null || entityInstance != this)
return;
@ -662,7 +662,7 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
entity.getViewers().forEach(p -> entity.removeViewer(p));
}
Chunk chunk = getChunkAt(entity.getPosition());
final Chunk chunk = getChunkAt(entity.getPosition());
removeEntityFromChunk(entity, chunk);
});
}
@ -679,7 +679,7 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
Check.notNull(chunk,
"The chunk " + chunk + " is not loaded, you can make it automatic by using Instance#enableAutoChunkLoad(true)");
Check.argCondition(!chunk.isLoaded(), "Chunk " + chunk + " has been unloaded previously");
long chunkIndex = ChunkUtils.getChunkIndex(chunk.getChunkX(), chunk.getChunkZ());
final long chunkIndex = ChunkUtils.getChunkIndex(chunk.getChunkX(), chunk.getChunkZ());
synchronized (chunkEntities) {
Set<Entity> entities = getEntitiesInChunk(chunkIndex);
entities.add(entity);
@ -708,7 +708,7 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
public void removeEntityFromChunk(Entity entity, Chunk chunk) {
synchronized (chunkEntities) {
if (chunk != null) {
long chunkIndex = ChunkUtils.getChunkIndex(chunk.getChunkX(), chunk.getChunkZ());
final long chunkIndex = ChunkUtils.getChunkIndex(chunk.getChunkX(), chunk.getChunkZ());
Set<Entity> entities = getEntitiesInChunk(chunkIndex);
entities.remove(entity);
if (entities.isEmpty()) {
@ -800,7 +800,7 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
* @throws IllegalStateException If no {@link ExplosionSupplier} was supplied
*/
public void explode(float centerX, float centerY, float centerZ, float strength, Data additionalData) {
ExplosionSupplier explosionSupplier = getExplosionSupplier();
final ExplosionSupplier explosionSupplier = getExplosionSupplier();
if (explosionSupplier == null)
throw new IllegalStateException("Tried to create an explosion with no explosion supplier");
Explosion explosion = explosionSupplier.createExplosion(centerX, centerY, centerZ, strength, additionalData);

View File

@ -75,7 +75,7 @@ public class InstanceContainer extends Instance {
// Retrieve instance data
this.uniqueId = storageFolder.getOrDefault(UUID_KEY, UUID.class, uniqueId);
Data data = storageFolder.getOrDefault(DATA_KEY, SerializableData.class, null);
final Data data = storageFolder.getOrDefault(DATA_KEY, SerializableData.class, null);
setData(data);
}
@ -86,23 +86,23 @@ public class InstanceContainer extends Instance {
@Override
public void setCustomBlock(int x, int y, int z, short customBlockId, Data data) {
CustomBlock customBlock = BLOCK_MANAGER.getCustomBlock(customBlockId);
final CustomBlock customBlock = BLOCK_MANAGER.getCustomBlock(customBlockId);
setBlock(x, y, z, customBlock.getBlockId(), customBlock, data);
}
@Override
public void setSeparateBlocks(int x, int y, int z, short blockId, short customBlockId, Data data) {
CustomBlock customBlock = BLOCK_MANAGER.getCustomBlock(customBlockId);
final CustomBlock customBlock = BLOCK_MANAGER.getCustomBlock(customBlockId);
setBlock(x, y, z, blockId, customBlock, data);
}
private synchronized void setBlock(int x, int y, int z, short blockId, CustomBlock customBlock, Data data) {
Chunk chunk = getChunkAt(x, z);
final Chunk chunk = getChunkAt(x, z);
synchronized (chunk) {
boolean isCustomBlock = customBlock != null;
final boolean isCustomBlock = customBlock != null;
BlockPosition blockPosition = new BlockPosition(x, y, z);
final BlockPosition blockPosition = new BlockPosition(x, y, z);
if (isAlreadyChanged(blockPosition, blockId)) { // do NOT change the block again.
// Avoids StackOverflowExceptions when onDestroy tries to destroy the block itself
@ -110,7 +110,7 @@ public class InstanceContainer extends Instance {
return;
}
setAlreadyChanged(blockPosition, blockId);
int index = ChunkUtils.getBlockIndex(x, y, z);
final int index = ChunkUtils.getBlockIndex(x, y, z);
// Call the destroy listener if previous block was a custom block
callBlockDestroy(chunk, index, blockPosition);
@ -149,7 +149,7 @@ public class InstanceContainer extends Instance {
* @return
*/
private boolean isAlreadyChanged(BlockPosition blockPosition, short blockId) {
Block changedBlock = currentlyChangingBlocks.get(blockPosition);
final Block changedBlock = currentlyChangingBlocks.get(blockPosition);
if (changedBlock == null)
return false;
return changedBlock.getBlockId() == blockId;
@ -157,7 +157,7 @@ public class InstanceContainer extends Instance {
@Override
public void refreshBlockId(BlockPosition blockPosition, short blockId) {
Chunk chunk = getChunkAt(blockPosition.getX(), blockPosition.getZ());
final Chunk chunk = getChunkAt(blockPosition.getX(), blockPosition.getZ());
synchronized (chunk) {
chunk.refreshBlockId(blockPosition.getX(), blockPosition.getY(),
blockPosition.getZ(), blockId);
@ -167,22 +167,22 @@ public class InstanceContainer extends Instance {
}
private void callBlockDestroy(Chunk chunk, int index, BlockPosition blockPosition) {
CustomBlock previousBlock = chunk.getCustomBlock(index);
final CustomBlock previousBlock = chunk.getCustomBlock(index);
if (previousBlock != null) {
Data previousData = chunk.getData(index);
final Data previousData = chunk.getData(index);
previousBlock.onDestroy(this, blockPosition, previousData);
chunk.UNSAFE_removeCustomBlock(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ());
}
}
private void callBlockPlace(Chunk chunk, int index, BlockPosition blockPosition) {
CustomBlock actualBlock = chunk.getCustomBlock(index);
Data previousData = chunk.getData(index);
final CustomBlock actualBlock = chunk.getCustomBlock(index);
final Data previousData = chunk.getData(index);
actualBlock.onPlace(this, blockPosition, previousData);
}
private short executeBlockPlacementRule(short blockId, BlockPosition blockPosition) {
BlockPlacementRule blockPlacementRule = BLOCK_MANAGER.getBlockPlacementRule(blockId);
final BlockPlacementRule blockPlacementRule = BLOCK_MANAGER.getBlockPlacementRule(blockId);
if (blockPlacementRule != null) {
return blockPlacementRule.blockRefresh(this, blockPosition, blockId);
}
@ -195,13 +195,13 @@ public class InstanceContainer extends Instance {
for (int offsetZ = -1; offsetZ < 2; offsetZ++) {
if (offsetX == 0 && offsetY == 0 && offsetZ == 0)
continue;
int neighborX = blockPosition.getX() + offsetX;
int neighborY = blockPosition.getY() + offsetY;
int neighborZ = blockPosition.getZ() + offsetZ;
short neighborId = getBlockId(neighborX, neighborY, neighborZ);
BlockPlacementRule neighborBlockPlacementRule = BLOCK_MANAGER.getBlockPlacementRule(neighborId);
final int neighborX = blockPosition.getX() + offsetX;
final int neighborY = blockPosition.getY() + offsetY;
final int neighborZ = blockPosition.getZ() + offsetZ;
final short neighborId = getBlockId(neighborX, neighborY, neighborZ);
final BlockPlacementRule neighborBlockPlacementRule = BLOCK_MANAGER.getBlockPlacementRule(neighborId);
if (neighborBlockPlacementRule != null) {
short newNeighborId = neighborBlockPlacementRule.blockRefresh(this,
final short newNeighborId = neighborBlockPlacementRule.blockRefresh(this,
new BlockPosition(neighborX, neighborY, neighborZ), neighborId);
if (neighborId != newNeighborId) {
refreshBlockId(neighborX, neighborY, neighborZ, newNeighborId);
@ -209,7 +209,7 @@ public class InstanceContainer extends Instance {
}
// Update neighbors
CustomBlock customBlock = getCustomBlock(neighborX, neighborY, neighborZ);
final CustomBlock customBlock = getCustomBlock(neighborX, neighborY, neighborZ);
if (customBlock != null) {
boolean directNeighbor = false; // only if directly connected to neighbor (no diagonals)
if (offsetX != 0 ^ offsetZ != 0) {
@ -228,17 +228,17 @@ public class InstanceContainer extends Instance {
public boolean breakBlock(Player player, BlockPosition blockPosition) {
player.resetTargetBlock();
Chunk chunk = getChunkAt(blockPosition);
final Chunk chunk = getChunkAt(blockPosition);
// Chunk unloaded, stop here
if (ChunkUtils.isChunkUnloaded(chunk))
return false;
int x = blockPosition.getX();
int y = blockPosition.getY();
int z = blockPosition.getZ();
final int x = blockPosition.getX();
final int y = blockPosition.getY();
final int z = blockPosition.getZ();
short blockId = getBlockId(x, y, z);
final short blockId = getBlockId(x, y, z);
// The player probably have a wrong version of this chunk section, send it
if (blockId == 0) {
@ -246,11 +246,11 @@ public class InstanceContainer extends Instance {
return false;
}
CustomBlock customBlock = getCustomBlock(x, y, z);
final CustomBlock customBlock = getCustomBlock(x, y, z);
PlayerBlockBreakEvent blockBreakEvent = new PlayerBlockBreakEvent(blockPosition, blockId, customBlock, (short) 0, (short) 0);
player.callEvent(PlayerBlockBreakEvent.class, blockBreakEvent);
boolean result = !blockBreakEvent.isCancelled();
final boolean result = !blockBreakEvent.isCancelled();
if (result) {
// Break or change the broken block based on event result
setSeparateBlocks(x, y, z, blockBreakEvent.getResultBlockId(), blockBreakEvent.getResultCustomBlockId());
@ -271,7 +271,7 @@ public class InstanceContainer extends Instance {
} else {
// Cancelled so we need to refresh player chunk section
int section = ChunkUtils.getSectionAt(blockPosition.getY());
final int section = ChunkUtils.getSectionAt(blockPosition.getY());
sendChunkSectionUpdate(chunk, section, player);
}
return result;
@ -279,7 +279,7 @@ public class InstanceContainer extends Instance {
@Override
public void loadChunk(int chunkX, int chunkZ, Consumer<Chunk> callback) {
Chunk chunk = getChunk(chunkX, chunkZ);
final Chunk chunk = getChunk(chunkX, chunkZ);
if (chunk != null) {
// Chunk already loaded
if (callback != null)
@ -292,7 +292,7 @@ public class InstanceContainer extends Instance {
@Override
public void loadOptionalChunk(int chunkX, int chunkZ, Consumer<Chunk> callback) {
Chunk chunk = getChunk(chunkX, chunkZ);
final Chunk chunk = getChunk(chunkX, chunkZ);
if (chunk != null) {
// Chunk already loaded
if (callback != null)
@ -311,10 +311,10 @@ public class InstanceContainer extends Instance {
@Override
public void unloadChunk(Chunk chunk) {
int chunkX = chunk.getChunkX();
int chunkZ = chunk.getChunkZ();
final int chunkX = chunk.getChunkX();
final int chunkZ = chunk.getChunkZ();
long index = ChunkUtils.getChunkIndex(chunkX, chunkZ);
final long index = ChunkUtils.getChunkIndex(chunkX, chunkZ);
UnloadChunkPacket unloadChunkPacket = new UnloadChunkPacket();
unloadChunkPacket.chunkX = chunkX;
@ -342,7 +342,7 @@ public class InstanceContainer extends Instance {
@Override
public Chunk getChunk(int chunkX, int chunkZ) {
Chunk chunk = chunks.get(ChunkUtils.getChunkIndex(chunkX, chunkZ));
final Chunk chunk = chunks.get(ChunkUtils.getChunkIndex(chunkX, chunkZ));
return ChunkUtils.isChunkUnloaded(chunk) ? null : chunk;
}
@ -376,7 +376,7 @@ public class InstanceContainer extends Instance {
@Override
public void saveChunksToStorageFolder(Runnable callback) {
Check.notNull(getStorageFolder(), "You cannot save the instance if no StorageFolder has been defined");
if(chunkLoader.supportsParallelSaving()) {
if (chunkLoader.supportsParallelSaving()) {
ExecutorService parallelSavingThreadPool = new MinestomThread(MinecraftServer.THREAD_COUNT_PARALLEL_CHUNK_SAVING, MinecraftServer.THREAD_NAME_PARALLEL_CHUNK_SAVING, true);
getChunks().forEach(c -> parallelSavingThreadPool.execute(() -> {
saveChunkToStorageFolder(c, null);
@ -384,7 +384,7 @@ public class InstanceContainer extends Instance {
try {
parallelSavingThreadPool.shutdown();
parallelSavingThreadPool.awaitTermination(1L, java.util.concurrent.TimeUnit.DAYS);
if(callback != null)
if (callback != null)
callback.run();
} catch (InterruptedException e) {
e.printStackTrace();
@ -392,8 +392,8 @@ public class InstanceContainer extends Instance {
} else {
Iterator<Chunk> chunks = getChunks().iterator();
while (chunks.hasNext()) {
Chunk chunk = chunks.next();
boolean isLast = !chunks.hasNext();
final Chunk chunk = chunks.next();
final boolean isLast = !chunks.hasNext();
saveChunkToStorageFolder(chunk, isLast ? callback : null);
}
}
@ -412,7 +412,7 @@ public class InstanceContainer extends Instance {
@Override
protected void retrieveChunk(int chunkX, int chunkZ, Consumer<Chunk> callback) {
boolean loaded = chunkLoader.loadChunk(this, chunkX, chunkZ, chunk -> {
final boolean loaded = chunkLoader.loadChunk(this, chunkX, chunkZ, chunk -> {
cacheChunk(chunk);
callChunkLoadEvent(chunkX, chunkZ);
if (callback != null)
@ -434,14 +434,14 @@ public class InstanceContainer extends Instance {
chunkGenerator.fillBiomes(biomes, chunkX, chunkZ);
}
Chunk chunk = new Chunk(biomes, chunkX, chunkZ);
final Chunk chunk = new Chunk(biomes, chunkX, chunkZ);
cacheChunk(chunk);
if (chunkGenerator != null) {
ChunkBatch chunkBatch = createChunkBatch(chunk);
final ChunkBatch chunkBatch = createChunkBatch(chunk);
chunkBatch.flushChunkGenerator(chunkGenerator, callback);
}
callChunkLoadEvent(chunkX, chunkZ);
}
@ -466,7 +466,7 @@ public class InstanceContainer extends Instance {
if (!PlayerUtils.isNettyClient(player))
return;
ByteBuf data = chunk.getFullDataPacket();
final ByteBuf data = chunk.getFullDataPacket();
if (data == null || !chunk.packetUpdated) {
PacketWriterUtils.writeCallbackPacket(chunk.getFreshFullDataPacket(), packet -> {
chunk.setFullDataPacket(packet);
@ -476,6 +476,7 @@ public class InstanceContainer extends Instance {
sendChunkUpdate(player, chunk);
}
// TODO do not hardcore
if (MinecraftServer.isFixLighting()) {
UpdateLightPacket updateLightPacket = new UpdateLightPacket();
updateLightPacket.chunkX = chunk.getChunkX();
@ -521,7 +522,7 @@ public class InstanceContainer extends Instance {
}
private void cacheChunk(Chunk chunk) {
long index = ChunkUtils.getChunkIndex(chunk.getChunkX(), chunk.getChunkZ());
final long index = ChunkUtils.getChunkIndex(chunk.getChunkX(), chunk.getChunkZ());
this.chunks.put(index, chunk);
}
@ -567,14 +568,14 @@ public class InstanceContainer extends Instance {
@Override
public void scheduleUpdate(int time, TimeUnit unit, BlockPosition position) {
Instance instance = this;
CustomBlock toUpdate = getCustomBlock(position);
final CustomBlock toUpdate = getCustomBlock(position);
if (toUpdate == null) {
return;
}
MinecraftServer.getSchedulerManager().addDelayedTask(new TaskRunnable() {
@Override
public void run() {
CustomBlock currentBlock = instance.getCustomBlock(position);
final CustomBlock currentBlock = instance.getCustomBlock(position);
if (currentBlock == null)
return;
if (currentBlock.getCustomBlockId() != toUpdate.getCustomBlockId()) { // block changed

View File

@ -36,7 +36,7 @@ public final class InstanceManager {
}
public SharedInstance createSharedInstance(SharedInstance sharedInstance) {
InstanceContainer instanceContainer = sharedInstance.getInstanceContainer();
final InstanceContainer instanceContainer = sharedInstance.getInstanceContainer();
Check.notNull(instanceContainer, "SharedInstance needs to have an InstanceContainer to be created!");
instanceContainer.addSharedInstance(sharedInstance);
@ -47,7 +47,7 @@ public final class InstanceManager {
public SharedInstance createSharedInstance(InstanceContainer instanceContainer) {
Check.notNull(instanceContainer, "Instance container cannot be null when creating a SharedInstance!");
SharedInstance sharedInstance = new SharedInstance(UUID.randomUUID(), instanceContainer);
final SharedInstance sharedInstance = new SharedInstance(UUID.randomUUID(), instanceContainer);
return createSharedInstance(sharedInstance);
}

View File

@ -62,9 +62,9 @@ public class BlockBatch implements InstanceBatch {
int counter = 0;
for (Map.Entry<Chunk, List<BlockData>> entry : data.entrySet()) {
counter++;
Chunk chunk = entry.getKey();
List<BlockData> dataList = entry.getValue();
boolean isLast = counter == data.size();
final Chunk chunk = entry.getKey();
final List<BlockData> dataList = entry.getValue();
final boolean isLast = counter == data.size();
batchesPool.execute(() -> {
synchronized (chunk) {
if (!chunk.isLoaded())

View File

@ -73,7 +73,7 @@ public class ChunkBatch implements InstanceBatch {
if (hasPopulator) {
Iterator<ChunkPopulator> populatorIterator = populators.iterator();
while (populatorIterator.hasNext()) {
ChunkPopulator chunkPopulator = populatorIterator.next();
final ChunkPopulator chunkPopulator = populatorIterator.next();
chunkPopulator.populateChunk(this, chunk);
}
singleThreadFlush(callback);

View File

@ -6,8 +6,8 @@ import java.util.Map;
public class BlockAlternative {
private short id;
private String[] properties;
private final short id;
private final String[] properties;
public BlockAlternative(short id, String... properties) {
this.id = id;
@ -24,7 +24,7 @@ public class BlockAlternative {
public Map<String, String> createPropertiesMap() {
Map<String, String> map = new HashMap<>();
for(String p : properties) {
for (String p : properties) {
String[] parts = p.split("=");
map.put(parts[0], parts[1]);
}

View File

@ -18,8 +18,8 @@ public class BlockManager {
* @param customBlock the custom block to register
*/
public void registerCustomBlock(CustomBlock customBlock) {
String identifier = customBlock.getIdentifier();
short id = customBlock.getCustomBlockId();
final String identifier = customBlock.getIdentifier();
final short id = customBlock.getCustomBlockId();
this.customBlocksInternalId.put(id, customBlock);
this.customBlocksId.put(identifier, customBlock);
}
@ -36,7 +36,7 @@ public class BlockManager {
* @return the block placement rule associated with the id, null if not any
*/
public BlockPlacementRule getBlockPlacementRule(short blockId) {
Block block = Block.fromId(blockId); // Convert block alternative
final Block block = Block.fromId(blockId); // Convert block alternative
blockId = block.getBlockId();
return this.placementRules.get(blockId);
}

View File

@ -110,7 +110,7 @@ public abstract class CustomBlock {
* @return true if {@link #getUpdateOption()} is not null, false otherwise
*/
public boolean hasUpdate() {
UpdateOption updateOption = getUpdateOption();
final UpdateOption updateOption = getUpdateOption();
if (updateOption == null)
return false;

View File

@ -32,7 +32,7 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
private static volatile byte lastInventoryId;
private byte id;
private InventoryType inventoryType;
private final InventoryType inventoryType;
private String title;
private int size;
@ -169,14 +169,14 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
@Override
public boolean addViewer(Player player) {
boolean result = this.viewers.add(player);
final boolean result = this.viewers.add(player);
PacketWriterUtils.writeAndSend(player, createWindowItemsPacket());
return result;
}
@Override
public boolean removeViewer(Player player) {
boolean result = this.viewers.remove(player);
final boolean result = this.viewers.remove(player);
this.cursorPlayersItem.remove(player);
this.clickProcessor.clearCache(player);
return result;
@ -253,13 +253,13 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
@Override
public boolean leftClick(Player player, int slot) {
PlayerInventory playerInventory = player.getInventory();
ItemStack cursor = getCursorItem(player);
boolean isInWindow = isClickInWindow(slot);
ItemStack clicked = isInWindow ? getItemStack(slot) : playerInventory.getItemStack(slot, offset);
final PlayerInventory playerInventory = player.getInventory();
final ItemStack cursor = getCursorItem(player);
final boolean isInWindow = isClickInWindow(slot);
final ItemStack clicked = isInWindow ? getItemStack(slot) : playerInventory.getItemStack(slot, offset);
InventoryClickResult clickResult = clickProcessor.leftClick(this, player, slot, clicked, cursor);
final InventoryClickResult clickResult = clickProcessor.leftClick(this, player, slot, clicked, cursor);
if (clickResult.doRefresh()) {
updateFromClick(clickResult, player);
@ -281,12 +281,12 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
@Override
public boolean rightClick(Player player, int slot) {
PlayerInventory playerInventory = player.getInventory();
ItemStack cursor = getCursorItem(player);
boolean isInWindow = isClickInWindow(slot);
ItemStack clicked = isInWindow ? getItemStack(slot) : playerInventory.getItemStack(slot, offset);
final PlayerInventory playerInventory = player.getInventory();
final ItemStack cursor = getCursorItem(player);
final boolean isInWindow = isClickInWindow(slot);
final ItemStack clicked = isInWindow ? getItemStack(slot) : playerInventory.getItemStack(slot, offset);
InventoryClickResult clickResult = clickProcessor.rightClick(this, player, slot, clicked, cursor);
final InventoryClickResult clickResult = clickProcessor.rightClick(this, player, slot, clicked, cursor);
if (clickResult.doRefresh()) {
updateFromClick(clickResult, player);
@ -308,13 +308,13 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
@Override
public boolean shiftClick(Player player, int slot) {
PlayerInventory playerInventory = player.getInventory();
boolean isInWindow = isClickInWindow(slot);
ItemStack clicked = isInWindow ? getItemStack(slot) : playerInventory.getItemStack(slot, offset);
ItemStack cursor = getCursorItem(player); // Isn't used in the algorithm
final PlayerInventory playerInventory = player.getInventory();
final boolean isInWindow = isClickInWindow(slot);
final ItemStack clicked = isInWindow ? getItemStack(slot) : playerInventory.getItemStack(slot, offset);
final ItemStack cursor = getCursorItem(player); // Isn't used in the algorithm
InventoryClickResult clickResult;
final InventoryClickResult clickResult;
if (isInWindow) {
clickResult = clickProcessor.shiftClick(this, player, slot, clicked, cursor,
@ -360,12 +360,12 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
@Override
public boolean changeHeld(Player player, int slot, int key) {
PlayerInventory playerInventory = player.getInventory();
boolean isInWindow = isClickInWindow(slot);
ItemStack clicked = isInWindow ? getItemStack(slot) : playerInventory.getItemStack(slot, offset);
ItemStack heldItem = playerInventory.getItemStack(key);
final PlayerInventory playerInventory = player.getInventory();
final boolean isInWindow = isClickInWindow(slot);
final ItemStack clicked = isInWindow ? getItemStack(slot) : playerInventory.getItemStack(slot, offset);
final ItemStack heldItem = playerInventory.getItemStack(key);
InventoryClickResult clickResult = clickProcessor.changeHeld(this, player, slot, key, clicked, heldItem);
final InventoryClickResult clickResult = clickProcessor.changeHeld(this, player, slot, key, clicked, heldItem);
if (clickResult.doRefresh()) {
updateFromClick(clickResult, player);
@ -395,13 +395,13 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
@Override
public boolean drop(Player player, int mode, int slot, int button) {
PlayerInventory playerInventory = player.getInventory();
boolean isInWindow = isClickInWindow(slot);
ItemStack clicked = slot == -999 ?
final PlayerInventory playerInventory = player.getInventory();
final boolean isInWindow = isClickInWindow(slot);
final ItemStack clicked = slot == -999 ?
null : (isInWindow ? getItemStack(slot) : playerInventory.getItemStack(slot, offset));
ItemStack cursor = getCursorItem(player);
final ItemStack cursor = getCursorItem(player);
InventoryClickResult clickResult = clickProcessor.drop(this, player,
final InventoryClickResult clickResult = clickProcessor.drop(this, player,
mode, slot, button, clicked, cursor);
if (clickResult.doRefresh()) {
@ -424,14 +424,14 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
@Override
public boolean dragging(Player player, int slot, int button) {
PlayerInventory playerInventory = player.getInventory();
boolean isInWindow = isClickInWindow(slot);
final PlayerInventory playerInventory = player.getInventory();
final boolean isInWindow = isClickInWindow(slot);
ItemStack clicked = null;
ItemStack cursor = getCursorItem(player);
final ItemStack cursor = getCursorItem(player);
if (slot != -999)
clicked = isInWindow ? getItemStack(slot) : playerInventory.getItemStack(slot, offset);
InventoryClickResult clickResult = clickProcessor.dragging(this, player,
final InventoryClickResult clickResult = clickProcessor.dragging(this, player,
slot, button,
clicked, cursor,
@ -460,11 +460,11 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
@Override
public boolean doubleClick(Player player, int slot) {
PlayerInventory playerInventory = player.getInventory();
ItemStack cursor = getCursorItem(player);
final PlayerInventory playerInventory = player.getInventory();
final ItemStack cursor = getCursorItem(player);
InventoryClickResult clickResult = clickProcessor.doubleClick(this, player, slot, cursor,
final InventoryClickResult clickResult = clickProcessor.doubleClick(this, player, slot, cursor,
// Start by looping through the opened inventory
new InventoryClickLoopHandler(0, getSize(), 1,
i -> i,

View File

@ -5,19 +5,60 @@ import net.minestom.server.item.ItemStack;
import java.util.List;
/**
* Represent an inventory where its items can be modified/retrieved
*/
public interface InventoryModifier {
/**
* Set an item at the specified slot
*
* @param slot the slot to set the item
* @param itemStack the item to set
*/
void setItemStack(int slot, ItemStack itemStack);
/**
* Add an item to the inventory
*
* @param itemStack the item to add
* @return true if the item has been sucessfully fully added, false otherwise
*/
boolean addItemStack(ItemStack itemStack);
/**
* Get the item at the specified slot
*
* @param slot the slot to check
* @return the item in the slot {@code slot}
*/
ItemStack getItemStack(int slot);
/**
* Get all the items in the inventory
*
* @return an array containing all the inventory's items
*/
ItemStack[] getItemStacks();
/**
* Get the size of the inventory
*
* @return the inventory's size
*/
int getSize();
/**
* Get all the inventory conditions of this inventory
*
* @return the inventory conditions
*/
List<InventoryCondition> getInventoryConditions();
/**
* Add a new inventory condition to this inventory
*
* @param inventoryCondition the inventory condition to add
*/
void addInventoryCondition(InventoryCondition inventoryCondition);
}

View File

@ -330,7 +330,7 @@ public class PlayerInventory implements InventoryModifier, InventoryClickHandler
ItemStack[] convertedSlots = new ItemStack[INVENTORY_SIZE];
for (int i = 0; i < items.length; i++) {
int slot = convertToPacketSlot(i);
final int slot = convertToPacketSlot(i);
convertedSlots[slot] = items[i];
}
@ -342,10 +342,10 @@ public class PlayerInventory implements InventoryModifier, InventoryClickHandler
@Override
public boolean leftClick(Player player, int slot) {
ItemStack cursor = getCursorItem();
ItemStack clicked = getItemStack(convertSlot(slot, OFFSET));
final ItemStack cursor = getCursorItem();
final ItemStack clicked = getItemStack(convertSlot(slot, OFFSET));
InventoryClickResult clickResult = clickProcessor.leftClick(null, player, slot, clicked, cursor);
final InventoryClickResult clickResult = clickProcessor.leftClick(null, player, slot, clicked, cursor);
if (clickResult.doRefresh())
sendSlotRefresh((short) slot, clicked);
@ -361,10 +361,10 @@ public class PlayerInventory implements InventoryModifier, InventoryClickHandler
@Override
public boolean rightClick(Player player, int slot) {
ItemStack cursor = getCursorItem();
ItemStack clicked = getItemStack(slot, OFFSET);
final ItemStack cursor = getCursorItem();
final ItemStack clicked = getItemStack(slot, OFFSET);
InventoryClickResult clickResult = clickProcessor.rightClick(null, player, slot, clicked, cursor);
final InventoryClickResult clickResult = clickProcessor.rightClick(null, player, slot, clicked, cursor);
if (clickResult.doRefresh())
sendSlotRefresh((short) slot, clicked);
@ -386,10 +386,10 @@ public class PlayerInventory implements InventoryModifier, InventoryClickHandler
@Override
public boolean drop(Player player, int mode, int slot, int button) {
ItemStack cursor = getCursorItem();
ItemStack clicked = slot == -999 ? null : getItemStack(slot, OFFSET);
final ItemStack cursor = getCursorItem();
final ItemStack clicked = slot == -999 ? null : getItemStack(slot, OFFSET);
InventoryClickResult clickResult = clickProcessor.drop(null, player,
final InventoryClickResult clickResult = clickProcessor.drop(null, player,
mode, slot, button, clicked, cursor);
if (clickResult.doRefresh())
@ -405,11 +405,11 @@ public class PlayerInventory implements InventoryModifier, InventoryClickHandler
@Override
public boolean shiftClick(Player player, int slot) {
ItemStack cursor = getCursorItem();
ItemStack clicked = getItemStack(slot, OFFSET);
final ItemStack cursor = getCursorItem();
final ItemStack clicked = getItemStack(slot, OFFSET);
boolean hotbarClick = convertToPacketSlot(slot) < 9;
InventoryClickResult clickResult = clickProcessor.shiftClick(null, player, slot, clicked, cursor,
final boolean hotbarClick = convertToPacketSlot(slot) < 9;
final InventoryClickResult clickResult = clickProcessor.shiftClick(null, player, slot, clicked, cursor,
new InventoryClickLoopHandler(0, items.length, 1,
i -> {
if (hotbarClick) {
@ -437,10 +437,10 @@ public class PlayerInventory implements InventoryModifier, InventoryClickHandler
if (!getCursorItem().isAir())
return false;
ItemStack heldItem = getItemStack(key);
ItemStack clicked = getItemStack(slot, OFFSET);
final ItemStack heldItem = getItemStack(key);
final ItemStack clicked = getItemStack(slot, OFFSET);
InventoryClickResult clickResult = clickProcessor.changeHeld(null, player, slot, key, clicked, heldItem);
final InventoryClickResult clickResult = clickProcessor.changeHeld(null, player, slot, key, clicked, heldItem);
if (clickResult.doRefresh()) {
sendSlotRefresh((short) slot, clicked);
@ -460,12 +460,12 @@ public class PlayerInventory implements InventoryModifier, InventoryClickHandler
@Override
public boolean dragging(Player player, int slot, int button) {
ItemStack cursor = getCursorItem();
final ItemStack cursor = getCursorItem();
ItemStack clicked = null;
if (slot != -999)
clicked = getItemStack(slot, OFFSET);
InventoryClickResult clickResult = clickProcessor.dragging(null, player,
final InventoryClickResult clickResult = clickProcessor.dragging(null, player,
slot, button,
clicked, cursor, s -> getItemStack(s, OFFSET),
(s, item) -> setItemStack(s, OFFSET, item));
@ -484,9 +484,9 @@ public class PlayerInventory implements InventoryModifier, InventoryClickHandler
@Override
public boolean doubleClick(Player player, int slot) {
ItemStack cursor = getCursorItem();
final ItemStack cursor = getCursorItem();
InventoryClickResult clickResult = clickProcessor.doubleClick(null, player, slot, cursor,
final InventoryClickResult clickResult = clickProcessor.doubleClick(null, player, slot, cursor,
new InventoryClickLoopHandler(0, items.length, 1,
i -> i < 9 ? i + 9 : i - 9,
index -> items[index],

View File

@ -20,7 +20,7 @@ public class ItemStack implements DataContainer {
private static final StackingRule DEFAULT_STACKING_RULE = new VanillaStackingRule(127);
private Material material;
private final Material material;
private static StackingRule defaultStackingRule;
private ItemMeta itemMeta;
@ -192,6 +192,18 @@ public class ItemStack implements DataContainer {
return itemMeta;
}
/**
* Change the item meta linked to this item
* <p>
* WARNING: be sure to have nbt data useful for this item, items should automatically get the appropriate
* item meta
*
* @param itemMeta the new item meta
*/
public void setItemMeta(ItemMeta itemMeta) {
this.itemMeta = itemMeta;
}
/**
* Get the item display name
*

View File

@ -68,7 +68,7 @@ public class PotionMeta implements ItemMeta {
@Override
public ItemMeta clone() {
PotionMeta potionMeta = new PotionMeta();
potionMeta.potionTypes = new HashSet<>(potionTypes);
potionMeta.potionTypes.addAll(potionTypes);
return potionMeta;
}

View File

@ -12,7 +12,7 @@ import java.util.concurrent.ConcurrentHashMap;
public class PacketListenerManager {
private static ConnectionManager connectionManager = MinecraftServer.getConnectionManager();
private static final ConnectionManager CONNECTION_MANAGER = MinecraftServer.getConnectionManager();
private Map<Class<? extends ClientPlayPacket>, PacketListenerConsumer> listeners = new ConcurrentHashMap<>();
@ -51,7 +51,7 @@ public class PacketListenerManager {
final Class clazz = packet.getClass();
PacketListenerConsumer<T> packetListenerConsumer = listeners.get(clazz);
final PacketListenerConsumer<T> packetListenerConsumer = listeners.get(clazz);
// Listener can be null if none has been set before, call PacketConsumer anyway
if (packetListenerConsumer == null) {
@ -59,8 +59,8 @@ public class PacketListenerManager {
}
PacketController packetController = new PacketController(packetListenerConsumer);
for (PacketConsumer packetConsumer : connectionManager.getPacketConsumers()) {
final PacketController packetController = new PacketController(packetListenerConsumer);
for (PacketConsumer packetConsumer : CONNECTION_MANAGER.getPacketConsumers()) {
packetConsumer.accept(player, packetController, packet);
}

View File

@ -56,10 +56,10 @@ public final class ConnectionManager {
* @param condition the condition to receive the message
*/
public void broadcastMessage(RichMessage richMessage, Function<Player, Boolean> condition) {
Collection<Player> recipients = getRecipients(condition);
final Collection<Player> recipients = getRecipients(condition);
if (!recipients.isEmpty()) {
String jsonText = richMessage.toString();
final String jsonText = richMessage.toString();
broadcastJson(jsonText, recipients);
}
}
@ -80,10 +80,10 @@ public final class ConnectionManager {
* @param condition the condition to receive the message
*/
public void broadcastMessage(ColoredText coloredText, Function<Player, Boolean> condition) {
Collection<Player> recipients = getRecipients(condition);
final Collection<Player> recipients = getRecipients(condition);
if (!recipients.isEmpty()) {
String jsonText = coloredText.toString();
final String jsonText = coloredText.toString();
broadcastJson(jsonText, recipients);
}
}
@ -112,7 +112,7 @@ public final class ConnectionManager {
} else {
recipients = new ArrayList<>();
getOnlinePlayers().forEach(player -> {
boolean result = condition.apply(player);
final boolean result = condition.apply(player);
if (result)
recipients.add(player);
});
@ -186,7 +186,7 @@ public final class ConnectionManager {
* Add a new player in the players list
* Is currently used at
* {@link net.minestom.server.network.packet.client.login.LoginStartPacket#process(PlayerConnection, ConnectionManager)}
* and in {@link net.minestom.server.entity.fakeplayer.FakePlayer#initPlayer(UUID, String, boolean, Consumer)}
* and in {@link net.minestom.server.entity.fakeplayer.FakePlayer#initPlayer(UUID, String, Consumer)}
*
* @param player the player to add
*/
@ -203,7 +203,7 @@ public final class ConnectionManager {
* @param connection the new player connection
*/
public void createPlayer(UUID uuid, String username, PlayerConnection connection) {
Player player = new Player(uuid, username, connection);
final Player player = new Player(uuid, username, connection);
createPlayer(player);
}
@ -214,7 +214,7 @@ public final class ConnectionManager {
* @param connection the player connection
*/
public void removePlayer(PlayerConnection connection) {
Player player = this.connectionPlayerMap.get(connection);
final Player player = this.connectionPlayerMap.get(connection);
if (player == null)
return;

View File

@ -1,5 +1,8 @@
package net.minestom.server.network;
/**
* Represent the current connection state of a player
*/
public enum ConnectionState {
UNKNOWN, STATUS, LOGIN, PLAY
}

View File

@ -1,6 +1,5 @@
package net.minestom.server.network;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.socket.SocketChannel;
import net.minestom.server.MinecraftServer;
@ -47,7 +46,7 @@ public class PacketProcessor {
channel, c -> new NettyPlayerConnection((SocketChannel) channel.channel())
);
ConnectionState connectionState = playerConnection.getConnectionState();
final ConnectionState connectionState = playerConnection.getConnectionState();
//if (!printBlackList.contains(id)) {
//System.out.println("RECEIVED ID: 0x" + Integer.toHexString(id) + " State: " + connectionState);
@ -67,20 +66,18 @@ public class PacketProcessor {
switch (connectionState) {
case PLAY:
Player player = playerConnection.getPlayer();
final Player player = playerConnection.getPlayer();
ClientPlayPacket playPacket = (ClientPlayPacket) playPacketsHandler.getPacketInstance(packet.packetId);
playPacket.read(packetReader);
//System.out.println("play");
player.addPacketToQueue(playPacket);
break;
case LOGIN:
ClientPreplayPacket loginPacket = (ClientPreplayPacket) loginPacketsHandler.getPacketInstance(packet.packetId);
final ClientPreplayPacket loginPacket = (ClientPreplayPacket) loginPacketsHandler.getPacketInstance(packet.packetId);
loginPacket.read(packetReader);
//System.out.println("login");
loginPacket.process(playerConnection, connectionManager);
break;
case STATUS:
ClientPreplayPacket statusPacket = (ClientPreplayPacket) statusPacketsHandler.getPacketInstance(packet.packetId);
final ClientPreplayPacket statusPacket = (ClientPreplayPacket) statusPacketsHandler.getPacketInstance(packet.packetId);
statusPacket.read(packetReader);
statusPacket.process(playerConnection, connectionManager);
@ -92,10 +89,6 @@ public class PacketProcessor {
return connectionPlayerConnectionMap.get(channel);
}
public boolean hasPlayerConnection(ChannelHandlerContext channel) {
return connectionPlayerConnectionMap.containsKey(channel);
}
public void removePlayerConnection(ChannelHandlerContext channel) {
connectionPlayerConnectionMap.remove(channel);
}

View File

@ -19,7 +19,7 @@ public class PacketWriterUtils {
public static void writeCallbackPacket(ServerPacket serverPacket, Consumer<ByteBuf> consumer) {
batchesPool.execute(() -> {
ByteBuf buffer = PacketUtils.writePacket(serverPacket);
final ByteBuf buffer = PacketUtils.writePacket(serverPacket);
consumer.accept(buffer);
});
}
@ -31,7 +31,7 @@ public class PacketWriterUtils {
final ByteBuf buffer = PacketUtils.writePacket(serverPacket);
for (Player player : players) {
PlayerConnection playerConnection = player.getPlayerConnection();
final PlayerConnection playerConnection = player.getPlayerConnection();
if (PlayerUtils.isNettyClient(player)) {
playerConnection.writePacket(buffer, true);
} else {

View File

@ -26,25 +26,25 @@ public class ChunkReader {
biomes[i] = Biome.fromId(stream.readByte());
}
Chunk chunk = new Chunk(biomes, chunkX, chunkZ);
final Chunk chunk = new Chunk(biomes, chunkX, chunkZ);
chunkBatch = instance.createChunkBatch(chunk);
while (true) {
int x = stream.readInt();
int y = stream.readInt();
int z = stream.readInt();
final int x = stream.readInt();
final int y = stream.readInt();
final int z = stream.readInt();
short blockId = stream.readShort();
short customBlockId = stream.readShort();
final short blockId = stream.readShort();
final short customBlockId = stream.readShort();
boolean hasData = stream.readBoolean();
final boolean hasData = stream.readBoolean();
Data data = null;
// Data deserializer
if (hasData) {
int dataLength = stream.readInt();
byte[] dataArray = stream.readNBytes(dataLength);
final int dataLength = stream.readInt();
final byte[] dataArray = stream.readNBytes(dataLength);
data = DataReader.readData(Unpooled.wrappedBuffer(dataArray));
}

View File

@ -28,7 +28,7 @@ public class DataReader {
SerializableData data = new SerializableData();
try {
while (true) {
short typeLength = buffer.readShort();
final short typeLength = buffer.readShort();
if (typeLength == 0xff) {
// End of data
@ -40,8 +40,8 @@ public class DataReader {
typeCache[i] = buffer.readByte();
}
String className = new String(typeCache);
Class type = Class.forName(className);
final String className = new String(typeCache);
final Class type = Class.forName(className);
short nameLength = buffer.readShort();
byte[] nameCache = new byte[nameLength];
@ -49,11 +49,11 @@ public class DataReader {
nameCache[i] = buffer.readByte();
}
ByteBuf valueCache = buffer.readBytes(buffer.readInt());
final ByteBuf valueCache = buffer.readBytes(buffer.readInt());
String name = new String(nameCache);
final String name = new String(nameCache);
PacketReader packetReader = new PacketReader(valueCache);
Object value = DATA_MANAGER.getDataType(type).decode(packetReader);
final Object value = DATA_MANAGER.getDataType(type).decode(packetReader);
data.set(name, value, type);
}

View File

@ -6,6 +6,7 @@ import net.minestom.server.chat.ColoredText;
import net.minestom.server.entity.Player;
import net.minestom.server.network.packet.server.play.DisplayScoreboardPacket;
import net.minestom.server.network.packet.server.play.ScoreboardObjectivePacket;
import net.minestom.server.network.packet.server.play.TeamsPacket;
import net.minestom.server.network.packet.server.play.UpdateScorePacket;
import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.utils.validate.Check;
@ -84,7 +85,7 @@ public class Sidebar implements Viewable {
}
public void updateLineContent(String id, ColoredText content) {
ScoreboardLine scoreboardLine = getLine(id);
final ScoreboardLine scoreboardLine = getLine(id);
if (scoreboardLine != null) {
scoreboardLine.refreshContent(content);
sendPacketToViewers(scoreboardLine.sidebarTeam.updatePrefix(content));
@ -92,7 +93,7 @@ public class Sidebar implements Viewable {
}
public void updateLineScore(String id, int score) {
ScoreboardLine scoreboardLine = getLine(id);
final ScoreboardLine scoreboardLine = getLine(id);
if (scoreboardLine != null) {
scoreboardLine.line = score;
sendPacketToViewers(scoreboardLine.getLineScoreUpdatePacket(objectiveName, score));
@ -111,7 +112,7 @@ public class Sidebar implements Viewable {
synchronized (lines) {
Iterator<ScoreboardLine> iterator = lines.iterator();
while (iterator.hasNext()) {
ScoreboardLine line = iterator.next();
final ScoreboardLine line = iterator.next();
if (line.id.equals(id)) {
// Remove the line for current viewers
@ -126,7 +127,7 @@ public class Sidebar implements Viewable {
@Override
public boolean addViewer(Player player) {
boolean result = this.viewers.add(player);
final boolean result = this.viewers.add(player);
PlayerConnection playerConnection = player.getPlayerConnection();
ScoreboardObjectivePacket scoreboardObjectivePacket = new ScoreboardObjectivePacket();
@ -248,4 +249,74 @@ public class Sidebar implements Viewable {
}
private static class SidebarTeam {
private String teamName;
private ColoredText prefix, suffix;
private String entityName;
private ColoredText teamDisplayName = ColoredText.of("displaynametest");
private byte friendlyFlags = 0x00;
private TeamsPacket.NameTagVisibility nameTagVisibility = TeamsPacket.NameTagVisibility.NEVER;
private TeamsPacket.CollisionRule collisionRule = TeamsPacket.CollisionRule.NEVER;
private int teamColor = 2;
private SidebarTeam(String teamName, ColoredText prefix, ColoredText suffix, String entityName) {
this.teamName = teamName;
this.prefix = prefix;
this.suffix = suffix;
this.entityName = entityName;
}
private TeamsPacket getCreationPacket() {
TeamsPacket teamsPacket = new TeamsPacket();
teamsPacket.teamName = teamName;
teamsPacket.action = TeamsPacket.Action.CREATE_TEAM;
teamsPacket.teamDisplayName = teamDisplayName.toString();
teamsPacket.friendlyFlags = friendlyFlags;
teamsPacket.nameTagVisibility = nameTagVisibility;
teamsPacket.collisionRule = collisionRule;
teamsPacket.teamColor = teamColor;
teamsPacket.teamPrefix = prefix.toString();
teamsPacket.teamSuffix = suffix.toString();
teamsPacket.entities = new String[]{entityName};
return teamsPacket;
}
private TeamsPacket getDestructionPacket() {
TeamsPacket teamsPacket = new TeamsPacket();
teamsPacket.teamName = teamName;
teamsPacket.action = TeamsPacket.Action.REMOVE_TEAM;
return teamsPacket;
}
private TeamsPacket updatePrefix(ColoredText prefix) {
TeamsPacket teamsPacket = new TeamsPacket();
teamsPacket.teamName = teamName;
teamsPacket.action = TeamsPacket.Action.UPDATE_TEAM_INFO;
teamsPacket.teamDisplayName = teamDisplayName.toString();
teamsPacket.friendlyFlags = friendlyFlags;
teamsPacket.nameTagVisibility = nameTagVisibility;
teamsPacket.collisionRule = collisionRule;
teamsPacket.teamColor = teamColor;
teamsPacket.teamPrefix = prefix.toString();
teamsPacket.teamSuffix = suffix.toString();
return teamsPacket;
}
private String getEntityName() {
return entityName;
}
private ColoredText getPrefix() {
return prefix;
}
private void refreshPrefix(ColoredText prefix) {
this.prefix = prefix;
}
}
}

View File

@ -1,73 +0,0 @@
package net.minestom.server.scoreboard;
import net.minestom.server.chat.ColoredText;
import net.minestom.server.network.packet.server.play.TeamsPacket;
public class SidebarTeam {
private String teamName;
private ColoredText prefix, suffix;
private String entityName;
private ColoredText teamDisplayName = ColoredText.of("displaynametest");
private byte friendlyFlags = 0x00;
private TeamsPacket.NameTagVisibility nameTagVisibility = TeamsPacket.NameTagVisibility.NEVER;
private TeamsPacket.CollisionRule collisionRule = TeamsPacket.CollisionRule.NEVER;
private int teamColor = 2;
protected SidebarTeam(String teamName, ColoredText prefix, ColoredText suffix, String entityName) {
this.teamName = teamName;
this.prefix = prefix;
this.suffix = suffix;
this.entityName = entityName;
}
protected TeamsPacket getCreationPacket() {
TeamsPacket teamsPacket = new TeamsPacket();
teamsPacket.teamName = teamName;
teamsPacket.action = TeamsPacket.Action.CREATE_TEAM;
teamsPacket.teamDisplayName = teamDisplayName.toString();
teamsPacket.friendlyFlags = friendlyFlags;
teamsPacket.nameTagVisibility = nameTagVisibility;
teamsPacket.collisionRule = collisionRule;
teamsPacket.teamColor = teamColor;
teamsPacket.teamPrefix = prefix.toString();
teamsPacket.teamSuffix = suffix.toString();
teamsPacket.entities = new String[]{entityName};
return teamsPacket;
}
protected TeamsPacket getDestructionPacket() {
TeamsPacket teamsPacket = new TeamsPacket();
teamsPacket.teamName = teamName;
teamsPacket.action = TeamsPacket.Action.REMOVE_TEAM;
return teamsPacket;
}
protected TeamsPacket updatePrefix(ColoredText prefix) {
TeamsPacket teamsPacket = new TeamsPacket();
teamsPacket.teamName = teamName;
teamsPacket.action = TeamsPacket.Action.UPDATE_TEAM_INFO;
teamsPacket.teamDisplayName = teamDisplayName.toString();
teamsPacket.friendlyFlags = friendlyFlags;
teamsPacket.nameTagVisibility = nameTagVisibility;
teamsPacket.collisionRule = collisionRule;
teamsPacket.teamColor = teamColor;
teamsPacket.teamPrefix = prefix.toString();
teamsPacket.teamSuffix = suffix.toString();
return teamsPacket;
}
protected String getEntityName() {
return entityName;
}
protected ColoredText getPrefix() {
return prefix;
}
protected void refreshPrefix(ColoredText prefix) {
this.prefix = prefix;
}
}

View File

@ -52,7 +52,7 @@ public class Team {
}
public void addPlayer(Player player) {
String newElement = player.getUsername();
final String newElement = player.getUsername();
TeamsPacket addPlayerPacket = new TeamsPacket();
addPlayerPacket.teamName = teamName;

View File

@ -3,6 +3,7 @@ package net.minestom.server.scoreboard;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
// TODO
public final class TeamManager {
// Represents all registered teams

View File

@ -19,21 +19,43 @@ public class SchedulerManager {
private List<Task> tasks = new CopyOnWriteArrayList<>();
private List<Task> shutdownTasks = new CopyOnWriteArrayList<>();
/**
* Add a task with a custom update option and a precise call count
*
* @param runnable the task to execute
* @param updateOption the update option of the task
* @param maxCallCount the number of time this task should be executed
* @return the task id
*/
public int addTask(TaskRunnable runnable, UpdateOption updateOption, int maxCallCount) {
int id = COUNTER.incrementAndGet();
final int id = COUNTER.incrementAndGet();
runnable.setId(id);
Task task = new Task(runnable, updateOption, maxCallCount);
final Task task = new Task(runnable, updateOption, maxCallCount);
task.refreshLastUpdateTime(System.currentTimeMillis());
this.tasks.add(task);
return id;
}
/**
* Add a task which will be repeated without interruption
*
* @param runnable the task to execute
* @param updateOption the update option of the task
* @return the task id
*/
public int addRepeatingTask(TaskRunnable runnable, UpdateOption updateOption) {
return addTask(runnable, updateOption, 0);
}
/**
* Add a task which will be executed only once
*
* @param runnable the task to execute
* @param updateOption the update option of the task
* @return the task id
*/
public int addDelayedTask(TaskRunnable runnable, UpdateOption updateOption) {
return addTask(runnable, updateOption, 1);
}
@ -42,18 +64,21 @@ public class SchedulerManager {
* Adds a task to run when the server shutdowns
*
* @param runnable the task to perform
* @return
* @return the task id
*/
public int addShutdownTask(TaskRunnable runnable) {
int id = SHUTDOWN_COUNTER.incrementAndGet();
final int id = SHUTDOWN_COUNTER.incrementAndGet();
runnable.setId(id);
Task task = new Task(runnable, null, 1);
final Task task = new Task(runnable, null, 1);
this.shutdownTasks.add(task);
return id;
}
/**
* Shutdown all the tasks and call tasks added from {@link #addShutdownTask(TaskRunnable)}
*/
public void shutdown() {
batchesPool.execute(() -> {
for (Task task : shutdownTasks) {
@ -63,24 +88,30 @@ public class SchedulerManager {
batchesPool.shutdown();
try {
batchesPool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {}
} catch (InterruptedException e) {
}
}
/**
* Force the end of a task
*
* @param taskId the id of the task to remove
*/
public void removeTask(int taskId) {
this.tasks.removeIf(task -> task.getId() == taskId);
}
public void update() {
long time = System.currentTimeMillis();
final long time = System.currentTimeMillis();
batchesPool.execute(() -> {
for (Task task : tasks) {
UpdateOption updateOption = task.getUpdateOption();
long lastUpdate = task.getLastUpdateTime();
boolean hasCooldown = CooldownUtils.hasCooldown(time, lastUpdate, updateOption.getTimeUnit(), updateOption.getValue());
final UpdateOption updateOption = task.getUpdateOption();
final long lastUpdate = task.getLastUpdateTime();
final boolean hasCooldown = CooldownUtils.hasCooldown(time, lastUpdate, updateOption.getTimeUnit(), updateOption.getValue());
if (!hasCooldown) {
TaskRunnable runnable = task.getRunnable();
int maxCallCount = task.getMaxCallCount();
int callCount = runnable.getCallCount() + 1;
final TaskRunnable runnable = task.getRunnable();
final int maxCallCount = task.getMaxCallCount();
final int callCount = runnable.getCallCount() + 1;
runnable.setCallCount(callCount);
runnable.run();

View File

@ -53,7 +53,7 @@ public class NBTUtils {
public static void saveAllItems(NBTList<NBTCompound> list, Inventory inventory) {
for (int i = 0; i < inventory.getSize(); i++) {
ItemStack stack = inventory.getItemStack(i);
final ItemStack stack = inventory.getItemStack(i);
NBTCompound nbt = new NBTCompound();
NBTCompound tag = new NBTCompound();
@ -71,8 +71,8 @@ public class NBTUtils {
private static void writeEnchant(NBTCompound nbt, String listName, Map<Enchantment, Short> enchantmentMap) {
NBTList<NBTCompound> enchantList = new NBTList<>(NBTTypes.TAG_Compound);
for (Map.Entry<Enchantment, Short> entry : enchantmentMap.entrySet()) {
Enchantment enchantment = entry.getKey();
short level = entry.getValue();
final Enchantment enchantment = entry.getKey();
final short level = entry.getValue();
enchantList.add(new NBTCompound()
.setShort("lvl", level)
@ -177,9 +177,9 @@ public class NBTUtils {
private static void loadEnchantments(NBTList<NBTCompound> enchantments, EnchantmentSetter setter) {
for (NBTCompound enchantment : enchantments) {
short level = enchantment.getShort("lvl");
String id = enchantment.getString("id");
Enchantment enchant = Registries.getEnchantment(id);
final short level = enchantment.getShort("lvl");
final String id = enchantment.getString("id");
final Enchantment enchant = Registries.getEnchantment(id);
if (enchant != null) {
setter.applyEnchantment(enchant, level);
} else {
@ -207,7 +207,7 @@ public class NBTUtils {
saveDataIntoNBT(itemStack, itemNBT);
// Custom item nbt
NBTConsumer nbtConsumer = itemStack.getNBTConsumer();
final NBTConsumer nbtConsumer = itemStack.getNBTConsumer();
if (nbtConsumer != null) {
nbtConsumer.accept(itemNBT);
}