package cofh.mod; import cofh.mod.updater.IUpdatableMod; import cofh.mod.updater.ModRange; import cofh.mod.updater.ModVersion; import com.google.common.base.Strings; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.ICrashCallable; import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.ModContainer; import cpw.mods.fml.common.ObfuscationReflectionHelper; import cpw.mods.fml.common.network.NetworkCheckHandler; import cpw.mods.fml.common.registry.LanguageRegistry; import cpw.mods.fml.common.versioning.InvalidVersionSpecificationException; import cpw.mods.fml.relauncher.FMLLaunchHandler; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Properties; import java.util.jar.JarFile; import java.util.zip.ZipEntry; import net.minecraft.client.Minecraft; import net.minecraft.client.resources.IReloadableResourceManager; import net.minecraft.client.resources.IResource; import net.minecraft.client.resources.IResourceManager; import net.minecraft.client.resources.IResourceManagerReloadListener; import net.minecraft.util.ResourceLocation; import net.minecraft.util.StringTranslate; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.core.helpers.Loader; import org.apache.logging.log4j.spi.AbstractLogger; public abstract class BaseMod implements IUpdatableMod { protected File _configFolder; protected final String _modid; protected final Logger _log; protected BaseMod(Logger log) { String name = getModId(); _modid = name.toLowerCase(Locale.US); _log = log; init(); } protected BaseMod() { String name = getModId(); _modid = name.toLowerCase(Locale.US); _log = LogManager.getLogger(name); init(); } private void init() { ModContainer container = cpw.mods.fml.common.Loader.instance().activeModContainer(); if (container.getSource().isDirectory()) { FMLCommonHandler.instance().registerCrashCallable(new CrashCallable("Loaded from a directory")); } else { try { JarFile jar = new JarFile(container.getSource()); ZipEntry file = jar.getEntry("vers.prop"); if (file != null) { BufferedReader reader = new BufferedReader(new InputStreamReader(jar.getInputStream(file))); String data = reader.readLine(); FMLCommonHandler.instance().registerCrashCallable(new CrashCallable(data)); } else { FMLCommonHandler.instance().registerCrashCallable(new CrashCallable("Lacking version information.")); } jar.close(); } catch (IOException e) { FMLCommonHandler.instance().registerCrashCallable(new CrashCallable("Error reading version information." + e.getMessage())); } } } @NetworkCheckHandler public final boolean networkCheck(Map remoteVersions, Side side) throws InvalidVersionSpecificationException { if (!requiresRemoteFrom(side)) { return true; } Mod mod = getClass().getAnnotation(Mod.class); String _modid = mod.modid(); if (!remoteVersions.containsKey(_modid)) { return false; } String remotes = mod.acceptableRemoteVersions(); if (!"*".equals(remotes)) { String remote = remoteVersions.get(_modid); if (Strings.isNullOrEmpty(remotes)) { return getModVersion().equalsIgnoreCase(remote); } return ModRange.createFromVersionSpec(_modid, remotes).containsVersion(new ModVersion(_modid, remote)); } return true; } protected boolean requiresRemoteFrom(Side side) { return true; } protected String getConfigBaseFolder() { String base = getClass().getPackage().getName(); int i = base.indexOf('.'); if (i >= 0) { return base.substring(0, i); } return ""; } protected void setConfigFolderBase(File folder) { _configFolder = new File(folder, getConfigBaseFolder() + "/" + _modid + "/"); } protected File getConfig(String name) { return new File(_configFolder, name + ".cfg"); } protected File getClientConfig() { return getConfig("client"); } protected File getCommonConfig() { return getConfig("common"); } protected String getAssetDir() { return _modid; } @Override public Logger getLogger() { return _log; } private void loadLanguageFile(Properties lang, InputStream stream) throws Throwable { InputStreamReader is = new InputStreamReader(stream, "UTF-8"); Properties langPack = new Properties(); langPack.load(is); lang.putAll(langPack); } @SuppressWarnings({ "unchecked", "rawtypes" }) private void loadLanguageFile(String lang, Properties langPack) { HashMap parsedLangFile = new HashMap(); parsedLangFile.putAll((Map) langPack); // lovely casting hack LanguageRegistry.instance().injectLanguage(lang.intern(), parsedLangFile); } @SuppressWarnings({ "unchecked", "rawtypes" }) protected void loadLang() { if (FMLLaunchHandler.side() == Side.CLIENT) { try { loadClientLang(); return; } catch (Throwable t) { _log.error(AbstractLogger.CATCHING_MARKER, "???", t); } } String path = "assets/" + getAssetDir() + "/language/"; String lang = "en_US"; try (InputStream is = Loader.getResource(path + lang + ".lang", null).openStream();) { Properties langPack = new Properties(); loadLanguageFile(langPack, is); StringTranslate i = ObfuscationReflectionHelper.getPrivateValue(StringTranslate.class, null, "instance", "field_74817_a"); Map m = ObfuscationReflectionHelper.getPrivateValue(StringTranslate.class, i, "field_74816_c", "languageList"); m.putAll(langPack); } catch (Throwable t) { _log.catching(Level.INFO, t); } } @SideOnly(Side.CLIENT) private void loadClientLang() { IReloadableResourceManager manager = (IReloadableResourceManager) Minecraft.getMinecraft().getResourceManager(); manager.registerReloadListener(new LangManager(manager)); } @SideOnly(Side.CLIENT) private class LangManager implements IResourceManagerReloadListener { private final String _path; public LangManager(IResourceManager manager) { _path = getAssetDir() + ":language/"; onResourceManagerReload(manager); } @Override public void onResourceManagerReload(IResourceManager manager) { String l = null; try { l = Minecraft.getMinecraft().getLanguageManager().getCurrentLanguage().getLanguageCode(); } catch (Throwable t) { _log.catching(Level.WARN, t); } for (String lang : Arrays.asList("en_US", l)) { if (lang != null) { Properties langPack = new Properties(); try { List files = manager.getAllResources(new ResourceLocation(_path + lang + ".lang")); for (IResource file : files) { if (file.getInputStream() == null) { _log.warn("A resource pack defines an entry for language '" + lang + "' but the InputStream is null."); continue; } try { loadLanguageFile(langPack, file.getInputStream()); } catch (Throwable t) { _log.warn(AbstractLogger.CATCHING_MARKER, "A resource pack has a file for language '" + lang + "' but the file is invalid.", t); } } } catch (Throwable t) { _log.info(AbstractLogger.CATCHING_MARKER, "No language data for '" + lang + "'", t); } loadLanguageFile(lang, langPack); } } Minecraft.getMinecraft().getLanguageManager().onResourceManagerReload(manager); } } private class CrashCallable implements ICrashCallable { private final String data; private CrashCallable(String data) { this.data = data; } @Override public String call() throws Exception { return data; } @Override public String getLabel() { return getModId(); } } }