Implement API for mods to control their server status response..
Signed-off-by: cpw <cpw+github@weeksfamily.ca>
This commit is contained in:
parent
4ecb04ed9f
commit
3f735b715b
|
@ -4,7 +4,7 @@
|
||||||
private ServerStatusResponse.Players field_151324_b;
|
private ServerStatusResponse.Players field_151324_b;
|
||||||
private ServerStatusResponse.Version field_151325_c;
|
private ServerStatusResponse.Version field_151325_c;
|
||||||
private String field_151323_d;
|
private String field_151323_d;
|
||||||
+ private net.minecraftforge.fml.network.FMLStatusPing forgeData;
|
+ private transient net.minecraftforge.fml.network.FMLStatusPing forgeData;
|
||||||
|
|
||||||
+ public net.minecraftforge.fml.network.FMLStatusPing getForgeData() {
|
+ public net.minecraftforge.fml.network.FMLStatusPing getForgeData() {
|
||||||
+ return this.forgeData;
|
+ return this.forgeData;
|
||||||
|
|
|
@ -22,6 +22,7 @@ package net.minecraftforge.common;
|
||||||
import net.minecraftforge.eventbus.api.IEventBus;
|
import net.minecraftforge.eventbus.api.IEventBus;
|
||||||
import net.minecraftforge.fml.BrandingControl;
|
import net.minecraftforge.fml.BrandingControl;
|
||||||
import net.minecraftforge.fml.DistExecutor;
|
import net.minecraftforge.fml.DistExecutor;
|
||||||
|
import net.minecraftforge.fml.ExtensionPoint;
|
||||||
import net.minecraftforge.fml.FMLWorldPersistenceHook;
|
import net.minecraftforge.fml.FMLWorldPersistenceHook;
|
||||||
import net.minecraftforge.fml.ModLoadingContext;
|
import net.minecraftforge.fml.ModLoadingContext;
|
||||||
import net.minecraftforge.fml.VersionChecker;
|
import net.minecraftforge.fml.VersionChecker;
|
||||||
|
@ -38,6 +39,7 @@ import net.minecraftforge.server.command.ForgeCommand;
|
||||||
import net.minecraftforge.versions.forge.ForgeVersion;
|
import net.minecraftforge.versions.forge.ForgeVersion;
|
||||||
import net.minecraftforge.versions.mcp.MCPVersion;
|
import net.minecraftforge.versions.mcp.MCPVersion;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
@ -99,6 +101,8 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook
|
||||||
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, ForgeConfig.clientSpec);
|
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, ForgeConfig.clientSpec);
|
||||||
ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, ForgeConfig.serverSpec);
|
ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, ForgeConfig.serverSpec);
|
||||||
modEventBus.register(ForgeConfig.class);
|
modEventBus.register(ForgeConfig.class);
|
||||||
|
// Forge does not display problems when the remote is not matching.
|
||||||
|
ModLoadingContext.get().registerExtensionPoint(ExtensionPoint.DISPLAYTEST, ()-> Pair.of(()->"ANY", (remote, isServer)-> true));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -24,17 +24,28 @@ import net.minecraft.client.gui.GuiScreen;
|
||||||
import net.minecraft.resources.IResourcePack;
|
import net.minecraft.resources.IResourcePack;
|
||||||
import net.minecraftforge.fml.network.FMLPlayMessages;
|
import net.minecraftforge.fml.network.FMLPlayMessages;
|
||||||
import net.minecraftforge.fml.packs.ModFileResourcePack;
|
import net.minecraftforge.fml.packs.ModFileResourcePack;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.BiPredicate;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class ExtensionPoint<T>
|
public class ExtensionPoint<T>
|
||||||
{
|
{
|
||||||
public static final ExtensionPoint<BiFunction<Minecraft, GuiScreen, GuiScreen>> CONFIGGUIFACTORY = new ExtensionPoint<>();
|
public static final ExtensionPoint<BiFunction<Minecraft, GuiScreen, GuiScreen>> CONFIGGUIFACTORY = new ExtensionPoint<>();
|
||||||
public static final ExtensionPoint<BiFunction<Minecraft, ModFileResourcePack, IResourcePack>> RESOURCEPACK = new ExtensionPoint<>();
|
public static final ExtensionPoint<BiFunction<Minecraft, ModFileResourcePack, IResourcePack>> RESOURCEPACK = new ExtensionPoint<>();
|
||||||
|
/**
|
||||||
|
* Compatibility display test for the mod.
|
||||||
|
* Used for displaying compatibility with remote servers with the same mod, and on disk saves.
|
||||||
|
*
|
||||||
|
* The supplier provides my "local" version for sending across the network or writing to disk
|
||||||
|
* The predicate tests the version from a remote instance or save for acceptability (Boolean is true for network, false for local save)
|
||||||
|
*/
|
||||||
|
public static final ExtensionPoint<Pair<Supplier<String>, BiPredicate<String, Boolean>>> DISPLAYTEST = new ExtensionPoint<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register with {@link ModLoadingContext#}
|
* Register with {@link ModLoadingContext#registerExtensionPoint(ExtensionPoint, Supplier)}
|
||||||
*/
|
*/
|
||||||
public static final ExtensionPoint<Function<FMLPlayMessages.OpenContainer, GuiScreen>> GUIFACTORY = new ExtensionPoint<>();
|
public static final ExtensionPoint<Function<FMLPlayMessages.OpenContainer, GuiScreen>> GUIFACTORY = new ExtensionPoint<>();
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,16 @@ package net.minecraftforge.fml;
|
||||||
|
|
||||||
import net.minecraftforge.fml.config.ModConfig;
|
import net.minecraftforge.fml.config.ModConfig;
|
||||||
import net.minecraftforge.forgespi.language.IModInfo;
|
import net.minecraftforge.forgespi.language.IModInfo;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.Collections;
|
||||||
|
import java.util.EnumMap;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.IdentityHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
@ -60,6 +68,9 @@ public abstract class ModContainer
|
||||||
this.modInfo = info;
|
this.modInfo = info;
|
||||||
this.triggerMap = new HashMap<>();
|
this.triggerMap = new HashMap<>();
|
||||||
this.modLoadingStage = ModLoadingStage.CONSTRUCT;
|
this.modLoadingStage = ModLoadingStage.CONSTRUCT;
|
||||||
|
// default displaytest extension checks for version string match
|
||||||
|
registerExtensionPoint(ExtensionPoint.DISPLAYTEST, () -> Pair.of(()->this.modInfo.getVersion().toString(),
|
||||||
|
(incoming, isNetwork)->Objects.equals(incoming, this.modInfo.getVersion().toString())));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -183,4 +183,8 @@ public class ModList
|
||||||
{
|
{
|
||||||
modFiles.stream().map(ModFileInfo::getFile).forEach(fileConsumer);
|
modFiles.stream().map(ModFileInfo::getFile).forEach(fileConsumer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void forEachModContainer(BiConsumer<String, ModContainer> modContainerConsumer) {
|
||||||
|
indexedMods.forEach(modContainerConsumer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,18 +22,28 @@ package net.minecraftforge.fml.client;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.google.common.collect.*;
|
import com.google.common.collect.HashBasedTable;
|
||||||
import net.minecraft.client.gui.*;
|
import com.google.common.collect.HashMultimap;
|
||||||
|
import com.google.common.collect.SetMultimap;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import com.google.common.collect.Table;
|
||||||
|
import net.minecraft.client.gui.Gui;
|
||||||
|
import net.minecraft.client.gui.GuiMultiplayer;
|
||||||
|
import net.minecraft.client.gui.GuiWorldSelection;
|
||||||
|
import net.minecraftforge.fml.ExtensionPoint;
|
||||||
import net.minecraftforge.fml.ForgeI18n;
|
import net.minecraftforge.fml.ForgeI18n;
|
||||||
|
import net.minecraftforge.fml.ModList;
|
||||||
import net.minecraftforge.fml.network.FMLNetworkConstants;
|
import net.minecraftforge.fml.network.FMLNetworkConstants;
|
||||||
import net.minecraftforge.fml.network.NetworkRegistry;
|
import net.minecraftforge.fml.network.NetworkRegistry;
|
||||||
import net.minecraftforge.registries.RegistryManager;
|
|
||||||
import net.minecraftforge.versions.forge.ForgeVersion;
|
import net.minecraftforge.versions.forge.ForgeVersion;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.apache.logging.log4j.Marker;
|
import org.apache.logging.log4j.Marker;
|
||||||
|
@ -70,36 +80,59 @@ public class ClientHooks
|
||||||
|
|
||||||
private static final ResourceLocation iconSheet = new ResourceLocation(ForgeVersion.MOD_ID, "textures/gui/icons.png");
|
private static final ResourceLocation iconSheet = new ResourceLocation(ForgeVersion.MOD_ID, "textures/gui/icons.png");
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|
||||||
public static void processForgeListPingData(ServerStatusResponse packet, ServerData target)
|
public static void processForgeListPingData(ServerStatusResponse packet, ServerData target)
|
||||||
{
|
{
|
||||||
if(packet.getForgeData() != null){
|
if (packet.getForgeData() != null) {
|
||||||
int numberOfMods = packet.getForgeData().getNumberOfMods();
|
final Map<String, String> mods = packet.getForgeData().getRemoteModData();
|
||||||
int fmlver = packet.getForgeData().getFMLNetworkVersion();
|
final Map<ResourceLocation, Pair<String, Boolean>> remoteChannels = packet.getForgeData().getRemoteChannels();
|
||||||
|
final int fmlver = packet.getForgeData().getFMLNetworkVersion();
|
||||||
|
|
||||||
boolean b = NetworkRegistry.checkListPingCompatibilityForClient(packet.getForgeData().getPresentMods())
|
boolean fmlNetMatches = fmlver == FMLNetworkConstants.FMLNETVERSION;
|
||||||
&& fmlver == FMLNetworkConstants.FMLNETVERSION;
|
boolean channelsMatch = NetworkRegistry.checkListPingCompatibilityForClient(remoteChannels);
|
||||||
|
AtomicBoolean result = new AtomicBoolean(true);
|
||||||
|
ModList.get().forEachModContainer((modid, mc)-> mc.getCustomExtension(ExtensionPoint.DISPLAYTEST).ifPresent(ext->
|
||||||
|
result.compareAndSet(true, ext.getRight().test(mods.get(modid), true))));
|
||||||
|
boolean modsMatch = result.get();
|
||||||
|
|
||||||
LOGGER.debug(CLIENTHOOKS, "Received FML ping data from server at {}: FMLNETVER={}, {} mods, channels: [{}] - compatible: {}", target.serverIP, fmlver, numberOfMods, packet.getForgeData().getPresentMods().entrySet(), b);
|
final Map<String, String> extraServerMods = mods.entrySet().stream().
|
||||||
|
filter(e -> !Objects.equals(FMLNetworkConstants.IGNORESERVERONLY, e.getValue())).
|
||||||
|
filter(e -> !ModList.get().isLoaded(e.getKey())).
|
||||||
|
collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||||
|
|
||||||
|
LOGGER.debug(CLIENTHOOKS, "Received FML ping data from server at {}: FMLNETVER={}, mod list is compatible : {}, channel list is compatible: {}, extra server mods: {}", target.serverIP, fmlver, modsMatch, channelsMatch, extraServerMods);
|
||||||
|
|
||||||
String extraReason = null;
|
String extraReason = null;
|
||||||
if(fmlver<FMLNetworkConstants.FMLNETVERSION)
|
|
||||||
extraReason = "fml.menu.multiplayer.serveroutdated";
|
|
||||||
else if(fmlver > FMLNetworkConstants.FMLNETVERSION)
|
|
||||||
extraReason = "fml.menu.multiplayer.clientoutdated";
|
|
||||||
|
|
||||||
target.forgeData = new ExtendedServerListData("FML", b, packet.getForgeData().getPresentMods(), numberOfMods, extraReason);
|
if (!extraServerMods.isEmpty()) {
|
||||||
}else{
|
extraReason = "fml.menu.multiplayer.extraservermods";
|
||||||
target.forgeData = new ExtendedServerListData("VANILLA", NetworkRegistry.canConnectToVanillaServer(), Maps.newHashMap(), 0, null);
|
}
|
||||||
|
if (!modsMatch) {
|
||||||
|
extraReason = "fml.menu.multiplayer.modsincompatible";
|
||||||
|
}
|
||||||
|
if (!channelsMatch) {
|
||||||
|
extraReason = "fml.menu.multiplayer.networkincompatible";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fmlver < FMLNetworkConstants.FMLNETVERSION) {
|
||||||
|
extraReason = "fml.menu.multiplayer.serveroutdated";
|
||||||
|
}
|
||||||
|
if (fmlver > FMLNetworkConstants.FMLNETVERSION) {
|
||||||
|
extraReason = "fml.menu.multiplayer.clientoutdated";
|
||||||
|
}
|
||||||
|
target.forgeData = new ExtendedServerListData("FML", extraServerMods.isEmpty() && fmlNetMatches && channelsMatch && modsMatch, mods.size(), extraReason);
|
||||||
|
} else {
|
||||||
|
target.forgeData = new ExtendedServerListData("VANILLA", NetworkRegistry.canConnectToVanillaServer(),0, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void drawForgePingInfo(GuiMultiplayer gui, ServerData target, int x, int y, int width, int relativeMouseX, int relativeMouseY){
|
public static void drawForgePingInfo(GuiMultiplayer gui, ServerData target, int x, int y, int width, int relativeMouseX, int relativeMouseY) {
|
||||||
int idx;
|
int idx;
|
||||||
String tooltip;
|
String tooltip;
|
||||||
if(target.forgeData == null)
|
if (target.forgeData == null)
|
||||||
return;
|
return;
|
||||||
switch (target.forgeData.type){
|
switch (target.forgeData.type) {
|
||||||
case "FML":
|
case "FML":
|
||||||
if (target.forgeData.isCompatible) {
|
if (target.forgeData.isCompatible) {
|
||||||
idx = 0;
|
idx = 0;
|
||||||
|
@ -115,7 +148,7 @@ public class ClientHooks
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "VANILLA":
|
case "VANILLA":
|
||||||
if(target.forgeData.isCompatible) {
|
if (target.forgeData.isCompatible) {
|
||||||
idx = 48;
|
idx = 48;
|
||||||
tooltip = ForgeI18n.parseMessage("fml.menu.multiplayer.vanilla");
|
tooltip = ForgeI18n.parseMessage("fml.menu.multiplayer.vanilla");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -19,23 +19,16 @@
|
||||||
|
|
||||||
package net.minecraftforge.fml.client;
|
package net.minecraftforge.fml.client;
|
||||||
|
|
||||||
import net.minecraft.util.ResourceLocation;
|
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class ExtendedServerListData {
|
public class ExtendedServerListData {
|
||||||
public final String type;
|
public final String type;
|
||||||
public final boolean isCompatible;
|
public final boolean isCompatible;
|
||||||
public final Map<ResourceLocation, Pair<String, Boolean>> channelData;
|
|
||||||
public int numberOfMods;
|
public int numberOfMods;
|
||||||
public String extraReason;
|
public String extraReason;
|
||||||
|
|
||||||
public ExtendedServerListData(String type, boolean isCompatible, Map<ResourceLocation, Pair<String, Boolean>> channelData, int num, String extraReason)
|
public ExtendedServerListData(String type, boolean isCompatible, int num, String extraReason)
|
||||||
{
|
{
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.isCompatible = isCompatible;
|
this.isCompatible = isCompatible;
|
||||||
this.channelData = channelData;
|
|
||||||
this.numberOfMods = num;
|
this.numberOfMods = num;
|
||||||
this.extraReason = extraReason;
|
this.extraReason = extraReason;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,4 +42,8 @@ public class FMLNetworkConstants
|
||||||
static final ResourceLocation FML_PLAY_RESOURCE = new ResourceLocation("fml:play");
|
static final ResourceLocation FML_PLAY_RESOURCE = new ResourceLocation("fml:play");
|
||||||
static final SimpleChannel handshakeChannel = NetworkInitialization.getHandshakeChannel();
|
static final SimpleChannel handshakeChannel = NetworkInitialization.getHandshakeChannel();
|
||||||
static final SimpleChannel playChannel = NetworkInitialization.getPlayChannel();
|
static final SimpleChannel playChannel = NetworkInitialization.getPlayChannel();
|
||||||
|
/**
|
||||||
|
* Return this value in your {@link net.minecraftforge.fml.ExtensionPoint#DISPLAYTEST} function to be ignored.
|
||||||
|
*/
|
||||||
|
public static final String IGNORESERVERONLY = "OHNOES\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31";
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,80 +20,124 @@
|
||||||
package net.minecraftforge.fml.network;
|
package net.minecraftforge.fml.network;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.*;
|
import com.google.gson.JsonDeserializationContext;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonSerializationContext;
|
||||||
|
import com.google.gson.JsonSyntaxException;
|
||||||
import net.minecraft.util.JsonUtils;
|
import net.minecraft.util.JsonUtils;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import net.minecraftforge.fml.ExtensionPoint;
|
||||||
import net.minecraftforge.fml.ModList;
|
import net.minecraftforge.fml.ModList;
|
||||||
import net.minecraftforge.registries.RegistryManager;
|
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.StreamSupport;
|
||||||
|
|
||||||
|
import static net.minecraftforge.fml.network.FMLNetworkConstants.NETWORK;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {
|
||||||
|
* "fmlNetworkVersion" : FMLNETVERSION,
|
||||||
|
* "channels": [
|
||||||
|
* {
|
||||||
|
* "res": "fml:handshake",
|
||||||
|
* "version": "1.2.3.4",
|
||||||
|
* "required": true
|
||||||
|
* }
|
||||||
|
* ],
|
||||||
|
* "mods": [
|
||||||
|
* {
|
||||||
|
* "modid": "modid",
|
||||||
|
* "modmarker": "<somestring>"
|
||||||
|
* }
|
||||||
|
* ]
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
*/
|
||||||
public class FMLStatusPing {
|
public class FMLStatusPing {
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
|
|
||||||
private Map<ResourceLocation, Pair<String, Boolean>> channelVersions;
|
private transient Map<ResourceLocation, Pair<String, Boolean>> channels;
|
||||||
private int numberOfMods;
|
private transient Map<String, String> mods;
|
||||||
private int fmlNetworkVer;
|
private transient int fmlNetworkVer;
|
||||||
|
public FMLStatusPing() {
|
||||||
public FMLStatusPing(){
|
this.channels = NetworkRegistry.buildChannelVersionsForListPing();
|
||||||
this.channelVersions = NetworkRegistry.buildChannelVersionsForListPing();
|
this.mods = new HashMap<>();
|
||||||
this.numberOfMods = ModList.get().size();
|
ModList.get().forEachModContainer((modid, mc) ->
|
||||||
|
mods.put(modid, mc.getCustomExtension(ExtensionPoint.DISPLAYTEST).
|
||||||
|
map(Pair::getLeft).map(Supplier::get).orElse(FMLNetworkConstants.IGNORESERVERONLY)));
|
||||||
this.fmlNetworkVer = FMLNetworkConstants.FMLNETVERSION;
|
this.fmlNetworkVer = FMLNetworkConstants.FMLNETVERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
private FMLStatusPing(Map<ResourceLocation, Pair<String, Boolean>> deserialized, int nom, int fmlNetVer){
|
private FMLStatusPing(Map<ResourceLocation, Pair<String, Boolean>> deserialized, Map<String,String> modMarkers, int fmlNetVer) {
|
||||||
this.channelVersions = ImmutableMap.copyOf(deserialized);
|
this.channels = ImmutableMap.copyOf(deserialized);
|
||||||
this.numberOfMods = nom;
|
this.mods = modMarkers;
|
||||||
this.fmlNetworkVer = fmlNetVer;
|
this.fmlNetworkVer = fmlNetVer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Serializer {
|
public static class Serializer {
|
||||||
|
|
||||||
public static FMLStatusPing deserialize(JsonObject forgeData, JsonDeserializationContext ctx) {
|
public static FMLStatusPing deserialize(JsonObject forgeData, JsonDeserializationContext ctx) {
|
||||||
try {
|
try {
|
||||||
JsonArray mods = JsonUtils.getJsonArray(forgeData, "mods");
|
final Map<ResourceLocation, Pair<String, Boolean>> channels = StreamSupport.stream(JsonUtils.getJsonArray(forgeData, "channels").spliterator(), false).
|
||||||
Map<ResourceLocation, Pair<String, Boolean>> versions = Maps.newHashMap();
|
map(JsonElement::getAsJsonObject).
|
||||||
for(JsonElement el : mods){
|
collect(Collectors.toMap(jo -> new ResourceLocation(JsonUtils.getString(jo, "res")),
|
||||||
JsonObject jo = el.getAsJsonObject();
|
jo -> Pair.of(JsonUtils.getString(jo, "version"), JsonUtils.getBoolean(jo, "required")))
|
||||||
ResourceLocation name = new ResourceLocation(JsonUtils.getString(jo, "namespace"), JsonUtils.getString(jo, "path"));
|
);
|
||||||
String version = JsonUtils.getString(jo, "version");
|
|
||||||
Boolean canBeAbsent = JsonUtils.getBoolean(jo, "mayBeAbsent");
|
final Map<String, String> mods = StreamSupport.stream(JsonUtils.getJsonArray(forgeData, "mods").spliterator(), false).
|
||||||
versions.put(name, Pair.of(version, canBeAbsent));
|
map(JsonElement::getAsJsonObject).
|
||||||
}
|
collect(Collectors.toMap(jo -> JsonUtils.getString(jo, "modId"), jo->JsonUtils.getString(jo, "modmarker")));
|
||||||
return new FMLStatusPing(versions, JsonUtils.getInt(forgeData, "numberOfMods"), JsonUtils.getInt(forgeData, "fmlNetworkVersion"));
|
|
||||||
}catch (Exception c){
|
final int remoteFMLVersion = JsonUtils.getInt(forgeData, "fmlNetworkVersion");
|
||||||
|
return new FMLStatusPing(channels, mods, remoteFMLVersion);
|
||||||
|
} catch (JsonSyntaxException e) {
|
||||||
|
LOGGER.debug(NETWORK, "Encountered an error parsing status ping data", e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static JsonObject serialize(FMLStatusPing forgeData, JsonSerializationContext ctx){
|
public static JsonObject serialize(FMLStatusPing forgeData, JsonSerializationContext ctx) {
|
||||||
JsonObject obj = new JsonObject();
|
JsonObject obj = new JsonObject();
|
||||||
JsonArray mods = new JsonArray();
|
JsonArray channels = new JsonArray();
|
||||||
forgeData.channelVersions.entrySet().stream().map(p -> {
|
forgeData.channels.forEach((namespace, version) -> {
|
||||||
JsonObject mi = new JsonObject();
|
JsonObject mi = new JsonObject();
|
||||||
mi.addProperty("namespace", p.getKey().getNamespace());
|
mi.addProperty("res", namespace.toString());
|
||||||
mi.addProperty("path", p.getKey().getPath());
|
mi.addProperty("version", version.getLeft());
|
||||||
mi.addProperty("version", p.getValue().getKey());
|
mi.addProperty("required", version.getRight());
|
||||||
mi.addProperty("mayBeAbsent", p.getValue().getValue());
|
channels.add(mi);
|
||||||
return mi;
|
});
|
||||||
}).forEach(mods::add);
|
|
||||||
obj.add("mods", mods);
|
obj.add("channels", channels);
|
||||||
obj.addProperty("numberOfMods", forgeData.numberOfMods);
|
|
||||||
|
JsonArray modTestValues = new JsonArray();
|
||||||
|
forgeData.mods.forEach((modId, value) -> {
|
||||||
|
JsonObject mi = new JsonObject();
|
||||||
|
mi.addProperty("modId", modId);
|
||||||
|
mi.addProperty("modmarker", value);
|
||||||
|
modTestValues.add(mi);
|
||||||
|
});
|
||||||
|
obj.add("mods", modTestValues);
|
||||||
obj.addProperty("fmlNetworkVersion", forgeData.fmlNetworkVer);
|
obj.addProperty("fmlNetworkVersion", forgeData.fmlNetworkVer);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<ResourceLocation, Pair<String, Boolean>> getPresentMods(){
|
public Map<ResourceLocation, Pair<String, Boolean>> getRemoteChannels() {
|
||||||
return this.channelVersions;
|
return this.channels;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getNumberOfMods(){
|
public Map<String,String> getRemoteModData() {
|
||||||
return numberOfMods;
|
return mods;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getFMLNetworkVersion(){
|
public int getFMLNetworkVersion() {
|
||||||
return fmlNetworkVer;
|
return fmlNetworkVer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,14 +15,17 @@
|
||||||
"fml.menu.mods.info.childmods":"Child mods: {0}",
|
"fml.menu.mods.info.childmods":"Child mods: {0}",
|
||||||
"fml.menu.mods.info.updateavailable":"Update available: {0}",
|
"fml.menu.mods.info.updateavailable":"Update available: {0}",
|
||||||
"fml.menu.mods.info.changelogheader":"Changelog:",
|
"fml.menu.mods.info.changelogheader":"Changelog:",
|
||||||
"fml.menu.multiplayer.compatible":"Compatible FML modded server, {0,choice,1#1 mod|1<{0} mods} present",
|
"fml.menu.multiplayer.compatible":"Compatible FML modded server\n{0,choice,1#1 mod|1<{0} mods} present",
|
||||||
"fml.menu.multiplayer.incompatible":"Incompatible FML modded server",
|
"fml.menu.multiplayer.incompatible":"Incompatible FML modded server",
|
||||||
"fml.menu.multiplayer.incompatible.extra":"Incompatible FML modded server - {}",
|
"fml.menu.multiplayer.incompatible.extra":"Incompatible FML modded server\n{0}",
|
||||||
"fml.menu.multiplayer.vanilla":"Vanilla server",
|
"fml.menu.multiplayer.vanilla":"Vanilla server",
|
||||||
"fml.menu.multiplayer.vanilla.incompatible":"Incompatible Vanilla server",
|
"fml.menu.multiplayer.vanilla.incompatible":"Incompatible Vanilla server",
|
||||||
"fml.menu.multiplayer.unknown":"Unknown server {0}",
|
"fml.menu.multiplayer.unknown":"Unknown server {0}",
|
||||||
"fml.menu.multiplayer.serveroutdated":"Outdated server",
|
"fml.menu.multiplayer.serveroutdated":"The Forge server network version is outdated",
|
||||||
"fml.menu.multiplayer.clientoutdated":"Outdated client",
|
"fml.menu.multiplayer.clientoutdated":"The Forge client network version is outdated",
|
||||||
|
"fml.menu.multiplayer.extraservermods":"The Server has additional mods that may be needed on the client",
|
||||||
|
"fml.menu.multiplayer.modsincompatible":"The Server's mods are not compatible",
|
||||||
|
"fml.menu.multiplayer.networkincompatible":"The Server's network messages are not compatible",
|
||||||
"fml.menu.loadingmods": "{0,choice,0#No mods|1#1 mod|1<{0} mods} loaded",
|
"fml.menu.loadingmods": "{0,choice,0#No mods|1#1 mod|1<{0} mods} loaded",
|
||||||
"fml.button.open.file": "Open {0}",
|
"fml.button.open.file": "Open {0}",
|
||||||
"fml.button.open.mods.folder": "Open Mods Folder",
|
"fml.button.open.mods.folder": "Open Mods Folder",
|
||||||
|
|
Loading…
Reference in New Issue