[Concept] Addonless Object-Oriented Skript

  • 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!

Rezz

Addon Developer
Jan 24, 2017
80
37
18
"Addonless" is only partially true, but the point is: Object-Oriented Programming is 100% possible in Skript without an addon dedicated for it. All that's required is tedious manual scripting or a Skript compiler, which is what I'm currently working on. :emoji_wink:

My plan is to have this code:
code_language.skript:
class Test:

    method constructor():
        set [this]->count to 6

    method hello(to):
        send "Hello!!!" to [to]

    method count():
        add 1 to [this]->count
        return [this]->count

command /test:
    trigger:
        debug "Creating a new Test object and calling a method."

        set [object] to new Test()
        [object]->hello(sender)

        loop 3 times:
            set [number] to [object]->count()
            set [number-variable] to [object]->count

            send "The counter has counted: %[number]% and stored it as: %[number-variable]%"

compile into:
code_language.skript:
on script load:
    registerNewClass("Test")
    registerClassMethod("Test", "constructor", 0)
    registerClassMethod("Test", "hello", 1)
    registerClassMethod("Test", "count", 0)
 
sub "Test:constructor":
    set {_this} to parameter 1
 
    set {->%{_this}%::count} to 6

sub "Test:hello":
    set {_this} to parameter 1
    set {_return} to parameter 2
    set {_args} to parameter 3
 
    set {_to} to {->%{_args}%::1}
 
    send "Hello!!!" to {_to}
 
sub "Test:count":
    set {_this} to parameter 1
    set {_return} to parameter 2

    add 1 to {->%{_this}%::count}
    set {->%{_return}%} to {->%{_this}%::count}
 
command /test:
    trigger:
        invoke "debug" from script and "Creating a new Test object and calling several methods."
 
        set {_object} to newInstance("Test")
        invoke "Skim:Framework:construct" from {_object}
     
        set {_return$1} to newTemporaryAddress()
        invoke "Skim:Framework:call-method" from {_object} and "hello" and {_return$1} and sender
        delete({_return$1})
     
        loop 3 times:
            set {_return$2} to newTemporaryAddress()
            invoke "Skim:Framework:call-method" from {_object} and "count" and {_return$2}
            set {_number} to {->%{_return$2}%}
            delete({_return$2})
         
            set {_number-variable} to {->%{_object}%::count}
         
            send "The counter has counted: %{_number}% and stored it as: %{_number-variable}%"

The "compiled" version (it was written manually :emoji_cry:) currently works as expected, but I still have to complete the compiler.

yXPV5u7.png


Now, the "compiled" results look a bit funky, but let me explain.

I've implemented a way to pass by reference (like Java) instead of pass by value (how Skript normally behaves) using global-yet-effectively-temporary variables that get deleted often. I'm abusing the fact that all Skript variables names are keys in a giant map, so I pass around variable names instead of values.

In order to create dynamic functions, I use SkQuery subroutines. Subroutines don't offer a way to return a value, but that's quite easy to achieve: I simply pass a variable name that the subroutine should set and immediately delete it after use.
 
Last edited:
Sadly, Skript was meant to be easily understood. Because of this, it uses very basic, almost English, syntax, which makes it impossible to create certain extensions and features. Looking at your methods and syntax, it seems that Skript is growing farther and farther away from the simplicity that it was made to be.

Thus, I would find it harder for users to understand these methods, which is why you would need to make the syntax easily read.
 
I wonder if this had anything to do with my Umbaska Class idea :emoji_thinking:
 
Sadly, Skript was meant to be easily understood. Because of this, it uses very basic, almost English, syntax, which makes it impossible to create certain extensions and features. Looking at your methods and syntax, it seems that Skript is growing farther and farther away from the simplicity that it was made to be.

Thus, I would find it harder for users to understand these methods, which is why you would need to make the syntax easily read.
Do you find syntax like {_this::sort::%of%::thing::*} difficult? If not, then the syntax I'm creating isn't that hard to understand.
These are advanced features for advanced users. ¯\_(ツ)_/¯

I wonder if this had anything to do with my Umbaska Class idea :emoji_thinking:
Nope. The oldest file in my project is from last Saturday. :emoji_stuck_out_tongue:
 
Do you find syntax like {_this::sort::%of%::thing::*} difficult? If not, then the syntax I'm creating isn't that hard to understand.
These are advanced features for advanced users. ¯\_(ツ)_/¯
Even if they are for advanced users it loses the point for what Skript was created, modify your server without learning Java nor an IDE and what you've done here isn't even near to the Skript "style".
 
Even if they are for advanced users it loses the point for what Skript was created, modify your server without learning Java nor an IDE and what you've done here isn't even near to the Skript "style".
You can make that same argument for quite a few addons. Yet we still use them because they're useful tools. And you won't need an IDE for what I've created.

I'm really surprised by how many of you are opposed to this...
What exactly is so terribly not-skript-like about what I've done here?
 
You can make that same argument for quite a few addons. Yet we still use them because they're useful tools. And you won't need an IDE for what I've created.

I'm really surprised by how many of you are opposed to this...
What exactly is so terribly not-skript-like about what I've done here?
You're growing away from what Skript is meant to be. You said above that these were advanced features for advanced users, while Skript is supposed to be for everyone. Although you are trying to make certain functions easier, you are actually creating more confusion on what Skript actually is. It isn't supposed to be a programming language or have full-on syntax, it is supposed to be literally English.
 
You're growing away from what Skript is meant to be.
Skript is meant to be a scripting language for easier server customization.

You said above that these were advanced features for advanced users, while Skript is supposed to be for everyone.
What you're failing to realize is that by creating my class syntax, I'm making something that's already possible in Skript easier for everyone. That's why this thread is called "addonless object-oriented skript" - it's 100% possible to do this right now (not with my pretty syntax yet, of course).

It isn't supposed to be a programming language or have full-on syntax
What. That's just wrong.

it is supposed to be literally English.
It's supposed to be whatever users/devs make of it. Skript is simply a tool, after all.

Most things in Skript are English phrases, but there are also plenty of exceptions. Just look at the command syntax:
code_language.skript:
command /something <player> [<text>]
That is not an English sentence.

I mean, if users can handle functions...
code_language.skript:
function something(totally-not-a-sentence: text="some text") :: boolean:
    return true
... then they can easily handle my class syntax too. :emoji_wink:
 
Last edited:
Skript is meant to be a scripting language for easier server customization.


What you're failing to realize is that by creating my class syntax, I'm making something that's already possible in Skript easier for everyone. That's why this thread is called "addonless object-oriented skript" - it's 100% possible to do this right now (not with my pretty syntax yet, of course).


What. That's just wrong.


It's supposed to be whatever users/devs make of it. Skript is simply a tool, after all.

Most things in Skript are English phrases, but there are also plenty of exceptions. Just look at the command syntax:
code_language.skript:
command /something <player> [<text>]
That is not an English sentence.

I mean, if users can handle functions...
code_language.skript:
function something(totally-not-a-sentence: text="some text") :: boolean:
    return true
... then they can easily handle my class syntax too. :emoji_wink:
You're just not understand my view, and I totally get that.
I mean, it's not like my opinion is going to stop you from doing what you're doing, as it is only an opinion.
Thanks for taking the time to make this anyways.
 
Well, I'm trying to create a syntax reader to start off with. It's really confusing and I'm only doing it for fun though...
 
Here's a tiny update on this project so far: https://gist.github.com/RezzedUp/e75847a72152871619eeec31f5700db2

With the following files:

c60ZUWh.png

projects/Test/project.yml
YAML:
project:
    main: main

projects/Test/src/main.sk
code_language.skript:
#@ This comment will be removed.

@include "opposite"
@include "included/hello"

#@ Content within a raw section will not be modified.

@start "raw"

on skript load:

    send "Unmodified." to console
    #@ This comment will be included.

@end "raw"

command /hi:
    executable by: players
    permission: can.hello
    trigger:
        hello(sender)

command /opposite <boolean>:
    trigger:
        debug "Checking the opposite of '%arg-1%'"
        send "%opposite(arg-1)%"

projects/Test/src/opposite.sk
code_language.skript:
@include "okay"

function opposite(bool: boolean) :: boolean:

    if [bool]:
        return false
    else:
        return true

projects/Test/src/okay.sk
code_language.skript:
function okay_no_args() :: text: #include this comment #@ but exclude this one

    return "This function has no arguments. &3Okay."

on script load:

    send "%okay_no_args()%" to console

projects/Test/src/included/hello.sk
code_language.skript:
function hello(player: player):

    send "Hello!" to {_player}

Running /compile Test will produce:

FGTWvgY.png

code_language.skript:
# Test v1.0.0 compiled with Skim Compiler
#@: --> start 'plugins/Skript/projects/Test/src/main.sk' @ 0

#@: --> start 'plugins/Skript/projects/Test/src/opposite.sk' @ 0
#@: --> start 'plugins/Skript/projects/Test/src/okay.sk' @ 0
function okay_no_args(~: boolean=true) :: text: #include this comment

    return "This function has no arguments. &3Okay."

on script load:

    send "%okay_no_args()%" to console
#@: --> end 'plugins/Skript/projects/Test/src/okay.sk'
#@: --> resume 'plugins/Skript/projects/Test/src/opposite.sk' @ 1

function opposite(bool: boolean) :: boolean:

    if {_bool}:
        return false
    else:
        return true
#@: --> end 'plugins/Skript/projects/Test/src/opposite.sk'
#@: --> resume 'plugins/Skript/projects/Test/src/main.sk' @ 3
#@: --> start 'plugins/Skript/projects/Test/src/included/hello.sk' @ 0
function hello(player: player):

    send "Hello!" to {_player}
#@: --> end 'plugins/Skript/projects/Test/src/included/hello.sk'
#@: --> resume 'plugins/Skript/projects/Test/src/main.sk' @ 4



on skript load:

    send "Unmodified." to console
    #@ This comment will be included.


command /hi:
    executable by: players
    permission: can.hello
    trigger:
        hello(sender)

command /opposite <boolean>:
    trigger:
        send "%opposite(arg-1)%"
#@: --> end 'plugins/Skript/projects/Test/src/main.sk'

And here's a sample of what an error looks like:
(even though the preview above doesn't contain any)

0qrcSF7.png
 
Last edited: