@Override
 public void addHackable(
     Class<? extends Entity> entityClazz, Class<? extends IHackableEntity> iHackable) {
   if (entityClazz == null) throw new NullPointerException("Entity class is null!");
   if (iHackable == null) throw new NullPointerException("IHackableEntity is null!");
   if (Entity.class.isAssignableFrom(iHackable)) {
     Log.warning(
         "Entities that implement IHackableEntity shouldn't be registered as hackable! Registering entity: "
             + entityClazz.getCanonicalName());
   } else {
     try {
       IHackableEntity hackableEntity = iHackable.newInstance();
       if (hackableEntity.getId() != null)
         stringToEntityHackables.put(hackableEntity.getId(), iHackable);
       hackableEntities.put(entityClazz, iHackable);
     } catch (InstantiationException e) {
       Log.error(
           "Not able to register hackable entity: "
               + iHackable.getName()
               + ". Does the class have a parameterless constructor?");
       e.printStackTrace();
     } catch (IllegalAccessException e) {
       Log.error(
           "Not able to register hackable entity: "
               + iHackable.getName()
               + ". Is the class a public class?");
       e.printStackTrace();
     }
   }
 }
  @Override
  public void addHackable(Block block, Class<? extends IHackableBlock> iHackable) {
    if (block == null) throw new NullPointerException("Block is null!");
    if (iHackable == null) throw new NullPointerException("IHackableBlock is null!");

    if (Block.class.isAssignableFrom(iHackable)) {
      Log.warning(
          "Blocks that implement IHackableBlock shouldn't be registered as hackable! Registering block: "
              + block.getLocalizedName());
    } else {
      try {
        IHackableBlock hackableBlock = iHackable.newInstance();
        if (hackableBlock.getId() != null)
          stringToBlockHackables.put(hackableBlock.getId(), iHackable);
        hackableBlocks.put(block, iHackable);
      } catch (InstantiationException e) {
        Log.error(
            "Not able to register hackable block: "
                + iHackable.getName()
                + ". Does the class have a parameterless constructor?");
        e.printStackTrace();
      } catch (IllegalAccessException e) {
        Log.error(
            "Not able to register hackable block: "
                + iHackable.getName()
                + ". Is the class a public class?");
        e.printStackTrace();
      }
    }
  }
 @Override
 public IProgWidget getOutputWidget(IDroneBase drone, List<IProgWidget> allWidgets) {
   if (evaluator != null) {
     return ProgWidgetJump.jumpToLabel(allWidgets, this, evaluate(drone, this));
   } else {
     Log.error("Shouldn't be happening! ProgWidgetCondition");
     return super.getOutputWidget(drone, allWidgets);
   }
 }
 public boolean isAcknowledged() {
   if (acknowledged == null)
     acknowledged =
         ReflectionHelper.findField(
             ItemInWorldManager.class, "field_73097_j", "receivedFinishDiggingPacket");
   try {
     return acknowledged.getBoolean(this);
   } catch (Exception e) {
     Log.error("Drone FakePlayerItemInWorldManager failed with reflection (Acknowledge get)!");
     e.printStackTrace();
     return true;
   }
 }
 public boolean isDigging() {
   if (isDigging == null)
     isDigging =
         ReflectionHelper.findField(
             ItemInWorldManager.class, "field_73088_d", "isDestroyingBlock");
   try {
     return isDigging.getBoolean(this);
   } catch (Exception e) {
     Log.error("Drone FakePlayerItemInWorldManager failed with reflection (Digging)!");
     e.printStackTrace();
     return true;
   }
 }
 @Override
 public List<IHackableEntity> getCurrentEntityHacks(Entity entity) {
   HackingEntityProperties hackingProps =
       (HackingEntityProperties) entity.getExtendedProperties("PneumaticCraftHacking");
   if (hackingProps != null) {
     List<IHackableEntity> hackables = hackingProps.getCurrentHacks();
     if (hackables != null) return hackables;
   } else {
     Log.warning(
         "Extended entity props HackingEntityProperties couldn't be found in the entity "
             + entity.getCommandSenderName());
   }
   return new ArrayList<IHackableEntity>();
 }
 public HeatBehaviour getBehaviourForId(String id) {
   HeatBehaviour behaviour = behaviours.get(id);
   if (behaviour != null) {
     try {
       return behaviour.getClass().newInstance();
     } catch (Exception e) {
       e.printStackTrace();
       return null;
     }
   } else {
     Log.warning("No heat behaviour found for id: " + id);
     return null;
   }
 }
 @Override
 public void registerFuel(Fluid fluid, int mLPerBucket) {
   if (fluid == null) throw new NullPointerException("Fluid can't be null!");
   if (mLPerBucket < 0) throw new IllegalArgumentException("mLPerBucket can't be < 0");
   if (liquidFuels.containsKey(fluid)) {
     Log.info(
         "Overriding liquid fuel entry "
             + fluid.getLocalizedName(new FluidStack(fluid, 1))
             + " ("
             + fluid.getName()
             + ") with a fuel value of "
             + mLPerBucket
             + " (previously "
             + liquidFuels.get(fluid)
             + ")");
     if (mLPerBucket == 0) liquidFuels.remove(fluid);
   }
   if (mLPerBucket > 0) liquidFuels.put(fluid, mLPerBucket);
 }
 public void registerBehaviour(Class<? extends HeatBehaviour> behaviour) {
   if (behaviour == null) throw new IllegalArgumentException("Can't register a null behaviour!");
   try {
     HeatBehaviour ins = behaviour.newInstance();
     HeatBehaviour overridenBehaviour = behaviours.put(ins.getId(), ins);
     if (overridenBehaviour != null)
       Log.warning(
           "Registered a heat behaviour that has the same id as an already registered one. The old one will be discarded. Old behaviour class: "
               + overridenBehaviour.getClass()
               + ". New class: "
               + behaviour.getClass());
   } catch (InstantiationException e) {
     throw new IllegalArgumentException(
         "The behaviour class doesn't have a nullary constructor, or is abstract! Class: "
             + behaviour);
   } catch (IllegalAccessException e) {
     throw new IllegalArgumentException(
         "Doesn't have access to the class (is it private?) Class: " + behaviour);
   }
 }
  @Override
  public void readFromNBT(NBTTagCompound tag) {

    super.readFromNBT(tag);

    NBTTagList tagList = tag.getTagList("Items", 10);
    inventory = new ItemStack[INVENTORY_SIZE];
    for (int i = 0; i < tagList.tagCount(); ++i) {
      NBTTagCompound tagCompound = tagList.getCompoundTagAt(i);
      byte slot = tagCompound.getByte("Slot");
      if (slot >= 0 && slot < inventory.length) {
        inventory[slot] = ItemStack.loadItemStackFromNBT(tagCompound);
      }
    }

    tank.readFromNBT(tag.getCompoundTag("tank"));

    NBTTagList droneItemTag = tag.getTagList("droneItems", 10);
    droneItems = new ItemStack[getDroneSlots()];
    for (int i = 0; i < droneItemTag.tagCount(); ++i) {
      NBTTagCompound tagCompound = droneItemTag.getCompoundTagAt(i);
      byte slot = tagCompound.getByte("Slot");
      if (slot >= 0 && slot < droneItems.length) {
        droneItems[slot] = ItemStack.loadItemStackFromNBT(tagCompound);
      }
    }

    NBTTagList extendedList = tag.getTagList("extendedProperties", 10);
    for (int i = 0; i < extendedList.tagCount(); ++i) {
      NBTTagCompound propertyTag = extendedList.getCompoundTagAt(i);
      String key = propertyTag.getString("key");
      IExtendedEntityProperties property = properties.get(key);
      if (property != null) {
        property.loadNBTData(propertyTag);
      } else {
        Log.warning(
            "Extended entity property \"" + key + "\" doesn't exist in a Programmable Controller");
      }
    }
  }
 @Override
 public void setCarryingEntity(Entity entity) {
   Log.warning(
       "Drone AI setting carrying entity. However a Programmable Controller can't carry entities!");
   new Throwable().printStackTrace();
 }
 private static List<SyncedField> getSyncedFieldsForField(
     Field field, Object te, Class searchedAnnotation) {
   boolean isLazy = field.getAnnotation(LazySynced.class) != null;
   List<SyncedField> syncedFields = new ArrayList<SyncedField>();
   SyncedField syncedField = getSyncedFieldForField(field, te);
   if (syncedField != null) {
     syncedFields.add(syncedField.setLazy(isLazy));
     return syncedFields;
   } else {
     Object o;
     try {
       int filteredIndex =
           field.getAnnotation(FilteredSynced.class) != null
               ? field.getAnnotation(FilteredSynced.class).index()
               : -1;
       field.setAccessible(true);
       o = field.get(te);
       if (o instanceof int[]) {
         int[] array = (int[]) o;
         if (filteredIndex >= 0) {
           syncedFields.add(new SyncedInt(te, field).setArrayIndex(filteredIndex).setLazy(isLazy));
         } else {
           for (int i = 0; i < array.length; i++) {
             syncedFields.add(new SyncedInt(te, field).setArrayIndex(i).setLazy(isLazy));
           }
         }
         return syncedFields;
       }
       if (o instanceof float[]) {
         float[] array = (float[]) o;
         if (filteredIndex >= 0) {
           syncedFields.add(
               new SyncedFloat(te, field).setArrayIndex(filteredIndex).setLazy(isLazy));
         } else {
           for (int i = 0; i < array.length; i++) {
             syncedFields.add(new SyncedFloat(te, field).setArrayIndex(i).setLazy(isLazy));
           }
         }
         return syncedFields;
       }
       if (o instanceof double[]) {
         double[] array = (double[]) o;
         if (filteredIndex >= 0) {
           syncedFields.add(
               new SyncedDouble(te, field).setArrayIndex(filteredIndex).setLazy(isLazy));
         } else {
           for (int i = 0; i < array.length; i++) {
             syncedFields.add(new SyncedDouble(te, field).setArrayIndex(i).setLazy(isLazy));
           }
         }
         return syncedFields;
       }
       if (o instanceof boolean[]) {
         boolean[] array = (boolean[]) o;
         if (filteredIndex >= 0) {
           syncedFields.add(
               new SyncedBoolean(te, field).setArrayIndex(filteredIndex).setLazy(isLazy));
         } else {
           for (int i = 0; i < array.length; i++) {
             syncedFields.add(new SyncedBoolean(te, field).setArrayIndex(i).setLazy(isLazy));
           }
         }
         return syncedFields;
       }
       if (o instanceof String[]) {
         String[] array = (String[]) o;
         if (filteredIndex >= 0) {
           syncedFields.add(
               new SyncedString(te, field).setArrayIndex(filteredIndex).setLazy(isLazy));
         } else {
           for (int i = 0; i < array.length; i++) {
             syncedFields.add(new SyncedString(te, field).setArrayIndex(i).setLazy(isLazy));
           }
         }
         return syncedFields;
       }
       if (o.getClass().isArray() && o.getClass().getComponentType().isEnum()) {
         Object[] enumArray = (Object[]) o;
         if (filteredIndex >= 0) {
           syncedFields.add(
               new SyncedEnum(te, field).setArrayIndex(filteredIndex).setLazy(isLazy));
         } else {
           for (int i = 0; i < enumArray.length; i++) {
             syncedFields.add(new SyncedEnum(te, field).setArrayIndex(i).setLazy(isLazy));
           }
         }
         return syncedFields;
       }
       if (o instanceof ItemStack[]) {
         ItemStack[] array = (ItemStack[]) o;
         if (filteredIndex >= 0) {
           syncedFields.add(
               new SyncedItemStack(te, field).setArrayIndex(filteredIndex).setLazy(isLazy));
         } else {
           for (int i = 0; i < array.length; i++) {
             syncedFields.add(new SyncedItemStack(te, field).setArrayIndex(i).setLazy(isLazy));
           }
         }
         return syncedFields;
       }
       if (o instanceof FluidTank[]) {
         FluidTank[] array = (FluidTank[]) o;
         if (filteredIndex >= 0) {
           syncedFields.add(
               new SyncedFluidTank(te, field).setArrayIndex(filteredIndex).setLazy(isLazy));
         } else {
           for (int i = 0; i < array.length; i++) {
             syncedFields.add(new SyncedFluidTank(te, field).setArrayIndex(i).setLazy(isLazy));
           }
         }
         return syncedFields;
       }
       if (field.getType().isArray()) {
         Object[] array = (Object[]) o;
         for (Object obj : array) {
           syncedFields.addAll(getSyncedFields(obj, searchedAnnotation));
         }
       } else {
         syncedFields.addAll(getSyncedFields(o, searchedAnnotation));
       }
       if (syncedFields.size() > 0) return syncedFields;
     } catch (Exception e) {
       e.printStackTrace();
     }
     Log.warning("Field " + field + " didn't produce any syncable fields!");
     return syncedFields;
   }
 }