News:

Want to praise Simutrans?
Your feedback is important for us ;D.

Script tools get stuck and no longer show popups

Started by Yona-TYT, December 27, 2024, 11:06:04 AM

Previous topic - Next topic

0 Members and 3 Guests are viewing this topic.

Yona-TYT

This is a strange bug when combining rules with script tools, it seems that the forbidden rules are causing the tols scripts to get stuck, and to unblock them you have to change tools, click with it and then go back to the script tool.

prissi

Since "is_tool_allowed" can affect tool selection, I see somehow how this could happen. But does this happens also with the area rules? Can you give a bit more details or a test case?

Yona-TYT

It's a bit tricky to replicate.

There was one case where the two-click tool stopped working correctly and didn't show the cursor marks, I loaded a new game and it was still the same, I changed tools and it was still the same, in the end I had to restart simutrans to get it working again.

I was testing in server mode so maybe that's what's causing me problems, but the script tools should work fine in server mode, right?.

QuoteCan you give a bit more details or a test case?
I still don't know how to replicate this easily and the scripts I have are somewhat complicated.

prissi

There are many function which need to return quickly and must not call other GUI or debug output functions. See below.

Also, your test scripts are strange, they restart whenever they fail while the test scripts in the folder test properly terminate when they encouter an error. Maybe this is related too.

Finally, if you run the tools locally on the server, it is possible that the is_tool_allowed queries again the script and could cause the deadlock. Not sure, the scenarios in online games were never tested that much.

Also, did you do as the documentation said for these functions (and any callback fuction from the Simutrans main programm like recieving a messge if implemented):
void    resume_game ()
string    get_map_file ()
string    get_api_version ()
bool    is_tool_allowed (integer pl, integer tool_id, way_types wt, any_x name)
string    is_work_allowed_here (integer pl, integer tool_id, coord3d name, any_x pos)
string    is_schedule_allowed (integer pl, schedule_x schedule)
string    is_convoy_allowed (integer pl, convoy_x convoy, depot_x depot)
string    jump_to_link_executed (coord3d pos)
bool    init (player_x pl)
bool    exit (player_x pl)
void    is_valid_pos (player_x pl, coord3d pos, coord3d start)
Never call and map altering functions (and no GUI functions) from these tools. Including debug function.

Andarix

There are various tools that are restricted for normal players in network games. Among them is the climate tool.

There are also comments in the files that say that it does not work in network mode.

Yona-TYT

Quote from: prissi on December 28, 2024, 12:45:52 AMThere are many function which need to return quickly and must not call other GUI or debug output functions. See below.
When I say "popup message" I don't mean using a GUI, but rather it's the message that script tools display if the return value is not null.

Quote from: prissi on December 28, 2024, 12:45:52 AMAlso, your test scripts are strange, they restart whenever they fail while the test scripts in the folder test properly terminate when they encouter an error. Maybe this is related too.
Although this is not the case, it is a different script from those.

Quote from: prissi on December 28, 2024, 12:45:52 AMFinally, if you run the tools locally on the server, it is possible that the is_tool_allowed queries again the script and could cause the deadlock. Not sure, the scenarios in online games were never tested that much.

This does seem suspicious.

Quote from: prissi on December 28, 2024, 12:45:52 AMNever call and map altering functions (and no GUI functions) from these tools. Including debug function.
Yes, I only call construction functions or commands from is_scenario_complete()

Yona-TYT

#6
I finally found an easier way to replicate, the steps are as follows.

  • Load the savegame. rules-and-tools.sve
  • Start the scenario "rules-and-tool" by checking the box for server mode.
  • Use the "script_remove_label" tool repeatedly on the text labels on the map, it should show a message with a number the first few times, then it will get stuck  and no longer show messages.


The script tool and scenario here: script-and-tool-scr.zip

The only thing the scenario does is apply a rule where remove_tool and other tools are prohibited.


Edit.
This also affects the two-click tools, although in this case it is even stranger and more confusing, the messages get stuck and no matter how much you try to force it to show a different message, the tool keeps showing the previous message.
I had already mentioned this here before:
Quote from: Yona-TYT on December 17, 2024, 01:31:30 PMThere also seems to be a bug in the script tools with the popup messages, it seems that the buffer is not cleared correctly, so the previous popup message continues to appear, but without affecting the execution of the tool.

prissi

It cannot open more than 3 windows, but it did not cease to operate from me. SOmetimes showing a 1 sometimes a 3.

Yona-TYT

Quote from: prissi on December 28, 2024, 02:37:56 PMIt cannot open more than 3 windows, but it did not cease to operate from me. SOmetimes showing a 1 sometimes a 3.
Ok, I've already found out what exactly causes it.

local t =  tile_x(pos.x, pos.y, pos.z)
local lab =t.find_object(mo_label)
if(lab){
t.remove_object(player, mo_label)         
return "1"
}

return "2"

If you click on the map without a text label the message should always be "2", but if the condition is met, then the script tool get stuck and no longer displays any more messages.

Please replace the tool with this more simplified one and try again: script_remove_label.zip


prissi

It never removes the object, neither in network play nor normally. But in networkplay, the commands are queued to the server processing queue before they are processed. But instead testing locally like on the client, it queued the commands anyway. Fixed in r11545.

Also I think you should change the current player to whatever number you want in your scenario. I started as public player, it stays as public player. (And for networkgames, you must allow player change ... )

An error message for simple forbid tools would be helpful too. Added in r11546.

Yona-TYT

#10
Quote from: prissi on December 29, 2024, 02:27:53 AMIt never removes the object, neither in network play nor normally. But in networkplay, the commands are queued to the server processing queue before they are processed. But instead testing locally like on the client, it queued the commands anyway. Fixed
in r11545.

Excellent, it seems that it is already solved.



I was hoping this one would be fixed too, but it seems to be a completely different issue:
Quote from: Yona-TYT on December 28, 2024, 11:43:13 AMThis also affects the two-click tools, although in this case it is even stranger and more confusing, the messages get stuck and no matter how much you try to force it to show a different message, the tool keeps showing the previous message.
I had already mentioned this here before:

This one is even stranger, you don't need to load a scenario or start server mode.

In this case the message gets stuck and will keep appearing when the return is null.

I posted a debug message to check this and there is indeed a bug:
Script: Print:    SCRIPT TOOL: message called. 0 :: null
Script: Print:    SCRIPT TOOL: message called. 0 :: null
Script: Print:    SCRIPT TOOL: message called. 2 :: tile_x@95,323,0
Script: Print:    SCRIPT TOOL: message called. 0 :: null
Script: Print:    SCRIPT TOOL: message called. 0 :: null

In condition 0 the return is null so there will be no message, 2 means that you are on a "This building is the town hall", and the message will be displayed.
The next times that the condition is 0 (with return null), the previous message will keep appearing.

If you change tools and click back to the script tool you will notice that the message is still stuck.

To replicate you can use the previous savegame: https://forum.simutrans.com/index.php?action=dlattach;attach=34235

Select the "script_mark_test.zip" tool and try to mark a rectangle inside the city but making the edges pass over the town hall as seen in the image, a message "This building is the town hall" will appear, and the debug should show something like "Script: Print: SCRIPT TOOL: message called. 2 :: tile_x@95,323,0"
photo_2024-12-29_07-09-50.jpg


Now mark a new rectangle, this time the edges should not touch the town hall or tourist attractions, as seen in the image, then the previous message will still appear, but the debug will show that the return is null , something like this "Script: Print: SCRIPT TOOL: message called. 0 :: null".

photo_2024-12-29_07-10-43.jpg

By the way, the minimum size of a rectangle is 4x4, less than that will not mark anything.

prissi

The script tools in networkmode for allowed commands queues the commands. It never gets the return result, as the queuing returns immediately. It is impossible for the script tool to wait for a return value in networkmode. You can query the map and hope for the best, but that's it.

It is probably not that easy as one would need to suspend the script tool until a return result has been obtained asynchroniously. But I do not know enough about the implementation to do that in a short time frame.

Yona-TYT

Quote from: prissi on December 29, 2024, 12:24:32 PMThe script tools in networkmode for allowed commands queues the commands. It never gets the return result, as the queuing returns immediately. It is impossible for the script tool to wait for a return value in networkmode. You can query the map and hope for the best, but that's it.

It is probably not that easy as one would need to suspend the script tool until a return result has been obtained asynchroniously. But I do not know enough about the implementation to do that in a short time frame.
No, this bug seems to be in local mode, you don't need to start the server for this.

prissi

I am not sure what you want to achieve. The function mark_tiles is not allowed to do any map changing interaction or GUI call, it should just mark tiles. Any interaction is to be done in do_work().

/**
 * no return value
 */
function mark_tiles(pl, start, end)
{
    local l = min(start.x, end.x)
    local r = max(start.x, end.x)
    local b = min(start.y, end.y)
    local t = max(start.y, end.y)

    for(local xx=l; xx<=r; xx++) {
        for(local yy=b; yy<=t; yy++) {
            mark_tile(square_x(xx,yy).get_ground_tile())
        }
    }
}

function init(pl)
{
    return true
}

function do_work(player, start, end)
{
    return null
}


function exit(pl)
{
    return true
}

This function does exactly what it should, also marking from 2x1 onwards. Unmarking will be automatically and done before do_work.

Yona-TYT

Quote from: prissi on December 29, 2024, 01:32:55 PMI am not sure what you want to achieve. The function mark_tiles is not allowed to do any map changing interaction or GUI call, it should just mark tiles. Any interaction is to be done in do_work().

/**
 * no return value
 */
function mark_tiles(pl, start, end)
{
    local l = min(start.x, end.x)
    local r = max(start.x, end.x)
    local b = min(start.y, end.y)
    local t = max(start.y, end.y)

    for(local xx=l; xx<=r; xx++) {
        for(local yy=b; yy<=t; yy++) {
            mark_tile(square_x(xx,yy).get_ground_tile())
        }
    }
}

function init(pl)
{
    return true
}

function do_work(player, start, end)
{
    return null
}


function exit(pl)
{
    return true
}

This function does exactly what it should, also marking from 2x1 onwards. Unmarking will be automatically and done before do_work.
Yes, the function works fine, the problem is the return messages.


function message(val){
    mark_list = {}
    tile_list = {}

    print("SCRIPT TOOL: message called. " + val.nr + " :: " + val.t)

    switch (val.nr) {
        case 0:
            return null
            break
        case 1:
            return "It is not suitable terrain "+ "("+coord3d_to_string(val.t)+")."
            break

        case 2:
            return "This building is the town hall "+ "("+coord3d_to_string(val.t)+")."
            break

        case 3:
            return "This building is privately owned "+ "("+coord3d_to_string(val.t)+")."
            break

        case 4:
            return "Only public service can use this tool."
            break
    }
    return ""
}

Call here:
    local result = message(check_list(player))
If the case is 0 , the return is null so no message will be displayed.

If the case is other than 0 , one of those messages will appear, but on the next attempt if the case is zero again, a message will still be displayed, but this should not happen since the return is null.

The debug message will  indicate that the return is indeed null.
print("SCRIPT TOOL: message called. " + val.nr + " :: " + val.t)

prissi

You can only use the tiles and build your list of tiles in do_work. The last coordinates of mark_tiles might not be the same as in do_work. I still do not get where the error is. Marking tiles work and the function does not seem to do anything useful (that I understand) in do_work

By the way, to mark the outsides of a rectangle, you can use this code.
function mark_tiles(pl, start, end)
{
local l = min(start.x, end.x)
local r = max(start.x, end.x)
local b = min(start.y, end.y)
local t = max(start.y, end.y)

if((r-l)>1  &&  (t-b)>1) {
for(local x=l; x<=r; x++) {
local t_a = square_x(x,b).get_ground_tile()
local t_b = square_x(x,t).get_ground_tile()
if (t_a && t_b) {
if((r-l) > 1 && (t - b) > 1){
mark_tile(t_a)
mark_tile(t_b)
}
}
}
for(local y=b; y<=t; y++) {
local t_a = square_x(l,y).get_ground_tile()
local t_b = square_x(r,y).get_ground_tile()
if (t_a && t_b) {
mark_tile(t_a)
mark_tile(t_b)
}
}
}
else {
for(local xx=l; xx<=r; xx++) {
for(local yy=b; yy<=t; yy++) {
mark_tile(square_x(xx,yy).get_ground_tile())
}
}
}
}

Yona-TYT

Quote from: prissi on December 29, 2024, 02:02:48 PMI still do not get where the error is.

Watch the video below, the first popup is fine, but the following ones are not, because the return is null.

prissi

The was an error that the return string was static. So when there was nothing returned, the return string did not update.

Anyway, here is a much cleaned up version of your tool

Yona-TYT

Quote from: prissi on December 29, 2024, 02:37:49 PMThe was an error that the return string was static. So when there was nothing returned, the return string did not update.
Thank you very much Prissi, you have no idea how much confusion that bug caused me. :o

Quote from: prissi on December 29, 2024, 02:37:49 PMAnyway, here is a much cleaned up version of your tool
Great! Thank you very much for that!.

I'm moving this to resolved. ;)