Introduce a new centralized version checking system.
Using the @Mod annotation mods can opt-in to a centrally controlled update system. This is PURELY a notification system and will NOT automatically download any updates. The End User can control which mods check for updates and disabel the system entirely using the Forge Config and GUI. Format for the json the URL must point to is described here: https://gist.github.com/LexManos/7aacb9aa991330523884
This commit is contained in:
parent
479c7f8b54
commit
d790008353
11 changed files with 291 additions and 41 deletions
|
@ -6,42 +6,38 @@
|
|||
package net.minecraftforge.client.gui;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraftforge.common.ForgeChunkManager;
|
||||
import net.minecraftforge.common.ForgeModContainer;
|
||||
import net.minecraftforge.common.ForgeVersion;
|
||||
import net.minecraftforge.common.config.ConfigCategory;
|
||||
import net.minecraftforge.common.config.ConfigElement;
|
||||
import net.minecraftforge.common.config.Configuration;
|
||||
import net.minecraftforge.common.config.Property;
|
||||
import net.minecraftforge.fml.client.IModGuiFactory;
|
||||
import net.minecraftforge.fml.client.IModGuiFactory.RuntimeOptionCategoryElement;
|
||||
import net.minecraftforge.fml.client.IModGuiFactory.RuntimeOptionGuiHandler;
|
||||
import net.minecraftforge.fml.client.config.ConfigGuiType;
|
||||
import net.minecraftforge.fml.client.config.DummyConfigElement;
|
||||
import net.minecraftforge.fml.client.config.DummyConfigElement.DummyCategoryElement;
|
||||
import net.minecraftforge.fml.client.config.GuiButtonExt;
|
||||
import net.minecraftforge.fml.client.config.GuiConfig;
|
||||
import net.minecraftforge.fml.client.config.GuiConfigEntries;
|
||||
import net.minecraftforge.fml.client.config.GuiConfigEntries.CategoryEntry;
|
||||
import net.minecraftforge.fml.client.config.GuiConfigEntries.IConfigEntry;
|
||||
import net.minecraftforge.fml.client.config.GuiConfigEntries.SelectValueEntry;
|
||||
import net.minecraftforge.fml.client.config.GuiConfigEntries.BooleanEntry;
|
||||
import net.minecraftforge.fml.client.config.HoverChecker;
|
||||
import net.minecraftforge.fml.client.config.IConfigElement;
|
||||
import net.minecraftforge.fml.client.config.GuiConfigEntries.ListEntryBase;
|
||||
import net.minecraftforge.fml.common.Loader;
|
||||
import net.minecraftforge.fml.common.ModContainer;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
import static net.minecraftforge.common.ForgeModContainer.VERSION_CHECK_CAT;
|
||||
|
||||
/**
|
||||
* This is the base GuiConfig screen class that all the other Forge-specific config screens will be called from.
|
||||
|
@ -109,6 +105,7 @@ public class ForgeGuiFactory implements IModGuiFactory
|
|||
List<IConfigElement> list = new ArrayList<IConfigElement>();
|
||||
list.add(new DummyCategoryElement("forgeCfg", "forge.configgui.ctgy.forgeGeneralConfig", GeneralEntry.class));
|
||||
list.add(new DummyCategoryElement("forgeChunkLoadingCfg", "forge.configgui.ctgy.forgeChunkLoadingConfig", ChunkLoaderEntry.class));
|
||||
list.add(new DummyCategoryElement("forgeVersionCheckCfg", "forge.configgui.ctgy.VersionCheckConfig", VersionCheckEntry.class));
|
||||
return list;
|
||||
}
|
||||
|
||||
|
@ -166,6 +163,59 @@ public class ForgeGuiFactory implements IModGuiFactory
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This custom list entry provides the Forge Version Checking Config entry on the Minecraft Forge Configuration screen.
|
||||
* It extends the base Category entry class and defines the IConfigElement objects that will be used to build the child screen.
|
||||
*/
|
||||
public static class VersionCheckEntry extends CategoryEntry
|
||||
{
|
||||
public VersionCheckEntry(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop)
|
||||
{
|
||||
super(owningScreen, owningEntryList, prop);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GuiScreen buildChildScreen()
|
||||
{
|
||||
ConfigCategory cfg = ForgeModContainer.getConfig().getCategory(VERSION_CHECK_CAT);
|
||||
Map<String, Property> values = new HashMap<String, Property>(cfg.getValues());
|
||||
values.remove("Global");
|
||||
|
||||
Property global = ForgeModContainer.getConfig().get(VERSION_CHECK_CAT, "Global", true);
|
||||
|
||||
List<Property> props = new ArrayList<Property>();
|
||||
|
||||
for (ModContainer mod : ForgeVersion.gatherMods().keySet())
|
||||
{
|
||||
values.remove(mod.getModId());
|
||||
props.add(ForgeModContainer.getConfig().get(VERSION_CHECK_CAT, mod.getModId(), true)); //Get or make the value in the config
|
||||
}
|
||||
props.addAll(values.values()); // Add any left overs from the config
|
||||
Collections.sort(props, new Comparator<Property>()
|
||||
{
|
||||
@Override
|
||||
public int compare(Property o1, Property o2)
|
||||
{
|
||||
return o1.getName().compareTo(o2.getName());
|
||||
}
|
||||
});
|
||||
|
||||
List<IConfigElement> list = new ArrayList<IConfigElement>();
|
||||
list.add(new ConfigElement(global));
|
||||
for (Property prop : props)
|
||||
{
|
||||
list.add(new ConfigElement(prop));
|
||||
}
|
||||
|
||||
// This GuiConfig object specifies the configID of the object and as such will force-save when it is closed. The parent
|
||||
// GuiConfig object's propertyList will also be refreshed to reflect the changes.
|
||||
return new GuiConfig(this.owningScreen,
|
||||
list,
|
||||
this.owningScreen.modID, VERSION_CHECK_CAT, true, true,
|
||||
GuiConfig.getAbridgedConfigPath(ForgeModContainer.getConfig().toString()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This custom list entry provides the Mod Overrides entry on the Forge Chunk Loading config screen.
|
||||
* It extends the base Category entry class and defines the IConfigElement objects that will be used to build the child screen.
|
||||
|
|
|
@ -12,13 +12,14 @@ import static net.minecraftforge.common.ForgeVersion.revisionVersion;
|
|||
import static net.minecraftforge.common.config.Configuration.CATEGORY_GENERAL;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.security.cert.Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.nbt.NBTBase;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.world.storage.SaveHandler;
|
||||
|
@ -58,6 +59,7 @@ import net.minecraftforge.fml.common.network.NetworkRegistry;
|
|||
|
||||
public class ForgeModContainer extends DummyModContainer implements WorldAccessContainer
|
||||
{
|
||||
public static final String VERSION_CHECK_CAT = "version_checking";
|
||||
public static int clumpingThreshold = 64;
|
||||
public static boolean removeErroringEntities = false;
|
||||
public static boolean removeErroringTileEntities = false;
|
||||
|
@ -73,6 +75,13 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC
|
|||
public static boolean forgeLightPipelineEnabled = true;
|
||||
|
||||
private static Configuration config;
|
||||
private static ForgeModContainer INSTANCE;
|
||||
public static ForgeModContainer getInstance()
|
||||
{
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private URL updateJSONUrl = null;
|
||||
|
||||
public ForgeModContainer()
|
||||
{
|
||||
|
@ -82,7 +91,7 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC
|
|||
meta.name = "Minecraft Forge";
|
||||
meta.version = String.format("%d.%d.%d.%d", majorVersion, minorVersion, revisionVersion, buildVersion);
|
||||
meta.credits = "Made possible with help from many people";
|
||||
meta.authorList = Arrays.asList("LexManos", "Eloraam", "Spacetoad");
|
||||
meta.authorList = Arrays.asList("LexManos", "Cpw");
|
||||
meta.description = "Minecraft Forge is a common open source API allowing a broad range of mods " +
|
||||
"to work cooperatively together. It allows many mods to be created without " +
|
||||
"them editing the main Minecraft code.";
|
||||
|
@ -90,12 +99,17 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC
|
|||
meta.updateUrl = "http://MinecraftForge.net/forum/index.php/topic,5.0.html";
|
||||
meta.screenshots = new String[0];
|
||||
meta.logoFile = "/forge_logo.png";
|
||||
try {
|
||||
updateJSONUrl = new URL("http://files.minecraftforge.net/maven/net/minecraftforge/forge/promotions_slim.json");
|
||||
} catch (MalformedURLException e) {}
|
||||
|
||||
config = null;
|
||||
File cfgFile = new File(Loader.instance().getConfigDir(), "forge.cfg");
|
||||
config = new Configuration(cfgFile);
|
||||
|
||||
syncConfig(true);
|
||||
|
||||
INSTANCE = this;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -230,6 +244,12 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC
|
|||
|
||||
config.setCategoryPropertyOrder(CATEGORY_GENERAL, propOrder);
|
||||
|
||||
propOrder = new ArrayList<String>();
|
||||
prop = config.get(VERSION_CHECK_CAT, "Global", true, "Enable the entire mod update check system. This only applies to mods using the Forge system.");
|
||||
propOrder.add("Global");
|
||||
|
||||
config.setCategoryPropertyOrder(VERSION_CHECK_CAT, propOrder);
|
||||
|
||||
if (config.hasChanged())
|
||||
{
|
||||
config.save();
|
||||
|
@ -254,6 +274,10 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC
|
|||
ForgeChunkManager.syncConfigDefaults();
|
||||
ForgeChunkManager.loadConfiguration();
|
||||
}
|
||||
else if (VERSION_CHECK_CAT.equals(event.configID))
|
||||
{
|
||||
syncConfig(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -396,4 +420,10 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC
|
|||
Certificate[] certificates = getClass().getProtectionDomain().getCodeSource().getCertificates();
|
||||
return certificates != null ? certificates[0] : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getUpdateUrl()
|
||||
{
|
||||
return updateJSONUrl;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,13 +8,25 @@ import static net.minecraftforge.common.ForgeVersion.Status.*;
|
|||
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.apache.logging.log4j.Level;
|
||||
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
import net.minecraftforge.fml.common.versioning.ArtifactVersion;
|
||||
import net.minecraftforge.fml.common.versioning.DefaultArtifactVersion;
|
||||
import net.minecraftforge.fml.common.FMLLog;
|
||||
import net.minecraftforge.fml.common.InjectedModContainer;
|
||||
import net.minecraftforge.fml.common.Loader;
|
||||
import net.minecraftforge.fml.common.ModContainer;
|
||||
import net.minecraftforge.fml.common.versioning.ComparableVersion;
|
||||
|
||||
public class ForgeVersion
|
||||
{
|
||||
|
@ -55,12 +67,13 @@ public class ForgeVersion
|
|||
|
||||
public static Status getStatus()
|
||||
{
|
||||
return status;
|
||||
return getResult(ForgeModContainer.getInstance()).status;
|
||||
}
|
||||
|
||||
public static String getTarget()
|
||||
{
|
||||
return target;
|
||||
CheckResult res = getResult(ForgeModContainer.getInstance());
|
||||
return res.target != null ? res.target.toString() : null;
|
||||
}
|
||||
|
||||
public static String getVersion()
|
||||
|
@ -79,32 +92,75 @@ public class ForgeVersion
|
|||
BETA_OUTDATED
|
||||
}
|
||||
|
||||
public static class CheckResult
|
||||
{
|
||||
public final Status status;
|
||||
public final ComparableVersion target;
|
||||
public final Map<ComparableVersion, String> changes;
|
||||
public final String url;
|
||||
|
||||
private CheckResult(Status status, ComparableVersion target, Map<ComparableVersion, String> changes, String url)
|
||||
{
|
||||
this.status = status;
|
||||
this.target = target;
|
||||
this.changes = changes == null ? null : Collections.unmodifiableMap(changes);
|
||||
this.url = url;
|
||||
}
|
||||
}
|
||||
|
||||
public static void startVersionCheck()
|
||||
{
|
||||
new Thread("Forge Version Check")
|
||||
{
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if (!ForgeModContainer.getConfig().get(ForgeModContainer.VERSION_CHECK_CAT, "Global", true).getBoolean())
|
||||
{
|
||||
FMLLog.log("ForgeVersionCheck", Level.INFO, "Global Forge version check system disabeld, no futher processing.");
|
||||
return;
|
||||
}
|
||||
|
||||
for (Entry<ModContainer, URL> entry : gatherMods().entrySet())
|
||||
{
|
||||
ModContainer mod = entry.getKey();
|
||||
if (ForgeModContainer.getConfig().get(ForgeModContainer.VERSION_CHECK_CAT, mod.getModId(), true).getBoolean())
|
||||
{
|
||||
process(mod, entry.getValue());
|
||||
}
|
||||
else
|
||||
{
|
||||
FMLLog.log("ForgeVersionCheck", Level.INFO, "[%s] Skipped version check", mod.getModId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void process(ModContainer mod, URL url)
|
||||
{
|
||||
try
|
||||
{
|
||||
URL url = new URL("http://files.minecraftforge.net/maven/net/minecraftforge/forge/promotions_slim.json");
|
||||
FMLLog.log("ForgeVersionCheck", Level.INFO, "[%s] Starting version check at %s", mod.getModId(), url.toString());
|
||||
Status status = PENDING;
|
||||
ComparableVersion target = null;
|
||||
|
||||
InputStream con = url.openStream();
|
||||
String data = new String(ByteStreams.toByteArray(con));
|
||||
con.close();
|
||||
|
||||
FMLLog.log("ForgeVersionCheck", Level.DEBUG, "[%s] Received version check data:\n%s", mod.getModId(), data);
|
||||
|
||||
|
||||
Map<String, Object> json = new Gson().fromJson(data, Map.class);
|
||||
//String homepage = (String)json.get("homepage");
|
||||
Map<String, String> promos = (Map<String, String>)json.get("promos");
|
||||
String display_url = (String)json.get("homepage");
|
||||
|
||||
String rec = promos.get(MinecraftForge.MC_VERSION + "-recommended");
|
||||
String lat = promos.get(MinecraftForge.MC_VERSION + "-latest");
|
||||
ArtifactVersion current = new DefaultArtifactVersion(getVersion());
|
||||
ComparableVersion current = new ComparableVersion(mod.getVersion());
|
||||
|
||||
if (rec != null)
|
||||
{
|
||||
ArtifactVersion recommended = new DefaultArtifactVersion(rec);
|
||||
ComparableVersion recommended = new ComparableVersion(rec);
|
||||
int diff = recommended.compareTo(current);
|
||||
|
||||
if (diff == 0)
|
||||
|
@ -114,39 +170,95 @@ public class ForgeVersion
|
|||
status = AHEAD;
|
||||
if (lat != null)
|
||||
{
|
||||
if (current.compareTo(new DefaultArtifactVersion(lat)) < 0)
|
||||
ComparableVersion latest = new ComparableVersion(lat);
|
||||
if (current.compareTo(latest) < 0)
|
||||
{
|
||||
status = OUTDATED;
|
||||
target = lat;
|
||||
target = latest;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = OUTDATED;
|
||||
target = rec;
|
||||
target = recommended;
|
||||
}
|
||||
}
|
||||
else if (lat != null)
|
||||
{
|
||||
if (current.compareTo(new DefaultArtifactVersion(lat)) < 0)
|
||||
ComparableVersion latest = new ComparableVersion(lat);
|
||||
if (current.compareTo(latest) < 0)
|
||||
{
|
||||
status = BETA_OUTDATED;
|
||||
target = lat;
|
||||
target = latest;
|
||||
}
|
||||
else
|
||||
status = BETA;
|
||||
}
|
||||
else
|
||||
status = BETA;
|
||||
|
||||
FMLLog.log("ForgeVersionCheck", Level.INFO, "[%s] Found status: %s Target: %s", mod.getModId(), status, target);
|
||||
|
||||
Map<ComparableVersion, String> changes = new LinkedHashMap<ComparableVersion, String>();
|
||||
Map<String, String> tmp = (Map<String, String>)json.get(MinecraftForge.MC_VERSION);
|
||||
if (tmp != null)
|
||||
{
|
||||
List<ComparableVersion> ordered = new ArrayList<ComparableVersion>();
|
||||
for (String key : tmp.keySet())
|
||||
{
|
||||
ComparableVersion ver = new ComparableVersion(key);
|
||||
if (ver.compareTo(current) > 0 && (target == null || ver.compareTo(target) < 1))
|
||||
{
|
||||
ordered.add(ver);
|
||||
}
|
||||
}
|
||||
Collections.sort(ordered);
|
||||
|
||||
for (ComparableVersion ver : ordered)
|
||||
{
|
||||
changes.put(ver, tmp.get(ver.toString()));
|
||||
}
|
||||
}
|
||||
if (mod instanceof InjectedModContainer)
|
||||
mod = ((InjectedModContainer)mod).wrappedContainer;
|
||||
results.put(mod, new CheckResult(status, target, changes, display_url));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
FMLLog.log("ForgeVersionCheck", Level.DEBUG, e, "Failed to process update information");
|
||||
status = FAILED;
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
// Gather a list of mods that have opted in to this update system by providing a URL.
|
||||
// Small hack needed to support a interface change until we force a recompile.
|
||||
public static Map<ModContainer, URL> gatherMods()
|
||||
{
|
||||
Map<ModContainer, URL> ret = new HashMap<ModContainer, URL>();
|
||||
for (ModContainer mod : Loader.instance().getActiveModList())
|
||||
{
|
||||
URL url = null;
|
||||
try {
|
||||
url = mod.getUpdateUrl();
|
||||
} catch (AbstractMethodError abs) { } //TODO: Remove this in 1.8.8+?
|
||||
if (url != null)
|
||||
ret.put(mod, url);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static Map<ModContainer, CheckResult> results = new ConcurrentHashMap<ModContainer, CheckResult>();
|
||||
private static final CheckResult PENDING_CHECK = new CheckResult(PENDING, null, null, null);
|
||||
|
||||
public static CheckResult getResult(ModContainer mod)
|
||||
{
|
||||
if (mod instanceof InjectedModContainer)
|
||||
mod = ((InjectedModContainer)mod).wrappedContainer;
|
||||
CheckResult ret = results.get(mod);
|
||||
return ret == null ? PENDING_CHECK : ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
|
@ -43,10 +44,14 @@ import net.minecraft.util.IChatComponent;
|
|||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.StringUtils;
|
||||
import net.minecraftforge.common.ForgeHooks;
|
||||
import net.minecraftforge.common.ForgeVersion;
|
||||
import net.minecraftforge.common.ForgeVersion.CheckResult;
|
||||
import net.minecraftforge.common.ForgeVersion.Status;
|
||||
import net.minecraftforge.fml.common.FMLLog;
|
||||
import net.minecraftforge.fml.common.Loader;
|
||||
import net.minecraftforge.fml.common.ModContainer;
|
||||
import net.minecraftforge.fml.common.ModContainer.Disableable;
|
||||
import net.minecraftforge.fml.common.versioning.ComparableVersion;
|
||||
import static net.minecraft.util.EnumChatFormatting.*;
|
||||
|
||||
import org.apache.logging.log4j.Level;
|
||||
|
@ -343,7 +348,7 @@ public class GuiModList extends GuiScreen
|
|||
ResourceLocation logoPath = null;
|
||||
Dimension logoDims = new Dimension(0, 0);
|
||||
List<String> lines = new ArrayList<String>();
|
||||
//CheckResult vercheck = ForgeVersion.getResult(selectedMod);
|
||||
CheckResult vercheck = ForgeVersion.getResult(selectedMod);
|
||||
|
||||
String logoFile = selectedMod.getMetadata().logoFile;
|
||||
if (!logoFile.isEmpty())
|
||||
|
@ -408,8 +413,8 @@ public class GuiModList extends GuiScreen
|
|||
else
|
||||
lines.add("Child mods: " + selectedMod.getMetadata().getChildModList());
|
||||
|
||||
//if (vercheck.status == Status.OUTDATED || vercheck.status == Status.BETA_OUTDATED)
|
||||
// lines.add("Update Avalible: " + (vercheck.url == null ? "" : vercheck.url));
|
||||
if (vercheck.status == Status.OUTDATED || vercheck.status == Status.BETA_OUTDATED)
|
||||
lines.add("Update Avalible: " + (vercheck.url == null ? "" : vercheck.url));
|
||||
|
||||
lines.add(null);
|
||||
lines.add(selectedMod.getMetadata().description);
|
||||
|
@ -419,15 +424,15 @@ public class GuiModList extends GuiScreen
|
|||
lines.add(WHITE + selectedMod.getName());
|
||||
lines.add(WHITE + "Version: " + selectedMod.getVersion());
|
||||
lines.add(WHITE + "Mod State: " + Loader.instance().getModState(selectedMod));
|
||||
//if (vercheck.status == Status.OUTDATED || vercheck.status == Status.BETA_OUTDATED)
|
||||
// lines.add("Update Avalible: " + (vercheck.url == null ? "" : vercheck.url));
|
||||
if (vercheck.status == Status.OUTDATED || vercheck.status == Status.BETA_OUTDATED)
|
||||
lines.add("Update Avalible: " + (vercheck.url == null ? "" : vercheck.url));
|
||||
|
||||
lines.add(null);
|
||||
lines.add(RED + "No mod information found");
|
||||
lines.add(RED + "Ask your mod author to provide a mod mcmod.info file");
|
||||
}
|
||||
|
||||
/*if ((vercheck.status == Status.OUTDATED || vercheck.status == Status.BETA_OUTDATED) && vercheck.changes.size() > 0)
|
||||
if ((vercheck.status == Status.OUTDATED || vercheck.status == Status.BETA_OUTDATED) && vercheck.changes.size() > 0)
|
||||
{
|
||||
lines.add(null);
|
||||
lines.add("Changes:");
|
||||
|
@ -437,7 +442,7 @@ public class GuiModList extends GuiScreen
|
|||
lines.add(entry.getValue());
|
||||
lines.add(null);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
modInfo = new Info(this.width - this.listWidth - 30, lines, logoPath, logoDims);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ import java.util.ArrayList;
|
|||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.util.StringUtils;
|
||||
import net.minecraftforge.common.ForgeVersion;
|
||||
import net.minecraftforge.common.ForgeVersion.CheckResult;
|
||||
import net.minecraftforge.fml.common.Loader;
|
||||
import net.minecraftforge.fml.common.LoaderState.ModState;
|
||||
import net.minecraftforge.fml.common.ModContainer;
|
||||
|
@ -79,7 +81,7 @@ public class GuiSlotModList extends GuiScrollingList
|
|||
String name = StringUtils.stripControlCodes(mc.getName());
|
||||
String version = StringUtils.stripControlCodes(mc.getDisplayVersion());
|
||||
FontRenderer font = this.parent.getFontRenderer();
|
||||
//CheckResult vercheck = ForgeVersion.getResult(mc);
|
||||
CheckResult vercheck = ForgeVersion.getResult(mc);
|
||||
|
||||
if (Loader.instance().getModState(mc) == ModState.DISABLED)
|
||||
{
|
||||
|
@ -93,7 +95,7 @@ public class GuiSlotModList extends GuiScrollingList
|
|||
font.drawString(font.trimStringToWidth(version, listWidth - 10), this.left + 3 , top + 12, 0xCCCCCC);
|
||||
font.drawString(font.trimStringToWidth(mc.getMetadata() != null ? mc.getMetadata().getChildModCountString() : "Metadata not found", listWidth - 10), this.left + 3 , top + 22, 0xCCCCCC);
|
||||
|
||||
/*switch(vercheck.status) //TODO: Change to icons?
|
||||
switch(vercheck.status) //TODO: Change to icons?
|
||||
{
|
||||
case BETA_OUTDATED:
|
||||
case OUTDATED:
|
||||
|
@ -105,8 +107,7 @@ public class GuiSlotModList extends GuiScrollingList
|
|||
case PENDING:
|
||||
case UP_TO_DATE:
|
||||
break;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
package net.minecraftforge.fml.common;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.security.cert.Certificate;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
@ -206,4 +207,10 @@ public class DummyModContainer implements ModContainer
|
|||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getUpdateUrl()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ import java.lang.annotation.Annotation;
|
|||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.security.cert.Certificate;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
@ -87,6 +89,7 @@ public class FMLModContainer implements ModContainer
|
|||
private ListMultimap<Class<? extends FMLEvent>,Method> eventMethods;
|
||||
private Map<String, String> customModProperties;
|
||||
private ModCandidate candidate;
|
||||
private URL updateJSONUrl;
|
||||
|
||||
public FMLModContainer(String className, ModCandidate container, Map<String,Object> modDescriptor)
|
||||
{
|
||||
|
@ -215,6 +218,19 @@ public class FMLModContainer implements ModContainer
|
|||
{
|
||||
minecraftAccepted = Loader.instance().getMinecraftModContainer().getStaticVersionRange();
|
||||
}
|
||||
|
||||
String jsonURL = (String)descriptor.get("updateJSON");
|
||||
if (!Strings.isNullOrEmpty(jsonURL))
|
||||
{
|
||||
try
|
||||
{
|
||||
this.updateJSONUrl = new URL(jsonURL);
|
||||
}
|
||||
catch (MalformedURLException e)
|
||||
{
|
||||
FMLLog.log(getModId(), Level.DEBUG, "Specified json URL invalid: %s", jsonURL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Properties searchForVersionProperties()
|
||||
|
@ -663,4 +679,10 @@ public class FMLModContainer implements ModContainer
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getUpdateUrl()
|
||||
{
|
||||
return updateJSONUrl;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
package net.minecraftforge.fml.common;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.security.cert.Certificate;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -207,4 +208,10 @@ public class InjectedModContainer implements ModContainer
|
|||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getUpdateUrl()
|
||||
{
|
||||
return wrappedContainer.getUpdateUrl();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -157,18 +157,18 @@ public @interface Mod
|
|||
* @return The language the mod is authored in
|
||||
*/
|
||||
String modLanguage() default "java";
|
||||
|
||||
|
||||
/**
|
||||
* The language adapter to be used to load this mod. This overrides the value of modLanguage. The class must have a
|
||||
* public zero variable constructor and implement {@link ILanguageAdapter} just like the Java and Scala adapters.
|
||||
*
|
||||
*
|
||||
* A class with an invalid constructor or that doesn't implement {@link ILanguageAdapter} will throw an exception and
|
||||
* halt loading.
|
||||
*
|
||||
*
|
||||
* @return The full class name of the language adapter
|
||||
*/
|
||||
String modLanguageAdapter() default "";
|
||||
|
||||
|
||||
/**
|
||||
* NOT YET IMPLEMENTED. </br>
|
||||
* An optional ASM hook class, that can be used to apply ASM to classes loaded from this mod. It is also given
|
||||
|
@ -198,6 +198,14 @@ public @interface Mod
|
|||
* @return The name of a class implementing {@link IModGuiFactory}
|
||||
*/
|
||||
String guiFactory() default "";
|
||||
|
||||
/**
|
||||
* An optional URL to a JSON file that will be checked once per launch to determine if there is an updated
|
||||
* version of this mod and notify the end user. For more information see ForgeVersion.
|
||||
* @return URL to update metadata json
|
||||
*/
|
||||
String updateJSON() default "";
|
||||
|
||||
/**
|
||||
* A list of custom properties for this mod. Completely up to the mod author if/when they
|
||||
* want to put anything in here.
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
package net.minecraftforge.fml.common;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.security.cert.Certificate;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -149,4 +150,6 @@ public interface ModContainer
|
|||
List<String> getOwnedPackages();
|
||||
|
||||
boolean shouldLoadInEnvironment();
|
||||
|
||||
URL getUpdateUrl();
|
||||
}
|
||||
|
|
|
@ -35,7 +35,12 @@ public class ModMetadata
|
|||
public String description = "";
|
||||
|
||||
public String url = "";
|
||||
@Deprecated //Never really used for anything and format is undefined. See updateJSON for replacement.
|
||||
public String updateUrl = "";
|
||||
/**
|
||||
* URL to update json file. Format is defined here: https://gist.github.com/LexManos/7aacb9aa991330523884
|
||||
*/
|
||||
public String updateJSON = "";
|
||||
|
||||
public String logoFile = "";
|
||||
public String version = "";
|
||||
|
|
Loading…
Reference in a new issue