Page 1 of 1

Resolvers, how do they work?

Posted: Sat Mar 12, 2016 11:17 pm
by ibanix
For wiki stuff I need to understand code, and at the moment I'm at the "how the hell do resolvers work" place.

For example:

Code: Select all

function resolvers.rngrange(x, y)
	return {__resolver="rngrange",  __resolve_instant=true, x, y}
end
function resolvers.calc.rngrange(t)
	return rng.range(t[1], t[2])
end
Questions:

1) What's with the ___resolver? Is this a magic word defined somewhere?
2) What glue causes __resolver to connect to resolvers.calc.nameoffunction?
3) Same question for __resolve_instant, and what's with 'true'?

Also, for types like this:

Code: Select all

function resolvers.attachtinker(t)
	return {__resolver="attachtinker", __resolve_last=true, t}
end

function resolvers.calc.attachtinker(t, e)
....
end
4) Where did 'e' come from?

Thanks in advance.

Re: Resolvers, how do they work?

Posted: Sun Mar 13, 2016 12:12 am
by HousePet
1) I think this is just a property that is looked for when the final thing is resolved.

2) I presume it looks for the __resolver field and then uses that to find a resolves.calc.X function.

3) That means it is done first when there are multiple.

4) Not sure, but I'm guessing it is the object the tinker is attached to? Or maybe the tinker itself.

Re: Resolvers, how do they work?

Posted: Mon Mar 14, 2016 4:32 am
by Zizzo
[sound F/X: wiki diving] Hmm, the wiki's guide on resolvers is surprisingly sparse. Here's a rough overview:

newEntity{} defines basically a template of an entity. In Zone:makeEntity(), that template gets cloned and fleshed out into a full-fledged entity via Entity:resolve(). So say your entity definition has a field that you want to vary between entitles:

Code: Select all

newEntity {
  name = 'Silly example',
  silliness = rng.range(1, 10),
}
That won't work, because the field will be set in stone when the template is loaded and every copy will get the same value. Instead you use:

Code: Select all

newEntity {
  name = 'Silly example',
  silliness = resolvers.rngrange(1, 10),
}
which, as your code listing above shows, expands to:

Code: Select all

newEntity {
  name = 'Silly example',
  silliness = { __resolver="rngrange",  __resolve_instant=true, 1, 10 },
}
Then when an entity of this type is being created, Entity:resolve() walks the cloned template looking for anything shaped like a {__resolver} table and calls its associated resolvers.calc[__resolver]() method — in our case, resolvers.calc.rngrange(). The calc method gets called with two parameters: 't' is the {__resolver} table itself, which contains all the parameters passed to the original resolvers.whatever() call, and 'e' is the entity that's in the process of being resolved [in our example, resolvers.calc.rngrange() ignores its 'e' parameter because it doesn't need it]. The value returned from the calc method is assigned back to the field it comes from; if it's just a bare 'resolvers.something()' without a 'fieldname =' in front of it, you'll probably want to have the calc method return nil to delete the field.

Now the {__resolver} table returned by resolvers.whatever() can have a couple extra fields of interest:
  • __resolve_last: Entity:resolve() actually does two sweeps looking for {__resolver} tables, one at the very end. If your {__resolver} table includes __resolve_last=true, it will be processed in that second sweep; otherwise, it gets processed with everything else in the first sweep.
  • __resolve_instant: If your resolvers.calc.whatever() method returns something like another entity template that contains resolvers of its own, __resolve_instant=true tells Entity:resolve() to walk that return value immediately looking for more {__resolver} tables to resolve. I'm not sure why resolvers.rngrange() uses it, since it's just returning a number.

Re: Resolvers, how do they work?

Posted: Sat Mar 19, 2016 5:00 am
by ibanix
Zizzo, this is super helpful. Thank you.