It’s also perhaps worth mentioning that in 1.8 I have removed the table attribute type.
When you declared a table attribute it meant using an object as the value and that meant you could nest value arbitrarily deep by using lists or objects as values in the table.
Now there’s nothing especially wrong with that except… updating nested attributes was a pain. You had to read the attribute value, reach inside it and update it, then put the whole object attribute value back again. In Clojure this is idiomatic, in Javascript it’s painful.
That’s how I ended up with the composition-over-nesting strategy and why _id attributes are treated in a special way to make it easier to work with composed elements.
So instead of:
@actor player {
attributes: {
strength: 10
dexterity: 14
constitution: 11
intelligence: 18
wisdom: 7
charisma: 16
}
inc_strength: function() {
const attrs = this.attributes;
attrs.strength += 1;
this.attributes = attrs;
}
}
A situation that got worse the more nested your structure was (for example strength might itself be a nested table with current_value, maximum_value, modifier, and so on). Using element composition you would express the same thing as:
@actor player {
attributes_id: #player_attributes
inc_strength: function() {
this.attributes.strength += 1;
}
}
@object player_attributes {
strength: 10
dexterity: 14
constitution: 11
intelligence: 18
wisdom: 7
charisma: 16
}
This is because Rez automatically manages a reference property for any attribute with an _id suffix. You can see that we use .attributes even though we don’t define it directly.
So if you have an attribute attributes_id and set its value to #player_attributes then it will automatically manage a paired property attributes that refers to the game element with the same id. In practice this works great and has the added bonus of making serialisation so much easier: no object references anywhere!
Removing tables has not been without consequences as I was using them in several places. However I’ve managed to convert all of those into binding lists.
I introduced binding lists to be able to specify ordered key-value bindings for binding properties in the rendering process. A bindings list is a list of key-value pairs but with restricted value types (i.e. no nesting).
For example the v1.7 syntax to specify JS events to be handled at game startup the syntax was:
@game {
start_events: {"DOMContentLoaded": "event_name", ...}
}
In 1.8 it would be:
@game {
start_events: [DOMContentLoaded: "event_name", ...]
}
Which is such a small difference that it feels like a reasonable compromise. In fact binding lists are a reasonably good substitute for anything except nested structures but, as I say, I’ve settled on composing game elements instead.
In practice what this means is that I’ve got the {} syntax available again and perhaps I can think of something useful to do with it.
Oh I have also removed the ability to put collections in sets. In practice I cannot see any situation in which I would want to put, e.g. a list, into a set. If such a situation arises it wouldn’t be hard to put back. But it simplifies the parser a little not to have to deal with nested collection values here either.