예제 #1
0
 private void parseSimpleFieldAnnotation(
     SetMultimap<String, ASMData> annotations,
     String annotationClassName,
     Function<ModContainer, Object> retreiver)
     throws IllegalAccessException {
   String[] annName = annotationClassName.split("\\.");
   String annotationName = annName[annName.length - 1];
   for (ASMData targets : annotations.get(annotationClassName)) {
     String targetMod = (String) targets.getAnnotationInfo().get("value");
     Field f = null;
     Object injectedMod = null;
     ModContainer mc = this;
     boolean isStatic = false;
     Class<?> clz = modInstance.getClass();
     if (!Strings.isNullOrEmpty(targetMod)) {
       if (Loader.isModLoaded(targetMod)) {
         mc = Loader.instance().getIndexedModList().get(targetMod);
       } else {
         mc = null;
       }
     }
     if (mc != null) {
       try {
         clz = Class.forName(targets.getClassName(), true, Loader.instance().getModClassLoader());
         f = clz.getDeclaredField(targets.getObjectName());
         f.setAccessible(true);
         isStatic = Modifier.isStatic(f.getModifiers());
         injectedMod = retreiver.apply(mc);
       } catch (Exception e) {
         Throwables.propagateIfPossible(e);
         FMLLog.log(
             getModId(),
             Level.WARNING,
             e,
             "Attempting to load @%s in class %s for %s and failing",
             annotationName,
             targets.getClassName(),
             mc.getModId());
       }
     }
     if (f != null) {
       Object target = null;
       if (!isStatic) {
         target = modInstance;
         if (!modInstance.getClass().equals(clz)) {
           FMLLog.log(
               getModId(),
               Level.WARNING,
               "Unable to inject @%s in non-static field %s.%s for %s as it is NOT the primary mod instance",
               annotationName,
               targets.getClassName(),
               targets.getObjectName(),
               mc.getModId());
           continue;
         }
       }
       f.set(target, injectedMod);
     }
   }
 }
예제 #2
0
 public void transition(LoaderState desiredState) {
   LoaderState oldState = state;
   state = state.transition(!errors.isEmpty());
   if (state != desiredState) {
     Throwable toThrow = null;
     FMLLog.severe(
         "Fatal errors were detected during the transition from %s to %s. Loading cannot continue",
         oldState, desiredState);
     StringBuilder sb = new StringBuilder();
     printModStates(sb);
     FMLLog.getLogger().severe(sb.toString());
     if (errors.size() > 0) {
       FMLLog.severe("The following problems were captured during this phase");
       for (Entry<String, Throwable> error : errors.entries()) {
         FMLLog.log(Level.SEVERE, error.getValue(), "Caught exception from %s", error.getKey());
         if (error.getValue() instanceof IFMLHandledException) {
           toThrow = error.getValue();
         } else if (toThrow == null) {
           toThrow = error.getValue();
         }
       }
     } else {
       FMLLog.severe(
           "The ForgeModLoader state engine has become corrupted. Probably, a state was missed by and invalid modification to a base class"
               + "ForgeModLoader depends on. This is a critical error and not recoverable. Investigate any modifications to base classes outside of"
               + "ForgeModLoader, especially Optifine, to see if there are fixes available.");
       throw new RuntimeException("The ForgeModLoader state engine is invalid");
     }
     if (toThrow != null && toThrow instanceof RuntimeException) {
       throw (RuntimeException) toThrow;
     } else {
       throw new LoaderException(toThrow);
     }
   }
 }
예제 #3
0
  public void runtimeDisableMod(String modId) {
    ModContainer mc = namedMods.get(modId);
    Disableable disableable = mc.canBeDisabled();
    if (disableable == Disableable.NEVER) {
      FMLLog.info("Cannot disable mod %s - it is never allowed to be disabled", modId);
      return;
    }
    if (disableable == Disableable.DEPENDENCIES) {
      FMLLog.info(
          "Cannot disable mod %s - there are dependent mods that require its presence", modId);
      return;
    }
    if (disableable == Disableable.YES) {
      FMLLog.info("Runtime disabling mod %s", modId);
      modController.disableMod(mc);
      List<ModContainer> localmods = Lists.newArrayList(mods);
      localmods.remove(mc);
      mods = ImmutableList.copyOf(localmods);
    }

    try {
      Properties props = new Properties();
      props.load(new FileReader(forcedModFile));
      props.put(modId, "false");
      props.store(new FileWriter(forcedModFile), null);
    } catch (Exception e) {
      FMLLog.log(
          Level.INFO,
          e,
          "An error occurred writing the fml mod states file, your disabled change won't persist");
    }
  }
예제 #4
0
 public Properties searchForVersionProperties() {
   try {
     FMLLog.log(
         getModId(),
         Level.FINE,
         "Attempting to load the file version.properties from %s to locate a version number for %s",
         getSource().getName(),
         getModId());
     Properties version = null;
     if (getSource().isFile()) {
       ZipFile source = new ZipFile(getSource());
       ZipEntry versionFile = source.getEntry("version.properties");
       if (versionFile != null) {
         version = new Properties();
         version.load(source.getInputStream(versionFile));
       }
       source.close();
     } else if (getSource().isDirectory()) {
       File propsFile = new File(getSource(), "version.properties");
       if (propsFile.exists() && propsFile.isFile()) {
         version = new Properties();
         FileInputStream fis = new FileInputStream(propsFile);
         version.load(fis);
         fis.close();
       }
     }
     return version;
   } catch (Exception e) {
     Throwables.propagateIfPossible(e);
     FMLLog.log(getModId(), Level.FINEST, "Failed to find a usable version.properties file");
     return null;
   }
 }
예제 #5
0
 public void beginLoading(IFMLSidedHandler handler) {
   sidedDelegate = handler;
   FMLLog.info("Attempting early MinecraftForge initialization");
   callForgeMethod("initialize");
   callForgeMethod("registerCrashCallable");
   FMLLog.info("Completed early MinecraftForge initialization");
 }
예제 #6
0
  @Subscribe
  public void buildModList(FMLLoadEvent event) {
    this.modList = loader.getIndexedModList();
    Builder<String, EventBus> eventBus = ImmutableMap.builder();

    for (ModContainer mod : loader.getModList()) {
      EventBus bus = new EventBus(mod.getModId());
      boolean isActive = mod.registerBus(bus, this);
      if (isActive) {
        Level level = Logger.getLogger(mod.getModId()).getLevel();
        FMLLog.log(
            mod.getModId(),
            Level.FINE,
            "Mod Logging channel %s configured at %s level.",
            level == null ? "default" : level);
        FMLLog.log(mod.getModId(), Level.INFO, "Activating mod %s", mod.getModId());
        activeModList.add(mod);
        modStates.put(mod.getModId(), ModState.UNLOADED);
        eventBus.put(mod.getModId(), bus);
      } else {
        FMLLog.log(
            mod.getModId(),
            Level.WARNING,
            "Mod %s has been disabled through configuration",
            mod.getModId());
        modStates.put(mod.getModId(), ModState.UNLOADED);
        modStates.put(mod.getModId(), ModState.DISABLED);
      }
    }

    eventChannels = eventBus.build();
  }
예제 #7
0
 private Method gatherAnnotations(Class<?> clazz) throws Exception {
   Method factoryMethod = null;
   for (Method m : clazz.getDeclaredMethods()) {
     for (Annotation a : m.getAnnotations()) {
       if (modTypeAnnotations.containsKey(a.annotationType())) {
         Class<?>[] paramTypes = new Class[] {modTypeAnnotations.get(a.annotationType())};
         if (Arrays.equals(m.getParameterTypes(), paramTypes)) {
           m.setAccessible(true);
           eventMethods.put(modTypeAnnotations.get(a.annotationType()), m);
         } else {
           FMLLog.log(
               getModId(),
               Level.SEVERE,
               "The mod %s appears to have an invalid method annotation %s. This annotation can only apply to methods with argument types %s -it will not be called",
               getModId(),
               a.annotationType().getSimpleName(),
               Arrays.toString(paramTypes));
         }
       } else if (a.annotationType().equals(Mod.EventHandler.class)) {
         if (m.getParameterTypes().length == 1
             && modAnnotationTypes.containsKey(m.getParameterTypes()[0])) {
           m.setAccessible(true);
           eventMethods.put((Class<? extends FMLEvent>) m.getParameterTypes()[0], m);
         } else {
           FMLLog.log(
               getModId(),
               Level.SEVERE,
               "The mod %s appears to have an invalid event annotation %s. This annotation can only apply to methods with recognized event arguments - it will not be called",
               getModId(),
               a.annotationType().getSimpleName());
         }
       } else if (a.annotationType().equals(Mod.InstanceFactory.class)) {
         if (Modifier.isStatic(m.getModifiers())
             && m.getParameterTypes().length == 0
             && factoryMethod == null) {
           m.setAccessible(true);
           factoryMethod = m;
         } else if (!(Modifier.isStatic(m.getModifiers()) && m.getParameterTypes().length == 0)) {
           FMLLog.log(
               getModId(),
               Level.SEVERE,
               "The InstanceFactory annotation can only apply to a static method, taking zero arguments - it will be ignored on %s(%s)",
               m.getName(),
               Arrays.asList(m.getParameterTypes()));
         } else if (factoryMethod != null) {
           FMLLog.log(
               getModId(),
               Level.SEVERE,
               "The InstanceFactory annotation can only be used once, the application to %s(%s) will be ignored",
               m.getName(),
               Arrays.asList(m.getParameterTypes()));
         }
       }
     }
   }
   return factoryMethod;
 }
예제 #8
0
  private void initializeLoader() {
    File modsDir = new File(minecraftDir, "mods");
    File configDir = new File(minecraftDir, "config");
    String canonicalModsPath;
    String canonicalConfigPath;

    try {
      canonicalModsPath = modsDir.getCanonicalPath();
      canonicalConfigPath = configDir.getCanonicalPath();
      canonicalConfigDir = configDir.getCanonicalFile();
      canonicalModsDir = modsDir.getCanonicalFile();
    } catch (IOException ioe) {
      FMLLog.log(
          Level.ERROR,
          ioe,
          "Failed to resolve loader directories: mods : %s ; config %s",
          canonicalModsDir.getAbsolutePath(),
          configDir.getAbsolutePath());
      throw new LoaderException(ioe);
    }

    if (!canonicalModsDir.exists()) {
      FMLLog.info("No mod directory found, creating one: %s", canonicalModsPath);
      boolean dirMade = canonicalModsDir.mkdir();
      if (!dirMade) {
        FMLLog.severe("Unable to create the mod directory %s", canonicalModsPath);
        throw new LoaderException(
            String.format("Unable to create the mod directory %s", canonicalModsPath));
      }
      FMLLog.info("Mod directory created successfully");
    }

    if (!canonicalConfigDir.exists()) {
      FMLLog.fine("No config directory found, creating one: %s", canonicalConfigPath);
      boolean dirMade = canonicalConfigDir.mkdir();
      if (!dirMade) {
        FMLLog.severe("Unable to create the config directory %s", canonicalConfigPath);
        throw new LoaderException();
      }
      FMLLog.info("Config directory created successfully");
    }

    if (!canonicalModsDir.isDirectory()) {
      FMLLog.severe("Attempting to load mods from %s, which is not a directory", canonicalModsPath);
      throw new LoaderException();
    }

    if (!configDir.isDirectory()) {
      FMLLog.severe(
          "Attempting to load configuration from %s, which is not a directory",
          canonicalConfigPath);
      throw new LoaderException();
    }

    readInjectedDependencies();
  }
예제 #9
0
 public ModMetadata(JsonNode node) {
   Map<JsonStringNode, Object> processedFields =
       Maps.transformValues(node.getFields(), new JsonStringConverter());
   modId = (String) processedFields.get(aStringBuilder("modid"));
   if (Strings.isNullOrEmpty(modId)) {
     FMLLog.log(Level.SEVERE, "Found an invalid mod metadata file - missing modid");
     throw new LoaderException();
   }
   name = Strings.nullToEmpty((String) processedFields.get(aStringBuilder("name")));
   description = Strings.nullToEmpty((String) processedFields.get(aStringBuilder("description")));
   url = Strings.nullToEmpty((String) processedFields.get(aStringBuilder("url")));
   updateUrl = Strings.nullToEmpty((String) processedFields.get(aStringBuilder("updateUrl")));
   logoFile = Strings.nullToEmpty((String) processedFields.get(aStringBuilder("logoFile")));
   version = Strings.nullToEmpty((String) processedFields.get(aStringBuilder("version")));
   credits = Strings.nullToEmpty((String) processedFields.get(aStringBuilder("credits")));
   parent = Strings.nullToEmpty((String) processedFields.get(aStringBuilder("parent")));
   authorList =
       Objects.firstNonNull(
           ((List<String>) processedFields.get(aStringBuilder("authors"))),
           Objects.firstNonNull(
               ((List<String>) processedFields.get(aStringBuilder("authorList"))), authorList));
   requiredMods =
       processReferences(processedFields.get(aStringBuilder("requiredMods")), HashSet.class);
   dependencies =
       processReferences(processedFields.get(aStringBuilder("dependencies")), ArrayList.class);
   dependants =
       processReferences(processedFields.get(aStringBuilder("dependants")), ArrayList.class);
   useDependencyInformation =
       Boolean.parseBoolean(
           Strings.nullToEmpty(
               (String) processedFields.get(aStringBuilder("useDependencyInformation"))));
 }
예제 #10
0
 public void distributeStateMessage(Class<?> customEvent) {
   try {
     masterChannel.post(customEvent.newInstance());
   } catch (Exception e) {
     FMLLog.log(Level.SEVERE, e, "An unexpected exception");
     throw new LoaderException(e);
   }
 }
예제 #11
0
 private void readInjectedDependencies() {
   File injectedDepFile = new File(getConfigDir(), "injectedDependencies.json");
   if (!injectedDepFile.exists()) {
     FMLLog.getLogger()
         .log(
             Level.DEBUG,
             "File {} not found. No dependencies injected",
             injectedDepFile.getAbsolutePath());
     return;
   }
   JsonParser parser = new JsonParser();
   JsonElement injectedDeps;
   try {
     injectedDeps = parser.parse(new FileReader(injectedDepFile));
     for (JsonElement el : injectedDeps.getAsJsonArray()) {
       JsonObject jo = el.getAsJsonObject();
       String modId = jo.get("modId").getAsString();
       JsonArray deps = jo.get("deps").getAsJsonArray();
       for (JsonElement dep : deps) {
         JsonObject depObj = dep.getAsJsonObject();
         String type = depObj.get("type").getAsString();
         if (type.equals("before")) {
           injectedBefore.put(
               modId, VersionParser.parseVersionReference(depObj.get("target").getAsString()));
         } else if (type.equals("after")) {
           injectedAfter.put(
               modId, VersionParser.parseVersionReference(depObj.get("target").getAsString()));
         } else {
           FMLLog.getLogger().log(Level.ERROR, "Invalid dependency type {}", type);
           throw new RuntimeException("Unable to parse type");
         }
       }
     }
   } catch (Exception e) {
     FMLLog.getLogger().log(Level.ERROR, "Unable to parse {} - skipping", injectedDepFile);
     FMLLog.getLogger().throwing(Level.ERROR, e);
     return;
   }
   FMLLog.getLogger()
       .log(
           Level.DEBUG,
           "Loaded {} injected dependencies on modIds: {}",
           injectedBefore.size(),
           injectedBefore.keySet());
 }
예제 #12
0
 public BiMap<ModContainer, Object> getModObjectList() {
   if (modObjectList == null) {
     FMLLog.severe(
         "Detected an attempt by a mod %s to perform game activity during mod construction. This is a serious programming error.",
         activeContainer);
     return buildModObjectList();
   }
   return ImmutableBiMap.copyOf(modObjectList);
 }
예제 #13
0
 public boolean serverStarting(Object server) {
   try {
     modController.distributeStateMessage(LoaderState.SERVER_STARTING, server);
     modController.transition(LoaderState.SERVER_STARTING, false);
   } catch (Throwable t) {
     FMLLog.log(Level.ERROR, t, "A fatal exception occurred during the server starting event");
     return false;
   }
   return true;
 }
예제 #14
0
 /**
  * Not a fully fleshed out API, may change in future MC versions. However feel free to use and
  * suggest additions.
  */
 public static void pop(ProgressBar bar) {
   if (bar.getSteps() != bar.getStep())
     throw new IllegalStateException("can't pop unfinished ProgressBar " + bar.getTitle());
   bars.remove(bar);
   if (bar.getSteps() != 0) {
     long newTime = System.nanoTime();
     if (bar.timeEachStep)
       FMLLog.fine(
           "Bar Step: %s - %s took %.3fs",
           bar.getTitle(), bar.getMessage(), ((float) (newTime - bar.lastTime) / 1000000 / 1000));
     if (bar.getSteps() == 1)
       FMLLog.fine(
           "Bar Finished: %s - %s took %.3fs",
           bar.getTitle(), bar.getMessage(), ((float) (newTime - bar.startTime) / 1000000 / 1000));
     else
       FMLLog.fine(
           "Bar Finished: %s took %.3fs",
           bar.getTitle(), ((float) (newTime - bar.startTime) / 1000000 / 1000));
   }
   FMLCommonHandler.instance().processWindowMessages();
 }
예제 #15
0
 @Override
 public boolean registerBus(EventBus bus, LoadController controller) {
   if (this.enabled) {
     FMLLog.log(getModId(), Level.FINE, "Enabling mod %s", getModId());
     this.eventBus = bus;
     this.controller = controller;
     eventBus.register(this);
     return true;
   } else {
     return false;
   }
 }
예제 #16
0
  @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);
      modMetadata.requiredMods = requirements;
      modMetadata.dependencies = dependencies;
      modMetadata.dependants = dependants;
      FMLLog.finest("Parsed dependency info : %s %s %s", requirements, dependencies, dependants);
    } else {
      FMLLog.finest(
          "Using mcmod dependency info : %s %s %s",
          modMetadata.requiredMods, modMetadata.dependencies, modMetadata.dependants);
    }
    if (Strings.isNullOrEmpty(modMetadata.name)) {
      FMLLog.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.fine(
            "Found version %s for mod %s in version.properties, using",
            internalVersion, getModId());
      }
    }
    if (Strings.isNullOrEmpty(internalVersion) && !Strings.isNullOrEmpty(modMetadata.version)) {
      FMLLog.warning(
          "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.warning(
          "Mod %s is missing the required element 'version' and no fallback can be found. Substituting '1.0'.",
          getModId());
      modMetadata.version = internalVersion = "1.0";
    }

    String mcVersionString = (String) descriptor.get("acceptedMinecraftVersions");
    if (!Strings.isNullOrEmpty(mcVersionString)) {
      minecraftAccepted = VersionParser.parseRange(mcVersionString);
    } else {
      minecraftAccepted = Loader.instance().getMinecraftModContainer().getStaticVersionRange();
    }
  }
예제 #17
0
 public void step(String message) {
   if (step >= steps) throw new IllegalStateException("too much steps for ProgressBar " + title);
   if (timeEachStep && step != 0) {
     long newTime = System.nanoTime();
     FMLLog.fine(
         "Bar Step: %s - %s took %.3fs",
         getTitle(), getMessage(), ((float) (newTime - lastTime) / 1000000 / 1000));
     lastTime = newTime;
   }
   step++;
   this.message = FMLCommonHandler.instance().stripSpecialChars(message);
   FMLCommonHandler.instance().processWindowMessages();
 }
예제 #18
0
 @Subscribe
 public void propogateStateMessage(FMLEvent stateEvent) {
   if (stateEvent instanceof FMLPreInitializationEvent) {
     modObjectList = buildModObjectList();
   }
   for (ModContainer mc : activeModList) {
     activeContainer = mc;
     String modId = mc.getModId();
     stateEvent.applyModContainer(activeContainer());
     FMLLog.log(
         modId, Level.FINEST, "Sending event %s to mod %s", stateEvent.getEventType(), modId);
     eventChannels.get(modId).post(stateEvent);
     FMLLog.log(modId, Level.FINEST, "Sent event %s to mod %s", stateEvent.getEventType(), modId);
     activeContainer = null;
     if (stateEvent instanceof FMLStateEvent) {
       if (!errors.containsKey(modId)) {
         modStates.put(modId, ((FMLStateEvent) stateEvent).getModState());
       } else {
         modStates.put(modId, ModState.ERRORED);
       }
     }
   }
 }
예제 #19
0
 public void preinitializeMods() {
   if (!modController.isInState(LoaderState.PREINITIALIZATION)) {
     FMLLog.warning("There were errors previously. Not beginning mod initialization phase");
     return;
   }
   ObjectHolderRegistry.INSTANCE.findObjectHolders(discoverer.getASMTable());
   ItemStackHolderInjector.INSTANCE.findHolders(discoverer.getASMTable());
   modController.distributeStateMessage(
       LoaderState.PREINITIALIZATION, discoverer.getASMTable(), canonicalConfigDir);
   ObjectHolderRegistry.INSTANCE.applyObjectHolders();
   ItemStackHolderInjector.INSTANCE.inject();
   modController.transition(LoaderState.INITIALIZATION, false);
   progressBar.step("Initializing Minecraft Engine");
 }
 @Override
 public void readData(
     SaveHandler handler, WorldInfo info, Map<String, NBTBase> propertyMap, NBTTagCompound tag) {
   if (tag.hasKey("ModList")) {
     NBTTagList modList = tag.getTagList("ModList");
     for (int i = 0; i < modList.tagCount(); i++) {
       NBTTagCompound mod = (NBTTagCompound) modList.tagAt(i);
       String modId = mod.getString("ModId");
       String modVersion = mod.getString("ModVersion");
       ModContainer container = Loader.instance().getIndexedModList().get(modId);
       if (container == null) {
         FMLLog.log(
             "fml.ModTracker",
             Level.SEVERE,
             "This world was saved with mod %s which appears to be missing, things may not work well",
             modId);
         continue;
       }
       if (!modVersion.equals(container.getVersion())) {
         FMLLog.log(
             "fml.ModTracker",
             Level.INFO,
             "This world was saved with mod %s version %s and it is now at version %s, things may not work well",
             modId,
             modVersion,
             container.getVersion());
       }
     }
   }
   if (tag.hasKey("ModItemData")) {
     NBTTagList modList = tag.getTagList("ModItemData");
     Set<ItemData> worldSaveItems = GameData.buildWorldItemData(modList);
     GameData.validateWorldSave(worldSaveItems);
   } else {
     GameData.validateWorldSave(null);
   }
 }
  public static void inject(
      ModContainer mod, ASMDataTable data, Side side, ILanguageAdapter languageAdapter) {
    FMLLog.fine("Attempting to inject @SidedProxy classes into %s", mod.getModId());
    Set<ASMData> targets = data.getAnnotationsFor(mod).get(SidedProxy.class.getName());
    ClassLoader mcl = Loader.instance().getModClassLoader();

    for (ASMData targ : targets) {
      try {
        Class<?> proxyTarget = Class.forName(targ.getClassName(), true, mcl);
        Field target = proxyTarget.getDeclaredField(targ.getObjectName());
        if (target == null) {
          // Impossible?
          FMLLog.severe(
              "Attempted to load a proxy type into %s.%s but the field was not found",
              targ.getClassName(), targ.getObjectName());
          throw new LoaderException();
        }

        SidedProxy annotation = target.getAnnotation(SidedProxy.class);
        if (!Strings.isNullOrEmpty(annotation.modId())
            && !annotation.modId().equals(mod.getModId())) {
          FMLLog.fine(
              "Skipping proxy injection for %s.%s since it is not for mod %s",
              targ.getClassName(), targ.getObjectName(), mod.getModId());
          continue;
        }
        String targetType = side.isClient() ? annotation.clientSide() : annotation.serverSide();
        Object proxy = Class.forName(targetType, true, mcl).newInstance();

        if (languageAdapter.supportsStatics() && (target.getModifiers() & Modifier.STATIC) == 0) {
          FMLLog.severe(
              "Attempted to load a proxy type %s into %s.%s, but the field is not static",
              targetType, targ.getClassName(), targ.getObjectName());
          throw new LoaderException();
        }
        if (!target.getType().isAssignableFrom(proxy.getClass())) {
          FMLLog.severe(
              "Attempted to load a proxy type %s into %s.%s, but the types don't match",
              targetType, targ.getClassName(), targ.getObjectName());
          throw new LoaderException();
        }
        languageAdapter.setProxy(target, proxyTarget, proxy);
      } catch (Exception e) {
        FMLLog.log(
            Level.SEVERE,
            e,
            "An error occured trying to load a proxy into %s.%s",
            targ.getAnnotationInfo(),
            targ.getClassName(),
            targ.getObjectName());
        throw new LoaderException(e);
      }
    }

    // Allow language specific proxy injection.
    languageAdapter.setInternalProxies(mod, side, mcl);
  }
예제 #22
0
  boolean checkRemoteModList(Map<String, String> modList, Side side) {
    Set<String> remoteModIds = modList.keySet();
    Set<String> localModIds = namedMods.keySet();

    Set<String> difference = Sets.newLinkedHashSet(Sets.difference(localModIds, remoteModIds));
    for (Iterator<String> iterator = difference.iterator(); iterator.hasNext(); ) {
      String missingRemotely = iterator.next();
      ModState modState = modController.getModState(namedMods.get(missingRemotely));
      if (modState == ModState.DISABLED) {
        iterator.remove();
      }
    }

    if (difference.size() > 0)
      FMLLog.info("Attempting connection with missing mods %s at %s", difference, side);
    return true;
  }
예제 #23
0
  /**
   * The primary loading code
   *
   * <p>The found resources are first loaded into the {@link #modClassLoader} (always) then scanned
   * for class resources matching the specification above.
   *
   * <p>If they provide the {@link Mod} annotation, they will be loaded as "FML mods"
   *
   * <p>Finally, if they are successfully loaded as classes, they are then added to the available
   * mod list.
   */
  private ModDiscoverer identifyMods() {
    FMLLog.fine("Building injected Mod Containers %s", injectedContainers);
    // Add in the MCP mod container
    mods.add(new InjectedModContainer(mcp, new File("minecraft.jar")));
    for (String cont : injectedContainers) {
      ModContainer mc;
      try {
        mc = (ModContainer) Class.forName(cont, true, modClassLoader).newInstance();
      } catch (Exception e) {
        FMLLog.log(
            Level.ERROR, e, "A problem occured instantiating the injected mod container %s", cont);
        throw new LoaderException(e);
      }
      mods.add(new InjectedModContainer(mc, mc.getSource()));
    }
    ModDiscoverer discoverer = new ModDiscoverer();
    FMLLog.fine(
        "Attempting to load mods contained in the minecraft jar file and associated classes");
    discoverer.findClasspathMods(modClassLoader);
    FMLLog.fine("Minecraft jar mods loaded successfully");

    FMLLog.getLogger()
        .log(
            Level.INFO,
            "Found {} mods from the command line. Injecting into mod discoverer",
            ModListHelper.additionalMods.size());
    FMLLog.info("Searching %s for mods", canonicalModsDir.getAbsolutePath());
    discoverer.findModDirMods(
        canonicalModsDir, ModListHelper.additionalMods.values().toArray(new File[0]));
    File versionSpecificModsDir = new File(canonicalModsDir, mccversion);
    if (versionSpecificModsDir.isDirectory()) {
      FMLLog.info("Also searching %s for mods", versionSpecificModsDir);
      discoverer.findModDirMods(versionSpecificModsDir);
    }

    mods.addAll(discoverer.identifyMods());
    identifyDuplicates(mods);
    namedMods = Maps.uniqueIndex(mods, new ModIdFunction());
    FMLLog.info(
        "Forge Mod Loader has identified %d mod%s to load",
        mods.size(), mods.size() != 1 ? "s" : "");
    return discoverer;
  }
예제 #24
0
 public ImmutableBiMap<ModContainer, Object> buildModObjectList() {
   ImmutableBiMap.Builder<ModContainer, Object> builder =
       ImmutableBiMap.<ModContainer, Object>builder();
   for (ModContainer mc : activeModList) {
     if (!mc.isImmutable() && mc.getMod() != null) {
       builder.put(mc, mc.getMod());
     }
     if (mc.getMod() == null && !mc.isImmutable() && state != LoaderState.CONSTRUCTING) {
       FMLLog.severe(
           "There is a severe problem with %s - it appears not to have constructed correctly",
           mc.getModId());
       if (state != LoaderState.CONSTRUCTING) {
         this.errorOccurred(mc, new RuntimeException());
       }
     }
   }
   return builder.build();
 }
예제 #25
0
  private Loader() {
    modClassLoader = new ModClassLoader(getClass().getClassLoader());
    if (!mccversion.equals(MC_VERSION)) {
      FMLLog.severe(
          "This version of FML is built for Minecraft %s, we have detected Minecraft %s in your minecraft jar file",
          mccversion, MC_VERSION);
      throw new LoaderException(
          String.format(
              "This version of FML is built for Minecraft %s, we have detected Minecraft %s in your minecraft jar file",
              mccversion, MC_VERSION));
    }

    minecraft = new MinecraftDummyContainer(MC_VERSION);
    mcp =
        new MCPDummyContainer(
            MetadataCollection.from(getClass().getResourceAsStream("/mcpmod.info"), "MCP")
                .getMetadataForId("mcp", null));
  }
예제 #26
0
 public void initializeMods() {
   progressBar.step("Initializing mods Phase 2");
   // Mod controller should be in the initialization state here
   modController.distributeStateMessage(LoaderState.INITIALIZATION);
   progressBar.step("Initializing mods Phase 3");
   modController.transition(LoaderState.POSTINITIALIZATION, false);
   modController.distributeStateMessage(FMLInterModComms.IMCEvent.class);
   ItemStackHolderInjector.INSTANCE.inject();
   modController.distributeStateMessage(LoaderState.POSTINITIALIZATION);
   progressBar.step("Finishing up");
   modController.transition(LoaderState.AVAILABLE, false);
   modController.distributeStateMessage(LoaderState.AVAILABLE);
   GameData.freezeData();
   FMLLog.info(
       "Forge Mod Loader has successfully loaded %d mod%s",
       mods.size(), mods.size() == 1 ? "" : "s");
   progressBar.step("Completing Minecraft initialization");
 }
예제 #27
0
  private void disableRequestedMods() {
    String forcedModList = System.getProperty("fml.modStates", "");
    FMLLog.finer("Received a system property request \'%s\'", forcedModList);
    Map<String, String> sysPropertyStateList =
        Splitter.on(CharMatcher.anyOf(";:"))
            .omitEmptyStrings()
            .trimResults()
            .withKeyValueSeparator("=")
            .split(forcedModList);
    FMLLog.finer(
        "System property request managing the state of %d mods", sysPropertyStateList.size());
    Map<String, String> modStates = Maps.newHashMap();

    forcedModFile = new File(canonicalConfigDir, "fmlModState.properties");
    Properties forcedModListProperties = new Properties();
    if (forcedModFile.exists() && forcedModFile.isFile()) {
      FMLLog.finer("Found a mod state file %s", forcedModFile.getName());
      try {
        forcedModListProperties.load(new FileReader(forcedModFile));
        FMLLog.finer("Loaded states for %d mods from file", forcedModListProperties.size());
      } catch (Exception e) {
        FMLLog.log(Level.INFO, e, "An error occurred reading the fmlModState.properties file");
      }
    }
    modStates.putAll(Maps.fromProperties(forcedModListProperties));
    modStates.putAll(sysPropertyStateList);
    FMLLog.fine("After merging, found state information for %d mods", modStates.size());

    Map<String, Boolean> isEnabled =
        Maps.transformValues(
            modStates,
            new Function<String, Boolean>() {
              @Override
              public Boolean apply(String input) {
                return Boolean.parseBoolean(input);
              }
            });

    for (Map.Entry<String, Boolean> entry : isEnabled.entrySet()) {
      if (namedMods.containsKey(entry.getKey())) {
        FMLLog.info("Setting mod %s to enabled state %b", entry.getKey(), entry.getValue());
        namedMods.get(entry.getKey()).setEnabledState(entry.getValue());
      }
    }
  }
예제 #28
0
  private Multimap<Class<? extends Annotation>, Object> gatherAnnotations(Class<?> clazz)
      throws Exception {
    Multimap<Class<? extends Annotation>, Object> anns = ArrayListMultimap.create();

    for (Method m : clazz.getDeclaredMethods()) {
      for (Annotation a : m.getAnnotations()) {
        if (modTypeAnnotations.containsKey(a.annotationType())) {
          Class<?>[] paramTypes = new Class[] {modTypeAnnotations.get(a.annotationType())};

          if (Arrays.equals(m.getParameterTypes(), paramTypes)) {
            m.setAccessible(true);
            anns.put(a.annotationType(), m);
          } else {
            FMLLog.severe(
                "The mod %s appears to have an invalid method annotation %s. This annotation can only apply to methods with argument types %s -it will not be called",
                getModId(), a.annotationType().getSimpleName(), Arrays.toString(paramTypes));
          }
        }
      }
    }
    return anns;
  }
예제 #29
0
 @Subscribe
 public void constructMod(FMLConstructionEvent event) {
   try {
     ModClassLoader modClassLoader = event.getModClassLoader();
     modClassLoader.addFile(source);
     // MCPC - show users what mod is being loaded in case a crash occurs
     FMLLog.fine("Constructing mod from file source : " + source);
     Class<?> clazz = Class.forName(className, true, modClassLoader);
     ASMDataTable asmHarvestedAnnotations = event.getASMHarvestedData();
     // TODO
     asmHarvestedAnnotations.getAnnotationsFor(this);
     annotations = gatherAnnotations(clazz);
     isNetworkMod =
         FMLNetworkHandler.instance().registerNetworkMod(this, clazz, event.getASMHarvestedData());
     modInstance = clazz.newInstance();
     ProxyInjector.inject(
         this, event.getASMHarvestedData(), FMLCommonHandler.instance().getSide());
     processFieldAnnotations(event.getASMHarvestedData());
   } catch (Throwable e) {
     controller.errorOccurred(this, e);
     Throwables.propagateIfPossible(e);
   }
 }
예제 #30
0
  private void identifyDuplicates(List<ModContainer> mods) {
    TreeMultimap<ModContainer, File> dupsearch =
        TreeMultimap.create(new ModIdComparator(), Ordering.arbitrary());
    for (ModContainer mc : mods) {
      if (mc.getSource() != null) {
        dupsearch.put(mc, mc.getSource());
      }
    }

    ImmutableMultiset<ModContainer> duplist = Multisets.copyHighestCountFirst(dupsearch.keys());
    SetMultimap<ModContainer, File> dupes = LinkedHashMultimap.create();
    for (Entry<ModContainer> e : duplist.entrySet()) {
      if (e.getCount() > 1) {
        FMLLog.severe(
            "Found a duplicate mod %s at %s",
            e.getElement().getModId(), dupsearch.get(e.getElement()));
        dupes.putAll(e.getElement(), dupsearch.get(e.getElement()));
      }
    }
    if (!dupes.isEmpty()) {
      throw new DuplicateModsFoundException(dupes);
    }
  }