Пример #1
0
 /**
  * Internal method.
  *
  * <p>Used to quickly load {@link LuaObjectMeta} instances by passing the instance.
  */
 static void loadMeta(LuaObjectMeta metaInstance) {
   if (metaInstance.isPrimaryType()) {
     Lua.PMETA.put(metaInstance.getTargetObjectClass(), metaInstance);
   } else {
     Lua.META.put(metaInstance.getTargetObjectClass(), metaInstance);
   }
 }
Пример #2
0
  /**
   * Returns the {@link LuaObjectMeta} associated with the provided object.
   *
   * <p>If the provided object is an instance of {@link LuaImplementable} and has a primary
   * identifying class, the meta associated with that class is scanned for first.
   *
   * @param obj the Object to query with
   * @return the LuaObjectMeta associated with the provided object, or null if one was not found
   */
  public static LuaObjectMeta getMeta(Object obj) {
    if (obj == null) {
      return null;
    }

    Class<?> target = null;

    if (obj instanceof LuaImplementable
        && ((LuaImplementable<?>) obj).getPrimaryIdentifyingClass() != null) {
      target = ((LuaImplementable<?>) obj).getPrimaryIdentifyingClass();
    } else {
      target = obj.getClass();
    }

    do {
      if (Lua.PMETA.containsKey(target)) {
        return Lua.PMETA.get(target);
      }

      if (Lua.META.containsKey(target)) {
        return Lua.META.get(target);
      }

      for (LuaObjectMeta meta : Lua.PMETA.values()) {
        if (meta.getTargetObjectClass().isInstance(obj)) {
          return meta;
        }
      }

      for (LuaObjectMeta meta : Lua.META.values()) {
        if (meta.getTargetObjectClass().isInstance(obj)) {
          return meta;
        }
      }

      if (target != obj.getClass()) {
        target = obj.getClass();
      } else {
        target = null;
      }
    } while (target != null);

    return null;
  }
Пример #3
0
  /**
   * Generates a metatable containing metafunctions for a given object type using the currently
   * registered {@link LuaObjectMeta}s.
   *
   * <p>This method will only generate one metatable per class type; the mapping of already made
   * metatables will not be cleared at any point during runtime. If a metatable had already been
   * generated, that metatable is returned.
   *
   * <p>It is possible for functions within each object meta to override each other when this method
   * generates a new metatable.
   *
   * <p>If there are no suitable meta objects for the provided object or none of the applicable meta
   * objects have any metafunctions to register, null is returned.
   *
   * @param obj the Object to generate a metatable for
   * @return the metatable for the given Object
   */
  public static LuaTable generateMetatable(Object obj) {
    LuaTable copyTable = Lua.METATABLES.get(obj.getClass());
    if (copyTable == null && copyTable != Lua.EMPTY_METATABLE) {
      LuaTable functable = new LuaTable();
      Lua.metas.clear();
      Lua.META.values().forEach(Lua.metas::add);
      Lua.PMETA.values().forEach(Lua.metas::add);

      Lua.metas.forEach(
          meta -> {
            if (meta.getTargetObjectClass().isInstance(obj) && meta.getMetatable() != null) {
              LuaUtil.iterateTable(
                  meta.getMetatable(),
                  vargs -> {
                    functable.set(vargs.arg(1), vargs.arg(2));
                  });
            }
          });

      Lua.metas.forEach(
          meta -> {
            meta.postMetaInit(functable);
          });

      if (LuaUtil.getTableSize(functable) > 0) {
        LuaTable metatable = new LuaTable();

        // add the object's metatable functions
        metatable.set("__index", functable);

        // add the stuff we do for every metatable
        GLOBAL_METATABLE
            .entries()
            .forEach(
                entry -> {
                  metatable.set(entry.key, entry.value);
                });

        Lua.METATABLES.put(obj.getClass(), metatable);
        copyTable = metatable;
      } else {
        Lua.METATABLES.put(obj.getClass(), Lua.EMPTY_METATABLE);
      }
    }

    if (copyTable != null && copyTable != Lua.EMPTY_METATABLE) {
      return LuaUtil.copyTable(copyTable, true);
    }

    return null;
  }
Пример #4
0
  /**
   * Internal method.
   *
   * <p>Returns a stored {@link LuaObjectMeta} instance.
   */
  static LuaObjectMeta getMeta(Class<? extends LuaObjectMeta> metaClass) {
    for (LuaObjectMeta meta : Lua.PMETA.values()) {
      if (meta.getClass() == metaClass) {
        return meta;
      }
    }

    for (LuaObjectMeta meta : Lua.META.values()) {
      if (meta.getClass() == metaClass) {
        return meta;
      }
    }

    return null;
  }
Пример #5
0
  /**
   * Returns the {@link LuaObjectMeta} registered with the provided typename.
   *
   * @param metaName the typename to match
   * @return the LuaObjectMeta matching the given typename, or null if doesn't exist
   */
  public static LuaObjectMeta getMeta(String metaName) {
    for (LuaObjectMeta meta : Lua.PMETA.values()) {
      if (meta.getTypeName().equals(metaName)) {
        return meta;
      }
    }

    for (LuaObjectMeta meta : Lua.META.values()) {
      if (meta.getTypeName().equals(metaName)) {
        return meta;
      }
    }

    return null;
  }
Пример #6
0
  /**
   * Injects all registered metatables into the provided table, with the owning meta's typename as
   * their keys.
   *
   * <p>Should only be used by {@link MetaLib}.
   */
  public static void injectMetatables(LuaTable table) {
    Lua.PMETA
        .values()
        .forEach(
            meta -> {
              if (meta.getMetatable() != null) {
                table.set(meta.getTypeName(), meta.getMetatable());
              }
            });

    Lua.META
        .values()
        .forEach(
            meta -> {
              if (meta.getMetatable() != null) {
                table.set(meta.getTypeName(), meta.getMetatable());
              }
            });
  }