diff options
| author | Roman / Linnea Gräf <nea@nea.moe> | 2023-04-12 12:38:00 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-04-12 12:38:00 +0200 |
| commit | e9a6b9f6de0fd8d6bc0d97b03d07d9a8c2757f95 (patch) | |
| tree | f8a29569864aa798e85906fac1412f0583b684c6 /src/main/java/at/hannibal2/skyhanni/features | |
| parent | 0e2276bad532ffe06e1364900e6456cd5b50214e (diff) | |
| download | skyhanni-e9a6b9f6de0fd8d6bc0d97b03d07d9a8c2757f95.tar.gz skyhanni-e9a6b9f6de0fd8d6bc0d97b03d07d9a8c2757f95.tar.bz2 skyhanni-e9a6b9f6de0fd8d6bc0d97b03d07d9a8c2757f95.zip | |
Add AutoUpdater and license info gui (#26)
Diffstat (limited to 'src/main/java/at/hannibal2/skyhanni/features')
3 files changed, 227 insertions, 0 deletions
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 |
