232 lines
7.9 KiB
Java
232 lines
7.9 KiB
Java
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.loader.api.FabricLoader;
|
|
import net.fabricmc.loader.api.ModContainer;
|
|
import net.minecraft.client.Minecraft;
|
|
import net.minecraft.client.gui.screens.Screen;
|
|
import net.minecraft.network.FriendlyByteBuf;
|
|
import net.minecraft.resources.ResourceLocation;
|
|
import net.minecraft.server.MinecraftServer;
|
|
import ru.bclib.BCLib;
|
|
import ru.bclib.api.dataexchange.DataExchangeAPI;
|
|
import ru.bclib.api.dataexchange.DataHandler;
|
|
import ru.bclib.api.dataexchange.DataHandlerDescriptor;
|
|
import ru.bclib.api.dataexchange.handler.AutoSyncID.WithContentOverride;
|
|
import ru.bclib.api.datafixer.DataFixerAPI;
|
|
import ru.bclib.config.Configs;
|
|
import ru.bclib.gui.screens.SyncFilesScreen;
|
|
import ru.bclib.gui.screens.WarnBCLibVersionMismatch;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Map.Entry;
|
|
import java.util.Optional;
|
|
import java.util.function.Consumer;
|
|
import java.util.stream.Collectors;
|
|
|
|
/**
|
|
* Sent from the Server to the Client.
|
|
* <p>
|
|
* For Details refer to {@link HelloServer}
|
|
*/
|
|
public class HelloClient extends DataHandler {
|
|
public static DataHandlerDescriptor DESCRIPTOR = new DataHandlerDescriptor(new ResourceLocation(BCLib.MOD_ID, "hello_client"), HelloClient::new, false, false);
|
|
|
|
public HelloClient() {
|
|
super(DESCRIPTOR.IDENTIFIER, true);
|
|
}
|
|
|
|
public static String getModVersion(String modID){
|
|
Optional<ModContainer> optional = FabricLoader.getInstance().getModContainer(modID);
|
|
if (optional.isPresent()) {
|
|
ModContainer modContainer = optional.get();
|
|
return modContainer.getMetadata().getVersion().toString();
|
|
}
|
|
return "0.0.0";
|
|
}
|
|
|
|
static String getBCLibVersion(){
|
|
return getModVersion(BCLib.MOD_ID);
|
|
}
|
|
|
|
@Override
|
|
protected void serializeData(FriendlyByteBuf buf) {
|
|
final String vbclib = getBCLibVersion();
|
|
BCLib.LOGGER.info("Sending Hello to Client. (server="+vbclib+")");
|
|
final List<String> mods = DataExchangeAPI.registeredMods();
|
|
|
|
//write BCLibVersion (=protocol version)
|
|
buf.writeInt(DataFixerAPI.getModVersion(vbclib));
|
|
|
|
if (Configs.MAIN_CONFIG.getBoolean(Configs.MAIN_SYNC_CATEGORY, "offerMods", true)) {
|
|
//write Plugin Versions
|
|
buf.writeInt(mods.size());
|
|
for (String modID : mods) {
|
|
writeString(buf, modID);
|
|
final String ver = getModVersion(modID);
|
|
buf.writeInt(DataFixerAPI.getModVersion(ver));
|
|
BCLib.LOGGER.info(" - Listing Mod " + modID + " v" + ver);
|
|
}
|
|
} else {
|
|
BCLib.LOGGER.info("Server will not list Mods.");
|
|
buf.writeInt(0);
|
|
}
|
|
|
|
if (Configs.MAIN_CONFIG.getBoolean(Configs.MAIN_SYNC_CATEGORY, "offerConfigs", true)) {
|
|
//do only include files that exist on the server
|
|
final List<AutoFileSyncEntry> existingAutoSyncFiles = DataExchange
|
|
.getInstance()
|
|
.autoSyncFiles
|
|
.stream()
|
|
.filter(e -> e.fileName.exists())
|
|
.collect(Collectors.toList());
|
|
|
|
//send config Data
|
|
buf.writeInt(existingAutoSyncFiles.size());
|
|
for (AutoFileSyncEntry entry : existingAutoSyncFiles) {
|
|
entry.serialize(buf);
|
|
BCLib.LOGGER.info(" - Offering File " + entry);
|
|
}
|
|
} else {
|
|
BCLib.LOGGER.info("Server will not offer Configs.");
|
|
buf.writeInt(0);
|
|
}
|
|
}
|
|
|
|
String bclibVersion ="0.0.0";
|
|
Map<String, String> modVersion = new HashMap<>();
|
|
List<DataExchange.AutoSyncTriple> autoSyncedFiles = null;
|
|
@Override
|
|
protected void deserializeFromIncomingData(FriendlyByteBuf buf, PacketSender responseSender, boolean fromClient) {
|
|
//read BCLibVersion (=protocol version)
|
|
bclibVersion = DataFixerAPI.getModVersion(buf.readInt());
|
|
|
|
//read Plugin Versions
|
|
modVersion = new HashMap<>();
|
|
int count = buf.readInt();
|
|
for (int i=0; i< count; i++) {
|
|
String id = readString(buf);
|
|
String version = DataFixerAPI.getModVersion(buf.readInt());
|
|
modVersion.put(id, version);
|
|
}
|
|
|
|
//read config Data
|
|
count = buf.readInt();
|
|
autoSyncedFiles = new ArrayList<>(count);
|
|
for (int i=0; i< count; i++) {
|
|
//System.out.println("Deserializing ");
|
|
DataExchange.AutoSyncTriple t = AutoFileSyncEntry.deserializeAndMatch(buf);
|
|
autoSyncedFiles.add(t);
|
|
//System.out.println(t.first);
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
protected void runOnGameThread(Minecraft client, MinecraftServer server, boolean isClient) {
|
|
final boolean debugHashes = Configs.CLIENT_CONFIG.getBoolean(Configs.MAIN_SYNC_CATEGORY, "debugHashes", false);
|
|
final String localBclibVersion = getBCLibVersion();
|
|
BCLib.LOGGER.info("Received Hello from Server. (client="+localBclibVersion+", server="+bclibVersion+")");
|
|
|
|
// if (DataFixerAPI.getModVersion(localBclibVersion) != DataFixerAPI.getModVersion(bclibVersion)){
|
|
// showBCLibError(client);
|
|
// return;
|
|
// }
|
|
|
|
final List<AutoSyncID> filesToRequest = new ArrayList<>(2);
|
|
|
|
|
|
|
|
for (Entry<String, String> e : modVersion.entrySet()){
|
|
String ver = getModVersion(e.getKey());
|
|
BCLib.LOGGER.info(" - " + e.getKey() + " (client="+ver+", server="+ver+")");
|
|
}
|
|
|
|
if (autoSyncedFiles.size()>0) {
|
|
BCLib.LOGGER.info("Files offered by Server:");
|
|
}
|
|
for (DataExchange.AutoSyncTriple e : autoSyncedFiles) {
|
|
String actionString = "";
|
|
FileContentWrapper contentWrapper = new FileContentWrapper(e.serverContent);
|
|
if (e.localMatch == null) {
|
|
actionString = "(new, prepare update)";
|
|
filesToRequest.add(new AutoSyncID(e.serverHash.modID, e.serverHash.uniqueID));
|
|
} else if (e.localMatch.needTransfer.test(e.localMatch.getFileHash(), e.serverHash, contentWrapper)) {
|
|
actionString = "(prepare update)";
|
|
//we did not yet receive the new content
|
|
if (contentWrapper.getRawContent() == null) {
|
|
filesToRequest.add(new AutoSyncID(e.serverHash.modID, e.serverHash.uniqueID));
|
|
} else {
|
|
filesToRequest.add(new AutoSyncID.WithContentOverride(e.serverHash.modID, e.serverHash.uniqueID, contentWrapper, e.localMatch.fileName));
|
|
}
|
|
}
|
|
|
|
BCLib.LOGGER.info(" - " + e + ": " + actionString);
|
|
if (debugHashes) {
|
|
BCLib.LOGGER.info(" * " + e.serverHash + " (Server)");
|
|
BCLib.LOGGER.info(" * " + e.localMatch.getFileHash() + " (Client)");
|
|
BCLib.LOGGER.info(" * local Content " + (contentWrapper.getRawContent() == null));
|
|
}
|
|
}
|
|
|
|
if (filesToRequest.size()>0 && SendFiles.acceptFiles()) {
|
|
showDownloadConfigs(client, filesToRequest);
|
|
return;
|
|
}
|
|
}
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
protected void showBCLibError(Minecraft client){
|
|
BCLib.LOGGER.error("BCLib differs on client and server.");
|
|
client.setScreen(new WarnBCLibVersionMismatch((download) -> {
|
|
Minecraft.getInstance().setScreen((Screen)null);
|
|
if (download){
|
|
requestBCLibDownload((hadErrors)->{
|
|
client.stop();
|
|
});
|
|
}
|
|
}));
|
|
}
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
protected void showDownloadConfigs(Minecraft client, List<AutoSyncID> files){
|
|
client.setScreen(new SyncFilesScreen((download) -> {
|
|
Minecraft.getInstance().setScreen((Screen)null);
|
|
if (download){
|
|
BCLib.LOGGER.info("Updating local Files:");
|
|
List<AutoSyncID.WithContentOverride> localChanges = new ArrayList<>(files.toArray().length);
|
|
List<AutoSyncID> requestFiles = new ArrayList<>(files.toArray().length);
|
|
|
|
files.forEach(aid -> {
|
|
if (aid instanceof WithContentOverride) {
|
|
final WithContentOverride aidc = (WithContentOverride)aid;
|
|
BCLib.LOGGER.info(" - " + aid + " (updating Content)");
|
|
|
|
SendFiles.writeSyncedFile(aid, aidc.contentWrapper.getRawContent(), aidc.localFile);
|
|
} else {
|
|
requestFiles.add(aid);
|
|
BCLib.LOGGER.info(" - " + aid + " (requesting)");
|
|
}
|
|
});
|
|
|
|
requestFileDownloads(requestFiles);
|
|
}
|
|
}));
|
|
|
|
}
|
|
|
|
private void requestBCLibDownload(Consumer<Boolean> whenFinished){
|
|
BCLib.LOGGER.warning("Starting download of BCLib");
|
|
whenFinished.accept(true);
|
|
}
|
|
|
|
private void requestFileDownloads(List<AutoSyncID> files){
|
|
BCLib.LOGGER.info("Starting download of Files:" + files.size());
|
|
DataExchangeAPI.send(new RequestFiles(files));
|
|
}
|
|
}
|