Compare commits

...

17 Commits

Author SHA1 Message Date
TheBrokenRail 0bc2eb8b07 1.1.11
ModUpdater/pipeline/head This commit looks good Details
2020-08-11 17:50:32 -04:00
TheBrokenRail 37fe78675e Merge pull request 'Added Simplified Chinese Localization' (#11) from Samekichi/ModUpdater:samekichi-patch-1 into master
ModUpdater/pipeline/head This commit looks good Details
2020-08-11 21:48:34 +00:00
TheBrokenRail 64d94e4d68 1.1.10
ModUpdater/pipeline/head There was a failure building this commit Details
2020-08-11 17:25:20 -04:00
Samekichi a58350f0ce 添加 'src/main/resources/assets/modupdater/lang/zh_cn.json' 2020-08-11 21:13:04 +00:00
TheBrokenRail 0a2afee6ee 1.16.2
ModUpdater/pipeline/head This commit looks good Details
2020-08-11 16:46:15 -04:00
TheBrokenRail 47ac38726f Merge pull request 'update to 1.16.2' (#10) from Giselbaer/ModUpdater:master into master
ModUpdater/pipeline/head This commit looks good Details
2020-08-11 20:43:55 +00:00
Guntram Blohm bed078867d update to 1.16.2 2020-08-11 22:24:28 +02:00
TheBrokenRail 1d4494d905 1.1.9
ModUpdater/pipeline/head This commit looks good Details
2020-08-05 13:06:45 -04:00
TheBrokenRail 2f140c4a60 1.1.8
ModUpdater/pipeline/head This commit looks good Details
2020-07-25 14:10:06 -04:00
TheBrokenRail 4d4facdf50 Update Documentation
ModUpdater/pipeline/head This commit looks good Details
2020-06-29 12:43:20 -04:00
TheBrokenRail 74c97537b6 1.1.7
ModUpdater/pipeline/head This commit looks good Details
2020-06-29 12:33:55 -04:00
TheBrokenRail fedd2fe2d8 1.1.6
ModUpdater/pipeline/head This commit looks good Details
2020-06-29 11:01:40 -04:00
TheBrokenRail 7b43cf36bb Fix Documentation Jump Links
ModUpdater/pipeline/head This commit looks good Details
2020-06-29 10:26:25 -04:00
TheBrokenRail 4f6bc2c108 1.1.5
ModUpdater/pipeline/head This commit looks good Details
2020-06-29 10:21:36 -04:00
TheBrokenRail c3c2b47b67 Improve Documentation Again
ModUpdater/pipeline/head This commit looks good Details
2020-06-28 15:24:35 -04:00
TheBrokenRail 9c9f759ab5 Improve Documentation
ModUpdater/pipeline/head This commit looks good Details
2020-06-28 15:03:20 -04:00
TheBrokenRail bafa2723c2 Reformat COde
ModUpdater/pipeline/head This commit looks good Details
2020-06-28 13:43:17 -04:00
21 changed files with 419 additions and 98 deletions

View File

@ -1,5 +1,27 @@
# Changelog
**1.1.11**
* Add Translations
**1.1.10**
* Improve
**1.1.9**
* Add ```modupdater``` Entry-Point
**1.1.8**
* Strict Minecraft Version Checking by Default
* Print Message To Log Showing All Scanned Mods
**1.1.7**
* Disable SemVer In JSON Strategy
**1.1.6**
* Drop Dom4j Dependency
**1.1.5**
* Add JSON Strategy
**1.1.4**
* Add Refresh Button To GUI
* Add ``/modupdater`` Command

13
Jenkinsfile vendored
View File

@ -15,5 +15,18 @@ pipeline {
}
}
}
stage('Publish') {
when {
expression {
return sh(returnStdout: true, script: 'git tag --contains').trim().length() > 0
}
}
steps {
sh './gradlew publish'
withCredentials([string(credentialsId: 'curseforge_key', variable: 'CURSEFORGE_KEY')]) {
sh './gradlew -Pcurseforge.api_key="${CURSEFORGE_KEY}" curseforge'
}
}
}
}
}

139
MOD_DEVELOPER.md Normal file
View File

@ -0,0 +1,139 @@
# Mod Developers
To opt-in a mod for ModUpdater, you must select an update strategy in ```fabric.mod.json```.
## CurseForge
This update strategy uses the CurseForge API to check for updates.
### ```fabric.mod.json```
```json
{
"custom": {
"modupdater": {
"strategy": "curseforge",
"projectID": 306612
}
}
}
```
- Requires Semantic Versioning
- In Loose Versioning Mode, Can Infer File's Supported Minecraft version From CurseForge Metadata
- [Requires ```build.gradle``` modification](#build-gradle-modification)
## GitHub Releases
This update strategy uses the GitHub Releases API to check for updates.
### ```fabric.mod.json```
```json
{
"custom": {
"modupdater": {
"strategy": "github",
"owner": "Repository Owner",
"repository": "Repository Name"
}
}
}
```
- Requires Semantic Versioning
- [Requires ```build.gradle``` Modification](#build-gradle-modification)
## Maven
This update strategy uses the specified Maven repository to check for updates.
### ```fabric.mod.json```
```json
{
"custom": {
"modupdater": {
"strategy": "maven",
"repository": "https://maven.fabricmc.net",
"group": "net.fabricmc.fabric-api",
"artifact": "fabric-api"
}
}
}
```
- Requires Semantic Versioning
- [Requires ```build.gradle``` Modification](#build-gradle-modification)
## JSON
This update strategy uses the specified JSON file to check for updates.
### ```fabric.mod.json```
```json
{
"custom": {
"modupdater": {
"strategy": "json",
"url": "https://example.com/thing.json"
}
}
}
```
### JSON Format
```json
{
"1.16.1": {
"version": "1.0.1",
"downloadUrl": "https://example.com/thing2.jar"
},
"20w20a": {
"version": "1.0.0",
"downloadUrl": "https://example.com/thing.jar"
}
}
```
- Does Not Use Semantic Versioning
- A mod is marked as out-of-date if the version in the JSON is different from the current version, so if the current version is newer than the one in the JSON, it will still be marked as out-of-date.
- ```build.gradle``` Modification Is Not Required
## ```build.gradle``` Modification
Multiple update strategies require the Minecraft version to be appended to the end of the JAR version to detect what Minecraft version a JAR supports.
Replace:
```gradle
version = project.mod_version
```
with:
```gradle
version = "${project.mod_version}+${project.minecraft_version}"
```
If you prefer hyphens you can also use:
```gradle
version = "${project.mod_version}-${project.minecraft_version}"
```
## Loose VS Strict Versioning Mode
### Strict (Default)
In strict mode it only marks a file as compatibleif the Minecraft version is identical.
### Loose
```json
{
"custom": {
"modupdater": {
"strict": false
}
}
}
```
In loose mode, it will also mark a file as compatible if it has the same release target.
## Custom Version Compatibility Checking
You can also specify the ```modupdater``` entry-point as a ```ModUpdaterEntryPoint``` to check if a version is compatible with the current MC version.
```gradle
repositories {
maven { url 'https://maven.thebrokenrail.com' }
}
dependencies {
modCompileOnly 'com.thebrokenrail:modupdater:VERSION'
// VERSION = "<Mod Version>+<MC Version>", for example "1.2.4+20w12a"
}
```

View File

@ -6,60 +6,10 @@ Created For [ModFest 1.16](https://modfest.net/1.16)
**NOTE:** This is only able to scan mods that have opted-in!
## Mod Users
Go to the Mod Menu and click the configure icon for ModUpdater to view available updates.
Go to the Mod Menu and click the configure icon to show the ModUpdater GUI or use the ```/modupdater``` command.
## Mod Developers
Both ```fabric.mod.json``` and ```build.gradle``` must be modified to opt-in to ModUpdater.
### ```fabric.mod.json```
**Maven**
```json
{
"custom": {
"modupdater": {
"strategy": "maven",
"repository": "https://maven.fabricmc.net",
"group": "net.fabricmc.fabric-api",
"artifact": "fabric-api"
}
}
}
```
**CurseForge**
```json
{
"custom": {
"modupdater": {
"strategy": "curseforge",
"projectID": 306612
}
}
}
```
**GitHub Releases**
```json
{
"custom": {
"modupdater": {
"strategy": "github",
"owner": "Repository Owner",
"repository": "Repository Name"
}
}
}
```
### ```build.gradle```
Replace:
```gradle
version = project.mod_version
```
with this:
```gradle
version = "${project.mod_version}+${project.minecraft_version}"
```
[View Mod Developers](MOD_DEVELOPER.md)
## Changelog
[View Changelog](CHANGELOG.md)

View File

@ -1,6 +1,7 @@
plugins {
id 'fabric-loom' version '0.4-SNAPSHOT'
id 'com.matthewprenger.cursegradle' version '1.4.0'
id 'maven-publish'
}
compileJava {
@ -30,9 +31,6 @@ dependencies {
implementation "com.squareup.moshi:moshi:${project.moshi_version}"
includeTransitive "com.squareup.moshi:moshi:${project.moshi_version}"
implementation "org.dom4j:dom4j:${project.dom4j_version}"
includeTransitive "org.dom4j:dom4j:${project.dom4j_version}"
compileOnly 'com.google.code.findbugs:jsr305:3.0.2'
}
@ -102,4 +100,19 @@ if (project.hasProperty('curseforge.api_key')) {
forgeGradleIntegration = false
}
}
}
publishing {
publications {
mavenJava(MavenPublication) {
artifact(remapJar) {
builtBy remapJar
}
}
}
repositories {
maven {
url '/data/maven'
}
}
}

View File

@ -2,18 +2,17 @@
org.gradle.jvmargs = -Xmx1G
# Fabric Properties
minecraft_version = 1.16.1
minecraft_version = 1.16.2-rc2
curseforge_id = 391583
simple_minecraft_version = 1.16.1
simple_minecraft_version = 1.16.2
yarn_build = 1
fabric_loader_version = 0.8.8+build.202
fabric_loader_version = 0.9.1+build.205
# Mod Properties
mod_version = 1.1.4
mod_version = 1.1.11
maven_group = com.thebrokenrail
# Dependencies
fabric_api_version = 0.13.1+build.370-1.16
modmenu_version = 1.12.2+build.16
fabric_api_version = 0.17.2+build.396-1.16
modmenu_version = 1.14.6+build.31
moshi_version = 1.9.2
dom4j_version = 2.1.3

View File

@ -1,8 +1,8 @@
package com.thebrokenrail.modupdater;
import com.thebrokenrail.modupdater.command.ModUpdaterCommand;
import com.thebrokenrail.modupdater.strategy.util.UpdateStrategyRunner;
import com.thebrokenrail.modupdater.data.ModUpdate;
import com.thebrokenrail.modupdater.strategy.util.UpdateStrategyRunner;
import net.fabricmc.api.ModInitializer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

View File

@ -2,8 +2,11 @@ package com.thebrokenrail.modupdater.api;
public interface ConfigObject {
String getString(String str) throws MissingValueException;
int getInt(String str) throws MissingValueException;
boolean getBoolean(String str) throws MissingValueException;
class MissingValueException extends Exception {
private static final String MISSING_MSG = "Missing Configuration Property: %s";
private static final String INVALID_MSG = "Invalid Configuration Property: %s";

View File

@ -6,5 +6,13 @@ import javax.annotation.Nullable;
public interface UpdateStrategy {
@Nullable
ModUpdate run(ConfigObject obj, String oldVersion, String name);
ModUpdate run(ConfigObject obj, String oldVersion, String name, String id);
default boolean isStrict(ConfigObject obj) {
try {
return obj.getBoolean("strict");
} catch (ConfigObject.MissingValueException e) {
return true;
}
}
}

View File

@ -0,0 +1,5 @@
package com.thebrokenrail.modupdater.api.entrypoint;
public interface ModUpdaterEntryPoint {
boolean isVersionCompatible(String version);
}

View File

@ -35,4 +35,17 @@ public class ConfigObjectCustom implements ConfigObject {
throw new MissingValueException(false, str);
}
}
@Override
public boolean getBoolean(String str) throws MissingValueException {
if (obj.containsKey(str)) {
try {
return obj.get(str).getAsBoolean();
} catch (ClassCastException e) {
throw new MissingValueException(true, str);
}
} else {
throw new MissingValueException(false, str);
}
}
}

View File

@ -36,4 +36,17 @@ public class ConfigObjectHardcoded implements ConfigObject {
throw new MissingValueException(false, str);
}
}
@Override
public boolean getBoolean(String str) throws MissingValueException {
if (map.containsKey(str)) {
try {
return (Boolean) map.get(str);
} catch (ClassCastException e) {
throw new MissingValueException(true, str);
}
} else {
throw new MissingValueException(false, str);
}
}
}

View File

@ -26,7 +26,7 @@ public class ModUpdaterCommand {
ModUpdate[] updates = ModUpdater.getUpdates();
assert updates != null;
for (ModUpdate update : updates) {
context.getSource().sendFeedback(new LiteralText(update.text).styled(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, update.downloadURL)).setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableText("commands." + ModUpdater.NAMESPACE + ".hover")))), false);
context.getSource().sendFeedback(new LiteralText(update.text).styled(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, update.downloadURL)).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableText("commands." + ModUpdater.NAMESPACE + ".hover")))), false);
}
return updates.length;
}))

View File

@ -6,11 +6,11 @@ import com.squareup.moshi.JsonDataException;
import com.squareup.moshi.Moshi;
import com.thebrokenrail.modupdater.ModUpdater;
import com.thebrokenrail.modupdater.api.ConfigObject;
import com.thebrokenrail.modupdater.data.ModUpdate;
import com.thebrokenrail.modupdater.api.UpdateStrategy;
import com.thebrokenrail.modupdater.data.ModUpdate;
import com.thebrokenrail.modupdater.util.Util;
import net.fabricmc.loader.api.SemanticVersion;
import net.fabricmc.loader.util.version.VersionParsingException;
import net.fabricmc.loader.api.VersionParsingException;
import javax.annotation.Nullable;
import java.io.IOException;
@ -33,7 +33,7 @@ public class CurseForgeStrategy implements UpdateStrategy {
@Override
@Nullable
public ModUpdate run(ConfigObject obj, String oldVersion, String name) {
public ModUpdate run(ConfigObject obj, String oldVersion, String name, String id) {
int projectID;
try {
projectID = obj.getInt("projectID");
@ -65,16 +65,18 @@ public class CurseForgeStrategy implements UpdateStrategy {
String versionStr;
GameVersion version = Util.getMinecraftVersion();
if (version.isStable()) {
versionStr = version.getName();
versionStr = version.getId();
} else {
versionStr = version.getReleaseTarget() + "-Snapshot";
}
boolean strict = isStrict(obj);
CurseForgeFile newestFile = null;
for (CurseForgeFile file : files) {
if (Util.isFileCompatible(file.fileName)) {
String fileVersion = Util.getVersionFromFileName(file.fileName);
if (Arrays.asList(file.gameVersion).contains(versionStr) || Util.isVersionCompatible(fileVersion)) {
if ((Arrays.asList(file.gameVersion).contains(versionStr) && !strict) || Util.isVersionCompatible(id, fileVersion, strict)) {
if (newestFile != null) {
String newestFileVersion = Util.getVersionFromFileName(newestFile.fileName);
try {

View File

@ -5,11 +5,11 @@ import com.squareup.moshi.JsonDataException;
import com.squareup.moshi.Moshi;
import com.thebrokenrail.modupdater.ModUpdater;
import com.thebrokenrail.modupdater.api.ConfigObject;
import com.thebrokenrail.modupdater.data.ModUpdate;
import com.thebrokenrail.modupdater.api.UpdateStrategy;
import com.thebrokenrail.modupdater.data.ModUpdate;
import com.thebrokenrail.modupdater.util.Util;
import net.fabricmc.loader.api.SemanticVersion;
import net.fabricmc.loader.util.version.VersionParsingException;
import net.fabricmc.loader.api.VersionParsingException;
import javax.annotation.Nullable;
import java.io.IOException;
@ -35,7 +35,7 @@ public class GitHubReleasesStrategy implements UpdateStrategy {
@Override
@Nullable
public ModUpdate run(ConfigObject obj, String oldVersion, String name) {
public ModUpdate run(ConfigObject obj, String oldVersion, String name, String id) {
String owner;
String repo;
try {
@ -66,12 +66,14 @@ public class GitHubReleasesStrategy implements UpdateStrategy {
return null;
}
boolean strict = isStrict(obj);
GitHubReleaseAsset newestFile = null;
for (GitHubRelease release : releases) {
for (GitHubReleaseAsset asset : release.assets) {
if (Util.isFileCompatible(asset.name)) {
String fileVersion = Util.getVersionFromFileName(asset.name);
if (Util.isVersionCompatible(fileVersion)) {
if (Util.isVersionCompatible(id, fileVersion, strict)) {
if (newestFile != null) {
try {
if (SemanticVersion.parse(fileVersion).compareTo(SemanticVersion.parse(fileVersion)) > 0) {

View File

@ -0,0 +1,76 @@
package com.thebrokenrail.modupdater.strategy;
import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.JsonDataException;
import com.squareup.moshi.Moshi;
import com.squareup.moshi.Types;
import com.thebrokenrail.modupdater.ModUpdater;
import com.thebrokenrail.modupdater.api.ConfigObject;
import com.thebrokenrail.modupdater.api.UpdateStrategy;
import com.thebrokenrail.modupdater.data.ModUpdate;
import com.thebrokenrail.modupdater.util.Util;
import javax.annotation.Nullable;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Map;
public class JSONStrategy implements UpdateStrategy {
@SuppressWarnings("unused")
private static class LatestVersionEntry {
private String version;
private String downloadUrl;
}
private final JsonAdapter<Map<String, LatestVersionEntry>> jsonAdapter;
public JSONStrategy() {
Moshi moshi = new Moshi.Builder().build();
Type map = Types.newParameterizedType(Map.class, String.class, LatestVersionEntry.class);
jsonAdapter = moshi.adapter(map);
}
@Override
@Nullable
public ModUpdate run(ConfigObject obj, String oldVersion, String name, String id) {
String url;
try {
url = obj.getString("url");
} catch (ConfigObject.MissingValueException e) {
ModUpdater.logWarn(name, e.getMessage());
return null;
}
String data;
try {
data = Util.urlToString(url);
} catch (IOException e) {
ModUpdater.logWarn(name, e.toString());
return null;
}
Map<String, LatestVersionEntry> map;
try {
map = jsonAdapter.fromJson(data);
} catch (JsonDataException | IOException e) {
ModUpdater.logWarn(name, e.toString());
return null;
}
if (map == null) {
return null;
}
String version = Util.getMinecraftVersion().getId();
if (map.containsKey(version)) {
LatestVersionEntry entry = map.get(version);
if (!oldVersion.equals(entry.version)) {
return new ModUpdate(oldVersion, entry.version, entry.downloadUrl, name);
} else {
return null;
}
} else {
return null;
}
}
}

View File

@ -2,28 +2,45 @@ package com.thebrokenrail.modupdater.strategy;
import com.thebrokenrail.modupdater.ModUpdater;
import com.thebrokenrail.modupdater.api.ConfigObject;
import com.thebrokenrail.modupdater.data.ModUpdate;
import com.thebrokenrail.modupdater.api.UpdateStrategy;
import com.thebrokenrail.modupdater.data.ModUpdate;
import com.thebrokenrail.modupdater.util.Util;
import net.fabricmc.loader.api.SemanticVersion;
import net.fabricmc.loader.util.version.VersionParsingException;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import net.fabricmc.loader.api.VersionParsingException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.annotation.Nullable;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class MavenStrategy implements UpdateStrategy {
private final SAXReader reader = new SAXReader();
private final DocumentBuilder builder;
public MavenStrategy() {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(true);
factory.setIgnoringElementContentWhitespace(true);
try {
builder = factory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
throw new RuntimeException(e);
}
}
@Override
@Nullable
public ModUpdate run(ConfigObject obj, String oldVersion, String name) {
public ModUpdate run(ConfigObject obj, String oldVersion, String name, String id) {
String repository;
String group;
String artifact;
@ -48,18 +65,29 @@ public class MavenStrategy implements UpdateStrategy {
Document doc;
try (InputStream source = new ByteArrayInputStream(data.getBytes())) {
doc = reader.read(source);
} catch (DocumentException | IOException e) {
doc = builder.parse(source);
} catch (IOException | SAXException e) {
ModUpdater.logWarn(name, e.toString());
return null;
}
List<Node> versions = doc.selectNodes("/metadata/versioning/versions/*");
XPath xPath = XPathFactory.newInstance().newXPath();
NodeList versions;
try {
versions = (NodeList) xPath.compile("/metadata/versioning/versions/*").evaluate(doc, XPathConstants.NODESET);
} catch (XPathExpressionException e) {
ModUpdater.logWarn(name, e.toString());
return null;
}
boolean strict = isStrict(obj);
String newestVersion = null;
for (Node node : versions) {
String version = node.getText();
if (Util.isVersionCompatible(version)) {
for (int i = 0; i < versions.getLength(); i++) {
Node node = versions.item(i);
String version = node.getTextContent();
if (Util.isVersionCompatible(id, version, strict)) {
if (newestVersion != null) {
try {
if (SemanticVersion.parse(version).compareTo(SemanticVersion.parse(newestVersion)) > 0) {

View File

@ -3,6 +3,7 @@ package com.thebrokenrail.modupdater.strategy.util;
import com.thebrokenrail.modupdater.api.UpdateStrategy;
import com.thebrokenrail.modupdater.strategy.CurseForgeStrategy;
import com.thebrokenrail.modupdater.strategy.GitHubReleasesStrategy;
import com.thebrokenrail.modupdater.strategy.JSONStrategy;
import com.thebrokenrail.modupdater.strategy.MavenStrategy;
import javax.annotation.Nullable;
@ -21,5 +22,6 @@ public class UpdateStrategyRegistry {
data.put("curseforge", new CurseForgeStrategy());
data.put("maven", new MavenStrategy());
data.put("github", new GitHubReleasesStrategy());
data.put("json", new JSONStrategy());
}
}

View File

@ -2,9 +2,9 @@ package com.thebrokenrail.modupdater.strategy.util;
import com.thebrokenrail.modupdater.ModUpdater;
import com.thebrokenrail.modupdater.api.ConfigObject;
import com.thebrokenrail.modupdater.api.UpdateStrategy;
import com.thebrokenrail.modupdater.api.impl.ConfigObjectCustom;
import com.thebrokenrail.modupdater.data.ModUpdate;
import com.thebrokenrail.modupdater.api.UpdateStrategy;
import com.thebrokenrail.modupdater.util.Util;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer;
@ -14,10 +14,11 @@ import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
public class UpdateStrategyRunner {
@Nullable
private static ModUpdate checkModForUpdate(ModMetadata metadata) {
private static ModUpdate checkModForUpdate(ModMetadata metadata, Consumer<String> scan) {
String name = metadata.getName() + " (" + metadata.getId() + ')';
ConfigObject obj;
@ -51,13 +52,16 @@ public class UpdateStrategyRunner {
return null;
}
return strategyObj.run(obj, oldVersion, name);
scan.accept(name);
return strategyObj.run(obj, oldVersion, name, metadata.getId());
}
public static ModUpdate[] checkAllModsForUpdates() {
ModUpdater.logInfo("Checking For Mod Updates...");
List<ModUpdate> updates = new ArrayList<>();
List<String> scannedMods = new ArrayList<>();
AtomicInteger remaining = new AtomicInteger(0);
@ -66,7 +70,11 @@ public class UpdateStrategyRunner {
try {
ModMetadata metadata = mod.getMetadata();
ModUpdate update = checkModForUpdate(metadata);
ModUpdate update = checkModForUpdate(metadata, name -> {
synchronized (scannedMods) {
scannedMods.add(name);
}
});
if (update != null) {
ModUpdater.logInfo(update.text + " (" + update.downloadURL + ')');
@ -100,6 +108,8 @@ public class UpdateStrategyRunner {
ModUpdater.logInfo(updates.size() + String.format(" Mod Update%s Found", updates.size() == 1 ? "" : "s"));
ModUpdater.logInfo("Scanned " + scannedMods.size() + " Mods: " + String.join(", ", scannedMods));
return updates.toArray(new ModUpdate[0]);
}
}

View File

@ -1,10 +1,13 @@
package com.thebrokenrail.modupdater.util;
import com.mojang.bridge.game.GameVersion;
import com.thebrokenrail.modupdater.ModUpdater;
import com.thebrokenrail.modupdater.api.ConfigObject;
import com.thebrokenrail.modupdater.api.entrypoint.ModUpdaterEntryPoint;
import com.thebrokenrail.modupdater.api.impl.ConfigObjectHardcoded;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer;
import net.fabricmc.loader.api.entrypoint.EntrypointContainer;
import net.minecraft.MinecraftVersion;
import java.io.BufferedReader;
@ -12,6 +15,7 @@ import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@ -71,17 +75,24 @@ public class Util {
if (parts.length > 1) {
return String.format("%s.%s", parts[0], parts[1]);
} else {
return minecraftVersion.getName();
return minecraftVersion.getId();
}
}
private static boolean isVersionCompatible(String versionStr, char prefix) {
private static boolean isVersionCompatible(String versionStr, char prefix, boolean strict) {
updateMinecraftVersion();
return versionStr.endsWith(prefix + minecraftVersionSemantic) || versionStr.endsWith(prefix + minecraftVersion.getReleaseTarget()) || versionStr.endsWith(prefix + getMajorVersion());
return versionStr.endsWith(prefix + minecraftVersionSemantic) || versionStr.endsWith(prefix + minecraftVersion.getId()) || (!strict && (versionStr.endsWith(prefix + minecraftVersion.getReleaseTarget()) || versionStr.endsWith(prefix + getMajorVersion())));
}
public static boolean isVersionCompatible(String versionStr) {
return isVersionCompatible(versionStr,'+') || isVersionCompatible(versionStr, '-');
public static boolean isVersionCompatible(String id, String versionStr, boolean strict) {
List<EntrypointContainer<ModUpdaterEntryPoint>> list = FabricLoader.getInstance().getEntrypointContainers(ModUpdater.NAMESPACE, ModUpdaterEntryPoint.class);
for (EntrypointContainer<ModUpdaterEntryPoint> container : list) {
if (container.getProvider().getMetadata().getId().equals(id)) {
return container.getEntrypoint().isVersionCompatible(versionStr);
}
}
return isVersionCompatible(versionStr, '+', strict) || isVersionCompatible(versionStr, '-', strict);
}
public static boolean isFileCompatible(String fileName) {
@ -99,12 +110,14 @@ public class Util {
Map<String, Object> map = new HashMap<>();
map.put("strategy", "curseforge");
map.put("projectID", 306612);
map.put("strict", false);
return new ConfigObjectHardcoded(map);
}
case "modmenu": {
Map<String, Object> map = new HashMap<>();
map.put("strategy", "curseforge");
map.put("projectID", 308702);
map.put("strict", false);
return new ConfigObjectHardcoded(map);
}
default: {

View File

@ -0,0 +1,10 @@
{
"gui.modupdater.title": "可用的模组更新",
"gui.modupdater.download": "下载",
"gui.modupdater.refresh": "刷新",
"gui.modupdater.loading": "加载中...",
"commands.modupdater.not_loaded": "模组更新加载时无法进行其它操作",
"commands.modupdater.refresh_start": "刷新模组更新列表中",
"commands.modupdater.hover": "点击下载",
"commands.modupdater.list_title": "可用的模组更新:"
}