Page 1 of 1

Equality (==) tests fail with scripting "Position" objects

Posted: Fri Sep 07, 2018 5:47 pm
by Reika
That is to say, it feels like == is using an identity check instead of semantic equality (ie .equals()).

The double-equals operator works fine with other script objects such as LuaEntity, so I imagine that this is an oversight rather than intentional.

Re: Equality (==) tests fail with scripting "Position" objects

Posted: Fri Sep 07, 2018 6:27 pm
by posila
https://www.lua.org/pil/3.2.html
Lua compares tables, userdata, and functions by reference, that is, two such values are considered equal only if they are the very same object. For instance, after the code

Code: Select all

    a = {}; a.x = 1; a.y = 0
    b = {}; b.x = 1; b.y = 0
    c = a
you have that a==c but a~=b.
I wonder if it really behaves differently for LuaEntity (ie. get first reference from create_entity and second through find_entities), but Position is just plain Lua table.
EDIT: Tried it and it does work with LuaEntity references, interesting.

Re: Equality (==) tests fail with scripting "Position" objects

Posted: Fri Sep 07, 2018 6:55 pm
by Klonan
posila wrote:EDIT: Tried it and it does work with LuaEntity references, interesting.
Things like LuaEntity use a custom equality check defined in the C++:

Code: Select all

bool LuaEntity::equals(const LuaObject* luaObject) const
{
  return *this->entityTarget == *static_cast<const LuaEntity*>(luaObject)->entityTarget;
}
We could also set similar functions for position by setting a metatable on the returned position LuaTable

Re: Equality (==) tests fail with scripting "Position" objects

Posted: Fri Sep 07, 2018 6:56 pm
by Reika
posila wrote:https://www.lua.org/pil/3.2.html
Lua compares tables, userdata, and functions by reference, that is, two such values are considered equal only if they are the very same object. For instance, after the code

Code: Select all

    a = {}; a.x = 1; a.y = 0
    b = {}; b.x = 1; b.y = 0
    c = a
you have that a==c but a~=b.
I wonder if it really behaves differently for LuaEntity (ie. get first reference from create_entity and second through find_entities), but Position is just plain Lua table.
EDIT: Tried it and it does work with LuaEntity references, interesting.
Klonan wrote:
posila wrote:EDIT: Tried it and it does work with LuaEntity references, interesting.
Things like LuaEntity use a custom equality check defined in the C++:

Code: Select all

bool LuaEntity::equals(const LuaObject* luaObject) const
{
  return *this->entityTarget == *static_cast<const LuaEntity*>(luaObject)->entityTarget;
}
We could also set similar functions for position by setting a metatable on the returned position LuaTable
The reason that this is kind of an important thing with Position and Area/BoundingBox is that both of those objects can have multiple internal structures (x/y vs [1]/[2] and the fact that left_top/bottom_right is optional in Area), meaning a comparison is rather nontrivial and prone to issues. Combine that with the fact that Position and Area are likely to be compared for a large number of reasons, and I imagine that this can both simplify code and save a lot of headache for a great many people.

Re: Equality (==) tests fail with scripting "Position" objects

Posted: Fri Sep 07, 2018 7:37 pm
by Rseding91
Position and area will only ever be defined 1 way when you read them from the game: position with x/y and area with left_top/right_bottom.

I'm not going to implement metatable __eq for position and area because that would mean every single one of them would need another lua table + save/load/restore the meta table every time the game saves/loads.

That would add a *massive* amount of overhead to those things existing in any mod and simply isn't worth it. There's already measurable overhead to have position be a table with x/y instead of simply returning 2 integers when called.

Re: Equality (==) tests fail with scripting "Position" objects

Posted: Thu Jan 17, 2019 2:08 pm
by Fractaliste
Klonan wrote: Fri Sep 07, 2018 6:55 pm
posila wrote:EDIT: Tried it and it does work with LuaEntity references, interesting.
Things like LuaEntity use a custom equality check defined in the C++:

Code: Select all

bool LuaEntity::equals(const LuaObject* luaObject) const
{
  return *this->entityTarget == *static_cast<const LuaEntity*>(luaObject)->entityTarget;
}
We could also set similar functions for position by setting a metatable on the returned position LuaTable
I'm not familiar with C++, does it mean I can safely check if entity1 == entity2 (instead of checking both entity have same prototype name, belongs to same surface and are at same position) to ensure that entity1 is the same object ingame as entity2 ?

Re: Equality (==) tests fail with scripting "Position" objects

Posted: Thu Jan 17, 2019 4:09 pm
by darkfrei
Maybe some is_deep_equal function?

Re: Equality (==) tests fail with scripting "Position" objects

Posted: Thu Jan 17, 2019 11:15 pm
by Rseding91
Fractaliste wrote: Thu Jan 17, 2019 2:08 pm I'm not familiar with C++, does it mean I can safely check if entity1 == entity2 (instead of checking both entity have same prototype name, belongs to same surface and are at same position) to ensure that entity1 is the same object ingame as entity2 ?
Yes.