mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-16 05:02:19 +01:00
If the garbage collector is happy, everyone is - TheMode
This commit is contained in:
parent
47a18fc305
commit
2285c9622a
@ -597,10 +597,9 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Each entity has an unique id (server-wide) which will change after a restart.
|
* Each entity has an unique id (server-wide) which will change after a restart.
|
||||||
* <p>
|
|
||||||
* All entities can be retrieved by calling {@link Entity#getEntity(int)}.
|
|
||||||
*
|
*
|
||||||
* @return the unique entity id
|
* @return the unique entity id
|
||||||
|
* @see Entity#getEntity(int) to retrive an entity based on its id
|
||||||
*/
|
*/
|
||||||
public int getEntityId() {
|
public int getEntityId() {
|
||||||
return id;
|
return id;
|
||||||
|
@ -1,11 +1,18 @@
|
|||||||
package net.minestom.server.instance.batch;
|
package net.minestom.server.instance.batch;
|
||||||
|
|
||||||
import kotlin.collections.ArrayDeque;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
|
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
||||||
|
import it.unimi.dsi.fastutil.longs.LongList;
|
||||||
import net.minestom.server.data.Data;
|
import net.minestom.server.data.Data;
|
||||||
import net.minestom.server.instance.*;
|
import net.minestom.server.instance.*;
|
||||||
import net.minestom.server.instance.block.CustomBlock;
|
import net.minestom.server.instance.block.CustomBlock;
|
||||||
import net.minestom.server.utils.block.CustomBlockUtils;
|
import net.minestom.server.utils.block.CustomBlockUtils;
|
||||||
|
import net.minestom.server.utils.callback.OptionalCallback;
|
||||||
import net.minestom.server.utils.chunk.ChunkCallback;
|
import net.minestom.server.utils.chunk.ChunkCallback;
|
||||||
|
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||||
|
import net.minestom.server.utils.validate.Check;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -21,48 +28,68 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class ChunkBatch implements InstanceBatch {
|
public class ChunkBatch implements InstanceBatch {
|
||||||
|
|
||||||
private static final int INITIAL_SIZE = (Chunk.CHUNK_SIZE_X * Chunk.CHUNK_SIZE_Y * Chunk.CHUNK_SIZE_Z) / 2;
|
|
||||||
|
|
||||||
private final InstanceContainer instance;
|
private final InstanceContainer instance;
|
||||||
private final Chunk chunk;
|
private final Chunk chunk;
|
||||||
|
|
||||||
// Need to be synchronized manually
|
// Need to be synchronized manually
|
||||||
private final ArrayDeque<BlockData> dataList = new ArrayDeque<>(INITIAL_SIZE);
|
// Format: blockIndex/blockStateId/customBlockId (32/16/16 bits)
|
||||||
|
private final LongList blocks = new LongArrayList();
|
||||||
|
|
||||||
public ChunkBatch(InstanceContainer instance, Chunk chunk) {
|
// Need to be synchronized manually
|
||||||
|
// block index - data
|
||||||
|
private final Int2ObjectMap<Data> blockDataMap = new Int2ObjectOpenHashMap<>();
|
||||||
|
|
||||||
|
public ChunkBatch(@NotNull InstanceContainer instance, @NotNull Chunk chunk) {
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
this.chunk = chunk;
|
this.chunk = chunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setBlockStateId(int x, int y, int z, short blockStateId, Data data) {
|
public void setBlockStateId(int x, int y, int z, short blockStateId, @Nullable Data data) {
|
||||||
addBlockData((byte) x, y, (byte) z, blockStateId, (short) 0, data);
|
addBlockData((byte) x, y, (byte) z, blockStateId, (short) 0, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setCustomBlock(int x, int y, int z, short customBlockId, Data data) {
|
public void setCustomBlock(int x, int y, int z, short customBlockId, @Nullable Data data) {
|
||||||
final CustomBlock customBlock = BLOCK_MANAGER.getCustomBlock(customBlockId);
|
final CustomBlock customBlock = BLOCK_MANAGER.getCustomBlock(customBlockId);
|
||||||
|
Check.notNull(customBlock, "The custom block with the id " + customBlockId + " does not exist!");
|
||||||
addBlockData((byte) x, y, (byte) z, customBlock.getDefaultBlockStateId(), customBlockId, data);
|
addBlockData((byte) x, y, (byte) z, customBlock.getDefaultBlockStateId(), customBlockId, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSeparateBlocks(int x, int y, int z, short blockStateId, short customBlockId, Data data) {
|
public void setSeparateBlocks(int x, int y, int z, short blockStateId, short customBlockId, @Nullable Data data) {
|
||||||
addBlockData((byte) x, y, (byte) z, blockStateId, customBlockId, data);
|
addBlockData((byte) x, y, (byte) z, blockStateId, customBlockId, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addBlockData(byte x, int y, byte z, short blockStateId, short customBlockId, Data data) {
|
private void addBlockData(byte x, int y, byte z, short blockStateId, short customBlockId, @Nullable Data data) {
|
||||||
// TODO store a single long with bitwise operators (xyz;boolean,short,short,boolean) with the data in a map
|
final int index = ChunkUtils.getBlockIndex(x, y, z);
|
||||||
final BlockData blockData = new BlockData(x, y, z, blockStateId, customBlockId, data);
|
|
||||||
synchronized (dataList) {
|
if (data != null) {
|
||||||
this.dataList.add(blockData);
|
synchronized (blockDataMap) {
|
||||||
|
this.blockDataMap.put(index, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void flushChunkGenerator(ChunkGenerator chunkGenerator, @Nullable ChunkCallback callback) {
|
long value = index;
|
||||||
BLOCK_BATCH_POOL.execute(() -> {
|
value = (value << 16) | blockStateId;
|
||||||
|
value = (value << 16) | customBlockId;
|
||||||
|
|
||||||
|
synchronized (blocks) {
|
||||||
|
this.blocks.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void flushChunkGenerator(@NotNull ChunkGenerator chunkGenerator, @Nullable ChunkCallback callback) {
|
||||||
final List<ChunkPopulator> populators = chunkGenerator.getPopulators();
|
final List<ChunkPopulator> populators = chunkGenerator.getPopulators();
|
||||||
final boolean hasPopulator = populators != null && !populators.isEmpty();
|
final boolean hasPopulator = populators != null && !populators.isEmpty();
|
||||||
|
|
||||||
|
// Check if there is anything to process
|
||||||
|
if (blocks.isEmpty() && !hasPopulator) {
|
||||||
|
OptionalCallback.execute(callback, chunk);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BLOCK_BATCH_POOL.execute(() -> {
|
||||||
chunkGenerator.generateChunkData(this, chunk.getChunkX(), chunk.getChunkZ());
|
chunkGenerator.generateChunkData(this, chunk.getChunkX(), chunk.getChunkZ());
|
||||||
singleThreadFlush(hasPopulator ? null : callback, true);
|
singleThreadFlush(hasPopulator ? null : callback, true);
|
||||||
|
|
||||||
@ -104,8 +131,8 @@ public class ChunkBatch implements InstanceBatch {
|
|||||||
* Resets the chunk batch by removing all the entries.
|
* Resets the chunk batch by removing all the entries.
|
||||||
*/
|
*/
|
||||||
public void clearData() {
|
public void clearData() {
|
||||||
synchronized (dataList) {
|
synchronized (blocks) {
|
||||||
this.dataList.clear();
|
this.blocks.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,13 +143,18 @@ public class ChunkBatch implements InstanceBatch {
|
|||||||
* @param safeCallback true to run the callback in the instance update thread, otherwise run in the current one
|
* @param safeCallback true to run the callback in the instance update thread, otherwise run in the current one
|
||||||
*/
|
*/
|
||||||
private void singleThreadFlush(@Nullable ChunkCallback callback, boolean safeCallback) {
|
private void singleThreadFlush(@Nullable ChunkCallback callback, boolean safeCallback) {
|
||||||
|
if (blocks.isEmpty()) {
|
||||||
|
OptionalCallback.execute(callback, chunk);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
synchronized (chunk) {
|
synchronized (chunk) {
|
||||||
if (!chunk.isLoaded())
|
if (!chunk.isLoaded())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
synchronized (dataList) {
|
synchronized (blocks) {
|
||||||
for (BlockData data : dataList) {
|
for (long block : blocks) {
|
||||||
data.apply(chunk);
|
apply(chunk, block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,26 +173,30 @@ public class ChunkBatch implements InstanceBatch {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class BlockData {
|
/**
|
||||||
|
* Places a block which is encoded in a long.
|
||||||
|
*
|
||||||
|
* @param chunk the chunk to place the block on
|
||||||
|
* @param value the block data
|
||||||
|
*/
|
||||||
|
private void apply(@NotNull Chunk chunk, long value) {
|
||||||
|
final short customBlockId = (short) (value & 0xFF);
|
||||||
|
final short blockId = (short) (value >> 16 & 0xFF);
|
||||||
|
final int index = (int) (value >> 32 & 0xFFFF);
|
||||||
|
|
||||||
private final int x, y, z;
|
Data data = null;
|
||||||
private final short blockStateId;
|
if (!blockDataMap.isEmpty()) {
|
||||||
private final short customBlockId;
|
synchronized (blockDataMap) {
|
||||||
private final Data data;
|
data = blockDataMap.get(index);
|
||||||
|
}
|
||||||
private BlockData(int x, int y, int z, short blockStateId, short customBlockId, @Nullable Data data) {
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.z = z;
|
|
||||||
this.blockStateId = blockStateId;
|
|
||||||
this.customBlockId = customBlockId;
|
|
||||||
this.data = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void apply(Chunk chunk) {
|
|
||||||
chunk.UNSAFE_setBlock(x, y, z, blockStateId, customBlockId, data, CustomBlockUtils.hasUpdate(customBlockId));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chunk.UNSAFE_setBlock(ChunkUtils.blockIndexToChunkPositionX(index),
|
||||||
|
ChunkUtils.blockIndexToChunkPositionY(index),
|
||||||
|
ChunkUtils.blockIndexToChunkPositionZ(index),
|
||||||
|
blockId, customBlockId, data, CustomBlockUtils.hasUpdate(customBlockId));
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -186,7 +186,6 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
|
|||||||
setItemStackInternal(i, ItemStack.getAirItem());
|
setItemStackInternal(i, ItemStack.getAirItem());
|
||||||
}
|
}
|
||||||
// Send the cleared inventory to viewers
|
// Send the cleared inventory to viewers
|
||||||
// TODO cached packet with empty content
|
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,9 +196,7 @@ public final class ChunkUtils {
|
|||||||
* @return the X coordinate of the block index
|
* @return the X coordinate of the block index
|
||||||
*/
|
*/
|
||||||
public static int blockIndexToPositionX(int index, int chunkX) {
|
public static int blockIndexToPositionX(int index, int chunkX) {
|
||||||
int x = (byte) (index & 0xF);
|
return (int) blockIndexToChunkPositionX(index) + Chunk.CHUNK_SIZE_X * chunkX;
|
||||||
x += Chunk.CHUNK_SIZE_X * chunkX;
|
|
||||||
return x;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -219,9 +217,7 @@ public final class ChunkUtils {
|
|||||||
* @return the Z coordinate of the block index
|
* @return the Z coordinate of the block index
|
||||||
*/
|
*/
|
||||||
public static int blockIndexToPositionZ(int index, int chunkZ) {
|
public static int blockIndexToPositionZ(int index, int chunkZ) {
|
||||||
int z = (byte) (index >> 12 & 0xF);
|
return (int) blockIndexToChunkPositionZ(index) + Chunk.CHUNK_SIZE_Z * chunkZ;
|
||||||
z += Chunk.CHUNK_SIZE_Z * chunkZ;
|
|
||||||
return z;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -231,7 +227,7 @@ public final class ChunkUtils {
|
|||||||
* @return the chunk position X (O-15) of the specified index
|
* @return the chunk position X (O-15) of the specified index
|
||||||
*/
|
*/
|
||||||
public static byte blockIndexToChunkPositionX(int index) {
|
public static byte blockIndexToChunkPositionX(int index) {
|
||||||
return (byte) blockIndexToPositionX(index, 0);
|
return (byte) (index & 0xF);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -241,7 +237,7 @@ public final class ChunkUtils {
|
|||||||
* @return the chunk position Y (O-255) of the specified index
|
* @return the chunk position Y (O-255) of the specified index
|
||||||
*/
|
*/
|
||||||
public static short blockIndexToChunkPositionY(int index) {
|
public static short blockIndexToChunkPositionY(int index) {
|
||||||
return (short) blockIndexToPositionY(index);
|
return (short) (index >>> 4 & 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -251,7 +247,7 @@ public final class ChunkUtils {
|
|||||||
* @return the chunk position Z (O-15) of the specified index
|
* @return the chunk position Z (O-15) of the specified index
|
||||||
*/
|
*/
|
||||||
public static byte blockIndexToChunkPositionZ(int index) {
|
public static byte blockIndexToChunkPositionZ(int index) {
|
||||||
return (byte) blockIndexToPositionZ(index, 0);
|
return (byte) (index >> 12 & 0xF);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ import demo.blocks.UpdatableBlockDemo;
|
|||||||
import demo.commands.*;
|
import demo.commands.*;
|
||||||
import net.minestom.server.MinecraftServer;
|
import net.minestom.server.MinecraftServer;
|
||||||
import net.minestom.server.command.CommandManager;
|
import net.minestom.server.command.CommandManager;
|
||||||
import net.minestom.server.extras.bungee.BungeeCordProxy;
|
|
||||||
import net.minestom.server.extras.optifine.OptifineSupport;
|
import net.minestom.server.extras.optifine.OptifineSupport;
|
||||||
import net.minestom.server.instance.block.BlockManager;
|
import net.minestom.server.instance.block.BlockManager;
|
||||||
import net.minestom.server.instance.block.rule.vanilla.RedstonePlacementRule;
|
import net.minestom.server.instance.block.rule.vanilla.RedstonePlacementRule;
|
||||||
@ -53,7 +52,7 @@ public class Main {
|
|||||||
OptifineSupport.enable();
|
OptifineSupport.enable();
|
||||||
|
|
||||||
//VelocityProxy.enable("rBeJJ79W4MVU");
|
//VelocityProxy.enable("rBeJJ79W4MVU");
|
||||||
BungeeCordProxy.enable();
|
//BungeeCordProxy.enable();
|
||||||
|
|
||||||
// MojangAuth.init();
|
// MojangAuth.init();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user