PDA

View Full Version : DB.setValue() Fails to Write 0-value to db.xml in Client



Minty23185Fresh
February 23rd, 2019, 20:16
This seems like a bug to me, if not, it certainly is an irksome inconsistency between the client and the host. It elicits all sorts of misconstrued "random" behavior.

As part of my Druid Wild Shapes Implementor extension I save several values to the DB using setValue() prior to changing the Druid's stats to that of the NPC. It makes for easy reversion back from Wild Shape to Druid. Some of those saved values are numbers with a value of zero.

When testing during early development I usually do it in the host instance. Then once things are good, if needed, I test in client instance using localhost.

Everything was great in host. But when I went to client, things were radically wrong.

After several hours of head scratching I determined the issue to be, a host instance of this:


DB.setValue(node, "sizeBeforeWS", "number", nSize);
Would write a 0-value nSize to the db.xml file. But if executed in the client, the XML element:


<sizeBeforeWS type="number">0</sizeBeforeWS>
would be missing from the db.xml file.
This was exacerbated by error trapping of this nature:


local nValue = DB.getValue(node, "sizeBeforeWS", nil);
if nValue == nil then
return;
end

To complicate this, 0-value fields of builtin controls are written in either instance, it is just those added by user extensions that are discriminated against.

A final note: As I was writing this up it dawned on me... Please do tell me it is because of the camel casing of my XML tags, that would really make me a sad panda. Aargh!

Ckorik
February 23rd, 2019, 20:41
A hack would be to check for a 0 value and make it something way out of bounds - then on read if the number is that specific out of bounds number change it to 0?

if (sizeBeforeWS == 0) then sizeBeforeWS = 8675309;

Minty23185Fresh
February 23rd, 2019, 21:42
A hack would be to check for a 0 value and make it something way out of bounds - then on read if the number is that specific out of bounds number change it to 0?

if (sizeBeforeWS == 0) then sizeBeforeWS = 8675309;

I would choose 42, since it is the answer to everything. But that’s just me as I hitchhike across the galaxy...

Ikael
February 23rd, 2019, 22:46
First make sure that client is owner of the record, otherwise client cannot write anything to it. Easy way to debug is to open console with /console slash command as client and run the code which should write something. You would get warning if client does not have permission to write.

Minty23185Fresh
February 23rd, 2019, 23:03
First make sure that client is owner of the record, ...
The client is the owner. It is in the character sheet.
[EDIT] Oops, that was a bit terse! Thank you Ikael, but...

Let’s take size as a string instead.
I can write:


DB.setValue(node, “size”, “string”, sWSSize);
DB.setValue(node, “sizeBeforeWS”, “string”, sDruidSize);

just fine. And they’re both in the db.xml file.

But if they were both type number instead and equal to zero, then

<size type=“number”>0</size>
would be in the file, but

<sizeBeforeWS type=“number”>0</sizeBeforeWS>
would not be, if it’s was client.
But for host both are.

celestian
February 24th, 2019, 01:03
I assume if the value is not 0 that it saves it to the node?

If so, use something like DB.getValue(node,"record_name",0);. That will return 0 if the node doesn't have a value. I don't know the entire use case but that should work if I understand what you're doing.

Minty23185Fresh
February 24th, 2019, 03:40
I assume if the value is not 0 that it saves it to the node?

If so, use something like DB.getValue(node,"record_name",0);. That will return 0 if the node doesn't have a value. I don't know the entire use case but that should work if I understand what you're doing.
Thanks celestian, to answer your questions:
1) Non zero values save just fine, host and client.
2) use zero as default return of setValue(), is exactly what I have had to do.
3) understand... yes, most assuredly you do.

But we’re dancing around the issue. There are two suggestions for work-arounds now. In my mind work-around usually smacks of bug. Is this a bug or not?

For execution in the host, this whole discussion is moot. There is no problem, no work-around is necessary. But if executed in the client, different behavior is exhibited. And it is based on a single value (zero) of a single type (number).

The behavior is very much similar to trying to write a nil to the DB. IIRC,


local value = nil;
DB.setValue(node, mySubNode, myType, value);


does not throw any sort of error, it essentially just does nothing. Nothing is written to the DB, either in client or host instance. If you do that with a zero value of type number on the client, you get the same outcome. Does that really sound like desirable behavior?

celestian
February 24th, 2019, 03:49
I'm pretty sure it's not a bug but intended. The way it works is if there is no "value" for that type it doesn't create the node. I think it does the same if you save a string node with a value of "" tho I might be misspeaking and it's only if it's nil (or both).

Minty23185Fresh
February 24th, 2019, 05:38
I'm pretty sure it's not a bug but intended. The way it works is if there is no "value" for that type it doesn't create the node. I think it does the same if you save a string node with a value of "" tho I might be misspeaking and it's only if it's nil (or both).
Aargh! I've gone round-and-round on this now, to the point that I'm confused as well as having confused everyone else. Sorry.

celestian, not quite. That is true of strings, but not numbers.

Below are three sets of properties for the hit points in the <charsheet> section of the db.xml file (5E ruleset).

For this first set, the extension's write routine is being executed in the client, I have not wild shaped the Druid so I don't expect to see my fields in this section of XML. This is for reference, a starting point.

<hp>
<temporary type="number">0</temporary>
<total type="number">30</total>
<wounds type="number">10</wounds>
</hp>

For second set, the write routines are being executed in the client, after wild shaping the Druid. I expect to see three of my extension's fields in the XML, <tempBeforeWS>, <totalWS> and <woundBeforeWS>.

<hp>
<temporary type="number">9</temporary>
<total type="number">30</total>
<totalWS type="number">9</totalWS>
<woundBeforeWS type="number">10</woundBeforeWS>
<wounds type="number">0</wounds>
</hp>

And finally the third set. Written from routines executed in the host. Again after wild shaping, so I expect to see the three fields, <tempBeforeWS>, <totalWS> and <woundBeforeWS>.

<hp>
<tempBeforeWS type="number">0</tempBeforeWS>
<temporary type="number">9</temporary>
<total type="number">30</total>
<totalWS type="number">9</totalWS>
<woundBeforeWS type="number">10</woundBeforeWS>
<wounds type="number">0</wounds>
</hp>



Now to restate what I said originally.
(1)Notice that 0-valued builtin, or ruleset, control properties <temporary> in the first set and <wounds> in the 2nd and 3rd data sets are written to the XML regardless of whether the extension is executing in the client or the host.

(2) But, my extension's 0-valued property <tempBeforeWS> is not written to the XML file if the extension executes in client (2nd data set). Whereas the same 0-valued property is written to the XML if the extension code executes in host (3rd data set).