Skip to content
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

Open
wants to merge 12 commits into
base: master
Choose a base branch
from

Conversation

iamgreaser
Copy link
Contributor

@iamgreaser iamgreaser commented Dec 1, 2019

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.

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.
@iamgreaser iamgreaser marked this pull request as ready for review December 1, 2019 06:23
@NotAFile
Copy link
Member

NotAFile commented Dec 1, 2019

The tests appear to fail because the assert you added is hit by test_team_join.

@NotAFile NotAFile added the PR: improvement This PR includes an enhancement to piqueserver label Dec 1, 2019
@iamgreaser
Copy link
Contributor Author

iamgreaser commented Dec 1, 2019

The tests appear to fail because the assert you added is hit by test_team_join.

Ah right, thanks for digging it up, turns out python3 -m unittest runs the tests just fine w/o hitting bad things not related to the tests, so the test you mentioned fails on my end as well.

Considering that the peer is a mock in this test, which of these would be a better way to test this?

  • Call on_connect with a side-effect tied to the mock's eventData field.
  • Force game_version to GAME_VERSION_AOS075 (or possibly iterate through a list of all valid versions).
  • Allow setting game_version in the ServerConnection constructor.

In future I'd be very much in favour of having unit tests inherit from a base class where one could do, say, self.make_new_server_connection() and it'd spit out a suitable ServerConnection instance.

@iamgreaser
Copy link
Contributor Author

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.

Copy link
Member

@NotAFile NotAFile left a 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.

Comment on lines +426 to +429
self.game_versions = set(map(
GAME_VERSION_FROM_STRING.__getitem__,
game_versions.get()
))
Copy link
Member

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:
Copy link
Member

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?

Comment on lines +85 to +110
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,
}
Copy link
Member

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.

Comment on lines +32 to +33
from pyspades.constants import GAME_VERSION_AOS_075
from pyspades.constants import GAME_VERSION_AOS_076RC10
Copy link
Member

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

Comment on lines +181 to +182
for idx in range(len(self.items)):
item = self.items[idx]
Copy link
Member

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):
Copy link
Member

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).

Comment on lines +28 to +29
from pyspades.constants import GAME_PROTOCOL_VERSIONS
from pyspades.constants import GAME_VERSION_TO_STRING
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imports again

Comment on lines +261 to +265
# 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)

Copy link
Member

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
Copy link
Member

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()
Copy link
Member

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
PR: improvement This PR includes an enhancement to piqueserver
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants