aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at
diff options
context:
space:
mode:
authorRoman / Linnea Gräf <nea@nea.moe>2023-04-12 12:38:00 +0200
committerGitHub <noreply@github.com>2023-04-12 12:38:00 +0200
commite9a6b9f6de0fd8d6bc0d97b03d07d9a8c2757f95 (patch)
treef8a29569864aa798e85906fac1412f0583b684c6 /src/main/java/at
parent0e2276bad532ffe06e1364900e6456cd5b50214e (diff)
downloadskyhanni-e9a6b9f6de0fd8d6bc0d97b03d07d9a8c2757f95.tar.gz
skyhanni-e9a6b9f6de0fd8d6bc0d97b03d07d9a8c2757f95.tar.bz2
skyhanni-e9a6b9f6de0fd8d6bc0d97b03d07d9a8c2757f95.zip
Add AutoUpdater and license info gui (#26)
Diffstat (limited to 'src/main/java/at')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java11
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/ConfigManager.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/Features.java6
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/About.java77
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/update/ConfigVersionDisplay.java11
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/update/GuiOptionEditorUpdateCheck.kt88
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/update/UpdateManager.kt128
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/APIUtil.kt2
8 files changed, 321 insertions, 4 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java
index 3392e83c7..48d49ec87 100644
--- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java
+++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java
@@ -34,6 +34,7 @@ import at.hannibal2.skyhanni.features.minion.MinionFeatures;
import at.hannibal2.skyhanni.features.misc.*;
import at.hannibal2.skyhanni.features.misc.tiarelay.TiaRelayHelper;
import at.hannibal2.skyhanni.features.misc.tiarelay.TiaRelayWaypoints;
+import at.hannibal2.skyhanni.features.misc.update.UpdateManager;
import at.hannibal2.skyhanni.features.mobs.AreaMiniBossFeatures;
import at.hannibal2.skyhanni.features.mobs.MobHighlight;
import at.hannibal2.skyhanni.features.nether.ashfang.*;
@@ -58,6 +59,7 @@ import kotlinx.coroutines.*;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import net.minecraftforge.common.MinecraftForge;
+import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
@@ -70,13 +72,17 @@ import org.apache.logging.log4j.Logger;
import java.util.ArrayList;
import java.util.List;
-@Mod(modid = SkyHanniMod.MODID, version = SkyHanniMod.VERSION, clientSideOnly = true, useMetadata = true,
+@Mod(modid = SkyHanniMod.MODID, clientSideOnly = true, useMetadata = true,
guiFactory = "at.hannibal2.skyhanni.config.ConfigGuiForgeInterop",
dependencies = SkyHanniMod.DEPENDENCIES)
public class SkyHanniMod {
public static final String MODID = "skyhanni";
- public static final String VERSION = "0.17.Beta.31";
+
+ public static String getVersion() {
+ return Loader.instance().getIndexedModList().get(MODID).getVersion();
+ }
+
public static final String DEPENDENCIES = "after:notenoughupdates@[2.1.1,);";
@@ -126,6 +132,7 @@ public class SkyHanniMod {
loadModule(new OwnInventoryData());
loadModule(new ToolTipData());
loadModule(new GuiEditManager());
+ loadModule(UpdateManager.INSTANCE);
// APIs
loadModule(new BazaarApi());
diff --git a/src/main/java/at/hannibal2/skyhanni/config/ConfigManager.kt b/src/main/java/at/hannibal2/skyhanni/config/ConfigManager.kt
index dd10d8482..de41a1e4b 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/ConfigManager.kt
+++ b/src/main/java/at/hannibal2/skyhanni/config/ConfigManager.kt
@@ -2,6 +2,7 @@ package at.hannibal2.skyhanni.config
import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.events.ConfigLoadEvent
+import at.hannibal2.skyhanni.features.misc.update.UpdateManager
import at.hannibal2.skyhanni.features.garden.CropType
import com.google.gson.GsonBuilder
import io.github.moulberry.moulconfig.observer.PropertyTypeAdapterFactory
@@ -79,6 +80,7 @@ class ConfigManager {
val features = SkyHanniMod.feature
processor = MoulConfigProcessor(SkyHanniMod.feature)
BuiltinMoulConfigGuis.addProcessors(processor)
+ UpdateManager.injectConfigProcessor(processor)
ConfigProcessorDriver.processConfig(
features.javaClass,
features,
diff --git a/src/main/java/at/hannibal2/skyhanni/config/Features.java b/src/main/java/at/hannibal2/skyhanni/config/Features.java
index bc7913f37..064b5ce2a 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/Features.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/Features.java
@@ -32,10 +32,14 @@ public class Features extends Config {
@Override
public String getTitle() {
- return "SkyHanni " + SkyHanniMod.VERSION + " by §channibal2§r, config by §5Moulberry §rand §5nea89";
+ return "SkyHanni " + SkyHanniMod.getVersion() + " by §channibal2§r, config by §5Moulberry §rand §5nea89";
}
@Expose
+ @Category(name = "About", desc = "Information about SkyHanni and updates")
+ public About about = new About();
+
+ @Expose
@Category(name = "GUI Locations", desc = "Change the locations of GUI elements. (§e/sh gui§7)")
public GUI gui = new GUI();
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/About.java b/src/main/java/at/hannibal2/skyhanni/config/features/About.java
new file mode 100644
index 000000000..0bb71a7e1
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/About.java
@@ -0,0 +1,77 @@
+package at.hannibal2.skyhanni.config.features;
+
+import at.hannibal2.skyhanni.features.misc.update.ConfigVersionDisplay;
+import com.google.gson.annotations.Expose;
+import io.github.moulberry.moulconfig.annotations.*;
+import io.github.moulberry.moulconfig.observer.Property;
+import io.github.moulberry.notenoughupdates.util.Utils;
+
+public class About {
+
+
+ @ConfigOption(name = "Current Version", desc = "This is the SkyHanni version you are running currently")
+ @ConfigVersionDisplay
+ public Void currentVersion = null;
+
+ @ConfigOption(name = "Auto Updates", desc = "Automatically check for updates on each startup")
+ @Expose
+ @ConfigEditorBoolean
+ public boolean autoUpdates = true;
+
+ @ConfigOption(name = "Update Stream", desc = "How frequently do you want updates for SkyHanni")
+ @Expose
+ @ConfigEditorDropdown
+ public Property<UpdateStream> updateStream = Property.of(UpdateStream.RELEASES);
+
+
+ @ConfigOption(name = "Used Software", desc = "Information about used software and licenses")
+ @Accordion
+ public Licenses licenses = new Licenses();
+
+ public enum UpdateStream {
+ NONE("None", "none"),
+ BETA("Beta", "pre"),
+ RELEASES("Full", "full");
+
+ private final String label;
+ private final String stream;
+
+ UpdateStream(String label, String stream) {
+ this.label = label;
+ this.stream = stream;
+ }
+
+ public String getStream() {
+ return stream;
+ }
+
+ @Override
+ public String toString() {
+ return label;
+ }
+ }
+
+ public static class Licenses {
+
+ @ConfigOption(name = "MoulConfig", desc = "MoulConfig is available under the LGPL 3.0 License or later version")
+ @ConfigEditorButton(buttonText = "GitHub")
+ public Runnable moulConfig = () -> Utils.openUrl("https://github.com/NotEnoughUpdates/MoulConfig");
+
+ @ConfigOption(name = "NotEnoughUpdates", desc = "NotEnoughUpdates is available under the LGPL 3.0 License or later version")
+ @ConfigEditorButton(buttonText = "GitHub")
+ public Runnable notEnoughUpdates = () -> Utils.openUrl("https://github.com/NotEnoughUpdates/NotEnoughUpdates");
+
+ @ConfigOption(name = "Forge", desc = "Forge is available under the LGPL 3.0 license")
+ @ConfigEditorButton(buttonText = "GitHub")
+ public Runnable forge = () -> Utils.openUrl("https://github.com/MinecraftForge/MinecraftForge");
+
+ @ConfigOption(name = "LibAutoUpdate", desc = "LibAutoUpdate is available under the BSD 2 Clause License")
+ @ConfigEditorButton(buttonText = "Git")
+ public Runnable libAutoUpdate = () -> Utils.openUrl("https://git.nea.moe/nea/libautoupdate/");
+
+ @ConfigOption(name = "Mixin", desc = "LibAutoUpdate is available under the MIT License")
+ @ConfigEditorButton(buttonText = "GitHub")
+ public Runnable mixin = () -> Utils.openUrl("https://github.com/SpongePowered/Mixin/");
+
+ }
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/update/ConfigVersionDisplay.java b/src/main/java/at/hannibal2/skyhanni/features/misc/update/ConfigVersionDisplay.java
new file mode 100644
index 000000000..ddb837efb
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/update/ConfigVersionDisplay.java
@@ -0,0 +1,11 @@
+package at.hannibal2.skyhanni.features.misc.update;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface ConfigVersionDisplay {
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/update/GuiOptionEditorUpdateCheck.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/update/GuiOptionEditorUpdateCheck.kt
new file mode 100644
index 000000000..395975aa6
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/update/GuiOptionEditorUpdateCheck.kt
@@ -0,0 +1,88 @@
+package at.hannibal2.skyhanni.features.misc.update
+
+import io.github.moulberry.moulconfig.gui.GuiOptionEditor
+import io.github.moulberry.moulconfig.internal.TextRenderUtils
+import io.github.moulberry.moulconfig.processor.ProcessedOption
+import io.github.moulberry.notenoughupdates.itemeditor.GuiElementButton
+import net.minecraft.client.Minecraft
+import net.minecraft.client.renderer.GlStateManager
+import net.minecraft.util.EnumChatFormatting.GREEN
+import net.minecraft.util.EnumChatFormatting.RED
+import org.lwjgl.input.Mouse
+
+class GuiOptionEditorUpdateCheck(option: ProcessedOption) : GuiOptionEditor(option) {
+ val button = GuiElementButton("", -1) { }
+
+ override fun render(x: Int, y: Int, width: Int) {
+ val fr = Minecraft.getMinecraft().fontRendererObj
+
+ GlStateManager.pushMatrix()
+ GlStateManager.translate(x.toFloat() + 10, y.toFloat(), 1F)
+ val width = width - 20
+ val nextVersion = UpdateManager.getNextVersion()
+
+ button.text = when (UpdateManager.updateState) {
+ UpdateManager.UpdateState.AVAILABLE -> "Download update"
+ UpdateManager.UpdateState.QUEUED -> "Downloading..."
+ UpdateManager.UpdateState.DOWNLOADED -> "Downloaded"
+ UpdateManager.UpdateState.NONE -> if (nextVersion == null) "Check for Updates" else "Up to date"
+ }
+ button.render(getButtonPosition(width), 10)
+
+ if (UpdateManager.updateState == UpdateManager.UpdateState.DOWNLOADED) {
+ TextRenderUtils.drawStringCentered(
+ "${GREEN}The update will be installed after your next restart.",
+ fr,
+ width / 2F,
+ 40F,
+ true,
+ -1
+ )
+ }
+
+ val widthRemaining = width - button.width - 10
+
+ GlStateManager.scale(2F, 2F, 1F)
+ TextRenderUtils.drawStringCenteredScaledMaxWidth(
+ "${if (UpdateManager.updateState == UpdateManager.UpdateState.NONE) GREEN else RED}${UpdateManager.getCurrentVersion()}" +
+ if (nextVersion != null) "➜ ${GREEN}${nextVersion}" else "",
+ fr,
+ widthRemaining / 4F,
+ 10F,
+ true,
+ widthRemaining / 2,
+ -1
+ )
+
+ GlStateManager.popMatrix()
+ }
+
+ fun getButtonPosition(width: Int) = width - button.width
+ override fun getHeight(): Int {
+ return 55
+ }
+
+ override fun mouseInput(x: Int, y: Int, width: Int, mouseX: Int, mouseY: Int): Boolean {
+ val width = width - 20
+ if (Mouse.getEventButtonState()) {
+ if ((mouseX - getButtonPosition(width) - x) in (0..button.width) && (mouseY - 10 - y) in (0..button.height)) {
+ when (UpdateManager.updateState) {
+ UpdateManager.UpdateState.AVAILABLE -> UpdateManager.queueUpdate()
+ UpdateManager.UpdateState.QUEUED -> {}
+ UpdateManager.UpdateState.DOWNLOADED -> {}
+ UpdateManager.UpdateState.NONE -> UpdateManager.checkUpdate()
+ }
+ return true
+ }
+ }
+ return false
+ }
+
+ override fun keyboardInput(): Boolean {
+ return false
+ }
+
+ override fun fulfillsSearch(word: String): Boolean {
+ return super.fulfillsSearch(word) || word in "download" || word in "update"
+ }
+} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/update/UpdateManager.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/update/UpdateManager.kt
new file mode 100644
index 000000000..adb130a76
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/update/UpdateManager.kt
@@ -0,0 +1,128 @@
+package at.hannibal2.skyhanni.features.misc.update
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.config.features.About
+import at.hannibal2.skyhanni.events.ConfigLoadEvent
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import io.github.moulberry.moulconfig.processor.MoulConfigProcessor
+import io.github.moulberry.notenoughupdates.util.MinecraftExecutor
+import moe.nea.libautoupdate.*
+import net.minecraft.client.Minecraft
+import net.minecraftforge.common.MinecraftForge
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import net.minecraftforge.fml.common.gameevent.TickEvent
+import java.util.concurrent.CompletableFuture
+
+object UpdateManager {
+
+ private val logger = SkyHanniMod.getLogger("UpdateManager")
+ private var _activePromise: CompletableFuture<*>? = null
+ private var activePromise: CompletableFuture<*>?
+ get() = _activePromise
+ set(value) {
+ _activePromise?.cancel(true)
+ _activePromise = value
+ }
+
+ var updateState: UpdateState = UpdateState.NONE
+ private set
+
+ fun getNextVersion(): String? {
+ return potentialUpdate?.update?.versionNumber?.asString
+ }
+
+ @SubscribeEvent
+ fun onConfigLoad(event: ConfigLoadEvent) {
+ SkyHanniMod.feature.about.updateStream.whenChanged { oldValue, newValue ->
+ if (oldValue != newValue)
+ reset()
+ }
+ }
+
+ @SubscribeEvent
+ fun onPlayerAvailableOnce(event: TickEvent.ClientTickEvent) {
+ val p = Minecraft.getMinecraft().thePlayer ?: return
+ MinecraftForge.EVENT_BUS.unregister(this)
+ if (config.autoUpdates)
+ checkUpdate()
+ }
+
+ fun getCurrentVersion(): String {
+ return SkyHanniMod.getVersion()
+ }
+
+ fun injectConfigProcessor(processor: MoulConfigProcessor<*>) {
+ processor.registerConfigEditor(ConfigVersionDisplay::class.java) { option, _ ->
+ GuiOptionEditorUpdateCheck(option)
+ }
+ }
+
+ fun isBetaRelease(): Boolean {
+ return getCurrentVersion().contains("beta", ignoreCase = true)
+ }
+
+ val config get() = SkyHanniMod.feature.about
+
+ fun reset() {
+ updateState = UpdateState.NONE
+ _activePromise = null
+ potentialUpdate = null
+ logger.info("Reset update state")
+ }
+
+ fun checkUpdate() {
+ if (updateState != UpdateState.NONE) {
+ logger.error("Trying to perform update check while another update is already in progress")
+ return
+ }
+ logger.info("Starting update check")
+ var updateStream = config.updateStream.get()
+ if (updateStream == About.UpdateStream.RELEASES && isBetaRelease()) {
+ updateStream = About.UpdateStream.BETA
+ }
+ activePromise = context.checkUpdate(updateStream.stream)
+ .thenAcceptAsync({
+ logger.info("Update check completed")
+ if (updateState != UpdateState.NONE) {
+ logger.warn("This appears to be the second update check. Ignoring this one")
+ return@thenAcceptAsync
+ }
+ potentialUpdate = it
+ if (it.isUpdateAvailable) {
+ updateState = UpdateState.AVAILABLE
+ LorenzUtils.chat("§e[SkyHanni] §aSkyhanni found a new update: ${it.update.versionName}. Go check §b/sh download update §afor more info.")
+ }
+ }, MinecraftExecutor.OnThread)
+ }
+
+ fun queueUpdate() {
+ if (updateState != UpdateState.AVAILABLE) {
+ logger.error("Trying to enqueue an update while another one is already downloaded or none is present")
+ }
+ updateState = UpdateState.QUEUED
+ activePromise = CompletableFuture.supplyAsync {
+ logger.info("Update download started")
+ potentialUpdate!!.prepareUpdate()
+ }.thenAcceptAsync({
+ logger.info("Update download completed, setting exit hook")
+ updateState = UpdateState.DOWNLOADED
+ potentialUpdate!!.executeUpdate()
+ }, MinecraftExecutor.OnThread)
+ }
+
+ val context = UpdateContext(
+ UpdateSource.githubUpdateSource("hannibal002", "Skyhanni"),
+ UpdateTarget.deleteAndSaveInTheSameFolder(UpdateManager::class.java),
+ CurrentVersion.ofTag(SkyHanniMod.getVersion()),
+ SkyHanniMod.MODID,
+ )
+
+ enum class UpdateState {
+ AVAILABLE,
+ QUEUED,
+ DOWNLOADED,
+ NONE
+ }
+
+ var potentialUpdate: PotentialUpdate? = null
+} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/APIUtil.kt b/src/main/java/at/hannibal2/skyhanni/utils/APIUtil.kt
index 1f03ed837..ff0c7a1ea 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/APIUtil.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/APIUtil.kt
@@ -22,7 +22,7 @@ object APIUtil {
private var showApiErrors = false
val builder: HttpClientBuilder =
- HttpClients.custom().setUserAgent("SkyHanni/${SkyHanniMod.VERSION}")
+ HttpClients.custom().setUserAgent("SkyHanni/${SkyHanniMod.getVersion()}")
.setDefaultHeaders(
mutableListOf(
BasicHeader("Pragma", "no-cache"),