Help with setting variables

Posted by Abellio on Tue 15 Aug 2006 02:55 AM — 9 posts, 30,941 views.

#0
Ok, I have a table that I'm trying to seralize into a variable but it is just not changing the value of the variable. At first I thought there was something wrong if the table so I change it to add a normal string and it still didn't change the variable. I don't know what is wrong with it.

This is the table I'm trying to serialize:


health_stats = {
	health = 1000,
	mana = 1000,
	endurance = 1000,
	willpower = 1000,
	blood = 100,
	max_health = 1000,
	max_mana = 1000,
	max_endurance = 1000,
	max_willpower = 1000
}

function save_tables(a, b, c)
	SetVariable("sr_health_stats", serialize('health_stats'))
	Note("Table saved")
end -- function


I have printed the output from the serialization code and it is this:

Quote:

health_stats = {}
health_stats.max_mana = 1000
health_stats.max_willpower = 1000
health_stats.mana = 1000
health_stats.blood = 100
health_stats.health = 1000
health_stats.endurance = 1000
health_stats.max_health = 1000
health_stats.willpower = 1000
health_stats.max_endurance = 1000
Table saved


Anyone know what the problem is?
Australia Forum Administrator #1
Seems to work for me. Are you calling the function save_tables ? Is this in a plugin? If so, the plugin variables are in a different "script space" than the main world variables. Try this:



health_stats = {
	health = 1000,
	mana = 1000,
	endurance = 1000,
	willpower = 1000,
	blood = 100,
	max_health = 1000,
	max_mana = 1000,
	max_endurance = 1000,
	max_willpower = 1000
}

function save_tables(a, b, c)
	SetVariable("sr_health_stats", serialize('health_stats'))
	Note("Table saved")
end -- function

save_tables ()

print (GetVariable ("sr_health_stats"))


When I run that exact code, I get:


Table saved
health_stats = {}
  health_stats.max_mana = 1000
  health_stats.max_willpower = 1000
  health_stats.mana = 1000
  health_stats.blood = 100
  health_stats.health = 1000
  health_stats.endurance = 1000
  health_stats.max_health = 1000
  health_stats.willpower = 1000
  health_stats.max_endurance = 1000

#2
The save_tables function is in a plugin along with an alias that calls it and the table itself is in a seperate .lua file. It seems to save the table while the session is still running but as soon as I close the session it clears the variable and I cannot load it back in at all.
Australia Forum Administrator #3
Quote:

... the table itself is in a seperate .lua file ...


I'm not quite sure what you mean by that. Once the table is serialized it will be in a variable, so in what way is that a separate .lua file?

I have demonstrated that the serialization definitely sets the variable, so the problem is what you are doing with that variable. Perhaps the plugin is not saving its state, for example.

I would need to see the whole plugin, to see what order you are doing things. If you can make a cut-down version that just demonstrates the problem, that would be good.
#4
Here's the plugin:


<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE muclient>

<muclient>
<plugin
  name="test"
  author="Abellio"
  id="8c8ae9ae978d7ff856821eac"
  language="Lua"
  purpose="test"
  save_state="y"
  date_written="2006-12-08 5:21:12"
  requires="3.7"
  version="1.1"
>
</plugin>

<aliases>
	<alias
		name="save"
		regexp="y"
		enabled="y"
		match="save"
		script="save_tables">
	</alias>
	<alias
		name="load"
		regexp="y"
		enabled="y"
		match="load"
		script="load_tables">
	</alias>
</aliases>

<script>
<![CDATA[

require(path .. 'modules\scripts\serialize.lua')
require(path .. 'modules\scripts\lookups.lua') -- < Tables located in this file

function save_tables(a, b, c)
	SetVariable("sr_health_stats", serialize('health_stats'))
	print (GetVariable("sr_health_stats"))
end -- function

function load_tables(a, b, c)
	loadstring(GetVariable("sr_health_stats"))
end -- function


]]>
</script> 
</muclient>
Australia Forum Administrator #5
Hmm, this has been interesting to track down. I had to add a bit of debugging as it is hard to see what Lua variables are inside a plugin, as they have their own address space.

It turns out your problem is in the loadstring line. The documentation for loadstring says:


Parses the string and returns the compiled chunk as a function. Does not execute it.


The sentence "does not execute it" is the key. You need to run the returned function. Also it is helpful to do an assert in case the loadstring fails, as it will fail silently. This modification fixes both problems:


function load_tables(a, b, c)
	assert (loadstring(GetVariable("sr_health_stats"))) ()
end -- function


The assert confirms that the loadstring worked, and the final brackets run the returned function.

What I would be doing is doing the load and save in the appropriate callbacks, that makes them completely automatic. This example modification shows the idea:


<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE muclient>

<muclient>
<plugin
  name="test"
  author="Abellio"
  id="8c8ae9ae978d7ff856821eac"
  language="Lua"
  purpose="test"
  save_state="y"
  date_written="2006-12-08 5:21:12"
  requires="3.7"
  version="1.1"
>
</plugin>

<aliases>
    <alias
		enabled="y"
		match="tprint"
		script="print_tables">
	</alias>
    <alias
		enabled="y"
		match="blood *"
		script="change_blood">
	</alias>
</aliases>

<script>
<![CDATA[

-- calculate plugin directory from where the plugin is located
_, _, path = string.find (GetPluginInfo (GetPluginID (), 6), "(.*\\)[%a_]+%.xml") 

require(path .. 'serialize.lua')
require(path .. 'lookups.lua') -- < Tables located in this file

function OnPluginSaveState()
	SetVariable("sr_health_stats", serialize('health_stats'))
end -- function

function OnPluginInstall()
	assert (loadstring(GetVariable("sr_health_stats") or "")) ()
end -- function

function print_tables()
    if type (health_stats) == "table" then
    	table.foreach (health_stats, print)
    else
        print ("health_stats is type: " .. type (health_stats))
    end -- if
end -- function

function change_blood (name, line, wildcards)
  health_stats.blood = tonumber (wildcards [1])
  print ("health_stats.blood now " .. health_stats.blood)
end -- function

]]>
</script> 
</muclient>



This example uses OnPluginInstall to load the variable from the state file. It also has the extra bit:


or ""


This takes care of the initial time, when the variable won't exist in the state file.

Then it uses OnPluginSaveState to serialize back, just before the plugin saves its state.

My example plugin has a "blood x" alias so you can change one of the variables and confirm it stays changed next time you load the plugin.

The "tprint" alias shows the contents of the table so you can see that it is changed.

I am also calculating the path from the path of whereever the plugin is installed.

You realize of course that the file "lookups.lua" will load the initial values for the table, after that they will be serialized in from the state file.
Amended on Tue 15 Aug 2006 10:09 PM by Nick Gammon
Australia Forum Administrator #6
Quote:

<alias
name="save"
regexp="y"
enabled="y"
match="save"
script="save_tables">
</alias>


You also want to be a bit cautious with regular expressions. I know this is just a test, but your example alias here, which had regular expressions checked, will match any line with "save" in it. For example, if you typed:


say I think I have saved my changes


That line has "save" in it, so it would run the alias and not get sent to the MUD.

Australia Forum Administrator #7
I thought there was an easier way of finding the plugin directory. This will do it, from version 3.76 onwards:


path = GetPluginInfo (GetPluginID (), 20)


The help file had not been updated, this will be corrected in the next version.
#8
It worked! Yay! Thanks.