Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Update README.rst and setup.py
  • Loading branch information
cclauss committed May 25, 2022
commit 1f18ff757e91801190ddffb95da2f12da2c52adf
16 changes: 6 additions & 10 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
What is sc2reader?
====================

sc2reader is a python library for extracting information from various different Starcraft II resources. These resources currently include Replays, Maps, and Game Summaries; we have plans to add support for Battle.net profiles and would gladly accept adapters to the more entrenched SCII sites such as sc2ranks.
sc2reader is a Python 3 library for extracting information from various different Starcraft II resources. These resources currently include Replays, Maps, and Game Summaries; we have plans to add support for Battle.net profiles and would gladly accept adapters to the more entrenched SCII sites such as sc2ranks.

There is a pressing need in the SC2 community for better statistics, better analytics, better tools for organizing and searching replays. Better websites for sharing replays and hosting tournaments. These tools can't be created without first being able to open up Starcraft II game files and analyze the data within. Our goal is to give anyone and everyone the power to construct their own tools, do their own analysis, and hack on their own Starcraft II projects under the open MIT license.

Expand Down Expand Up @@ -195,26 +195,22 @@ The new GameHeartNormalizerplugin is registered by default.
Installation
================

sc2reader runs on any system with Python 2.6+, 3.2+, or PyPy installed.
sc2reader runs on any system with Python 3.7+, or PyPy3 installed.


From PyPI (stable)
---------------------

Install from the latest release on PyPI with pip::

pip install sc2reader

or easy_install::

easy_install sc2reader
python3 -m pip install sc2reader

or with setuptools (specify a valid x.x.x)::

wget http://pypi.python.org/packages/source/s/sc2reader/sc2reader-x.x.x.tar.gz
tar -xzf sc2reader-x.x.x.tar.gz
cd sc2reader-x.x.x
python setup.py install
python3 setup.py install

Releases to PyPi can be very delayed (sorry!), for the latest and greatest you are encouraged to install from Github upstream.

Expand All @@ -235,7 +231,7 @@ or with setuptools::
wget -O sc2reader-upstream.tar.gz https://github.com/ggtracker/sc2reader/tarball/upstream
tar -xzf sc2reader-upstream.tar.gz
cd sc2reader-upstream
python setup.py install
python3 setup.py install

.. _circle-ci: https://circleci.com/
.. _coveralls.io: https://coveralls.io
Expand All @@ -250,7 +246,7 @@ Contributors should install from an active git repository using setuptools in `d

git clone https://github.com/ggtracker/sc2reader.git
cd sc2reader
python setup.py develop
python3 setup.py develop

Please review the `CONTRIBUTING.md`_ file and get in touch with us before doing too much work. It'll make everyone happier in the long run.

Expand Down
4 changes: 1 addition & 3 deletions sc2reader/decoders.py
Original file line number Diff line number Diff line change
Expand Up @@ -410,9 +410,7 @@ def read_struct(self, datatype=None):

elif datatype == 0x05: # Struct
entries = self.read_vint()
data = {
self.read_vint(): self.read_struct() for i in range(entries)
}
data = {self.read_vint(): self.read_struct() for i in range(entries)}

elif datatype == 0x06: # u8
data = ord(self._buffer.read(1))
Expand Down
19 changes: 10 additions & 9 deletions sc2reader/events/game.py
Original file line number Diff line number Diff line change
Expand Up @@ -630,9 +630,7 @@ def __init__(self, frame, pid, data):
self.yaw = data["yaw"]

def __str__(self):
return self._str_prefix() + "{} at ({}, {})".format(
self.name, self.x, self.y
)
return self._str_prefix() + "{} at ({}, {})".format(self.name, self.x, self.y)


@loggable
Expand Down Expand Up @@ -673,12 +671,15 @@ def __init__(self, frame, pid, data):
self.custom_resource = self.resources[3] if len(self.resources) >= 4 else None

def __str__(self):
return self._str_prefix() + " transfer {} minerals, {} gas, {} terrazine, and {} custom to {}".format(
self.minerals,
self.vespene,
self.terrazine,
self.custom_resource,
self.recipient,
return (
self._str_prefix()
+ " transfer {} minerals, {} gas, {} terrazine, and {} custom to {}".format(
self.minerals,
self.vespene,
self.terrazine,
self.custom_resource,
self.recipient,
)
)


Expand Down
4 changes: 1 addition & 3 deletions sc2reader/factories/plugins/replay.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,7 @@ def SelectionTracker(replay):
person.selection_errors += 1
if debug:
logger.warn(
"Error detected in deselection mode {}.".format(
event.mask_type
)
"Error detected in deselection mode {}.".format(event.mask_type)
)

person.selection = player_selections
Expand Down
8 changes: 2 additions & 6 deletions sc2reader/factories/sc2factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,9 +259,7 @@ def get_remote_cache_key(self, remote_resource):
def load_remote_resource_contents(self, remote_resource, **options):
cache_key = self.get_remote_cache_key(remote_resource)
if not self.cache_has(cache_key):
resource = super().load_remote_resource_contents(
remote_resource, **options
)
resource = super().load_remote_resource_contents(remote_resource, **options)
self.cache_set(cache_key, resource)
else:
resource = self.cache_get(cache_key)
Expand Down Expand Up @@ -363,9 +361,7 @@ class DoubleCachedSC2Factory(DictCachedSC2Factory, FileCachedSC2Factory):
"""

def __init__(self, cache_dir, cache_max_size=0, **options):
super().__init__(
cache_max_size, cache_dir=cache_dir, **options
)
super().__init__(cache_max_size, cache_dir=cache_dir, **options)

def load_remote_resource_contents(self, remote_resource, **options):
cache_key = self.get_remote_cache_key(remote_resource)
Expand Down
14 changes: 7 additions & 7 deletions sc2reader/objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class Team:
"""

#: A unique hash identifying the team of players
hash = ''
hash = ""

#: The team number as recorded in the replay
number = int()
Expand All @@ -29,7 +29,7 @@ class Team:

#: The result of the game for this team.
#: One of "Win", "Loss", or "Unknown"
result = ''
result = ""

def __init__(self, number):
self.number = number
Expand Down Expand Up @@ -385,10 +385,10 @@ class PlayerSummary:
teamid = int()

#: The race the player played in the game.
play_race = ''
play_race = ""

#: The race the player picked in the lobby.
pick_race = ''
pick_race = ""

#: If the player is a computer
is_ai = False
Expand All @@ -403,7 +403,7 @@ class PlayerSummary:
subregion = int()

#: The player's region, such as us, eu, sea
region = ''
region = ""

#: unknown1
unknown1 = int()
Expand Down Expand Up @@ -569,15 +569,15 @@ def __init__(self, contents):
self.small_preview_type = data.read_uint32()

#: (Optional) Small map preview path; relative to root of map archive
self.small_preview_path = ''
self.small_preview_path = ""
if self.small_preview_type == 2:
self.small_preview_path = data.read_cstring()

#: Large map preview type: 0 = None, 1 = Minimap, 2 = Custom
self.large_preview_type = data.read_uint32()

#: (Optional) Large map preview path; relative to root of map archive
self.large_preview_path = ''
self.large_preview_path = ""
if self.large_preview_type == 2:
self.large_preview_path = data.read_cstring()

Expand Down
50 changes: 25 additions & 25 deletions sc2reader/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class Replay(Resource):
attributes = defaultdict(dict)

#: Fully qualified filename of the replay file represented.
filename = ''
filename = ""

#: Total number of frames in this game at 16 frames per second.
frames = int()
Expand All @@ -59,27 +59,27 @@ class Replay(Resource):
base_build = int()

#: The full version release string as seen on Battle.net
release_string = ''
release_string = ""

#: A tuple of the individual pieces of the release string
versions = tuple()

#: The game speed: Slower, Slow, Normal, Fast, Faster
speed = ''
speed = ""

#: Deprecated, use :attr:`game_type` or :attr:`real_type` instead
type = ''
type = ""

#: The game type chosen at game creation: 1v1, 2v2, 3v3, 4v4, FFA
game_type = ''
game_type = ""

#: The real type of the replay as observed by counting players on teams.
#: For outmatched games, the smaller team numbers come first.
#: Example Values: 1v1, 2v2, 3v3, FFA, 2v4, etc.
real_type = ''
real_type = ""

#: The category of the game, Ladder and Private
category = ''
category = ""

#: A flag for public ladder games
is_ladder = bool()
Expand All @@ -88,10 +88,10 @@ class Replay(Resource):
is_private = bool()

#: The raw hash name of the s2ma resource as hosted on bnet depots
map_hash = ''
map_hash = ""

#: The name of the map the game was played on
map_name = ''
map_name = ""

#: A reference to the loaded :class:`Map` resource.
map = None
Expand Down Expand Up @@ -127,7 +127,7 @@ class Replay(Resource):
real_length = None

#: The region the game was played on: us, eu, sea, etc
region = ''
region = ""

#: An integrated list of all the game events
events = list()
Expand Down Expand Up @@ -184,10 +184,10 @@ class Replay(Resource):
#: A sha256 hash uniquely representing the combination of people in the game.
#: Can be used in conjunction with date times to match different replays
#: of the game game.
people_hash = ''
people_hash = ""

#: SC2 Expansion. One of 'WoL', 'HotS'
expansion = ''
expansion = ""

#: True of the game was resumed from a replay
resume_from_replay = False
Expand All @@ -205,7 +205,7 @@ def __init__(
load_level=4,
engine=sc2reader.engine,
do_tracker_events=True,
**options
**options,
):
super().__init__(replay_file, filename, **options)
self.datapack = None
Expand Down Expand Up @@ -915,16 +915,16 @@ def __init__(self, map_file, filename=None, region=None, map_hash=None, **option
super().__init__(map_file, filename, **options)

#: The localized (only enUS supported right now) map name.
self.name = ''
self.name = ""

#: The localized (only enUS supported right now) map author.
self.author = ''
self.author = ""

#: The localized (only enUS supported right now) map description.
self.description = ''
self.description = ""

#: The localized (only enUS supported right now) map website.
self.website = ''
self.website = ""

#: The unique hash used to identify this map on bnet's depots.
self.hash = map_hash
Expand Down Expand Up @@ -1015,7 +1015,7 @@ class GameSummary(Resource):
"""

#: Game speed
game_speed = ''
game_speed = ""

#: Game length (real-time)
real_length = int()
Expand Down Expand Up @@ -1069,8 +1069,8 @@ def __init__(self, summary_file, filename=None, lang="enUS", **options):
self.localization_urls = dict()
self.lobby_properties = dict()
self.lobby_player_properties = dict()
self.game_type = ''
self.real_type = ''
self.game_type = ""
self.real_type = ""

# The first 16 bytes appear to be some sort of compression header
buffer = BitPackedDecoder(zlib.decompress(summary_file.read()[16:]))
Expand Down Expand Up @@ -1442,19 +1442,19 @@ class MapHeader(Resource):
"""**Experimental**"""

#: The name of the map
name = ''
name = ""

#: Hash of map file
map_hash = ''
map_hash = ""

#: Link to the map file
map_url = ''
map_url = ""

#: Hash of the map image
image_hash = ''
image_hash = ""

#: Link to the image of the map (.s2mv)
image_url = ''
image_url = ""

#: Localization dictionary, {language, url}
localization_urls = dict()
Expand Down
4 changes: 1 addition & 3 deletions sc2reader/scripts/sc2attributes.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,7 @@ def get_choice(s2gs_key, old_value, new_value):
# This way old/new values can be swapped and decision is remembered
key = frozenset([s2gs_key, old_value, new_value])
if key not in decisions:
print(
f"Naming conflict on {s2gs_key}: {old_value} != {new_value}"
)
print(f"Naming conflict on {s2gs_key}: {old_value} != {new_value}")
print("Which do you want to use?")
print(f" (o) Old value '{old_value}'")
print(f" (n) New value '{new_value}'")
Expand Down
16 changes: 7 additions & 9 deletions sc2reader/scripts/sc2parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,17 @@ def main():

human_pids = {human.pid for human in replay.humans}
event_pids = {
event.player.pid
for event in replay.events
if getattr(event, "player", None)
event.player.pid
for event in replay.events
if getattr(event, "player", None)
}
player_pids = {
player.pid for player in replay.players if player.is_human
}
ability_pids = {
event.player.pid
for event in replay.events
if "CommandEvent" in event.name
event.player.pid
for event in replay.events
if "CommandEvent" in event.name
}
if human_pids != event_pids:
print(
Expand Down Expand Up @@ -99,9 +99,7 @@ def main():
)
print(
"Units were: {units}".format(
units={
obj.name for obj in replay.objects.values()
}
units={obj.name for obj in replay.objects.values()}
)
)

Expand Down
Loading