1. Welcome to skUnity!

    Welcome to skUnity! This is a forum where members of the Skript community can communicate and interact. Skript Resource Creators can post their Resources for all to see and use.

    If you haven't done so already, feel free to join our official Discord server to expand your level of interaction with the comminuty!

    Now, what are you waiting for? Join the community now!

Dismiss Notice
This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Addon IdkSk - The Nashorn/JS Eval Addon 1.2.1

The Nashorn/JS Eval Addon

  1. Nicofisi
    Supported Minecraft Versions:
    • 1.8, 1.9, 1.10, 1.11, 1.12
    Hey you! IdkSk is currently the best unnamed addon

    Does it mean "I don't know Skript", you may think? No! I means that I had no idea for a name.. well, actually - the "I don't know Skript" version would be true for me, so translate it how you prefer :emoji_cactus: After all, IdkSk isn't that counter-intuitive at all, is it? Maybe let's continue to the actual features

    IdkSk is an addon using which you can execute code. What type of code? - one may ask. Well, many types of code.

    Inb4, I propose to take a look at the code below:
    Code (Skript):
    1. command /hi:
    2.         trigger:
    3.                 set {_x} to new "js" script engine
    4.                 pass sender named "sender" to script engine {_x}
    5.                 add "Packages.java.lang.System.out.println(2 + 2)" to {_code::*}
    6.                 add "sender.sendMessage(""hello!"")" to {_code::*}
    7.                 add "throw new Packages.java.lang.RuntimeException()" to {_code::*}
    8.                 set {_res} to eval {_code::*} with script engine {_x}
    9.                 if {_res} is a script exception:
    10.                         message "An error has occured: %title line of {_res}%"
    11.                         message "For the full stacktrace check the console"
    12.                         send "Stacktrace of an error caused by code executed by %sender%:" to console
    13.                         send "%stacktrace of {_res}%" to console
    14.                 else:
    15.                         message "The result is %{_res}%"
    And compare it to the result of running it:
    Code (Text):
    1. >hi
    2. [21:46:20 INFO]: 4
    3. [21:46:20 INFO]: hello!
    4. [21:46:20 INFO]: An error has occured: jdk.nashorn.internal.runtime.ECMAException: java.lang.RuntimeException
    5. [21:46:20 INFO]: For the full stacktrace check the console
    6. [21:46:20 INFO]: Stacktrace of an error caused by code executed by CONSOLE:
    7. [21:46:20 INFO]: <eval>:3:0 java.lang.RuntimeException
    8.         at jdk.nashorn.internal.runtime.ECMAException.create(ECMAException.java:113)
    9.         at jdk.nashorn.internal.scripts.Script$23$\^eval\_.:program(<eval>:3)
    10.         at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:637)
    11.         <many more lines here>
    Let's try to understand it line by line, starting from line number three:
    Code (Skript):
    1. set {_x} to new "js" script engine
    2. #syntax is "new %string% script[ing] engine", "new script[ing] engine (of|with|using) lang[uage] %string%"
    In this line, we use the NewScriptEngine expression for the first time. It returns a new script engine, something that we will use for running code later. In this line we need to choose the language. IdkSk currently supports only Nashorn (that is, JavaScript), but if you'd like to see support for languages like Scala and Kotlin, please let me know. I'll explain later what Nashorn exactly is, please read on now.
    Nashorn has a few aliases which mean the same, you can use any of these names: nashorn, Nashorn, js, JS, JavaScript, javascript, ECMAScript, ecmascript with this expression
    Code (Skript):
    1. pass sender named "sender" to script engine {_x}
    2. #syntax is "(pass|add) [(arg[ument]|param[eter]|var[iable]|obj[ect])] %objects% (named|with name) %string% to [script[ ]engine] %scriptengine%"
    Here we use the PassToScriptEngine effect for the first time. If you'd like to use any variable from the outside world in your code, pass it here. It will be kept in the script engine {_x} even after you execute the code, so you can execute it multiple times (or run very different code) and and your variables will be waiting for you safely
    Code (Skript):
    1. add "Packages.java.lang.System.out.println(2 + 2)" to {_code::*}
    2. add "sender.sendMessage(""hello!"")" to {_code::*}
    3. add "throw new Packages.java.lang.RuntimeException()" to {_code::*}
    Here you define the code that you want to run. Of course you can choose not to save it here this way and in one of the next lines simply use "code" or "line1" and "line2" or "line1%nl%line2" or "line1;line2" etc.
    Note how I used the Packages. word to let Java know that java is a package, not some variable. And by the way, here we also use the sender object that we passed before.
    Code (Skript):
    1. set {_res} to eval {_code::*} with script engine {_x}
    2. #syntax is "(eval|run|execute|exec|evaluate) [code] %strings% (using|with) [script[ ]engine] %scriptengine% [and (get|return) [the] result]"
    Here we actually execute the code and get the result. If can be the expected result, or a script exception (that's how it's called internally in the scripting API so i named it this way too)
    Code (Skript):
    1.  if {_res} is a script exception:
    Here we check if {_res(ult)} is an script exception. If it's not, it's expected result (unless the error is what you expected..)
    Code (Skript):
    1. message "An error has occured: %title line of {_res}%"
    2. message "For the full stacktrace check the console"
    3. send "Stacktrace of an error caused by code executed by %sender%:" to console
    4. send "%stacktrace of {_res}%" to console
    Here you can see an example use of two property expressions. Look at the console output on the top of the post to examine what they return
    Code (Skript):
    1. else:
    2.         message "The result is %{_res}%"
    As I wrote before, if it's not an error - it's the actual result. Great job - your code worked! Probably at least. And, it's great unless you're DDOSing someone. If you are, it's only half great.

    Cool! We did it. I did my best to explain everything and you hopefully read and understood that.

    Now - about Nashorn.
    Nashorn is simply a js engine written specifically for Java. And JavaScript is almost like Java. A great deal of stuff works exactly the way you'd expect it to work in java.
    Just remember that when you're using something that normally would have to be imported in java, you need to use either Packages.pa.cka.ge.he.re.ClassName.method() or Java.type("pa.cka.ge.he.re.ClassName").method()
    Here is an example of some "more advanced code" that you could execute (it's very simple though probably 10 times more complicated than what you'll be usually running lol):
    Code (Javascript):
    1. var IntArray = Java.type("int[]");
    3. var array = new IntArray(5);
    4. array[0] = 5;
    5. array[1] = 4;
    6. array[2] = 3;
    7. array[3] = 2;
    8. array[4] = 1;
    10. try {
    11.    array[5] = 23;
    12. } catch (e) {
    13.    print(e.message);  // Array index out of range: 5
    14. }
    16. array[0] = "17";
    17. print(array[0]);  // 17
    19. array[0] = "wrong type";
    20. print(array[0]);  // 0
    22. array[0] = "17.3";
    23. print(array[0]);  // 17
    See? It's very similar to Java. Here are more examples:
    Code (Javascript):
    1. var map = new java.util.HashMap();
    2. map.put('foo', 'val1');
    3. map.put('bar', 'val2');
    5. for each (var e in map.keySet()) print(e);  // foo, bar
    7. for each (var e in map.values()) print(e);  // val1, val2
    9. // Lambda expressions and Streams
    10. var list2 = new java.util.ArrayList();
    11. list2.add("ddd2");
    12. list2.add("aaa2");
    13. list2.add("bbb1");
    14. list2.add("aaa1");
    15. list2.add("bbb3");
    16. list2.add("ccc");
    17. list2.add("bbb2");
    18. list2.add("ddd1");
    20. list2
    21.    .stream()
    22.    .filter(function(el) {
    23.        return el.startsWith("aaa");
    24.    })
    25.    .sorted()
    26.    .forEach(function(el) {
    27.        print(el);
    28.    });
    29.    // aaa1, aaa2
    I copied the above from http://winterbe.com/posts/2014/04/05/java8-nashorn-tutorial/ - I highly recommend you to go and read that.

    I made this addon mainly because I needed it for my Skript Discord bot to be fair, so I can update this thread with a Discord example later if you want - simply ask and give me some time :emoji_heart:

    If you have any issues, questions or suggestions, feel free to contact me here, but even better - on Discord (I'm Nicofisi#4467), and eventually on GitHub. Have fun!

Recent Reviews

  1. InvisibleBlade
    Version: 1.2.1
    The greatest addon i've ever had.
    I hope you will realise more addons with Scala evaluation support.
    1. Nicofisi
      Author's Response
      Thanks bae! May the Ducky be with you
  2. iDarkyy
    Version: 1.2.1
    Great addon ^^
    Could you add Kotlin or Scala evaluation support, Thanks.
    1. Nicofisi
      Author's Response
      Ilyt, Scala or Kotlin first?