-
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.
How to debug
-
Why you are here
Debugging is essentially problem-solving. Every programmer must know how to debug.
In this short tutorial, I'll demonstrate ways of debugging your problems in Skript
Debugging
[[ Introduction ]]
Debugging is essentially checking if everything works correctly
for instance, A -> B -> C... -> Z
and if A doesn't show Z, it means that anything could have gone wrong
This tutorial covers console debugging as well as other good practices
[[ Explicitly showing the problem ]]
A bad code here looks like this - source : skUnity Discord
Code (Text):- format gui slot 24 of player with glowing iron sword named "&6{@flower} &eKitPVP &6{@flower}" with lore "&c&lKitPVP is currently under development!", "&f", "&7Kill other players to", "&7gain exp and level up!", "&f", "&e{@flower} &fKits", "&e{@flower} &fPvP Levels", "&e{@flower} &fLeaderboards" "&f", "&fVersions &b1.8.x - 1.15.x", "&b%{_players_kitpvp}% players online!", "&aClick here to connect!" to close then run player command "/kitpvp"
If someone were to debug this, it would take ages. So? you should explicitly show what is wrong
Code (Text):- format gui slot 24 of player with glowing iron sword named "test"
So lets test more things
Code (Text):- format gui slot 24 of player with glowing iron sword named "test" with lore "hi"
then you start making it longer and longer until you realize
Code (Text):- "&e{@flower} &fLeaderboards" "&f", "&fVersions &b1
[[ Condition checking / Debug messages]]
Your problems most occur when you least expect it. So it is a good idea to check if everything else is working
NOTE: DO NOT USE MESSAGE/SEND INSTEAD OF BROADCAST
here is why:send effects are often unreliable
here is an example
Code (Text):- on right click:
- send "fired"
this is because send doesn't always send to the person who is activating the event
there are more examples where send might not work
Code (Text):- on projectile hit:
- send "hit"
also, broadcast sends the message to console as well. if you have really long debugs, you can scroll up on your console whereas default minecraft clients have that scroll limit
please use broadcasts over sends/messages
A simple example is a person arguing that 'on mine' doesn't work
Code (Text):- on mine:
- if {mine} is 1:
- give 1 diamond to player
Code (Text):- on mine:
- broadcast "on mine called"
- broadcast "{mine} is %{mine}%"
- if {mine} is 1:
- broadcast "{mine} = 1 condition passed"
- give 1 diamond to player
on mine called
{mine} is <none>
that means, {mine} was not set at the first place
For example, let's look at a bad code posted on the skUnity Discord
Code (Text):- every 1 second:
- loop all players:
- if {kit.%loop-player%::dwarf} is 1:
- if loop-player is sneaking:
- add 1 to {dwarf.timer::%loop-player%}
- if loop-player is not sneaking:
- remove 2 from {dwarf.timer::%loop-player%}
- if {dwarf.timer::%loop-player%} is less than 1:
- set {dwarf.timer::%loop-player%} to 0
- is {kit.%loop-player%::dwarf} not set?
- is loop-player is sneaking condition working?
- is adding 1 to {dwarf.timer::%loop-player%} working?
- ...
So, here is a code with debug messages
Code (Text):- every 1 second:
- loop all players:
- broadcast "looping player %loop-player%"
- if {kit.%loop-player%::dwarf} is 1:
- broadcast "dwarf is 1"
- if loop-player is sneaking:
- add 1 to {dwarf.timer::%loop-player%}
- broadcast "%{dwarf.timer::%loop-player%}%"
- if loop-player is not sneaking:
- broadcast "happening"
- remove 2 from {dwarf.timer::%loop-player%}
- broadcast "%{dwarf.timer::%loop-player%}%"
- if {dwarf.timer::%loop-player%} is less than 1:
- set {dwarf.timer::%loop-player%} to 0
- broadcast "stopped"
when they ran the code, it broadcasted
looping player notch
so that means, {kit.%loop-player%::dwarf} is not set
[[ Step checking ]]
The use of Functions allows us to embed multiple actions into one line. Because of this, they are prone to bugs
For example
Code (Text):- set {_elo} to {_k} * (1 - 1 / (1 + (10^(-1 * (({_a} - {_b}) / {_n}))))))
So, split the thing into multiple parts
Code (Text):- set {_awin} to {_a} - {_b}
- set {_aexponent} to -1 * ({_awin} / {_n})
- set {_aexpected} to 1 / (1 + (10^{_aexponent}))
- return {_k} * (1 - {_aexpected})
[[ Examples ]]
Examples are a good way of debugging things
For example
Let's say you want to use metadata but the code is not working
Code (Text):- if metadata {_str} or (substring of {_wtf} from {_a} to 10) of {_p}= "{@optionsomething}":
If the example was
Code (Text):- metadata "lastchat" of player
Code (Text):- command /debug:
- trigger:
- set {_metadata} to metadata ("lastchat" or "2ndlastchat") of player
- send "%{_metadata}%"
That means you cant just use 2 values on metadata.
That also means you cant read syntax
Debugging Tools
Debugging is tedious, debugging is hard. And programmers want to automate such stuff
[[ List debugging tool ]]
I created a debugging tool for lists.
It helps you inspect the layers of a list with ease
Requires Skript 2.4+
Code (Text):- function List_Print(node: string, layer: string=" ", list: string="", currentlayer: string="") :: strings:
- # Prints a list
- # example
- # set {listname::*} to online players
- # send List_Print("listname")
- #
- # do not touch list and current layer
- # layer is customizeable and is defaulted to 4 spaces
- set {_returnarr::1} to "%{_currentlayer}%[%{_node}%]"
- set {_t} to 1
- loop indices of {%{_list}%%{_node}%::*}:
- add 1 to {_t}
- set {_returnarr::%{_t}%} to "%{_currentlayer}%%{_layer}%%loop-value%:%{%{_list}%%{_node}%::%loop-value%}%" if {%{_list}%%{_node}%::%loop-value%} is set
- if {%{_list}%%{_node}%::%loop-value%::*} is set:
- loop List_Print(loop-value, {_layer}, "%{_list}%%{_node}%::", "%{_currentlayer}%%{_layer}%"):
- add 1 to {_t}
- set {_returnarr::%{_t}%} to loop-value-2
- return {_returnarr::*}
example response
executing 'broadcast List_Print("island")'
[island]
[farm]
[admin]
069a79f4-44e9-4726-a5be-fca90e38aaf5:Notch
b22b0d29-ce73-4b98-8aad-f6a7aa47c1af:lilMelon
e2016a5c-f93b-4e60-984d-d794ce853d03:Nopeful
[config]
[permname]
0:banned
1:visitor
2:member
3: owner
4:admin
[size]
1:2
2:4
3:6
[id]
[-1]
[setting]
[player]
build:4
[0]
[setting]
spawnpoint:x: -12, y: 128, z: -12
[1]
reference:0
[4]
level:1
owner:nopeless
reference:5
[statistic]
createdtime:1/2/20 6:2 PM
lastactive:1/2/20 6:2 PM
[5]
[children]
4:true
8:true
level:1
owner:nopeless
[setting]
[permission]
df5f766e-8d62-42af-9f10-18f95e671067:3
[player]
ban:3
build:2
chest:2
damageentity:2
drop:2
enter:1
entityinteract:2
item:2
kick:2
nofalldamage:1
nofiredamage:1
pvp:3
redstone:2
trample:5
[statistic]
createdtime:1/2/20 6:2 PM
lastactive:1/2/20 6:2 PM
[8]
level:1
owner:nopeless
reference:5
[statistic]
createdtime:1/2/20 6:2 PM
lastactive:1/2/20 6:2 PM
[9]
level:1
owner:nopeless
[setting]
[permission]
df5f766e-8d62-42af-9f10-18f95e671067:3
[player]
ban:3
build:2
chest:2
damageentity:2
drop:2
enter:1
entityinteract:2
item:2
kick:2
nofalldamage:1
nofiredamage:1
pvp:3
redstone:2
trample:5
[statistic]
createdtime:1/2/20 6:2 PM
lastactive:1/2/20 6:2 PM
[player]
[df5f766e-8d62-42af-9f10-18f95e671067]
[island]
nopeless's farm - 1:5
nopeless's farm - 2:8
nopeless's farm - 3:9
nopeless's farm:4
maxisland:100
[[ Create your own debugging tool ]]
Sometimes, you might want to create a debugging tool yourself, here is an example
Code (Text):- command /debuginventory:
- # sends every inventory action
- trigger:
- if {debug::inventory} = true:
- set {debug::inventory} to false
- else:
- set {debug::inventory} to true
- send "set debuginventory to %{debug::inventory}%"
- on inventory click:
- if {debug::inventory} = true:
- send "inventory name:%inventory name of event-inventory%"
- send "event-item:%event-item%"
- send "event-inventoryaction:%event-inventoryaction%"
- send "event-inventory:%event-inventory%"
- set {_slot} to event-slot
- send "event-slot:%{_slot}%"
- send "event-clicktype:%event-clicktype%"
- send "hotkey:%event-key%"
- send "hotkey slot:%event-hotbar-slot%"
- send "cursor slot:%cursor slot of player%"
- send inventory name of event-inventory
- send "-slot:%index of event-slot%"
- send "-count:%item amount of {_slot}%"
Tips & Tricks
[[ Skript effects ]]
Did you know that you can run Skript™ can run effects on the fly?
go to
Skript/config.sk
turn on
Code (Text):
!send "hello world"
it will say something like
executing 'send "hello world"'
hello world
this feature allows you to run Functions as well
if you are wondering what {block::1} is, just type
!send "%{block::1}%"
without the hassle of going to scripts and putting a command debug for that
more detail can be found here
https://forums.skunity.com/wiki/run-effect/
[[ Debug option ]]
Tired of deleting broadcast every time you fixed the problem only to type it again?
There is an easy way to toggle broadcast on these
Code (Text):- options:
- debug:broadcast
- on mine:
- {@debug} "on mine called"
- # stuff
Code (Text):- options:
- debug:set {_faioeal} to
- # remember to set it to something that has a 0 possibility of creating conflicts
- on mine:
- {@debug} "on mine called"
- # stuff
a code from skUnity Discord
Code (Text):- function survivalscoreboard(p: player):
- send "true" to {_p}
- <some effect> "World = %{_p} <some expression>%" to {_p}
The person also tested the code outside the function and said it executed the second line
This means one of 2 things are happening
1. the second line expression bugged out for some reason
- a) this is possible if addon developers didn't fully consider or put exception handling on their code. => Check console
- b) this is possible if the expression doesn't work on Functions. => clearly show the code not working, issue a bug report on their respective repositories.
- a) this is possible on some Functions, where addon developers didn't fully consider the use of effects inside Functions. => try changing parameters to a fixed global variable. if that works, submit a bug issue on git.
- b) the effect doesn't work in those particular parameters inside the function => change all parameters into global Variables and then test it inside and outside a function
- i) if the global variable version doesn't work, it means that the object has a problem referencing/serializing the data. => submit a bug on git
- ii) if the global variable works, test if the parameter version is the same. for example
Code (Text):- # is the object same
- command objtest:
- trigger:
- set {global} to <something>
- if {global} = param({global}):
- send "no problems"
- else:
- send "something went wrong"
- function param(o: object) :: object:
- return {_o}
[[ Flawless Debug ]]
If you are checking a string, don't broadcast the string only
Bad example
Code (Text):- set {_str} to substring of "whatever" from {_a} to {_b}
- broadcast {_str}
Code (Text):- set {_str} to substring of "whatever" from {_a} to {_b}
- broadcast "{_str} = %{_str}%"
Generally a good practice to add more info when debugging
[[ Recursive things ]]
Using recursive features? Good! you are an above-average programmer. However, you are also putting yourself at a high risk of constantly crashing your server.
Put delays and emergency stops on those Functions
Bad example
Code (Text):- function factorial(n: number) :: number:
- return 1 if {_n} = 1
- return {_n} * factorial({_n} - 1)
Code (Text):- function factorial(n: number) :: number:
- stop if {emergencystop} = 1
- wait 1 tick
- return 1 if {_n} = 1
- return {_n} * factorial({_n} - 1)
However, it is crucial when developing
[[ Types ]]
Skript Variables have types. strings, integers(longs), booleans, etc. But there seems to be virtually no way to test the type of the variable, right?
Rezz created a snippet that allows you to inspect the type of a variable. https://forums.skunity.com/threads/rezzs-snippets-things-you-can-do-in-pure-skript-2-2.2471/ <- original link. All credits to Rezz
Code (Text):- options:
- DATA: Skript-types
- function declareUsableType(addon: text, user-input: text):
- set {_type} to {_user-input} parsed as type
- {_type} is set
- add {_type} to {{@DATA}::types::*}
- set {_index} to amount of {{@DATA}::types::*}
- set {{@DATA}::type-of::%{_user-input}%} to {_type}
- set {{@DATA}::user-input-of::%{_type}%} to {_user-input}
- set {{@DATA}::index-of::%{_type}%} to {_index}
- add {_index} to {{@DATA}::addons::%{_addon}%::types::*}
- if {{@DATA}::addons::%{_addon}%} isn't set:
- set {{@DATA}::addons::%{_addon}%} to {_addon}
- function declareUsableTypes(addon: text, types: Texts):
- loop {_types::*}:
- declareUsableType({_addon}, loop-value)
- on script load:
- delete {{@DATA}::*}
- set {{@DATA}::object-type} to "object" parsed as type
- # Data Types
- declareUsableTypes("Skript", ("type", "boolean", "integer", "number", and "text"))
- # Players & Entities
- declareUsableTypes("Skript", ("player", "offline player", "command sender", "living entity", "entity", and "projectile"))
- # Blocks & Locations
- declareUsableTypes("Skript", ("block", "location", "vector", and "direction"))
- # Worlds
- declareUsableTypes("Skript", ("biome", "chunk", "world", and "weather"))
- # Items & Inventories
- declareUsableTypes("Skript", ("item", "item type", "potion effect", "inventory", "slot", "inventory action", and "click action"))
- # Enchantments
- declareUsableTypes("Skript", ("enchantment", and "enchantment type"))
- # Time
- declareUsableTypes("Skript", ("time", "timespan", "timeperiod", and "date"))
- # Misc
- declareUsableTypes("Skript", ("gamemode", "damage cause", "color", "tree type", and "particle effect"))
- on script unload:
- delete {{@DATA}::*}
- function typeof(var: object) :: type:
- loop {{@DATA}::types::*}:
- if {_var} is loop-value:
- return loop-value
- return {{@DATA}::object-type}
- Returns the variable's type, or 'object' if its type isn't declared.
declareUsableTypes(<addon name>, <list of types>)
- Declare all types listed in their user-input form. This function simply calls declareUsableType() on each list item.
declareUsableType(<addon name>, <type in standard user-input form>)
- Declare a usable type. It's important to declare specific types before general types because declaration order is preserved. i.e. A variable of a specific type, like 'player', can also be considered a more general type as well -- 'offline player' in this example. If 'offline player' is declared before 'player', 'player' type Variables will always be considered 'offline players'.
You can check more details and examples on the link
[[ Console ]]
If your code creates errors on console, believe it or not, it's actually a good sign. You can find the problem of your code by reading the error logs
Here are some common bugs and how to fix them
- NullPointer
- this usually happens when the variable you put inside the function as an argument is not set. Also, see array out of bounds exception - OutOfBounds
- this happens when you put 2 values in 1 argument when you are only allowed to put 1. This is not your fault. Skript tries to create lists whenever they see a comma. To fix this problem, add parentheses. ex) func(1, 2, 3) -> func((1), (2), (3)) - TypeError
- this happens when you have the incorrect type. Some of them are unintuitive. If you get "expected integer but number", add round({_thevariable}) to it. Some other TypeErrors are hard to fix but if you encounter them, please shorten your code so the error can be explicit
- IllegalArgument
- you entered an argument that is out of the range of that function. For example, you cant set slot 100 of an inventory - StackOverflow
this is a rare error. but most fall into 2 categories
- lack of ram: simply give your server more ram
- recursive function: there is a recursive function in your code that isn't working properly.
just some common mistakes from people
[[ Color ]]
- bold, italics don't show -> color codes reset Formatting. if you want do disable it, go to the Skript config
- color does not change to Minecraft color doe -> use colored expression
[[ List ]]
- lists don't work properly -> lists are probably not what you think. read above and get listprint
- list keeps deleting after restart -> are you sure you don't have a "clear {list::*}" somewhere
- list is not ordered -> list's indices are not what you think. read above and get listprint
- adding stuff to lists is slow -> adding is slow. use set and Loops instead
[[ Addons ]]
- using skquery, wild Skript, umbaska, skrayfall -> just no
- using Skript-mirror for simple stuff -> why
idk ill add more if i see more
Addition to things
Something is wrong? Want to contribute to this page? PM me on this account with details, I will update it.
Update log
- 2020/1/23 : Created page
- 2020/2/5 : added [ Debug sends but code doesn't work ]
- 2020/2/25 : edited format so it looks better
- 2020/2/29 : added Skript effects tutorial
- 2020/3/1 : added more information
- 2020/5/30 : added common mistakes section