Addons/script-engine/CCS Block Modify

When you edit the map from the scripts you must be aware of the bukkit system. The server allows only the main thread(?) to modify blocks, so the threaded scripts simply does not have permission to do that. On the other hand, however, the error is thrown, but the blocks usually got modified when I tested, just simply did not update the visual for the players. But you should not afraid, I took care of this synchronization problem. Even if I did, you should learn how it works, you will see why.

First of all, we start on that only the main thread can modify. I have no control over that, so it works that way and dot. If you ask for block modify (from script) then it gets queued in a synchronization queue. The queue is runned on every tick, so (on faster servers) it gets executed in 1/20 second. But that's a lot of time, especially, when you check the block and use it as requirement:

<sub>#</sub>01| b = p.loc.relative(0,-1,0).block
<sub>#</sub>02| b.material := @M.glass

This code turns the block under the player into glass. Then continue our codel like this:

<sub>#</sub>01| b = p.loc.relative(0,-1,0).block
<sub>#</sub>02| b.material := @M.glass
<sub>#</sub>03| if b.material=@M.glass p.tell:"Glass set!"
<sub>#</sub>04| else p.tell:"No glass yet :("

Running this code will tell you, that there is no glass yet, and the console will be sad. I think I have to tell you the explanation, why did this happen. The b.material is not a field, but a "value" that has getter and setter. Its modify would be asynchorous - call from out of main thread - so it would throw an error. The intelligent interface knows that, and puts the material-setter request to the synchronizer queue. No modify happens, when the line is processed. The if statement is evalueted, and as the block under the player 'p' wasn't glass already, it will be false, and run the false way instead of what we expected (that the block would be surely a glass block already). This is caused by the time delay between the script thread, and the synchronization, the check of the block happens before the block is actually set. (Remember, the block-to-glass request is waiting to be synchronized). As for gameplay, you will see, that the block is changed anyways, and you see no time delay. Because it is only one tick. As for the script code, one tick is a huge amount of time.

Handle delayed lines

Now, how will we solve this? There are two ways to do that, but both works the same way: we must wait for the modification, before we continue our code. Notice, that every time we wait it means 1 tick (1/20 sec). It may does not seems much, but ten block modify is a half second. 40 blocks is 2 second. But only if we wait for every single modify... let's see, how to handle it in code:

  • set script mechanism to wait sync

or

  • wait for sync manually

Scriptwise

First, let's see the first way. It requires only one line of code in the beginning of our code which is:

@S.syncmode = wait

After that line, the current script execution will switch into "wait-on-line" mode, and will not continue until a process of a line is fully completed, counting the synchronization too. Running the last code again having the line mentioned on its beginning will show us the results we expected, the block is glass, and the text says the same. Yaay.

Manually

Now, let's see the other one. I call this the "manual" way. The script is just works the same as before, and we call the wait our selves:

<sub>#</sub>01| b = p.loc.relative(0,-1,0)
<sub>#</sub>02| b.material := @M.glass
<sub>#</sub>03| @S.sync;
<sub>#</sub>04| if [email protected] p.tell:"Glass set!"
<sub>#</sub>05| else p.tell:"No glass yet :("

This way the second line registers the task to the queue (waiting for sync), then the third line makes the script thread sleep until the synchronization is complete.


Comments

Posts Quoted:
Reply
Clear All Quotes