gt:             modMetadata.version = internalVersion = "1.0";
context: /*
   * The FML Forge Mod Loader suite. Copyright (C) 2012 cpw
   *
   * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
   * Software Foundation; either version 2.1 of the License, or any later version.
   *
   * This library 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 Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
   * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  package net.minecraftforge.fml.common;
  
  import java.io.File;
  import java.io.FileInputStream;
  import java.lang.annotation.Annotation;
  import java.lang.reflect.Field;
  import java.lang.reflect.Method;
  import java.lang.reflect.Modifier;
  import java.security.cert.Certificate;
  import java.util.Arrays;
  import java.util.List;
  import java.util.Map;
  import java.util.Properties;
  import java.util.Set;
  
  import net.minecraftforge.fml.common.Mod.Instance;
  import net.minecraftforge.fml.common.Mod.Metadata;
  import net.minecraftforge.fml.common.asm.transformers.BlamingTransformer;
  import net.minecraftforge.fml.common.discovery.ASMDataTable;
  import net.minecraftforge.fml.common.discovery.ModCandidate;
  import net.minecraftforge.fml.common.discovery.ASMDataTable.ASMData;
  import net.minecraftforge.fml.common.event.FMLConstructionEvent;
  import net.minecraftforge.fml.common.event.FMLEvent;
  import net.minecraftforge.fml.common.event.FMLFingerprintViolationEvent;
  import net.minecraftforge.fml.common.network.NetworkRegistry;
  import net.minecraftforge.fml.common.versioning.ArtifactVersion;
  import net.minecraftforge.fml.common.versioning.DefaultArtifactVersion;
  import net.minecraftforge.fml.common.versioning.VersionParser;
  import net.minecraftforge.fml.common.versioning.VersionRange;
  import net.minecraftforge.fml.relauncher.Side;
  
  import org.apache.logging.log4j.Level;
  
  import java.util.zip.ZipEntry;
  import java.util.zip.ZipFile;
  
  import com.google.common.base.Function;
  import com.google.common.base.Strings;
  import com.google.common.base.Throwables;
  import com.google.common.collect.ArrayListMultimap;
  import com.google.common.collect.ImmutableList;
  import com.google.common.collect.ImmutableList.Builder;
  import com.google.common.collect.ImmutableMap;
  import com.google.common.collect.ImmutableSet;
  import com.google.common.collect.ListMultimap;
  import com.google.common.collect.Lists;
  import com.google.common.collect.Maps;
  import com.google.common.collect.SetMultimap;
  import com.google.common.collect.Sets;
  import com.google.common.eventbus.EventBus;
  import com.google.common.eventbus.Subscribe;
  
  public class FMLModContainer implements ModContainer
  {
      private Object modInstance;
      private File source;
      private ModMetadata modMetadata;
      private String className;
      private Map<String, Object> descriptor;
      private boolean enabled = true;
      private String internalVersion;
      private boolean overridesMetadata;
      private EventBus eventBus;
      private LoadController controller;
      private DefaultArtifactVersion processedVersion;
  
      private String annotationDependencies;
      private VersionRange minecraftAccepted;
      private boolean fingerprintNotPresent;
      private Set<String> sourceFingerprints;
      private Certificate certificate;
      private String modLanguage;
      private ILanguageAdapter languageAdapter;
      private Disableable disableability;
      private ListMultimap<Class<? extends FMLEvent>,Method> eventMethods;
      private Map<String, String> customModProperties;
      private ModCandidate candidate;
  
      public FMLModContainer(String className, ModCandidate container, Map<String,Object> modDescriptor)
      {
          this.className = className;
          this.source = container.getModContainer();
          this.candidate = container;
          this.descriptor = modDescriptor;
          this.eventMethods = ArrayListMultimap.create();
  
          this.modLanguage = (String) modDescriptor.get("modLanguage");
          String languageAdapterType = (String)modDescriptor.get("modLanguageAdapter");
          if (Strings.isNullOrEmpty(languageAdapterType))
          {
              this.languageAdapter = "scala".equals(modLanguage) ? new ILanguageAdapter.ScalaAdapter() : new ILanguageAdapter.JavaAdapter();
          }
          else
          {
              try
              {
                  this.languageAdapter = (ILanguageAdapter)Class.forName(languageAdapterType, true, Loader.instance().getModClassLoader()).newInstance();
                  FMLLog.finer("Using custom language adapter %s (type %s) for %s (modid %s)", this.languageAdapter, languageAdapterType, this.className, getModId());
              }
              catch (Exception ex)
              {
                  FMLLog.log(Level.ERROR, ex, "Error constructing custom mod language adapter %s (referenced by %s) (modid: %s)", languageAdapterType, this.className, getModId());
                  throw new LoaderException(ex);
              }
          }
      }
  
      private ILanguageAdapter getLanguageAdapter()
      {
          return languageAdapter;
      }
      @Override
      public String getModId()
      {
          return (String) descriptor.get("modid");
      }
  
      @Override
      public String getName()
      {
          return modMetadata.name;
      }
  
      @Override
      public String getVersion()
      {
          return internalVersion;
      }
  
      @Override
      public File getSource()
      {
          return source;
      }
  
      @Override
      public ModMetadata getMetadata()
      {
          return modMetadata;
      }
  
      @Override
      public void bindMetadata(MetadataCollection mc)
      {
          modMetadata = mc.getMetadataForId(getModId(), descriptor);
  
          if (descriptor.containsKey("useMetadata"))
          {
              overridesMetadata = !((Boolean)descriptor.get("useMetadata")).booleanValue();
          }
  
          if (overridesMetadata || !modMetadata.useDependencyInformation)
          {
              Set<ArtifactVersion> requirements = Sets.newHashSet();
              List<ArtifactVersion> dependencies = Lists.newArrayList();
              List<ArtifactVersion> dependants = Lists.newArrayList();
              annotationDependencies = (String) descriptor.get("dependencies");
              Loader.instance().computeDependencies(annotationDependencies, requirements, dependencies, dependants);
              dependants.addAll(Loader.instance().getInjectedBefore(getModId()));
              dependencies.addAll(Loader.instance().getInjectedAfter(getModId()));
              modMetadata.requiredMods = requirements;
              modMetadata.dependencies = dependencies;
              modMetadata.dependants = dependants;
              FMLLog.log(getModId(), Level.TRACE, "Parsed dependency info : %s %s %s", requirements, dependencies, dependants);
          }
          else
          {
              FMLLog.log(getModId(), Level.TRACE, "Using mcmod dependency info : %s %s %s", modMetadata.requiredMods, modMetadata.dependencies, modMetadata.dependants);
          }
          if (Strings.isNullOrEmpty(modMetadata.name))
          {
              FMLLog.log(getModId(), Level.INFO,"Mod %s is missing the required element 'name'. Substituting %s", getModId(), getModId());
              modMetadata.name = getModId();
          }
          internalVersion = (String) descriptor.get("version");
          if (Strings.isNullOrEmpty(internalVersion))
          {
              Properties versionProps = searchForVersionProperties();
              if (versionProps != null)
              {
                  internalVersion = versionProps.getProperty(getModId()+".version");
                  FMLLog.log(getModId(), Level.DEBUG, "Found version %s for mod %s in version.properties, using", internalVersion, getModId());
              }
  
          }
          if (Strings.isNullOrEmpty(internalVersion) && !Strings.isNullOrEmpty(modMetadata.version))
          {
              FMLLog.log(getModId(), Level.WARN, "Mod %s is missing the required element 'version' and a version.properties file could not be found. Falling back to metadata version %s", getModId(), modMetadata.version);
              internalVersion = modMetadata.version;
          }
          if (Strings.isNullOrEmpty(internalVersion))
          {
              FMLLog.log(getModId(), Level.WARN, "Mod %s is missing the required element 'version' and no fallback can be found. Substituting '1.0'.", getModId());
  