mirror of
https://github.com/Minestom/Minestom.git
synced 2024-11-08 03:40:27 +01:00
Merge branches '1.16.2' and 'master' of https://github.com/Minestom/Minestom
Conflicts: src/main/java/net/minestom/server/UpdateManager.java src/main/java/net/minestom/server/thread/PerGroupChunkProvider.java src/main/java/net/minestom/server/thread/PerInstanceThreadProvider.java
This commit is contained in:
commit
1b7641c0e1
@ -61,8 +61,13 @@ public final class UpdateManager {
|
|||||||
//Tick Callbacks
|
//Tick Callbacks
|
||||||
tickStartCallbacks.forEach(Runnable::run);
|
tickStartCallbacks.forEach(Runnable::run);
|
||||||
|
|
||||||
|
ArrayList<Future<?>> futures;
|
||||||
|
|
||||||
// Server tick (instance/chunk/entity)
|
// Server tick (instance/chunk/entity)
|
||||||
ArrayList<Future<?>> futures = threadProvider.update(time);
|
// Synchronize with the update manager instance, like the signal for chunk load/unload
|
||||||
|
synchronized (this) {
|
||||||
|
futures = threadProvider.update(time);
|
||||||
|
}
|
||||||
|
|
||||||
// Waiting players update (newly connected waiting to get into the server)
|
// Waiting players update (newly connected waiting to get into the server)
|
||||||
entityManager.updateWaitingPlayers();
|
entityManager.updateWaitingPlayers();
|
||||||
|
@ -16,7 +16,7 @@ public abstract class DataType<T> {
|
|||||||
/**
|
/**
|
||||||
* Decode the data type
|
* Decode the data type
|
||||||
*
|
*
|
||||||
* @param packetReader the data readerr
|
* @param packetReader the data reader
|
||||||
* @return the decoded value
|
* @return the decoded value
|
||||||
*/
|
*/
|
||||||
public abstract T decode(PacketReader packetReader);
|
public abstract T decode(PacketReader packetReader);
|
||||||
|
@ -5,18 +5,19 @@ import net.minestom.server.inventory.Inventory;
|
|||||||
import net.minestom.server.inventory.InventoryType;
|
import net.minestom.server.inventory.InventoryType;
|
||||||
import net.minestom.server.network.packet.PacketReader;
|
import net.minestom.server.network.packet.PacketReader;
|
||||||
import net.minestom.server.network.packet.PacketWriter;
|
import net.minestom.server.network.packet.PacketWriter;
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTException;
|
|
||||||
|
|
||||||
public class InventoryData extends DataType<Inventory> {
|
public class InventoryData extends DataType<Inventory> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void encode(PacketWriter packetWriter, Inventory value) {
|
public void encode(PacketWriter packetWriter, Inventory value) {
|
||||||
InventoryType inventoryType = value.getInventoryType();
|
final InventoryType inventoryType = value.getInventoryType();
|
||||||
int size = inventoryType.getAdditionalSlot();
|
final int size = inventoryType.getAdditionalSlot();
|
||||||
|
|
||||||
|
// Inventory title & type
|
||||||
packetWriter.writeSizedString(value.getTitle());
|
packetWriter.writeSizedString(value.getTitle());
|
||||||
packetWriter.writeSizedString(inventoryType.name());
|
packetWriter.writeSizedString(inventoryType.name());
|
||||||
|
|
||||||
|
// Write all item stacks
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
packetWriter.writeItemStack(value.getItemStack(i));
|
packetWriter.writeItemStack(value.getItemStack(i));
|
||||||
}
|
}
|
||||||
@ -24,12 +25,13 @@ public class InventoryData extends DataType<Inventory> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Inventory decode(PacketReader packetReader) {
|
public Inventory decode(PacketReader packetReader) {
|
||||||
String title = packetReader.readSizedString();
|
final String title = packetReader.readSizedString();
|
||||||
InventoryType inventoryType = InventoryType.valueOf(packetReader.readSizedString());
|
final InventoryType inventoryType = InventoryType.valueOf(packetReader.readSizedString());
|
||||||
int size = inventoryType.getAdditionalSlot();
|
final int size = inventoryType.getAdditionalSlot();
|
||||||
|
|
||||||
Inventory inventory = new Inventory(inventoryType, title);
|
Inventory inventory = new Inventory(inventoryType, title);
|
||||||
|
|
||||||
|
// Read all item stacks
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
inventory.setItemStack(i, packetReader.readSlot());
|
inventory.setItemStack(i, packetReader.readSlot());
|
||||||
}
|
}
|
||||||
|
@ -85,31 +85,27 @@ public class ItemEntity extends ObjectEntity {
|
|||||||
if (getDistance(itemEntity) > mergeRange)
|
if (getDistance(itemEntity) > mergeRange)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Use the class as a monitor to prevent deadlock
|
final ItemStack itemStackEntity = itemEntity.getItemStack();
|
||||||
// Shouldn't happen too often to be an issue
|
|
||||||
synchronized (ItemEntity.class) {
|
|
||||||
final ItemStack itemStackEntity = itemEntity.getItemStack();
|
|
||||||
|
|
||||||
final StackingRule stackingRule = itemStack.getStackingRule();
|
final StackingRule stackingRule = itemStack.getStackingRule();
|
||||||
final boolean canStack = stackingRule.canBeStacked(itemStack, itemStackEntity);
|
final boolean canStack = stackingRule.canBeStacked(itemStack, itemStackEntity);
|
||||||
|
|
||||||
if (!canStack)
|
if (!canStack)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
final int totalAmount = stackingRule.getAmount(itemStack) + stackingRule.getAmount(itemStackEntity);
|
final int totalAmount = stackingRule.getAmount(itemStack) + stackingRule.getAmount(itemStackEntity);
|
||||||
final boolean canApply = stackingRule.canApply(itemStack, totalAmount);
|
final boolean canApply = stackingRule.canApply(itemStack, totalAmount);
|
||||||
|
|
||||||
if (!canApply)
|
if (!canApply)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
final ItemStack result = stackingRule.apply(itemStack.clone(), totalAmount);
|
final ItemStack result = stackingRule.apply(itemStack.clone(), totalAmount);
|
||||||
|
|
||||||
EntityItemMergeEvent entityItemMergeEvent = new EntityItemMergeEvent(this, itemEntity, result);
|
EntityItemMergeEvent entityItemMergeEvent = new EntityItemMergeEvent(this, itemEntity, result);
|
||||||
callCancellableEvent(EntityItemMergeEvent.class, entityItemMergeEvent, () -> {
|
callCancellableEvent(EntityItemMergeEvent.class, entityItemMergeEvent, () -> {
|
||||||
setItemStack(entityItemMergeEvent.getResult());
|
setItemStack(entityItemMergeEvent.getResult());
|
||||||
itemEntity.remove();
|
itemEntity.remove();
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,20 +100,18 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
|
|||||||
|
|
||||||
final BoundingBox itemBoundingBox = itemEntity.getBoundingBox();
|
final BoundingBox itemBoundingBox = itemEntity.getBoundingBox();
|
||||||
if (expandedBoundingBox.intersect(itemBoundingBox)) {
|
if (expandedBoundingBox.intersect(itemBoundingBox)) {
|
||||||
synchronized (itemEntity) {
|
if (itemEntity.shouldRemove() || itemEntity.isRemoveScheduled())
|
||||||
if (itemEntity.shouldRemove() || itemEntity.isRemoveScheduled())
|
continue;
|
||||||
continue;
|
final ItemStack item = itemEntity.getItemStack();
|
||||||
final ItemStack item = itemEntity.getItemStack();
|
PickupItemEvent pickupItemEvent = new PickupItemEvent(item);
|
||||||
PickupItemEvent pickupItemEvent = new PickupItemEvent(item);
|
callCancellableEvent(PickupItemEvent.class, pickupItemEvent, () -> {
|
||||||
callCancellableEvent(PickupItemEvent.class, pickupItemEvent, () -> {
|
CollectItemPacket collectItemPacket = new CollectItemPacket();
|
||||||
CollectItemPacket collectItemPacket = new CollectItemPacket();
|
collectItemPacket.collectedEntityId = itemEntity.getEntityId();
|
||||||
collectItemPacket.collectedEntityId = itemEntity.getEntityId();
|
collectItemPacket.collectorEntityId = getEntityId();
|
||||||
collectItemPacket.collectorEntityId = getEntityId();
|
collectItemPacket.pickupItemCount = item.getAmount();
|
||||||
collectItemPacket.pickupItemCount = item.getAmount();
|
sendPacketToViewersAndSelf(collectItemPacket);
|
||||||
sendPacketToViewersAndSelf(collectItemPacket);
|
entity.remove();
|
||||||
entity.remove();
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -227,7 +227,7 @@ public class Player extends LivingEntity implements CommandSender {
|
|||||||
recipesIdentifier.add(recipe.getRecipeId());
|
recipesIdentifier.add(recipe.getRecipeId());
|
||||||
}
|
}
|
||||||
if (!recipesIdentifier.isEmpty()) {
|
if (!recipesIdentifier.isEmpty()) {
|
||||||
String[] identifiers = recipesIdentifier.toArray(new String[0]);
|
final String[] identifiers = recipesIdentifier.toArray(new String[0]);
|
||||||
UnlockRecipesPacket unlockRecipesPacket = new UnlockRecipesPacket();
|
UnlockRecipesPacket unlockRecipesPacket = new UnlockRecipesPacket();
|
||||||
unlockRecipesPacket.mode = 0;
|
unlockRecipesPacket.mode = 0;
|
||||||
unlockRecipesPacket.recipesId = identifiers;
|
unlockRecipesPacket.recipesId = identifiers;
|
||||||
@ -321,15 +321,13 @@ public class Player extends LivingEntity implements CommandSender {
|
|||||||
final ExperienceOrb experienceOrb = (ExperienceOrb) entity;
|
final ExperienceOrb experienceOrb = (ExperienceOrb) entity;
|
||||||
final BoundingBox itemBoundingBox = experienceOrb.getBoundingBox();
|
final BoundingBox itemBoundingBox = experienceOrb.getBoundingBox();
|
||||||
if (expandedBoundingBox.intersect(itemBoundingBox)) {
|
if (expandedBoundingBox.intersect(itemBoundingBox)) {
|
||||||
synchronized (experienceOrb) {
|
if (experienceOrb.shouldRemove() || experienceOrb.isRemoveScheduled())
|
||||||
if (experienceOrb.shouldRemove() || experienceOrb.isRemoveScheduled())
|
continue;
|
||||||
continue;
|
PickupExperienceEvent pickupExperienceEvent = new PickupExperienceEvent(experienceOrb);
|
||||||
PickupExperienceEvent pickupExperienceEvent = new PickupExperienceEvent(experienceOrb);
|
callCancellableEvent(PickupExperienceEvent.class, pickupExperienceEvent, () -> {
|
||||||
callCancellableEvent(PickupExperienceEvent.class, pickupExperienceEvent, () -> {
|
short experienceCount = pickupExperienceEvent.getExperienceCount(); // TODO give to player
|
||||||
short experienceCount = pickupExperienceEvent.getExperienceCount(); // TODO give to player
|
entity.remove();
|
||||||
entity.remove();
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,8 +128,8 @@ public class ItemStack implements DataContainer {
|
|||||||
* @param itemStack The ItemStack to compare to
|
* @param itemStack The ItemStack to compare to
|
||||||
* @return true if both items are similar
|
* @return true if both items are similar
|
||||||
*/
|
*/
|
||||||
public synchronized boolean isSimilar(ItemStack itemStack) {
|
public boolean isSimilar(ItemStack itemStack) {
|
||||||
synchronized (itemStack) {
|
synchronized (ItemStack.class) {
|
||||||
final ColoredText itemDisplayName = itemStack.getDisplayName();
|
final ColoredText itemDisplayName = itemStack.getDisplayName();
|
||||||
final boolean displayNameCheck = (displayName == null && itemDisplayName == null) ||
|
final boolean displayNameCheck = (displayName == null && itemDisplayName == null) ||
|
||||||
(displayName != null && itemDisplayName != null && displayName.equals(itemDisplayName));
|
(displayName != null && itemDisplayName != null && displayName.equals(itemDisplayName));
|
||||||
|
@ -99,7 +99,7 @@ public class PlayerDiggingListener {
|
|||||||
if (itemUpdateStateEvent == null) {
|
if (itemUpdateStateEvent == null) {
|
||||||
player.refreshActiveHand(true, false, false);
|
player.refreshActiveHand(true, false, false);
|
||||||
} else {
|
} else {
|
||||||
boolean isOffHand = itemUpdateStateEvent.getHand() == Player.Hand.OFF;
|
final boolean isOffHand = itemUpdateStateEvent.getHand() == Player.Hand.OFF;
|
||||||
player.refreshActiveHand(itemUpdateStateEvent.hasHandAnimation(), isOffHand, false);
|
player.refreshActiveHand(itemUpdateStateEvent.hasHandAnimation(), isOffHand, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ public class TagsPacket implements ServerPacket {
|
|||||||
// name
|
// name
|
||||||
writer.writeSizedString(tag.getName().toString());
|
writer.writeSizedString(tag.getName().toString());
|
||||||
|
|
||||||
Set<NamespaceID> values = tag.getValues();
|
final Set<NamespaceID> values = tag.getValues();
|
||||||
// count
|
// count
|
||||||
writer.writeVarInt(values.size());
|
writer.writeVarInt(values.size());
|
||||||
// entries
|
// entries
|
||||||
|
@ -49,9 +49,9 @@ public abstract class PlayerConnection {
|
|||||||
tickCounter++;
|
tickCounter++;
|
||||||
if (tickCounter % 20 == 0 && tickCounter > 0) {
|
if (tickCounter % 20 == 0 && tickCounter > 0) {
|
||||||
tickCounter = 0;
|
tickCounter = 0;
|
||||||
int i = packetCounter.get();
|
final int count = packetCounter.get();
|
||||||
packetCounter.set(0);
|
packetCounter.set(0);
|
||||||
if (i > MinecraftServer.getRateLimit()) {
|
if (count > MinecraftServer.getRateLimit()) {
|
||||||
if (connectionState == ConnectionState.LOGIN) {
|
if (connectionState == ConnectionState.LOGIN) {
|
||||||
sendPacket(new LoginDisconnect("Too Many Packets"));
|
sendPacket(new LoginDisconnect("Too Many Packets"));
|
||||||
} else {
|
} else {
|
||||||
|
@ -4,7 +4,6 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
|||||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||||
import it.unimi.dsi.fastutil.longs.LongArraySet;
|
import it.unimi.dsi.fastutil.longs.LongArraySet;
|
||||||
import it.unimi.dsi.fastutil.longs.LongSet;
|
import it.unimi.dsi.fastutil.longs.LongSet;
|
||||||
import net.minestom.server.instance.Chunk;
|
|
||||||
import net.minestom.server.instance.Instance;
|
import net.minestom.server.instance.Instance;
|
||||||
import net.minestom.server.utils.chunk.ChunkUtils;
|
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||||
|
|
||||||
@ -23,12 +22,12 @@ public class PerGroupChunkProvider extends ThreadProvider {
|
|||||||
/**
|
/**
|
||||||
* Chunk -> its chunk group
|
* Chunk -> its chunk group
|
||||||
*/
|
*/
|
||||||
private Map<Instance, Long2ObjectMap<LongSet>> instanceChunksGroupMap = new ConcurrentHashMap<>();
|
private final Map<Instance, Long2ObjectMap<LongSet>> instanceChunksGroupMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to know to which instance is linked a Set of chunks
|
* Used to know to which instance is linked a Set of chunks
|
||||||
*/
|
*/
|
||||||
private Map<Instance, Map<LongSet, Instance>> instanceInstanceMap = new ConcurrentHashMap<>();
|
private final Map<Instance, Map<LongSet, Instance>> instanceInstanceMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onChunkLoad(Instance instance, int chunkX, int chunkZ) {
|
public void onChunkLoad(Instance instance, int chunkX, int chunkZ) {
|
||||||
@ -62,8 +61,11 @@ public class PerGroupChunkProvider extends ThreadProvider {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The size of the final list, used as the initial capacity
|
||||||
|
final int size = neighboursGroups.stream().mapToInt(value -> value.size()).sum() + 1;
|
||||||
|
|
||||||
// Represent the merged group of all the neighbours
|
// Represent the merged group of all the neighbours
|
||||||
LongSet finalGroup = new LongArraySet();
|
LongSet finalGroup = new LongArraySet(size);
|
||||||
|
|
||||||
// Add the newly loaded chunk to the group
|
// Add the newly loaded chunk to the group
|
||||||
final long chunkIndex = ChunkUtils.getChunkIndex(chunkX, chunkZ);
|
final long chunkIndex = ChunkUtils.getChunkIndex(chunkX, chunkZ);
|
||||||
@ -115,8 +117,7 @@ public class PerGroupChunkProvider extends ThreadProvider {
|
|||||||
AtomicBoolean instanceUpdated = new AtomicBoolean(false);
|
AtomicBoolean instanceUpdated = new AtomicBoolean(false);
|
||||||
|
|
||||||
// Update all the chunks + instances
|
// Update all the chunks + instances
|
||||||
for (Map.Entry<LongSet, Instance> ent : instanceMap.entrySet()) {
|
instanceMap.keySet().forEach(chunksIndexes -> {
|
||||||
final LongSet chunksIndexes = ent.getKey();
|
|
||||||
|
|
||||||
final boolean shouldUpdateInstance = updatedInstance.add(instance);
|
final boolean shouldUpdateInstance = updatedInstance.add(instance);
|
||||||
futures.add(pool.submit(() -> {
|
futures.add(pool.submit(() -> {
|
||||||
@ -131,21 +132,11 @@ public class PerGroupChunkProvider extends ThreadProvider {
|
|||||||
while (!instanceUpdated.get()) {
|
while (!instanceUpdated.get()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (long chunkIndex : chunksIndexes) {
|
// Tick all this chunk group
|
||||||
final int[] chunkCoordinates = ChunkUtils.getChunkCoord(chunkIndex);
|
chunksIndexes.forEach((long chunkIndex) -> processChunkTick(instance, chunkIndex, time));
|
||||||
final Chunk chunk = instance.getChunk(chunkCoordinates[0], chunkCoordinates[1]);
|
});
|
||||||
if (!ChunkUtils.isLoaded(chunk)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
updateChunk(instance, chunk, time);
|
|
||||||
|
|
||||||
updateEntities(instance, chunk, time);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
});
|
||||||
});
|
});
|
||||||
return futures;
|
return futures;
|
||||||
}
|
}
|
||||||
@ -155,7 +146,7 @@ public class PerGroupChunkProvider extends ThreadProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Map<LongSet, Instance> getInstanceMap(Instance instance) {
|
private Map<LongSet, Instance> getInstanceMap(Instance instance) {
|
||||||
return instanceInstanceMap.computeIfAbsent(instance, inst -> new ConcurrentHashMap<>());
|
return instanceInstanceMap.computeIfAbsent(instance, inst -> new HashMap<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package net.minestom.server.thread;
|
|||||||
|
|
||||||
import it.unimi.dsi.fastutil.longs.LongArraySet;
|
import it.unimi.dsi.fastutil.longs.LongArraySet;
|
||||||
import it.unimi.dsi.fastutil.longs.LongSet;
|
import it.unimi.dsi.fastutil.longs.LongSet;
|
||||||
import net.minestom.server.instance.Chunk;
|
|
||||||
import net.minestom.server.instance.Instance;
|
import net.minestom.server.instance.Instance;
|
||||||
import net.minestom.server.utils.chunk.ChunkUtils;
|
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||||
|
|
||||||
@ -16,54 +15,43 @@ import java.util.concurrent.Future;
|
|||||||
*/
|
*/
|
||||||
public class PerInstanceThreadProvider extends ThreadProvider {
|
public class PerInstanceThreadProvider extends ThreadProvider {
|
||||||
|
|
||||||
private Map<Instance, LongSet> instanceChunkMap = new HashMap<>();
|
private Map<Instance, LongSet> instanceChunkMap = new HashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onChunkLoad(Instance instance, int chunkX, int chunkZ) {
|
public void onChunkLoad(Instance instance, int chunkX, int chunkZ) {
|
||||||
// Add the loaded chunk to the instance chunks list
|
// Add the loaded chunk to the instance chunks list
|
||||||
LongSet chunkCoordinates = getChunkCoordinates(instance);
|
LongSet chunkCoordinates = getChunkCoordinates(instance);
|
||||||
final long index = ChunkUtils.getChunkIndex(chunkX, chunkZ);
|
final long index = ChunkUtils.getChunkIndex(chunkX, chunkZ);
|
||||||
chunkCoordinates.add(index);
|
chunkCoordinates.add(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onChunkUnload(Instance instance, int chunkX, int chunkZ) {
|
public void onChunkUnload(Instance instance, int chunkX, int chunkZ) {
|
||||||
LongSet chunkCoordinates = getChunkCoordinates(instance);
|
LongSet chunkCoordinates = getChunkCoordinates(instance);
|
||||||
final long index = ChunkUtils.getChunkIndex(chunkX, chunkZ);
|
final long index = ChunkUtils.getChunkIndex(chunkX, chunkZ);
|
||||||
// Remove the unloaded chunk from the instance list
|
// Remove the unloaded chunk from the instance list
|
||||||
chunkCoordinates.remove(index);
|
chunkCoordinates.remove(index);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ArrayList<Future<?>> update(long time) {
|
public ArrayList<Future<?>> update(long time) {
|
||||||
ArrayList<Future<?>> futures = new ArrayList<>();
|
ArrayList<Future<?>> futures = new ArrayList<>();
|
||||||
|
|
||||||
for (Map.Entry<Instance, LongSet> entry : instanceChunkMap.entrySet()) {
|
instanceChunkMap.forEach((instance, chunkIndexes) -> {
|
||||||
final Instance instance = entry.getKey();
|
|
||||||
final LongSet chunkIndexes = entry.getValue();
|
|
||||||
|
|
||||||
futures.add(pool.submit(() -> {
|
futures.add(pool.submit(() -> {
|
||||||
updateInstance(instance, time);
|
// Tick instance
|
||||||
|
updateInstance(instance, time);
|
||||||
|
// Tick chunks
|
||||||
|
chunkIndexes.forEach((long chunkIndex) -> processChunkTick(instance, chunkIndex, time));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return futures;
|
||||||
|
}
|
||||||
|
|
||||||
for (long chunkIndex : chunkIndexes) {
|
private LongSet getChunkCoordinates(Instance instance) {
|
||||||
final int[] chunkCoordinates = ChunkUtils.getChunkCoord(chunkIndex);
|
return instanceChunkMap.computeIfAbsent(instance, inst -> new LongArraySet());
|
||||||
final Chunk chunk = instance.getChunk(chunkCoordinates[0], chunkCoordinates[1]);
|
}
|
||||||
if (!ChunkUtils.isLoaded(chunk))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
updateChunk(instance, chunk, time);
|
|
||||||
|
|
||||||
updateEntities(instance, chunk, time);
|
|
||||||
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
return futures;
|
|
||||||
}
|
|
||||||
|
|
||||||
private LongSet getChunkCoordinates(Instance instance) {
|
|
||||||
return instanceChunkMap.computeIfAbsent(instance, inst -> new LongArraySet());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import net.minestom.server.MinecraftServer;
|
|||||||
import net.minestom.server.entity.*;
|
import net.minestom.server.entity.*;
|
||||||
import net.minestom.server.instance.Chunk;
|
import net.minestom.server.instance.Chunk;
|
||||||
import net.minestom.server.instance.Instance;
|
import net.minestom.server.instance.Instance;
|
||||||
|
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||||
import net.minestom.server.utils.thread.MinestomThread;
|
import net.minestom.server.utils.thread.MinestomThread;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -85,6 +86,24 @@ public abstract class ThreadProvider {
|
|||||||
* INSTANCE UPDATE
|
* INSTANCE UPDATE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process a whole tick for a chunk
|
||||||
|
*
|
||||||
|
* @param instance the instance of the chunk
|
||||||
|
* @param chunkIndex the index of the chunk {@link ChunkUtils#getChunkIndex(int, int)}
|
||||||
|
* @param time the time of the update in milliseconds
|
||||||
|
*/
|
||||||
|
protected void processChunkTick(Instance instance, long chunkIndex, long time) {
|
||||||
|
final int[] chunkCoordinates = ChunkUtils.getChunkCoord(chunkIndex);
|
||||||
|
final Chunk chunk = instance.getChunk(chunkCoordinates[0], chunkCoordinates[1]);
|
||||||
|
if (!ChunkUtils.isLoaded(chunk))
|
||||||
|
return;
|
||||||
|
|
||||||
|
updateChunk(instance, chunk, time);
|
||||||
|
|
||||||
|
updateEntities(instance, chunk, time);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute an instance tick
|
* Execute an instance tick
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user