/*
* Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
* Copyright (C) 2021 cyoung06
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
package kr.syeyoung.dungeonsguide.launcher;
import kr.syeyoung.dungeonsguide.launcher.auth.AuthManager;
import kr.syeyoung.dungeonsguide.launcher.branch.UpdateRetrieverUtil;
import kr.syeyoung.dungeonsguide.launcher.exceptions.DungeonsGuideLoadingException;
import kr.syeyoung.dungeonsguide.launcher.exceptions.NoSuitableLoaderFoundException;
import kr.syeyoung.dungeonsguide.launcher.exceptions.NoVersionFoundException;
import kr.syeyoung.dungeonsguide.launcher.exceptions.ReferenceLeakedException;
import kr.syeyoung.dungeonsguide.launcher.exceptions.auth.AuthenticationUnavailableException;
import kr.syeyoung.dungeonsguide.launcher.gui.screen.GuiDisplayer;
import kr.syeyoung.dungeonsguide.launcher.gui.screen.GuiLoadingError;
import kr.syeyoung.dungeonsguide.launcher.gui.screen.GuiReferenceLeak;
import kr.syeyoung.dungeonsguide.launcher.gui.screen.SpecialGuiScreen;
import kr.syeyoung.dungeonsguide.launcher.loader.IDGLoader;
import kr.syeyoung.dungeonsguide.launcher.loader.JarLoader;
import kr.syeyoung.dungeonsguide.launcher.loader.LocalLoader;
import kr.syeyoung.dungeonsguide.launcher.loader.RemoteLoader;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.IReloadableResourceManager;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.ProgressManager;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import java.io.*;
import java.util.*;
@Mod(modid = Main.MOD_ID, version = Main.VERSION)
public class Main
{
public static final String MOD_ID = "dungeons_guide_wrapper";
public static final String VERSION = "1.0";
public static final String DOMAIN = "http://testmachine2/api";
private static Main main;
private static File configDir;
private DGInterface dgInterface;
private final List listeners = new ArrayList<>();
public static File getConfigDir() {
return configDir;
}
public void addDGReloadListener(DungeonsGuideReloadListener dungeonsGuideReloadListener) {
listeners.add(Objects.requireNonNull(dungeonsGuideReloadListener));
}
public void removeDGReloadListener(DungeonsGuideReloadListener dungeonsGuideReloadListener) {
listeners.remove(dungeonsGuideReloadListener);
}
private IDGLoader currentLoader;
@EventHandler
public void initEvent(FMLInitializationEvent initializationEvent) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
MinecraftForge.EVENT_BUS.register(this);
MinecraftForge.EVENT_BUS.register(GuiDisplayer.INSTANCE);
try {
File f = new File(configDir, "loader.cfg");
Configuration configuration = new Configuration(f);
IDGLoader idgLoader = obtainLoader(configuration);
load(idgLoader);
} catch (NoSuitableLoaderFoundException e) {
e.printStackTrace();
GuiDisplayer.INSTANCE.displayGui(new GuiLoadingError(e));
} catch (NoVersionFoundException e) {
e.printStackTrace();
GuiDisplayer.INSTANCE.displayGui(new GuiLoadingError(e));
} catch (DungeonsGuideLoadingException e) {
e.printStackTrace();
GuiDisplayer.INSTANCE.displayGui(new GuiLoadingError(e));
}
}
public void unload() throws ReferenceLeakedException {
if (currentLoader != null && !currentLoader.isUnloadable()) {
throw new UnsupportedOperationException("Current version is not unloadable");
}
dgInterface = null;
for (DungeonsGuideReloadListener listener : listeners) {
listener.unloadReference();
}
if (currentLoader != null) {
currentLoader.unloadDungeonsGuide();
}
currentLoader = null;
}
private void load(IDGLoader newLoader) throws DungeonsGuideLoadingException {
if (dgInterface != null) throw new IllegalStateException("DG is loaded");
dgInterface = newLoader.loadDungeonsGuide();
currentLoader = newLoader;
dgInterface.init(configDir);
for (DungeonsGuideReloadListener listener : listeners) {
listener.onLoad(dgInterface);
}
}
public void reload(IDGLoader newLoader) {
try {
unload();
load(newLoader);
} catch (DungeonsGuideLoadingException | ReferenceLeakedException e) {
dgInterface = null;
currentLoader = null;
e.printStackTrace();
if (e instanceof DungeonsGuideLoadingException) {
GuiDisplayer.INSTANCE.displayGui(new GuiLoadingError(e));
} else {
GuiDisplayer.INSTANCE.displayGui(new GuiReferenceLeak(e));
}
}
}
public String getLoaderName(Configuration configuration) {
String loader = System.getProperty("dg.loader");
if (loader == null) {
loader = configuration.get("loader", "modsource", "auto").getString();
}
if (loader == null) loader = "auto";
return loader;
}
public IDGLoader obtainLoader(Configuration configuration) throws NoVersionFoundException, NoSuitableLoaderFoundException {
String loader = getLoaderName(configuration);
if ("local".equals(loader) ||
(loader.equals("auto") && this.getClass().getResourceAsStream("/kr/syeyoung/dungeonsguide/DungeonsGuide.class") == null)) {
return new LocalLoader();
} else if ("jar".equals(loader) ||
(loader.equals("auto") && this.getClass().getResourceAsStream("/mod.jar") == null)) {
return new JarLoader();
} else if (loader.equals("remote") || loader.equals("auto") ){
// remote load
String branch = System.getProperty("branch") == null ? configuration.get("loader", "remoteBranch", "$default").getString() : System.getProperty("branch");
String version = System.getProperty("version") == null ? configuration.get("loader", "remoteVersion", "latest").getString() : System.getProperty("version");
try {
UpdateRetrieverUtil.VersionInfo versionInfo = UpdateRetrieverUtil.getIds(
branch,
version
);
return new RemoteLoader(versionInfo.getFriendlyBranchName(), versionInfo.getBranchId(), versionInfo.getUpdateId());
} catch (IOException e) {
throw new NoVersionFoundException(branch, version, "IO err", e);
}
} else {
throw new NoSuitableLoaderFoundException(System.getProperty("dg.loader"), configuration.get("loader", "modsource", "auto").getString());
}
}
@EventHandler
public void preInit(FMLPreInitializationEvent preInitializationEvent) {
// setup static variables
main = this;
dgInterface = null;
currentLoader = null;
configDir = preInitializationEvent.getModConfigurationDirectory();
// setup preinit progress bar for well, progress bar!
ProgressManager.ProgressBar bar = ProgressManager.push("DungeonsGuide", 1);
// Try authenticate
bar.step("Authenticating...");
try {
AuthManager.getInstance().init();
} catch (Exception e) {
e.printStackTrace();
}
File f = new File(preInitializationEvent.getModConfigurationDirectory(), "loader.cfg");
Configuration configuration = new Configuration(f);
// Save config because... well to generate it
configuration.save();
while(bar.getStep() < bar.getSteps()) bar.step("");
ProgressManager.pop(bar);
((IReloadableResourceManager) Minecraft.getMinecraft().getResourceManager()).registerReloadListener(a -> {
if (dgInterface != null) dgInterface.onResourceReload(a);
});
}
public static Main getMain() {
return main;
}
}