openra 2.2.0 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|