mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-01 05:58:00 +01:00
Micro optimization + cleanup
This commit is contained in:
parent
c5172a7275
commit
8b30caa8c8
@ -102,8 +102,6 @@ public class MinecraftServer {
|
||||
//Rate Limiting
|
||||
private static int rateLimit = 0;
|
||||
|
||||
// Networking
|
||||
private static PacketProcessor packetProcessor;
|
||||
private static PacketListenerManager packetListenerManager;
|
||||
private static NettyServer nettyServer;
|
||||
|
||||
@ -161,7 +159,8 @@ public class MinecraftServer {
|
||||
Fluid.values();
|
||||
|
||||
connectionManager = new ConnectionManager();
|
||||
packetProcessor = new PacketProcessor();
|
||||
// Networking
|
||||
final PacketProcessor packetProcessor = new PacketProcessor();
|
||||
packetListenerManager = new PacketListenerManager();
|
||||
|
||||
instanceManager = new InstanceManager();
|
||||
|
@ -13,6 +13,7 @@ import net.minestom.server.utils.thread.MinestomThread;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.function.Consumer;
|
||||
@ -61,7 +62,7 @@ public final class UpdateManager {
|
||||
//Tick Callbacks
|
||||
tickStartCallbacks.forEach(Runnable::run);
|
||||
|
||||
ArrayList<Future<?>> futures;
|
||||
List<Future<?>> futures;
|
||||
|
||||
// Server tick (instance/chunk/entity)
|
||||
// Synchronize with the update manager instance, like the signal for chunk load/unload
|
||||
|
@ -11,7 +11,7 @@ import java.util.Map;
|
||||
*/
|
||||
public class AdvancementManager {
|
||||
|
||||
private Map<String, AdvancementTab> advancementTabMap = new HashMap<>();
|
||||
private final Map<String, AdvancementTab> advancementTabMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Create a new tab with a single advancement
|
||||
|
@ -16,14 +16,14 @@ import java.util.*;
|
||||
*/
|
||||
public class AdvancementTab implements Viewable {
|
||||
|
||||
private static Map<Player, Set<AdvancementTab>> playerTabMap = new HashMap<>();
|
||||
private static final Map<Player, Set<AdvancementTab>> PLAYER_TAB_MAP = new HashMap<>();
|
||||
|
||||
private Set<Player> viewers = new HashSet<>();
|
||||
private final Set<Player> viewers = new HashSet<>();
|
||||
|
||||
private AdvancementRoot root;
|
||||
private final AdvancementRoot root;
|
||||
|
||||
// Advancement -> its parent
|
||||
private Map<Advancement, Advancement> advancementMap = new HashMap<>();
|
||||
private final Map<Advancement, Advancement> advancementMap = new HashMap<>();
|
||||
|
||||
// Packet cache, updated every time the tab changes
|
||||
protected ByteBuf createBuffer;
|
||||
@ -47,7 +47,7 @@ public class AdvancementTab implements Viewable {
|
||||
* @return all the advancement tabs that the player sees
|
||||
*/
|
||||
public static Set<AdvancementTab> getTabs(Player player) {
|
||||
return playerTabMap.getOrDefault(player, null);
|
||||
return PLAYER_TAB_MAP.getOrDefault(player, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -171,7 +171,7 @@ public class AdvancementTab implements Viewable {
|
||||
* @param player the player
|
||||
*/
|
||||
private void addPlayer(Player player) {
|
||||
Set<AdvancementTab> tabs = playerTabMap.computeIfAbsent(player, p -> new HashSet<>());
|
||||
Set<AdvancementTab> tabs = PLAYER_TAB_MAP.computeIfAbsent(player, p -> new HashSet<>());
|
||||
tabs.add(this);
|
||||
}
|
||||
|
||||
@ -181,13 +181,13 @@ public class AdvancementTab implements Viewable {
|
||||
* @param player the player
|
||||
*/
|
||||
private void removePlayer(Player player) {
|
||||
if (!playerTabMap.containsKey(player)) {
|
||||
if (!PLAYER_TAB_MAP.containsKey(player)) {
|
||||
return;
|
||||
}
|
||||
Set<AdvancementTab> tabs = playerTabMap.get(player);
|
||||
Set<AdvancementTab> tabs = PLAYER_TAB_MAP.get(player);
|
||||
tabs.remove(this);
|
||||
if (tabs.isEmpty()) {
|
||||
playerTabMap.remove(player);
|
||||
PLAYER_TAB_MAP.remove(player);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,6 @@ public class BenchmarkManager {
|
||||
|
||||
private boolean enabled = false;
|
||||
private volatile boolean stop = false;
|
||||
private Thread thread;
|
||||
|
||||
private long time;
|
||||
|
||||
@ -51,7 +50,7 @@ public class BenchmarkManager {
|
||||
|
||||
time = updateOption.getTimeUnit().toMilliseconds(updateOption.getValue());
|
||||
|
||||
this.thread = new Thread(null, () -> {
|
||||
final Thread thread = new Thread(null, () -> {
|
||||
|
||||
while (!stop) {
|
||||
refreshData();
|
||||
@ -67,7 +66,7 @@ public class BenchmarkManager {
|
||||
|
||||
}, MinecraftServer.THREAD_NAME_BENCHMARK, 0L);
|
||||
|
||||
this.thread.start();
|
||||
thread.start();
|
||||
|
||||
this.enabled = true;
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ public class ColoredText {
|
||||
}
|
||||
|
||||
private static String toLegacy(String message, char colorChar) {
|
||||
String result = "";
|
||||
StringBuilder result = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < message.length(); i++) {
|
||||
final char c = message.charAt(i);
|
||||
@ -71,19 +71,19 @@ public class ColoredText {
|
||||
final char nextChar = message.charAt(i + 1);
|
||||
final ChatColor color = ChatColor.fromLegacyColorCodes(nextChar);
|
||||
if (color != ChatColor.NO_COLOR) {
|
||||
String replacement = color.toString();
|
||||
result += replacement;
|
||||
final String replacement = color.toString();
|
||||
result.append(replacement);
|
||||
i++; // Increment to ignore the color code
|
||||
} else {
|
||||
result += c;
|
||||
result.append(c);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result += c;
|
||||
result.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public ColoredText appendLegacy(String message, char colorChar) {
|
||||
|
@ -39,11 +39,11 @@ public class TranslatableText {
|
||||
final String prefix = "{@";
|
||||
final String suffix = "}";
|
||||
|
||||
String content = code;
|
||||
StringBuilder content = new StringBuilder(code);
|
||||
|
||||
if (arguments != null && arguments.length > 0) {
|
||||
for (String arg : arguments) {
|
||||
content += "," + arg;
|
||||
content.append("," + arg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,37 +104,41 @@ public class CommandDispatcher {
|
||||
// true if the arg is valid, false otherwise
|
||||
boolean correct = false;
|
||||
// the raw string representing the correct argument syntax
|
||||
String argValue = "";
|
||||
StringBuilder argValue = new StringBuilder();
|
||||
|
||||
if (useRemaining) {
|
||||
for (int i = argIndex; i < args.length; i++) {
|
||||
final String arg = args[i];
|
||||
if (argValue.length() > 0)
|
||||
argValue += " ";
|
||||
argValue += arg;
|
||||
argValue.append(" ");
|
||||
argValue.append(arg);
|
||||
}
|
||||
|
||||
correctionResult = argument.getCorrectionResult(argValue);
|
||||
final String argValueString = argValue.toString();
|
||||
|
||||
correctionResult = argument.getCorrectionResult(argValueString);
|
||||
if (correctionResult == Argument.SUCCESS) {
|
||||
correct = true;
|
||||
argsValues[argIndex] = argValue;
|
||||
argsValues[argIndex] = argValueString;
|
||||
}
|
||||
} else {
|
||||
for (int i = argIndex; i < args.length; i++) {
|
||||
final String arg = args[i];
|
||||
|
||||
argValue += arg;
|
||||
argValue.append(arg);
|
||||
|
||||
correctionResult = argument.getCorrectionResult(argValue);
|
||||
final String argValueString = argValue.toString();
|
||||
|
||||
correctionResult = argument.getCorrectionResult(argValueString);
|
||||
if (correctionResult == Argument.SUCCESS) {
|
||||
correct = true;
|
||||
argsValues[argIndex] = argValue;
|
||||
argsValues[argIndex] = argValueString;
|
||||
argIndex = i + 1;
|
||||
break;
|
||||
} else {
|
||||
if (!argument.allowSpace())
|
||||
break;
|
||||
argValue += " ";
|
||||
argValue.append(" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -145,7 +149,7 @@ public class CommandDispatcher {
|
||||
syntaxCorrect = false;
|
||||
CommandSuggestionHolder suggestionHolder = new CommandSuggestionHolder();
|
||||
suggestionHolder.syntax = syntax;
|
||||
suggestionHolder.argValue = argValue;
|
||||
suggestionHolder.argValue = argValue.toString();
|
||||
suggestionHolder.correctionResult = correctionResult;
|
||||
suggestionHolder.argIndex = argCount;
|
||||
syntaxesSuggestions.put(argCount, suggestionHolder);
|
||||
@ -222,7 +226,7 @@ public class CommandDispatcher {
|
||||
return result;
|
||||
}
|
||||
|
||||
private class CommandSuggestionHolder {
|
||||
private static class CommandSuggestionHolder {
|
||||
private CommandSyntax syntax;
|
||||
private String argValue;
|
||||
private int correctionResult;
|
||||
@ -230,7 +234,7 @@ public class CommandDispatcher {
|
||||
|
||||
}
|
||||
|
||||
private class CommandResult {
|
||||
private static class CommandResult {
|
||||
|
||||
// Command
|
||||
private Command command;
|
||||
|
@ -27,7 +27,7 @@ public class Data {
|
||||
}
|
||||
};
|
||||
|
||||
protected ConcurrentHashMap<String, Object> data = new ConcurrentHashMap();
|
||||
protected final ConcurrentHashMap<String, Object> data = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Set a value to a specific key
|
||||
|
@ -28,16 +28,15 @@ public final class EntityManager {
|
||||
private void waitingPlayersTick() {
|
||||
Player waitingPlayer;
|
||||
while ((waitingPlayer = waitingPlayers.poll()) != null) {
|
||||
final Player playerCache = waitingPlayer;
|
||||
playerCache.init();
|
||||
waitingPlayer.init();
|
||||
|
||||
PlayerLoginEvent loginEvent = new PlayerLoginEvent(playerCache);
|
||||
playerCache.callEvent(PlayerLoginEvent.class, loginEvent);
|
||||
PlayerLoginEvent loginEvent = new PlayerLoginEvent(waitingPlayer);
|
||||
waitingPlayer.callEvent(PlayerLoginEvent.class, loginEvent);
|
||||
final Instance spawningInstance = loginEvent.getSpawningInstance();
|
||||
|
||||
Check.notNull(spawningInstance, "You need to specify a spawning instance in the PlayerLoginEvent");
|
||||
|
||||
playerCache.setInstance(spawningInstance);
|
||||
waitingPlayer.setInstance(spawningInstance);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
|
||||
// Bounding box used for items' pickup (see LivingEntity#setBoundingBox)
|
||||
protected BoundingBox expandedBoundingBox;
|
||||
|
||||
private float[] attributeValues = new float[Attribute.values().length];
|
||||
private final float[] attributeValues = new float[Attribute.values().length];
|
||||
|
||||
private boolean isHandActive;
|
||||
private boolean offHand;
|
||||
|
@ -1858,8 +1858,8 @@ public class Player extends LivingEntity implements CommandSender {
|
||||
if (isFood && !allowFood)
|
||||
return null;
|
||||
|
||||
ItemUpdateStateEvent itemUpdateStateEvent = new ItemUpdateStateEvent(updatedItem,
|
||||
isOffhand ? Hand.OFF : Hand.MAIN);
|
||||
final Hand hand = isOffhand ? Hand.OFF : Hand.MAIN;
|
||||
ItemUpdateStateEvent itemUpdateStateEvent = new ItemUpdateStateEvent(this, hand, updatedItem);
|
||||
callEvent(ItemUpdateStateEvent.class, itemUpdateStateEvent);
|
||||
|
||||
return itemUpdateStateEvent;
|
||||
|
@ -17,7 +17,7 @@ public class Hologram implements Viewable {
|
||||
|
||||
private static final float OFFSET_Y = -0.9875f;
|
||||
|
||||
private HologramEntity entity;
|
||||
private final HologramEntity entity;
|
||||
|
||||
private Position position;
|
||||
private ColoredText text;
|
||||
@ -124,7 +124,7 @@ public class Hologram implements Viewable {
|
||||
}
|
||||
|
||||
|
||||
private class HologramEntity extends EntityArmorStand {
|
||||
private static class HologramEntity extends EntityArmorStand {
|
||||
|
||||
public HologramEntity(Position spawnPosition) {
|
||||
super(spawnPosition);
|
||||
|
@ -7,7 +7,7 @@ import net.minestom.server.instance.block.Block;
|
||||
|
||||
public class PFBlockDescription implements IBlockDescription {
|
||||
|
||||
private static Short2ObjectMap<PFBlockDescription> blockDescriptionMap = new Short2ObjectOpenHashMap<>();
|
||||
private static final Short2ObjectMap<PFBlockDescription> BLOCK_DESCRITION_MAP = new Short2ObjectOpenHashMap<>();
|
||||
|
||||
/**
|
||||
* Get the {@link PFBlockDescription} linked to the block state id
|
||||
@ -18,19 +18,19 @@ public class PFBlockDescription implements IBlockDescription {
|
||||
* @return the {@link PFBlockDescription} linked to {@code blockStateId}
|
||||
*/
|
||||
public static PFBlockDescription getBlockDescription(short blockStateId) {
|
||||
if (!blockDescriptionMap.containsKey(blockStateId)) {
|
||||
synchronized (blockDescriptionMap) {
|
||||
if (!BLOCK_DESCRITION_MAP.containsKey(blockStateId)) {
|
||||
synchronized (BLOCK_DESCRITION_MAP) {
|
||||
final Block block = Block.fromStateId(blockStateId);
|
||||
final PFBlockDescription blockDescription = new PFBlockDescription(block);
|
||||
blockDescriptionMap.put(blockStateId, blockDescription);
|
||||
BLOCK_DESCRITION_MAP.put(blockStateId, blockDescription);
|
||||
return blockDescription;
|
||||
}
|
||||
}
|
||||
|
||||
return blockDescriptionMap.get(blockStateId);
|
||||
return BLOCK_DESCRITION_MAP.get(blockStateId);
|
||||
}
|
||||
|
||||
private Block block;
|
||||
private final Block block;
|
||||
|
||||
public PFBlockDescription(Block block) {
|
||||
this.block = block;
|
||||
|
@ -8,7 +8,7 @@ import net.minestom.server.instance.block.Block;
|
||||
|
||||
public class PFBlockObject implements IBlockObject {
|
||||
|
||||
private static Short2ObjectMap<PFBlockObject> blockObjectsMap = new Short2ObjectOpenHashMap<>();
|
||||
private static final Short2ObjectMap<PFBlockObject> BLOCK_OBJECT_MAP = new Short2ObjectOpenHashMap<>();
|
||||
|
||||
/**
|
||||
* Get the {@link PFBlockObject} linked to the block state id
|
||||
@ -19,19 +19,19 @@ public class PFBlockObject implements IBlockObject {
|
||||
* @return the {@link PFBlockObject} linked to {@code blockStateId}
|
||||
*/
|
||||
public static PFBlockObject getBlockObject(short blockStateId) {
|
||||
if (!blockObjectsMap.containsKey(blockStateId)) {
|
||||
synchronized (blockObjectsMap) {
|
||||
if (!BLOCK_OBJECT_MAP.containsKey(blockStateId)) {
|
||||
synchronized (BLOCK_OBJECT_MAP) {
|
||||
final Block block = Block.fromStateId(blockStateId);
|
||||
final PFBlockObject blockObject = new PFBlockObject(block);
|
||||
blockObjectsMap.put(blockStateId, blockObject);
|
||||
BLOCK_OBJECT_MAP.put(blockStateId, blockObject);
|
||||
return blockObject;
|
||||
}
|
||||
}
|
||||
|
||||
return blockObjectsMap.get(blockStateId);
|
||||
return BLOCK_OBJECT_MAP.get(blockStateId);
|
||||
}
|
||||
|
||||
private Block block;
|
||||
private final Block block;
|
||||
|
||||
public PFBlockObject(Block block) {
|
||||
this.block = block;
|
||||
|
@ -31,14 +31,11 @@ public class PFInstanceSpace implements IInstanceSpace {
|
||||
return null;
|
||||
}
|
||||
|
||||
final PFColumnarSpace columnarSpace =
|
||||
chunkSpaceMap.computeIfAbsent(chunk, c -> {
|
||||
final PFColumnarSpace cs = new PFColumnarSpace(this, c);
|
||||
c.setColumnarSpace(cs);
|
||||
return cs;
|
||||
});
|
||||
|
||||
return columnarSpace;
|
||||
return chunkSpaceMap.computeIfAbsent(chunk, c -> {
|
||||
final PFColumnarSpace cs = new PFColumnarSpace(this, c);
|
||||
c.setColumnarSpace(cs);
|
||||
return cs;
|
||||
});
|
||||
}
|
||||
|
||||
public Instance getInstance() {
|
||||
|
@ -43,7 +43,7 @@ public interface EventHandler {
|
||||
* @param <E> the event type
|
||||
*/
|
||||
default <E extends Event> void callEvent(Class<E> eventClass, E event) {
|
||||
List<EventCallback> eventCallbacks = getEventCallbacks(eventClass);
|
||||
final List<EventCallback> eventCallbacks = getEventCallbacks(eventClass);
|
||||
for (EventCallback<E> eventCallback : eventCallbacks) {
|
||||
eventCallback.run(event);
|
||||
}
|
||||
|
@ -8,8 +8,8 @@ import net.minestom.server.instance.Instance;
|
||||
*/
|
||||
public class InstanceChunkLoadEvent extends Event {
|
||||
|
||||
private Instance instance;
|
||||
private int chunkX, chunkZ;
|
||||
private final Instance instance;
|
||||
private final int chunkX, chunkZ;
|
||||
|
||||
public InstanceChunkLoadEvent(Instance instance, int chunkX, int chunkZ) {
|
||||
this.instance = instance;
|
||||
|
@ -8,8 +8,8 @@ import net.minestom.server.instance.Instance;
|
||||
*/
|
||||
public class InstanceChunkUnloadEvent extends Event {
|
||||
|
||||
private Instance instance;
|
||||
private int chunkX, chunkZ;
|
||||
private final Instance instance;
|
||||
private final int chunkX, chunkZ;
|
||||
|
||||
public InstanceChunkUnloadEvent(Instance instance, int chunkX, int chunkZ) {
|
||||
this.instance = instance;
|
||||
|
@ -8,14 +8,15 @@ import net.minestom.server.item.ItemStack;
|
||||
|
||||
public class InventoryClickEvent extends Event {
|
||||
|
||||
private Player player;
|
||||
private Inventory inventory;
|
||||
private int slot;
|
||||
private ClickType clickType;
|
||||
private ItemStack clickedItem;
|
||||
private ItemStack cursorItem;
|
||||
private final Player player;
|
||||
private final Inventory inventory;
|
||||
private final int slot;
|
||||
private final ClickType clickType;
|
||||
private final ItemStack clickedItem;
|
||||
private final ItemStack cursorItem;
|
||||
|
||||
public InventoryClickEvent(Player player, Inventory inventory, int slot, ClickType clickType, ItemStack clicked, ItemStack cursor) {
|
||||
this.player = player;
|
||||
this.inventory = inventory;
|
||||
this.slot = slot;
|
||||
this.clickType = clickType;
|
||||
|
@ -6,8 +6,8 @@ import net.minestom.server.inventory.Inventory;
|
||||
|
||||
public class InventoryCloseEvent extends Event {
|
||||
|
||||
private Player player;
|
||||
private Inventory inventory;
|
||||
private final Player player;
|
||||
private final Inventory inventory;
|
||||
private Inventory newInventory;
|
||||
|
||||
public InventoryCloseEvent(Player player, Inventory inventory) {
|
||||
|
@ -6,7 +6,7 @@ import net.minestom.server.inventory.Inventory;
|
||||
|
||||
public class InventoryOpenEvent extends CancellableEvent {
|
||||
|
||||
private Player player;
|
||||
private final Player player;
|
||||
private Inventory inventory;
|
||||
|
||||
public InventoryOpenEvent(Player player, Inventory inventory) {
|
||||
|
@ -9,10 +9,10 @@ import net.minestom.server.utils.item.ItemStackUtils;
|
||||
|
||||
public class InventoryPreClickEvent extends CancellableEvent {
|
||||
|
||||
private Player player;
|
||||
private Inventory inventory;
|
||||
private int slot;
|
||||
private ClickType clickType;
|
||||
private final Player player;
|
||||
private final Inventory inventory;
|
||||
private final int slot;
|
||||
private final ClickType clickType;
|
||||
private ItemStack clickedItem;
|
||||
private ItemStack cursorItem;
|
||||
|
||||
|
@ -6,23 +6,29 @@ import net.minestom.server.item.ItemStack;
|
||||
|
||||
public class ItemUpdateStateEvent extends Event {
|
||||
|
||||
private ItemStack itemStack;
|
||||
private Player.Hand hand;
|
||||
private Player player;
|
||||
private final Player.Hand hand;
|
||||
private final ItemStack itemStack;
|
||||
private boolean handAnimation;
|
||||
|
||||
public ItemUpdateStateEvent(ItemStack itemStack, Player.Hand hand) {
|
||||
this.itemStack = itemStack;
|
||||
public ItemUpdateStateEvent(Player player, Player.Hand hand, ItemStack itemStack) {
|
||||
this.player = player;
|
||||
this.hand = hand;
|
||||
this.itemStack = itemStack;
|
||||
}
|
||||
|
||||
public ItemStack getItemStack() {
|
||||
return itemStack;
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public Player.Hand getHand() {
|
||||
return hand;
|
||||
}
|
||||
|
||||
public ItemStack getItemStack() {
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
public void setHandAnimation(boolean handAnimation) {
|
||||
this.handAnimation = handAnimation;
|
||||
}
|
||||
|
@ -28,7 +28,6 @@ import net.minestom.server.world.biomes.Biome;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
// TODO light data & API
|
||||
@ -46,10 +45,6 @@ public abstract class Chunk implements Viewable {
|
||||
protected Biome[] biomes;
|
||||
protected int chunkX, chunkZ;
|
||||
|
||||
// blocks id based on coord, see Chunk#getBlockIndex
|
||||
//public short[] blocksStateId = new short[CHUNK_SIZE_X * CHUNK_SIZE_Y * CHUNK_SIZE_Z];
|
||||
//protected short[] customBlocksId = new short[CHUNK_SIZE_X * CHUNK_SIZE_Y * CHUNK_SIZE_Z];
|
||||
|
||||
// Used to get all blocks with data (no null)
|
||||
// Key is still chunk coord
|
||||
protected Int2ObjectMap<Data> blocksData = new Int2ObjectOpenHashMap<>(16 * 16); // Start with the size of a single row
|
||||
@ -59,7 +54,7 @@ public abstract class Chunk implements Viewable {
|
||||
// (block index)/(last update in ms)
|
||||
protected Int2LongMap updatableBlocksLastUpdate = new Int2LongOpenHashMap();
|
||||
|
||||
protected AtomicBoolean packetUpdated = new AtomicBoolean(false);
|
||||
protected volatile boolean packetUpdated;
|
||||
|
||||
// Block entities
|
||||
protected Set<Integer> blockEntities = new CopyOnWriteArraySet<>();
|
||||
@ -114,8 +109,10 @@ public abstract class Chunk implements Viewable {
|
||||
public abstract CustomBlock getCustomBlock(int x, int y, int z);
|
||||
|
||||
protected CustomBlock getCustomBlock(int index) {
|
||||
final int[] pos = ChunkUtils.indexToChunkPosition(index);
|
||||
return getCustomBlock(pos[0], pos[1], pos[2]);
|
||||
final int x = ChunkUtils.blockIndexToChunkPositionX(index);
|
||||
final int y = ChunkUtils.blockIndexToChunkPositionY(index);
|
||||
final int z = ChunkUtils.blockIndexToChunkPositionZ(index);
|
||||
return getCustomBlock(x, y, z);
|
||||
}
|
||||
|
||||
protected abstract void refreshBlockValue(int x, int y, int z, short blockStateId, short customId);
|
||||
@ -142,7 +139,7 @@ public abstract class Chunk implements Viewable {
|
||||
return;
|
||||
|
||||
// Block all chunk operation during the update
|
||||
IntIterator iterator = new IntOpenHashSet(updatableBlocks).iterator();
|
||||
final IntIterator iterator = new IntOpenHashSet(updatableBlocks).iterator();
|
||||
while (iterator.hasNext()) {
|
||||
final int index = iterator.nextInt();
|
||||
final CustomBlock customBlock = getCustomBlock(index);
|
||||
@ -156,12 +153,7 @@ public abstract class Chunk implements Viewable {
|
||||
|
||||
this.updatableBlocksLastUpdate.put(index, time); // Refresh last update time
|
||||
|
||||
final int[] blockPos = ChunkUtils.indexToPosition(index, chunkX, chunkZ);
|
||||
final int x = blockPos[0];
|
||||
final int y = blockPos[1];
|
||||
final int z = blockPos[2];
|
||||
|
||||
final BlockPosition blockPosition = new BlockPosition(x, y, z);
|
||||
final BlockPosition blockPosition = ChunkUtils.getBlockPosition(index, chunkX, chunkZ);
|
||||
final Data data = getData(index);
|
||||
customBlock.update(instance, blockPosition, data);
|
||||
}
|
||||
@ -192,7 +184,7 @@ public abstract class Chunk implements Viewable {
|
||||
|
||||
public void setFullDataPacket(ByteBuf fullDataPacket) {
|
||||
this.fullDataPacket = fullDataPacket;
|
||||
this.packetUpdated.set(true);
|
||||
this.packetUpdated = true;
|
||||
}
|
||||
|
||||
protected boolean isBlockEntity(short blockStateId) {
|
||||
@ -214,13 +206,13 @@ public abstract class Chunk implements Viewable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the updated data packet
|
||||
* Retrieve (and save if needed) the updated data packet
|
||||
*
|
||||
* @param consumer the consumer called once the packet is sure to be up-to-date
|
||||
*/
|
||||
public void retrieveDataBuffer(Consumer<ByteBuf> consumer) {
|
||||
final ByteBuf data = getFullDataPacket();
|
||||
if (data == null || !packetUpdated.get()) {
|
||||
if (data == null || !packetUpdated) {
|
||||
PacketWriterUtils.writeCallbackPacket(getFreshFullDataPacket(), packet -> {
|
||||
setFullDataPacket(packet);
|
||||
consumer.accept(packet);
|
||||
@ -325,9 +317,7 @@ public abstract class Chunk implements Viewable {
|
||||
|
||||
final PlayerConnection playerConnection = player.getPlayerConnection();
|
||||
|
||||
retrieveDataBuffer(buf -> {
|
||||
playerConnection.sendPacket(buf, true);
|
||||
});
|
||||
retrieveDataBuffer(buf -> playerConnection.sendPacket(buf, true));
|
||||
|
||||
// TODO do not hardcode
|
||||
if (MinecraftServer.isFixLighting()) {
|
||||
@ -372,15 +362,13 @@ public abstract class Chunk implements Viewable {
|
||||
public void sendChunkUpdate() {
|
||||
final Set<Player> chunkViewers = getViewers();
|
||||
if (!chunkViewers.isEmpty()) {
|
||||
retrieveDataBuffer(buf -> {
|
||||
chunkViewers.forEach(player -> {
|
||||
final PlayerConnection playerConnection = player.getPlayerConnection();
|
||||
if (!PlayerUtils.isNettyClient(playerConnection))
|
||||
return;
|
||||
retrieveDataBuffer(buf -> chunkViewers.forEach(player -> {
|
||||
final PlayerConnection playerConnection = player.getPlayerConnection();
|
||||
if (!PlayerUtils.isNettyClient(playerConnection))
|
||||
return;
|
||||
|
||||
playerConnection.sendPacket(buf, true);
|
||||
});
|
||||
});
|
||||
playerConnection.sendPacket(buf, true);
|
||||
}));
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -18,8 +18,9 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
public class DynamicChunk extends Chunk {
|
||||
|
||||
public short[] blocksStateId = new short[CHUNK_SIZE_X * CHUNK_SIZE_Y * CHUNK_SIZE_Z];
|
||||
private short[] customBlocksId = new short[CHUNK_SIZE_X * CHUNK_SIZE_Y * CHUNK_SIZE_Z];
|
||||
// blocks id based on coordinate, see Chunk#getBlockIndex
|
||||
private final short[] blocksStateId = new short[CHUNK_SIZE_X * CHUNK_SIZE_Y * CHUNK_SIZE_Z];
|
||||
private final short[] customBlocksId = new short[CHUNK_SIZE_X * CHUNK_SIZE_Y * CHUNK_SIZE_Z];
|
||||
|
||||
public DynamicChunk(Biome[] biomes, int chunkX, int chunkZ) {
|
||||
super(biomes, chunkX, chunkZ);
|
||||
@ -50,8 +51,7 @@ public class DynamicChunk extends Chunk {
|
||||
}
|
||||
|
||||
final int index = getBlockIndex(x, y, z);
|
||||
if (blockStateId != 0
|
||||
|| (blockStateId == 0 && customId != 0 && updateConsumer != null)) { // Allow custom air block for update purpose, refused if no update consumer has been found
|
||||
if (blockStateId != 0 || customId != 0 && updateConsumer != null) { // Allow custom air block for update purpose, refused if no update consumer has been found
|
||||
this.blocksStateId[index] = blockStateId;
|
||||
this.customBlocksId[index] = customId;
|
||||
} else {
|
||||
@ -66,7 +66,7 @@ public class DynamicChunk extends Chunk {
|
||||
|
||||
this.blockEntities.remove(index);
|
||||
|
||||
this.packetUpdated.set(false);
|
||||
this.packetUpdated = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -93,7 +93,7 @@ public class DynamicChunk extends Chunk {
|
||||
this.blockEntities.remove(index);
|
||||
}
|
||||
|
||||
this.packetUpdated.set(false);
|
||||
this.packetUpdated = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -102,8 +102,7 @@ public class DynamicChunk extends Chunk {
|
||||
if (!MathUtils.isBetween(index, 0, blocksStateId.length)) {
|
||||
return 0; // TODO: custom invalid block
|
||||
}
|
||||
final short id = blocksStateId[index];
|
||||
return id;
|
||||
return blocksStateId[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -112,8 +111,7 @@ public class DynamicChunk extends Chunk {
|
||||
if (!MathUtils.isBetween(index, 0, blocksStateId.length)) {
|
||||
return 0; // TODO: custom invalid block
|
||||
}
|
||||
final short id = customBlocksId[index];
|
||||
return id;
|
||||
return customBlocksId[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -179,7 +177,7 @@ public class DynamicChunk extends Chunk {
|
||||
dos.writeShort(customBlockId);
|
||||
|
||||
// Data
|
||||
final boolean hasData = (data != null && (data instanceof SerializableData));
|
||||
final boolean hasData = data instanceof SerializableData;
|
||||
dos.writeBoolean(hasData);
|
||||
if (hasData) {
|
||||
final byte[] d = ((SerializableData) data).getSerializedData();
|
||||
@ -190,8 +188,7 @@ public class DynamicChunk extends Chunk {
|
||||
}
|
||||
}
|
||||
|
||||
final byte[] result = output.toByteArray();
|
||||
return result;
|
||||
return output.toByteArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -48,9 +48,9 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
|
||||
|
||||
private boolean registered;
|
||||
|
||||
private DimensionType dimensionType;
|
||||
private final DimensionType dimensionType;
|
||||
|
||||
private WorldBorder worldBorder;
|
||||
private final WorldBorder worldBorder;
|
||||
|
||||
// Tick since the creation of the instance
|
||||
private long worldAge;
|
||||
@ -61,24 +61,24 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
|
||||
private UpdateOption timeUpdate = new UpdateOption(1, TimeUnit.TICK);
|
||||
private long lastTimeUpdate;
|
||||
|
||||
private Map<Class<? extends Event>, List<EventCallback>> eventCallbacks = new ConcurrentHashMap<>();
|
||||
private final Map<Class<? extends Event>, List<EventCallback>> eventCallbacks = new ConcurrentHashMap<>();
|
||||
|
||||
// Entities present in this instance
|
||||
protected Set<Player> players = new CopyOnWriteArraySet<>();
|
||||
protected Set<EntityCreature> creatures = new CopyOnWriteArraySet<>();
|
||||
protected Set<ObjectEntity> objectEntities = new CopyOnWriteArraySet<>();
|
||||
protected Set<ExperienceOrb> experienceOrbs = new CopyOnWriteArraySet<>();
|
||||
protected final Set<Player> players = new CopyOnWriteArraySet<>();
|
||||
protected final Set<EntityCreature> creatures = new CopyOnWriteArraySet<>();
|
||||
protected final Set<ObjectEntity> objectEntities = new CopyOnWriteArraySet<>();
|
||||
protected final Set<ExperienceOrb> experienceOrbs = new CopyOnWriteArraySet<>();
|
||||
// Entities per chunk
|
||||
protected Map<Long, Set<Entity>> chunkEntities = new ConcurrentHashMap<>();
|
||||
protected final Map<Long, Set<Entity>> chunkEntities = new ConcurrentHashMap<>();
|
||||
protected UUID uniqueId;
|
||||
|
||||
protected List<Consumer<Instance>> nextTick = Collections.synchronizedList(new ArrayList<>());
|
||||
protected final List<Consumer<Instance>> nextTick = Collections.synchronizedList(new ArrayList<>());
|
||||
|
||||
private Data data;
|
||||
private ExplosionSupplier explosionSupplier;
|
||||
|
||||
// Pathfinder
|
||||
private PFInstanceSpace instanceSpace = new PFInstanceSpace(this);
|
||||
private final PFInstanceSpace instanceSpace = new PFInstanceSpace(this);
|
||||
|
||||
public Instance(UUID uniqueId, DimensionType dimensionType) {
|
||||
this.uniqueId = uniqueId;
|
||||
@ -754,13 +754,13 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
|
||||
*/
|
||||
public void removeEntity(Entity entity) {
|
||||
final Instance entityInstance = entity.getInstance();
|
||||
if (entityInstance == null || entityInstance != this)
|
||||
if (entityInstance != this)
|
||||
return;
|
||||
|
||||
RemoveEntityFromInstanceEvent event = new RemoveEntityFromInstanceEvent(this, entity);
|
||||
callCancellableEvent(RemoveEntityFromInstanceEvent.class, event, () -> {
|
||||
// Remove this entity from players viewable list and send delete entities packet
|
||||
entity.getViewers().forEach(p -> entity.removeViewer(p));
|
||||
entity.getViewers().forEach(entity::removeViewer);
|
||||
|
||||
// Remove the entity from cache
|
||||
final Chunk chunk = getChunkAt(entity.getPosition());
|
||||
@ -832,8 +832,7 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
|
||||
}
|
||||
|
||||
private Set<Entity> getEntitiesInChunk(long index) {
|
||||
final Set<Entity> entities = chunkEntities.computeIfAbsent(index, i -> new CopyOnWriteArraySet<>());
|
||||
return entities;
|
||||
return chunkEntities.computeIfAbsent(index, i -> new CopyOnWriteArraySet<>());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -864,7 +863,7 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
|
||||
// time
|
||||
this.worldAge++;
|
||||
|
||||
this.time += 1 * timeRate;
|
||||
this.time += timeRate;
|
||||
|
||||
if (timeUpdate != null && !CooldownUtils.hasCooldown(time, lastTimeUpdate, timeUpdate)) {
|
||||
PacketWriterUtils.writeAndSend(getPlayers(), getTimePacket());
|
||||
|
@ -54,8 +54,8 @@ public class InstanceContainer extends Instance {
|
||||
|
||||
private ChunkGenerator chunkGenerator;
|
||||
// WARNING: need to be synchronized properly
|
||||
private Long2ObjectMap<Chunk> chunks = new Long2ObjectOpenHashMap();
|
||||
private Set<Chunk> scheduledChunksToRemove = new HashSet<>();
|
||||
private final Long2ObjectMap<Chunk> chunks = new Long2ObjectOpenHashMap<>();
|
||||
private final Set<Chunk> scheduledChunksToRemove = new HashSet<>();
|
||||
|
||||
private ReadWriteLock changingBlockLock = new ReentrantReadWriteLock();
|
||||
private Map<BlockPosition, Block> currentlyChangingBlocks = new HashMap<>();
|
||||
@ -351,8 +351,9 @@ public class InstanceContainer extends Instance {
|
||||
Check.notNull(getStorageFolder(), "You cannot save the instance if no StorageFolder has been defined");
|
||||
|
||||
this.storageFolder.set(UUID_KEY, getUniqueId(), UUID.class);
|
||||
Data data = getData();
|
||||
final Data data = getData();
|
||||
if (data != null) {
|
||||
// Save the instance data
|
||||
Check.stateCondition(!(data instanceof SerializableData),
|
||||
"Instance#getData needs to be a SerializableData in order to be saved");
|
||||
this.storageFolder.set(DATA_KEY, (SerializableData) getData(), SerializableData.class);
|
||||
|
@ -11,7 +11,7 @@ import java.util.function.Consumer;
|
||||
public class MinestomBasicChunkLoader implements IChunkLoader {
|
||||
|
||||
private final static Logger LOGGER = LoggerFactory.getLogger(MinestomBasicChunkLoader.class);
|
||||
private StorageFolder storageFolder;
|
||||
private final StorageFolder storageFolder;
|
||||
|
||||
public MinestomBasicChunkLoader(StorageFolder storageFolder) {
|
||||
this.storageFolder = storageFolder;
|
||||
|
@ -19,7 +19,7 @@ import java.util.function.Consumer;
|
||||
*/
|
||||
public class SharedInstance extends Instance {
|
||||
|
||||
private InstanceContainer instanceContainer;
|
||||
private final InstanceContainer instanceContainer;
|
||||
|
||||
public SharedInstance(UUID uniqueId, InstanceContainer instanceContainer) {
|
||||
super(uniqueId, instanceContainer.getDimensionType());
|
||||
|
@ -70,8 +70,10 @@ public class StaticChunk extends Chunk {
|
||||
fullDataPacket.chunkZ = chunkZ;
|
||||
short[] blocksStateId = new short[CHUNK_SIZE_X * CHUNK_SIZE_Y * CHUNK_SIZE_Z];
|
||||
for (int i = 0; i < blocksStateId.length; i++) {
|
||||
final int[] pos = ChunkUtils.indexToPosition(i, 0, 0);
|
||||
blocksStateId[i] = blockProvider.getBlockStateId(pos[0], pos[1], pos[2]);
|
||||
final int x = ChunkUtils.blockIndexToChunkPositionX(i);
|
||||
final int y = ChunkUtils.blockIndexToChunkPositionY(i);
|
||||
final int z = ChunkUtils.blockIndexToChunkPositionZ(i);
|
||||
blocksStateId[i] = blockProvider.getBlockStateId(x, y, z);
|
||||
}
|
||||
fullDataPacket.blocksStateId = blocksStateId;
|
||||
fullDataPacket.customBlocksId = new short[0];
|
||||
|
@ -11,7 +11,7 @@ import net.minestom.server.utils.Position;
|
||||
*/
|
||||
public class WorldBorder {
|
||||
|
||||
private Instance instance;
|
||||
private final Instance instance;
|
||||
|
||||
private float centerX, centerZ;
|
||||
|
||||
|
@ -87,7 +87,7 @@ public class BlockBatch implements InstanceBatch {
|
||||
}
|
||||
}
|
||||
|
||||
private class BlockData {
|
||||
private static class BlockData {
|
||||
|
||||
private int x, y, z;
|
||||
private boolean hasCustomBlock;
|
||||
|
@ -18,8 +18,8 @@ import java.util.function.Consumer;
|
||||
*/
|
||||
public class ChunkBatch implements InstanceBatch {
|
||||
|
||||
private InstanceContainer instance;
|
||||
private Chunk chunk;
|
||||
private final InstanceContainer instance;
|
||||
private final Chunk chunk;
|
||||
|
||||
// Give it the max capacity by default (avoid resizing)
|
||||
private List<BlockData> dataList =
|
||||
@ -110,7 +110,7 @@ public class ChunkBatch implements InstanceBatch {
|
||||
}
|
||||
}
|
||||
|
||||
private class BlockData {
|
||||
private static class BlockData {
|
||||
|
||||
private int x, y, z;
|
||||
private boolean hasCustomBlock;
|
||||
|
@ -27,25 +27,26 @@ import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class Inventory implements InventoryModifier, InventoryClickHandler, Viewable {
|
||||
|
||||
private static volatile byte lastInventoryId;
|
||||
private static AtomicInteger lastInventoryId = new AtomicInteger();
|
||||
|
||||
private byte id;
|
||||
private final byte id;
|
||||
private final InventoryType inventoryType;
|
||||
private String title;
|
||||
|
||||
private int size;
|
||||
private final int size;
|
||||
|
||||
private int offset;
|
||||
private final int offset;
|
||||
|
||||
private ItemStack[] itemStacks;
|
||||
private Set<Player> viewers = new CopyOnWriteArraySet<>();
|
||||
private ConcurrentHashMap<Player, ItemStack> cursorPlayersItem = new ConcurrentHashMap<>();
|
||||
private final ItemStack[] itemStacks;
|
||||
private final Set<Player> viewers = new CopyOnWriteArraySet<>();
|
||||
private final ConcurrentHashMap<Player, ItemStack> cursorPlayersItem = new ConcurrentHashMap<>();
|
||||
|
||||
private List<InventoryCondition> inventoryConditions = new CopyOnWriteArrayList<>();
|
||||
private InventoryClickProcessor clickProcessor = new InventoryClickProcessor();
|
||||
private final List<InventoryCondition> inventoryConditions = new CopyOnWriteArrayList<>();
|
||||
private final InventoryClickProcessor clickProcessor = new InventoryClickProcessor();
|
||||
|
||||
// Cached windows packet
|
||||
|
||||
@ -64,8 +65,8 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
|
||||
}
|
||||
|
||||
private static byte generateId() {
|
||||
byte newInventoryId = ++lastInventoryId;
|
||||
if (newInventoryId < 0)
|
||||
byte newInventoryId = (byte) lastInventoryId.incrementAndGet();
|
||||
if (newInventoryId == Byte.MAX_VALUE)
|
||||
newInventoryId = 1;
|
||||
return newInventoryId;
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ public enum InventoryProperty {
|
||||
BREWING_STAND_FUEL_TIME((short) 1);
|
||||
|
||||
|
||||
private short property;
|
||||
private final short property;
|
||||
|
||||
InventoryProperty(short property) {
|
||||
this.property = property;
|
||||
|
@ -26,8 +26,8 @@ public enum InventoryType {
|
||||
CARTOGRAPHY(21, 3),
|
||||
STONE_CUTTER(22, 2);
|
||||
|
||||
private int windowType;
|
||||
private int slot;
|
||||
private final int windowType;
|
||||
private final int slot;
|
||||
|
||||
InventoryType(int windowType, int slot) {
|
||||
this.windowType = windowType;
|
||||
|
@ -8,12 +8,12 @@ import java.util.function.BiConsumer;
|
||||
|
||||
public class InventoryClickLoopHandler {
|
||||
|
||||
private int start;
|
||||
private int end;
|
||||
private int step;
|
||||
private Int2IntFunction indexModifier;
|
||||
private Int2ObjectFunction<ItemStack> itemGetter;
|
||||
private BiConsumer<Integer, ItemStack> itemSetter;
|
||||
private final int start;
|
||||
private final int end;
|
||||
private final int step;
|
||||
private final Int2IntFunction indexModifier;
|
||||
private final Int2ObjectFunction<ItemStack> itemGetter;
|
||||
private final BiConsumer<Integer, ItemStack> itemSetter;
|
||||
|
||||
public InventoryClickLoopHandler(int start, int end, int step,
|
||||
Int2IntFunction indexModifier,
|
||||
|
@ -23,8 +23,8 @@ import java.util.function.BiConsumer;
|
||||
public class InventoryClickProcessor {
|
||||
|
||||
// Dragging maps
|
||||
private Map<Player, IntSet> leftDraggingMap = new HashMap<>();
|
||||
private Map<Player, IntSet> rightDraggingMap = new HashMap<>();
|
||||
private final Map<Player, IntSet> leftDraggingMap = new HashMap<>();
|
||||
private final Map<Player, IntSet> rightDraggingMap = new HashMap<>();
|
||||
|
||||
public InventoryClickResult leftClick(Inventory inventory, Player player, int slot, ItemStack clicked, ItemStack cursor) {
|
||||
final InventoryClickResult clickResult = startCondition(inventory, player, slot, ClickType.LEFT_CLICK, clicked, cursor);
|
||||
|
@ -7,12 +7,12 @@ import java.util.UUID;
|
||||
|
||||
public class ItemAttribute {
|
||||
|
||||
private UUID uuid;
|
||||
private String internalName;
|
||||
private Attribute attribute;
|
||||
private AttributeOperation operation;
|
||||
private double value;
|
||||
private AttributeSlot slot;
|
||||
private final UUID uuid;
|
||||
private final String internalName;
|
||||
private final Attribute attribute;
|
||||
private final AttributeOperation operation;
|
||||
private final double value;
|
||||
private final AttributeSlot slot;
|
||||
|
||||
public ItemAttribute(UUID uuid, String internalName, Attribute attribute, AttributeOperation operation, double value, AttributeSlot slot) {
|
||||
this.uuid = uuid;
|
||||
|
@ -42,7 +42,7 @@ public class PlayerVehicleListener {
|
||||
public static void boatSteerListener(ClientSteerBoatPacket packet, Player player) {
|
||||
final Entity vehicle = player.getVehicle();
|
||||
|
||||
if (vehicle == null || !(vehicle instanceof EntityBoat))
|
||||
if (!(vehicle instanceof EntityBoat))
|
||||
return;
|
||||
|
||||
EntityBoat boat = (EntityBoat) vehicle;
|
||||
|
@ -17,8 +17,8 @@ import java.util.UUID;
|
||||
|
||||
public class PacketReader extends InputStream {
|
||||
|
||||
private ByteBuf buffer;
|
||||
private NBTReader nbtReader = new NBTReader(this, false);
|
||||
private final ByteBuf buffer;
|
||||
private final NBTReader nbtReader = new NBTReader(this, false);
|
||||
|
||||
public PacketReader(ByteBuf buffer) {
|
||||
this.buffer = buffer;
|
||||
|
@ -20,8 +20,8 @@ import java.util.function.Consumer;
|
||||
|
||||
public class PacketWriter extends OutputStream {
|
||||
|
||||
private ByteBuf buffer = Unpooled.buffer();
|
||||
private NBTWriter nbtWriter = new NBTWriter(this, false);
|
||||
private final ByteBuf buffer = Unpooled.buffer();
|
||||
private final NBTWriter nbtWriter = new NBTWriter(this, false);
|
||||
|
||||
public void writeBoolean(boolean b) {
|
||||
buffer.writeBoolean(b);
|
||||
|
@ -19,10 +19,10 @@ public class StorageFolder {
|
||||
|
||||
private static final DataManager DATA_MANAGER = MinecraftServer.getDataManager();
|
||||
|
||||
private StorageSystem storageSystem;
|
||||
private String folderPath;
|
||||
private final StorageSystem storageSystem;
|
||||
private final String folderPath;
|
||||
|
||||
private Map<String, SerializableData> cachedData;
|
||||
private final Map<String, SerializableData> cachedData;
|
||||
|
||||
protected StorageFolder(StorageSystem storageSystem, String folderPath, StorageOptions storageOptions) {
|
||||
this.storageSystem = storageSystem;
|
||||
@ -50,27 +50,26 @@ public class StorageFolder {
|
||||
}
|
||||
|
||||
public <T> void set(String key, T object, Class<T> type) {
|
||||
DataType<T> dataType = DATA_MANAGER.getDataType(type);
|
||||
final DataType<T> dataType = DATA_MANAGER.getDataType(type);
|
||||
Check.notNull(dataType, "You can only save registered DataType type!");
|
||||
|
||||
PacketWriter packetWriter = new PacketWriter();
|
||||
dataType.encode(packetWriter, object); // Encode
|
||||
byte[] encodedValue = packetWriter.toByteArray(); // Retrieve bytes
|
||||
final byte[] encodedValue = packetWriter.toByteArray(); // Retrieve bytes
|
||||
|
||||
set(key, encodedValue);
|
||||
}
|
||||
|
||||
public <T> T get(String key, Class<T> type) {
|
||||
DataType<T> dataType = DATA_MANAGER.getDataType(type);
|
||||
final DataType<T> dataType = DATA_MANAGER.getDataType(type);
|
||||
Check.notNull(dataType, "You can only save registered DataType type!");
|
||||
|
||||
byte[] data = get(key);
|
||||
final byte[] data = get(key);
|
||||
if (data == null)
|
||||
return null;
|
||||
|
||||
PacketReader packetReader = new PacketReader(data);
|
||||
T value = dataType.decode(packetReader);
|
||||
return value;
|
||||
return dataType.decode(packetReader);
|
||||
}
|
||||
|
||||
public <T> T getOrDefault(String key, Class<T> type, T defaultValue) {
|
||||
@ -95,7 +94,7 @@ public class StorageFolder {
|
||||
}
|
||||
|
||||
// Load it from the storage system
|
||||
byte[] bytes = get(key);
|
||||
final byte[] bytes = get(key);
|
||||
SerializableData data;
|
||||
|
||||
if (bytes != null) {
|
||||
@ -128,7 +127,7 @@ public class StorageFolder {
|
||||
}
|
||||
|
||||
// Load it from the storage system and cache it
|
||||
byte[] bytes = get(key);
|
||||
final byte[] bytes = get(key);
|
||||
SerializableData data;
|
||||
|
||||
if (bytes != null) {
|
||||
@ -151,7 +150,7 @@ public class StorageFolder {
|
||||
*/
|
||||
public void saveAndRemoveCachedData(String key) {
|
||||
synchronized (cachedData) {
|
||||
SerializableData serializableData = cachedData.get(key);
|
||||
final SerializableData serializableData = cachedData.get(key);
|
||||
if (serializableData == null)
|
||||
return;
|
||||
|
||||
@ -173,8 +172,8 @@ public class StorageFolder {
|
||||
try {
|
||||
synchronized (cachedData) {
|
||||
for (Map.Entry<String, SerializableData> entry : cachedData.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
SerializableData data = entry.getValue();
|
||||
final String key = entry.getKey();
|
||||
final SerializableData data = entry.getValue();
|
||||
|
||||
set(key, data.getSerializedData());
|
||||
}
|
||||
@ -192,7 +191,7 @@ public class StorageFolder {
|
||||
public void saveCachedData(String key) {
|
||||
try {
|
||||
synchronized (cachedData) {
|
||||
SerializableData data = cachedData.get(key);
|
||||
final SerializableData data = cachedData.get(key);
|
||||
set(key, data.getSerializedData());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
|
@ -30,9 +30,8 @@ public class StorageManager {
|
||||
*/
|
||||
public StorageFolder getFolder(String folderPath, StorageOptions storageOptions, StorageSystem storageSystem) {
|
||||
Check.notNull(storageOptions, "The storage option cannot be null");
|
||||
StorageFolder storageFolder =
|
||||
folderMap.computeIfAbsent(folderPath, s -> new StorageFolder(storageSystem, folderPath, storageOptions));
|
||||
return storageFolder;
|
||||
return folderMap.computeIfAbsent(folderPath,
|
||||
s -> new StorageFolder(storageSystem, folderPath, storageOptions));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -47,7 +46,7 @@ public class StorageManager {
|
||||
public StorageFolder getFolder(String folderPath, StorageOptions storageOptions) {
|
||||
Check.notNull(defaultStorageSystemSupplier,
|
||||
"You need to either define a default storage system or specify your storage system for this specific folder");
|
||||
StorageSystem storageSystem = defaultStorageSystemSupplier.get();
|
||||
final StorageSystem storageSystem = defaultStorageSystemSupplier.get();
|
||||
return getFolder(folderPath, storageOptions, storageSystem);
|
||||
}
|
||||
|
||||
|
@ -42,8 +42,7 @@ public class FileStorageSystem implements StorageSystem {
|
||||
@Override
|
||||
public byte[] get(String key) {
|
||||
try {
|
||||
byte[] result = this.rocksDB.get(getKey(key));
|
||||
return result;
|
||||
return rocksDB.get(getKey(key));
|
||||
} catch (RocksDBException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
|
@ -9,8 +9,8 @@ import net.minestom.server.utils.chunk.ChunkUtils;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* Separate chunks into group of linked chunks
|
||||
@ -105,16 +105,16 @@ public class PerGroupChunkProvider extends ThreadProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<Future<?>> update(long time) {
|
||||
public List<Future<?>> update(long time) {
|
||||
// Set of already-updated instances this tick
|
||||
final Set<Instance> updatedInstance = new HashSet<>();
|
||||
|
||||
ArrayList<Future<?>> futures = new ArrayList<>();
|
||||
List<Future<?>> futures = new ArrayList<>();
|
||||
|
||||
instanceInstanceMap.forEach((instance, instanceMap) -> {
|
||||
|
||||
// True if the instance ended its tick call
|
||||
AtomicBoolean instanceUpdated = new AtomicBoolean(false);
|
||||
// True if the instance ended its tick call¬
|
||||
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||
|
||||
// Update all the chunks + instances
|
||||
instanceMap.keySet().forEach(chunksIndexes -> {
|
||||
@ -124,12 +124,15 @@ public class PerGroupChunkProvider extends ThreadProvider {
|
||||
// Used to check if the instance has already been updated this tick
|
||||
if (shouldUpdateInstance) {
|
||||
updateInstance(instance, time);
|
||||
instanceUpdated.set(true);
|
||||
countDownLatch.countDown();
|
||||
}
|
||||
|
||||
// Wait for the instance to be updated
|
||||
// Needed because the instance tick is used to unload waiting chunks
|
||||
while (!instanceUpdated.get()) {
|
||||
try {
|
||||
countDownLatch.await();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// Tick all this chunk group
|
||||
|
@ -7,6 +7,7 @@ import net.minestom.server.utils.chunk.ChunkUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
@ -15,43 +16,43 @@ import java.util.concurrent.Future;
|
||||
*/
|
||||
public class PerInstanceThreadProvider extends ThreadProvider {
|
||||
|
||||
private Map<Instance, LongSet> instanceChunkMap = new HashMap<>();
|
||||
private Map<Instance, LongSet> instanceChunkMap = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void onChunkLoad(Instance instance, int chunkX, int chunkZ) {
|
||||
// Add the loaded chunk to the instance chunks list
|
||||
LongSet chunkCoordinates = getChunkCoordinates(instance);
|
||||
final long index = ChunkUtils.getChunkIndex(chunkX, chunkZ);
|
||||
chunkCoordinates.add(index);
|
||||
}
|
||||
@Override
|
||||
public void onChunkLoad(Instance instance, int chunkX, int chunkZ) {
|
||||
// Add the loaded chunk to the instance chunks list
|
||||
LongSet chunkCoordinates = getChunkCoordinates(instance);
|
||||
final long index = ChunkUtils.getChunkIndex(chunkX, chunkZ);
|
||||
chunkCoordinates.add(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkUnload(Instance instance, int chunkX, int chunkZ) {
|
||||
LongSet chunkCoordinates = getChunkCoordinates(instance);
|
||||
final long index = ChunkUtils.getChunkIndex(chunkX, chunkZ);
|
||||
// Remove the unloaded chunk from the instance list
|
||||
chunkCoordinates.remove(index);
|
||||
@Override
|
||||
public void onChunkUnload(Instance instance, int chunkX, int chunkZ) {
|
||||
LongSet chunkCoordinates = getChunkCoordinates(instance);
|
||||
final long index = ChunkUtils.getChunkIndex(chunkX, chunkZ);
|
||||
// Remove the unloaded chunk from the instance list
|
||||
chunkCoordinates.remove(index);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<Future<?>> update(long time) {
|
||||
ArrayList<Future<?>> futures = new ArrayList<>();
|
||||
@Override
|
||||
public List<Future<?>> update(long time) {
|
||||
List<Future<?>> futures = new ArrayList<>();
|
||||
|
||||
instanceChunkMap.forEach((instance, chunkIndexes) -> {
|
||||
instanceChunkMap.forEach((instance, chunkIndexes) -> {
|
||||
|
||||
futures.add(pool.submit(() -> {
|
||||
// Tick instance
|
||||
updateInstance(instance, time);
|
||||
// Tick chunks
|
||||
chunkIndexes.forEach((long chunkIndex) -> processChunkTick(instance, chunkIndex, time));
|
||||
}));
|
||||
});
|
||||
return futures;
|
||||
}
|
||||
futures.add(pool.submit(() -> {
|
||||
// Tick instance
|
||||
updateInstance(instance, time);
|
||||
// Tick chunks
|
||||
chunkIndexes.forEach((long chunkIndex) -> processChunkTick(instance, chunkIndex, time));
|
||||
}));
|
||||
});
|
||||
return futures;
|
||||
}
|
||||
|
||||
private LongSet getChunkCoordinates(Instance instance) {
|
||||
return instanceChunkMap.computeIfAbsent(instance, inst -> new LongArraySet());
|
||||
}
|
||||
private LongSet getChunkCoordinates(Instance instance) {
|
||||
return instanceChunkMap.computeIfAbsent(instance, inst -> new LongArraySet());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||
import net.minestom.server.utils.thread.MinestomThread;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Future;
|
||||
@ -55,9 +55,9 @@ public abstract class ThreadProvider {
|
||||
* Perform a server tick for all chunks based on their linked thread
|
||||
*
|
||||
* @param time the update time in milliseconds
|
||||
* @return
|
||||
* @return the futures to execute to complete the tick
|
||||
*/
|
||||
public abstract ArrayList<Future<?>> update(long time);
|
||||
public abstract List<Future<?>> update(long time);
|
||||
|
||||
/**
|
||||
* Get the current size of the thread pool
|
||||
|
@ -64,7 +64,7 @@ public final class ArrayUtils {
|
||||
public static int[] toArray(IntList list) {
|
||||
int[] array = new int[list.size()];
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
array[i] = list.get(i);
|
||||
array[i] = list.getInt(i);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
@ -64,11 +64,11 @@ public final class MathUtils {
|
||||
}
|
||||
|
||||
public static int setBetween(int number, int min, int max) {
|
||||
return number > max ? max : number < min ? min : number;
|
||||
return number > max ? max : Math.max(number, min);
|
||||
}
|
||||
|
||||
public static float setBetween(float number, float min, float max) {
|
||||
return number > max ? max : number < min ? min : number;
|
||||
return number > max ? max : Math.max(number, min);
|
||||
}
|
||||
|
||||
public static int clamp(int value, int min, int max) {
|
||||
|
@ -23,21 +23,21 @@ public class PrimitiveConversion {
|
||||
}
|
||||
|
||||
public static String getObjectClassString(String clazz) {
|
||||
if (clazz == "boolean")
|
||||
if (clazz.equals("boolean"))
|
||||
return "java.lang.Boolean";
|
||||
if (clazz == "byte")
|
||||
if (clazz.equals("byte"))
|
||||
return "java.lang.Byte";
|
||||
if (clazz == "char")
|
||||
if (clazz.equals("char"))
|
||||
return "java.lang.Character";
|
||||
if (clazz == "short")
|
||||
if (clazz.equals("short"))
|
||||
return "java.lang.Short";
|
||||
if (clazz == "int")
|
||||
if (clazz.equals("int"))
|
||||
return "java.lang.Integer";
|
||||
if (clazz == "long")
|
||||
if (clazz.equals("long"))
|
||||
return "java.lang.Long";
|
||||
if (clazz == "float")
|
||||
if (clazz.equals("float"))
|
||||
return "java.lang.Float";
|
||||
if (clazz == "double")
|
||||
if (clazz.equals("double"))
|
||||
return "java.lang.Double";
|
||||
return clazz;
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ public class WeightedRandom<E extends WeightedRandomItem> {
|
||||
public E get(Random rng) {
|
||||
final double p = rng.nextDouble() * totalWeight;
|
||||
for (int i = 0; i < entries.size(); i++) {
|
||||
final double weightSum = weightSums.get(i);
|
||||
final double weightSum = weightSums.getDouble(i);
|
||||
if (weightSum >= p) {
|
||||
return entries.get(i);
|
||||
}
|
||||
|
@ -85,8 +85,6 @@ public final class ChunkUtils {
|
||||
* @return the chunk Z based on the index
|
||||
*/
|
||||
public static int getChunkCoordZ(long index) {
|
||||
final int chunkX = (int) (index >> 32);
|
||||
final int chunkZ = (int) index;
|
||||
return (int) index;
|
||||
}
|
||||
|
||||
@ -117,8 +115,7 @@ public final class ChunkUtils {
|
||||
for (int z = startLoop; z < endLoop; z++) {
|
||||
final int chunkX = getChunkCoordinate((int) (position.getX() + Chunk.CHUNK_SIZE_X * x));
|
||||
final int chunkZ = getChunkCoordinate((int) (position.getZ() + Chunk.CHUNK_SIZE_Z * z));
|
||||
visibleChunks[counter] = getChunkIndex(chunkX, chunkZ);
|
||||
counter++;
|
||||
visibleChunks[counter++] = getChunkIndex(chunkX, chunkZ);
|
||||
}
|
||||
}
|
||||
return visibleChunks;
|
||||
@ -130,8 +127,7 @@ public final class ChunkUtils {
|
||||
* @param instance the instance of the chunks
|
||||
* @param chunkX the chunk X
|
||||
* @param chunkZ the chunk Z
|
||||
* @return an array containing all the loaded neighbours
|
||||
* can be deserialized using {@link #indexToChunkPosition(int)}
|
||||
* @return an array containing all the loaded neighbours chunk index
|
||||
*/
|
||||
public static long[] getNeighbours(Instance instance, int chunkX, int chunkZ) {
|
||||
LongList chunks = new LongArrayList();
|
||||
@ -185,36 +181,76 @@ public final class ChunkUtils {
|
||||
* @return the instance position of the block located in {@code index}
|
||||
*/
|
||||
public static BlockPosition getBlockPosition(int index, int chunkX, int chunkZ) {
|
||||
final int[] pos = indexToPosition(index, chunkX, chunkZ);
|
||||
return new BlockPosition(pos[0], pos[1], pos[2]);
|
||||
final int x = blockIndexToPositionX(index, chunkX);
|
||||
final int y = blockIndexToPositionY(index);
|
||||
final int z = blockIndexToPositionZ(index, chunkZ);
|
||||
return new BlockPosition(x, y, z);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param index an index computed from {@link #getBlockIndex(int, int, int)}
|
||||
* Convert a block chunk index to its instance position X
|
||||
*
|
||||
* @param index the block chunk index from {@link #getBlockIndex(int, int, int)}
|
||||
* @param chunkX the chunk X
|
||||
* @param chunkZ the chunk Z
|
||||
* @return the world position of the specified index with its chunks being {@code chunkX} and {@code chunk Z}
|
||||
* positions in the array are in the order X/Y/Z
|
||||
* @return the X coordinate of the block index
|
||||
*/
|
||||
public static int[] indexToPosition(int index, int chunkX, int chunkZ) {
|
||||
int z = (byte) (index >> 12 & 0xF);
|
||||
final int y = (index >>> 4 & 0xFF);
|
||||
// index >> 0 = index
|
||||
public static int blockIndexToPositionX(int index, int chunkX) {
|
||||
int x = (byte) (index & 0xF);
|
||||
|
||||
x += 16 * chunkX;
|
||||
z += 16 * chunkZ;
|
||||
|
||||
return new int[]{x, y, z};
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param index an index computed from {@link #getBlockIndex(int, int, int)}
|
||||
* @return the chunk position (O-15) of the specified index,
|
||||
* positions in the array are in the order X/Y/Z
|
||||
* Convert a block chunk index to its instance position Y
|
||||
*
|
||||
* @param index the block chunk index from {@link #getBlockIndex(int, int, int)}
|
||||
* @return the Y coordinate of the block index
|
||||
*/
|
||||
public static int[] indexToChunkPosition(int index) {
|
||||
return indexToPosition(index, 0, 0);
|
||||
public static int blockIndexToPositionY(int index) {
|
||||
return (index >>> 4 & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a block chunk index to its instance position Z
|
||||
*
|
||||
* @param index the block chunk index from {@link #getBlockIndex(int, int, int)}
|
||||
* @param chunkZ the chunk Z
|
||||
* @return the Z coordinate of the block index
|
||||
*/
|
||||
public static int blockIndexToPositionZ(int index, int chunkZ) {
|
||||
int z = (byte) (index >> 12 & 0xF);
|
||||
z += 16 * chunkZ;
|
||||
return z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a block index to a chunk position X
|
||||
*
|
||||
* @param index an index computed from {@link #getBlockIndex(int, int, int)}
|
||||
* @return the chunk position X (O-15) of the specified index
|
||||
*/
|
||||
public static int blockIndexToChunkPositionX(int index) {
|
||||
return blockIndexToPositionX(index, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a block index to a chunk position Y
|
||||
*
|
||||
* @param index an index computed from {@link #getBlockIndex(int, int, int)}
|
||||
* @return the chunk position Y (O-255) of the specified index
|
||||
*/
|
||||
public static int blockIndexToChunkPositionY(int index) {
|
||||
return blockIndexToPositionY(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a block index to a chunk position Z
|
||||
*
|
||||
* @param index an index computed from {@link #getBlockIndex(int, int, int)}
|
||||
* @return the chunk position Z (O-15) of the specified index
|
||||
*/
|
||||
public static int blockIndexToChunkPositionZ(int index) {
|
||||
return blockIndexToPositionZ(index, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user