[#4] Skript Challenge - Loop area

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

Status
Not open for further replies.

BaeFell

I'm Poppy
Staff member
Admin
skUnity Legend
Nov 27, 2016
1,024
241
73
discord.gg
Discord Username
BaeFell
Hi everyone,

Welcome to another Skript Challenge!

Based on the #3 Skript Challenge - Area Fill, in this Skript Challenge you must loop between 2 dynamically set points (which you must also provide the code for setting the points)

Another mathematically thinking Skript Challenge in which you must be aware of how to loop an area but do it efficiently and easily while maintaining code readability.

The rules are as follows (note: rules may change between challenge):
- Your code must be in
Code:
<code>
tags so that I can easily read it.
- You can use addons, but, you're not allowed to use a feature from an addon which does this and the addon must of been released publicly prior to the creation of this thread (eg. skQuery's loop between...)
- You can use another user's code, but please don't edit your messages. I can see all message history and posts that do have edit history like this will not be counted
Remember: this one is about quality, not just length. So trying to cut variable names from someone elses code will lose points! I want readability and functionality over length
- Web API's or using an external source (outside of Skript), to get your result in not allowed. All submissions must actually do the conversions themselves.
- You must list all addons used. I will be testing on Spigot 1.11.2.

I might add a rule after a submission has been made, it's up to me whether or not that submission is valid. I can deny any submission for any reason.

Challenge details (specifics about this challenge):
- The default area will be a rectangle or square. More points if you can easily let me have weird shaped areas.
- You must provide a way for me to set the points to loop between. More points for making this easy to use and functional
- There must be a command or something to loop between the 2 points. I'd like to know how many blocks and what type of blocks there are in the area... more information = more points.


Tips:
- Be efficient and smart about your code. I like to be able to read the code and make sense of it. Comments and good variable naming is a plus.
- Try not to crash my server

How answers will be judged:
Unlike others, the winner for this one, will be judged based on quality. I and others (who I'm yet to pick), will go around and find the best answers. I'm not sure on the specifics of how the scoring will work, the final judgement and most other things, but I've got a week to figure that out!

Important
If you don't understand how your answer will be judged here is an explanation:
Better code quality = more points. I'm very anti-addon with some things. If you're using an addon for what can be done normally in Skript, then you're not Skripting right. Variable names, code structure, use of functions and code readability matters for this challenge. I'm specifically looking for the best code, not the smallest, but you shouldn't have code that is far too long, otherwise it's unlikely to be efficient.

The closing date is 7 days from now -> 7th of April - have fun!
(I might be too busy to post winners on the 8th of April, but any entries after the 7th of April at 11:59PM GMT will not be counted)
 
no addons and tested on dev32. the looping takes some time if the area selection is big so please be patient!
code_language.skript:
#Set point 1 command
command /setpoint1:   
    trigger:
        set {point1} to player's location
        send "&aPoint 1 has been set to your location."

#Set point 2 command
command /setpoint2:   
    trigger:
        set {point2} to player's location
        send "&aPoint 2 has been set to your location."

#Main command
command /loopblocks:
    trigger:
        #Make sure everything is good to go before looping
        if {point1} is not set:
            send "&cPoint 1 has not been set."
        else if {point2} is not set:
            send "&cPoint 2 has not been set."
        else if {point1}'s world is not {point2}'s world:
            send "&cBoth points must be in the same world."
        else:
            send "&aLooping blocks... this will take a few moments, please be patient."

            #Get min/max coords
            if x-coord of {point1} is greater than x-coord of {point2}:
                set {_minX} to x-coord of {point2}
                set {_maxX} to x-coord of {point1}
            else:
                set {_minX} to x-coord of {point1}
                set {_maxX} to x-coord of {point2}
            if y-coord of {point1} is greater than y-coord of {point2}:
                set {_minY} to y-coord of {point2}
                set {_maxY} to y-coord of {point1}
            else:
                set {_minY} to y-coord of {point1}
                set {_maxY} to y-coord of {point2}
            if z-coord of {point1} is greater than z-coord of {point2}:
                set {_minZ} to z-coord of {point2}
                set {_maxZ} to z-coord of {point1}
            else:
                set {_minZ} to z-coord of {point1}
                set {_maxZ} to z-coord of {point2}

            #Loop the blocks
            set {_looping} to true
            set {_loopX} to {_minX}
            set {_loopY} to {_minY}
            set {_loopZ} to {_minZ}
            while {_looping} is true:
                add block at location at {_loopX}, {_loopY}, {_loopZ} to {_blocks::*}
                add 1 to {_loopX}
                if {_loopX} is greater than {_maxX}:
                    set {_loopX} to {_minX}
                    add 1 to {_loopY}
                    if {_loopY} is greater than {_maxY}:
                        set {_loopY} to {_minY}
                        add 1 to {_loopZ}
                        if {_loopZ} is greater than {_maxZ}:
                            set {_looping} to false
                wait 1 tick

            #Get a string containing all the block counts
            loop {_blocks::*}:
                set {_blockType} to "%loop-value%"
                add 1 to {_blockCount::%{_blockType}%}
            set {_allBlockCounts} to ""
            loop {_blockCount::*}:
                set {_allBlockCounts} to "%{_allBlockCounts}%%{_blockCount::%loop-index%}% %loop-index% | "
            set {_allBlockCounts} to the first (length of {_allBlockCounts} - 2) characters of {_allBlockCounts}

            #Send results
            send "&aFinished!"
            send "&6Total number of blocks: &e%size of {_blocks::*}%"
            send "&6Block makeup: &e%{_allBlockCounts}%"
 
  • Like
Reactions: BaeFell
code_language.skript:
command /setpoint <number>:
    trigger:
        if arg-1 is not 1 or 2:
            message "You can only set point 1 and 2"
            stop
        set {point-%arg-1%} to location(floor(x coord of player), floor(y coord of player), floor(z coord of player), world of player)
        message "Point %arg-1% set!"

command /lb2:
    trigger:
        if {point-1} is not set:
            message "Set point 1 using '/setpoint 1' first!"
            stop
        if {point-2} is not set:
            message "Set point 2 using '/setpoint 2' first!"
            stop
        if the world of {point-1} is not the world of {point-2}:
            message "You need to have both points in the same world"
            stop
        message "&cWarning: when using large areas, lag will occur!"
        set {_min-x} to x coord of {point-1}
        set {_min-y} to y coord of {point-1}
        set {_min-z} to z coord of {point-1}
        if {_min-x} > x coord of {point-2}:
            set {_min-x} to x coord of {point-2}
        if {_min-y} > y coord of {point-2}:
            set {_min-y} to y coord of {point-2}
        if {_min-z} > z coord of {point-2}:
            set {_min-z} to z coord of {point-2}
        set {_dif-x} to (difference between x coord of {point-1} and x coord of {point-2}) + 1
        set {_dif-y} to (difference between y coord of {point-1} and y coord of {point-2}) + 1
        set {_dif-z} to (difference between z coord of {point-1} and z coord of {point-2}) + 1
        message "Expected time (only works with small areas): &2%{_dif-x} * {_dif-y} / 20% seconds"
        set {_now} to now
        message "Calculation started"
        loop {_dif-x} times:
            loop {_dif-y} times:
                loop {_dif-z} times:
                    set {_x} to loop-number-1 + {_min-x} - 1
                    set {_y} to loop-number-2 + {_min-y} - 1
                    set {_z} to loop-number-3 + {_min-z} - 1
                    add location({_x}, {_y}, {_z}, world of {point-1}) to {_locs::*}
                wait 1 tick
        loop {_locs::*}:
            delete {_b}
            set {_b} to "%block at loop-value%"
            if {_blocks::*} is not set:
                add {_b} to {_blocks::*}
            if {_blocks::*} does not contain {_b}:
                add {_b} to {_blocks::*}
            add 1 to {_blocks::%{_b}%::amount}
        message "Done!"
        message "Different types of blocks: "
        loop {_blocks::*}:
            message " - &2%{_blocks::%loop-value%::amount}% &rof &2%loop-value% &rbetween the points"
        message "Total blocks between the points: &2%amount of {_locs::*}%"
        message "Calculated area: &2%{_dif-x}% * %{_dif-y}% * %{_dif-z}% = %{_dif-x} * {_dif-y} * {_dif-z}%"
        message "Took &2%difference between now and {_now}%"
No addons required, tested on 2.2-dev34.
The biggest area I tried was 31020 blocks, and it took 10 minutes and 25 seconds and got the TPS down to 12.5, so be patient and expect some lag.

EDIT: I made some changes because I just noticed that the difference expression works a little bit differently than I expected and that Minecraft rounds its coordinates down.
 
Last edited:
I can't say that my code is very readable, but it's reasonably performant.
1. No lists, so it saves plenty of RAM.
2. Loops only once (gets all blocks and set them all inside itself).
3. The block is only set if it's a different one (not blue wool). Greatly increases performance if you want to make small adjustments.
4. No add %blocks% to {variable::*}, which also increases performance.
5. No addons, needs an a bit updated version of Bensku's Skript because of unix timestamp (I hate Skript's date/timespan, don't judge me).

[Old code, challenge isn't exactly about this lol]

code_language.skript:
on leftclick holding gold axe:
   event-block is set
   cancel event
   set {pos1} to location of event-block
   send "Pos1 is now set."
 
on rightclick holding gold axe:
   event-block is set
   cancel event
   set {pos2} to location of event-block
   send "Pos2 is now set."
 
command /rectangle [<text>]:
   trigger:
 
       set {_u} to unix timestamp of now
 
       # Getting positions (useless part)
       set {_1} to {pos1}
       set {_2} to {pos2}
 
       # Just saving 3 lines (elses)
       set {_x} to 1
       set {_y} to 1
       set {_z} to 1
 
       # Determines the direction to be used (it always goes from 1 to 2)
       if x coord of {_1} > x coord of {_2}:
           set {_x} to -1
       if y coord of {_1} > y coord of {_2}:
           set {_y} to -1
       if z coord of {_1} > z coord of {_2}:
           set {_z} to -1
 
       # As {_1} is the only one that is changed, I save it.
       # {_2} is used for base.
       set {_base1} to {_1}
 
       # Getting the blocks.
       # I'm not a big fan of whiles, so I just get the difference.
       loop abs(x coord of {_1} - x coord of {_2}) + 1 times:
           loop abs(z coord of {_1} - z coord of {_2}) + 1 times:
               loop abs(y coord of {_1} - y coord of {_2}) + 1 times:
  
                   # This greatly increases performance if the blocks are already set.
                   if block at {_1} != blue wool:
                       # set block at {_1} to blue wool

                   add 1 to {_total}
                   add {_y} to y coord of {_1}
      
               # Goes to the next Z and resets Y...
               add {_z} to z coord of {_1}
               set y coord of {_1} to y coord of {_base1}
  
           # Goes to the next X and resets Z...
           add {_x} to x coord of {_1}
           set z coord of {_1} to z coord of {_base1}
 
           # Optional waiting.
           # wait 1 tick

       set {_time} to (unix timestamp of now - {_u}) * 1000
       send " "
       send "&3&lCUBOID STATS"
       send "Blocks changed: &a%{_total}%"
       send "Cuboid took &a%{_time}%ms&f!"
       send " "
       send "Overall speed: &a%{_total} * 1000 / {_time}% blocks/s"
       send " "

In my tests, it scores about ~120,000 blocks/s without 1 tick delay and no preset blocks.
The tick delay is pretty ridiculous, I know, but I'm too lazy to make a better one. It's just to prevent your server from crashing, not lagging.

Do more of these challenges, I like them :emoji_stuck_out_tongue:

@EDIT
Yeah, so I was setting the blocks, but instead the challenge says to just give information about the blocks. It actually performs better doing that (my record is 284,711 blocks/s).

jekE9iX.png

Twice as fast :emoji_wink:

New code:
code_language.skript:
on leftclick holding gold axe:
   event-block is set
   cancel event
   set {pos1} to location of event-block
   send "Pos1 is now set."
  
on rightclick holding gold axe:
   event-block is set
   cancel event
   set {pos2} to location of event-block
   send "Pos2 is now set."
      
command /rectangle [<text>]:
   trigger:
  
       set {_u} to unix timestamp of now
  
       # Getting positions (useless part)
       set {_1} to {pos1}
       set {_2} to {pos2}
  
       # Just saving 3 lines (elses)
       set {_x} to 1
       set {_y} to 1
       set {_z} to 1
  
       # Determines the direction to be used (it always goes from 1 to 2)
       if x coord of {_1} > x coord of {_2}:
           set {_x} to -1
       if y coord of {_1} > y coord of {_2}:
           set {_y} to -1
       if z coord of {_1} > z coord of {_2}:
           set {_z} to -1
      
       # As {_1} is the only one that is changed, I save it.
       # {_2} is used for base.
       set {_base1} to {_1}
      
       # Getting the blocks.
       # I'm not a big fan of whiles, so I just get the difference.
       loop abs(x coord of {_1} - x coord of {_2}) + 1 times:
           loop abs(z coord of {_1} - z coord of {_2}) + 1 times:
               loop abs(y coord of {_1} - y coord of {_2}) + 1 times:
          
                   # A list for each block
                   set {_b} to "%block at {_1}%"
                   add 1 to {_blocks::%{_b}%}

                   # The total blocks.
                   add 1 to {_total}
              
                   add {_y} to y coord of {_1}
              
               # Goes to the next Z and resets Y...
               add {_z} to z coord of {_1}
               set y coord of {_1} to y coord of {_base1}
          
           # Goes to the next X and resets Z...
           add {_x} to x coord of {_1}
           set z coord of {_1} to z coord of {_base1}
      
           # Optional waiting.
           # wait 1 tick

       set {_time} to (unix timestamp of now - {_u}) * 1000
       send " "
       send "&3&lCUBOID STATS"
       send "Blocks changed: &a%{_total}%"
       send "Cuboid took &a%{_time}%ms&f!"
       send " "
       send "Overall speed: &a%{_total} * 1000 / {_time}% blocks/s"
  
       # Gives you a fancier (not that much) message, so you don't get blind when you see it.
       set {_blocks} to ""
       loop {_blocks::*}:
           set {_blocks} to "%{_blocks}%&f, &a%loop-index%: &7%loop-value%"
       send "Block replaced: %last length of {_blocks} - 4 characters of {_blocks}%"
  
       send " "
 
Last edited:
  • Like
Reactions: KingAlterIV
Tested with Skript version 2.2-dev33 and skDragon version 0.14.0 on PaperSpigot_1.11.2

Could do without skDragon, just added particles for oomph :emoji_slight_smile:

code_language.skript:
# Positive X = East; Negative X = West;
# Positive Z = South; Negative Z = North;

options:
    wand: iron sword of unbreaking 10 named "&f&lSelection Wand"

on join:
    clear {playerdata::%player%::blockhistory::*}
# Clears and removes variables from particles for safety
    if {playerdata::%player%::visualizer::pointA} is set:
        set {_temp::*} to split "ABCDEFGHIJKL" at ""
        loop {_temp::*}:
            stopEffect "selectionvisualizer::pointA::%loop-value%::%player%"
        clear {playerdata::%player%::visualizer::pointB}
    if {playerdata::%player%::visualizer::pointB} is set:
        set {_temp::*} to split "ABCDEFGHIJKL" at ""
        loop {_temp::*}:
            stopEffect "selectionvisualizer::pointB::%loop-value%::%player%"
        clear {playerdata::%player%::visualizer::pointB}

on quit:
    clear {playerdata::%player%::blockhistory::*}
# Clears and removes variables from particles for safety
    if {playerdata::%player%::visualizer::pointA} is set:
        set {_temp::*} to split "ABCDEFGHIJKL" at ""
        loop {_temp::*}:
            stopEffect "selectionvisualizer::pointA::%loop-value%::%player%"
        clear {playerdata::%player%::visualizer::pointB}
    if {playerdata::%player%::visualizer::pointB} is set:
        set {_temp::*} to split "ABCDEFGHIJKL" at ""
        loop {_temp::*}:
            stopEffect "selectionvisualizer::pointB::%loop-value%::%player%"
        clear {playerdata::%player%::visualizer::pointB}
        
on leftclick:
    if player's tool is {@wand}:
        if clicked block is not air:
# Sets a point with a visual effect
            set {playerdata::%player%::pointA} to location of clicked block
            drawLine particle redstone, RGB 10, 0, 255, center location of block 1 north 1 west of clicked block, target location of block 1 north 1 east of clicked block, id "selectionvisualizer::pointA::A::%player%", onlyFor player, rainbowMode false, solid true, density 5, length 2, zigZag count 0, height 0, visibleRange 32, displacementXYZ 0, 2, 0, pulseDelay 1
            drawLine particle redstone, RGB 10, 0, 255, center location of block 1 north 1 east of clicked block, target location of block 1 south 1 east of clicked block, id "selectionvisualizer::pointA::B::%player%", onlyFor player, rainbowMode false, solid true, density 5, length 2, zigZag count 0, height 0, visibleRange 32, displacementXYZ 0, 2, 0, pulseDelay 1
            drawLine particle redstone, RGB 10, 0, 255, center location of block 1 south 1 east of clicked block, target location of block 1 south 1 west of clicked block, id "selectionvisualizer::pointA::C::%player%", onlyFor player, rainbowMode false, solid true, density 5, length 2, zigZag count 0, height 0, visibleRange 32, displacementXYZ 0, 2, 0, pulseDelay 1
            drawLine particle redstone, RGB 10, 0, 255, center location of block 1 south 1 west of clicked block, target location of block 1 north 1 west of clicked block, id "selectionvisualizer::pointA::D::%player%", onlyFor player, rainbowMode false, solid true, density 5, length 2, zigZag count 0, height 0, visibleRange 32, displacementXYZ 0, 2, 0, pulseDelay 1
            drawLine particle redstone, RGB 10, 0, 255, center location of block 1 north 1 west of clicked block, target location of block above clicked block, id "selectionvisualizer::pointA::E::%player%", onlyFor player, rainbowMode false, solid true, density 5, length 2, zigZag count 0, height 0, visibleRange 32, displacementXYZ 0, 2, 0, pulseDelay 1
            drawLine particle redstone, RGB 10, 0, 255, center location of block 1 north 1 east of clicked block, target location of block above clicked block, id "selectionvisualizer::pointA::F::%player%", onlyFor player, rainbowMode false, solid true, density 5, length 2, zigZag count 0, height 0, visibleRange 32, displacementXYZ 0, 2, 0, pulseDelay 1
            drawLine particle redstone, RGB 10, 0, 255, center location of block 1 south 1 east of clicked block, target location of block above clicked block, id "selectionvisualizer::pointA::G::%player%", onlyFor player, rainbowMode false, solid true, density 5, length 2, zigZag count 0, height 0, visibleRange 32, displacementXYZ 0, 2, 0, pulseDelay 1
            drawLine particle redstone, RGB 10, 0, 255, center location of block 1 south 1 west of clicked block, target location of block above clicked block, id "selectionvisualizer::pointA::H::%player%", onlyFor player, rainbowMode false, solid true, density 5, length 2, zigZag count 0, height 0, visibleRange 32, displacementXYZ 0, 2, 0, pulseDelay 1
            drawLine particle redstone, RGB 10, 0, 255, center location of block 1 north 1 west of clicked block, target location of block below clicked block, id "selectionvisualizer::pointA::I::%player%", onlyFor player, rainbowMode false, solid true, density 5, length 2, zigZag count 0, height 0, visibleRange 32, displacementXYZ 0, 2, 0, pulseDelay 1
            drawLine particle redstone, RGB 10, 0, 255, center location of block 1 north 1 east of clicked block, target location of block below clicked block, id "selectionvisualizer::pointA::J::%player%", onlyFor player, rainbowMode false, solid true, density 5, length 2, zigZag count 0, height 0, visibleRange 32, displacementXYZ 0, 2, 0, pulseDelay 1
            drawLine particle redstone, RGB 10, 0, 255, center location of block 1 south 1 east of clicked block, target location of block below clicked block, id "selectionvisualizer::pointA::K::%player%", onlyFor player, rainbowMode false, solid true, density 5, length 2, zigZag count 0, height 0, visibleRange 32, displacementXYZ 0, 2, 0, pulseDelay 1
            drawLine particle redstone, RGB 10, 0, 255, center location of block 1 south 1 west of clicked block, target location of block below clicked block, id "selectionvisualizer::pointA::L::%player%", onlyFor player, rainbowMode false, solid true, density 5, length 2, zigZag count 0, height 0, visibleRange 32, displacementXYZ 0, 2, 0, pulseDelay 1
            set {playerdata::%player%::visualizer::pointA} to now
            send "&7(&a!&7) &7Set point &aA&7 at location <tooltip:Click to teleport to this location.><cmd:/sktp %player% %x-coord of clicked block% %y-coord of clicked block% %z-coord of clicked block% %world of clicked block%>&f(%location of clicked block%)." to player
        
on rightclick:
    if player's tool is {@wand}:
        if clicked block is not air:
# Sets a point with a visual effect
            set {playerdata::%player%::pointB} to location of clicked block
            drawLine particle redstone, RGB 255, 0, 10, center location of block 1 north 1 west of clicked block, target location of block 1 north 1 east of clicked block, id "selectionvisualizer::pointB::A::%player%", onlyFor player, rainbowMode false, solid true, density 5, length 2, zigZag count 0, height 0, visibleRange 32, displacementXYZ 0, 2, 0, pulseDelay 1
            drawLine particle redstone, RGB 255, 0, 10, center location of block 1 north 1 east of clicked block, target location of block 1 south 1 east of clicked block, id "selectionvisualizer::pointB::B::%player%", onlyFor player, rainbowMode false, solid true, density 5, length 2, zigZag count 0, height 0, visibleRange 32, displacementXYZ 0, 2, 0, pulseDelay 1
            drawLine particle redstone, RGB 255, 0, 10, center location of block 1 south 1 east of clicked block, target location of block 1 south 1 west of clicked block, id "selectionvisualizer::pointB::C::%player%", onlyFor player, rainbowMode false, solid true, density 5, length 2, zigZag count 0, height 0, visibleRange 32, displacementXYZ 0, 2, 0, pulseDelay 1
            drawLine particle redstone, RGB 255, 0, 10, center location of block 1 south 1 west of clicked block, target location of block 1 north 1 west of clicked block, id "selectionvisualizer::pointB::D::%player%", onlyFor player, rainbowMode false, solid true, density 5, length 2, zigZag count 0, height 0, visibleRange 32, displacementXYZ 0, 2, 0, pulseDelay 1
            drawLine particle redstone, RGB 255, 0, 10, center location of block 1 north 1 west of clicked block, target location of block above clicked block, id "selectionvisualizer::pointB::E::%player%", onlyFor player, rainbowMode false, solid true, density 5, length 2, zigZag count 0, height 0, visibleRange 32, displacementXYZ 0, 2, 0, pulseDelay 1
            drawLine particle redstone, RGB 255, 0, 10, center location of block 1 north 1 east of clicked block, target location of block above clicked block, id "selectionvisualizer::pointB::F::%player%", onlyFor player, rainbowMode false, solid true, density 5, length 2, zigZag count 0, height 0, visibleRange 32, displacementXYZ 0, 2, 0, pulseDelay 1
            drawLine particle redstone, RGB 255, 0, 10, center location of block 1 south 1 east of clicked block, target location of block above clicked block, id "selectionvisualizer::pointB::G::%player%", onlyFor player, rainbowMode false, solid true, density 5, length 2, zigZag count 0, height 0, visibleRange 32, displacementXYZ 0, 2, 0, pulseDelay 1
            drawLine particle redstone, RGB 255, 0, 10, center location of block 1 south 1 west of clicked block, target location of block above clicked block, id "selectionvisualizer::pointB::H::%player%", onlyFor player, rainbowMode false, solid true, density 5, length 2, zigZag count 0, height 0, visibleRange 32, displacementXYZ 0, 2, 0, pulseDelay 1
            drawLine particle redstone, RGB 255, 0, 10, center location of block 1 north 1 west of clicked block, target location of block below clicked block, id "selectionvisualizer::pointB::I::%player%", onlyFor player, rainbowMode false, solid true, density 5, length 2, zigZag count 0, height 0, visibleRange 32, displacementXYZ 0, 2, 0, pulseDelay 1
            drawLine particle redstone, RGB 255, 0, 10, center location of block 1 north 1 east of clicked block, target location of block below clicked block, id "selectionvisualizer::pointB::J::%player%", onlyFor player, rainbowMode false, solid true, density 5, length 2, zigZag count 0, height 0, visibleRange 32, displacementXYZ 0, 2, 0, pulseDelay 1
            drawLine particle redstone, RGB 255, 0, 10, center location of block 1 south 1 east of clicked block, target location of block below clicked block, id "selectionvisualizer::pointB::K::%player%", onlyFor player, rainbowMode false, solid true, density 5, length 2, zigZag count 0, height 0, visibleRange 32, displacementXYZ 0, 2, 0, pulseDelay 1
            drawLine particle redstone, RGB 255, 0, 10, center location of block 1 south 1 west of clicked block, target location of block below clicked block, id "selectionvisualizer::pointB::L::%player%", onlyFor player, rainbowMode false, solid true, density 5, length 2, zigZag count 0, height 0, visibleRange 32, displacementXYZ 0, 2, 0, pulseDelay 1
            set {playerdata::%player%::visualizer::pointB} to now
            send "&7(&a!&7) &7Set point &aB&7 at location <tooltip:Click to teleport to this location.><cmd:/sktp %player% %x-coord of clicked block% %y-coord of clicked block% %z-coord of clicked block% %world of clicked block%>&f(%location of clicked block%)." to player
        
every second:
    loop all players:
# Clearing visual effects
        if {playerdata::%loop-player%::visualizer::pointA} is set:
            if difference between {playerdata::%loop-player%::visualizer::pointA} and now > 3 seconds:
                set {_temp::*} to split "ABCDEFGHIJKL" at ""
                loop {_temp::*}:
                    stopEffect "selectionvisualizer::pointA::%loop-value-2%::%loop-player%"
                clear {playerdata::%loop-player%::visualizer::pointA}
        if {playerdata::%loop-player%::visualizer::pointB} is set:
            if difference between {playerdata::%loop-player%::visualizer::pointB} and now > 3 seconds:
                set {_temp::*} to split "ABCDEFGHIJKL" at ""
                loop {_temp::*}:
                    stopEffect "selectionvisualizer::pointB::%loop-value-2%::%loop-player%"
                clear {playerdata::%loop-player%::visualizer::pointB}
 
command /sktp [<player>] [<number>] [<number>] [<number>] [<text>]:
    permission: skript.selection
    trigger:
        set {_w} to world("%arg-5%")
        teleport arg-1 to location(arg-2, arg-3, arg-4, {_w})
    
command /manualselection [<text>] [<number>] [<number>] [<number>] [<text>]:
    permission: skript.selection
    trigger:
        if arg-1 = "pointA":
            arg-2 is set
            arg-3 is set
            arg-4 is set
            if arg-5 is set:
                set {_w} to world("%arg-5%")
                set {playerdata::%player%::pointA} to location(arg-2, arg-3, arg-4, {_w})
                send "&7(&a!&7) &7Set point &aA&7 at location <tooltip:Click to teleport to this location.><cmd:/sktp %player% %x-coord of {playerdata::%player%::pointA}% %y-coord of {playerdata::%player%::pointA}% %z-coord of {playerdata::%player%::pointA}% %world of {playerdata::%player%::pointA}%>&f(%location of {playerdata::%player%::pointA}%)." to player
            else:
                send "&7(&a!&7) Usage /manualselection (pointA/pointB) (x) (y) (z) (world)" to player
        if arg-1 = "pointB":
            arg-2 is set
            arg-3 is set
            arg-4 is set
            if arg-5 is set:
                set {_w} to world("%arg-5%")
                set {playerdata::%player%::pointB} to location(arg-2, arg-3, arg-4, {_w})
                send "&7(&a!&7) &7Set point &aB&7 at location <tooltip:Click to teleport to this location.><cmd:/sktp %player% %x-coord of {playerdata::%player%::pointB}% %y-coord of {playerdata::%player%::pointB}% %z-coord of {playerdata::%player%::pointB}% %world of {playerdata::%player%::pointB}%>&f(%location of {playerdata::%player%::pointB}%)." to player
            else:
                send "&7(&a!&7) Usage /manualselection (pointA/pointB) (x) (y) (z) (world)" to player
        else:
            send "&7(&a!&7) Usage /manualselection (pointA/pointB) (x) (y) (z) (world)" to player

command /selection [<text>] [<number>] [<text>]:
    permission: skript.selection
    trigger:
        if arg-1 is "wand":
            give {@wand} to player
        if arg-1 is "analyze":
            if arg-2 is not set:
                if arg-3 is not set:
                    send "&7(&a!&7) &7Usage /selection analyze (number) &nor&7 (slow/normal/fast)" to player
            if arg-2 is a number:
                if arg-2 >= 150:
                    send "&7(&a!&7) &7Unsafe value input. This input will loop &f150 &7blocks per &fTICK&7." to player
                if arg-2 < 150:
                    analyzeSelection(player, {playerdata::%player%::pointA}, {playerdata::%player%::pointB}, arg-2)
            if arg-3 is "ultraslow":
                analyzeSelection(player, {playerdata::%player%::pointA}, {playerdata::%player%::pointB}, 1)
            if arg-3 is "slow":
                analyzeSelection(player, {playerdata::%player%::pointA}, {playerdata::%player%::pointB}, 10)
            if arg-3 is "normal":
                analyzeSelection(player, {playerdata::%player%::pointA}, {playerdata::%player%::pointB}, 20)
            if arg-3 is "fast":
                analyzeSelection(player, {playerdata::%player%::pointA}, {playerdata::%player%::pointB}, 30)
            if arg-3 is "ultrafast":
                analyzeSelection(player, {playerdata::%player%::pointA}, {playerdata::%player%::pointB}, 50)
        if arg-1 is "history":
            if {playerdata::%player%::blockhistory::*} is set:
                send "&8-----------------------------------------------------" to player
                loop {playerdata::%player%::blockhistory::*}:
                    send "&7➥ &f%loop-index%: &7%loop-value%" to player
                send "&8-----------------------------------------------------" to player
            if {playerdata::%player%::blockhistory::*} is not set:
                send "&8-----------------------------------------------------" to player
                send "&8&7➥ &fNo blocks loaded in history!" to player
                send "&8-----------------------------------------------------" to player

function analyzeSelection(p: player, pointA: location, pointB: location, speed: number):
    if world of {_pointA} != world of {_pointB}:
        send "&7&l(&5&l!&7&l)&7 Points are located in two different worlds!" to {_p}
        stop
    clear {playerdata::%{_p}%::blockhistory::*}
    set {_time} to now
    set {_world} to world of {_pointA}
# Takes given locations and finds new fixed cuboid points
    set {_x1} to floor(x-coordinate of {_pointA})
    set {_y1} to floor(y-coordinate of {_pointA})
    set {_z1} to floor(z-coordinate of {_pointA})
    set {_x2} to floor(x-coordinate of {_pointB})
    set {_y2} to floor(y-coordinate of {_pointB})
    set {_z2} to floor(z-coordinate of {_pointB})
    if {_z1} > {_z2}:
        set {_northZ} to {_z2}
        set {_southZ} to {_z1}
    if {_z1} < {_z2}:
        set {_northZ} to {_z1}
        set {_southZ} to {_z2}
    if {_x1} > {_x2}:
        set {_eastX} to {_x1}
        set {_westX} to {_x2}
    if {_x1} < {_x2}:
        set {_eastX} to {_x2}
        set {_westX} to {_x1}
    if {_y1} > {_y2}:
        set {_highestY} to {_y1}
        set {_lowestY} to {_y2}
    if {_y1} < {_y2}:
        set {_highestY} to {_y2}
        set {_lowestY} to {_y1}
    if {_x1} = {_x2}:
        set {_eastX} to {_x1}
        set {_westX} to {_x1}
    if {_y1} = {_y2}:
        set {_highestY} to {_y1}
        set {_lowestY} to {_y1}
    if {_z1} = {_z2}:
        set {_northZ} to {_z1}
        set {_southZ} to {_z1}
# Sets optimal cuboid selection points based off input locations
    set {_fixedpointA} to location({_westX}, {_lowestY}, {_southZ}, {_world})
    set {_fixedpointB} to location({_eastX}, {_highestY}, {_northZ}, {_world})
    broadcast "&7(&a!&7) &7Analyzing..."
# Adds the first block because it starts at this one...
    set {_currentlocation} to {_fixedpointA}
    add 1 to {_blockcount}
    set {_loopX} to {_westX}
    set {_loopY} to {_lowestY}
    set {_loopZ} to {_southZ}
    set {_block} to "%block at {_currentlocation}%"
    add 1 to {playerdata::%{_p}%::blockhistory::%{_block}%}
    add 1 to {_lagcounter}
# Loops the south-western-lowest most block until the it reaches the north-western-highest most block
# Loops west to east, south to north, then up the Z coordinate
    while {_currentlocation} != {_fixedpointB}:
        # Lag measures...
        if {_lagcounter} >= {_speed}:
            clear {_lagcounter}
            wait 1 tick
        if {_loopX} != {_eastX}:
            add 1 to {_blockcount}
            add 1 to {_loopX}
            set {_currentlocation} to location({_loopX}, {_loopY}, {_loopZ}, {_world})
            set {_block} to "%block at {_currentlocation}%"
            add 1 to {playerdata::%{_p}%::blockhistory::%{_block}%}
        if {_loopX} = {_eastX}:
            if {_loopZ} != {_northZ}:
                add 1 to {_blockcount}
                add 1 to {_lagcounter}
                set {_loopX} to {_westX}
                remove 1 from {_loopZ}
                set {_currentlocation} to location({_loopX}, {_loopY}, {_loopZ}, {_world})
                set {_block} to "%block at {_currentlocation}%"
                add 1 to {playerdata::%{_p}%::blockhistory::%{_block}%}
            else if {_loopZ} = {_northZ}:
                if {_loopY} < {_highestY}:
                    add 1 to {_blockcount}
                    add 1 to {_lagcounter}
                    set {_loopX} to {_westX}
                    set {_loopZ} to {_southZ}
                    add 1 to {_loopY}
                    set {_currentlocation} to location({_loopX}, {_loopY}, {_loopZ}, {_world})
                    set {_block} to "%block at {_currentlocation}%"
                    add 1 to {playerdata::%{_p}%::blockhistory::%{_block}%}
                else if {_loopY} >= {_highestY}:
                    broadcast "&7(&a!&7) &7Finished analyzing blocks! Took &a%difference between {_time} and now% &7to analyze."
    if {_currentlocation} = {_fixedpointB}:
        send "&4█&c█&6█&e█&2█&a█&b█&9█&1█&d█&5█&4█&c█&6█&e█&2█&a█&b█&9█&1█&d█&5█&4█&c█&6█&e█&2█&a█&b█&9█&1█&d█&5█&4█&c█" to {_p}
        send "&7➥ &fTotal blocks in selection: &7%{_blockcount}%" to {_p}
        send "&7➥ &fDifferent types of blocks: &7%size of {playerdata::%{_p}%::blockhistory::*}%" to {_p}
        send "&7➥ <tooltip:Click me!><cmd:/selection history>&7[Click to view types of blocks]" to {_p}
        send "&4█&c█&6█&e█&2█&a█&b█&9█&1█&d█&5█&4█&c█&6█&e█&2█&a█&b█&9█&1█&d█&5█&4█&c█&6█&e█&2█&a█&b█&9█&1█&d█&5█&4█&c█" to {_p}

# Positive X = East; Negative X = West;
# Positive Z = South; Negative Z = North;

Permissions: skript.selection
Commands:
/selection wand: gives you the selection wand
/selection analyze (1-149) or (ultraslow/slow/normal/fast/ultrafast): Analyzes your selection and gives basic info
/selection history: Shows types of block in your last selection history (If you have one)
/manualselection (pointA/pointB) (x) (y) (z) (world): Manually set a point without going there.

Maybe the next Skript Challenge could be an entire skript that will be uploaded as an official skunity resource. It could be something simple like an essentials / worldedit remake. The winner could be the one who does it the most efficient with variables and size.
 
Last edited:
  • Like
Reactions: Sashie
Last day for entries! Will begin judging them tonight :emoji_slight_smile:
 
Supports cube, round and linear shapes with a bit more info of it in output
Shows info about total amount of blocks, block type, amount of each block type, amount of chunks, the locations in chunks and container's items
size of ...
is only used in selected position count
Global variables are used to not use repeating code (ex. blocks() function would be repeated 2 times, in sphere and cuboid selections)
Selections are done with a wooden hoe

Code:
on load:
    clear {main::*}

#selection point stuff
function click(i: integer, b: block):
    set {main::pos::%{_i}%} to {_b}
    broadcast "Position %{_i}% has been set (x %x-coord of {main::pos::%{_i}%}%, y %y-coord of {main::pos::%{_i}%}%, z %z-coord of {main::pos::%{_i}%}%)"

#all the needed stuff for information about the block
function blocks(x: number, y: number, z: number):

    #counting total amount of blocks
    add 1 to {main::amount}
 
    #setting location (local)
    set {_location} to location({_x}, {_y}, {_z}, ({main::pos::1}'s world))
 
    #getting the block (local)
    set {_blockName} to "%block at {_location}%"

    #setting chunk (local)
    set {_chunk} to "%{_location}'s chunk%"
 
    #adding block type to a list by it's name
    if {main::blockTypes::%{_blockName}%} is not set:
        set {main::blockTypes::%{_blockName}%} to true
 
    #adding chunks to a list and counting amount
    if {main::blockChunks::%{_chunk}%} is not set:
        set {main::blockChunks::%{_chunk}%} to true
        add 1 to {main::blocksChunks::amount}
     
    #adding the blocks to a list, by their names in a chunk
    add block at {_location} to {main::blocks::%{_chunk}%::%{_blockName}%::*}
 
    #counting specific amount of blocks
    add 1 to {main::blockAmount::%{_blockName}%}

#checking which coordinate is higher where {_?2} is always bigger than {_?1}, then getting the length of the axis
function coordsAndAxis():
    if x-coord of {main::pos::1} > x-coord of {main::pos::2}:
        set {main::x1} to x-coord of {main::pos::2}
        set {main::x2} to x-coord of {main::pos::1}
    else:
        set {main::x1} to x-coord of {main::pos::1}
        set {main::x2} to x-coord of {main::pos::2}
    if y-coord of {main::pos::1} > y-coord of {main::pos::2}:
        set {main::y1} to y-coord of {main::pos::2}
        set {main::y2} to y-coord of {main::pos::1}
    else:
        set {main::y1} to y-coord of {main::pos::1}
        set {main::y2} to y-coord of {main::pos::2}
    if z-coord of {main::pos::1} > z-coord of {main::pos::2}:
        set {main::z1} to z-coord of {main::pos::2}
        set {main::z2} to z-coord of {main::pos::1}
    else:
        set {main::z1} to z-coord of {main::pos::1}
        set {main::z2} to z-coord of {main::pos::2}
    set {main::x} to {main::x2} - {main::x1} + 1
    set {main::y} to {main::y2} - {main::y1} + 1
    set {main::z} to {main::z2} - {main::z1} + 1

#axis length check
function length() :: strings:
    if {main::x} = 1:
        return "y" and "z"
    if {main::y} = 1:
        return "x" and "z"
    if {main::z} = 1:
        return "x" and "y"
    return {_none}

#shape perfection check
function perfect() :: boolean:
    if {main::x} != {main::y}:
        return false
    else if {main::x} != {main::z}:
        return false
    return true

#broadcast axis lengths
function axis():
    broadcast "Axis lengths:"
    broadcast "x - %{main::x}%", "y - %{main::y}%" and "z - %{main::z}%"

#new line
function space():
    broadcast ""
 
#position 1 selection
on leftclick with wooden hoe:
    clicked block is set
    cancel event
    click(1, clicked block)

#position 2 selection
on rightclick with wooden hoe:
    clicked block is set
    cancel event
    click(2, clicked block)

#arg-1 can be <cube", "rectangle" or "square"> or <"linear", "line" or "vector"> or <"sphere", "circle", "egg" or "round">
#arg-2 can be "detailed" or "simple"
command blocks [<text="cube">] [<text="detailed">]:
    trigger:

        #if positions are not set
        if size of {main::pos::*} != 2:
            send "Position(s) not set"
            stop
         
        #if world's of both positions are not the same
        if {main::pos::1}'s world != {main::pos::2}'s world:
            send "Positions' worlds are different"
            stop
         
        space()
     
        broadcast "&aUsed command /blocks %arg-1% %arg-2%"
     
        #cuboid stuff
        if arg-1 = "cube", "rectangle" or "square":
     
            #checking which coordinate is higher where {main::?2} is always bigger than {main::?1}, then getting the length of the axis
            coordsAndAxis()

            loop {main::y} times:
                loop {main::z} times:
                    loop {main::x} times:

                        #counting and doing shit with the block
                        blocks(({main::x1} - 1 + loop-value-3), ({main::y1} - 1 + loop-value-1), ({main::z1} - 1 + loop-value-2))

        #line stuff
        else if arg-1 = "linear" or "line":
            loop blocks from {main::pos::1} to {main::pos::2}:

                #counting and doing shit with the block
                blocks((x-coord of loop-value), (y-coord of loop-value), (z-coord of loop-value))
         
        #round stuff
        else if arg-1 = "sphere", "circle", "egg" or "round":
            #checking which coordinate is higher where {main::?2} is always bigger than {main::?1}, then getting the length of the axis
            coordsAndAxis()

            #getting the highest selection point to deduct numbers from
            set {_location} to location({main::x2}, {main::y2}, {main::z2}, world of {main::pos::1})

            #if it's a dot, we just input one block
            if {main::pos::1} = {main::pos::2}:
                blocks((x-coord of {_location}), (y-coord of {_location}), (z-coord of {_location}))
            else:
                #getting the middle block's location
                remove {main::x}/2 from x-coord of {_location}
                remove {main::y}/2 from y-coord of {_location}
                remove {main::z}/2 from z-coord of {_location}

                set {_block} to block at {_location}

                set {_radius} to max({main::x},{main::y},{main::z})/2

                loop blocks in radius {_radius} of {_block}:
                    x-coord of loop-value is between {main::x1} and {main::x2}
                    y-coord of loop-value is between {main::y1} and {main::y2}
                    z-coord of loop-value is between {main::z1} and {main::z2}
                    blocks((x-coord of loop-value), (y-coord of loop-value), (z-coord of loop-value))
#can be used for debug
#                    set loop-value to stone bricks
                 
        else:
            broadcast "just wrong input :( %arg-1%"
            stop
         
        space()

        #showing detailed stuff
        if arg-2 = "detailed":

            loop {main::blockTypes::*}:

                #Showing what's block
                broadcast "&6%loop-index-1%(s) at:"

                loop {main::blockChunks::*}:

                    #checking if the blockType in a chunk exists
                    {main::blocks::%loop-index-2%::%loop-index-1%::1} is set

                    #broadcasting chunk
                    broadcast " At %loop-index-2%:"

                    #looping the blocks in a chunk of a blockType
                    loop {main::blocks::%loop-index-2%::%loop-index-1%::*}:

                        #broadcasting the location of the block
                        broadcast "  &7%location of loop-value-3%"

                        #checking if the block is a container to show more info
                        if loop-value-3 = chest, furnace, dropper, hopper, brewing stand, dispenser or trapped chest:

                            #if the container has any items in it
                            if items in loop-value-3 is set:

                                broadcast "  &6Containing:"

                                #sets the amount of items it has in a list variable by it's name
                                loop items in loop-value-3's inventory:
                                    set {_item} to "%loop-value-4%"
                                    add 1 to {_chestInventory::%{_item}%}

                                #loops the list variable showing the amount of an item
                                loop {_chestInventory::*}:
                                    broadcast "   &7%loop-value-4% of %loop-index-4%"

                                #clears the var for another container
                                clear {_chestInventory::*}

                            else:
                                broadcast "   &6Empty"

                broadcast "&c-----------------------"
                space()
         
        #showing amounts of each block type
        loop {main::blockTypes::*}:
            broadcast "%{main::blockAmount::%loop-index%}% of %loop-index%"
         
        space()
         
        #total amount of chunks.
        broadcast "Total amount of chunks: %{main::blocksChunks::amount}%"
     
        #total amount of blocks
        broadcast "Total amount of blocks: %{main::amount}%"
     
        space()
     
        broadcast "Selection shape:"
     
        #1 block amount is a dot :^)
        if {main::amount} = 1:
            broadcast "dot"
        else:

            #cuboid stuff
            if arg-1 = "cube", "rectangle" or "square":
         
                #checking which length out of x, y, z is equal to 1 and setting the list var to other symbols
                #if none are equal to 1 returns none
                #ex. if x = 1, then return "y" and "z"
                set {_notCube::*} to length()
                if {_notCube::1} is not set:
                    if perfect() is true:
                        broadcast "perfect cube"
                    else:
                        broadcast "non-perfect cube (cuboid?)"
                else:
                    if {main::%{_notCube::1}%} = {main::%{_notCube::2}%}:
                        broadcast "square"
                    else:
                        broadcast "rectangle"
                space()
                axis()

            #line stuff
            else if arg-1 = "linear" or "line":
                if round(distance between {main::pos::1} and {main::pos::2}) = distance between {main::pos::1} and {main::pos::2}:
                    broadcast "straight line"
                else:
                    broadcast "wiggly/non-straight(?) line"
                space()
                broadcast "with length %distance between {main::pos::1} and {main::pos::2}%"

            #round stuff
            else if arg-1 = "sphere", "circle", "egg" or "round":
                #checking which length out of x, y, z is equal to 1 and setting the list var to other symbols
                #if none are equal to 1 returns none
                #ex. if x = 1, then return "y" and "z"
                set {_notSphere::*} to length()
                if {_notSphere::*} is set:
                    if {main::%{_notSphere::1}%} = {main::%{_notSphere::2}%}:
                        broadcast "perfect 2d circle"
                    else:
                        broadcast "2d egg"
                else:
                    if perfect() is true:
                        broadcast "perfect 3d sphere"
                    else:
                        broadcast "3d egg"
                broadcast "with radius %{_radius}%"
                space()
                axis()
            else:
                broadcast "Unknown shape.. This shouldn't happen. Hm :thonk:"


        #everything's done, so deleting stored information
        clear {main::*}
 
Last edited:
I coded it using the latest version of skript bensku's edit and a 1.11.2 server. No addons needed.
Use /tool to receive the selection tool. Rightclick any block to select the first corner, rightclick a second block to select the second corner. It will automaticly loop the area when the second corner is selected. If the selected area is bigger than 5.000 blocks, it will wait a tick when looping blocks to prevent your server from crashing.

code_language.skript:
# Main command to get the tool to select corners
command /tool:
    trigger:
        give player iron axe named "&ePoint Selection"

# When you rightclick using an iron axe:
on rightclick using iron axe:
# Axe's name is "&ePoint Selection":
    name of event-item contains "&ePoint Selection":
# It will continue only if the rightclicked block isn't air:
        event-block is not air:
# If this variable is not set means you are selecting point 1.
            {variable::p1} is not set:
# Setting the variable that refers to point 1 to the location of clicked block
                set {variable::p1} to event-block's location
                send "&7You successfully selected the point: &b##1"
# If the first corner is already set:
            else:
                send "&7You successfully selected the point: &b##2"
                send ""
                send "&7Operation started. Let me do my work..."
# Setting another var to the corner 1
                set {_p1} to {variable::p1}
# Deleting the main corner 1 variable so you will be able to do more than 1 process at the same time
                delete {variable::*}
# This variable contains the starting time
                set {_start-time} to now
# Positive coords
                set {_x} to (x-coord of {_p1} - (x-coord of event-block + 1))
                set {_y} to (y-coord of {_p1} - (y-coord of event-block + 1))
                set {_z} to (z-coord of {_p1} - (z-coord of event-block + 1))
# Negative number
                set {_sign::%{_x}%} to "-1" parsed as number
                set {_sign::%{_y}%} to "-1" parsed as number
                set {_sign::%{_z}%} to "-1" parsed as number
# It coord is negative
                if x-coord of {_p1} > x-coord of event-block:
# Negative coord
                    set {_x} to (x-coord of {_p1} - (x-coord of event-block - 1))
# Positive number
                    set {_sign::%{_x}%} to "+1" parsed as number
                if y-coord of {_p1} > y-coord of event-block:
                    set {_y} to (y-coord of {_p1} - (y-coord of event-block - 1))
                    set {_sign::%{_y}%} to "+1" parsed as number
                if z-coord of {_p1} > z-coord of event-block:
                    set {_z} to (z-coord of {_p1} - (z-coord of event-block - 1))
                    set {_sign::%{_z}%} to "+1" parsed as number
# Selection is bigger than 5000 blocks
                if abs({_x} * {_y} * {_z}) > 5000:
                    send ""
                    send " &7Too big selection (&a%abs({_x} * {_y} * {_z})% &7blocks)! Tick delay is activated for this selection."
# Looping the absolute value of x, y, z variables
                    loop abs({_z}) times:
                        loop abs({_y}) times:
                            loop abs({_x}) times:
                                wait 1 tick
# Adding the current looping block to a variable containing total blocks processed.
                                add block at {_p1} to {_blocks::*}
# Remove positive or negative number depending if the coord is negative or positive
                                remove {_sign::%{_x}%} from x-coord of {_p1}
# Sets the x coord to it's default value
                            add {_x} to x-coord of {_p1}
                            remove {_sign::%{_y}%} from y-coord of {_p1}
                        add {_y} to y-coord of {_p1}
                        remove {_sign::%{_z}%} from z-coord of {_p1}
# Selection is less than 5000 blocks
                else:
# Same as above but without the waiting tick
                    loop abs({_z}) times:
                        loop abs({_y}) times:
                            loop abs({_x}) times:
                                add block at {_p1} to {_blocks::*}
                                remove {_sign::%{_x}%} from x-coord of {_p1}
                            add {_x} to x-coord of {_p1}
                            remove {_sign::%{_y}%} from y-coord of {_p1}
                        add {_y} to y-coord of {_p1}
                        remove {_sign::%{_z}%} from z-coord of {_p1}
# Looping each block the variable contains
                loop {_blocks::*}:
# Setting a variable to the block
                    set {_blockType} to "%loop-value%"
# Adding 1 to the variable of the block if it's repeated
                    add 1 to {_blockCount::%{_blockType}%}
                set {_allBlockCounts} to ""
# Looping each value the variable contains contains
                loop {_blockCount::*}:
# Getting the block list, with a cool formating
                    set {_allBlockCounts} to "%{_allBlockCounts}%<tooltip:&7(&a%{_blockCount::%loop-index%}%&7)>&a%loop-index%&7, "
# Replacing some characters of the variable because I don't like them
                replace all "_" in {_allBlockCounts} with " "
# And the final message!
                send ""
                send "&a&lFINISHED! &7See the results:"
                send "&7Some of them contain tooltips."
                send ""
                send " &7Elapsed time: &a%difference between {_start-time} and now%"
                send " &7Number of blocks: &a%abs({_x} * {_y} * {_z})%"
                send " &7Block list: %{_allBlockCounts}%"
 
Challenge over. Thread locked. Winners will be announced within a day or two.
 
Status
Not open for further replies.