mirror of
https://github.com/Minestom/Minestom.git
synced 2024-12-27 19:47:44 +01:00
Added CachedObject to access a single-object cache
This commit is contained in:
parent
14b59d6a04
commit
1c39e06d55
@ -16,6 +16,7 @@ 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.cache.CachedObject;
|
||||
import net.minestom.server.utils.callback.OptionalCallback;
|
||||
import net.minestom.server.utils.chunk.ChunkCallback;
|
||||
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||
@ -26,7 +27,6 @@ import net.minestom.server.world.biomes.Biome;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@ -60,8 +60,7 @@ public class DynamicChunk extends Chunk {
|
||||
|
||||
private long lastChangeTime;
|
||||
|
||||
private SoftReference<ChunkDataPacket> cachedPacket = new SoftReference<>(null);
|
||||
private long cachedPacketTime;
|
||||
private CachedObject<ChunkDataPacket> cachedPacket = new CachedObject<>();
|
||||
|
||||
public DynamicChunk(@NotNull Instance instance, @Nullable Biome[] biomes, int chunkX, int chunkZ,
|
||||
@NotNull PaletteStorage blockPalette, @NotNull PaletteStorage customBlockPalette) {
|
||||
@ -387,22 +386,17 @@ public class DynamicChunk extends Chunk {
|
||||
@NotNull
|
||||
@Override
|
||||
protected ChunkDataPacket createFreshPacket() {
|
||||
ChunkDataPacket packet = cachedPacket.get();
|
||||
if (packet != null && cachedPacketTime == getLastChangeTime()) {
|
||||
return packet;
|
||||
}
|
||||
packet = new ChunkDataPacket(getIdentifier(), getLastChangeTime());
|
||||
packet.biomes = biomes;
|
||||
packet.chunkX = chunkX;
|
||||
packet.chunkZ = chunkZ;
|
||||
packet.paletteStorage = blockPalette.clone();
|
||||
packet.customBlockPaletteStorage = customBlockPalette.clone();
|
||||
packet.blockEntities = blockEntities.clone();
|
||||
packet.blocksData = blocksData.clone();
|
||||
|
||||
this.cachedPacketTime = getLastChangeTime();
|
||||
this.cachedPacket = new SoftReference<>(packet);
|
||||
return packet;
|
||||
return cachedPacket.getUpdatedCache(() -> {
|
||||
ChunkDataPacket chunkDataPacket = new ChunkDataPacket(getIdentifier(), getLastChangeTime());
|
||||
chunkDataPacket.biomes = biomes;
|
||||
chunkDataPacket.chunkX = chunkX;
|
||||
chunkDataPacket.chunkZ = chunkZ;
|
||||
chunkDataPacket.paletteStorage = blockPalette.clone();
|
||||
chunkDataPacket.customBlockPaletteStorage = customBlockPalette.clone();
|
||||
chunkDataPacket.blockEntities = blockEntities.clone();
|
||||
chunkDataPacket.blocksData = blocksData.clone();
|
||||
return chunkDataPacket;
|
||||
}, getLastChangeTime());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
@ -6,6 +6,7 @@ import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.item.attribute.ItemAttribute;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import net.minestom.server.utils.binary.Writeable;
|
||||
import net.minestom.server.utils.cache.CachedObject;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@ -33,8 +34,8 @@ public class ItemMeta implements Writeable {
|
||||
private final NBTCompound nbt;
|
||||
private final ItemMetaBuilder emptyBuilder;
|
||||
|
||||
private String cachedSNBT;
|
||||
private ByteBuf cachedBuffer;
|
||||
private CachedObject<String> cachedSNBT = new CachedObject<>();
|
||||
private CachedObject<ByteBuf> cachedBuffer = new CachedObject<>();
|
||||
|
||||
protected ItemMeta(@NotNull ItemMetaBuilder metaBuilder) {
|
||||
this.damage = metaBuilder.damage;
|
||||
@ -128,10 +129,7 @@ public class ItemMeta implements Writeable {
|
||||
}
|
||||
|
||||
public @NotNull String toSNBT() {
|
||||
if (cachedSNBT == null) {
|
||||
this.cachedSNBT = nbt.toSNBT();
|
||||
}
|
||||
return cachedSNBT;
|
||||
return cachedSNBT.getCache(nbt::toSNBT);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -155,12 +153,12 @@ public class ItemMeta implements Writeable {
|
||||
|
||||
@Override
|
||||
public synchronized void write(@NotNull BinaryWriter writer) {
|
||||
if (cachedBuffer == null) {
|
||||
final var buffer = cachedBuffer.getCache(() -> {
|
||||
BinaryWriter w = new BinaryWriter();
|
||||
w.writeNBT("", nbt);
|
||||
this.cachedBuffer = w.getBuffer();
|
||||
}
|
||||
writer.write(cachedBuffer);
|
||||
this.cachedBuffer.resetReaderIndex();
|
||||
return w.getBuffer();
|
||||
});
|
||||
writer.write(buffer);
|
||||
buffer.resetReaderIndex();
|
||||
}
|
||||
}
|
||||
|
69
src/main/java/net/minestom/server/utils/cache/CachedObject.java
vendored
Normal file
69
src/main/java/net/minestom/server/utils/cache/CachedObject.java
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
package net.minestom.server.utils.cache;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Represents a single that can be collected by the garbage collector
|
||||
* depending on memory demand.
|
||||
*
|
||||
* @param <T> the object to cache
|
||||
*/
|
||||
@Beta
|
||||
public class CachedObject<T> extends SoftReference<AtomicReference<T>> {
|
||||
|
||||
private long cacheTime;
|
||||
|
||||
public CachedObject() {
|
||||
super(new AtomicReference<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the cache.
|
||||
*
|
||||
* @param supplier supplier for the value if absent
|
||||
* @return the cache
|
||||
*/
|
||||
public @NotNull T getCache(@NotNull Supplier<@NotNull T> supplier) {
|
||||
var referent = get();
|
||||
assert referent != null;
|
||||
var value = referent.get();
|
||||
if (value == null) {
|
||||
value = supplier.get();
|
||||
referent.set(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the cache, and ensure that the value is up-to-date.
|
||||
*
|
||||
* @param supplier supplier for the value if absent or outdated
|
||||
* @param lastUpdate the required internal timestamp, supplier will be called otherwise
|
||||
* @return the cache
|
||||
*/
|
||||
public @NotNull T getUpdatedCache(@NotNull Supplier<@NotNull T> supplier, long lastUpdate) {
|
||||
var referent = get();
|
||||
assert referent != null;
|
||||
var value = referent.get();
|
||||
if (value == null || cacheTime != lastUpdate) {
|
||||
value = supplier.get();
|
||||
this.cacheTime = lastUpdate;
|
||||
referent.set(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #getCache(Supplier)}
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public AtomicReference<T> get() {
|
||||
return super.get();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user