Compare files on client/server
This commit is contained in:
parent
8397ef7cca
commit
119e94520c
9 changed files with 371 additions and 53 deletions
|
@ -5,29 +5,117 @@ import net.fabricmc.api.Environment;
|
|||
import net.fabricmc.fabric.api.client.networking.v1.ClientLoginConnectionEvents;
|
||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import ru.bclib.api.dataexchange.ConnectorClientside;
|
||||
import ru.bclib.api.dataexchange.ConnectorServerside;
|
||||
import ru.bclib.api.dataexchange.DataExchangeAPI;
|
||||
import ru.bclib.api.dataexchange.DataHandler;
|
||||
import ru.bclib.api.dataexchange.DataHandlerDescriptor;
|
||||
import ru.bclib.api.dataexchange.FileHash;
|
||||
import ru.bclib.util.Pair;
|
||||
import ru.bclib.util.Triple;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
abstract public class DataExchange {
|
||||
private static class AutoFileSyncEntry {
|
||||
public final Predicate<Object> needTransfer;
|
||||
public final File fileName;
|
||||
@FunctionalInterface
|
||||
public interface NeedTransferPredicate {
|
||||
public boolean test(FileHash clientHash, FileHash serverHash, byte[] content);
|
||||
}
|
||||
|
||||
private AutoFileSyncEntry(Predicate<Object> needTransfer, File fileName) {
|
||||
final static class AutoSyncTriple extends Triple<FileHash, byte[], DataExchange.AutoFileSyncEntry>{
|
||||
public AutoSyncTriple(FileHash first, byte[] second, AutoFileSyncEntry third) {
|
||||
super(first, second, third);
|
||||
}
|
||||
}
|
||||
static class AutoFileSyncEntry {
|
||||
public final NeedTransferPredicate needTransfer;
|
||||
public final File fileName;
|
||||
public final String modID;
|
||||
public final String uniqueID;
|
||||
public final boolean requestContent;
|
||||
private FileHash hash;
|
||||
|
||||
AutoFileSyncEntry(String modID, File fileName, boolean requestContent, NeedTransferPredicate needTransfer) {
|
||||
this(modID, fileName.getName(), fileName, requestContent, needTransfer);
|
||||
}
|
||||
|
||||
AutoFileSyncEntry(String modID, String uniqueID, File fileName, boolean requestContent, NeedTransferPredicate needTransfer) {
|
||||
this.needTransfer = needTransfer;
|
||||
this.fileName = fileName;
|
||||
this.modID = modID;
|
||||
this.uniqueID = uniqueID;
|
||||
this.requestContent = requestContent;
|
||||
}
|
||||
|
||||
public FileHash getFileHash(){
|
||||
if (hash == null) {
|
||||
hash = FileHash.create(modID, fileName, uniqueID);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
public byte[] getContent(){
|
||||
if (!fileName.exists()) return new byte[0];
|
||||
final Path path = fileName.toPath();
|
||||
|
||||
try {
|
||||
return Files.readAllBytes(path);
|
||||
} catch (IOException e) {
|
||||
|
||||
}
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
|
||||
public void serialize(FriendlyByteBuf buf){
|
||||
getFileHash().serialize(buf);
|
||||
buf.writeBoolean(requestContent);
|
||||
|
||||
if (requestContent) {
|
||||
byte[] content = getContent();
|
||||
buf.writeInt(content.length);
|
||||
buf.writeByteArray(content);
|
||||
}
|
||||
}
|
||||
|
||||
public static AutoSyncTriple deserializeAndMatch(FriendlyByteBuf buf){
|
||||
Pair<FileHash, byte[]> e = deserialize(buf);
|
||||
AutoFileSyncEntry match = findMatching(e.first);
|
||||
return new AutoSyncTriple(e.first, e.second, match);
|
||||
}
|
||||
|
||||
public static Pair<FileHash, byte[]> deserialize(FriendlyByteBuf buf){
|
||||
FileHash hash = FileHash.deserialize(buf);
|
||||
boolean withContent = buf.readBoolean();
|
||||
byte[] data = null;
|
||||
if (withContent) {
|
||||
int size = buf.readInt();
|
||||
data = buf.readByteArray(size);
|
||||
}
|
||||
|
||||
return new Pair(hash, data);
|
||||
}
|
||||
|
||||
public static AutoFileSyncEntry findMatching(FileHash hash){
|
||||
return DataExchange
|
||||
.getInstance()
|
||||
.autoSyncFiles
|
||||
.stream()
|
||||
.filter(asf -> asf.modID.equals(hash.modID) && asf.uniqueID.equals(hash.uniqueID))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,8 +173,8 @@ abstract public class DataExchange {
|
|||
* This is automatically called by BCLib. You can register {@link DataHandler}-Objects before this Method is called
|
||||
*/
|
||||
@Environment(EnvType.CLIENT)
|
||||
public void prepareClientside(){
|
||||
DataExchangeAPI api = DataExchangeAPI.getInstance();
|
||||
public static void prepareClientside(){
|
||||
DataExchange api = DataExchange.getInstance();
|
||||
api.initClientside();
|
||||
|
||||
}
|
||||
|
@ -97,7 +185,7 @@ abstract public class DataExchange {
|
|||
* This is automatically called by BCLib. You can register {@link DataHandler}-Objects before this Method is called
|
||||
*/
|
||||
public static void prepareServerside(){
|
||||
DataExchange api = DataExchangeAPI.getInstance();
|
||||
DataExchange api = DataExchange.getInstance();
|
||||
api.initServerSide();
|
||||
}
|
||||
|
||||
|
@ -124,10 +212,36 @@ abstract public class DataExchange {
|
|||
/**
|
||||
* Registers a File for automatic client syncing.
|
||||
*
|
||||
* @param modID The ID of the calling Mod
|
||||
* @param needTransfer If the predicate returns true, the file needs to get copied to the server.
|
||||
* @param fileName The name of the File
|
||||
* @param requestContent When {@code true} the content of the file is requested for comparison. This will copy the
|
||||
* entire file from the client to the server.
|
||||
* <p>
|
||||
* 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}
|
||||
* for comparison is sufficient.
|
||||
*/
|
||||
protected void addAutoSyncFileData(Predicate<Object> needTransfer, File fileName){
|
||||
autoSyncFiles.add(new AutoFileSyncEntry(needTransfer, fileName));
|
||||
protected void addAutoSyncFileData(String modID, File fileName, boolean requestContent, NeedTransferPredicate needTransfer){
|
||||
autoSyncFiles.add(new AutoFileSyncEntry(modID, fileName, requestContent, needTransfer));
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a File for automatic client syncing.
|
||||
*
|
||||
* @param modID The ID of the calling Mod
|
||||
* @param uniqueID A unique Identifier for the File. (see {@link ru.bclib.api.dataexchange.FileHash#uniqueID} for
|
||||
* Details
|
||||
* @param needTransfer If the predicate returns true, the file needs to get copied to the server.
|
||||
* @param fileName The name of the File
|
||||
* @param requestContent When {@code true} the content of the file is requested for comparison. This will copy the
|
||||
* entire file from the client to the server.
|
||||
* <p>
|
||||
* 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}
|
||||
* for comparison is sufficient.
|
||||
*/
|
||||
protected void addAutoSyncFileData(String modID, String uniqueID, File fileName, boolean requestContent, NeedTransferPredicate needTransfer){
|
||||
autoSyncFiles.add(new AutoFileSyncEntry(modID, uniqueID, fileName, requestContent, needTransfer));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue