Пример #1
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;
  }