DerpScript 1.1

Script plugin in 100 lines, totally useless, but it works. Java 8 needed.

  1. GoToFinal
    Small plugin that I wrote just because I wanted small break from updating my AutoIn plugin.
    Main "feature" of this plugin, is only 100 lines of code.
    What this plugins does?
    This is just very small scripting plugin.
    PS: Professional logo!

    Implemented features:
    • Whole plugin is based on simple one-word tokens, and it's uses reverse polish notation All the way... so yeach, it's hard to write something, like you should write "5 5 + 2 *" instead of "(5+ 5) *2" :D
      Most of actions will "consume" item from stack, exceptions are: print and DUP
      All operations are executed on top variable from the stack (a.k.a. current)
    • +, -, /, *
      Simple Math symbols, plugin use double and long for all operations.
    • simpleWorld
      Every word that isn't reserved keyword it's saved to memory as String.
      You can escape reserved keyword by \\, like \\+ \\print etc..
      To use empty string or space see LOAD keyword.
    • numbers
      Every typed number will be also added to stack, it support long and double numbers.
    • booleans
      Use TRUE or FALSE to add value to stack, you can use:
      + on booleans works like OR gate (just A + B)
      - A must be TRUE and B must be FALSE to return TRUE. (just A - B)
      * on booleans works like AND gate (just A * B)
      / is exception, and it works like XOR gate. (A ^ B in java)
    • print
      Prints last element from stack to console.
    • DUP
      Add copy of current (top of the stack) variable to stack.
    • DEL
      Remove variable from top of the stack.
    • <name> SAVE
      Save variable to hashMap in plugin, use "name SAVE", and current (or current before "name" was added) variable from top of the stack will be saved to memory.
    • <name> LOAD
      Load variable from memory, "name LOAD" and variable is added to top of the stack.
      There are two variables "build-in" to memory, "space" and "empty", so this is just string with one space and empty string.
    • <size> <class> NEW_ARRAY
      Create new array with selected size. (it's filled from stack)
      If you wrtie:
      "one two three four five 4 java.lang.String.class NEW_ARRAY" you will get String[] {five, four, three, two} array.
      PS: yes, there is no method to set/get object from memory, sorry, 100 lines isn't enough, (you can try use INVOKE and java.lang.reflect.Array for that)
    • <object> <paramTypes... (separated by space)> <className#methodName> <num of params> INVOKE
      invoke selected method from java.
      If method is static, just use space in place of object, so it will be double space between objects from stack and paramTypes.
      "2 3 double.class double.class java.lang.Math#pow 2 invoke" (see, there are two spaces after "3", this mean that there is NULL value) This method will invoke Math.pow(3,2), results from methods with void return type will be not added to stack.
    Not implemented features:
    (for 99.99% I will not implement them in main branch [see github], 100 lines is max, maybe if someone find way to implement one of them without adding new lines)
    • Logic instructions
      Something that will run instruction only if boolean from top of the stack is TRUE
    • Negation
      Some easy way to change TRUE to FALSE and FALSE to TRUE.
    • Array get/set
      method for get and set object to/from array.
    • Goto
      Some way to jump to other line of code.
    • Bukkit Listeners and Tasks
      Some easy way to create bukkit listeners and tasks
    How to install and use:
    Place .jar file to your plugins folder, create "DerpScript" folder, and add scripts here, each script MUST have ".drp" extension, like "src.drp"
    That all.

    Code snippets:
    Code (Text):
    //#===========================================================================================

    //# It work! I don't know how! but it works!
    //# DerpScript by GotoFinal :P
    //# Sample codes, PS: //# This is comment
    //#===========================================================================================

    //# simple num tests
    add print DEL
    5 10 + print DEL
    muliple print DEL
    2 5 * print DEL
    div print DEL
    5 40 / print DEL
    min print DEL
    40 2 - print DEL
    //# Method invoking test, replace ing to _ping in testing, and Math.pow(4, Math.pow(3, 2))
    testing
    print
    _ping ing testujemy java.lang.CharSequence java.lang.CharSequence java.lang.String#replace 2 invoke print
    pow print DEL DEL DEL DEL DEL DEL
    2 3  double.class double.class java.lang.Math#pow 2 invoke print
    4  double.class double.class java.lang.Math#pow 2 invoke print DEL
    DEL DEL DEL DEL DEL DEL
    //# Creating array
    arrays print DEL
    20 40 60 3 int.class NEW_ARRAY
    //# Show table (there is space on first char)
    [Ljava.lang.Object; print  java.lang.String java.lang.Class#forName 1 invoke print java.util.Arrays#toString 1 invoke print DEL

    //#====================================
    //# Code to create and run other code :D (5 5 + print)
    //#====================================

    //# Create string with script (5 5 + print)
    space LOAD \\print space LOAD \\+ space LOAD 5 space LOAD 5 + + + + + + print
    //# Split to tokens
    java.lang.String.class java.lang.String#split 1 invoke
    //# Duplicate variable, we want also display it to console.
    DUP
    //# Display it (there is space on first char)
    [Ljava.lang.Object;  java.lang.String java.lang.Class#forName i invoke java.util.Arrays#toString 1 invoke print DEL
    //# Run interpreter (there is space on first char)
    [Ljava.lang.String;.class tests.script.SimpleScriptTest#interpretor 1 invoke

    //#====================================
    //# Boolean logic testing code
    //#====================================

    TRUE TRUE + space LOAD \\= space LOAD true space LOAD +(OR) space LOAD true + + + + + + + + print DEL DEL
    TRUE FALSE + space LOAD \\= space LOAD true space LOAD +(OR) space LOAD false + + + + + + + + print DEL DEL
    FALSE TRUE + space LOAD \\= space LOAD false space LOAD +(OR) space LOAD true + + + + + + + + print DEL DEL
    FALSE FALSE + space LOAD \\= space LOAD false space LOAD +(OR) space LOAD false + + + + + + + + print DEL DEL
    TRUE TRUE - space LOAD \\= space LOAD true space LOAD \\- space LOAD true + + + + + + + + print DEL DEL
    TRUE FALSE - space LOAD \\= space LOAD true space LOAD \\- space LOAD false + + + + + + + + print DEL DEL
    FALSE TRUE - space LOAD \\= space LOAD false space LOAD \\- space LOAD true + + + + + + + + print DEL DEL
    FALSE FALSE - space LOAD \\= space LOAD false space LOAD \\- space LOAD false + + + + + + + + print DEL DEL
    TRUE TRUE * space LOAD \\= space LOAD true space LOAD *(AND) space LOAD true + + + + + + + + print DEL DEL
    TRUE FALSE * space LOAD \\= space LOAD true space LOAD *(AND) space LOAD false + + + + + + + + print DEL DEL
    FALSE TRUE * space LOAD \\= space LOAD false space LOAD *(AND) space LOAD true + + + + + + + + print DEL DEL
    FALSE FALSE * space LOAD \\= space LOAD false space LOAD *(AND) space LOAD false + + + + + + + + print DEL DEL
    TRUE TRUE / space LOAD \\= space LOAD true space LOAD /(XOR) space LOAD true + + + + + + + + print DEL DEL
    TRUE FALSE / space LOAD \\= space LOAD true space LOAD /(XOR) space LOAD false + + + + + + + + print DEL DEL
    FALSE TRUE / space LOAD \\= space LOAD false space LOAD /(XOR) space LOAD true + + + + + + + + print DEL DEL
    FALSE FALSE / space LOAD \\= space LOAD false space LOAD /(XOR) space LOAD false + + + + + + + + print DEL DEL
    end print DEL

    Plugin code:
    (100 lines)
    Code (Text):
    package com.gmail.gotofinaldev.derpscript;
    public class DerpScript extends org.bukkit.plugin.java.JavaPlugin{
      static               java.util.Deque<java.util.Optional<Object>>                                   stack  =new java.util.concurrent.ConcurrentLinkedDeque<>();
      private static final java.util.Map<String,java.util.function.Supplier<java.util.Optional<Object>>> actions=new java.util.concurrent.ConcurrentHashMap<>(4);
      private static final java.util.Map<String,Object>                                                  vars   =new java.util.concurrent.ConcurrentHashMap<>(4);
      static{
        vars.put("space"," "); // The only possible way to get space, space LOAD
        vars.put("empty",""); // The only possible way to get empty string, empty LOAD
        actions.put("DEL",()->stack.isEmpty()?java.util.Optional.empty():(stack.pop().isPresent()?java.util.Optional.empty():java.util.Optional.empty()));
        actions.put("DUP",stack::peek);
        actions.put("NEW_ARRAY",()->java.util.Optional.ofNullable(createArrayFromStacks((clazz(stack.pop().get().toString())),(((Number)stack.pop().get()).intValue()),obj->obj)));
        actions.put("SAVE",()->{
          vars.put(stack.pop().toString(),stack.pop().orElse(null));
          return java.util.Optional.empty();
        });
        actions.put("LOAD",()->java.util.Optional.ofNullable(vars.get(stack.pop().orElse(null))));
        actions.put("+",()->{
          final Object[] ab={stack.pop().orElse(null),stack.pop().orElse(null)};
          return java.util.Optional.ofNullable(((getType(ab[0])==8)&&(getType(ab[1])==8))?((Boolean)ab[0]||(Boolean)ab[1]):(((getType(ab[0])>2)||(getType(ab[1])>2))?(((ab[0]==null)?null:ab[0].toString())+((ab[1]==null)?null:ab[1].toString())):(((getType(ab[0])==2)||(getType(ab[1])==2))?(((Number)ab[0]).doubleValue()+((Number)ab[1]).doubleValue()):(((Number)ab[0]).longValue()+((Number)ab[1]).longValue()))));
        });
        actions.put("-",()->{
          final Object[] ab={stack.pop().orElse(null),stack.pop().orElse(null)};
          return java.util.Optional.ofNullable(((getType(ab[0])==8)&&(getType(ab[1])==8))?((Boolean)ab[0]&&!(Boolean)ab[1]):(((getType(ab[0])==2)||(getType(ab[1])==2))?(((Number)ab[0]).doubleValue()-((Number)ab[1]).doubleValue()):(((Number)ab[0]).longValue()-((Number)ab[1]).longValue())));
        });
        actions.put("*",()->{
          final Object[] ab={stack.pop().orElse(null),stack.pop().orElse(null)};
          return java.util.Optional.ofNullable(((getType(ab[0])==8)&&(getType(ab[1])==8))?((Boolean)ab[0]&&(Boolean)ab[1]):(((getType(ab[0])==2)||(getType(ab[1])==2))?(((Number)ab[0]).doubleValue()*((Number)ab[1]).doubleValue()):(((Number)ab[0]).longValue()*((Number)ab[1]).longValue())));
        });
        actions.put("/",()->{
          final Object[] ab={stack.pop().orElse(null),stack.pop().orElse(null)};
          return java.util.Optional.ofNullable(((getType(ab[0])==8)&&(getType(ab[1])==8))?((Boolean)ab[0]^(Boolean)ab[1]):(((getType(ab[0])==2)||(getType(ab[1])==2))?(((Number)ab[0]).doubleValue()/((Number)ab[1]).doubleValue()):(((Number)ab[0]).longValue()/((Number)ab[1]).longValue())));
        });
        actions.put("print",()->{
          System.out.println((stack.isEmpty())?"[Error][Print] <stack is empty>":("[Print] "+stack.peek().orElse(null)));
          return stack.isEmpty()?java.util.Optional.empty():stack.pop();
        });
        actions.put("invoke",()->{
          try{
            final int paramNum=((Number)stack.pop().get()).intValue();
            final String[] data=stack.pop().get().toString().split("#");
            final Class<?>[] classes=(Class<?>[])createArrayFromStacks(Class.class,paramNum,obj->(obj instanceof Class<?>)?obj:clazz(obj.toString()));
            final Object obj=stack.pop().orElse(null);
            final Object params=createArrayFromStacks(Object.class,paramNum,param->param);
            java.lang.reflect.Method method=clazz(data[0]).getDeclaredMethod(data[1],classes);
            Object returned=java.lang.reflect.Method.class.getDeclaredMethod("invoke",Object.class,Object[].class).invoke(method,obj,params);
            return java.util.Optional.ofNullable(((getType(returned)==1)?((Number)returned).longValue():((getType(returned)==2)?((Number)returned).doubleValue():((getType(returned)==4)?returned.toString():((getType(returned)==3)?((Character)returned).charValue():(((method.getReturnType()==null)||method.getReturnType().equals(Void.class)||method.getReturnType().equals(void.class))?null:returned))))));
          }catch(Exception e){
            throw new RuntimeException(e);
          }
        });
      }
      public static <T> Object createArrayFromStacks(Class<?> clazz,final int size,final java.util.function.Function<Object,Object> func){
        final Object array=java.lang.reflect.Array.newInstance((clazz=clazz.equals(long.class)?Long.class:clazz.equals(int.class)?Integer.class:clazz.equals(short.class)?Short.class:clazz.equals(byte.class)?Byte.class:clazz.equals(float.class)?Float.class:clazz.equals(double.class)?Double.class:clazz.equals(char.class)?Character.class:clazz),size);
        for(int i=0;i<java.lang.reflect.Array.getLength(array);i++)
          java.lang.reflect.Array.set(array,i,func.apply(toObject(stack.pop().orElse(null),clazz)));
        return array;
      }
      public static Object toObject(final Object primitive,final Class<?> target){
        return target.equals(Long.class)?Long.valueOf(((Number)primitive).longValue()):(target.equals(Integer.class)?Integer.valueOf(((Number)primitive).intValue()):(target.equals(Short.class)?Short.valueOf(((Number)primitive).shortValue()):(target.equals(Byte.class)?Byte.valueOf(((Number)primitive).byteValue()):(target.equals(Float.class)?Float.valueOf(((Number)primitive).floatValue()):(target.equals(Double.class)?Double.valueOf(((Number)primitive).doubleValue()):(primitive.equals(long.class)?Long.class:(primitive.equals(int.class)?Integer.class:(primitive.equals(short.class)?Short.class:(primitive.equals(byte.class)?Byte.class:(primitive.equals(float.class)?Float.class:(primitive.equals(double.class)?Double.class:(primitive.equals(char.class)?Character.class:(primitive.equals(long[].class)?Long[].class:(primitive.equals(int[].class)?Integer[].class:(primitive.equals(short[].class)?Short[].class:(primitive.equals(byte[].class)?Byte[].class:(primitive.equals(float[].class)?Float[].class:(primitive.equals(double[].class)?Double[].class:(primitive.equals(char[].class)?Character[].class:primitive)))))))))))))))))));
      }
      public static Class<?> clazz(String str){
        try{
          return ((str=str.replace(".class","")).equalsIgnoreCase("double")?double.class:(str.equalsIgnoreCase("float")?float.class:(str.equalsIgnoreCase("long")?long.class:(str.equalsIgnoreCase("int")?int.class:(str.equalsIgnoreCase("short")?short.class:(str.equalsIgnoreCase("byte")?byte.class:(str.equalsIgnoreCase("char")?char.class:(str.equalsIgnoreCase("void")?void.class:Class.forName((String)str)))))))));
        }catch(final Exception e){
          throw new RuntimeException(e);
        }
      }
      @Override public void onEnable(){ //   public static void main(String[] args){
        java.util.Arrays.stream(this.getDataFolder().listFiles(name->name.getName().endsWith(".drp"))).map(java.io.File::toPath).forEach(DerpScript::run); // run(new java.io.File("B:\\Dane\\Derp\\src.drp").toPath());
      }
      public static void run(final java.nio.file.Path path){
        try{
          java.nio.file.Files.lines(path,java.nio.charset.Charset.forName("UTF-8")).filter(str->!(str.startsWith("//#")||str.startsWith("//#")||str.equals(""))).map(str->str.split(" ")).forEach(DerpScript::interpretor);
        }catch(final Exception ignored){
        }
      }
      public static void interpretor(final String... strings){
        java.util.Arrays.stream(strings).forEach(token->{
          if(token.trim().isEmpty()){
            stack.addFirst(java.util.Optional.empty());
            return;
          }
          final java.util.function.Supplier<java.util.Optional<Object>> act;
          if((!(token.startsWith("\\")&&!((token=token.substring(2).trim()).isEmpty())))&&((act=actions.get(token))!=null)){
            final java.util.Optional<Object> stackEntry=act.get();
            if(stackEntry.isPresent())
              stack.addFirst(stackEntry);
          }else{
            try{
              stack.addFirst(java.util.Optional.ofNullable(token.trim().matches("[\\d]+")?Long.parseLong(token):Double.parseDouble(token)));
            }catch(final NumberFormatException e){
              stack.addFirst(java.util.Optional.ofNullable(token.equals("TRUE")?Boolean.TRUE:(token.equals("FALSE")?Boolean.FALSE:token)));
            }
          }
        });
      }
      public static byte getType(final Object value){
        return (byte)(((value instanceof Long)||(value instanceof Integer)||(value instanceof Short)||(value instanceof Byte))?1:((value instanceof Boolean)?8:(((value instanceof Float)||(value instanceof Double))?2:((value instanceof CharSequence)?4:((value instanceof Character)?3:((value==null)?5:(value.getClass().isArray()?7:6)))))));
      }
    }

    Source code repo:
    GitHub: https://github.com/GotoFinal/DerpScript
    There are 3 branches, main with 100 lines limit, "Challenge" without 100 lines limit, and "4Fun" without any rules. When (and if) I will start developing this other branches, they will be added to download.


    NOTE:
    This project is currently just for challenge and fun, I developing it when I need break from other more stressing projects.
    PS: Only I have problems with decompilling it in any program? :p They just stop responding ;3


    Donations:
    Chances for donations on this great project are soo big that I added donation buttons here!
    Fell free to use them.
    You don't must use them.
    Trust me.
    There are yellow.
    USD

    [​IMG]
    EUR / PLN / GBP
    EUR / PLN / GBP
    [​IMG][​IMG]
    [​IMG]
    Donors:
    <yep>


    Yeach, that all :D just one more useless plugin!

Recent Updates

  1. Load fix, and primitives!

Recent Reviews

  1. S3RG10
    S3RG10
    5/5,
    Version: 1.1
    Useless plugin I'll add into a friend's server just to increase the amount of plugins there. I would rate it 11/10 but Spigot doesn't let me do it.
  2. rickerd120
    rickerd120
    5/5,
    Version: 1.1
    lol
  3. Shadow48402
    Shadow48402
    5/5,
    Version: 1.0
    Looks awesome =)