-
Notifications
You must be signed in to change notification settings - Fork 37
EntityDictionary registers entity deletion callback only once (for the first instance) #191
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Long story short, ya'll broken, EntityDictionary instances never empty (besides the very lucky one), I've been triying to figure out why the server crashes for 3+ hours and I ain't developing SPA anymore until I have some sleep :P |
Too clarify this ticket more, the real issue (as explained by Invincible) is somewhere around there. |
To add more info, Python equality check is returning true because both methods are technically the same even if they carry different class foo():
def bar():
pass
a = foo()
b = foo()
c = set()
c.add(a.bar)
c.add(b.bar)
print(c) Overall, I think we should re-work how we store callbacks in general as this is an issue that might affect other modules that relies on registered callables (hooks, commands, etc.). I think we should expose a Callbacks container class directly from the c++ side that ensure methods bound to different objects are correctly added and iterated over for every objects they have been added for. Also, I think that in general we should not silently ignore if a callback is being registered twice and should rather raise a duplicated error; if the same function is registered more than once, the plugin is definitely doing something wrong breaking its own logic and I believe it is much more easier to debug an explicit exception than trying to figure out the weird things that might or might not occurs. And this is an issue we would have noticed way before, I guess. This was also probably the cause for the following result Satoon encountered: #181 (comment) |
Isn't that the purpose of CListenerManager?
I totally agree! Thus, I have added it: c857356 Though, your example works fine: from listeners import ListenerManager
class Foo(object):
def f(self):
print(self)
a = Foo()
b = Foo()
mgr = ListenerManager()
mgr.register_listener(a.f)
mgr.register_listener(b.f)
# Prints 'self' twice
mgr.notify()
def unload():
mgr.clear() |
If you instantiate two EntityDictionary, do you get a duplicate error? |
Yeah, I just noticed that I also get the error when I change the base class from |
I just did a few more tests and to fix this issue we need to implement the following def is_same(f1, f2):
try:
self1 = f1.__self__
except AttributeError:
return f1 is f2
try:
self2 = f2.__self__
except AttributeError:
return f1 is f2
return self1 is self2 and f1.__func__ is f2.__func__
class Foo(dict):
def f(self):
pass
@staticmethod
def f2():
pass
@classmethod
def f3(cls):
pass
a = Foo()
b = Foo()
def f():
pass
def get_f2():
def f2():
pass
return f2
assert is_same(a.f, a.f) == True
assert is_same(a.f, b.f) == False
assert is_same(a.f, a) == False
assert is_same(a.f, b) == False
assert is_same(a.f, Foo) == False
assert is_same(a.f, f) == False
assert is_same(a.f, get_f2()) == False
assert is_same(f, f) == True
assert is_same(f, a.f) == False
assert is_same(f, a) == False
assert is_same(a, f) == False
assert is_same(a, a.f) == False
assert is_same(get_f2(), get_f2()) == False
assert is_same(Foo.f, Foo.f) == True
assert is_same(Foo.f2, Foo.f2) == True
assert is_same(Foo.f2, a.f2) == True
assert is_same(a.f2, Foo.f2) == True
assert is_same(a.f3, a.f3) == True
assert is_same(Foo.f3, a.f3) == True |
Windows, CS:GO
Snippet 1 (one line is commented out)
Everything works as intented.
Client connects, and
my_player_dictionary[index]
is set toNone
.When I disconnect,
is printed. Well, along with 15 other lines (for bots).
Snippet 2 (that line is not commented out)
And everything's going to hell. Client connects, and
my_player_dictionary[index]
is set toNone
.But when I disconnect, nothing is printed.
Tests have shown that in the second snippet
my_player_dictionary._on_entity_deleted
is never called. Although the same method (player_dictionary._on_entity_deleted
) on the first dict is called successfully.The text was updated successfully, but these errors were encountered: