public WeightedRandomModel(ModelResourceLocation parent, Variants variants) {
      this.variants = variants.getVariants();
      ImmutableList.Builder<Pair<IModel, IModelState>> builder = ImmutableList.builder();
      for (Variant v : (List<Variant>) variants.getVariants()) {
        ResourceLocation loc = v.getModelLocation();
        locations.add(loc);

        IModel model = null;
        try {
          model = getModel(loc);
        } catch (Exception e) {
          /*
           * Vanilla eats this, which makes it only show variants that have models.
           * But that doesn't help debugging, so we maintain the missing model
           * so that resource pack makers have a hint that their states are broken.
           */
          FMLLog.warning(
              "Unable to load block model: \'"
                  + loc
                  + "\' for variant: \'"
                  + parent
                  + "\': "
                  + e.toString());
          model = getMissingModel();
        }

        if (v instanceof ISmartVariant) {
          model = ((ISmartVariant) v).process(model, ModelLoader.this);
          try {
            resolveDependencies(model);
          } catch (IOException e) {
            FMLLog.getLogger()
                .error("Exception resolving indirect dependencies for model" + loc, e);
          }
          textures.addAll(model.getTextures()); // Kick this, just in case.
        }

        models.add(model);
        builder.add(Pair.of(model, v.getState()));
      }

      if (models.size()
          == 0) // If all variants are missing, add one with the missing model and default rotation.
      {
        IModel missing = getMissingModel();
        models.add(missing);
        builder.add(Pair.<IModel, IModelState>of(missing, TRSRTransformation.identity()));
      }

      defaultState = new MultiModelState(builder.build());
    }
  public static void revertToFrozen() {
    if (frozen == null) {
      FMLLog.warning("Can't revert to frozen GameData state without freezing first.");
    } else {
      FMLLog.fine("Reverting to frozen data state.");

      getMain().set(frozen);
    }
    // the id mapping has reverted, fire remap events for those that care about id changes
    Loader.instance()
        .fireRemapEvent(ImmutableMap.<String, Integer[]>of(), ImmutableMap.<String, Integer[]>of());
    // the id mapping has reverted, ensure we sync up the object holders
    ObjectHolderRegistry.INSTANCE.applyObjectHolders();
  }
  /**
   * Registers a ore item into the dictionary. Raises the registerOre function in all registered
   * handlers.
   *
   * @param name The name of the ore
   * @param ore The ore's ItemStack
   */
  private static void registerOreImpl(String name, ItemStack ore) {
    if ("Unknown".equals(name)) return; // prevent bad IDs.
    if (ore == null || ore.getItem() == null) {
      FMLLog.bigWarning(
          "Invalid registration attempt for an Ore Dictionary item with name %s has occurred. The registration has been denied to prevent crashes. The mod responsible for the registration needs to correct this.",
          name);
      return; // prevent bad ItemStacks.
    }

    int oreID = getOreID(name);
    // HACK: use the registry name's ID. It is unique and it knows about substitutions. Fallback to
    // a -1 value (what Item.getIDForItem would have returned) in the case where the registry is not
    // aware of the item yet
    // IT should be noted that -1 will fail the gate further down, if an entry already exists with
    // value -1 for this name. This is what is broken and being warned about.
    // APPARENTLY it's quite common to do this. OreDictionary should be considered alongside Recipes
    // - you can't make them properly until you've registered with the game.
    ResourceLocation registryName = ore.getItem().delegate.name();
    int hash;
    if (registryName == null) {
      FMLLog.bigWarning(
          "A broken ore dictionary registration with name %s has occurred. It adds an item (type: %s) which is currently unknown to the game registry. This dictionary item can only support a single value when"
              + " registered with ores like this, and NO I am not going to turn this spam off. Just register your ore dictionary entries after the GameRegistry.\n"
              + "TO USERS: YES this is a BUG in the mod "
              + Loader.instance().activeModContainer().getName()
              + " report it to them!",
          name,
          ore.getItem().getClass());
      hash = -1;
    } else {
      hash = GameData.getItemRegistry().getId(registryName);
    }
    if (ore.getItemDamage() != WILDCARD_VALUE) {
      hash |= ((ore.getItemDamage() + 1) << 16); // +1 so 0 is significant
    }

    // Add things to the baked version, and prevent duplicates
    List<Integer> ids = stackToId.get(hash);
    if (ids != null && ids.contains(oreID)) return;
    if (ids == null) {
      ids = Lists.newArrayList();
      stackToId.put(hash, ids);
    }
    ids.add(oreID);

    // Add to the unbaked version
    ore = ore.copy();
    idToStack.get(oreID).add(ore);
    MinecraftForge.EVENT_BUS.post(new OreRegisterEvent(name, ore));
  }
Exemple #4
0
 @Override
 public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
   if (this.state != null) {
     FMLLog.getLogger()
         .log(
             Level.INFO,
             "Opening channel which already seems to have a state set. This is a vanilla connection. Handshake handler will stop now");
     return;
   }
   FMLLog.getLogger().log(Level.TRACE, "Handshake channel activating");
   this.state = ConnectionState.OPENING;
   // send ourselves as a user event, to kick the pipeline active
   this.handshakeChannel.pipeline().fireUserEventTriggered(this);
   this.manager.channel().config().setAutoRead(true);
 }
 public static void rebakeMap() {
   // System.out.println("Baking OreDictionary:");
   stackToId.clear();
   for (int id = 0; id < idToStack.size(); id++) {
     List<ItemStack> ores = idToStack.get(id);
     if (ores == null) continue;
     for (ItemStack ore : ores) {
       // HACK: use the registry name's ID. It is unique and it knows about substitutions
       ResourceLocation name = ore.getItem().delegate.name();
       int hash;
       if (name == null) {
         FMLLog.log(
             Level.DEBUG,
             "Defaulting unregistered ore dictionary entry for ore dictionary %s: type %s to -1",
             getOreName(id),
             ore.getItem().getClass());
         hash = -1;
       } else {
         hash = GameData.getItemRegistry().getId(name);
       }
       if (ore.getItemDamage() != WILDCARD_VALUE) {
         hash |= ((ore.getItemDamage() + 1) << 16); // +1 so meta 0 is significant
       }
       List<Integer> ids = stackToId.get(hash);
       if (ids == null) {
         ids = Lists.newArrayList();
         stackToId.put(hash, ids);
       }
       ids.add(id);
       // System.out.println(id + " " + getOreName(id) + " " + Integer.toHexString(hash) + " " +
       // ore);
     }
   }
 }
  /**
   * Gets all the integer ID for the ores that the specified item stack is registered to. If the
   * item stack is not linked to any ore, this will return an empty array and no new entry will be
   * created.
   *
   * @param stack The item stack of the ore.
   * @return An array of ids that this ore is registered as.
   */
  public static int[] getOreIDs(ItemStack stack) {
    if (stack == null || stack.getItem() == null)
      throw new IllegalArgumentException("Stack can not be null!");

    Set<Integer> set = new HashSet<Integer>();

    // HACK: use the registry name's ID. It is unique and it knows about substitutions. Fallback to
    // a -1 value (what Item.getIDForItem would have returned) in the case where the registry is not
    // aware of the item yet
    // IT should be noted that -1 will fail the gate further down, if an entry already exists with
    // value -1 for this name. This is what is broken and being warned about.
    // APPARENTLY it's quite common to do this. OreDictionary should be considered alongside Recipes
    // - you can't make them properly until you've registered with the game.
    ResourceLocation registryName = stack.getItem().delegate.name();
    int id;
    if (registryName == null) {
      FMLLog.log(
          Level.DEBUG,
          "Attempted to find the oreIDs for an unregistered object (%s). This won't work very well.",
          stack);
      return new int[0];
    } else {
      id = GameData.getItemRegistry().getId(registryName);
    }
    List<Integer> ids = stackToId.get(id);
    if (ids != null) set.addAll(ids);
    ids = stackToId.get(id | ((stack.getItemDamage() + 1) << 16));
    if (ids != null) set.addAll(ids);

    Integer[] tmp = set.toArray(new Integer[set.size()]);
    int[] ret = new int[tmp.length];
    for (int x = 0; x < tmp.length; x++) ret[x] = tmp[x];
    return ret;
  }
  private void testConsistency() {
    // test if there's an entry for every set bit in availabilityMap
    for (int i = availabilityMap.nextSetBit(0); i >= 0; i = availabilityMap.nextSetBit(i + 1)) {
      if (iBlockRegistry.getRaw(i) == null
          && iItemRegistry.getRaw(i) == null
          && !blockedIds.contains(i)) {
        throw new IllegalStateException(
            String.format("availabilityMap references empty entries for id %d.", i));
      }
    }

    for (int pass = 0; pass < 2; pass++) {
      boolean isBlock = pass == 0;
      String type = isBlock ? "block" : "item";
      FMLControlledNamespacedRegistry<?> registry = isBlock ? iBlockRegistry : iItemRegistry;
      registry.validateContent(
          (isBlock ? MAX_BLOCK_ID : MAX_ITEM_ID),
          type,
          availabilityMap,
          blockedIds,
          iBlockRegistry);
    }

    FMLLog.fine("Registry consistency check successful");
  }
Exemple #8
0
  @Override
  public IFlexibleBakedModel bake(
      IModelState state,
      VertexFormat format,
      Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter) {
    IFlexibleBakedModel bakedBase = null;

    if (base != null) bakedBase = base.bake(state, format, bakedTextureGetter);

    ImmutableMap.Builder<String, IFlexibleBakedModel> mapBuilder = ImmutableMap.builder();

    for (Entry<String, Pair<IModel, IModelState>> entry : parts.entrySet()) {
      Pair<IModel, IModelState> pair = entry.getValue();
      mapBuilder.put(
          entry.getKey(), pair.getLeft().bake(pair.getRight(), format, bakedTextureGetter));
    }

    if (bakedBase == null && parts.isEmpty()) {
      FMLLog.log(
          Level.ERROR,
          "MultiModel %s is empty (no base model or parts were provided/resolved)",
          location);
      IModel missing = ModelLoaderRegistry.getMissingModel();
      return missing.bake(missing.getDefaultState(), format, bakedTextureGetter);
    }
    return new Baked(location, true, bakedBase, mapBuilder.build());
  }
  public static void freezeData() {
    FMLLog.fine("Freezing block and item id maps");

    getMain().testConsistency();
    frozen = new GameData(getMain());
    frozen.testConsistency();
  }
Exemple #10
0
 @Override
 public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
   if (evt instanceof ConnectionType && side == Side.SERVER) {
     FMLLog.info("Timeout occurred, assuming a vanilla client");
     kickVanilla();
   }
 }
Exemple #11
0
 @Override
 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
   // Stop the epic channel closed spam at close
   if (!(cause instanceof ClosedChannelException)) {
     FMLLog.log(Level.ERROR, cause, "NetworkDispatcher exception");
   }
   super.exceptionCaught(ctx, cause);
 }
Exemple #12
0
 private boolean handleVanilla(Packet msg) {
   if (state == ConnectionState.AWAITING_HANDSHAKE && msg instanceof S01PacketJoinGame) {
     handshakeChannel.pipeline().fireUserEventTriggered(msg);
   } else {
     FMLLog.info(
         "Unexpected packet during modded negotiation - assuming vanilla or keepalives : %s",
         msg.getClass().getName());
   }
   return false;
 }
 public void onPostBakeEvent(IRegistry<ModelResourceLocation, IBakedModel> modelRegistry) {
   IBakedModel missingModel = modelRegistry.getObject(MODEL_MISSING);
   for (ModelResourceLocation missing : missingVariants) {
     IBakedModel model = modelRegistry.getObject(missing);
     if (model == null || model == missingModel) {
       FMLLog.severe("Model definition for location %s not found", missing);
     }
   }
   isLoading = false;
 }
Exemple #14
0
 public void completeHandshake(Side target) {
   if (state == ConnectionState.CONNECTED) {
     FMLLog.severe("Attempt to double complete the network connection!");
     throw new FMLNetworkException("Attempt to double complete!");
   }
   if (side == Side.CLIENT) {
     completeClientSideConnection(ConnectionType.MODDED);
   } else {
     this.state = ConnectionState.FINALIZING; // Delay and finalize in the world tick loop.
   }
 }
Exemple #15
0
 private void completeClientSideConnection(ConnectionType type) {
   this.connectionType = type;
   FMLLog.info(
       "[%s] Client side %s connection established",
       Thread.currentThread().getName(), this.connectionType.name().toLowerCase(Locale.ENGLISH));
   this.state = ConnectionState.CONNECTED;
   FMLCommonHandler.instance()
       .bus()
       .post(
           new FMLNetworkEvent.ClientConnectedToServerEvent(manager, this.connectionType.name()));
 }
  int registerBlock(Block block, String name) // from GameRegistry
      {
    int index = name.indexOf(':');
    if (name.indexOf(':') != -1)
      FMLLog.bigWarning(
          "Illegal extra prefix %s for name %s, invalid registry invocation/invalid name?",
          name.substring(0, index), name);

    name = addPrefix(name);
    return registerBlock(block, name, -1);
  }
Exemple #17
0
  public static TileEntity func_190200_a(World p_190200_0_, NBTTagCompound p_190200_1_) {
    TileEntity tileentity = null;
    String s = p_190200_1_.getString("id");
    Class<? extends TileEntity> oclass = null;

    try {
      oclass = nameToClassMap.get(s);

      if (oclass != null) {
        tileentity = (TileEntity) oclass.newInstance();
      }
    } catch (Throwable throwable1) {
      LOGGER.error("Failed to create block entity {}", new Object[] {s, throwable1});
      net.minecraftforge.fml.common.FMLLog.log(
          org.apache.logging.log4j.Level.ERROR,
          throwable1,
          "A TileEntity %s(%s) has thrown an exception during loading, its state cannot be restored. Report this to the mod author",
          s,
          oclass.getName());
    }

    if (tileentity != null) {
      try {
        tileentity.func_190201_b(p_190200_0_);
        tileentity.readFromNBT(p_190200_1_);
      } catch (Throwable throwable) {
        LOGGER.error("Failed to load data for block entity {}", new Object[] {s, throwable});
        net.minecraftforge.fml.common.FMLLog.log(
            org.apache.logging.log4j.Level.ERROR,
            throwable,
            "A TileEntity %s(%s) has thrown an exception during loading, its state cannot be restored. Report this to the mod author",
            s,
            oclass.getName());
        tileentity = null;
      }
    } else {
      LOGGER.warn("Skipping BlockEntity with id {}", new Object[] {s});
    }

    return tileentity;
  }
 /**
  * Retrieves the proxy for black/whitelist-based API queries.
  *
  * @return The proxy for black/whitelist-based API queries
  */
 public static IBlacklistProxy getBlacklistProxy() {
   if (blacklistProxy == null) {
     try {
       Class<?> clazz = Class.forName("moze_intel.projecte.impl.BlacklistProxyImpl");
       blacklistProxy = (IBlacklistProxy) clazz.getField("instance").get(null);
     } catch (ReflectiveOperationException ex) {
       FMLLog.warning(
           "[ProjectEAPI] Error retrieving BlacklistProxyImpl, ProjectE may be absent, damaged, or outdated.");
     }
   }
   return blacklistProxy;
 }
Exemple #19
0
  @Override
  public ModelFluid process(ImmutableMap<String, String> customData) {
    if (!customData.containsKey("fluid")) return this;

    String fluidStr = customData.get("fluid");
    JsonElement e = new JsonParser().parse(fluidStr);
    String fluid = e.getAsString();
    if (!FluidRegistry.isFluidRegistered(fluid)) {
      FMLLog.severe("fluid '%s' not found", fluid);
      return WATER;
    }
    return new ModelFluid(FluidRegistry.getFluid(fluid));
  }
Exemple #20
0
 public void serverToClientHandshake(EntityPlayerMP player) {
   this.player = player;
   insertIntoChannel();
   Boolean fml = this.manager.channel().attr(NetworkRegistry.FML_MARKER).get();
   if (fml != null && fml.booleanValue()) {
     // FML on client, send server hello
     // TODO: Make this cleaner as it uses netty magic 0.o
   } else {
     serverInitiateHandshake();
     FMLLog.info("Connection received without FML marker, assuming vanilla.");
     this.completeServerSideConnection(ConnectionType.VANILLA);
   }
 }
  private List<String> loadGenericRegistries(GameDataSnapshot snapshot, GameData existing) {
    List<String> result = Lists.newArrayList();
    for (Map.Entry<String, FMLControlledNamespacedRegistry<?>> e :
        existing.genericRegistries.entrySet()) {
      String regName = e.getKey();
      FMLControlledNamespacedRegistry<?> registry = e.getValue();
      FMLControlledNamespacedRegistry<?> newRegistry = genericRegistries.get(regName);
      if (newRegistry == null) {
        newRegistry = registry.makeShallowCopy();
        genericRegistries.put(regName, newRegistry);
      }

      GameDataSnapshot.Entry regSnap = snapshot.entries.get("fmlgr:" + regName);
      if (regSnap == null) {
        FMLLog.info(
            "Weird, there was no registry data for registry %s found in the snapshot", regName);
        continue;
      }

      for (Entry<String, Integer> entry : regSnap.ids.entrySet()) {
        String entryName = entry.getKey();
        int entryId = entry.getValue();
        int currId = registry.getId(entryName);

        if (currId == -1) {
          FMLLog.info("Found a missing id in registry %s from the world %s", regName, entryName);
          result.add(regName + "{" + entryName + "}=" + entryId);
          continue; // no block/item -> nothing to add
        } else if (currId != entryId) {
          FMLLog.fine(
              "Fixed registry %s id mismatch %s: %d (init) -> %d (map).",
              regName, entryName, currId, entryId);
        }

        newRegistry.add(entryId, entryName, registry.getRaw(entryName));
      }
    }
    return result;
  }
Exemple #22
0
 private synchronized void completeServerSideConnection(ConnectionType type) {
   this.connectionType = type;
   FMLLog.info(
       "[%s] Server side %s connection established",
       Thread.currentThread().getName(), this.connectionType.name().toLowerCase(Locale.ENGLISH));
   this.state = ConnectionState.CONNECTED;
   FMLCommonHandler.instance()
       .bus()
       .post(new FMLNetworkEvent.ServerConnectionFromClientEvent(manager));
   if (DEBUG_HANDSHAKE)
     manager.closeChannel(
         new ChatComponentText("Handshake Complete review log file for details."));
   scm.initializeConnectionToPlayer(manager, player, serverHandler);
 }
  private void verifyItemBlockName(ItemBlock item) {
    Object blockName = iBlockRegistry.getNameForObject(item.block);
    Object itemName = iItemRegistry.getNameForObject(item);

    // Vanilla has a mismatch:
    // Block <-> ItemBlock name mismatch, block name minecraft:standing_banner, item name
    // minecraft:banner
    // TODO: Untie these in the rest of the registry
    if (blockName != null
        && !blockName.equals(itemName)
        && !"minecraft:standing_banner".equals(blockName.toString())) {
      FMLLog.bigWarning(
          "Block <-> ItemBlock name mismatch, block name %s, item name %s", blockName, itemName);
    }
  }
Exemple #24
0
 private void resize(int x, int y, int z) {
   if (x <= 0 || x > MAX_X_SIZE || y <= 0 || y > MAX_Y_SIZE || z <= 0 || z > MAX_Z_SIZE) {
     FMLLog.severe("Out-of-range [x,y,z] in VoxelSelection constructor: [%d, %d, %d]", x, y, z);
     x = 1;
     y = 1;
     z = 1;
   }
   xSize = x;
   ySize = y;
   zSize = z;
   if (voxels == null) {
     voxels = new BitSet(xSize * ySize * zSize); // default to all false
   } else {
     voxels.clear();
   }
 }
 private FMLControlledNamespacedRegistry<?> findRegistry(Class<?> type) {
   BiMap<Class<?>, String> typeReg = registryTypes.inverse();
   String name = typeReg.get(type);
   if (name == null) {
     Set<Class<?>> parents = Sets.newHashSet();
     findSuperTypes(type, parents);
     SetView<Class<?>> foundType = Sets.intersection(parents, registryTypes.values());
     if (foundType.isEmpty()) {
       FMLLog.severe("Unable to find registry for type %s", type.getName());
       throw new IllegalArgumentException(
           "Attempt to register an object without an associated registry");
     }
     Class<?> regtype = Iterables.getOnlyElement(foundType);
     name = typeReg.get(regtype);
   }
   return genericRegistries.get(name);
 }
  private int registerBlock(Block block, String name, int idHint) {
    // handle ItemBlock-before-Block registrations
    ItemBlock itemBlock = null;

    for (Item item : iItemRegistry.typeSafeIterable()) // find matching ItemBlock
    {
      if (item instanceof ItemBlock && ((ItemBlock) item).block == block) {
        itemBlock = (ItemBlock) item;
        break;
      }
    }

    if (itemBlock
        != null) // has ItemBlock, adjust id and clear the slot already occupied by the
                 // corresponding item
    {
      idHint = iItemRegistry.getId(itemBlock);
      FMLLog.fine("Found matching ItemBlock %s for Block %s at id %d", itemBlock, block, idHint);
      freeSlot(
          idHint,
          block); // temporarily free the slot occupied by the Item for the block registration
    }

    // add
    int blockId = iBlockRegistry.add(idHint, name, block, availabilityMap);

    if (itemBlock != null) // verify
    {
      if (blockId != idHint)
        throw new IllegalStateException(
            String.format(
                "Block at itemblock id %d insertion failed, got id %d.", idHint, blockId));
      verifyItemBlockName(itemBlock);
    }

    useSlot(blockId);
    ((RegistryDelegate.Delegate<Block>) block.delegate).setName(name);

    for (IBlockState state : ((List<IBlockState>) block.getBlockState().getValidStates())) {
      GameData.BLOCKSTATE_TO_ID.put(state, blockId << 4 | block.getMetaFromState(state));
    }

    return blockId;
  }
  /**
   * Adds a Chapter (or overrides one that already exists)
   *
   * @param chapter Chapter to add
   */
  public void addChapter(Chapter chapter) {
    for (Chapter chap : chapters)
      if (chap.identifier.equals(chapter.identifier)) {
        chap = chapter;
        return;
      }

    if (chapters.length < 7) {
      Chapter[] newchap = new Chapter[chapters.length + 1];
      for (int i = 0; i < chapters.length; i++) newchap[i] = chapters[i];

      newchap[chapters.length] = chapter;

      chapters = newchap;
    } else
      FMLLog.log(
          "AbyssalCraftAPI",
          Level.ERROR,
          "NecroData instance is already full, can't add a new Chapter!");
  }
 @SuppressWarnings("unchecked")
 private <T> FMLControlledNamespacedRegistry<T> createGenericRegistry(
     String registryName, Class<T> type, int minId, int maxId) {
   Set<Class<?>> parents = Sets.newHashSet();
   findSuperTypes(type, parents);
   SetView<Class<?>> overlappedTypes = Sets.intersection(parents, registryTypes.values());
   if (!overlappedTypes.isEmpty()) {
     Class<?> foundType = overlappedTypes.iterator().next();
     FMLLog.severe(
         "Found existing registry of type %1s named %2s, you cannot create a new registry (%3s) with type %4s, as %4s has a parent of that type",
         foundType, registryTypes.inverse().get(foundType), registryName, type);
     throw new IllegalArgumentException(
         "Duplicate registry parent type found - you can only have one registry for a particular super type");
   }
   FMLControlledNamespacedRegistry<?> fmlControlledNamespacedRegistry =
       new FMLControlledNamespacedRegistry<T>(null, maxId, minId, type);
   genericRegistries.put(registryName, fmlControlledNamespacedRegistry);
   registryTypes.put(registryName, type);
   return (FMLControlledNamespacedRegistry<T>) fmlControlledNamespacedRegistry;
 }
  /** ■視線先のEntityを捕捉する EntityRender.getMouseOver()をぱくぱく */
  @Override
  public List<MovingObjectPosition> getEntity(ItemStack itemStackIn, EntityPlayer playerIn) {
    List<MovingObjectPosition> targets =
        new ArrayList<MovingObjectPosition>(); // new ArrayList<MovingObjectPosition>();

    if (playerIn != null && playerIn.worldObj != null) {
      MovingObjectPosition blockMOP = null;

      // ■りふれくしょん!
      Timer timer;
      try {
        timer =
            ObfuscationReflectionHelper.getPrivateValue(
                Minecraft.class, Minecraft.getMinecraft(), 19);
      } catch (UnableToAccessFieldException e) {
        FMLLog.log(Level.ERROR, e, "りふれくしょん! に失敗しました!><  ClientProxy.getEntity()");
        throw e;
      }

      // ■レンジ(チンッ!)
      double range = 20d;
      // ■直近のブロックとの距離
      double nearBlockRange = 0;

      // ■れいとれーす!
      //  (プレイヤーの視線の先で最寄のブロックまでの距離を返す。
      //   ブロックが無かったら指定したレンジぐらいのアタイ!を返す)
      //  TODO 奈落とか天上だとどうなるか要検証
      blockMOP = playerIn.rayTrace(range, timer.renderPartialTicks);

      // ■プレイヤーの視点位置
      //  (renderPartialTicks:0.0 - 1.0) 一回前の描画位置からどれだけ動いたかの比率(?)として使ってる(?)
      Vec3 playerEyePos = playerIn.getPositionEyes(timer.renderPartialTicks);

      // ■入手したモップがある
      if (blockMOP != null) {
        // ■「プレイヤーの視点」と「最寄ブロック」との距離を取得
        nearBlockRange = blockMOP.hitVec.distanceTo(playerEyePos);
      }

      // ■プレイヤーの視線(単位ベクトル)(ベクトルに乗算するメソッドが無い事に驚愕)
      Vec3 playerSight = playerIn.getLook(timer.renderPartialTicks);
      // ■プレイヤーの視線(レンジ)
      Vec3 playerRange =
          playerEyePos.addVector(
              playerSight.xCoord * range, playerSight.yCoord * range, playerSight.zCoord * range);

      // ■プレイヤーの視線(立方体)に入っているEntityをかき集める
      float f1 = 1.0f; // 立方体拡張(上下に1.0F)
      AxisAlignedBB aabb1 =
          playerIn
              .getEntityBoundingBox()
              .addCoord(
                  playerSight.xCoord * range,
                  playerSight.yCoord * range,
                  playerSight.zCoord * range)
              .expand(f1, f1, f1);
      List<Entity> list = playerIn.worldObj.getEntitiesWithinAABBExcludingEntity(playerIn, aabb1);

      // TODO ごり押し君(SOWはEntityWeatherの為)
      list.addAll(playerIn.worldObj.weatherEffects);

      // ■Entity! 君に決めた! 枠
      Entity mob = null;
      Vec3 mobDist = null;
      double mobRange = nearBlockRange;
      Entity sow = null;
      Vec3 sowDist = null;
      double sowRange = nearBlockRange;

      // ■かき集めたEntity共をチェックしていく(candidate:候補者)
      for (Entity candidate : list) {
        // ■「判定なし」かつ「SOWでは無い」を満たすEntityはスルー
        // if (!candidate.canBeCollidedWith() && !(candidate instanceof EntitySOW)) { continue; }

        // ■ドラゴン(概念)は対象外
        if (candidate instanceof EntityDragon) {
          continue;
        }

        // ■「not 生物」かつ「not ドラゴンパーツ」かつ「not SOW」を満たすEntityはスルー
        if (!(candidate instanceof EntityLivingBase)
            && !(candidate instanceof EntityDragonPart)
            && !(candidate instanceof EntitySOW)) {
          continue;
        }

        // ■ターゲットの当たり判定を拡張
        float fExpand = candidate.getCollisionBorderSize() * 3f;
        AxisAlignedBB aabb2 = candidate.getEntityBoundingBox().expand(fExpand, fExpand, fExpand);

        // ■拡張したターゲットの当たり判定と視線(レンジ)が交差するなら、モップが帰る
        MovingObjectPosition targetMOP = aabb2.calculateIntercept(playerEyePos, playerRange);

        // ■ターゲットの中、あったかいナリ(当たり判定が重なってる)
        if (aabb2.isVecInside(playerEyePos)) {
          // ■Entityの種類によって格納するインスタンスを分ける
          if (candidate instanceof EntitySOW) {
            // ■距離が近いので更新
            if (0.0D < sowRange || sowRange == 0.0D) {
              sow = candidate;
              sowDist = targetMOP == null ? playerEyePos : targetMOP.hitVec;
              sowRange = 0.0D;
            }
          } else {
            // ■距離が近いので更新
            if (0.0D < mobRange || mobRange == 0.0D) {
              mob = candidate;
              mobDist = targetMOP == null ? playerEyePos : targetMOP.hitVec;
              mobRange = 0.0D;
            }
          }
        }
        // ■帰ってきたモップ
        else if (targetMOP != null) {
          double range2 = playerEyePos.distanceTo(targetMOP.hitVec);

          // ■前に調べた奴より距離が近い
          if (candidate instanceof EntitySOW) {
            if (range2 < sowRange || sowRange == 0.0D) {
              sow = candidate;
              sowDist = targetMOP.hitVec;
              sowRange = range2;
            }
          } else {
            if (range2 < mobRange || mobRange == 0.0D) {
              // ■現在乗ってるEntity かつ 対象Entityに乗った状態で右クリックが有効か否か(このメソッド、使えそう)
              if (candidate == playerIn.ridingEntity && !candidate.canRiderInteract()) {
                // TODO このシーケンスには入れるの?
                if (mobRange == 0.0D) {
                  mob = candidate;
                  mobDist = targetMOP.hitVec;
                }
              } else {
                mob = candidate;
                mobDist = targetMOP.hitVec;
                mobRange = range2;
              }
            }
          }
        }
      }

      // ■調べ終えました。
      //  「ターゲット」が居る かつ
      //   (「ターゲットの間にブロックが無い」 または
      //    「モップがヌルポ(TODO どうやったらこの条件になるか要検証)」)
      if (mob != null && (mobRange < nearBlockRange || blockMOP == null)) {
        // mop = new MovingObjectPosition(mob, mobDist);
        targets.add(new MovingObjectPosition(mob, mobDist));
        // TODO
        // System.out.println("targets.add(mob) = " + mob.getName());
      }

      if (sow != null && (sowRange < nearBlockRange || blockMOP == null)) {
        targets.add(new MovingObjectPosition(sow, sowDist));
        // TODO
        // System.out.println("targets.add(sow) = " + sow.getName());
      }
    }

    return targets;
  }
  private int registerItem(Item item, String name, int idHint) {
    if (item instanceof ItemBlock
        && !(item
            instanceof
            ItemBanner)) // ItemBlock, adjust id and clear the slot already occupied by the
                         // corresponding block
    {
      Block block = ((ItemBlock) item).block;
      if (idHint != -1 && getMain().blockSubstitutions.containsKey(name)) {
        block = getMain().blockSubstitutions.get(name);
      }
      int id = iBlockRegistry.getId(block);

      if (id == -1) // ItemBlock before its Block
      {
        if (idHint < 0
            || availabilityMap.get(idHint)
            || idHint
                > MAX_BLOCK_ID) // non-suitable id, allocate one in the block id range, add would
                                // use the item id range otherwise
        {
          id =
              availabilityMap.nextClearBit(
                  MIN_BLOCK_ID); // find suitable id here, iItemRegistry would search from
                                 // MIN_ITEM_ID
          if (id > MAX_BLOCK_ID)
            throw new RuntimeException(
                String.format("Invalid id %d - maximum id range exceeded.", id));
          FMLLog.fine(
              "Allocated id %d for ItemBlock %s in the block id range, original id requested: %d.",
              id, name, idHint);
        } else // idHint is suitable without changes
        {
          id = idHint;
        }
      } else // ItemBlock after its Block
      {
        if (FMLControlledNamespacedRegistry.DEBUG)
          FMLLog.fine(
              "Found matching Block %s for ItemBlock %s at id %d, original id requested: %d",
              block, item, id, idHint);
        freeSlot(
            id, item); // temporarily free the slot occupied by the Block for the item registration
      }

      idHint = id;
    }

    int itemId = iItemRegistry.add(idHint, name, item, availabilityMap);

    if (item instanceof ItemBlock) // verify
    {
      if (itemId != idHint)
        throw new IllegalStateException(
            String.format("ItemBlock at block id %d insertion failed, got id %d.", idHint, itemId));
      verifyItemBlockName((ItemBlock) item);
    }

    // block the Block Registry slot with the same id
    useSlot(itemId);
    ((RegistryDelegate.Delegate<Item>) item.delegate).setName(name);
    return itemId;
  }