Finished first draft of File syncing

This commit is contained in:
Frank 2021-08-06 23:08:13 +02:00
parent c28a566c78
commit 6883287c72
10 changed files with 209 additions and 18 deletions

View file

@ -7,8 +7,11 @@ import net.minecraft.resources.ResourceLocation;
import ru.bclib.api.TagAPI; import ru.bclib.api.TagAPI;
import ru.bclib.api.WorldDataAPI; import ru.bclib.api.WorldDataAPI;
import ru.bclib.api.dataexchange.DataExchangeAPI; import ru.bclib.api.dataexchange.DataExchangeAPI;
import ru.bclib.api.dataexchange.DataHandler;
import ru.bclib.api.dataexchange.handler.HelloClient; import ru.bclib.api.dataexchange.handler.HelloClient;
import ru.bclib.api.dataexchange.handler.HelloServer; import ru.bclib.api.dataexchange.handler.HelloServer;
import ru.bclib.api.dataexchange.handler.RequestFiles;
import ru.bclib.api.dataexchange.handler.SendFiles;
import ru.bclib.config.Configs; import ru.bclib.config.Configs;
import ru.bclib.recipes.CraftingRecipes; import ru.bclib.recipes.CraftingRecipes;
import ru.bclib.registry.BaseBlockEntities; import ru.bclib.registry.BaseBlockEntities;
@ -16,6 +19,9 @@ import ru.bclib.registry.BaseRegistry;
import ru.bclib.util.Logger; import ru.bclib.util.Logger;
import ru.bclib.world.surface.BCLSurfaceBuilders; import ru.bclib.world.surface.BCLSurfaceBuilders;
import java.util.ArrayList;
import java.util.List;
public class BCLib implements ModInitializer { public class BCLib implements ModInitializer {
public static final String MOD_ID = "bclib"; public static final String MOD_ID = "bclib";
public static final Logger LOGGER = new Logger(MOD_ID); public static final Logger LOGGER = new Logger(MOD_ID);
@ -30,8 +36,12 @@ public class BCLib implements ModInitializer {
WorldDataAPI.registerModCache(MOD_ID); WorldDataAPI.registerModCache(MOD_ID);
Configs.save(); Configs.save();
DataExchangeAPI.registerDescriptor(HelloClient.DESCRIPTOR); DataExchangeAPI.registerDescriptors(List.of(
DataExchangeAPI.registerDescriptor(HelloServer.DESCRIPTOR); HelloClient.DESCRIPTOR,
HelloServer.DESCRIPTOR,
RequestFiles.DESCRIPTOR,
SendFiles.DESCRIPTOR
));
} }
public static boolean isDevEnvironment() { public static boolean isDevEnvironment() {

View file

@ -59,7 +59,7 @@ public class DataExchangeAPI extends DataExchange {
} }
/** /**
* Add a new Descriptor for a 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){
@ -67,6 +67,15 @@ public class DataExchangeAPI extends DataExchange {
api.getDescriptors().add(desc); api.getDescriptors().add(desc);
} }
/**
* Bulk-Add a Descriptors for your {@link DataHandler}-Objects.
* @param desc The Descriptors you want to add.
*/
public static void registerDescriptors(List<DataHandlerDescriptor> desc){
DataExchange api = DataExchange.getInstance();
api.getDescriptors().addAll(desc);
}
/** /**
* Sends the Handler. * Sends the Handler.
* <p> * <p>

View file

@ -1,6 +1,10 @@
package ru.bclib.api.dataexchange; package ru.bclib.api.dataexchange;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import ru.bclib.api.dataexchange.handler.HelloClient;
import ru.bclib.api.dataexchange.handler.HelloServer;
import ru.bclib.api.dataexchange.handler.RequestFiles;
import ru.bclib.api.dataexchange.handler.SendFiles;
import java.util.function.Supplier; import java.util.function.Supplier;

View file

@ -97,10 +97,10 @@ abstract public class DataExchange {
return new byte[0]; return new byte[0];
} }
public void serializeContent(FriendlyByteBuf buf){ public int serializeContent(FriendlyByteBuf buf){
DataHandler.writeString(buf, modID); DataHandler.writeString(buf, modID);
DataHandler.writeString(buf, uniqueID); DataHandler.writeString(buf, uniqueID);
serializeFileContent(buf); return serializeFileContent(buf);
} }
public static Pair<AutoFileSyncEntry, byte[]> deserializeContent(FriendlyByteBuf buf){ public static Pair<AutoFileSyncEntry, byte[]> deserializeContent(FriendlyByteBuf buf){
final String modID = DataHandler.readString(buf); final String modID = DataHandler.readString(buf);
@ -138,10 +138,11 @@ abstract public class DataExchange {
return new Pair(hash, data); return new Pair(hash, data);
} }
private void serializeFileContent(FriendlyByteBuf buf) { private int serializeFileContent(FriendlyByteBuf buf) {
byte[] content = getContent(); byte[] content = getContent();
buf.writeInt(content.length); buf.writeInt(content.length);
buf.writeByteArray(content); buf.writeByteArray(content);
return content.length;
} }
private static byte[] deserializeFileContent(FriendlyByteBuf buf) { private static byte[] deserializeFileContent(FriendlyByteBuf buf) {

View file

@ -16,6 +16,7 @@ import ru.bclib.api.dataexchange.DataHandler;
import ru.bclib.api.dataexchange.DataHandlerDescriptor; import ru.bclib.api.dataexchange.DataHandlerDescriptor;
import ru.bclib.api.dataexchange.handler.DataExchange.AutoSyncID; import ru.bclib.api.dataexchange.handler.DataExchange.AutoSyncID;
import ru.bclib.api.datafixer.DataFixerAPI; import ru.bclib.api.datafixer.DataFixerAPI;
import ru.bclib.gui.screens.SyncFilesScreen;
import ru.bclib.gui.screens.WarnBCLibVersionMismatch; import ru.bclib.gui.screens.WarnBCLibVersionMismatch;
import java.util.ArrayList; import java.util.ArrayList;
@ -134,8 +135,10 @@ public class HelloClient extends DataHandler {
BCLib.LOGGER.info(" - " + e + ": " + (willRequest ? " (requesting)":"")); BCLib.LOGGER.info(" - " + e + ": " + (willRequest ? " (requesting)":""));
} }
if (filesToRequest.size()>0) { if (filesToRequest.size()>0) {
showDonwloadConfigs(client, filesToRequest); showDonwloadConfigs(client, filesToRequest);
return;
} }
} }
@ -154,9 +157,13 @@ public class HelloClient extends DataHandler {
@Environment(EnvType.CLIENT) @Environment(EnvType.CLIENT)
protected void showDonwloadConfigs(Minecraft client, List<AutoSyncID> files){ protected void showDonwloadConfigs(Minecraft client, List<AutoSyncID> files){
requestFileDownloads((hadErrors)->{ client.setScreen(new SyncFilesScreen((download) -> {
client.stop(); Minecraft.getInstance().setScreen((Screen)null);
}, files); if (download){
requestFileDownloads(files);
}
}));
} }
private void requestBCLibDownload(Consumer<Boolean> whenFinished){ private void requestBCLibDownload(Consumer<Boolean> whenFinished){
@ -164,9 +171,8 @@ public class HelloClient extends DataHandler {
whenFinished.accept(true); whenFinished.accept(true);
} }
private void requestFileDownloads(Consumer<Boolean> whenFinished, List<AutoSyncID> files){ private void requestFileDownloads(List<AutoSyncID> files){
BCLib.LOGGER.info("Starting download of Files:" + files.size()); BCLib.LOGGER.info("Starting download of Files:" + files.size());
DataExchangeAPI.send(new RequestFiles(files)); DataExchangeAPI.send(new RequestFiles(files));
whenFinished.accept(true);
} }
} }

View file

@ -12,10 +12,12 @@ import ru.bclib.api.dataexchange.handler.DataExchange.AutoSyncID;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class RequestFiles extends DataHandler { public class RequestFiles extends DataHandler {
public static DataHandlerDescriptor DESCRIPTOR = new DataHandlerDescriptor(new ResourceLocation(BCLib.MOD_ID, "request_files"), RequestFiles::new, false, false); public static DataHandlerDescriptor DESCRIPTOR = new DataHandlerDescriptor(new ResourceLocation(BCLib.MOD_ID, "request_files"), RequestFiles::new, false, false);
static String currentToken = "";
protected List<AutoSyncID> files; protected List<AutoSyncID> files;
private RequestFiles(){ private RequestFiles(){
@ -29,6 +31,9 @@ public class RequestFiles extends DataHandler {
@Override @Override
protected void serializeData(FriendlyByteBuf buf) { protected void serializeData(FriendlyByteBuf buf) {
newToken();
writeString(buf, currentToken);
buf.writeInt(files.size()); buf.writeInt(files.size());
for (AutoSyncID a : files){ for (AutoSyncID a : files){
@ -36,9 +41,11 @@ public class RequestFiles extends DataHandler {
writeString(buf, a.getUniqueID()); writeString(buf, a.getUniqueID());
} }
} }
String receivedToken = "";
@Override @Override
protected void deserializeFromIncomingData(FriendlyByteBuf buf, PacketSender responseSender, boolean fromClient) { protected void deserializeFromIncomingData(FriendlyByteBuf buf, PacketSender responseSender, boolean fromClient) {
receivedToken = readString(buf);
int size = buf.readInt(); int size = buf.readInt();
files = new ArrayList<>(size); files = new ArrayList<>(size);
@ -61,6 +68,16 @@ public class RequestFiles extends DataHandler {
.filter(e -> e!=null) .filter(e -> e!=null)
.collect(Collectors.toList()); .collect(Collectors.toList());
reply(new SendFiles(syncEntries), server); reply(new SendFiles(syncEntries, receivedToken), server);
}
public static void newToken(){
currentToken = UUID.randomUUID().toString();
}
static {
newToken();
} }
} }

View file

@ -1,44 +1,67 @@
package ru.bclib.api.dataexchange.handler; package ru.bclib.api.dataexchange.handler;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.networking.v1.PacketSender; import net.fabricmc.fabric.api.networking.v1.PacketSender;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import ru.bclib.BCLib; import ru.bclib.BCLib;
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.gui.screens.ConfirmRestartScreen;
import ru.bclib.gui.screens.SyncFilesScreen;
import ru.bclib.util.Pair; import ru.bclib.util.Pair;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class SendFiles extends DataHandler { public class SendFiles extends DataHandler {
public static DataHandlerDescriptor DESCRIPTOR = new DataHandlerDescriptor(new ResourceLocation(BCLib.MOD_ID, "send_files"), SendFiles::new, false, false); public static DataHandlerDescriptor DESCRIPTOR = new DataHandlerDescriptor(new ResourceLocation(BCLib.MOD_ID, "send_files"), SendFiles::new, false, false);
protected List<DataExchange.AutoFileSyncEntry> files; protected List<DataExchange.AutoFileSyncEntry> files;
private String token = "";
public SendFiles(){ public SendFiles(){
this(null); this(null, "");
} }
public SendFiles(List<DataExchange.AutoFileSyncEntry> files) { public SendFiles(List<DataExchange.AutoFileSyncEntry> files, String token) {
super(DESCRIPTOR.IDENTIFIER, true); super(DESCRIPTOR.IDENTIFIER, true);
this.files = files; this.files = files;
this.token = token;
} }
@Override @Override
protected void serializeData(FriendlyByteBuf buf) { protected void serializeData(FriendlyByteBuf buf) {
List<DataExchange.AutoFileSyncEntry> existingFiles = files.stream().filter(e -> e.fileName.exists()).collect(Collectors.toList()); List<DataExchange.AutoFileSyncEntry> existingFiles = files.stream().filter(e -> e.fileName.exists()).collect(Collectors.toList());
writeString(buf, token);
buf.writeInt(existingFiles.size()); buf.writeInt(existingFiles.size());
BCLib.LOGGER.info("Sending " + existingFiles.size() + " Files to Client:");
for (DataExchange.AutoFileSyncEntry entry : existingFiles) { for (DataExchange.AutoFileSyncEntry entry : existingFiles) {
entry.serializeContent(buf); int length = entry.serializeContent(buf);
BCLib.LOGGER.info(" - " + entry + " (" + length + " Bytes)");
} }
} }
private List<Pair<DataExchange.AutoFileSyncEntry, byte[]>> receivedFiles; private List<Pair<DataExchange.AutoFileSyncEntry, byte[]>> receivedFiles;
@Override @Override
protected void deserializeFromIncomingData(FriendlyByteBuf buf, PacketSender responseSender, boolean fromClient) { protected void deserializeFromIncomingData(FriendlyByteBuf buf, PacketSender responseSender, boolean fromClient) {
token = readString(buf);
if (!token.equals(RequestFiles.currentToken)) {
BCLib.LOGGER.error("Unrequested File Transfer!");
receivedFiles = new ArrayList<>(0);
return;
}
int size = buf.readInt(); int size = buf.readInt();
receivedFiles = new ArrayList<>(size); receivedFiles = new ArrayList<>(size);
BCLib.LOGGER.info("Server sent " + size + " Files:"); BCLib.LOGGER.info("Server sent " + size + " Files:");
@ -55,6 +78,28 @@ public class SendFiles extends DataHandler {
@Override @Override
protected void runOnGameThread(Minecraft client, MinecraftServer server, boolean isClient) { protected void runOnGameThread(Minecraft client, MinecraftServer server, boolean isClient) {
BCLib.LOGGER.info("Writing Files:");
for (Pair<DataExchange.AutoFileSyncEntry, byte[]> entry : receivedFiles) {
final DataExchange.AutoFileSyncEntry e = entry.first;
final byte[] data = entry.second;
Path path = e.fileName.toPath();
BCLib.LOGGER.info(" - Writing " + path + " (" + data.length + " Bytes)");
try {
Files.write(path, data);
} catch (IOException ioException) {
BCLib.LOGGER.error(" --> Writing "+e.fileName+" failed: " + ioException);
}
}
showConfirmRestart(client);
}
@Environment(EnvType.CLIENT)
protected void showConfirmRestart(Minecraft client){
client.setScreen(new ConfirmRestartScreen(() -> {
Minecraft.getInstance().setScreen((Screen)null);
client.stop();
}));
} }
} }

View file

@ -0,0 +1,49 @@
package ru.bclib.gui.screens;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import ru.bclib.gui.GridScreen;
@Environment(EnvType.CLIENT)
public class ConfirmRestartScreen extends GridScreen {
private final Component description;
private final ConfirmRestartScreen.Listener listener;
public ConfirmRestartScreen(ConfirmRestartScreen.Listener listener) {
this(listener, null);
}
public ConfirmRestartScreen(ConfirmRestartScreen.Listener listener, Component message) {
super(30, new TranslatableComponent("bclib.datafixer.confirmrestart.title"));
this.description = message==null?new TranslatableComponent("bclib.datafixer.confirmrestart.message"):message;
this.listener = listener;
}
protected void initLayout() {
final int BUTTON_HEIGHT = 20;
grid.addMessageRow(this.description, 25);
grid.startRow();
grid.addButton( BUTTON_HEIGHT, CommonComponents.GUI_PROCEED, (button) -> {
listener.proceed();
});
grid.endRow();
grid.recenterVertically();
}
public boolean shouldCloseOnEsc() {
return false;
}
@Environment(EnvType.CLIENT)
public interface Listener {
void proceed();
}
}

View file

@ -0,0 +1,46 @@
package ru.bclib.gui.screens;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import ru.bclib.gui.GridScreen;
@Environment(EnvType.CLIENT)
public class SyncFilesScreen extends GridScreen {
private final Component description;
private final SyncFilesScreen.Listener listener;
public SyncFilesScreen(SyncFilesScreen.Listener listener) {
super(30, new TranslatableComponent("bclib.datafixer.syncfiles.title"));
this.description = new TranslatableComponent("bclib.datafixer.syncfiles.message");
this.listener = listener;
}
protected void initLayout() {
final int BUTTON_HEIGHT = 20;
grid.addMessageRow(this.description, 25);
grid.startRow();
grid.addButton( BUTTON_HEIGHT, CommonComponents.GUI_NO, (button) -> {
listener.proceed(false);
});
grid.addButton( BUTTON_HEIGHT, CommonComponents.GUI_YES, (button) -> {
listener.proceed(true);
});
grid.endRow();
grid.recenterVertically();
}
public boolean shouldCloseOnEsc() {
return false;
}
@Environment(EnvType.CLIENT)
public interface Listener {
void proceed(boolean download);
}
}

View file

@ -6,5 +6,9 @@
"bclib.datafixer.backupWarning.nofixes": "Continue Without Fixes", "bclib.datafixer.backupWarning.nofixes": "Continue Without Fixes",
"bclib.datafixer.backupWarning.continue": "Continue Without Backup", "bclib.datafixer.backupWarning.continue": "Continue Without Backup",
"bclib.datafixer.bclibmissmatch.title": "Version Mismatch", "bclib.datafixer.bclibmissmatch.title": "Version Mismatch",
"bclib.datafixer.bclibmissmatch.message": "The Version of BCLib on the server and this client do not match. This will cause problems when playing.\n\nDo you want to automatically download the BCLib-Version from the server. You will need to delete the old version from your Mods Directory and restart the game." "bclib.datafixer.bclibmissmatch.message": "The Version of BCLib on the server and this client do not match. This will cause problems when playing.\n\nDo you want to automatically download the BCLib-Version from the server. You will need to delete the old version from your Mods Directory and restart the game.",
"bclib.datafixer.syncfiles.title": "Mismatching (Config-)Files",
"bclib.datafixer.syncfiles.message": "Some Files on the Server doe not match the versions on the client.\n\nDo you want to replace the local versions with the ones from the server?",
"bclib.datafixer.confirmrestart.title": "Restart Required",
"bclib.datafixer.confirmrestart.message": "The requested files were processed. You need o restart Minecraft now."
} }