Cleanup...

This commit is contained in:
TheMode 2021-05-23 00:28:31 +02:00
parent 21df05605d
commit 333825c032
19 changed files with 114 additions and 605 deletions

View File

@ -567,10 +567,7 @@ public class Entity implements Viewable, Tickable, EventHandler, DataContainer,
float drag;
if (onGround) {
final BlockPosition blockPosition = position.toBlockPosition();
final CustomBlock customBlock = finalChunk.getCustomBlock(
blockPosition.getX(),
blockPosition.getY(),
blockPosition.getZ());
final CustomBlock customBlock = null;//finalChunk.getCustomBlock(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ());
if (customBlock != null) {
// Custom drag
drag = customBlock.getDrag(instance, blockPosition);
@ -624,7 +621,7 @@ public class Entity implements Viewable, Tickable, EventHandler, DataContainer,
continue;
}
final CustomBlock customBlock = chunk.getCustomBlock(x, y, z);
final CustomBlock customBlock = null;//chunk.getCustomBlock(x, y, z);
if (customBlock != null) {
tmpPosition.setX(x);
tmpPosition.setY(y);

View File

@ -17,7 +17,10 @@ import net.minestom.server.instance.block.Block;
import net.minestom.server.inventory.EquipmentHandler;
import net.minestom.server.item.ItemStack;
import net.minestom.server.network.ConnectionState;
import net.minestom.server.network.packet.server.play.*;
import net.minestom.server.network.packet.server.play.CollectItemPacket;
import net.minestom.server.network.packet.server.play.EntityAnimationPacket;
import net.minestom.server.network.packet.server.play.EntityPropertiesPacket;
import net.minestom.server.network.packet.server.play.SoundEffectPacket;
import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.scoreboard.Team;
import net.minestom.server.sound.SoundEvent;
@ -602,7 +605,7 @@ public class LivingEntity extends Entity implements EquipmentHandler {
public void setFlyingWithElytra(boolean isFlying) {
this.entityMeta.setFlyingWithElytra(isFlying);
}
/**
* Used to change the {@code isDead} internal field.
*
@ -721,7 +724,7 @@ public class LivingEntity extends Entity implements EquipmentHandler {
Iterator<BlockPosition> it = new BlockIterator(this, maxDistance);
while (it.hasNext()) {
BlockPosition position = it.next();
if (Block.fromStateId(getInstance().getBlockStateId(position)) != Block.AIR) blocks.add(position);
if (!getInstance().getBlock(position).isAir()) blocks.add(position);
}
return blocks;
}
@ -742,7 +745,7 @@ public class LivingEntity extends Entity implements EquipmentHandler {
Iterator<BlockPosition> it = new BlockIterator(start, direction.normalize(), 0D, maxDistance);
while (it.hasNext()) {
Block block = Block.fromStateId(getInstance().getBlockStateId(it.next()));
Block block = getInstance().getBlock(it.next());
if (!block.isAir() && !block.isLiquid()) {
return false;
}
@ -760,7 +763,7 @@ public class LivingEntity extends Entity implements EquipmentHandler {
Iterator<BlockPosition> it = new BlockIterator(this, maxDistance);
while (it.hasNext()) {
BlockPosition position = it.next();
if (Block.fromStateId(getInstance().getBlockStateId(position)) != Block.AIR) return position;
if (getInstance().getBlock(position) != Block.AIR) return position;
}
return null;
}

View File

@ -14,13 +14,13 @@ public class PFBlockDescription implements IBlockDescription {
* <p>
* Cache the result if it is not already.
*
* @param blockStateId the block state id
* @param block the block
* @return the {@link PFBlockDescription} linked to {@code blockStateId}
*/
public static PFBlockDescription getBlockDescription(short blockStateId) {
public static PFBlockDescription getBlockDescription(Block block) {
final short blockStateId = block.getStateId();
if (!BLOCK_DESCRIPTION_MAP.containsKey(blockStateId)) {
synchronized (BLOCK_DESCRIPTION_MAP) {
final Block block = Block.fromStateId(blockStateId);
final PFBlockDescription blockDescription = new PFBlockDescription(block);
BLOCK_DESCRIPTION_MAP.put(blockStateId, blockDescription);
return blockDescription;

View File

@ -15,13 +15,13 @@ public class PFBlockObject implements IBlockObject {
* <p>
* Cache the result if it is not already.
*
* @param blockStateId the block state id
* @param block the block
* @return the {@link PFBlockObject} linked to {@code blockStateId}
*/
public static PFBlockObject getBlockObject(short blockStateId) {
public static PFBlockObject getBlockObject(Block block) {
final short blockStateId = block.getStateId();
if (!BLOCK_OBJECT_MAP.containsKey(blockStateId)) {
synchronized (BLOCK_OBJECT_MAP) {
final Block block = Block.fromStateId(blockStateId);
final PFBlockObject blockObject = new PFBlockObject(block);
BLOCK_OBJECT_MAP.put(blockStateId, blockObject);
return blockObject;

View File

@ -5,6 +5,7 @@ import com.extollit.gaming.ai.path.model.IBlockDescription;
import com.extollit.gaming.ai.path.model.IColumnarSpace;
import com.extollit.gaming.ai.path.model.IInstanceSpace;
import net.minestom.server.instance.Chunk;
import net.minestom.server.instance.block.Block;
public class PFColumnarSpace implements IColumnarSpace {
@ -20,8 +21,8 @@ public class PFColumnarSpace implements IColumnarSpace {
@Override
public IBlockDescription blockAt(int x, int y, int z) {
final short blockStateId = chunk.getBlockStateId(x, y, z);
return PFBlockDescription.getBlockDescription(blockStateId);
final Block block = chunk.getBlock(x, y, z);
return PFBlockDescription.getBlockDescription(block);
}
@Override

View File

@ -5,6 +5,7 @@ import com.extollit.gaming.ai.path.model.IColumnarSpace;
import com.extollit.gaming.ai.path.model.IInstanceSpace;
import net.minestom.server.instance.Chunk;
import net.minestom.server.instance.Instance;
import net.minestom.server.instance.block.Block;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@ -20,8 +21,8 @@ public class PFInstanceSpace implements IInstanceSpace {
@Override
public IBlockObject blockObjectAt(int x, int y, int z) {
final short blockStateId = instance.getBlockStateId(x, y, z);
return PFBlockObject.getBlockObject(blockStateId);
final Block block = instance.getBlock(x, y, z);
return PFBlockObject.getBlockObject(block);
}
@Override

View File

@ -1,15 +1,11 @@
package net.minestom.server.instance;
import net.minestom.server.MinecraftServer;
import net.minestom.server.data.Data;
import net.minestom.server.instance.batch.Batch;
import net.minestom.server.instance.block.Block;
import net.minestom.server.instance.block.BlockManager;
import net.minestom.server.instance.block.CustomBlock;
import net.minestom.server.utils.BlockPosition;
import net.minestom.server.utils.validate.Check;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Represents an element which can place blocks at position.
@ -20,88 +16,9 @@ public interface BlockModifier {
BlockManager BLOCK_MANAGER = MinecraftServer.getBlockManager();
/**
* Sets a block at a position.
* <p>
* You can use {@link #setBlock(int, int, int, Block)} if you want it to be more explicit.
*
* @param x the block X
* @param y the block Y
* @param z the block Z
* @param blockStateId the block state id
* @param data the block {@link Data}, can be null
*/
void setBlockStateId(int x, int y, int z, short blockStateId, @Nullable Data data);
/**
* Sets a {@link CustomBlock} at a position.
* <p>
* The custom block id should be the one returned by {@link CustomBlock#getCustomBlockId()}.
*
* @param x the block X
* @param y the block Y
* @param z the block Z
* @param customBlockId the custom block id
* @param data the block {@link Data}, can be null
*/
void setCustomBlock(int x, int y, int z, short customBlockId, @Nullable Data data);
/**
* Sets a {@link CustomBlock} at a position with a custom state id.
* <p>
* The custom block id should be the one returned by {@link CustomBlock#getCustomBlockId()},
* and the block state id can be anything you want, state id can be retrieved using {@link Block#getBlockId()}.
*
* @param x the block X
* @param y the block Y
* @param z the block Z
* @param blockStateId the block state id
* @param customBlockId the custom block id
* @param data the block {@link Data}, can be null
*/
void setSeparateBlocks(int x, int y, int z, short blockStateId, short customBlockId, @Nullable Data data);
default void setBlockStateId(int x, int y, int z, short blockStateId) {
setBlockStateId(x, y, z, blockStateId, null);
}
default void setBlock(int x, int y, int z, @NotNull Block block) {
setBlockStateId(x, y, z, block.getBlockId(), null);
}
void setBlock(int x, int y, int z, @NotNull Block block);
default void setBlock(@NotNull BlockPosition blockPosition, @NotNull Block block) {
setBlock(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ(), block);
}
default void setBlockStateId(@NotNull BlockPosition blockPosition, short blockStateId) {
setBlockStateId(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ(), blockStateId);
}
default void setCustomBlock(int x, int y, int z, short customBlockId) {
setCustomBlock(x, y, z, customBlockId, null);
}
default void setCustomBlock(int x, int y, int z, @NotNull String customBlockId, @Nullable Data data) {
CustomBlock customBlock = BLOCK_MANAGER.getCustomBlock(customBlockId);
Check.notNull(customBlock, "The CustomBlock " + customBlockId + " is not registered");
setCustomBlock(x, y, z, customBlock.getCustomBlockId(), data);
}
default void setCustomBlock(int x, int y, int z, @NotNull String customBlockId) {
setCustomBlock(x, y, z, customBlockId, null);
}
default void setCustomBlock(@NotNull BlockPosition blockPosition, @NotNull String customBlockId) {
setCustomBlock(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ(), customBlockId);
}
default void setSeparateBlocks(int x, int y, int z, short blockStateId, short customBlockId) {
setSeparateBlocks(x, y, z, blockStateId, customBlockId, null);
}
default void setSeparateBlocks(@NotNull BlockPosition blockPosition, short blockStateId, short customBlockId) {
setSeparateBlocks(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ(), blockStateId, customBlockId, null);
}
}

View File

@ -11,7 +11,6 @@ import net.minestom.server.event.player.PlayerChunkLoadEvent;
import net.minestom.server.event.player.PlayerChunkUnloadEvent;
import net.minestom.server.instance.block.Block;
import net.minestom.server.instance.block.BlockManager;
import net.minestom.server.instance.block.CustomBlock;
import net.minestom.server.network.packet.server.play.ChunkDataPacket;
import net.minestom.server.network.packet.server.play.UpdateLightPacket;
import net.minestom.server.network.player.PlayerConnection;
@ -102,21 +101,16 @@ public abstract class Chunk implements Viewable, Tickable, DataContainer {
* <p>
* This is used when the previous block has to be destroyed/replaced, meaning that it clears the previous data and update method.
* <p>
* WARNING: this method is not thread-safe (in order to bring performance improvement with {@link net.minestom.server.instance.batch.Batch}s)
* The thread-safe version is {@link InstanceContainer#setSeparateBlocks(int, int, int, short, short, Data)} (or any similar instance methods)
* WARNING: this method is not thread-safe (in order to bring performance improvement with {@link net.minestom.server.instance.batch.Batch batches})
* The thread-safe version is {@link Instance#setBlock(int, int, int, Block)} (or any similar instance methods)
* Otherwise, you can simply do not forget to have this chunk synchronized when this is called.
*
* @param x the block X
* @param y the block Y
* @param z the block Z
* @param blockStateId the block state id
* @param customBlockId the custom block id, 0 if not
* @param data the {@link Data} of the block, can be null
* @param updatable true if the block has an update method
* Warning: <code>customBlockId</code> cannot be 0 in this case and needs to be valid since the update delay and method
* will be retrieved from the associated {@link CustomBlock} object
* @param x the block X
* @param y the block Y
* @param z the block Z
* @param block the block to place
*/
public abstract void UNSAFE_setBlock(int x, int y, int z, short blockStateId, short customBlockId, @Nullable Data data, boolean updatable);
public abstract void UNSAFE_setBlock(int x, int y, int z, @NotNull Block block);
/**
* Executes a chunk tick.
@ -131,64 +125,14 @@ public abstract class Chunk implements Viewable, Tickable, DataContainer {
public abstract void tick(long time);
/**
* Gets the block state id at a position.
* Gets the block at a position.
*
* @param x the block X
* @param y the block Y
* @param z the block Z
* @return the block state id at the position
* @return the block at the position
*/
public abstract short getBlockStateId(int x, int y, int z);
/**
* Gets the custom block id at a position.
*
* @param x the block X
* @param y the block Y
* @param z the block Z
* @return the custom block id at the position
*/
public abstract short getCustomBlockId(int x, int y, int z);
/**
* Changes the block state id and the custom block id at a position.
*
* @param x the block X
* @param y the block Y
* @param z the block Z
* @param blockStateId the new block state id
* @param customBlockId the new custom block id
*/
protected abstract void refreshBlockValue(int x, int y, int z, short blockStateId, short customBlockId);
/**
* Changes the block state id at a position (the custom block id stays the same).
*
* @param x the block X
* @param y the block Y
* @param z the block Z
* @param blockStateId the new block state id
*/
protected abstract void refreshBlockStateId(int x, int y, int z, short blockStateId);
/**
* Gets the {@link Data} at a block index.
*
* @param index the block index
* @return the {@link Data} at the block index, null if none
*/
@Nullable
public abstract Data getBlockData(int index);
/**
* Sets the {@link Data} at a position.
*
* @param x the block X
* @param y the block Y
* @param z the block Z
* @param data the new data, can be null
*/
public abstract void setBlockData(int x, int y, int z, @Nullable Data data);
public abstract @NotNull Block getBlock(int x, int y, int z);
/**
* Gets all the block entities in this chunk.
@ -257,34 +201,6 @@ public abstract class Chunk implements Viewable, Tickable, DataContainer {
*/
public abstract void reset();
/**
* Gets the {@link CustomBlock} at a position.
*
* @param x the block X
* @param y the block Y
* @param z the block Z
* @return the {@link CustomBlock} at the position
*/
@Nullable
public CustomBlock getCustomBlock(int x, int y, int z) {
final short customBlockId = getCustomBlockId(x, y, z);
return customBlockId != 0 ? BLOCK_MANAGER.getCustomBlock(customBlockId) : null;
}
/**
* Gets the {@link CustomBlock} at a block index.
*
* @param index the block index
* @return the {@link CustomBlock} at the block index
*/
@Nullable
protected CustomBlock getCustomBlock(int index) {
final int x = ChunkUtils.blockIndexToChunkPositionX(index);
final int y = ChunkUtils.blockIndexToChunkPositionY(index);
final int z = ChunkUtils.blockIndexToChunkPositionZ(index);
return getCustomBlock(x, y, z);
}
/**
* Gets the unique identifier of this chunk.
* <p>
@ -417,10 +333,10 @@ public abstract class Chunk implements Viewable, Tickable, DataContainer {
UpdateLightPacket updateLightPacket = new UpdateLightPacket(getIdentifier(), getLastChangeTime());
updateLightPacket.chunkX = getChunkX();
updateLightPacket.chunkZ = getChunkZ();
updateLightPacket.skyLightMask = 0b111111111111111111;
updateLightPacket.emptySkyLightMask = 0b000000000000000000;
updateLightPacket.blockLightMask = 0b000000000000000000;
updateLightPacket.emptyBlockLightMask = 0b111111111111111111;
updateLightPacket.skyLightMask = 0b111111111111111111;
updateLightPacket.emptySkyLightMask = 0b000000000000000000;
updateLightPacket.blockLightMask = 0b000000000000000000;
updateLightPacket.emptyBlockLightMask = 0b111111111111111111;
byte[] bytes = new byte[2048];
Arrays.fill(bytes, (byte) 0xFF);
final List<byte[]> temp = new ArrayList<>(18);
@ -592,17 +508,6 @@ public abstract class Chunk implements Viewable, Tickable, DataContainer {
UpdateLightPacket.CACHE.invalidate(getIdentifier());
}
/**
* Gets if a block state id represents a block entity.
*
* @param blockStateId the block state id to check
* @return true if {@code blockStateId} represents a block entity
*/
protected boolean isBlockEntity(short blockStateId) {
final Block block = Block.fromStateId(blockStateId);
return block.hasBlockEntity();
}
/**
* Gets the index of a position, used to store blocks.
*

View File

@ -1,7 +1,10 @@
package net.minestom.server.instance;
import com.extollit.gaming.ai.path.model.ColumnarOcclusionFieldList;
import it.unimi.dsi.fastutil.ints.*;
import it.unimi.dsi.fastutil.ints.Int2LongMap;
import it.unimi.dsi.fastutil.ints.Int2LongOpenHashMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.objects.Object2ShortMap;
import it.unimi.dsi.fastutil.objects.Object2ShortOpenHashMap;
import net.minestom.server.MinecraftServer;
@ -9,18 +12,14 @@ import net.minestom.server.data.Data;
import net.minestom.server.data.SerializableData;
import net.minestom.server.data.SerializableDataImpl;
import net.minestom.server.entity.pathfinding.PFBlockDescription;
import net.minestom.server.instance.block.CustomBlock;
import net.minestom.server.instance.block.Block;
import net.minestom.server.instance.palette.PaletteStorage;
import net.minestom.server.network.packet.server.play.ChunkDataPacket;
import net.minestom.server.utils.BlockPosition;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
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.ChunkUtils;
import net.minestom.server.utils.time.Cooldown;
import net.minestom.server.utils.time.UpdateOption;
import net.minestom.server.utils.validate.Check;
import net.minestom.server.world.biomes.Biome;
import org.jetbrains.annotations.NotNull;
@ -77,8 +76,11 @@ public class DynamicChunk extends Chunk {
}
@Override
public void UNSAFE_setBlock(int x, int y, int z, short blockStateId, short customBlockId, Data data, boolean updatable) {
public void UNSAFE_setBlock(int x, int y, int z, @NotNull Block block) {
final short blockStateId = block.getStateId();
final short customBlockId = 0; // TODO
final boolean updatable = false; // TODO
final boolean nbt = false; // TODO
{
// Update pathfinder
if (columnarSpace != null) {
@ -124,7 +126,7 @@ public class DynamicChunk extends Chunk {
}
// Set block entity
if (isBlockEntity(blockStateId)) {
if (nbt) {
this.blockEntities.add(index);
} else {
this.blockEntities.remove(index);
@ -133,66 +135,15 @@ public class DynamicChunk extends Chunk {
@Override
public void tick(long time) {
if (updatableBlocks.isEmpty())
return;
// Block all chunk operation during the update
final IntIterator iterator = new IntOpenHashSet(updatableBlocks).iterator();
while (iterator.hasNext()) {
final int index = iterator.nextInt();
final CustomBlock customBlock = getCustomBlock(index);
// Update cooldown
final UpdateOption updateOption = customBlock.getUpdateOption();
if (updateOption != null) {
final long lastUpdate = updatableBlocksLastUpdate.get(index);
final boolean hasCooldown = Cooldown.hasCooldown(time, lastUpdate, updateOption);
if (hasCooldown)
continue;
this.updatableBlocksLastUpdate.put(index, time); // Refresh last update time
final BlockPosition blockPosition = ChunkUtils.getBlockPosition(index, chunkX, chunkZ);
final Data data = getBlockData(index);
customBlock.update(instance, blockPosition, data);
}
}
// TODO block update
}
@Override
public short getBlockStateId(int x, int y, int z) {
return getBlockAt(blockPalette, x, y, z);
}
@Override
public short getCustomBlockId(int x, int y, int z) {
return getBlockAt(customBlockPalette, x, y, z);
}
@Override
protected void refreshBlockValue(int x, int y, int z, short blockStateId, short customBlockId) {
setBlockAt(blockPalette, x, y, z, blockStateId);
setBlockAt(customBlockPalette, x, y, z, customBlockId);
}
@Override
protected void refreshBlockStateId(int x, int y, int z, short blockStateId) {
setBlockAt(blockPalette, x, y, z, blockStateId);
}
@Override
public Data getBlockData(int index) {
return blocksData.get(index);
}
@Override
public void setBlockData(int x, int y, int z, Data data) {
final int index = getBlockIndex(x, y, z);
if (data != null) {
this.blocksData.put(index, data);
} else {
this.blocksData.remove(index);
}
public @NotNull Block getBlock(int x, int y, int z) {
final short blockStateId = getBlockAt(blockPalette, x, y, z);
Block block = Block.fromStateId(blockStateId);
// TODO nbt/handler
return block;
}
@NotNull
@ -268,7 +219,7 @@ public class DynamicChunk extends Chunk {
chunkWriter.writeShort(customBlockId);
// Data
final Data data = getBlockData(index);
final Data data = null;//getBlockData(index);
final boolean hasBlockData = data instanceof SerializableData && !data.isEmpty();
chunkWriter.writeBoolean(hasBlockData);
if (hasBlockData) {
@ -375,7 +326,10 @@ public class DynamicChunk extends Chunk {
}
}
UNSAFE_setBlock(x, y, z, blockStateId, customBlockId, data, CustomBlockUtils.hasUpdate(customBlockId));
Block block = Block.fromStateId(blockStateId);
// TODO read other data
UNSAFE_setBlock(x, y, z, block);
}
// Finished reading

View File

@ -132,16 +132,6 @@ public abstract class Instance implements BlockModifier, Tickable, EventHandler,
this.nextTick.add(callback);
}
/**
* Used to change the id of the block in a specific {@link BlockPosition}.
* <p>
* In case of a {@link CustomBlock} it does not remove it but only refresh its visual.
*
* @param blockPosition the block position
* @param blockStateId the new block state
*/
public abstract void refreshBlockStateId(@NotNull BlockPosition blockPosition, short blockStateId);
/**
* Does call {@link net.minestom.server.event.player.PlayerBlockBreakEvent}
* and send particle packets
@ -495,46 +485,6 @@ public abstract class Instance implements BlockModifier, Tickable, EventHandler,
return Collections.unmodifiableSet(entities);
}
/**
* Refreshes the visual block id at the position.
* <p>
* WARNING: the custom block id at the position will not change.
*
* @param x the X position
* @param y the Y position
* @param z the Z position
* @param blockStateId the new block state id
*/
public void refreshBlockStateId(int x, int y, int z, short blockStateId) {
refreshBlockStateId(new BlockPosition(x, y, z), blockStateId);
}
/**
* Refreshes the visual block id at the position.
* <p>
* WARNING: the custom block id at the position will not change.
*
* @param x the X position
* @param y the Y position
* @param z the Z position
* @param block the new visual block
*/
public void refreshBlockId(int x, int y, int z, @NotNull Block block) {
refreshBlockStateId(x, y, z, block.getBlockId());
}
/**
* Refreshes the visual block id at the {@link BlockPosition}.
* <p>
* WARNING: the custom block id at the position will not change.
*
* @param blockPosition the block position
* @param block the new visual block
*/
public void refreshBlockId(@NotNull BlockPosition blockPosition, @NotNull Block block) {
refreshBlockStateId(blockPosition, block.getBlockId());
}
/**
* Loads the {@link Chunk} at the given position without any callback.
* <p>
@ -584,16 +534,6 @@ public abstract class Instance implements BlockModifier, Tickable, EventHandler,
unloadChunk(chunk);
}
/**
* Gets block from given position.
*
* @param position position to get from
* @return Block at given position.
*/
public Block getBlock(BlockPosition position) {
return getBlock(position.getX(), position.getY(), position.getZ());
}
/**
* Gets Block type from given coordinates.
*
@ -602,74 +542,22 @@ public abstract class Instance implements BlockModifier, Tickable, EventHandler,
* @param z z coordinate
* @return Block at given position.
*/
public Block getBlock(int x, int y, int z) {
return Block.fromStateId(getBlockStateId(x, y, z));
}
/**
* Gives the block state id at the given position.
*
* @param x the X position
* @param y the Y position
* @param z the Z position
* @return the block state id at the position
*/
public short getBlockStateId(int x, int y, int z) {
public @NotNull Block getBlock(int x, int y, int z) {
final Chunk chunk = getChunkAt(x, z);
Check.notNull(chunk, "The chunk at " + x + ":" + z + " is not loaded");
Check.notNull(chunk, "The chunk at {0}:{1} is not loaded", x, z);
synchronized (chunk) {
return chunk.getBlockStateId(x, y, z);
return chunk.getBlock(x, y, z);
}
}
/**
* Gives the block state id at the given position.
* Gets block from given position.
*
* @param x the X position
* @param y the Y position
* @param z the Z position
* @return the block state id at the position
* @param position position to get from
* @return Block at given position.
*/
public short getBlockStateId(double x, double y, double z) {
return getBlockStateId((int) Math.round(x), (int) Math.round(y), (int) Math.round(z));
}
/**
* Gives the block state id at the given {@link BlockPosition}.
*
* @param blockPosition the block position
* @return the block state id at the position
*/
public short getBlockStateId(@NotNull BlockPosition blockPosition) {
return getBlockStateId(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ());
}
/**
* Gets the custom block object at the given position.
*
* @param x the X position
* @param y the Y position
* @param z the Z position
* @return the custom block object at the position, null if not any
*/
@Nullable
public CustomBlock getCustomBlock(int x, int y, int z) {
final Chunk chunk = getChunkAt(x, z);
Check.notNull(chunk, "The chunk at " + x + ":" + z + " is not loaded");
synchronized (chunk) {
return chunk.getCustomBlock(x, y, z);
}
}
/**
* Gets the custom block object at the given {@link BlockPosition}.
*
* @param blockPosition the block position
* @return the custom block object at the position, null if not any
*/
@Nullable
public CustomBlock getCustomBlock(@NotNull BlockPosition blockPosition) {
return getCustomBlock(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ());
public @NotNull Block getBlock(@NotNull BlockPosition position) {
return getBlock(position.getX(), position.getY(), position.getZ());
}
/**
@ -681,8 +569,7 @@ public abstract class Instance implements BlockModifier, Tickable, EventHandler,
* @see <a href="https://wiki.vg/Protocol#Block_Action">BlockActionPacket</a> for the action id &amp; param
*/
public void sendBlockAction(@NotNull BlockPosition blockPosition, byte actionId, byte actionParam) {
final short blockStateId = getBlockStateId(blockPosition);
final Block block = Block.fromStateId(blockStateId);
final Block block = getBlock(blockPosition);
BlockActionPacket blockActionPacket = new BlockActionPacket();
blockActionPacket.blockPosition = blockPosition;
@ -695,61 +582,6 @@ public abstract class Instance implements BlockModifier, Tickable, EventHandler,
chunk.sendPacketToViewers(blockActionPacket);
}
/**
* Gets the block data at the given position.
*
* @param x the X position
* @param y the Y position
* @param z the Z position
* @return the block data at the position, null if not any
*/
@Nullable
public Data getBlockData(int x, int y, int z) {
final Chunk chunk = getChunkAt(x, z);
Check.notNull(chunk, "The chunk at " + x + ":" + z + " is not loaded");
final int index = ChunkUtils.getBlockIndex(x, y, z);
synchronized (chunk) {
return chunk.getBlockData(index);
}
}
/**
* Gets the block {@link Data} at the given {@link BlockPosition}.
*
* @param blockPosition the block position
* @return the block data at the position, null if not any
*/
@Nullable
public Data getBlockData(@NotNull BlockPosition blockPosition) {
return getBlockData(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ());
}
/**
* Sets the block {@link Data} at the given {@link BlockPosition}.
*
* @param x the X position
* @param y the Y position
* @param z the Z position
* @param data the data to be set, can be null
*/
public void setBlockData(int x, int y, int z, @Nullable Data data) {
final Chunk chunk = getChunkAt(x, z);
Check.notNull(chunk, "The chunk at " + x + ":" + z + " is not loaded");
synchronized (chunk) {
chunk.setBlockData(x, (byte) y, z, data);
}
}
/**
* Sets the block {@link Data} at the given {@link BlockPosition}.
*
* @param blockPosition the block position
* @param data the data to be set, can be null
*/
public void setBlockData(@NotNull BlockPosition blockPosition, @Nullable Data data) {
setBlockData(blockPosition.getX(), (byte) blockPosition.getY(), blockPosition.getZ(), data);
}
/**
* Gets the {@link Chunk} at the given {@link BlockPosition}, null if not loaded.
*

View File

@ -104,47 +104,16 @@ public class InstanceContainer extends Instance {
}
@Override
public void setBlockStateId(int x, int y, int z, short blockStateId, @Nullable Data data) {
setBlock(x, y, z, blockStateId, null, data);
}
@Override
public void setCustomBlock(int x, int y, int z, short customBlockId, @Nullable Data data) {
final CustomBlock customBlock = BLOCK_MANAGER.getCustomBlock(customBlockId);
Check.notNull(customBlock, "The custom block with the id " + customBlockId + " does not exist.");
setBlock(x, y, z, customBlock.getDefaultBlockStateId(), customBlock, data);
}
@Override
public void setSeparateBlocks(int x, int y, int z, short blockStateId, short customBlockId, @Nullable Data data) {
final CustomBlock customBlock = BLOCK_MANAGER.getCustomBlock(customBlockId);
setBlock(x, y, z, blockStateId, customBlock, data);
}
/**
* Set a block at the position
* <p>
* Verifies if the {@link Chunk} at the position is loaded, place the block if yes.
* Otherwise, check if {@link #hasEnabledAutoChunkLoad()} is true to load the chunk automatically and place the block.
*
* @param x the block X
* @param y the block Y
* @param z the block Z
* @param blockStateId the block state id
* @param customBlock the {@link CustomBlock}, null if none
* @param data the {@link Data}, null if none
*/
private synchronized void setBlock(int x, int y, int z, short blockStateId,
@Nullable CustomBlock customBlock, @Nullable Data data) {
public synchronized void setBlock(int x, int y, int z, @NotNull Block block) {
final Chunk chunk = getChunkAt(x, z);
if (ChunkUtils.isLoaded(chunk)) {
UNSAFE_setBlock(chunk, x, y, z, blockStateId, customBlock, data);
UNSAFE_setBlock(chunk, x, y, z, block);
} else {
Check.stateCondition(!hasEnabledAutoChunkLoad(),
"Tried to set a block to an unloaded chunk with auto chunk load disabled");
final int chunkX = ChunkUtils.getChunkCoordinate(x);
final int chunkZ = ChunkUtils.getChunkCoordinate(z);
loadChunk(chunkX, chunkZ, c -> UNSAFE_setBlock(c, x, y, z, blockStateId, customBlock, data));
loadChunk(chunkX, chunkZ, c -> UNSAFE_setBlock(c, x, y, z, block));
}
}
@ -153,16 +122,13 @@ public class InstanceContainer extends Instance {
* <p>
* Unsafe because the method is not synchronized and it does not verify if the chunk is loaded or not.
*
* @param chunk the {@link Chunk} which should be loaded
* @param x the block X
* @param y the block Y
* @param z the block Z
* @param blockStateId the block state id
* @param customBlock the {@link CustomBlock}, null if none
* @param data the {@link Data}, null if none
* @param chunk the {@link Chunk} which should be loaded
* @param x the block X
* @param y the block Y
* @param z the block Z
* @param block the block to place
*/
private void UNSAFE_setBlock(@NotNull Chunk chunk, int x, int y, int z, short blockStateId,
@Nullable CustomBlock customBlock, @Nullable Data data) {
private void UNSAFE_setBlock(@NotNull Chunk chunk, int x, int y, int z, @NotNull Block block) {
// Cannot place block in a read-only chunk
if (chunk.isReadOnly()) {
@ -174,8 +140,6 @@ public class InstanceContainer extends Instance {
// Refresh the last block change time
this.lastBlockChangeTime = System.currentTimeMillis();
final boolean isCustomBlock = customBlock != null;
final BlockPosition blockPosition = new BlockPosition(x, y, z);
if (isAlreadyChanged(blockPosition, blockStateId)) { // do NOT change the block again.
@ -195,25 +159,16 @@ public class InstanceContainer extends Instance {
}
// Change id based on neighbors
blockStateId = executeBlockPlacementRule(blockStateId, blockPosition);
// Retrieve custom block values
short customBlockId = 0;
boolean hasUpdate = false;
if (isCustomBlock) {
customBlockId = customBlock.getCustomBlockId();
data = customBlock.createData(this, blockPosition, data);
hasUpdate = CustomBlockUtils.hasUpdate(customBlock);
}
block = executeBlockPlacementRule(block, blockPosition);
// Set the block
chunk.UNSAFE_setBlock(x, y, z, blockStateId, customBlockId, data, hasUpdate);
chunk.UNSAFE_setBlock(x, y, z, block);
// Refresh neighbors since a new block has been placed
executeNeighboursBlockPlacementRule(blockPosition);
// Refresh player chunk block
sendBlockChange(chunk, blockPosition, blockStateId);
sendBlockChange(chunk, blockPosition, block);
// Call the destroy listener for the previously destroyed block
if (previousBlock != null) {
@ -246,18 +201,6 @@ public class InstanceContainer extends Instance {
return changedBlock.getBlockId() == blockStateId;
}
@Override
public void refreshBlockStateId(@NotNull BlockPosition blockPosition, short blockStateId) {
final Chunk chunk = getChunkAt(blockPosition.getX(), blockPosition.getZ());
Check.notNull(chunk, "You cannot refresh a block in a null chunk!");
synchronized (chunk) {
chunk.refreshBlockStateId(blockPosition.getX(), blockPosition.getY(),
blockPosition.getZ(), blockStateId);
sendBlockChange(chunk, blockPosition, blockStateId);
}
}
/**
* Calls {@link CustomBlock#onDestroy(Instance, BlockPosition, Data)} for {@code previousBlock}.
* <p>
@ -292,14 +235,14 @@ public class InstanceContainer extends Instance {
/**
* Calls the {@link BlockPlacementRule} for the specified block state id.
*
* @param blockStateId the block state id to modify
* @param block the block to modify
* @param blockPosition the block position
* @return the modified block state id
*/
private short executeBlockPlacementRule(short blockStateId, @NotNull BlockPosition blockPosition) {
final BlockPlacementRule blockPlacementRule = BLOCK_MANAGER.getBlockPlacementRule(blockStateId);
private Block executeBlockPlacementRule(Block block, @NotNull BlockPosition blockPosition) {
final BlockPlacementRule blockPlacementRule = BLOCK_MANAGER.getBlockPlacementRule(block);
if (blockPlacementRule != null) {
return blockPlacementRule.blockUpdate(this, blockPosition, blockStateId);
return blockPlacementRule.blockUpdate(this, blockPosition, block);
}
return blockStateId;
}
@ -746,12 +689,12 @@ public class InstanceContainer extends Instance {
*
* @param chunk the chunk where the block is
* @param blockPosition the block position
* @param blockStateId the new state of the block
* @param block the new block
*/
private void sendBlockChange(@NotNull Chunk chunk, @NotNull BlockPosition blockPosition, short blockStateId) {
private void sendBlockChange(@NotNull Chunk chunk, @NotNull BlockPosition blockPosition, @NotNull Block block) {
BlockChangePacket blockChangePacket = new BlockChangePacket();
blockChangePacket.blockPosition = blockPosition;
blockChangePacket.blockStateId = blockStateId;
blockChangePacket.blockStateId = block.getStateId();
chunk.sendPacketToViewers(blockChangePacket);
}

View File

@ -1,7 +1,7 @@
package net.minestom.server.instance;
import net.minestom.server.data.Data;
import net.minestom.server.entity.Player;
import net.minestom.server.instance.block.Block;
import net.minestom.server.storage.StorageLocation;
import net.minestom.server.utils.BlockPosition;
import net.minestom.server.utils.Position;
@ -27,8 +27,8 @@ public class SharedInstance extends Instance {
}
@Override
public void refreshBlockStateId(@NotNull BlockPosition blockPosition, short blockStateId) {
this.instanceContainer.refreshBlockStateId(blockPosition, blockStateId);
public void setBlock(int x, int y, int z, @NotNull Block block) {
this.instanceContainer.setBlock(x, y, z, block);
}
@Override
@ -117,21 +117,6 @@ public class SharedInstance extends Instance {
return instanceContainer.isInVoid(position);
}
@Override
public void setBlockStateId(int x, int y, int z, short blockStateId, Data data) {
this.instanceContainer.setBlockStateId(x, y, z, blockStateId, data);
}
@Override
public void setCustomBlock(int x, int y, int z, short customBlockId, Data data) {
this.instanceContainer.setCustomBlock(x, y, z, customBlockId, data);
}
@Override
public void setSeparateBlocks(int x, int y, int z, short blockStateId, short customBlockId, Data data) {
this.instanceContainer.setSeparateBlocks(x, y, z, blockStateId, customBlockId, data);
}
@Override
public void scheduleUpdate(int time, @NotNull TimeUnit unit, @NotNull BlockPosition position) {
this.instanceContainer.scheduleUpdate(time, unit, position);

View File

@ -1,12 +1,9 @@
package net.minestom.server.instance.batch;
import net.minestom.server.MinecraftServer;
import net.minestom.server.data.Data;
import net.minestom.server.instance.BlockModifier;
import net.minestom.server.instance.Instance;
import net.minestom.server.instance.block.CustomBlock;
import net.minestom.server.utils.thread.MinestomThread;
import net.minestom.server.utils.validate.Check;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -26,7 +23,6 @@ import java.util.concurrent.ExecutorService;
* applied.
*
* @param <C> The callback function type.
*
* @see ChunkBatch
* @see AbsoluteBlockBatch
* @see RelativeBlockBatch
@ -37,21 +33,6 @@ public interface Batch<C> extends BlockModifier {
MinecraftServer.THREAD_COUNT_BLOCK_BATCH,
MinecraftServer.THREAD_NAME_BLOCK_BATCH);
@Override
default void setBlockStateId(int x, int y, int z, short blockStateId, @Nullable Data data) {
setSeparateBlocks(x, y, z, blockStateId, (short) 0, data);
}
@Override
default void setCustomBlock(int x, int y, int z, short customBlockId, @Nullable Data data) {
final CustomBlock customBlock = BLOCK_MANAGER.getCustomBlock(customBlockId);
Check.notNull(customBlock, "The custom block with the id " + customBlockId + " does not exist!");
setSeparateBlocks((byte) x, y, (byte) z, customBlock.getDefaultBlockStateId(), customBlockId, data);
}
@Override
void setSeparateBlocks(int x, int y, int z, short blockStateId, short customBlockId, @Nullable Data data);
/**
* Gets if the batch is ready to be applied to an instance.
*

View File

@ -10,9 +10,9 @@ import net.minestom.server.data.Data;
import net.minestom.server.instance.Chunk;
import net.minestom.server.instance.Instance;
import net.minestom.server.instance.InstanceContainer;
import net.minestom.server.instance.block.Block;
import net.minestom.server.network.packet.server.play.ChunkDataPacket;
import net.minestom.server.utils.PacketUtils;
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.ChunkUtils;
@ -72,22 +72,25 @@ public class ChunkBatch implements Batch<ChunkCallback> {
}
@Override
public void setSeparateBlocks(int x, int y, int z, short blockStateId, short customBlockId, @Nullable Data data) {
public void setBlock(int x, int y, int z, @NotNull Block block) {
final short blockStateId = block.getStateId();
// TODO other ids
// Cache the entry to be placed later during flush
final int index = ChunkUtils.getBlockIndex(x, y, z);
long value = index;
value = (value << 16) | blockStateId;
value = (value << 16) | customBlockId;
//value = (value << 16) | customBlockId;
synchronized (blocks) {
this.blocks.add(value);
}
if (data != null) {
/*if (data != null) {
synchronized (blockDataMap) {
this.blockDataMap.put(index, data);
}
}
}*/
}
@Override
@ -245,10 +248,15 @@ public class ChunkBatch implements Batch<ChunkCallback> {
final int y = ChunkUtils.blockIndexToChunkPositionY(index);
final int z = ChunkUtils.blockIndexToChunkPositionZ(index);
if (inverse != null)
inverse.setSeparateBlocks(x, y, z, chunk.getBlockStateId(x, y, z), chunk.getCustomBlockId(x, y, z), chunk.getBlockData(index));
if (inverse != null) {
Block prevBlock = chunk.getBlock(x, y, z);
inverse.setBlock(x, y, z, prevBlock);
}
chunk.UNSAFE_setBlock(x, y, z, blockId, customBlockId, data, CustomBlockUtils.hasUpdate(customBlockId));
Block block = Block.fromStateId(blockId);
// TODO other data
chunk.UNSAFE_setBlock(x, y, z, block);
return ChunkUtils.getSectionAt(y);
}

View File

@ -56,18 +56,14 @@ public interface Block extends Keyed, TagReadable, BlockConstants {
BlockRegistry.register(namespaceID, block, range, blockSupplier);
}
/**
* Migrated to {@link #getData()}.{@link BlockData#isSolid()} method.
*
* @return True if the Block is solid.
*/
@Deprecated(
forRemoval = true
)
default boolean isSolid() {
return getData().isSolid();
}
default boolean isAir() {
return getData().isAir();
}
@FunctionalInterface
interface Supplier {
@NotNull Block get(short stateId);

View File

@ -43,7 +43,7 @@ public class BlockManager {
* @throws IllegalArgumentException if <code>blockPlacementRule</code> block id is negative
*/
public synchronized void registerBlockPlacementRule(@NotNull BlockPlacementRule blockPlacementRule) {
final short id = blockPlacementRule.getBlockId();
final int id = blockPlacementRule.getBlock().getBlockId();
Check.argCondition(id < 0, "Block ID must be >= 0, got: " + id);
this.placementRules[id] = blockPlacementRule;
@ -60,18 +60,6 @@ public class BlockManager {
return this.placementRules[block.getBlockId()];
}
/**
* Gets the {@link BlockPlacementRule} of the specific block.
*
* @param blockStateId the block id to check
* @return the block placement rule associated with the id, null if not any
*/
@Nullable
public BlockPlacementRule getBlockPlacementRule(short blockStateId) {
final Block block = Block.fromStateId(blockStateId); // Convert block alternative
return getBlockPlacementRule(block);
}
/**
* Gets the {@link CustomBlock} with the specific identifier {@link CustomBlock#getIdentifier()}.
*

View File

@ -87,8 +87,7 @@ public class StairsPlacementRule extends BlockPlacementRule {
if (block == null) {
return Pair.of(null, null);
}
short stateId = instance.getBlockStateId(blockPosition);
Block state = Block.fromStateId(stateId);
Block state = instance.getBlock(blockPosition);
try {
Shape shape = Shape.valueOf(state.getProperty("shape").toUpperCase());
Facing facing = Facing.valueOf(state.getProperty("facing").toUpperCase());

View File

@ -2,7 +2,6 @@ package net.minestom.server.instance.palette;
import net.minestom.server.MinecraftServer;
import net.minestom.server.instance.Chunk;
import net.minestom.server.instance.block.Block;
import net.minestom.server.utils.MathUtils;
import net.minestom.server.utils.chunk.ChunkUtils;
import net.minestom.server.utils.clone.CloneUtils;
@ -63,7 +62,7 @@ public class PaletteStorage implements PublicCloneable<PaletteStorage> {
final int sectionIndex = ChunkUtils.getSectionAt(y);
final Section section = sections[sectionIndex];
if (section == null) {
return Block.AIR.getBlockId();
return 0;
}
x = toChunkCoordinate(x);
z = toChunkCoordinate(z);

View File

@ -113,7 +113,7 @@ public class Section implements PublicCloneable<Section> {
public short getBlockAt(int x, int y, int z) {
if (blocks.length == 0) {
// Section is not loaded, can only be air
return Block.AIR.getBlockId();
return 0;
}
final int sectionIdentifier = getSectionIndex(x, y, z);