Beispiel #1
0
 @Override
 public ParseTree optimizeDynamic(Target t, List<ParseTree> children, FileOptions fileOptions)
     throws ConfigCompileException, ConfigRuntimeException {
   // We can check 2 things here, one, that the statement isn't dynamic, and if not, then
   // 2, that the parameter count matches the ? count. No checks can be done for typing,
   // without making a connection to the db though, so we won't do that here.
   Construct queryData = children.get(1).getData();
   if (queryData instanceof CFunction) {
     // If it's a concat or sconcat, warn them that this is bad
     if ("sconcat".equals(queryData.val()) || "concat".equals(queryData.val())) {
       CHLog.GetLogger()
           .w(
               CHLog.Tags.COMPILER,
               "Use of concatenated query detected! This"
                   + " is very bad practice, and could lead to SQL injection vulnerabilities"
                   + " in your code. It is highly recommended that you use prepared queries,"
                   + " which ensure that your parameters are properly escaped.",
               t);
     }
   } else if (queryData instanceof CString) {
     // It's a hard coded query, so we can double check parameter lengths
     int count = 0;
     for (char c : queryData.val().toCharArray()) {
       if (c == '?') {
         count++;
       }
     }
     // -2 accounts for the profile data and query
     if (children.size() - 2 != count) {
       throw new ConfigCompileException(
           StringUtils.PluralTemplateHelper(
                   count, "%d parameter token was", "%d parameter tokens were")
               + " found in the query, but "
               + StringUtils.PluralTemplateHelper(
                   children.size() - 2, "%d parameter was", "%d parameters were")
               + " provided to query().",
           t);
     }
   }
   return null;
 }
Beispiel #2
0
    public Map<String, Construct> evaluate(BindableEvent e) throws EventException {
      Map<String, Construct> retn = new HashMap<String, Construct>();

      if (e instanceof Numeric) {
        Numeric msg = (Numeric) e;

        retn.put("id", new CString(msg.getBot().getID(), Target.UNKNOWN));
        retn.put("numeric", new CString(msg.getNumeric().getName(), Target.UNKNOWN));
        retn.put("numericid", new CInt(msg.getNumeric().getCode(), Target.UNKNOWN));
        retn.put("args", Construct.GetConstruct(msg.getArgs()));
        retn.put("message", new CString(msg.getMessage(), Target.UNKNOWN));
      }

      return retn;
    }
Beispiel #3
0
  public void run(final List<Variable> vars, Environment myEnv, final MethodScriptComplete done) {
    // Some things, such as the label are determined at compile time
    this.CurrentEnv = myEnv;
    this.CurrentEnv.getEnv(GlobalEnv.class).SetLabel(this.label);
    MCCommandSender p = myEnv.getEnv(CommandHelperEnvironment.class).GetCommandSender();
    if (!hasBeenCompiled || compilerError) {
      Target target = Target.UNKNOWN;
      if (left.size() >= 1) {
        try {
          target = new Target(left.get(0).line_num, left.get(0).file, left.get(0).column);
        } catch (NullPointerException e) {
          // Oh well, we tried to get more information
        }
      }
      throw new ConfigRuntimeException(
          "Unable to run command, script not yet compiled, or a compiler error occured for that command."
              + " To see the compile error, run /reloadaliases",
          null,
          target);
    }
    if (p instanceof MCPlayer) {
      if (CurrentEnv.getEnv(GlobalEnv.class).GetLabel() != null) {
        PermissionsResolver perms = CurrentEnv.getEnv(GlobalEnv.class).GetPermissionsResolver();
        String[] groups = CurrentEnv.getEnv(GlobalEnv.class).GetLabel().split("/");
        for (String group : groups) {
          if (group.startsWith("-")
              && perms.inGroup(((MCPlayer) p).getName(), group.substring(1))) {
            // negative permission
            throw new ConfigRuntimeException(
                "You do not have permission to use that command",
                ExceptionType.InsufficientPermissionException,
                Target.UNKNOWN);
          } else if (perms.inGroup(((MCPlayer) p).getName(), group)) {
            // They do have permission.
            break;
          }
        }
      }
    }

    try {
      for (ParseTree rootNode : cright) {
        for (Construct tempNode : rootNode.getAllData()) {
          if (tempNode instanceof Variable) {
            if (left_vars == null) {
              throw new ConfigRuntimeException(
                  "$variables may not be used in this context. Only @variables may be.",
                  null,
                  tempNode.getTarget());
            }
            ((Variable) tempNode)
                .setVal(
                    new CString(
                        Static.resolveDollarVar(
                                left_vars.get(((Variable) tempNode).getName()), vars)
                            .toString(),
                        tempNode.getTarget()));
          }
        }

        MethodScriptCompiler.registerAutoIncludes(CurrentEnv, this);
        MethodScriptCompiler.execute(rootNode, CurrentEnv, done, this);
      }
    } catch (ConfigRuntimeException ex) {
      // We don't know how to handle this really, so let's pass it up the chain.
      throw ex;
    } catch (CancelCommandException e) {
      // p.sendMessage(e.getMessage());
      // The message in the exception is actually empty
    } catch (LoopBreakException e) {
      if (p != null) {
        p.sendMessage("The break() function must be used inside a for() or foreach() loop");
      }
      System.out.println("The break() function must be used inside a for() or foreach() loop");
    } catch (LoopContinueException e) {
      if (p != null) {
        p.sendMessage("The continue() function must be used inside a for() or foreach() loop");
      }
      System.out.println("The continue() function must be used inside a for() or foreach() loop");
    } catch (FunctionReturnException e) {
      if (myEnv.getEnv(CommandHelperEnvironment.class).GetEvent() != null) {
        // Oh, we're running in an event handler. Those know how to catch it too.
        throw e;
      }
      if (p != null) {
        p.sendMessage("The return() function must be used inside a procedure.");
      }
      System.out.println("The return() function must be used inside a procedure.");
    } catch (Throwable t) {
      System.out.println("An unexpected exception occured during the execution of a script.");
      t.printStackTrace();
      if (p != null) {
        p.sendMessage(
            "An unexpected exception occured during the execution of your script. Please check the console for more information.");
      }
    }
    if (done != null) {
      done.done(null);
    }
  }
Beispiel #4
0
  public void checkAmbiguous(List<Script> scripts) throws ConfigCompileException {
    // for (int i = 0; i < scripts.size(); i++) {
    List<Construct> thisCommand = this.cleft;
    for (int j = 0; j < scripts.size(); j++) {
      List<Construct> thatCommand = scripts.get(j).cleft;
      if (thatCommand == null) {
        // it hasn't been compiled yet.
        return;
      }
      if (this.cleft == scripts.get(j).cleft) {
        // Of course this command is going to match it's own signature
        continue;
      }
      boolean soFarAMatch = true;
      for (int k = 0; k < thisCommand.size(); k++) {
        try {
          Construct c1 = thisCommand.get(k);
          Construct c2 = thatCommand.get(k);
          if (c1.getCType() != c2.getCType()
              || ((c1 instanceof Variable) && !((Variable) c1).isOptional())) {
            soFarAMatch = false;
          } else {
            // It's a literal, check to see if it's the same literal
            if (c1.nval() == null || !c1.val().equals(c2.val())) {
              soFarAMatch = false;
            }
          }
        } catch (IndexOutOfBoundsException e) {
          /**
           * The two commands: /cmd $var1 [$var2] /cmd $var1 would cause this exception to be
           * thrown, but the signatures are the same, so the fact that they've matched this far
           * means they are ambiguous. However, /cmd $var1 $var2 /cmd $var1 is not ambiguous
           */
          // thatCommand is the short one
          if (!(thisCommand.get(k) instanceof Variable)
              || (thisCommand.get(k) instanceof Variable
                  && !((Variable) thisCommand.get(k)).isOptional())) {
            soFarAMatch = false;
          }
        }
      }
      if (thatCommand.size() > thisCommand.size()) {
        int k = thisCommand.size();
        // thisCommand is the short one
        if (!(thatCommand.get(k) instanceof Variable)
            || (thatCommand.get(k) instanceof Variable
                && !((Variable) thatCommand.get(k)).isOptional())) {
          soFarAMatch = false;
        }
      }

      if (soFarAMatch) {
        String commandThis = "";
        for (Construct c : thisCommand) {
          commandThis += c.val() + " ";
        }
        String commandThat = "";
        for (Construct c : thatCommand) {
          commandThat += c.val() + " ";
        }
        scripts.get(j).compilerError = true;
        this.compilerError = true;
        throw new ConfigCompileException(
            "The command "
                + commandThis.trim()
                + " is ambiguous because it "
                + "matches the signature of "
                + commandThat.trim(),
            thisCommand.get(0).getTarget());
      }
    }

    //        //Also, check for undefined variables on the right, and unused variables on the left
    //        ArrayList<String> left_copy = new ArrayList<String>();
    //        for (Map.Entry<String, Variable> v : left_vars.entrySet()) {
    //            left_copy.add(v.getValue().getName());
    //        }
    //        Arrays.asList(new String[]{}).toArray(new String[]{});
    //        for (ParseTree gtn : cright) {
    //            GenericTree<Construct> tree = new GenericTree<Construct>();
    //            tree.setRoot(gtn);
    //            List<ParseTree> builtTree = tree.build(GenericTreeTraversalOrderEnum.PRE_ORDER);
    //            for (ParseTree c : builtTree) {
    //                if (c.getData() instanceof Variable) {
    //                    for (Map.Entry<String, Variable> v : left_vars.entrySet()) {
    //                        if (v.getValue().getName().equals(((Variable) c.getData()).getName()))
    // {
    //                            //Found it, remove this from the left_copy, and break
    //                            left_copy.remove(v.getValue().getName());
    //                            break;
    //                            //TODO: Layton!
    //                        }
    //                    }
    //                }
    //            }
    //        }
    // }
  }
Beispiel #5
0
  public boolean match(String command) {
    if (cleft == null) {
      // The compilation error happened during the signature declaration, so
      // we can't match it, nor can we even tell if it's what they intended for us to run.
      return false;
    }
    boolean case_sensitive = Prefs.CaseSensitive();
    String[] cmds = command.split(" ");
    List<String> args = new ArrayList(Arrays.asList(cmds));
    boolean isAMatch = true;
    StringBuilder lastVar = new StringBuilder();
    int lastJ = 0;
    try {
      for (int j = 0; j < cleft.size(); j++) {
        if (!isAMatch) {
          break;
        }
        lastJ = j;
        Construct c = cleft.get(j);
        String arg = args.get(j);
        if (c.getCType() != ConstructType.VARIABLE) {
          if (case_sensitive && !c.val().equals(arg)
              || !case_sensitive && !c.val().equalsIgnoreCase(arg)) {
            isAMatch = false;
            continue;
          }
        } else {
          // It's a variable. If it's optional, the rest of them are optional too, so as long as the
          // size of
          // args isn't greater than the size of cleft, it's a match
          if (((Variable) c).isOptional()) {
            if (args.size() <= cleft.size()) {
              return true;
            } else {
              Construct fin = cleft.get(cleft.size() - 1);
              if (fin instanceof Variable) {
                if (((Variable) fin).isFinal()) {
                  return true;
                }
              }
              return false;
            }
          }
        }
        if (j == cleft.size() - 1) {
          if (cleft.get(j).getCType() == ConstructType.VARIABLE) {
            Variable lv = (Variable) cleft.get(j);
            if (lv.isFinal()) {
              for (int a = j; a < args.size(); a++) {
                if (lastVar.length() == 0) {
                  lastVar.append(args.get(a));
                } else {
                  lastVar.append(" ").append(args.get(a));
                }
              }
            }
          }
        }
      }
    } catch (IndexOutOfBoundsException e) {
      if (cleft.get(lastJ).getCType() != ConstructType.VARIABLE
          || cleft.get(lastJ).getCType() == ConstructType.VARIABLE
              && !((Variable) cleft.get(lastJ)).isOptional()) {
        isAMatch = false;
      }
    }
    boolean lastIsFinal = false;
    if (cleft.get(cleft.size() - 1) instanceof Variable) {
      Variable v = (Variable) cleft.get(cleft.size() - 1);
      if (v.isFinal()) {
        lastIsFinal = true;
      }
    }
    if ((cleft.get(lastJ) instanceof Variable && ((Variable) cleft.get(lastJ)).isOptional())) {
      return true;
    }

    if (cleft.size() != cmds.length && !lastIsFinal) {
      isAMatch = false;
    }
    //        ArrayList<Variable> vars = new ArrayList<Variable>();
    //        Variable v = null;
    //        for (int j = 0; j < cleft.size(); j++) {
    //            try {
    //                if (cleft.get(j).getCType() == ConstructType.VARIABLE) {
    //                    if (((Variable) cleft.get(j)).getName().equals("$")) {
    //                        v = new Variable(((Variable) cleft.get(j)).getName(),
    //                                lastVar.toString(), Target.UNKNOWN);
    //                    } else {
    //                        v = new Variable(((Variable) cleft.get(j)).getName(),
    //                                args.get(j), Target.UNKNOWN);
    //                    }
    //                }
    //            } catch (IndexOutOfBoundsException e) {
    //                v = new Variable(((Variable) cleft.get(j)).getName(),
    //                        ((Variable) cleft.get(j)).getDefault(), Target.UNKNOWN);
    //            }
    //            if (v != null) {
    //                vars.add(v);
    //            }
    //        }
    return isAMatch;
  }
Beispiel #6
0
  public Construct eval(ParseTree c, final Environment env) throws CancelCommandException {
    final Construct m = c.getData();
    CurrentEnv = env;
    // TODO: Reevaluate if this line is needed. The script doesn't know the label inherently, the
    // environment does, and setting it this way taints the environment.
    CurrentEnv.getEnv(GlobalEnv.class).SetLabel(this.label);
    if (m.getCType() == ConstructType.FUNCTION) {
      env.getEnv(GlobalEnv.class).SetScript(this);
      if (m.val().matches("^_[^_].*")) {
        // Not really a function, so we can't put it in Function.
        Procedure p = getProc(m.val());
        if (p == null) {
          throw new ConfigRuntimeException(
              "Unknown procedure \"" + m.val() + "\"",
              ExceptionType.InvalidProcedureException,
              m.getTarget());
        }
        Environment newEnv = env;
        try {
          newEnv = env.clone();
        } catch (Exception e) {
        }
        ProfilePoint pp =
            env.getEnv(GlobalEnv.class).GetProfiler().start(m.val() + " execution", LogLevel.INFO);
        Construct ret = p.cexecute(c.getChildren(), newEnv, m.getTarget());
        pp.stop();
        return ret;
      }
      final Function f;
      try {
        f = (Function) FunctionList.getFunction(m);
      } catch (ConfigCompileException e) {
        // Turn it into a config runtime exception. This shouldn't ever happen though.
        throw new ConfigRuntimeException("Unable to find function " + m.val(), m.getTarget());
      }
      // We have special handling for loop and other control flow functions
      if (f instanceof assign) {
        if (c.getChildAt(0).getData() instanceof CFunction) {
          CFunction test = (CFunction) c.getChildAt(0).getData();
          if (test.val().equals("array_get")) {
            env.getEnv(GlobalEnv.class).SetFlag("array_get_alt_mode", true);
            Construct arrayAndIndex = eval(c.getChildAt(0), env);
            env.getEnv(GlobalEnv.class).ClearFlag("array_get_alt_mode");
            return ((assign) f)
                .array_assign(m.getTarget(), env, arrayAndIndex, eval(c.getChildAt(1), env));
          }
        }
      }

      if (f.useSpecialExec()) {
        ProfilePoint p = null;
        if (f.shouldProfile()
            && env.getEnv(GlobalEnv.class).GetProfiler() != null
            && env.getEnv(GlobalEnv.class).GetProfiler().isLoggable(f.profileAt())) {
          p =
              env.getEnv(GlobalEnv.class)
                  .GetProfiler()
                  .start(f.profileMessageS(c.getChildren()), f.profileAt());
        }
        Construct ret =
            f.execs(m.getTarget(), env, this, c.getChildren().toArray(new ParseTree[] {}));
        if (p != null) {
          p.stop();
        }
        return ret;
      }

      ArrayList<Construct> args = new ArrayList<Construct>();
      for (ParseTree c2 : c.getChildren()) {
        args.add(eval(c2, env));
      }
      if (f.isRestricted()) {
        boolean perm = Static.hasCHPermission(f.getName(), env);
        if (!perm) {
          throw new ConfigRuntimeException(
              "You do not have permission to use the " + f.getName() + " function.",
              ExceptionType.InsufficientPermissionException,
              m.getTarget());
        }
      }
      Object[] a = args.toArray();
      Construct[] ca = new Construct[a.length];
      for (int i = 0; i < a.length; i++) {
        ca[i] = (Construct) a[i];
        // CArray, CBoolean, CDouble, CInt, CNull, CString, CVoid, CEntry, CLabel (only to sconcat).
        if (!(ca[i] instanceof CArray
                || ca[i] instanceof CBoolean
                || ca[i] instanceof CDouble
                || ca[i] instanceof CInt
                || ca[i] instanceof CNull
                || ca[i] instanceof CString
                || ca[i] instanceof CVoid
                || ca[i] instanceof IVariable
                || ca[i] instanceof CEntry
                || ca[i] instanceof CLabel)
            && (!f.getName().equals("__autoconcat__") && (ca[i] instanceof CLabel))) {
          throw new ConfigRuntimeException(
              "Invalid Construct ("
                  + ca[i].getClass()
                  + ") being passed as an argument to a function ("
                  + f.getName()
                  + ")",
              null,
              m.getTarget());
        }
        if (env.getEnv(GlobalEnv.class).GetFlag("array_get_alt_mode") == Boolean.TRUE && i == 0) {
          continue;
        }
        while (f.preResolveVariables() && ca[i] instanceof IVariable) {
          IVariable cur = (IVariable) ca[i];
          ca[i] =
              env.getEnv(GlobalEnv.class).GetVarList().get(cur.getName(), cur.getTarget()).ival();
        }
      }

      {
        // It takes a moment to generate the toString of some things, so lets not do it
        // if we actually aren't going to profile
        ProfilePoint p = null;
        if (f.shouldProfile()
            && env.getEnv(GlobalEnv.class).GetProfiler() != null
            && env.getEnv(GlobalEnv.class).GetProfiler().isLoggable(f.profileAt())) {
          p = env.getEnv(GlobalEnv.class).GetProfiler().start(f.profileMessage(ca), f.profileAt());
        }
        Construct ret = f.exec(m.getTarget(), env, ca);
        if (p != null) {
          p.stop();
        }
        return ret;
      }

    } else if (m.getCType() == ConstructType.VARIABLE) {
      return new CString(m.val(), m.getTarget());
    } else {
      return m;
    }
  }
 /**
  * Given a Location Object, returns a MCLocation. If the optional world is not specified in the
  * object, the world provided is used instead. Location "objects" are MethodScript arrays that
  * represent a location in game. There are 4 usages:
  *
  * <ul>
  *   <li>(x, y, z)
  *   <li>(x, y, z, world)
  *   <li>(x, y, z, yaw, pitch)
  *   <li>(x, y, z, world, yaw, pitch)
  * </ul>
  *
  * In all cases, the pitch and yaw default to 0, and the world defaults to the specified world.
  * <em>More conveniently: ([world], x, y, z, [yaw, pitch])</em>
  */
 public MCLocation location(Construct c, MCWorld w, Target t) {
   if (!(c instanceof CArray)) {
     throw new ConfigRuntimeException(
         "Expecting an array, received " + c.getCType(), ExceptionType.FormatException, t);
   }
   CArray array = (CArray) c;
   MCWorld world = w;
   double x = 0;
   double y = 0;
   double z = 0;
   float yaw = 0;
   float pitch = 0;
   if (!array.inAssociativeMode()) {
     if (array.size() == 3) {
       // Just the xyz, with default yaw and pitch, and given world
       x = Static.getNumber(array.get(0, t), t);
       y = Static.getNumber(array.get(1, t), t);
       z = Static.getNumber(array.get(2, t), t);
     } else if (array.size() == 4) {
       // x, y, z, world
       x = Static.getNumber(array.get(0, t), t);
       y = Static.getNumber(array.get(1, t), t);
       z = Static.getNumber(array.get(2, t), t);
       world = Static.getServer().getWorld(array.get(3, t).val());
     } else if (array.size() == 5) {
       // x, y, z, yaw, pitch, with given world
       x = Static.getNumber(array.get(0, t), t);
       y = Static.getNumber(array.get(1, t), t);
       z = Static.getNumber(array.get(2, t), t);
       yaw = (float) Static.getNumber(array.get(3, t), t);
       pitch = (float) Static.getNumber(array.get(4, t), t);
     } else if (array.size() == 6) {
       // All have been given
       x = Static.getNumber(array.get(0, t), t);
       y = Static.getNumber(array.get(1, t), t);
       z = Static.getNumber(array.get(2, t), t);
       world = Static.getServer().getWorld(array.get(3, t).val());
       yaw = (float) Static.getNumber(array.get(4, t), t);
       pitch = (float) Static.getNumber(array.get(5, t), t);
     } else {
       throw new ConfigRuntimeException(
           "Expecting a Location array, but the array did not meet the format specifications",
           ExceptionType.FormatException,
           t);
     }
   }
   if (array.containsKey("x")) {
     x = Static.getNumber(array.get("x"), t);
   }
   if (array.containsKey("y")) {
     y = Static.getNumber(array.get("y"), t);
   }
   if (array.containsKey("z")) {
     z = Static.getNumber(array.get("z"), t);
   }
   if (array.containsKey("world")) {
     world = Static.getServer().getWorld(array.get("world").val());
   }
   if (array.containsKey("yaw")) {
     yaw = (float) Static.getDouble(array.get("yaw"), t);
   }
   if (array.containsKey("pitch")) {
     pitch = (float) Static.getDouble(array.get("pitch"), t);
   }
   // If world is still null at this point, it's an error
   if (world == null) {
     throw new ConfigRuntimeException(
         "The specified world doesn't exist, or no world was provided",
         ExceptionType.InvalidWorldException,
         t);
   }
   return StaticLayer.GetLocation(world, x, y, z, yaw, pitch);
 }
 public MCItemMeta itemMeta(Construct c, int i, Target t) {
   MCItemMeta meta =
       Static.getServer().getItemFactory().getItemMeta(StaticLayer.GetConvertor().getMaterial(i));
   if (c instanceof CNull) {
     return meta;
   }
   CArray ma = null;
   if (c instanceof CArray) {
     ma = (CArray) c;
     try {
       if (ma.containsKey("display")) {
         Construct dni = ma.get("display");
         if (!(dni instanceof CNull)) {
           meta.setDisplayName(dni.val());
         }
       }
       if (ma.containsKey("lore")) {
         Construct li = ma.get("lore");
         if (li instanceof CNull) {
           // do nothing
         } else if (li instanceof CArray) {
           CArray la = (CArray) li;
           List<String> ll = new ArrayList<String>();
           for (int j = 0; j < la.size(); j++) {
             ll.add(la.get(j).val());
           }
           meta.setLore(ll);
         } else {
           throw new Exceptions.FormatException("Lore was expected to be an array.", t);
         }
       }
       if (meta instanceof MCLeatherArmorMeta) {
         if (ma.containsKey("color")) {
           Construct ci = ma.get("color");
           if (ci instanceof CNull) {
             // nothing
           } else if (ci instanceof CArray) {
             ((MCLeatherArmorMeta) meta).setColor(color((CArray) ci, t));
           } else {
             throw new Exceptions.FormatException("Color was expected to be an array.", t);
           }
         }
       }
       if (meta instanceof MCBookMeta) {
         if (ma.containsKey("title")) {
           Construct title = ma.get("title");
           if (!(title instanceof CNull)) {
             ((MCBookMeta) meta).setTitle(title.val());
           }
         }
         if (ma.containsKey("author")) {
           Construct author = ma.get("author");
           if (!(author instanceof CNull)) {
             ((MCBookMeta) meta).setAuthor(author.val());
           }
         }
         if (ma.containsKey("pages")) {
           Construct pages = ma.get("pages");
           if (pages instanceof CNull) {
             // nothing
           } else if (pages instanceof CArray) {
             CArray pa = (CArray) pages;
             List<String> pl = new ArrayList<String>();
             for (int j = 0; j < pa.size(); j++) {
               pl.add(pa.get(j).val());
             }
             ((MCBookMeta) meta).setPages(pl);
           } else {
             throw new Exceptions.FormatException("Pages field was expected to be an array.", t);
           }
         }
       }
       if (meta instanceof MCSkullMeta) {
         if (ma.containsKey("owner")) {
           Construct owner = ma.get("owner");
           if (!(owner instanceof CNull)) {
             ((MCSkullMeta) meta).setOwner(owner.val());
           }
         }
       }
       if (meta instanceof MCEnchantmentStorageMeta) {
         if (ma.containsKey("stored")) {
           Construct stored = ma.get("stored");
           if (stored instanceof CNull) {
             // Still doing nothing
           } else if (stored instanceof CArray) {
             for (String index : ((CArray) stored).keySet()) {
               try {
                 CArray earray = (CArray) ((CArray) stored).get(index);
                 MCEnchantment etype =
                     StaticLayer.GetConvertor().GetEnchantmentByName(earray.get("etype").val());
                 int elevel = Static.getInt32(earray.get("elevel"), t);
                 ((MCEnchantmentStorageMeta) meta).addStoredEnchant(etype, elevel, true);
               } catch (Exception bade) {
                 throw new Exceptions.FormatException(
                     "Could not get enchantment data from index " + index, t);
               }
             }
           } else {
             throw new Exceptions.FormatException(
                 "Stored field was expected to be an array of Enchantment arrays", t);
           }
         }
       }
     } catch (Exception ex) {
       throw new Exceptions.FormatException(
           "Could not get ItemMeta from the given information.", t);
     }
   } else {
     throw new Exceptions.FormatException(
         "An array was expected but recieved " + c + " instead.", t);
   }
   return meta;
 }
    @Override
    public Construct execs(Target t, Environment env, Script parent, ParseTree... nodes) {
      if (nodes.length < 5) {
        throw new ConfigRuntimeException(
            "bind accepts 5 or more parameters", ExceptionType.InsufficientArgumentsException, t);
      }
      Construct name = parent.seval(nodes[0], env);
      Construct options = parent.seval(nodes[1], env);
      Construct prefilter = parent.seval(nodes[2], env);
      Construct event_obj = parent.eval(nodes[3], env);
      IVariableList custom_params = new IVariableList();
      for (int a = 0; a < nodes.length - 5; a++) {
        Construct var = parent.eval(nodes[4 + a], env);
        if (!(var instanceof IVariable)) {
          throw new ConfigRuntimeException(
              "The custom parameters must be ivariables", ExceptionType.CastException, t);
        }
        IVariable cur = (IVariable) var;
        custom_params.set(
            env.getEnv(GlobalEnv.class).GetVarList().get(cur.getName(), cur.getTarget()));
      }
      Environment newEnv = env;
      try {
        newEnv = env.clone();
      } catch (Exception e) {
      }
      newEnv.getEnv(GlobalEnv.class).SetVarList(custom_params);
      ParseTree tree = nodes[nodes.length - 1];

      // Check to see if our arguments are correct
      if (!(options instanceof CNull || options instanceof CArray)) {
        throw new ConfigRuntimeException(
            "The options must be an array or null", ExceptionType.CastException, t);
      }
      if (!(prefilter instanceof CNull || prefilter instanceof CArray)) {
        throw new ConfigRuntimeException(
            "The prefilters must be an array or null", ExceptionType.CastException, t);
      }
      if (!(event_obj instanceof IVariable)) {
        throw new ConfigRuntimeException(
            "The event object must be an IVariable", ExceptionType.CastException, t);
      }
      CString id;
      if (options instanceof CNull) {
        options = null;
      }
      if (prefilter instanceof CNull) {
        prefilter = null;
      }
      Event event;
      try {
        BoundEvent be =
            new BoundEvent(
                name.val(),
                (CArray) options,
                (CArray) prefilter,
                ((IVariable) event_obj).getName(),
                newEnv,
                tree,
                t);
        EventUtils.RegisterEvent(be);
        id = new CString(be.getId(), t);
        event = EventList.getEvent(be.getEventName());
      } catch (EventException ex) {
        throw new ConfigRuntimeException(ex.getMessage(), ExceptionType.BindException, t);
      }

      // Set up our bind counter, but only if the event is supposed to be added to the counter
      if (event.addCounter()) {
        synchronized (bindCounter) {
          if (bindCounter.get() == 0) {
            env.getEnv(GlobalEnv.class).GetDaemonManager().activateThread(null);
            StaticLayer.GetConvertor()
                .addShutdownHook(
                    new Runnable() {

                      @Override
                      public void run() {
                        synchronized (bindCounter) {
                          bindCounter.set(0);
                        }
                      }
                    });
          }
          bindCounter.incrementAndGet();
        }
      }
      return id;
    }