DashingStrike / Automato-ATITD

Automato scripts for A Tale in the Desert
MIT License
5 stars 25 forks source link

error: attempt to index a string value (global 'settings') #169

Closed Cegaiel closed 5 years ago

Cegaiel commented 5 years ago

Many scripts use this include file: dofile("settings.inc");

This file is how we read/write settings to a file to be remembered for future sessions in a macro. Think of this behavior as cookies, for a web page.

These will save settings to a file with the name of the script. For example, mining_ore.lua will save settings to a file called Settings.mining_ore.lua.txt (both resides in the same folder, the 'scripts' folder'.

The bare minimum this file must have is:

return
{
}

An example of saved settings in a file looks something like:

return
{
    ["clickDelay"] = 100,
    ["dropdown_ore_cur_value"] = 1,
    ["dropdown_cur_value_key"] = 1,
}

I've heard of a handful of reports lately of when a player starts a macro and it immediately shows this error: attempt to index a string value (global 'settings'). No particular script, it's random, such as fishing.lua and mining_ore.lua.

I've been able to figure out that the solution to this error is to simply deleting the "settings" file. (Settings.luaScriptName.txt).

I'm not quite sure what causes this problem. It seems random and does not occur every often.

After some investigation, I have found 2 ways to force this error very easily.

  1. Have a blank file with (Settings.luaScriptName.txt).
  2. Have a file ((Settings.luaScriptName.txt)) that is not blank, but does not contain this format:
return
{
}

With some testing, I've found a reasonably simple solution (not fool-proof) , but for the most part, this should work when the file becomes corrupt (for whatever reason) and fix it.

    --Start: Check & Attempt to fix corrupt file
    --If file exists and is blank or does not have proper format:
    --return
    --{
    --}
    -- Then it will cause this error: "attempt to index a string value (global 'settings')

    local parsed = {};
    local outputFile = io.open("scripts/" .. filename,"r");
    for line in outputFile.lines(outputFile) do
      parsed[#parsed + 1] = line
    end
    outputFile:close();

    if parsed[1] ~= "return" then
    --sleepWithStatus(1000,"Format Error, Fixing!\n\nLine 1 does not say 'return'.", nil, 0.7, 0.7);
    outputFile = io.open("scripts/" .. filename,"w");
    outputFile:write("return\n{\n}");
    outputFile:close();
    end
    --End: Check & Attempt to fix corrupt file

When function deserialize(filename) is called from serialize.inc, -- usually when a script calls readSetting() -- ie autoWorkMine = readSetting("autoWorkMine",autoWorkMine);

What this new section of code does is (after verifying file exists):

  1. Open File and parse each line. Check if line 1 = "return"
  2. If return is not on line 1, then write "return\n{\n}"