*WIP* Prepared Folder Syncing - Filelist exchange
This commit is contained in:
parent
5df6de1e3a
commit
1f239baeb9
9 changed files with 323 additions and 190 deletions
|
@ -11,7 +11,7 @@ loader_version= 0.11.6
|
||||||
fabric_version = 0.36.1+1.17
|
fabric_version = 0.36.1+1.17
|
||||||
|
|
||||||
# Mod Properties
|
# Mod Properties
|
||||||
mod_version = 0.4.0
|
mod_version = 0.4.1
|
||||||
maven_group = ru.bclib
|
maven_group = ru.bclib
|
||||||
archives_base_name = bclib
|
archives_base_name = bclib
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@ public class BCLib implements ModInitializer {
|
||||||
TagAPI.init();
|
TagAPI.init();
|
||||||
CraftingRecipes.init();
|
CraftingRecipes.init();
|
||||||
WorldDataAPI.registerModCache(MOD_ID);
|
WorldDataAPI.registerModCache(MOD_ID);
|
||||||
|
DataExchangeAPI.registerMod(MOD_ID);
|
||||||
DataFixerAPI.registerPatch(() -> new BCLibPatch());
|
DataFixerAPI.registerPatch(() -> new BCLibPatch());
|
||||||
DataExchangeAPI.registerDescriptors(List.of(
|
DataExchangeAPI.registerDescriptors(List.of(
|
||||||
HelloClient.DESCRIPTOR,
|
HelloClient.DESCRIPTOR,
|
||||||
|
|
|
@ -8,7 +8,6 @@ import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.nbt.NbtIo;
|
import net.minecraft.nbt.NbtIo;
|
||||||
import net.minecraft.world.level.storage.LevelStorageSource.LevelStorageAccess;
|
import net.minecraft.world.level.storage.LevelStorageSource.LevelStorageAccess;
|
||||||
import ru.bclib.BCLib;
|
import ru.bclib.BCLib;
|
||||||
import ru.bclib.api.dataexchange.DataExchangeAPI;
|
|
||||||
import ru.bclib.api.datafixer.DataFixerAPI;
|
import ru.bclib.api.datafixer.DataFixerAPI;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -20,8 +19,8 @@ import java.util.function.Consumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mod-specifix data-storage for a world.
|
* Mod-specifix data-storage for a world.
|
||||||
*
|
* <p>
|
||||||
* This class provides the ability for mod to store persistent data inside a world. The Storage for the world is
|
* This class provides the ability for mod to store persistent data inside a world. The Storage for the world is
|
||||||
* currently initialized as part of the {@link DataFixerAPI} in {@link DataFixerAPI#fixData(LevelStorageAccess, boolean, Consumer)}
|
* currently initialized as part of the {@link DataFixerAPI} in {@link DataFixerAPI#fixData(LevelStorageAccess, boolean, Consumer)}
|
||||||
* or {@link DataFixerAPI#initializeWorldData(File, boolean)}
|
* or {@link DataFixerAPI#initializeWorldData(File, boolean)}
|
||||||
*/
|
*/
|
||||||
|
@ -32,45 +31,47 @@ public class WorldDataAPI {
|
||||||
|
|
||||||
public static void load(File dataDir) {
|
public static void load(File dataDir) {
|
||||||
WorldDataAPI.dataDir = dataDir;
|
WorldDataAPI.dataDir = dataDir;
|
||||||
MODS.stream().parallel().forEach(modID -> {
|
MODS.stream()
|
||||||
File file = new File(dataDir, modID + ".nbt");
|
.parallel()
|
||||||
CompoundTag root = new CompoundTag();
|
.forEach(modID -> {
|
||||||
if (file.exists()) {
|
File file = new File(dataDir, modID + ".nbt");
|
||||||
try {
|
CompoundTag root = new CompoundTag();
|
||||||
root = NbtIo.readCompressed(file);
|
if (file.exists()) {
|
||||||
}
|
try {
|
||||||
catch (IOException e) {
|
root = NbtIo.readCompressed(file);
|
||||||
BCLib.LOGGER.error("World data loading failed", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Optional<ModContainer> optional = FabricLoader.getInstance().getModContainer(modID);
|
|
||||||
if (optional.isPresent()) {
|
|
||||||
ModContainer modContainer = optional.get();
|
|
||||||
if (BCLib.isDevEnvironment()) {
|
|
||||||
root.putString("version", "255.255.9999");
|
|
||||||
}
|
}
|
||||||
else {
|
catch (IOException e) {
|
||||||
root.putString("version", modContainer.getMetadata().getVersion().toString());
|
BCLib.LOGGER.error("World data loading failed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Optional<ModContainer> optional = FabricLoader.getInstance()
|
||||||
|
.getModContainer(modID);
|
||||||
|
if (optional.isPresent()) {
|
||||||
|
ModContainer modContainer = optional.get();
|
||||||
|
if (BCLib.isDevEnvironment()) {
|
||||||
|
root.putString("version", "255.255.9999");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
root.putString("version", modContainer.getMetadata()
|
||||||
|
.getVersion()
|
||||||
|
.toString());
|
||||||
|
}
|
||||||
|
saveFile(modID);
|
||||||
}
|
}
|
||||||
saveFile(modID);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
TAGS.put(modID, root);
|
TAGS.put(modID, root);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register mod cache, world cache is located in world data folder.
|
* Register mod cache, world cache is located in world data folder.
|
||||||
* <p>
|
|
||||||
* Will also register the Mod for the {@link DataExchangeAPI} using {@link DataExchangeAPI#registerMod(String)}
|
|
||||||
*
|
*
|
||||||
* @param modID - {@link String} modID.
|
* @param modID - {@link String} modID.
|
||||||
*/
|
*/
|
||||||
public static void registerModCache(String modID) {
|
public static void registerModCache(String modID) {
|
||||||
MODS.add(modID);
|
MODS.add(modID);
|
||||||
DataExchangeAPI.registerMod(modID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -117,7 +118,7 @@ public class WorldDataAPI {
|
||||||
*/
|
*/
|
||||||
public static void saveFile(String modID) {
|
public static void saveFile(String modID) {
|
||||||
try {
|
try {
|
||||||
if (!dataDir.exists()){
|
if (!dataDir.exists()) {
|
||||||
dataDir.mkdirs();
|
dataDir.mkdirs();
|
||||||
}
|
}
|
||||||
NbtIo.writeCompressed(getRootTag(modID), new File(dataDir, modID + ".nbt"));
|
NbtIo.writeCompressed(getRootTag(modID), new File(dataDir, modID + ".nbt"));
|
||||||
|
|
|
@ -13,157 +13,181 @@ import java.util.List;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
public class DataExchangeAPI extends DataExchange {
|
public class DataExchangeAPI extends DataExchange {
|
||||||
private final static List<String> MODS = Lists.newArrayList();
|
private final static List<String> MODS = Lists.newArrayList();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* You should never need to create a custom instance of this Object.
|
* You should never need to create a custom instance of this Object.
|
||||||
*/
|
*/
|
||||||
public DataExchangeAPI() {
|
public DataExchangeAPI() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Environment(EnvType.CLIENT)
|
@Environment(EnvType.CLIENT)
|
||||||
protected ConnectorClientside clientSupplier(DataExchange api) {
|
protected ConnectorClientside clientSupplier(DataExchange api) {
|
||||||
return new ConnectorClientside(api);
|
return new ConnectorClientside(api);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ConnectorServerside serverSupplier(DataExchange api) {
|
protected ConnectorServerside serverSupplier(DataExchange api) {
|
||||||
return new ConnectorServerside(api);
|
return new ConnectorServerside(api);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a mod to participate in the DataExchange.
|
* Register a mod to participate in the DataExchange.
|
||||||
*
|
*
|
||||||
* @param modID - {@link String} modID.
|
* @param modID - {@link String} modID.
|
||||||
*/
|
*/
|
||||||
public static void registerMod(String modID) {
|
public static void registerMod(String modID) {
|
||||||
if (!MODS.contains(modID))
|
if (!MODS.contains(modID)) MODS.add(modID);
|
||||||
MODS.add(modID);
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
/**
|
* Returns the IDs of all registered Mods.
|
||||||
* Returns the IDs of all registered Mods.
|
*
|
||||||
*
|
* @return List of modIDs
|
||||||
* @return List of modIDs
|
*/
|
||||||
*/
|
public static List<String> registeredMods() {
|
||||||
public static List<String> registeredMods() {
|
return MODS;
|
||||||
return MODS;
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
/**
|
* Add a new Descriptor for a {@link DataHandler}.
|
||||||
* Add a new Descriptor for a {@link DataHandler}.
|
*
|
||||||
*
|
* @param desc The Descriptor you want to add.
|
||||||
* @param desc The Descriptor you want to add.
|
*/
|
||||||
*/
|
public static void registerDescriptor(DataHandlerDescriptor desc) {
|
||||||
public static void registerDescriptor(DataHandlerDescriptor desc) {
|
DataExchange api = DataExchange.getInstance();
|
||||||
DataExchange api = DataExchange.getInstance();
|
api.getDescriptors()
|
||||||
api.getDescriptors().add(desc);
|
.add(desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bulk-Add a Descriptors for your {@link DataHandler}-Objects.
|
* Bulk-Add a Descriptors for your {@link DataHandler}-Objects.
|
||||||
*
|
*
|
||||||
* @param desc The Descriptors you want to add.
|
* @param desc The Descriptors you want to add.
|
||||||
*/
|
*/
|
||||||
public static void registerDescriptors(List<DataHandlerDescriptor> desc) {
|
public static void registerDescriptors(List<DataHandlerDescriptor> desc) {
|
||||||
DataExchange api = DataExchange.getInstance();
|
DataExchange api = DataExchange.getInstance();
|
||||||
api.getDescriptors().addAll(desc);
|
api.getDescriptors()
|
||||||
}
|
.addAll(desc);
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Sends the Handler.
|
/**
|
||||||
* <p>
|
* Sends the Handler.
|
||||||
* Depending on what the result of {@link DataHandler#getOriginatesOnServer()}, the Data is sent from the server
|
* <p>
|
||||||
* to the client (if {@code true}) or the other way around.
|
* Depending on what the result of {@link DataHandler#getOriginatesOnServer()}, the Data is sent from the server
|
||||||
* <p>
|
* to the client (if {@code true}) or the other way around.
|
||||||
* The method {@link DataHandler#serializeData(FriendlyByteBuf)} is called just before the data is sent. You should
|
* <p>
|
||||||
* use this method to add the Data you need to the communication.
|
* The method {@link DataHandler#serializeData(FriendlyByteBuf)} is called just before the data is sent. You should
|
||||||
*
|
* use this method to add the Data you need to the communication.
|
||||||
* @param h The Data that you want to send
|
*
|
||||||
*/
|
* @param h The Data that you want to send
|
||||||
public static void send(DataHandler h) {
|
*/
|
||||||
if (h.getOriginatesOnServer()) {
|
public static void send(DataHandler h) {
|
||||||
DataExchangeAPI.getInstance().server.sendToClient(h);
|
if (h.getOriginatesOnServer()) {
|
||||||
} else {
|
DataExchangeAPI.getInstance().server.sendToClient(h);
|
||||||
DataExchangeAPI.getInstance().client.sendToServer(h);
|
}
|
||||||
}
|
else {
|
||||||
}
|
DataExchangeAPI.getInstance().client.sendToServer(h);
|
||||||
|
}
|
||||||
/**
|
}
|
||||||
* Registers a File for automatic client syncing.
|
|
||||||
*
|
/**
|
||||||
* @param modID The ID of the calling Mod
|
* Registers a File for automatic client syncing.
|
||||||
* @param fileName The name of the File
|
*
|
||||||
*/
|
* @param modID The ID of the calling Mod
|
||||||
public static void addAutoSyncFile(String modID, File fileName) {
|
* @param fileName The name of the File
|
||||||
getInstance().addAutoSyncFileData(modID, fileName, false, FileHash.NEED_TRANSFER);
|
*/
|
||||||
}
|
public static void addAutoSyncFile(String modID, File fileName) {
|
||||||
|
getInstance().addAutoSyncFileData(modID, fileName, false, FileHash.NEED_TRANSFER);
|
||||||
/**
|
}
|
||||||
* Registers a File for automatic client syncing.
|
|
||||||
* <p>
|
/**
|
||||||
* The file is synced of the {@link FileHash} on client and server are not equal. This method will not copy the
|
* Registers a File for automatic client syncing.
|
||||||
* configs content from the client to the server.
|
* <p>
|
||||||
*
|
* The file is synced of the {@link FileHash} on client and server are not equal. This method will not copy the
|
||||||
* @param modID The ID of the calling Mod
|
* configs content from the client to the server.
|
||||||
* @param uniqueID A unique Identifier for the File. (see {@link ru.bclib.api.dataexchange.FileHash#uniqueID} for
|
*
|
||||||
* Details
|
* @param modID The ID of the calling Mod
|
||||||
* @param fileName The name of the File
|
* @param uniqueID A unique Identifier for the File. (see {@link ru.bclib.api.dataexchange.FileHash#uniqueID} for
|
||||||
*/
|
* Details
|
||||||
public static void addAutoSyncFile(String modID, String uniqueID, File fileName) {
|
* @param fileName The name of the File
|
||||||
getInstance().addAutoSyncFileData(modID, uniqueID, fileName, false, FileHash.NEED_TRANSFER);
|
*/
|
||||||
}
|
public static void addAutoSyncFile(String modID, String uniqueID, File fileName) {
|
||||||
|
getInstance().addAutoSyncFileData(modID, uniqueID, fileName, false, FileHash.NEED_TRANSFER);
|
||||||
/**
|
}
|
||||||
* Registers a File for automatic client syncing.
|
|
||||||
* <p>
|
/**
|
||||||
* The content of the file is requested for comparison. This will copy the
|
* Registers a File for automatic client syncing.
|
||||||
* entire file from the client to the server.
|
* <p>
|
||||||
* <p>
|
* The content of the file is requested for comparison. This will copy the
|
||||||
* You should only use this option, if you need to compare parts of the file in order to decide
|
* entire file from the client to the server.
|
||||||
* if the File needs to be copied. Normally using the {@link ru.bclib.api.dataexchange.FileHash}
|
* <p>
|
||||||
* for comparison is sufficient.
|
* You should only use this option, if you need to compare parts of the file in order to decide
|
||||||
*
|
* if the File needs to be copied. Normally using the {@link ru.bclib.api.dataexchange.FileHash}
|
||||||
* @param modID The ID of the calling Mod
|
* for comparison is sufficient.
|
||||||
* @param fileName The name of the File
|
*
|
||||||
* @param needTransfer If the predicate returns true, the file needs to get copied to the server.
|
* @param modID The ID of the calling Mod
|
||||||
*/
|
* @param fileName The name of the File
|
||||||
public static void addAutoSyncFile(String modID, File fileName, NeedTransferPredicate needTransfer) {
|
* @param needTransfer If the predicate returns true, the file needs to get copied to the server.
|
||||||
getInstance().addAutoSyncFileData(modID, fileName, true, needTransfer);
|
*/
|
||||||
}
|
public static void addAutoSyncFile(String modID, File fileName, NeedTransferPredicate needTransfer) {
|
||||||
|
getInstance().addAutoSyncFileData(modID, fileName, true, needTransfer);
|
||||||
/**
|
}
|
||||||
* Registers a File for automatic client syncing.
|
|
||||||
* <p>
|
/**
|
||||||
* The content of the file is requested for comparison. This will copy the
|
* Registers a File for automatic client syncing.
|
||||||
* entire file from the client to the server.
|
* <p>
|
||||||
* <p>
|
* The content of the file is requested for comparison. This will copy the
|
||||||
* You should only use this option, if you need to compare parts of the file in order to decide
|
* entire file from the client to the server.
|
||||||
* if the File needs to be copied. Normally using the {@link ru.bclib.api.dataexchange.FileHash}
|
* <p>
|
||||||
* for comparison is sufficient.
|
* You should only use this option, if you need to compare parts of the file in order to decide
|
||||||
*
|
* if the File needs to be copied. Normally using the {@link ru.bclib.api.dataexchange.FileHash}
|
||||||
* @param modID The ID of the calling Mod
|
* for comparison is sufficient.
|
||||||
* @param uniqueID A unique Identifier for the File. (see {@link ru.bclib.api.dataexchange.FileHash#uniqueID} for
|
*
|
||||||
* Details
|
* @param modID The ID of the calling Mod
|
||||||
* @param fileName The name of the File
|
* @param uniqueID A unique Identifier for the File. (see {@link ru.bclib.api.dataexchange.FileHash#uniqueID} for
|
||||||
* @param needTransfer If the predicate returns true, the file needs to get copied to the server.
|
* Details
|
||||||
*/
|
* @param fileName The name of the File
|
||||||
public static void addAutoSyncFile(String modID, String uniqueID, File fileName, NeedTransferPredicate needTransfer) {
|
* @param needTransfer If the predicate returns true, the file needs to get copied to the server.
|
||||||
getInstance().addAutoSyncFileData(modID, uniqueID, fileName, true, needTransfer);
|
*/
|
||||||
}
|
public static void addAutoSyncFile(String modID, String uniqueID, File fileName, NeedTransferPredicate needTransfer) {
|
||||||
|
getInstance().addAutoSyncFileData(modID, uniqueID, fileName, true, needTransfer);
|
||||||
/**
|
}
|
||||||
* Register a function that is called whenever the client receives a file from the server and replaced toe local
|
|
||||||
* file with the new content.
|
/**
|
||||||
* <p>
|
* Register a function that is called whenever the client receives a file from the server and replaced toe local
|
||||||
* This callback is usefull if you need to reload the new content before the game is quit.
|
* file with the new content.
|
||||||
* @param callback A Function that receives the AutoSyncID as well as the Filename.
|
* <p>
|
||||||
*/
|
* This callback is usefull if you need to reload the new content before the game is quit.
|
||||||
public static void addOnWriteCallback(BiConsumer<AutoSyncID, File> callback) {
|
*
|
||||||
onWriteCallbacks.add(callback);
|
* @param callback A Function that receives the AutoSyncID as well as the Filename.
|
||||||
}
|
*/
|
||||||
|
public static void addOnWriteCallback(BiConsumer<AutoSyncID, File> callback) {
|
||||||
static {
|
onWriteCallbacks.add(callback);
|
||||||
addOnWriteCallback(Config::reloadSyncedConfig);
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* Returns the sync-folder for a given Mod.
|
||||||
|
* <p>
|
||||||
|
* BCLib will ensure that the contents of sync-folder on the client is the same as the one on the server.
|
||||||
|
*
|
||||||
|
* @param modID ID of the Mod
|
||||||
|
* @return The path to the sync-folder
|
||||||
|
*/
|
||||||
|
public static File getSyncFolder(String modID) {
|
||||||
|
File fl = SYNC_FOLDER.resolve(modID.replace(".", "-")
|
||||||
|
.replace(":", "-")
|
||||||
|
.replace("\\", "-")
|
||||||
|
.replace("/", "-"))
|
||||||
|
.toFile();
|
||||||
|
|
||||||
|
if (!fl.exists()){
|
||||||
|
fl.mkdirs();
|
||||||
|
}
|
||||||
|
return fl;
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
addOnWriteCallback(Config::reloadSyncedConfig);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,6 +103,7 @@ class AutoFileSyncEntry extends AutoSyncID {
|
||||||
data = buf.readByteArray(size);
|
data = buf.readByteArray(size);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static AutoFileSyncEntry findMatching(FileHash hash) {
|
public static AutoFileSyncEntry findMatching(FileHash hash) {
|
||||||
return findMatching(hash.modID, hash.uniqueID);
|
return findMatching(hash.modID, hash.uniqueID);
|
||||||
|
@ -115,7 +116,7 @@ class AutoFileSyncEntry extends AutoSyncID {
|
||||||
public static AutoFileSyncEntry findMatching(String modID, String uniqueID) {
|
public static AutoFileSyncEntry findMatching(String modID, String uniqueID) {
|
||||||
return DataExchange
|
return DataExchange
|
||||||
.getInstance()
|
.getInstance()
|
||||||
.autoSyncFiles
|
.getAutoSyncFiles()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(asf -> asf.modID.equals(modID) && asf.uniqueID.equals(uniqueID))
|
.filter(asf -> asf.modID.equals(modID) && asf.uniqueID.equals(uniqueID))
|
||||||
.findFirst()
|
.findFirst()
|
||||||
|
|
|
@ -4,14 +4,17 @@ import net.fabricmc.api.EnvType;
|
||||||
import net.fabricmc.api.Environment;
|
import net.fabricmc.api.Environment;
|
||||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
|
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
|
||||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
||||||
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
import ru.bclib.api.dataexchange.ConnectorClientside;
|
import ru.bclib.api.dataexchange.ConnectorClientside;
|
||||||
import ru.bclib.api.dataexchange.ConnectorServerside;
|
import ru.bclib.api.dataexchange.ConnectorServerside;
|
||||||
import ru.bclib.api.dataexchange.DataExchangeAPI;
|
import ru.bclib.api.dataexchange.DataExchangeAPI;
|
||||||
import ru.bclib.api.dataexchange.DataHandler;
|
import ru.bclib.api.dataexchange.DataHandler;
|
||||||
import ru.bclib.api.dataexchange.DataHandlerDescriptor;
|
import ru.bclib.api.dataexchange.DataHandlerDescriptor;
|
||||||
import ru.bclib.api.dataexchange.FileHash;
|
import ru.bclib.api.dataexchange.FileHash;
|
||||||
|
import ru.bclib.config.Configs;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -19,6 +22,12 @@ import java.util.Set;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
abstract public class DataExchange {
|
abstract public class DataExchange {
|
||||||
|
public final static Path SYNC_FOLDER = FabricLoader.getInstance()
|
||||||
|
.getGameDir()
|
||||||
|
.resolve("bclib-sync")
|
||||||
|
.toAbsolutePath();
|
||||||
|
public final static String SYNC_FOLDER_ID = "BCLIB-SYNC";
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface NeedTransferPredicate {
|
public interface NeedTransferPredicate {
|
||||||
public boolean test(FileHash clientHash, FileHash serverHash, FileContentWrapper content);
|
public boolean test(FileHash clientHash, FileHash serverHash, FileContentWrapper content);
|
||||||
|
@ -54,7 +63,9 @@ abstract public class DataExchange {
|
||||||
protected ConnectorServerside server;
|
protected ConnectorServerside server;
|
||||||
protected ConnectorClientside client;
|
protected ConnectorClientside client;
|
||||||
protected final Set<DataHandlerDescriptor> descriptors;
|
protected final Set<DataHandlerDescriptor> descriptors;
|
||||||
protected final List<AutoFileSyncEntry> autoSyncFiles = new ArrayList<>(4);
|
private final List<AutoFileSyncEntry> autoSyncFiles = new ArrayList<>(4);
|
||||||
|
|
||||||
|
private boolean didLoadSyncFolder = false;
|
||||||
|
|
||||||
abstract protected ConnectorClientside clientSupplier(DataExchange api);
|
abstract protected ConnectorClientside clientSupplier(DataExchange api);
|
||||||
abstract protected ConnectorServerside serverSupplier(DataExchange api);
|
abstract protected ConnectorServerside serverSupplier(DataExchange api);
|
||||||
|
@ -64,7 +75,11 @@ abstract public class DataExchange {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<DataHandlerDescriptor> getDescriptors() { return descriptors; }
|
public Set<DataHandlerDescriptor> getDescriptors() { return descriptors; }
|
||||||
|
|
||||||
|
public List<AutoFileSyncEntry> getAutoSyncFiles(){
|
||||||
|
return autoSyncFiles;
|
||||||
|
}
|
||||||
|
|
||||||
@Environment(EnvType.CLIENT)
|
@Environment(EnvType.CLIENT)
|
||||||
protected void initClientside(){
|
protected void initClientside(){
|
||||||
if (client!=null) return;
|
if (client!=null) return;
|
||||||
|
@ -177,4 +192,43 @@ abstract public class DataExchange {
|
||||||
static void didReceiveFile(AutoSyncID aid, File file){
|
static void didReceiveFile(AutoSyncID aid, File file){
|
||||||
onWriteCallbacks.forEach(fkt -> fkt.accept(aid, file));
|
onWriteCallbacks.forEach(fkt -> fkt.accept(aid, file));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<String> syncFolderContent;
|
||||||
|
protected List<String> getSyncFolderContent(){
|
||||||
|
if (syncFolderContent==null){
|
||||||
|
return new ArrayList<>(0);
|
||||||
|
}
|
||||||
|
return syncFolderContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
//we call this from HelloServer to prepare transfer
|
||||||
|
protected void loadSyncFolder() {
|
||||||
|
if (Configs.MAIN_CONFIG.getBoolean(Configs.MAIN_SYNC_CATEGORY, "offserSyncFolder", true))
|
||||||
|
{
|
||||||
|
final File syncPath = SYNC_FOLDER.toFile();
|
||||||
|
if (!syncPath.exists()) {
|
||||||
|
syncPath.mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (syncFolderContent == null) {
|
||||||
|
syncFolderContent = new ArrayList<>(8);
|
||||||
|
addFilesForSyncFolder(syncPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addFilesForSyncFolder(File path){
|
||||||
|
for (final File f : path.listFiles()) {
|
||||||
|
if (f.isDirectory()) {
|
||||||
|
addFilesForSyncFolder(f);
|
||||||
|
} else if (f.isFile()) {
|
||||||
|
if (!f.getName().startsWith(".")) {
|
||||||
|
Path p = f.toPath();
|
||||||
|
p = SYNC_FOLDER.relativize(p);
|
||||||
|
syncFolderContent.add(p.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,11 +77,11 @@ public class HelloClient extends DataHandler {
|
||||||
buf.writeInt(0);
|
buf.writeInt(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Configs.MAIN_CONFIG.getBoolean(Configs.MAIN_SYNC_CATEGORY, "offerConfigs", true)) {
|
if (Configs.MAIN_CONFIG.getBoolean(Configs.MAIN_SYNC_CATEGORY, "offerFiles", true)) {
|
||||||
//do only include files that exist on the server
|
//do only include files that exist on the server
|
||||||
final List<AutoFileSyncEntry> existingAutoSyncFiles = DataExchange
|
final List<AutoFileSyncEntry> existingAutoSyncFiles = DataExchange
|
||||||
.getInstance()
|
.getInstance()
|
||||||
.autoSyncFiles
|
.getAutoSyncFiles()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(e -> e.fileName.exists())
|
.filter(e -> e.fileName.exists())
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
@ -93,9 +93,22 @@ public class HelloClient extends DataHandler {
|
||||||
BCLib.LOGGER.info(" - Offering File " + entry);
|
BCLib.LOGGER.info(" - Offering File " + entry);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
BCLib.LOGGER.info("Server will not offer Configs.");
|
BCLib.LOGGER.info("Server will not offer Files.");
|
||||||
buf.writeInt(0);
|
buf.writeInt(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//for the moment this is only hardcoded for the sync-folder offered by BCLIB, but it can be extended in future
|
||||||
|
if (Configs.MAIN_CONFIG.getBoolean(Configs.MAIN_SYNC_CATEGORY, "offserSyncFolder", true)) {
|
||||||
|
buf.writeInt(1); //currently we do only sync a single folder
|
||||||
|
writeString(buf, DataExchange.SYNC_FOLDER_ID); //the UID of the Folder
|
||||||
|
final List<String> fileNames = DataExchange.getInstance().getSyncFolderContent();
|
||||||
|
buf.writeInt(fileNames.size());
|
||||||
|
fileNames.forEach(fl -> writeString(buf, fl));
|
||||||
|
} else {
|
||||||
|
BCLib.LOGGER.info("Server will not offer Sync Folders.");
|
||||||
|
buf.writeInt(0);
|
||||||
|
}
|
||||||
|
Configs.MAIN_CONFIG.saveChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
String bclibVersion ="0.0.0";
|
String bclibVersion ="0.0.0";
|
||||||
|
@ -124,6 +137,25 @@ public class HelloClient extends DataHandler {
|
||||||
autoSyncedFiles.add(t);
|
autoSyncedFiles.add(t);
|
||||||
//System.out.println(t.first);
|
//System.out.println(t.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//since this version we also send the sync folders
|
||||||
|
if (DataFixerAPI.isLargerOrEqualVersion(bclibVersion, "0.4.1")) {
|
||||||
|
final int folderCount = buf.readInt();
|
||||||
|
for (int i=0; i<folderCount; i++){
|
||||||
|
final String folderID = readString(buf);
|
||||||
|
final int entries = buf.readInt();
|
||||||
|
List<String> files = new ArrayList<>(entries);
|
||||||
|
for (int j=0; j<entries; j++){
|
||||||
|
files.add(readString(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (folderID.equals(DataExchange.SYNC_FOLDER_ID)) {
|
||||||
|
//TODO: implement the syncing here
|
||||||
|
} else {
|
||||||
|
BCLib.LOGGER.warning("Unknown Sync-Folder '"+folderID+"'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -84,5 +84,7 @@ public class HelloServer extends DataHandler {
|
||||||
} else {
|
} else {
|
||||||
BCLib.LOGGER.info("Auto-Sync was disabled on the server.");
|
BCLib.LOGGER.info("Auto-Sync was disabled on the server.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DataExchange.getInstance().loadSyncFolder();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -537,4 +537,22 @@ public class DataFixerAPI {
|
||||||
return String.format(Locale.ROOT, "%d.%d.%d", a, b, c);
|
return String.format(Locale.ROOT, "%d.%d.%d", a, b, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code true} if the version v1 is larger than v2
|
||||||
|
* @param v1 A Version string
|
||||||
|
* @param v2 Another Version string
|
||||||
|
* @return v1 > v2
|
||||||
|
*/
|
||||||
|
public static boolean isLargerVersion(String v1, String v2){
|
||||||
|
return getModVersion(v1) > getModVersion(v2);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* {@code true} if the version v1 is larger or equal v2
|
||||||
|
* @param v1 A Version string
|
||||||
|
* @param v2 Another Version string
|
||||||
|
* @return v1 ≥ v2
|
||||||
|
*/
|
||||||
|
public static boolean isLargerOrEqualVersion(String v1, String v2){
|
||||||
|
return getModVersion(v1) >= getModVersion(v2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue