Added an auto updater when game starts

This commit is contained in:
coolGi
2022-08-06 20:32:09 +09:30
parent 427b54b1eb
commit 841e831ce0
14 changed files with 246 additions and 19 deletions
@@ -19,7 +19,7 @@
package com.seibel.lod.common.wrappers;
import com.seibel.lod.common.wrappers.config.ConfigWrapper;
import com.seibel.lod.common.wrappers.gui.ConfigWrapper;
import com.seibel.lod.common.wrappers.minecraft.MinecraftDedicatedServerWrapper;
import com.seibel.lod.core.wrapperInterfaces.config.IConfigWrapper;
import com.seibel.lod.common.wrappers.minecraft.MinecraftClientWrapper;
@@ -34,8 +34,6 @@ import com.seibel.lod.core.wrapperInterfaces.config.LodConfigWrapperSingleton;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftSharedWrapper;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
/**
* Binds all necessary dependencies, so we
@@ -20,6 +20,7 @@
package com.seibel.lod.common.wrappers;
import com.seibel.lod.core.wrapperInterfaces.IVersionConstants;
import net.minecraft.client.Minecraft;
/**
* @author James Seibel
@@ -53,4 +54,9 @@ public class VersionConstants implements IVersionConstants
{
return false;
}
@Override
public String getMinecraftVersion() {
return Minecraft.getInstance().getGame().getVersion().getId();
}
}
@@ -1,4 +1,4 @@
package com.seibel.lod.common.wrappers.config;
package com.seibel.lod.common.wrappers.gui;
import java.util.AbstractMap;
import java.util.ArrayList;
@@ -12,7 +12,6 @@ import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
// Logger (for debug stuff)
@@ -1,4 +1,4 @@
package com.seibel.lod.common.wrappers.config;
package com.seibel.lod.common.wrappers.gui;
import com.mojang.blaze3d.vertex.PoseStack;
import com.seibel.lod.core.ModInfo;
@@ -6,7 +6,6 @@ import com.seibel.lod.core.config.gui.AbstractScreen;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.ContainerObjectSelectionList;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.Component;
#if PRE_MC_1_19
import net.minecraft.network.chat.TranslatableComponent;
#endif
@@ -1,4 +1,4 @@
package com.seibel.lod.common.wrappers.config;
package com.seibel.lod.common.wrappers.gui;
import com.seibel.lod.core.wrapperInterfaces.config.IConfigWrapper;
import net.minecraft.client.resources.language.I18n;
@@ -1,4 +1,4 @@
package com.seibel.lod.common.wrappers.config;
package com.seibel.lod.common.wrappers.gui;
import com.seibel.lod.core.config.gui.ConfigScreen;
import net.minecraft.client.gui.screens.Screen;
@@ -17,11 +17,10 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.lod.common.wrappers.config;
package com.seibel.lod.common.wrappers.gui;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.ImageButton;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.network.chat.Component;
@@ -0,0 +1,143 @@
package com.seibel.lod.common.wrappers.gui;
import com.mojang.blaze3d.vertex.PoseStack;
import com.seibel.lod.core.ModInfo;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.GuiComponent;
import net.minecraft.client.gui.components.AbstractWidget;
import net.minecraft.client.gui.components.ContainerObjectSelectionList;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.gui.narration.NarratableEntry;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import java.util.*;
public class UpdateModScreen extends Screen {
public static boolean modUpdated = false;
private ConfigListWidget list;
public UpdateModScreen() {
#if PRE_MC_1_19
super(new TranslatableComponent(ModInfo.ID + ".updateScreen"));
#else
super(Component.translatable(ModInfo.ID + ".updateScreen"));
#endif
}
@Override
protected void init() {
super.init();
this.list = new ConfigListWidget(this.minecraft, this.width, this.height, 0, this.height, 25); // Select the area to tint
if (this.minecraft != null && this.minecraft.level != null) // Check if in game
this.list.setRenderBackground(false); // Disable from rendering
this.addWidget(this.list); // Add the tint to the things to be rendered
}
@Override
public void render(PoseStack matrices, int mouseX, int mouseY, float delta) {
this.renderBackground(matrices); // Render background
this.list.render(matrices, mouseX, mouseY, delta); // Renders the items in the render list (currently only used to tint background darker)
super.render(matrices, mouseX, mouseY, delta); // Render the vanilla stuff (currently only used for the background and tint)
}
public static class ConfigListWidget extends ContainerObjectSelectionList<ButtonEntry> {
Font textRenderer;
public ConfigListWidget(Minecraft minecraftClient, int i, int j, int k, int l, int m) {
super(minecraftClient, i, j, k, l, m);
this.centerListVertically = false;
textRenderer = minecraftClient.font;
}
public void addButton(AbstractWidget button, AbstractWidget resetButton, AbstractWidget indexButton, Component text) {
this.addEntry(ButtonEntry.create(button, text, resetButton, indexButton));
}
@Override
public int getRowWidth() {
return 10000;
}
public Optional<AbstractWidget> getHoveredButton(double mouseX, double mouseY) {
for (ButtonEntry buttonEntry : this.children()) {
if (buttonEntry.button != null && buttonEntry.button.isMouseOver(mouseX, mouseY)) {
return Optional.of(buttonEntry.button);
}
}
return Optional.empty();
}
}
public static class ButtonEntry extends ContainerObjectSelectionList.Entry<ButtonEntry> {
private static final Font textRenderer = Minecraft.getInstance().font;
public final AbstractWidget button;
private final AbstractWidget resetButton;
private final AbstractWidget indexButton;
private final Component text;
private final List<AbstractWidget> children = new ArrayList<>();
public static final Map<AbstractWidget, Component> buttonsWithText = new HashMap<>();
private ButtonEntry(AbstractWidget button, Component text, AbstractWidget resetButton, AbstractWidget indexButton) {
buttonsWithText.put(button, text);
this.button = button;
this.resetButton = resetButton;
this.text = text;
this.indexButton = indexButton;
if (button != null)
children.add(button);
if (resetButton != null)
children.add(resetButton);
if (indexButton != null)
children.add(indexButton);
}
public static ButtonEntry create(AbstractWidget button, Component text, AbstractWidget resetButton, AbstractWidget indexButton) {
return new ButtonEntry(button, text, resetButton, indexButton);
}
@Override
public void render(PoseStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) {
if (button != null) {
button.y = y;
button.render(matrices, mouseX, mouseY, tickDelta);
}
if (resetButton != null) {
resetButton.y = y;
resetButton.render(matrices, mouseX, mouseY, tickDelta);
}
if (indexButton != null) {
indexButton.y = y;
indexButton.render(matrices, mouseX, mouseY, tickDelta);
}
if (text != null && (!text.getString().contains("spacer") || button != null))
GuiComponent.drawString(matrices, textRenderer, text, 12, y + 5, 0xFFFFFF);
}
@Override
public List<? extends GuiEventListener> children() {
return children;
}
// Only for 1.17 and over
// Remove in 1.16 and below
#if POST_MC_1_17_1
@Override
public List<? extends NarratableEntry> narratables() {
return children;
}
#endif
}
}
+1 -1
Submodule core updated: d58cd204cc...6aab2d287c
@@ -0,0 +1,83 @@
package com.seibel.lod.mixins.client;
import com.seibel.lod.common.wrappers.gui.UpdateModScreen;
import com.seibel.lod.core.ModInfo;
import com.seibel.lod.core.api.internal.a7.ClientApi;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.jar.JarUtils;
import com.seibel.lod.core.jar.installer.ModrinthGetter;
import com.seibel.lod.core.jar.installer.WebDownloader;
import com.seibel.lod.core.wrapperInterfaces.IVersionConstants;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.main.GameConfig;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.io.IOException;
import java.nio.file.Files;
import java.security.MessageDigest;
import java.util.Objects;
@Mixin(Minecraft.class)
public class MixinMinecraft {
private static boolean deleteOldOnClose = false;
@Inject(
method = "<init>(Lnet/minecraft/client/main/GameConfig;)V",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;setScreen(Lnet/minecraft/client/gui/screens/Screen;)V")
)
public void onOpenScreen(GameConfig gameConfig, CallbackInfo ci) {
if (!Config.Client.AutoUpdater.enableAutoUpdater.get()) // Don't do anything if the user doesn't want it
return;
// Some init stuff
// We use sha1 to check the version as our versioning system is diffrent to the one on modrinth
if (!ModrinthGetter.init()) return;
String jarSha = "";
try { jarSha = JarUtils.getFileChecksum(MessageDigest.getInstance("SHA"), JarUtils.jarFile);
} catch (Exception e) {
e.printStackTrace();
return;
}
String mcVersion = SingletonInjector.INSTANCE.get(IVersionConstants.class).getMinecraftVersion();
// Check the sha's of both our stuff
if (jarSha.equals(ModrinthGetter.getLatestShaForVersion(mcVersion)))
return;
ClientApi.LOGGER.info("New version ("+ModrinthGetter.getLatestNameForVersion(mcVersion)+") of "+ModInfo.READABLE_NAME+" is available");
if (Config.Client.AutoUpdater.promptForUpdate.get()) {
// Objects.requireNonNull(Minecraft.getInstance()).setScreen(new UpdateModScreen()); // Just uncommenting this to not annoy other devs for now
deleteOldOnClose = UpdateModScreen.modUpdated;
} else {
// Auto-update mod
try {
ClientApi.LOGGER.info("Attempting to auto update "+ModInfo.READABLE_NAME);
WebDownloader.downloadAsFile(ModrinthGetter.getLatestDownloadForVersion(mcVersion), JarUtils.jarFile.getParentFile().toPath().resolve(ModInfo.NAME+"-"+ModrinthGetter.getLatestNameForVersion(mcVersion)+".jar").toFile());
deleteOldOnClose = true;
ClientApi.LOGGER.info(ModInfo.READABLE_NAME+" successfully updated. It will apply on game's relaunch");
} catch (Exception e) {
ClientApi.LOGGER.info("Failed to update "+ModInfo.READABLE_NAME+" to version "+ModrinthGetter.getLatestNameForVersion(mcVersion));
e.printStackTrace();
}
}
}
@Inject(at = @At("HEAD"), method = "close()V")
public void close(CallbackInfo ci) {
if (deleteOldOnClose) {
try {
Files.delete(JarUtils.jarFile.toPath());
} catch (Exception e) {
ClientApi.LOGGER.warn("Failed to delete previous " + ModInfo.READABLE_NAME + " file, please delete it manually at [" + JarUtils.jarFile + "]");
e.printStackTrace();
}
}
}
}
@@ -19,8 +19,8 @@
package com.seibel.lod.mixins.client;
import com.seibel.lod.common.wrappers.config.GetConfigScreen;
import com.seibel.lod.common.wrappers.config.TexturedButtonWidget;
import com.seibel.lod.common.wrappers.gui.GetConfigScreen;
import com.seibel.lod.common.wrappers.gui.TexturedButtonWidget;
import com.seibel.lod.core.ModInfo;
import com.seibel.lod.core.config.Config;
import net.minecraft.client.gui.screens.OptionsScreen;
@@ -19,8 +19,7 @@
package com.seibel.lod.wrappers.config;
import com.seibel.lod.common.wrappers.config.ConfigScreenMC;
import com.seibel.lod.common.wrappers.config.GetConfigScreen;
import com.seibel.lod.common.wrappers.gui.GetConfigScreen;
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
import com.terraformersmc.modmenu.api.ModMenuApi;
import net.fabricmc.api.EnvType;
@@ -16,7 +16,8 @@
"client.MixinGameRenderer",
"client.MixinLevelRenderer",
"client.MixinLightmap",
"client.MixinOptionsScreen"
"client.MixinOptionsScreen",
"client.MixinMinecraft"
],
"injectors": {
"defaultRequire": 1
@@ -19,8 +19,8 @@
package com.seibel.lod.mixins.client;
import com.seibel.lod.common.wrappers.config.GetConfigScreen;
import com.seibel.lod.common.wrappers.config.TexturedButtonWidget;
import com.seibel.lod.common.wrappers.gui.GetConfigScreen;
import com.seibel.lod.common.wrappers.gui.TexturedButtonWidget;
import com.seibel.lod.core.ModInfo;
import com.seibel.lod.core.config.Config;
import net.minecraft.client.gui.screens.OptionsScreen;