You're generating a null pointer when you run the script.
NPC npc = sI.getNpcs().closest("Rat");
This will initialize before the constructor code runs, so the script object never actually gets set. This will cause your script to crash.
if(npc.exists()){
sI.npcs.closest(npcsName).interact("Attack");
There are also multiple issues in these two lines. Since the 'npc' variable is only set at the beginning of the script, it never gets updated. exists() will always return false once that npc despawns.
You are also not null checking anything. npcs.closest(npcsName) will return null when no npcs are found, which will crash your script.
Since this is such a small amount of code, you don't really need to create a separate class for it yet. Start with just calling things within onloop until you understand how a script works more.
case ATTACK:
if (!myPlayer().isUnderAttack()) {
NPC rat = getNpcs().closest("Rat");
if (rat != null && rat.interack("Attack")) {
Sleep.sleepUntil(() -> myPlayer().isUnderAttack(), 5000);
}
}
break;
This should be enough for your attack state.
Notice how I use a conditional sleep after attacking the rat. If you don't, then the bot will spam-click the rat until you are actually under attack. This is an extremely necessary thing to learn for writing efficient scripts.