-
Notifications
You must be signed in to change notification settings - Fork 68
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
0.76 support #555
base: master
Are you sure you want to change the base?
0.76 support #555
Conversation
Make mypy --strict happy and pylint less grumpy w/ pyspades.weapon This also fixes more potential bugs.
Currently does 0.75 and 0.76RC10 depending on the state of a constant. The 0.76 support currently lacks the extra map packet support which may need to be added back in somehow. Regardless, the game still works completely fine, although I haven't been testing this in the vanilla client.
* Add `game_version` * Cleaned up WorldUpdate packets and how they're differentiated * Basic support for dual 0.75/0.76 servers, if anyone wants to mess around with that
This also contains some groundwork for enabling the ability to announce to multiple master servers. Currently there's only one master server per game version, but I can think of a way to extend this into something more generic.
The tests appear to fail because the assert you added is hit by |
Ah right, thanks for digging it up, turns out Considering that the peer is a mock in this test, which of these would be a better way to test this?
In future I'd be very much in favour of having unit tests inherit from a base class where one could do, say, |
I've gone with the second option for making the unit test pass as it does less damage to the structure of the unit tests. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Glad I finally got around to reviewing this. My overall thoughts are:
- Enabling "zombie" servers adds a bunch of complexity. With no way to advertise them on the server list, complexity already being high, and more capable protocol extensions on the horizon, I'm not sure if this is still worthwhile.
- The master server implementation is a bit dated to the current plans, by catering only to one master server per version.
- Customizing weapon values in general is already something we desired (Allow simpler modification of weapon damage values #59). The 0.76 damage values can also be back-ported to 0.75 easily, since they are entirely server-side. This leaves only the ammo and accuracy changes, which I understand are a big deal to you though.
In general, I'd make it dependent on you if we want to proceed with this, or poach parts of it and rather put more energy behind using more capable extensions to modify the weapon values.
self.game_versions = set(map( | ||
GAME_VERSION_FROM_STRING.__getitem__, | ||
game_versions.get() | ||
)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
generator expressions are more readable than map
(often also faster):
set(GAME_VERSION_FROM_STRING[i] for i in game_versions.get())
|
||
|
||
def vector_collision(vec1, vec2, distance=3): | ||
def vector_collision(vec1: Any, vec2: Any, distance: int = 3) -> bool: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The real type should be Vertex3
here?
GAME_VERSION_AOS_075, | ||
GAME_VERSION_AOS_076RC10, | ||
|
||
GAME_VERSION_COUNT, | ||
) = range(2+1) | ||
|
||
# Mapping of game versions to protocol versions. | ||
# | ||
# AoS since version 0.75 has used an increasing single-integer | ||
# protocol version number. | ||
# | ||
# AoS 0.70 and older use a CRC-32 of the client.exe binary. | ||
# | ||
# Some prerelease versions of 0.75: | ||
# - 0o075001: Not known. Possibly a test candidate version. | ||
# Yes, that's an octal number. | ||
# - 1: 0.75RC12 and some older versions. | ||
# - 2: Some later release candidate. | ||
# | ||
# 0.76 seems to have stuck with version 4 as it was never | ||
# officially released as the mainline version. | ||
# | ||
GAME_PROTOCOL_VERSIONS = { | ||
GAME_VERSION_AOS_075: 3, | ||
GAME_VERSION_AOS_076RC10: 4, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For new enums, the enum
module should really be used.
from pyspades.constants import GAME_VERSION_AOS_075 | ||
from pyspades.constants import GAME_VERSION_AOS_076RC10 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use commas to import multiple items
for idx in range(len(self.items)): | ||
item = self.items[idx] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use for i, item in enumerate(self.items)
instead of range(len())
"with that id ({}) already exists.".format(cls, cls.id)) | ||
raise KeyError(msg) | ||
_server_loaders[cls.id] = cls | ||
for version in range(cls.since_version, cls.until_version, 1): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer if instead of building the lookup table for all versions in between at initialization, a loader dictionary for a specific version was requested via parameters (and then cached).
from pyspades.constants import GAME_PROTOCOL_VERSIONS | ||
from pyspades.constants import GAME_VERSION_TO_STRING |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
imports again
# 0.76RC10+ compact world update | ||
world_update_076 = loaders.WorldUpdate076() | ||
world_update_076.items = items[:highest_player_id+1] | ||
self.send_contained(world_update_076, unsequenced=True) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems unclean to construct the packets for all versions versions here.
log.info('Got master connection for version {!r}'.format( | ||
GAME_VERSION_TO_STRING[connection.game_version], | ||
)) | ||
self.master_connections[connection.game_version] = connection |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could probably get a lot cleaner using async/await
.
The restriction on only differentiating master connections only by version has obviously not aged that well.
position1: The starting position of the shot. | ||
position2: The position of the target we're hitting. | ||
""" | ||
raise NotImplementedError() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Abstract methods on ABCs that are not overriden raise automatically on class creation.
This is ready for review, and I'm very much expecting to see stuff that needs to be changed here.
This adds support for the 0.76 protocol. There's also some cleanups of the weapon stuff as we're doing a lot of stuff to pyspades/weapons.py here anyway.
A goal is to eventually be able to have clients speaking different protocols at the same time, which will be useful for a potential overhaul of the protocol as it stands. I don't promise that it will be a good idea to run any pair of protocol or game versions at the same time, but 0.75 and 0.76RC10 should be close enough to each other gameplaywise to not be absolutely awful.
NOTE: I ran tox on my machine and the build failures appear to be due to
bcrypt
not being pulled in in the requirements as part of twisted/conch/ssh.