Jump to content

States vs tasks?


Phaibooty

Recommended Posts

1 hour ago, Phaibooty said:

Was wondering what scripters mostly use? And why one over the other? 

Which situation would you use task over states and the reverse? 

 

Note: still learning scripting... so excuse the dumb questions pls 

I personally use neither.

"States" are a complete waste of space and makes your code far less readable.

And if by tasks you mean classes with a validate and execute method, those are just as shitty as states, except instead of having all your conditions in one weird method they're now split up in different classes.

You shouldn't really follow any of the weird design patterns people post on here 

Structure your script how you would any other Java program.

Use design patterns appropriately and don't be a ?, create your own design patterns if an existing one doesn't work

  • Like 4
Link to comment
Share on other sites

13 minutes ago, Explv said:

I personally use neither.

"States" are a complete waste of space and makes your code far less readable.

And if by tasks you mean classes with a validate and execute method, those are just as shitty as states, except instead of having all your conditions in one weird method they're now split up in different classes.

You shouldn't really follow any of the weird design patterns people post on here 

Structure your script how you would any other Java program.

Use design patterns appropriately and don't be a ?, create your own design patterns if an existing one doesn't work

Can you please elaborate?

Link to comment
Share on other sites

23 minutes ago, Nugaex said:

Can you please elaborate?

 

This is why "States" suck:

What looks cleaner, this:

enum State {
    CHOP,
    WALK_TO_BANK,
    WALK_TO_TREES,
    BANK
}

@Override
public int onLoop() throws InterruptedException {
    switch(getState()) {
        case CHOP:
            chop();
            break;
        case WALK_TO_BANK:
            getWalking()....
            break;
        case WALK_TO_TREES:
            getWalking()....
            break;
        case BANK:
            bank();
            break;
    }
    return 0;
}

private State getState() {
   if (whatever) {
       return State.BANK;
   } else if (whatever) {
       return State.WALK_TO_BANK; 
   } else if (whatever) {
       return State.WALK_TO_TREES; 
   } else {
       return State.CHOP; 
   }
}

 

Or this? :

@Override
public int onLoop() throws InterruptedException {
    if (whatever) {
       chop(); 
    } else if (whatever) {
       getWalking().... 
    } else if (whatever) {
       bank(); 
    } else {
       getWalking().... 
    }
}

 

Unless you are completely blind, I think you would agree the second is far more readable and much less code. Instead of having to look in a different method for the conditions, they are right there next to the code I am executing when they're satisfied. I don't need to maintain a redundant enum either.

People will argue that using "States" are cleaner, however this is probably because they are not making use of the DRY principle, not making effective use of methods etc. and without "States" they would just throw all of their code into onLoop.

 

As for "Tasks" or "Nodes", they have the exact same issues as "States" and more. People will argue they are cleaner because now each of their actions is in a nice self contained class, and the condition is in there too. However using this pattern you have now even less of an overview of the script as you did with states, and it's even harder to debug.

Consider this:

List<Node> someRandomAssNodes = new ArrayList<>();
  
@Override
public int onLoop() throws InterruptedException {
    for (Node node : someRandomAssNodes) {
        if (node.validate()) {
            node.execute();
        }
    }
    return 0;
}

 

The problem with this is that now in order to figure out how this script will execute I need to go into each of those Node classes, in the same order that you add them to the List and look at each of the validate methods and try and figure out how they all fit together:

 

brain.png

 

I mean, that pattern is pretty bonkers don't you think?

Instead of having:

WalkToBankNode
ChopNode
BankNode
WalkToTreesNode
DoSomeOtherShitIDKNode

Why not just just write something simple, and easy to understand like my previous example.

IF your script gets massively complex, then you should be making use of OOP principles to simplify it. You still don't need to use a weird 'Node' or 'Task' pattern, you can have a generic banking class without needing to add a validate method inside of it, and you can have a mining class without having a validate method in there either.

Sorry if the some of the syntax is off, or I rambled.

 

  • Like 13
Link to comment
Share on other sites

2 minutes ago, Explv said:

 

This is why "States" suck:

What looks cleaner, this:


enum State {
    CHOP,
    WALK_TO_BANK,
    WALK_TO_TREES,
    BANK
}

@Override
public int onLoop() throws InterruptedException {
    switch(getState()) {
        case CHOP:
            chop();
            break;
        case WALK_TO_BANK:
            getWalking()....
            break;
        case WALK_TO_TREES:
            getWalking()....
            break;
        case BANK:
            bank();
            break;
    }
    return 0;
}

private State getState() {
   if (whatever) {
       return State.BANK;
   } else if (whatever) {
       return State.WALK_TO_BANK; 
   } else if (whatever) {
       return State.WALK_TO_TREES; 
   } else {
       return State.CHOP; 
   }
}

 

Or this? :


@Override
public int onLoop() throws InterruptedException {
    if (whatever) {
       chop(); 
    } else if (whatever) {
       getWalking().... 
    } else if (whatever) {
       bank(); 
    } else {
       getWalking().... 
    }
}

 

Unless you are completely blind, I think you would agree the second is far more readable and much less code. Instead of having to look in a different method for the conditions, they are right there next to the code I am executing when they're satisfied. I don't need to maintain a redundant enum either.

People will argue that using "States" are cleaner, however this is probably because they are not making use of the DRY principle, not making effective use of methods etc. and without "States" they would just throw all of their code into onLoop.

 

As for "Tasks" or "Nodes", they have the exact same issues as "States" and more. People will argue they are cleaner because now each of their actions is in a nice self contained class, and the condition is in there too. However using this pattern you have now even less of an overview of the script as you did with states, and it's even harder to debug.

Consider this:


List<Node> someRandomAssNodes = new ArrayList<>();
  
@Override
public int onLoop() throws InterruptedException {
    for (Node node : someRandomAssNodes) {
        if (node.validate()) {
            node.execute();
        }
    }
    return 0;
}

 

The problem with this is that now in order to figure out how this script will execute I need to go into each of those Node classes, in the same order that you add them to the List and look at each of the validate methods and try and figure out how they all fit together:

 

brain.png

 

I mean, that pattern is pretty bonkers don't you think?

Instead of having:


WalkToBankNode
ChopNode
BankNode
WalkToTreesNode
DoSomeOtherShitIDKNode

Why not just just write something simple, and easy to understand like my previous example.

IF your script gets massively complex, then you should be making use of OOP principles to simplify it. You still don't need to use a weird 'Node' or 'Task' pattern, you can have a generic banking class without needing to add a validate method inside of it, and you can have a mining class without having a validate method in there either.

Sorry if the some of the syntax is off, or I rambled.

 

i would hit like but i hit my limit for the day

Link to comment
Share on other sites

imo it is good to use an object to represent activities because you can expand their functionality. For example, in my scripts i use have a cache that contains all tasks and their execution result.
This can be used as validators itself, eg if execute with iron ore fails 5 times hop worlds or if getmulecash fails 5 times stop script.
This isn't anything special, but extensions like these are way cleaner if you use proper oo.

Link to comment
Share on other sites

Both have their pros and cons. You should look into trying all of them to understand them for yourself, where best they are applied and which you prefer to use.

Throughout my RS scripting life, I've gone through all the funky and wacky methods of doing stuff, but none of them have worked for me. What I've found works best for me is to just cut out all the bullshit:

spend_weekend.png

Don't program; just script.

Don't create dependencies; just duplicate them.

  • Like 1
Link to comment
Share on other sites

  • Alek locked this topic
Guest
This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...