예제 #1
0
  public static List<String> processIdRematches(
      Iterable<MissingMapping> missedMappings,
      boolean isLocalWorld,
      GameData gameData,
      Map<String, Integer[]> remapBlocks,
      Map<String, Integer[]> remapItems) {
    List<String> failed = Lists.newArrayList();
    List<String> ignored = Lists.newArrayList();
    List<String> warned = Lists.newArrayList();
    List<String> defaulted = Lists.newArrayList();

    for (MissingMapping remap : missedMappings) {
      FMLMissingMappingsEvent.Action action = remap.getAction();

      if (action == FMLMissingMappingsEvent.Action.REMAP) {
        // block/item re-mapped, finish the registration with the new name/object, but the old id
        int currId, newId;
        String newName;

        if (remap.type == Type.BLOCK) {
          currId = getMain().iBlockRegistry.getId((Block) remap.getTarget());
          newName = getMain().iBlockRegistry.getNameForObject(remap.getTarget()).toString();
          FMLLog.fine("The Block %s is being remapped to %s.", remap.name, newName);

          newId = gameData.registerBlock((Block) remap.getTarget(), newName, remap.id);
          gameData.iBlockRegistry.addAlias(remap.name, newName);
        } else {
          currId = getMain().iItemRegistry.getId((Item) remap.getTarget());
          newName = getMain().iItemRegistry.getNameForObject(remap.getTarget()).toString();
          FMLLog.fine("The Item %s is being remapped to %s.", remap.name, newName);

          newId = gameData.registerItem((Item) remap.getTarget(), newName, remap.id);
          gameData.iItemRegistry.addAlias(remap.name, newName);
        }

        if (newId != remap.id) throw new IllegalStateException();

        if (currId != newId) {
          FMLLog.info(
              "Fixed %s id mismatch %s: %d (init) -> %d (map).",
              remap.type == Type.BLOCK ? "block" : "item", newName, currId, newId);
          (remap.type == Type.BLOCK ? remapBlocks : remapItems)
              .put(newName, new Integer[] {currId, newId});
        }
      } else if (action == FMLMissingMappingsEvent.Action.BLOCKONLY) {
        // Pulled out specifically so the block doesn't get reassigned a new ID just because it's
        // Item block has gone away
        FMLLog.fine(
            "The ItemBlock %s is no longer present in the game. The residual block will remain",
            remap.name);
      } else {
        // block item missing, warn as requested and block the id
        if (action == FMLMissingMappingsEvent.Action.DEFAULT) {
          defaulted.add(remap.name);
        } else if (action == FMLMissingMappingsEvent.Action.IGNORE) {
          ignored.add(remap.name);
        } else if (action == FMLMissingMappingsEvent.Action.FAIL) {
          failed.add(remap.name);
        } else if (action == FMLMissingMappingsEvent.Action.WARN) {
          warned.add(remap.name);
        }

        gameData.block(remap.id); // prevent the id from being reused later
      }
    }

    if (!defaulted.isEmpty()) {
      String text =
          "Forge Mod Loader detected missing blocks/items.\n\n"
              + "There are "
              + defaulted.size()
              + " missing blocks and items in this save.\n"
              + "If you continue the missing blocks/items will get removed.\n"
              + "A world backup will be automatically created in your saves directory.\n\n"
              + "Missing Blocks/Items:\n";

      for (String s : defaulted) text += s + "\n";

      boolean confirmed = StartupQuery.confirm(text);
      if (!confirmed) StartupQuery.abort();

      try {
        String skip = System.getProperty("fml.doNotBackup");
        if (skip == null || !"true".equals(skip)) {
          ZipperUtil.backupWorld();
        } else {
          for (int x = 0; x < 10; x++)
            FMLLog.severe("!!!!!!!!!! UPDATING WORLD WITHOUT DOING BACKUP !!!!!!!!!!!!!!!!");
        }
      } catch (IOException e) {
        StartupQuery.notify("The world backup couldn't be created.\n\n" + e);
        StartupQuery.abort();
      }

      warned.addAll(defaulted);
    }
    if (!failed.isEmpty()) {
      FMLLog.severe(
          "This world contains blocks and items that refuse to be remapped. The world will not be loaded");
      return failed;
    }
    if (!warned.isEmpty()) {
      FMLLog.severe("This world contains block and item mappings that may cause world breakage");
      return failed;
    } else if (!ignored.isEmpty()) {
      FMLLog.fine("There were %d missing mappings that have been ignored", ignored.size());
    }
    return failed;
  }
예제 #2
0
  /**
   * Fire a FMLMissingMappingsEvent to let mods determine how blocks/items defined in the world
   * save, but missing from the runtime, are to be handled.
   *
   * @param missing Map containing missing names with their associated id, blocks need to come
   *     before items for remapping.
   * @param isLocalWorld Whether this is executing for a world load (local/server) or a client.
   * @param gameData GameData instance where the new map's config is to be loaded into.
   * @return List with the mapping results.
   */
  public List<String> fireMissingMappingEvent(
      LinkedHashMap<String, Integer> missingBlocks,
      LinkedHashMap<String, Integer> missingItems,
      boolean isLocalWorld,
      GameData gameData,
      Map<String, Integer[]> remapBlocks,
      Map<String, Integer[]> remapItems) {
    if (missingBlocks.isEmpty() && missingItems.isEmpty()) // nothing to do
    {
      return ImmutableList.of();
    }

    FMLLog.fine(
        "There are %d mappings missing - attempting a mod remap",
        missingBlocks.size() + missingItems.size());
    ArrayListMultimap<String, MissingMapping> missingMappings = ArrayListMultimap.create();

    for (Map.Entry<String, Integer> mapping : missingBlocks.entrySet()) {
      MissingMapping m =
          new MissingMapping(GameRegistry.Type.BLOCK, mapping.getKey(), mapping.getValue());
      missingMappings.put(m.name.substring(0, m.name.indexOf(':')), m);
    }
    for (Map.Entry<String, Integer> mapping : missingItems.entrySet()) {
      MissingMapping m =
          new MissingMapping(GameRegistry.Type.ITEM, mapping.getKey(), mapping.getValue());
      missingMappings.put(m.name.substring(0, m.name.indexOf(':')), m);
    }

    FMLMissingMappingsEvent missingEvent = new FMLMissingMappingsEvent(missingMappings);
    modController.propogateStateMessage(missingEvent);

    if (isLocalWorld) // local world, warn about entries still being set to the default action
    {
      boolean didWarn = false;

      for (MissingMapping mapping : missingMappings.values()) {
        if (mapping.getAction() == FMLMissingMappingsEvent.Action.DEFAULT) {
          if (!didWarn) {
            FMLLog.severe(
                "There are unidentified mappings in this world - we are going to attempt to process anyway");
            didWarn = true;
          }

          FMLLog.severe(
              "Unidentified %s: %s, id %d",
              mapping.type == Type.BLOCK ? "block" : "item", mapping.name, mapping.id);
        }
      }
    } else // remote world, fail on entries with the default action
    {
      List<String> missedMapping = new ArrayList<String>();

      for (MissingMapping mapping : missingMappings.values()) {
        if (mapping.getAction() == FMLMissingMappingsEvent.Action.DEFAULT) {
          missedMapping.add(mapping.name);
        }
      }

      if (!missedMapping.isEmpty()) {
        return ImmutableList.copyOf(missedMapping);
      }
    }

    return GameData.processIdRematches(
        missingMappings.values(), isLocalWorld, gameData, remapBlocks, remapItems);
  }