mirror of
https://github.com/Minestom/Minestom.git
synced 2024-12-28 12:07:42 +01:00
Optimization to prevent permanent map lookup
This commit is contained in:
parent
648cad85c2
commit
0abedd7453
@ -51,6 +51,7 @@ public interface CommandSender extends PermissionHandler {
|
||||
* Casts this object to a {@link Player}.
|
||||
* No checks are performed, {@link ClassCastException} can very much happen.
|
||||
*
|
||||
* @throws ClassCastException if 'this' is not a player
|
||||
* @see #isPlayer()
|
||||
*/
|
||||
default Player asPlayer() {
|
||||
@ -61,6 +62,7 @@ public interface CommandSender extends PermissionHandler {
|
||||
* Casts this object to a {@link ConsoleSender}.
|
||||
* No checks are performed, {@link ClassCastException} can very much happen.
|
||||
*
|
||||
* @throws ClassCastException if 'this' is not a console sender
|
||||
* @see #isConsole()
|
||||
*/
|
||||
default ConsoleSender asConsole() {
|
||||
|
@ -379,8 +379,9 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P
|
||||
return;
|
||||
}
|
||||
|
||||
BlockPosition blockPosition = position.toBlockPosition();
|
||||
if (!ChunkUtils.isLoaded(instance, position.getX(), position.getZ()) || !ChunkUtils.isLoaded(instance, blockPosition.getX(), blockPosition.getZ())) {
|
||||
final Chunk currentChunk = getChunk(); // current entity chunk
|
||||
|
||||
if (!ChunkUtils.isLoaded(currentChunk)) {
|
||||
// No update for entities in unloaded chunk
|
||||
return;
|
||||
}
|
||||
@ -468,8 +469,8 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P
|
||||
|
||||
float drag;
|
||||
if (onGround) {
|
||||
final CustomBlock customBlock =
|
||||
instance.getCustomBlock(blockPosition);
|
||||
final BlockPosition blockPosition = position.toBlockPosition();
|
||||
final CustomBlock customBlock = instance.getCustomBlock(blockPosition);
|
||||
if (customBlock != null) {
|
||||
// Custom drag
|
||||
drag = customBlock.getDrag(instance, blockPosition);
|
||||
|
@ -19,7 +19,9 @@ import net.minestom.server.sound.Sound;
|
||||
import net.minestom.server.sound.SoundCategory;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import net.minestom.server.utils.time.CooldownUtils;
|
||||
import net.minestom.server.utils.time.TimeUnit;
|
||||
import net.minestom.server.utils.time.UpdateOption;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@ -29,7 +31,11 @@ import java.util.function.Consumer;
|
||||
|
||||
public abstract class LivingEntity extends Entity implements EquipmentHandler {
|
||||
|
||||
// Item pickup
|
||||
protected boolean canPickupItem;
|
||||
protected UpdateOption itemPickupCooldown = new UpdateOption(10, TimeUnit.TICK);
|
||||
protected long lastItemPickupTime;
|
||||
|
||||
protected boolean isDead;
|
||||
|
||||
private float health;
|
||||
@ -90,8 +96,10 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
|
||||
}
|
||||
|
||||
// Items picking
|
||||
if (canPickupItem()) {
|
||||
final Chunk chunk = instance.getChunkAt(getPosition()); // TODO check surrounding chunks
|
||||
if (canPickupItem() && !CooldownUtils.hasCooldown(time, lastItemPickupTime, itemPickupCooldown)) {
|
||||
this.lastItemPickupTime = time;
|
||||
|
||||
final Chunk chunk = getChunk(); // TODO check surrounding chunks
|
||||
final Set<Entity> entities = instance.getChunkEntities(chunk);
|
||||
for (Entity entity : entities) {
|
||||
if (entity instanceof ItemEntity) {
|
||||
|
@ -55,6 +55,9 @@ 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.instance.InstanceUtils;
|
||||
import net.minestom.server.utils.time.CooldownUtils;
|
||||
import net.minestom.server.utils.time.TimeUnit;
|
||||
import net.minestom.server.utils.time.UpdateOption;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
import net.minestom.server.world.DimensionType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -126,6 +129,10 @@ public class Player extends LivingEntity implements CommandSender {
|
||||
private byte targetStage; // The current stage of the target block, only if multi player breaking is disabled
|
||||
private final Set<Player> targetBreakers = new HashSet<>(1); // Only used if multi player breaking is disabled, contains only this player
|
||||
|
||||
// Experience orb pickup
|
||||
protected UpdateOption experiencePickupCooldown = new UpdateOption(10, TimeUnit.TICK);
|
||||
protected long lastExperiencePickupTime;
|
||||
|
||||
private BelowNameTag belowNameTag;
|
||||
|
||||
private int permissionLevel;
|
||||
@ -347,20 +354,24 @@ public class Player extends LivingEntity implements CommandSender {
|
||||
}
|
||||
|
||||
// Experience orb pickup
|
||||
final Chunk chunk = instance.getChunkAt(getPosition()); // TODO check surrounding chunks
|
||||
final Set<Entity> entities = instance.getChunkEntities(chunk);
|
||||
for (Entity entity : entities) {
|
||||
if (entity instanceof ExperienceOrb) {
|
||||
final ExperienceOrb experienceOrb = (ExperienceOrb) entity;
|
||||
final BoundingBox itemBoundingBox = experienceOrb.getBoundingBox();
|
||||
if (expandedBoundingBox.intersect(itemBoundingBox)) {
|
||||
if (experienceOrb.shouldRemove() || experienceOrb.isRemoveScheduled())
|
||||
continue;
|
||||
PickupExperienceEvent pickupExperienceEvent = new PickupExperienceEvent(experienceOrb);
|
||||
callCancellableEvent(PickupExperienceEvent.class, pickupExperienceEvent, () -> {
|
||||
short experienceCount = pickupExperienceEvent.getExperienceCount(); // TODO give to player
|
||||
entity.remove();
|
||||
});
|
||||
if (!CooldownUtils.hasCooldown(time, lastExperiencePickupTime, experiencePickupCooldown)) {
|
||||
this.lastExperiencePickupTime = time;
|
||||
|
||||
final Chunk chunk = getChunk(); // TODO check surrounding chunks
|
||||
final Set<Entity> entities = instance.getChunkEntities(chunk);
|
||||
for (Entity entity : entities) {
|
||||
if (entity instanceof ExperienceOrb) {
|
||||
final ExperienceOrb experienceOrb = (ExperienceOrb) entity;
|
||||
final BoundingBox itemBoundingBox = experienceOrb.getBoundingBox();
|
||||
if (expandedBoundingBox.intersect(itemBoundingBox)) {
|
||||
if (experienceOrb.shouldRemove() || experienceOrb.isRemoveScheduled())
|
||||
continue;
|
||||
PickupExperienceEvent pickupExperienceEvent = new PickupExperienceEvent(experienceOrb);
|
||||
callCancellableEvent(PickupExperienceEvent.class, pickupExperienceEvent, () -> {
|
||||
short experienceCount = pickupExperienceEvent.getExperienceCount(); // TODO give to player
|
||||
entity.remove();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -605,6 +605,15 @@ public class InstanceContainer extends Instance {
|
||||
return Collections.unmodifiableList(sharedInstances);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if this instance has {@link SharedInstance} linked to it.
|
||||
*
|
||||
* @return true if {@link #getSharedInstances()} is not empty
|
||||
*/
|
||||
public boolean hasSharedInstances() {
|
||||
return !sharedInstances.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns a {@link SharedInstance} to this container.
|
||||
* <p>
|
||||
|
@ -112,7 +112,7 @@ public abstract class ThreadProvider {
|
||||
// INSTANCE UPDATE
|
||||
|
||||
/**
|
||||
* Process a whole tick for a chunk.
|
||||
* Processes 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)}
|
||||
@ -243,6 +243,10 @@ public abstract class ThreadProvider {
|
||||
private void updateSharedInstances(@NotNull Instance instance, @NotNull Consumer<SharedInstance> callback) {
|
||||
if (instance instanceof InstanceContainer) {
|
||||
final InstanceContainer instanceContainer = (InstanceContainer) instance;
|
||||
|
||||
if (!instanceContainer.hasSharedInstances())
|
||||
return;
|
||||
|
||||
for (SharedInstance sharedInstance : instanceContainer.getSharedInstances()) {
|
||||
callback.accept(sharedInstance);
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
package net.minestom.server.utils;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minestom.server.instance.Chunk;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
import java.util.UUID;
|
||||
@ -94,6 +92,32 @@ public final class Utils {
|
||||
return new UUID(uuidMost, uuidLeast);
|
||||
}
|
||||
|
||||
public static void writeBlocks(ByteBuf buffer, short[] palette, long[] blocksId, int bitsPerEntry) {
|
||||
/*short count = 0;
|
||||
for (short id : blocksId)
|
||||
if (id != 0)
|
||||
count++;*/
|
||||
|
||||
//buffer.writeShort(count);
|
||||
buffer.writeShort(200);
|
||||
buffer.writeByte((byte) bitsPerEntry);
|
||||
|
||||
// Palette
|
||||
if (bitsPerEntry < 9) {
|
||||
// Palette has to exist
|
||||
writeVarIntBuf(buffer, palette.length);
|
||||
for (short paletteValue : palette) {
|
||||
writeVarIntBuf(buffer, paletteValue);
|
||||
}
|
||||
}
|
||||
|
||||
final long[] data = blocksId;
|
||||
writeVarIntBuf(buffer, data.length);
|
||||
for (long datum : data) {
|
||||
buffer.writeLong(datum);
|
||||
}
|
||||
}
|
||||
|
||||
private static final int[] MAGIC = {
|
||||
-1, -1, 0, Integer.MIN_VALUE, 0, 0, 1431655765, 1431655765, 0, Integer.MIN_VALUE,
|
||||
0, 1, 858993459, 858993459, 0, 715827882, 715827882, 0, 613566756, 613566756,
|
||||
@ -116,69 +140,6 @@ public final class Utils {
|
||||
70409299, 70409299, 0, 69273666, 69273666, 0, 68174084, 68174084, 0, Integer.MIN_VALUE,
|
||||
0, 5};
|
||||
|
||||
public static void writeBlocks(ByteBuf buffer, short[] palette, long[] blocksId, int bitsPerEntry) {
|
||||
/*short count = 0;
|
||||
for (short id : blocksId)
|
||||
if (id != 0)
|
||||
count++;*/
|
||||
|
||||
//buffer.writeShort(count);
|
||||
buffer.writeShort(200);
|
||||
buffer.writeByte((byte) bitsPerEntry);
|
||||
|
||||
// Palette
|
||||
if (bitsPerEntry < 9) {
|
||||
// Palette has to exist
|
||||
writeVarIntBuf(buffer, palette.length);
|
||||
for (short paletteValue : palette) {
|
||||
writeVarIntBuf(buffer, paletteValue);
|
||||
}
|
||||
}
|
||||
|
||||
final long[] data = blocksId;//encodeBlocksTEST(bitsPerEntry);
|
||||
writeVarIntBuf(buffer, data.length);
|
||||
for (long datum : data) {
|
||||
buffer.writeLong(datum);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized static long[] encodeBlocksTEST(int bitsPerEntry) {
|
||||
//long test = (Block.TORCH.getBlockId() << (64 - 50 - bitsPerEntry + 1));
|
||||
//System.out.println("BINARY: 0b" + Long.toBinaryString(test) + " " + (64 - 50 - bitsPerEntry + 1));
|
||||
final int blockCount = 16 * 16 * 16; // A whole chunk section
|
||||
final int longSize = Long.SIZE; // 64
|
||||
final char valuesPerLong = (char) (longSize / bitsPerEntry);
|
||||
final int arraySize = blockCount / valuesPerLong;
|
||||
|
||||
long[] data = new long[arraySize];
|
||||
data[0] = 0b000000010001L;
|
||||
data[1] = 0b000000010001L;
|
||||
|
||||
if (true) {
|
||||
return data;
|
||||
}
|
||||
|
||||
for (int y = 0; y < Chunk.CHUNK_SECTION_SIZE; y++) {
|
||||
for (int x = 0; x < Chunk.CHUNK_SIZE_X; x++) {
|
||||
for (int z = 0; z < Chunk.CHUNK_SIZE_Z; z++) {
|
||||
final long blockId = x % 2 == 0 && z % 2 == 0 ? Block.AIR.getBlockId() : Block.LAVA.getBlockId();
|
||||
int sectionIndex = (((y * 16) + z) * 16) + x;
|
||||
|
||||
final int index = sectionIndex / valuesPerLong;
|
||||
final int bitIndex = sectionIndex % valuesPerLong * bitsPerEntry;
|
||||
|
||||
data[index] |= (blockId << bitIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
private static String binary(long value) {
|
||||
return "0b" + Long.toBinaryString(value);
|
||||
}
|
||||
|
||||
public static long[] encodeBlocks(int[] blocks, int bitsPerEntry) {
|
||||
final long maxEntryValue = (1L << bitsPerEntry) - 1;
|
||||
final char valuesPerLong = (char) (64 / bitsPerEntry);
|
||||
|
Loading…
Reference in New Issue
Block a user