openra 2.2.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +1 -1
- data/lib/{openra-yaml.rb → openra-mini_yaml.rb} +1 -1
- data/lib/openra/cli.rb +1 -0
- data/lib/openra/cli/command_registry.rb +1 -0
- data/lib/openra/cli/commands/metadata.rb +64 -0
- data/lib/openra/cli/commands/replay_data.rb +25 -25
- data/lib/openra/cli/utils.rb +1 -0
- data/lib/openra/constants.rb +12 -0
- data/lib/openra/{yaml.rb → mini_yaml.rb} +1 -1
- data/lib/openra/replays.rb +1 -1
- data/lib/openra/replays/file.rb +5 -5
- data/lib/openra/replays/metadata.rb +1 -0
- data/lib/openra/replays/metadata_marker.rb +2 -0
- data/lib/openra/replays/order.rb +1 -0
- data/lib/openra/replays/replay.rb +1 -1
- data/lib/openra/version.rb +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 935333ec74bcce9f22c729a66247b9adbd18c25810254b60ffaae435c51f884f
|
4
|
+
data.tar.gz: 375cd8e312984afcf9316c1a58f6292be496f4177fd582c859490ee608341cbd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 43037b2237e9128f250417b965282a0f3b84aca84694f32044e6f43b2221230bf327a3e066884754861b7d130315323e2afc3addc24000a555146ede6c99dbed
|
7
|
+
data.tar.gz: d31fe43a09269b77a7a10cd0b6fb0f1ad88884f45ed9f801a2b11866d83f580a89daca4b9b95b9836175399ed1d4fedf7c8a5b8d51850e2823288bd07fa45e63
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
## Unreleased
|
2
2
|
|
3
|
+
### Added
|
4
|
+
|
5
|
+
* [replay-data] Add AdvancedChronoshift to Openra::SUPPORT_POWERS ([AMHOL](https://github.com/AMHOL))
|
6
|
+
* [metadata] Added metadata command ([AMHOL](https://github.com/AMHOL))
|
7
|
+
|
8
|
+
### Fixed
|
9
|
+
|
10
|
+
* [replay-data] Store clients from SyncInfo command and keep syncing after game start ([AMHOL](https://github.com/AMHOL))
|
11
|
+
|
3
12
|
[Compare v2.2.0...HEAD](https://github.com/AMHOL/openra-ruby/compare/v2.2.0...HEAD)
|
4
13
|
|
5
14
|
## v2.2.0
|
data/README.md
CHANGED
@@ -25,7 +25,7 @@ gem update openra
|
|
25
25
|
|
26
26
|
```sh
|
27
27
|
openra replay-data /path/to/replay.orarep [--format json|pretty-json|yaml]
|
28
|
-
openra
|
28
|
+
openra metadata /path/to/replay.orarep [--format json|pretty-json|yaml]
|
29
29
|
```
|
30
30
|
|
31
31
|
### Other tools
|
data/lib/openra/cli.rb
CHANGED
@@ -9,6 +9,7 @@ require 'openra/constants'
|
|
9
9
|
require 'openra/replays'
|
10
10
|
require 'openra/cli/utils'
|
11
11
|
require 'openra/cli/formatters'
|
12
|
+
require 'openra/cli/commands/metadata'
|
12
13
|
require 'openra/cli/commands/replay_data'
|
13
14
|
require 'openra/cli/commands/version'
|
14
15
|
require 'openra/cli/command_registry'
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Openra
|
4
|
+
class CLI
|
5
|
+
module Commands
|
6
|
+
class Metadata < Dry::CLI::Command
|
7
|
+
include CLI::Utils
|
8
|
+
|
9
|
+
desc 'Output replay metadata to stdout'
|
10
|
+
|
11
|
+
argument :replay, required: true, desc: 'Path of the replay file to read data from'
|
12
|
+
option :format, default: 'json', values: %w(json pretty-json yaml), desc: 'Output format'
|
13
|
+
|
14
|
+
def call(replay:, **options)
|
15
|
+
replay = Openra::Replays::Replay.new(replay)
|
16
|
+
|
17
|
+
data = {
|
18
|
+
mod: replay.metadata.mod,
|
19
|
+
version: replay.metadata.version,
|
20
|
+
map: {
|
21
|
+
name: utf8(replay.metadata.map_name),
|
22
|
+
hash: replay.metadata.map_hash
|
23
|
+
},
|
24
|
+
game: {
|
25
|
+
type: replay.players.each_with_object(Hash.new(0)) { |player, hash|
|
26
|
+
if player.team.nil?
|
27
|
+
hash[SecureRandom.uuid] += 1
|
28
|
+
else
|
29
|
+
hash[player.team] += 1
|
30
|
+
end
|
31
|
+
}.values.join('v'),
|
32
|
+
start_time: replay.metadata.start_time.iso8601,
|
33
|
+
end_time: replay.metadata.end_time.iso8601,
|
34
|
+
duration: time((replay.metadata.end_time - replay.metadata.start_time) * 1000)
|
35
|
+
},
|
36
|
+
players: replay.players.map { |player|
|
37
|
+
{
|
38
|
+
player_index: player.client_index,
|
39
|
+
name: utf8(player.name),
|
40
|
+
fingerprint: player.fingerprint,
|
41
|
+
color: player.color,
|
42
|
+
spawn: {
|
43
|
+
random: player&.is_random_spawn,
|
44
|
+
point: player.spawn_point
|
45
|
+
},
|
46
|
+
faction: {
|
47
|
+
random: player&.is_random_faction,
|
48
|
+
chosen: player.faction_name.downcase,
|
49
|
+
actual: player&.faction_id
|
50
|
+
},
|
51
|
+
team: player&.team,
|
52
|
+
is_bot: player&.is_bot || false,
|
53
|
+
is_winner: player&.outcome == 'Won',
|
54
|
+
outcome_time: player.outcome_time.iso8601
|
55
|
+
}
|
56
|
+
}
|
57
|
+
}
|
58
|
+
|
59
|
+
puts FORMATTERS.fetch(options[:format]).call(data)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -40,9 +40,8 @@ module Openra
|
|
40
40
|
chat: []
|
41
41
|
}
|
42
42
|
|
43
|
-
game_started = false
|
44
43
|
current_sync_clients = []
|
45
|
-
|
44
|
+
current_sync_info = nil
|
46
45
|
|
47
46
|
replay.each_order do |order|
|
48
47
|
client = current_sync_clients.find do |candidate|
|
@@ -51,9 +50,7 @@ module Openra
|
|
51
50
|
|
52
51
|
case order.command
|
53
52
|
when 'StartGame'
|
54
|
-
|
55
|
-
|
56
|
-
data[:clients] = sync_info.clients.map do |client|
|
53
|
+
data[:clients] = current_sync_info.clients.map do |client|
|
57
54
|
player = replay.player(client.index)
|
58
55
|
player_index = replay.players.index(player) + FIRST_PLAYER_INDEX if player
|
59
56
|
|
@@ -69,6 +66,7 @@ module Openra
|
|
69
66
|
point: client.spawn_point
|
70
67
|
},
|
71
68
|
faction: {
|
69
|
+
random: player&.is_random_faction,
|
72
70
|
chosen: client.faction_name.downcase,
|
73
71
|
actual: player&.faction_id
|
74
72
|
},
|
@@ -78,33 +76,35 @@ module Openra
|
|
78
76
|
is_admin: client.is_admin,
|
79
77
|
is_player: !player.nil?,
|
80
78
|
is_winner: player&.outcome == 'Won',
|
79
|
+
outcome_time: player.outcome_time.iso8601,
|
81
80
|
build: [],
|
82
81
|
support_powers: []
|
83
82
|
}
|
84
83
|
end
|
85
84
|
|
86
85
|
data[:game][:options] = {
|
87
|
-
explored_map:
|
88
|
-
speed:
|
89
|
-
starting_cash:
|
90
|
-
starting_units:
|
91
|
-
fog_enabled:
|
92
|
-
cheats_enabled:
|
93
|
-
kill_bounty_enabled:
|
94
|
-
allow_undeploy:
|
95
|
-
crates_enabled:
|
96
|
-
build_off_allies:
|
97
|
-
restrict_build_radius:
|
98
|
-
short_game:
|
99
|
-
techlevel:
|
86
|
+
explored_map: current_sync_info.global_settings.game_options.explored_map_enabled.value,
|
87
|
+
speed: current_sync_info.global_settings.game_options.game_speed.value,
|
88
|
+
starting_cash: current_sync_info.global_settings.game_options.starting_cash.value,
|
89
|
+
starting_units: current_sync_info.global_settings.game_options.starting_units.value,
|
90
|
+
fog_enabled: current_sync_info.global_settings.game_options.fog_enabled.value,
|
91
|
+
cheats_enabled: current_sync_info.global_settings.game_options.cheats_enabled.value,
|
92
|
+
kill_bounty_enabled: current_sync_info.global_settings.game_options.bounties_enabled.value,
|
93
|
+
allow_undeploy: current_sync_info.global_settings.game_options.conyard_undeploy_enabled.value,
|
94
|
+
crates_enabled: current_sync_info.global_settings.game_options.crates_enabled.value,
|
95
|
+
build_off_allies: current_sync_info.global_settings.game_options.build_off_allies_enabled.value,
|
96
|
+
restrict_build_radius: current_sync_info.global_settings.game_options.restricted_build_radius_enabled.value,
|
97
|
+
short_game: current_sync_info.global_settings.game_options.short_game_enabled.value,
|
98
|
+
techlevel: current_sync_info.global_settings.game_options.tech_level.value
|
100
99
|
}
|
101
100
|
when 'SyncInfo'
|
102
|
-
|
103
|
-
Openra::
|
104
|
-
)
|
101
|
+
current_sync_info = Openra::Struct::SyncInfo.new(
|
102
|
+
Openra::MiniYAML.load(order.target)
|
103
|
+
)
|
104
|
+
current_sync_clients = current_sync_info.clients
|
105
105
|
when 'SyncLobbyClients'
|
106
106
|
current_sync_clients = Openra::Struct::SyncLobbyClients.new(
|
107
|
-
Openra::
|
107
|
+
Openra::MiniYAML.load(order.target)
|
108
108
|
).clients
|
109
109
|
when *support_powers.keys
|
110
110
|
key = support_powers.fetch(utf8(order.command))
|
@@ -114,7 +114,7 @@ module Openra
|
|
114
114
|
|
115
115
|
client_hash[:support_powers] << {
|
116
116
|
type: key,
|
117
|
-
game_time: time(order.frame.pred *
|
117
|
+
game_time: time(order.frame.pred * current_sync_info.global_settings.frametime_multiplier),
|
118
118
|
placement: cell(order.target_cell.to_i),
|
119
119
|
extra_placement: cell(order.extra_cell.to_i),
|
120
120
|
}
|
@@ -127,7 +127,7 @@ module Openra
|
|
127
127
|
|
128
128
|
client_hash[:build] << {
|
129
129
|
structure: utf8(order.target),
|
130
|
-
game_time: time(order.frame.pred *
|
130
|
+
game_time: time(order.frame.pred * current_sync_info.global_settings.frametime_multiplier),
|
131
131
|
placement: cell(order.target_cell.to_i)
|
132
132
|
}
|
133
133
|
when 'Message'
|
@@ -151,7 +151,7 @@ module Openra
|
|
151
151
|
end
|
152
152
|
end
|
153
153
|
|
154
|
-
data[:server_name] = utf8(
|
154
|
+
data[:server_name] = utf8(current_sync_info.global_settings.server_name)
|
155
155
|
|
156
156
|
puts FORMATTERS.fetch(options[:format]).call(data)
|
157
157
|
end
|
data/lib/openra/cli/utils.rb
CHANGED
data/lib/openra/constants.rb
CHANGED
@@ -1,6 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Openra
|
4
|
+
# # https://github.com/OpenRA/OpenRA/blob/23b3c237b7071fd308c4664b0b6c5d719c0f3c74/OpenRA.Game/Map/MapPlayers.cs
|
5
|
+
# The player index is stored in the subject_id on orders to indicate which
|
6
|
+
# player issued the order, this is used because bot orders are issued by the
|
7
|
+
# host client
|
8
|
+
# I think the indices are as follows, but may differ for scripted maps:
|
9
|
+
# 0 => World
|
10
|
+
# 1 => Neutral
|
11
|
+
# 2 => Creeps
|
12
|
+
# 3 => Players@{0}
|
13
|
+
# 4 => Players@{1}
|
14
|
+
# 5 => ...
|
4
15
|
FIRST_PLAYER_INDEX = 3
|
5
16
|
|
6
17
|
SUPPORT_POWERS = {
|
@@ -9,6 +20,7 @@ module Openra
|
|
9
20
|
'SovietParatroopers' => :paratroopers,
|
10
21
|
'UkraineParabombs' => :parabombs,
|
11
22
|
'Chronoshift' => :chronoshift,
|
23
|
+
'AdvancedChronoshift' => :chronoshift,
|
12
24
|
'NukePowerInfoOrder' => :nuke,
|
13
25
|
'GrantExternalConditionPowerInfoOrder' => :iron_curtain
|
14
26
|
},
|
data/lib/openra/replays.rb
CHANGED
data/lib/openra/replays/file.rb
CHANGED
@@ -25,15 +25,15 @@ module Openra
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def metadata
|
28
|
+
# https://github.com/OpenRA/OpenRA/blob/23b3c237b7071fd308c4664b0b6c5d719c0f3c74/OpenRA.Game/FileFormats/ReplayMetadata.cs#L96
|
28
29
|
@metadata ||= begin
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
Metadata.read(
|
30
|
+
io = file.tap(&:rewind)
|
31
|
+
metadata_offset = -(metadata_marker.data_length + 4)
|
32
|
+
io.seek(metadata_offset, IO::SEEK_END)
|
33
|
+
Metadata.read(io)
|
33
34
|
end
|
34
35
|
end
|
35
36
|
|
36
|
-
|
37
37
|
private
|
38
38
|
|
39
39
|
attr_reader :filename
|
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
module Openra
|
4
4
|
module Replays
|
5
|
+
# The metadata markers is an int32 marker at the end of the file, indicating
|
6
|
+
# the offset at which the metadata MiniYAML is stored in the replay file
|
5
7
|
class MetadataMarker < BinData::Record
|
6
8
|
endian :little
|
7
9
|
count_bytes_remaining :total_size
|
data/lib/openra/replays/order.rb
CHANGED
data/lib/openra/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: openra
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andy Holland
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-05-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -151,18 +151,20 @@ files:
|
|
151
151
|
- lib/bindata/big_integer.rb
|
152
152
|
- lib/bindata/pascal_string.rb
|
153
153
|
- lib/openra-cli.rb
|
154
|
+
- lib/openra-mini_yaml.rb
|
154
155
|
- lib/openra-replays.rb
|
155
156
|
- lib/openra-struct.rb
|
156
157
|
- lib/openra-types.rb
|
157
|
-
- lib/openra-yaml.rb
|
158
158
|
- lib/openra.rb
|
159
159
|
- lib/openra/cli.rb
|
160
160
|
- lib/openra/cli/command_registry.rb
|
161
|
+
- lib/openra/cli/commands/metadata.rb
|
161
162
|
- lib/openra/cli/commands/replay_data.rb
|
162
163
|
- lib/openra/cli/commands/version.rb
|
163
164
|
- lib/openra/cli/formatters.rb
|
164
165
|
- lib/openra/cli/utils.rb
|
165
166
|
- lib/openra/constants.rb
|
167
|
+
- lib/openra/mini_yaml.rb
|
166
168
|
- lib/openra/replays.rb
|
167
169
|
- lib/openra/replays/file.rb
|
168
170
|
- lib/openra/replays/metadata.rb
|
@@ -187,7 +189,6 @@ files:
|
|
187
189
|
- lib/openra/struct/sync_lobby_clients.rb
|
188
190
|
- lib/openra/types.rb
|
189
191
|
- lib/openra/version.rb
|
190
|
-
- lib/openra/yaml.rb
|
191
192
|
- openra.gemspec
|
192
193
|
homepage: https://github.com/AMHOL/openra-ruby
|
193
194
|
licenses:
|