2020-05-04 18:18:50 +02:00
|
|
|
package net.minestom.server.storage;
|
|
|
|
|
|
|
|
import io.netty.buffer.Unpooled;
|
2020-05-08 16:15:08 +02:00
|
|
|
import net.minestom.server.MinecraftServer;
|
2020-05-04 18:18:50 +02:00
|
|
|
import net.minestom.server.data.DataContainer;
|
2020-05-08 16:15:08 +02:00
|
|
|
import net.minestom.server.data.DataManager;
|
|
|
|
import net.minestom.server.data.DataType;
|
2020-05-04 18:18:50 +02:00
|
|
|
import net.minestom.server.data.SerializableData;
|
2020-05-08 16:15:08 +02:00
|
|
|
import net.minestom.server.network.packet.PacketReader;
|
|
|
|
import net.minestom.server.network.packet.PacketWriter;
|
2020-05-04 18:18:50 +02:00
|
|
|
import net.minestom.server.reader.DataReader;
|
|
|
|
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.Map;
|
|
|
|
|
|
|
|
public class StorageFolder {
|
|
|
|
|
2020-05-08 16:15:08 +02:00
|
|
|
private static final DataManager DATA_MANAGER = MinecraftServer.getDataManager();
|
|
|
|
|
2020-05-04 18:18:50 +02:00
|
|
|
private StorageSystem storageSystem;
|
|
|
|
private String folderPath;
|
|
|
|
|
|
|
|
private Map<String, SerializableData> cachedData;
|
|
|
|
|
|
|
|
protected StorageFolder(StorageSystem storageSystem, String folderPath) {
|
|
|
|
this.storageSystem = storageSystem;
|
|
|
|
this.folderPath = folderPath;
|
|
|
|
|
|
|
|
this.cachedData = new HashMap<>();
|
|
|
|
|
|
|
|
this.storageSystem.open(folderPath);
|
|
|
|
}
|
|
|
|
|
2020-05-08 16:15:08 +02:00
|
|
|
public byte[] get(String key) {
|
|
|
|
return storageSystem.get(key);
|
2020-05-04 18:18:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public void set(String key, byte[] data) {
|
|
|
|
this.storageSystem.set(key, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void delete(String key) {
|
|
|
|
this.storageSystem.delete(key);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void close() {
|
|
|
|
this.storageSystem.close();
|
|
|
|
}
|
|
|
|
|
2020-05-08 16:15:08 +02:00
|
|
|
public <T> void set(String key, T object, Class<T> type) {
|
|
|
|
DataType<T> dataType = DATA_MANAGER.getDataType(type);
|
|
|
|
if (dataType == null)
|
|
|
|
throw new NullPointerException("You can only save registered DataType type!");
|
2020-05-16 22:07:24 +02:00
|
|
|
|
2020-05-08 16:15:08 +02:00
|
|
|
PacketWriter packetWriter = new PacketWriter();
|
|
|
|
dataType.encode(packetWriter, object); // Encode
|
|
|
|
byte[] encodedValue = packetWriter.toByteArray(); // Retrieve bytes
|
|
|
|
|
|
|
|
set(key, encodedValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
public <T> T get(String key, Class<T> type) {
|
|
|
|
DataType<T> dataType = DATA_MANAGER.getDataType(type);
|
|
|
|
if (dataType == null)
|
|
|
|
throw new NullPointerException("You can only save registered DataType type!");
|
|
|
|
|
2020-05-16 22:07:24 +02:00
|
|
|
byte[] data = get(key);
|
|
|
|
if (data == null)
|
|
|
|
return null;
|
|
|
|
|
2020-05-19 17:47:47 +02:00
|
|
|
PacketReader packetReader = new PacketReader(data);
|
2020-05-08 18:11:06 +02:00
|
|
|
T value = dataType.decode(packetReader);
|
2020-05-08 16:15:08 +02:00
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2020-05-16 22:07:24 +02:00
|
|
|
public <T> T getOrDefault(String key, Class<T> type, T defaultValue) {
|
|
|
|
T value;
|
|
|
|
return (value = get(key, type)) != null ? value : defaultValue;
|
|
|
|
}
|
|
|
|
|
2020-05-17 04:13:24 +02:00
|
|
|
/**
|
|
|
|
* Get an unique {@link SerializableData} which is cloned if cached or retrieved with the default {@link StorageSystem}
|
|
|
|
*
|
|
|
|
* @param key the key of the data
|
|
|
|
* @param dataContainer the {@link DataContainer} which will contain the new data
|
|
|
|
*/
|
2020-05-08 16:15:08 +02:00
|
|
|
public void getAndCloneData(String key, DataContainer dataContainer) {
|
2020-05-04 19:35:52 +02:00
|
|
|
synchronized (cachedData) {
|
|
|
|
|
|
|
|
// Copy data from the cachedMap
|
|
|
|
if (cachedData.containsKey(key)) {
|
|
|
|
SerializableData data = cachedData.get(key);
|
|
|
|
dataContainer.setData(data.clone());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Load it from the storage system
|
2020-05-08 16:15:08 +02:00
|
|
|
byte[] bytes = get(key);
|
|
|
|
SerializableData data;
|
2020-05-04 19:35:52 +02:00
|
|
|
|
2020-05-08 16:15:08 +02:00
|
|
|
if (bytes != null) {
|
|
|
|
data = DataReader.readData(Unpooled.wrappedBuffer(bytes));
|
|
|
|
} else {
|
|
|
|
data = new SerializableData();
|
|
|
|
}
|
2020-05-04 19:35:52 +02:00
|
|
|
|
2020-05-08 16:15:08 +02:00
|
|
|
dataContainer.setData(data);
|
2020-05-04 19:35:52 +02:00
|
|
|
|
2020-05-04 19:09:34 +02:00
|
|
|
}
|
2020-05-04 19:35:52 +02:00
|
|
|
}
|
2020-05-04 19:09:34 +02:00
|
|
|
|
2020-05-17 04:13:24 +02:00
|
|
|
/**
|
|
|
|
* Get a shared {@link SerializableData} if already in memory or retrieve it from the default {@link StorageSystem} and save it in cache
|
|
|
|
* for further request.
|
|
|
|
* Those cached data can be saved using {@link #saveCachedData()} or individually with {@link #saveCachedData(String)}
|
|
|
|
* It is also possible to save an individual data and remove it directly with {@link #saveAndRemoveCachedData(String)}
|
|
|
|
*
|
|
|
|
* @param key the key of the data
|
|
|
|
* @param dataContainer the {@link DataContainer} which will contain the new data
|
|
|
|
*/
|
2020-05-08 16:15:08 +02:00
|
|
|
public void getAndCacheData(String key, DataContainer dataContainer) {
|
2020-05-04 19:35:52 +02:00
|
|
|
synchronized (cachedData) {
|
2020-05-04 18:18:50 +02:00
|
|
|
|
2020-05-04 19:35:52 +02:00
|
|
|
// Give the cached SerializableData if already loaded
|
|
|
|
if (cachedData.containsKey(key)) {
|
|
|
|
dataContainer.setData(cachedData.get(key));
|
|
|
|
return;
|
2020-05-04 18:18:50 +02:00
|
|
|
}
|
|
|
|
|
2020-05-04 19:35:52 +02:00
|
|
|
// Load it from the storage system and cache it
|
2020-05-08 16:15:08 +02:00
|
|
|
byte[] bytes = get(key);
|
|
|
|
SerializableData data;
|
2020-05-04 18:18:50 +02:00
|
|
|
|
2020-05-08 16:15:08 +02:00
|
|
|
if (bytes != null) {
|
|
|
|
data = DataReader.readData(Unpooled.wrappedBuffer(bytes));
|
|
|
|
} else {
|
|
|
|
data = new SerializableData();
|
|
|
|
}
|
2020-05-04 19:09:34 +02:00
|
|
|
|
2020-05-08 16:15:08 +02:00
|
|
|
dataContainer.setData(data);
|
2020-05-04 19:35:52 +02:00
|
|
|
|
2020-05-08 16:15:08 +02:00
|
|
|
this.cachedData.put(key, data);
|
2020-05-04 19:35:52 +02:00
|
|
|
|
|
|
|
}
|
2020-05-04 18:18:50 +02:00
|
|
|
}
|
|
|
|
|
2020-05-17 04:13:24 +02:00
|
|
|
/**
|
|
|
|
* Save a specified cached data and remove it from memory
|
|
|
|
*
|
|
|
|
* @param key the specified cached data key
|
|
|
|
*/
|
|
|
|
public void saveAndRemoveCachedData(String key) {
|
2020-05-17 11:40:49 +02:00
|
|
|
synchronized (cachedData) {
|
|
|
|
SerializableData serializableData = cachedData.get(key);
|
|
|
|
if (serializableData == null)
|
|
|
|
return;
|
2020-05-17 04:13:24 +02:00
|
|
|
|
2020-05-17 11:40:49 +02:00
|
|
|
try {
|
|
|
|
set(key, serializableData.getSerializedData());
|
|
|
|
} catch (IOException e) {
|
|
|
|
e.printStackTrace();
|
|
|
|
}
|
2020-05-17 04:13:24 +02:00
|
|
|
|
2020-05-17 11:40:49 +02:00
|
|
|
// Remove from map
|
|
|
|
this.cachedData.remove(key);
|
|
|
|
}
|
2020-05-17 04:13:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Save the whole cached data
|
|
|
|
*/
|
2020-05-04 18:18:50 +02:00
|
|
|
public void saveCachedData() {
|
|
|
|
try {
|
2020-05-04 19:35:52 +02:00
|
|
|
synchronized (cachedData) {
|
|
|
|
for (Map.Entry<String, SerializableData> entry : cachedData.entrySet()) {
|
|
|
|
String key = entry.getKey();
|
|
|
|
SerializableData data = entry.getValue();
|
2020-05-04 18:18:50 +02:00
|
|
|
|
2020-05-04 19:35:52 +02:00
|
|
|
set(key, data.getSerializedData());
|
|
|
|
}
|
2020-05-04 18:18:50 +02:00
|
|
|
}
|
|
|
|
} catch (IOException e) {
|
|
|
|
e.printStackTrace();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-17 04:13:24 +02:00
|
|
|
/**
|
|
|
|
* Save an unique cached data
|
|
|
|
*
|
|
|
|
* @param key the data key
|
|
|
|
*/
|
|
|
|
public void saveCachedData(String key) {
|
|
|
|
try {
|
|
|
|
synchronized (cachedData) {
|
|
|
|
SerializableData data = cachedData.get(key);
|
|
|
|
set(key, data.getSerializedData());
|
|
|
|
}
|
|
|
|
} catch (IOException e) {
|
|
|
|
e.printStackTrace();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-04 18:18:50 +02:00
|
|
|
public String getFolderPath() {
|
|
|
|
return folderPath;
|
|
|
|
}
|
|
|
|
}
|