一、先上代码
安装
pip install sc2reader
读取一个replay文件
import sc2reader
replay = sc2reader.load_replay('MyReplay', load_map=true)
读取两个玩家的信息
import sc2reader
replay = sc2reader.load_replay("replays/1.SC2Replay")
# 遍历并输出玩家信息
for player in replay.players:
print(f"玩家ID: {player.pid}")
print(f"玩家名称: {player.name}")
print(f"种族: {player.pick_race}")
print(f"结果: {player.result}")
读取地图信息
import sc2reader
replay = sc2reader.load_replay("replays/1.SC2Replay")
# 输出回放的基本信息
print(f"地图: {replay.map_name}")
print(f"游戏版本: {replay.release_string}")
print(f"游戏时间: {replay.game_length}")
print(f"游戏模式: {replay.real_type}")
读取所有事件
import sc2reader
replay = sc2reader.load_replay("replays/1.SC2Replay")
# 输出游戏事件
for event in replay.events:
print(event)
二、高级用法
import sc2reader
replay = sc2reader.load_replay("replays/2.SC2Replay")
# 输出所有游戏事件
for event in replay.events:
print(event)
#保存游戏事件
with open("replay_events.txt", "a") as f:
f.write(str(event) + "\n")
#找出所有 UnitBornEvent(建造单位)类型的事件
event_names = set([event.name for event in replay.events])#回放中所有事件类型
events_of_type = {name: [] for name in event_names}
for event in replay.events:
events_of_type[event.name].append(event)
# print(events_of_type)
#造兵事件
unit_born_events = events_of_type["UnitBornEvent"]
for ube in unit_born_events:
print("{} created {} at second {}".format(ube.unit_controller,
ube.unit,
ube.second))
#建造建筑
unit_init_events = events_of_type["UnitInitEvent"]
for uie in unit_init_events:
print("{} started creating {} at second {}".format(uie.unit_controller,
uie.unit,
uie.second))
#建造建筑的结束事件
unit_done_events = events_of_type["UnitDoneEvent"]
for ude in unit_done_events:
print("{} finished at second {}".format(ude.unit,
ude.second))
#死亡的单位、杀手归属玩家和凶手单位,以及位置和时间
unit_died_events = events_of_type["UnitDiedEvent"]
for udiede in unit_died_events:
print("{} was killed by {} using {} at ({}, {}) at second {}".format(udiede.unit,
udiede.killer,
udiede.killing_unit,
udiede.x,
udiede.y,
udiede.second))
#绘制工人(SCV\工蜂\探机)数量随时间的变化
import matplotlib.pyplot as plt
def worker_counter(replay, second, player_id):
workers = []
for event in replay.events:
if event.name == "UnitBornEvent" and event.control_pid == player_id:
if event.unit.is_worker:
workers.append(event.unit)
if event.name == "UnitDiedEvent":
if event.unit in workers:
workers.remove(event.unit)
if event.second > second:
break
return len(workers)
length_of_game = replay.frames // 24
workers_1 = [worker_counter(replay, k, 1) for k in range(length_of_game)]
workers_2 = [worker_counter(replay, k, 2) for k in range(length_of_game)]
plt.figure()
plt.plot(workers_1, label=replay.players[0])
plt.plot(workers_2, label=replay.players[1])
plt.legend(loc=2)
plt.show()
三、变量溯源
找这些属性从哪里?
sc2reader大量使用了工厂类,在找代码时确实比较困难.......(好吧,我承认我是个弱鸡,但是这工厂模式真的把这些属性隐藏的好深),这部分挖个坑,以后再更加细化一下
可用加载函数
在__init__.py文件中能找到这些,可以 用的加载函数就这些了.
module = sys.modules[__name__]
module.load_replays = factory.load_replays
module.load_replay = factory.load_replay
module.load_maps = factory.load_maps
module.load_map = factory.load_map
module.load_game_summaries = factory.load_game_summaries
module.load_game_summary = factory.load_game_summary
module.configure = factory.configure
module.reset = factory.reset
module.register_plugin = factory.register_plugin
module._defaultFactory = factory
可用属性
在源码的resources.py文件中搜索到了players这个对象的来源,可以看到,每个属性上都有说明注释,这样就用不着那个说明文档了.
class Replay(Resource):
#: A nested dictionary of player => { attr_name : attr_value } for
#: known attributes. Player 16 represents the global context and
#: contains attributes like game speed.
attributes = defaultdict(dict)
#: Fully qualified filename of the replay file represented.
filename = ""
#: Total number of frames in this game at 16 frames per second.
frames = int()
#: The SCII client build number
build = int()
#: The SCII game engine build number
base_build = int()
#: The full version release string as seen on Battle.net
release_string = ""
#: A tuple of the individual pieces of the release string
versions = tuple()
#: The game speed: Slower, Slow, Normal, Fast, Faster
speed = ""
#: Deprecated, use :attr:`game_type` or :attr:`real_type` instead
type = ""
#: The game type chosen at game creation: 1v1, 2v2, 3v3, 4v4, FFA
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 = ""
#: The category of the game, Ladder and Private
category = ""
#: A flag for public ladder games
is_ladder = bool()
#: A flag for private non-ladder games
is_private = bool()
#: The raw hash name of the s2ma resource as hosted on bnet depots
map_hash = ""
#: The name of the map the game was played on
map_name = ""
#: A reference to the loaded :class:`Map` resource.
map = None
#: The UTC time (according to the client NOT the server) that the game
#: was ended as represented by the Windows OS
windows_timestamp = int()
#: The UTC time (according to the client NOT the server) that the game
#: was ended as represented by the Unix OS
unix_timestamp = int()
#: The time zone adjustment for the time zone registered on the local
#: computer that recorded this replay.
time_zone = int()
#: Deprecated: See `end_time` below.
date = None
#: A datetime object representing the utc time at the end of the game.
end_time = None
#: A datetime object representing the utc time at the start of the game
start_time = None
#: Deprecated: See `game_length` below.
length = None
#: The :class:`Length` of the replay as an alternative to :attr:`frames`
game_length = None
#: The :class:`Length` of the replay in real time adjusted for the game speed
real_length = None
#: The region the game was played on: us, eu, sea, etc
region = ""
#: An integrated list of all the game events
events = list()
#: A list of :class:`Team` objects from the game
teams = list()
#: A dict mapping team number to :class:`Team` object
team = dict()
#: A list of :class:`Player` objects from the game
players = list()
#: A dual key dict mapping player names and numbers to
#: :class:`Player` objects
player = dict()
#: A list of :class:`Observer` objects from the game
observers = list()
#: A list of :class:`Person` objects from the game representing
#: both the player and observer lists
people = list()
#: A dual key dict mapping :class:`Person` object to their
#: person id's and names
person = dict()
#: A list of :class:`Person` objects from the game representing
#: only the human players from the :attr:`people` list
humans = list()
#: A list of :class:`Computer` objects from the game.
computers = list()
#: A list of all the chat message events from the game
messages = list()
#: A list of pings sent by all the different people in the game
pings = list()
#: A list of packets sent between the various game clients
packets = list()
#: A reference to the :class:`Person` that recorded the game
recorder = None
#: If there is a valid winning team this will contain a :class:`Team` otherwise it will be :class:`None`
winner = None
#: A dictionary mapping unit unique ids to their corresponding classes
objects = dict()
#: 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 = ""
#: SC2 Expansion. One of 'WoL', 'HotS'
expansion = ""
#: True of the game was resumed from a replay
resume_from_replay = False
#: A flag marking which method was used to resume from replay. Unknown interpretation.
resume_method = None
#: Lists info for each user that is resuming from replay.
resume_user_info = None
def __init__(
self,
replay_file,
filename=None,
load_level=4,
engine=sc2reader.engine,
do_tracker_events=True,
**options,
):
............
四、介绍放后面:
先引入项目地址上说的能处理的东西:
Replays 回放
Replays can be parsed for the following general types of information:
可以解析重播以获取以下常规类型的信息:
- Replay details (map, length, version, expansion, datetime, game type/speed, ...)
重播详情(地图、长度、版本、扩展、日期时间、游戏类型/速度等)- Player details (name, race, team, color, bnet url, win/loss, ...)
玩家详细信息(姓名、种族、团队、颜色、bnet url、赢/输......- Message details (text, time, player, target, pings, ...)
消息详细信息(文本、时间、玩家、目标、ping 等)- Unit Selection and Hotkey (Control Group) events.
Unit Selection 和 Hotkey (Control Group) 事件。- Resource Transfers and Requests (but not collection rate or unspent totals!)
资源转移和请求(但不包括收集速率或未花费的总数!- Unfiltered Unit commands (attack, move, train, build, psi storm, etc)
未过滤的单位命令(攻击、移动、训练、建造、灵能风暴等)- Camera Movements for all players and observers.
适合所有玩家和观察员的摄像机移动。Replays from release 2.0.8 onward make additional state information available:
从版本 2.0.8 开始的重放提供了额外的状态信息:
- Unit states - creation time, positions, and deaths times
单位状态 - 创建时间、位置和死亡时间- Player resource stats - collection rates/unspent totals
玩家资源统计信息 - 收集率/未花费总数- Player spending stats - resources spent and lost
玩家花费统计数据 - 花费和丢失的资源Further game state information can be extracted from this raw information:
可以从此原始信息中提取更多游戏状态信息:
- All unit selections and hotkey values for every frame of the game.
游戏每一帧的所有单位选择和热键值。- APM/EPM and its untold variations.
APM/EPM 及其无数的变化。- Supply counts, expansion timings, build orders, etc
供应计数、扩展时间、构建顺序等We have data dictionaries in place for standard games that make unit meta data available. Unit meta data is currently limited to:
我们为标准游戏提供了数据字典,这些字典使单位元数据可用。商品元数据目前仅限于:
- Costs - mineral, vespene, supply
成本 - 矿物、vespene、供应- Classification - army, building, worker
分类 - 军队、建筑、工人Additionally, abilities that create units/buildings have the built unit linked with the build time in game seconds.
此外,创建单位/建筑的技能会将建造单位与建造时间(以游戏秒为单位)相关联。Unfortunately this information IS NOT currently versioned and is only accurate for the latest builds of Starcraft. Versioned meta data support will be added in future releases.
不幸的是,此信息当前没有版本控制,仅对最新版本的 Starcraft 准确。版本化元数据支持将在将来的版本中添加。Maps 地图
Maps can be parsed for the following information:
可以解析映射以获取以下信息:
- Minimap and Icon images (tga format)
小地图和图标图像(tga 格式)- enUS localized Name, Author, Description, Website (if available)
enUS 本地化名称、作者、描述、网站(如果可用)- Map Dimensions, Camera Bounds, Tileset
地图尺寸、相机边界、图块集- Player Slot data and Advanced Teams alliance/enemy data.
玩家槽位数据和高级团队联盟/敌人数据。There is a lot more in here to be had for the adventurous.
这里还有更多适合冒险者的地方。Game Summaries 游戏总结
Game Summary files are downloaded by the client in order to allow you to view the game summary from your match history. Prior to 2.0.8 they were the only way to get the information from the summary screen. Since the 2.0.8 release you have been able to compute this information yourself from the replay files.
客户端会下载比赛摘要文件,以便您查看比赛历史记录中的比赛摘要。在 2.0.8 之前,它们是从摘要屏幕获取信息的唯一方法。从 2.0.8 版本开始,您已经能够从重播文件中自行计算此信息。Thank you Prillan and Team Liquid for helping to decode this file.
感谢 Prillan 和 Team Liquid 帮助解码此文件。
- Lobby Properties (game speed, game type, ...)
大厅属性(游戏速度、游戏类型等)- Player Information (Race, Team, Result, bnet info, ...)
玩家信息(比赛、车队、结果、bnet 信息等)- Player Graphs & Stats (Army Graph, Income Graph, Avg Unspent Resources, ...)
球员图表和统计数据(军队图表、收入图表、平均未花费资源等)- URLs to map localization files and images
用于映射本地化文件和图像的 URL- Player build orders up to 64 (real) actions
播放器构建订单最多 64 个(实际)操作Parsing on these files is now production ready for those that can get them. See the Team Liquid thread for details on how to go about getting them.
现在,对这些文件的解析已为那些可以获取它们的人做好了生产准备。有关如何获得它们的详细信息,请参阅 Team Liquid 帖子。Again, these files are generally unnecessary after the 2.0.8 release.
同样,在 2.0.8 版本发布后,这些文件通常是不必要的。
参考
项目地址
有个说明文档,结果也没说清楚使用方法(至少我没看见)
SC2Reader User Manual — sc2reader 0.7.0-pre documentationhttps://sc2reader.readthedocs.io/en/latest/
高级用法