lzrtag-base 1.0.0 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +1 -0
- data/docs/EventSymbols.md +21 -0
- data/docs/MQTTBranches.md +17 -2
- data/lib/lzrtag/game/base_game.rb +5 -5
- data/lib/lzrtag/handler/base_handler.rb +20 -3
- data/lib/lzrtag/handler/count_handler.rb +35 -14
- data/lib/lzrtag/handler/game_handler.rb +15 -7
- data/lib/lzrtag/handler/hitArb_handler.rb +13 -6
- data/lib/lzrtag/hooks/base_hook.rb +7 -1
- data/lib/lzrtag/hooks/standard_hooks.rb +75 -20
- data/lib/lzrtag/player/base_player.rb +33 -8
- data/lib/lzrtag/player/hardware_player.rb +58 -16
- data/lib/lzrtag/player/life_player.rb +7 -3
- data/lib/lzrtag/player/stats_player.rb +107 -0
- metadata +22 -36
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ecf85ea86bb74b299da65766ec5c0d653416b605863e93ba833970e0db78fbbc
|
4
|
+
data.tar.gz: 460e8d9cdc4b01522e1373efc4a3b3417161e717c8848d4c2abce8fb3c4c7fb8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 10676d8495f7148b646fc3cc4a4025c2a0f4d37e8c4e75543668fc19d9bad2f8dbffae747393a5670c34f54021833d67ed77d3086dca8f15aca4e1bcadf5698c
|
7
|
+
data.tar.gz: d64f580c72c66e25b13dafa2e8dfcc93cd2cacb6265416caecc1312bc8f794b351bf5254ac579af099c1bac50ba1113dab3e613197d305e7b9aad3a2148841cd
|
data/README.md
CHANGED
data/docs/EventSymbols.md
CHANGED
@@ -15,6 +15,11 @@ It is only triggered when a game is present.
|
|
15
15
|
*Game class alternative:* Describe per-tick code using the
|
16
16
|
"phase" DSL. It allows easy and clean specification of tick code.
|
17
17
|
|
18
|
+
###### :slowTick
|
19
|
+
Sent in regular intervals (0.5s) as a slower alternative to :gameTick for less
|
20
|
+
critical tasks. This for example handles player beacon entering/leaving as well
|
21
|
+
as slow timeouts.
|
22
|
+
|
18
23
|
###### :gameStarting
|
19
24
|
Triggered when a new game is selected, either in Ruby or via MQTT.
|
20
25
|
Payload is [newGame]
|
@@ -86,6 +91,22 @@ Payload is [thePlayer, newGun, oldGun]
|
|
86
91
|
*TODO:* The gun number should be replaced by an ID string, when the
|
87
92
|
gun configuration is moved to a Filesystem-based one (possibly by loading from JSON)
|
88
93
|
|
94
|
+
###### :playerEnteredBeacon
|
95
|
+
Triggered once when a player receives a new IR Beacon signal, of a beacon that
|
96
|
+
he has not seen for the last 3s, to indicate that the Player entered a new zone.
|
97
|
+
Payload is [thePlayer, beaconID]
|
98
|
+
|
99
|
+
###### :playerInBeacon
|
100
|
+
Triggered for every single beacon pulse a player receives from a IR Beacon.
|
101
|
+
This can be useful to handle time-continuous beacon interaction, such as being
|
102
|
+
healed by a beacon, or a capture point.
|
103
|
+
Payload is [thePlayer, beaconID]
|
104
|
+
|
105
|
+
###### :playerLeftBeacon
|
106
|
+
Triggered once when a player does not see a beacon ID for at least 3s, indicating
|
107
|
+
that the player has left a zone.
|
108
|
+
Payload is [thePlayer, beaconID]
|
109
|
+
|
89
110
|
## Player life signals
|
90
111
|
These signals are sent whenever the player's HP count or life status is changed,
|
91
112
|
and let the application handle things like scoring damage and kills, and triggering
|
data/docs/MQTTBranches.md
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
# MQTT Branch setup description
|
2
2
|
|
3
|
+
## Game Branches
|
4
|
+
|
5
|
+
- Lasertag/Game/Events/Hits
|
6
|
+
- Lasertag/Game/Controls/+
|
7
|
+
- SetPhase
|
8
|
+
- SetGame
|
9
|
+
- Lasertag/Game/Phase/Valid
|
10
|
+
- Lasertag/Game/ParticipatingPlayers
|
11
|
+
- Lasertag/Game/KnownGames
|
12
|
+
- Lasertag/Game/CurrentGame
|
13
|
+
- Lasertag/Game/Phase/Current
|
14
|
+
|
3
15
|
## Weapon Branches
|
4
16
|
The weapons are the main unit of the Lasertag system. As such, they use a specific
|
5
17
|
branch setup to minimize traffic to them, while making code maintaining easier.
|
@@ -39,6 +51,7 @@ They are slow-changing configuration parameters for the weapons.
|
|
39
51
|
|Heartbeat|"1" or "0"|Enables/Disables heartbeat of the weapon|Yes|
|
40
52
|
|Hit|STR Number|Number, in seconds, to make the gun show that it's hit|No|
|
41
53
|
|Vibrate|STR Number|Number, in seconds, for which to make the gun vibrate|No|
|
54
|
+
|Reload|"1"|Trigger a gun-side reloading|No|
|
42
55
|
|
43
56
|
### Sound attributes
|
44
57
|
|
@@ -60,6 +73,7 @@ They all relate to the hardware of the system, such as battery etc.
|
|
60
73
|
|Ping|uint32_t[3]|Battery, free-heap and ping data|No|
|
61
74
|
|NSwitch|STR Number|Navigation switch press info (0-3)|No|
|
62
75
|
|Gyro|String|Clear string of the pose the gyroscope is reporting|Yes|
|
76
|
+
|BeaconDetect|STR Number|Number of the beacon signal that was detected (0-255)|No|
|
63
77
|
|
64
78
|
### Statistics Attributes
|
65
79
|
|
@@ -70,5 +84,6 @@ They all relate to various game statistics that do not directly influence the ha
|
|
70
84
|
|Key|Data|Descrition|Retained|
|
71
85
|
|--|--|--|--|
|
72
86
|
|HP|STR Number|Float number, 0 to 100 (or more with shields)|Yes|
|
73
|
-
|Ammo|uint32_t[
|
74
|
-
|Ammo/
|
87
|
+
|Ammo|uint32_t[3]|Current Clip ammo, max clip size and reserve ammo|No|
|
88
|
+
|Ammo/SetClip|STR Number|Set the amount of ammo in the player's clip|No|
|
89
|
+
|Ammo/SetReserve|STR Number| Set the amount of ammo in the player's reserve|No|
|
@@ -17,7 +17,7 @@ module LZRTag
|
|
17
17
|
#
|
18
18
|
# hook :dmgHook, LZRTag::Hook::Damager
|
19
19
|
#
|
20
|
-
# phase :
|
20
|
+
# phase :starting do |deltaTick|
|
21
21
|
# puts "I tick!"
|
22
22
|
# end
|
23
23
|
#
|
@@ -81,9 +81,9 @@ module LZRTag
|
|
81
81
|
def initialize(handler)
|
82
82
|
super(handler)
|
83
83
|
|
84
|
-
@hookList =
|
84
|
+
@hookList = Hash.new();
|
85
85
|
self.class.get_hooks().each do |hookID, hookData|
|
86
|
-
@hookList
|
86
|
+
@hookList[hookID] = hookData[0].new(@handler, **hookData[1])
|
87
87
|
end
|
88
88
|
|
89
89
|
@tickTime = 0.1;
|
@@ -113,7 +113,7 @@ module LZRTag
|
|
113
113
|
raise ArgumentError, "Hook needs to be a LZR::Hook!"
|
114
114
|
end
|
115
115
|
raise ArgumentError, "Hook options need to be a hash" unless hookOptions.is_a? Hash
|
116
|
-
get_hooks()[hookID]
|
116
|
+
get_hooks()[hookID] = [hookType, hookOptions];
|
117
117
|
end
|
118
118
|
|
119
119
|
# DSL function to provide a phase tick code to this game
|
@@ -188,7 +188,7 @@ module LZRTag
|
|
188
188
|
end
|
189
189
|
end
|
190
190
|
|
191
|
-
@hookList.each do |hook|
|
191
|
+
@hookList.each do |hookID, hook|
|
192
192
|
hook.consume_event(evt, data);
|
193
193
|
end
|
194
194
|
end
|
@@ -1,9 +1,11 @@
|
|
1
1
|
|
2
2
|
require 'mqtt/sub_handler'
|
3
3
|
|
4
|
+
require 'xasin_logger'
|
5
|
+
|
4
6
|
require_relative '../hooks/base_hook.rb'
|
5
7
|
|
6
|
-
require_relative '../player/
|
8
|
+
require_relative '../player/stats_player.rb'
|
7
9
|
|
8
10
|
module LZRTag
|
9
11
|
module Handler
|
@@ -20,13 +22,17 @@ module LZRTag
|
|
20
22
|
# # Using LZRTag.Handler instead of LZRTag::Handler::Base to fetch the latest handler
|
21
23
|
# handler = LZRTag.Handler.new(mqttConn);
|
22
24
|
class Base
|
25
|
+
include XasLogger::Mix
|
26
|
+
|
23
27
|
# Returns the MQTT connection
|
24
28
|
attr_reader :mqtt
|
25
29
|
|
26
30
|
# Returns the ID-Table, a Hash of Players and their matched IDs
|
27
31
|
attr_reader :idTable
|
28
32
|
|
29
|
-
def initialize(mqtt, playerClass = Player::
|
33
|
+
def initialize(mqtt, playerClass = Player::Statistics, clean_on_exit: true)
|
34
|
+
init_x_log("LZRTag Base", nil);
|
35
|
+
|
30
36
|
@mqtt = mqtt;
|
31
37
|
|
32
38
|
@playerClass = playerClass;
|
@@ -48,6 +54,12 @@ module LZRTag
|
|
48
54
|
end
|
49
55
|
end
|
50
56
|
@eventThread.abort_on_exception = true;
|
57
|
+
Thread.new do
|
58
|
+
loop do
|
59
|
+
sleep 0.5;
|
60
|
+
send_event(:slowTick);
|
61
|
+
end
|
62
|
+
end
|
51
63
|
|
52
64
|
@mqtt.subscribe_to "Lasertag/Players/#" do |data, topic|
|
53
65
|
dID = topic[0];
|
@@ -56,6 +68,7 @@ module LZRTag
|
|
56
68
|
@players[dID] = @playerClass.new(dID, self);
|
57
69
|
}
|
58
70
|
send_event(:playerRegistered, @players[dID]);
|
71
|
+
x_logi("New player registered: #{dID}");
|
59
72
|
end
|
60
73
|
|
61
74
|
@players[dID].on_mqtt_data(data, topic);
|
@@ -73,7 +86,7 @@ module LZRTag
|
|
73
86
|
}
|
74
87
|
end
|
75
88
|
|
76
|
-
|
89
|
+
x_logi("Initialisation complete");
|
77
90
|
end
|
78
91
|
|
79
92
|
# Send an event into the event loop.
|
@@ -99,6 +112,10 @@ module LZRTag
|
|
99
112
|
player = data[0];
|
100
113
|
@idTable[player.id] = nil;
|
101
114
|
player.id = nil;
|
115
|
+
when :slowTick
|
116
|
+
self.each do |pl|
|
117
|
+
pl._tick_connection();
|
118
|
+
end
|
102
119
|
end
|
103
120
|
end
|
104
121
|
|
@@ -12,22 +12,30 @@ module LZRTag
|
|
12
12
|
class Count < HitArb
|
13
13
|
# Returns a Hash with keys 0..7, describing which teams have
|
14
14
|
# how many players
|
15
|
-
attr_reader :
|
15
|
+
attr_reader :teamMap
|
16
16
|
# Returns a Hash with keys equal to player's brightnesses, describing
|
17
17
|
# how many players have which brightness
|
18
|
-
attr_reader :
|
18
|
+
attr_reader :brightnessMap
|
19
|
+
|
20
|
+
# Returns a hash with keys of beacon numbers, describing
|
21
|
+
# how many players are in which beacon
|
22
|
+
attr_reader :beaconMap
|
19
23
|
|
20
24
|
def initialize(*args, **argHash)
|
21
25
|
super(*args, **argHash);
|
22
26
|
|
23
|
-
@
|
27
|
+
@teamMap = Hash.new();
|
24
28
|
7.times do |i|
|
25
|
-
@
|
29
|
+
@teamMap[i] = Array.new;
|
26
30
|
end
|
27
31
|
|
28
|
-
@
|
32
|
+
@brightnessMap = Hash.new();
|
29
33
|
Player::Hardware.getBrightnessKeys().each do |bKey|
|
30
|
-
@
|
34
|
+
@brightnessMap[bKey] = Array.new;
|
35
|
+
end
|
36
|
+
|
37
|
+
@beaconMap = Hash.new() do |h, k|
|
38
|
+
h[k] = Array.new();
|
31
39
|
end
|
32
40
|
end
|
33
41
|
|
@@ -37,19 +45,32 @@ module LZRTag
|
|
37
45
|
|
38
46
|
case evtName
|
39
47
|
when :playerRegistered
|
40
|
-
@
|
41
|
-
@
|
48
|
+
@teamMap[data[0].team] << data[0];
|
49
|
+
@brightnessMap[data[0].brightness] << data[0];
|
42
50
|
when :playerUnregistered
|
43
|
-
@
|
44
|
-
@
|
51
|
+
@teamMap[data[0].team].delete data[0];
|
52
|
+
@brightnessMap[data[0].brightness].delete data[0];
|
45
53
|
when :playerTeamChanged
|
46
|
-
@
|
47
|
-
@
|
54
|
+
@teamMap[data[1]].delete data[0];
|
55
|
+
@teamMap[data[0].team] << data[0];
|
48
56
|
when :playerBrightnessChanged
|
49
|
-
@
|
50
|
-
@
|
57
|
+
@brightnessMap[data[1]].delete data[0];
|
58
|
+
@brightnessMap[data[0].brightness] << data[0];
|
59
|
+
when :playerEnteredBeacon
|
60
|
+
@beaconMap[data[1]] << data[0];
|
61
|
+
when :playerLeftBeacon
|
62
|
+
@beaconMap[data[1]].delete data[0];
|
51
63
|
end
|
52
64
|
end
|
65
|
+
|
66
|
+
def get_team_killcount(team)
|
67
|
+
total = 0;
|
68
|
+
@teamMap[team].each do |pl|
|
69
|
+
total += pl.stats["Kills"];
|
70
|
+
end
|
71
|
+
|
72
|
+
return total;
|
73
|
+
end
|
53
74
|
end
|
54
75
|
end
|
55
76
|
end
|
@@ -105,7 +105,8 @@ module LZRTag
|
|
105
105
|
send_event(:gameTick, dT);
|
106
106
|
end
|
107
107
|
|
108
|
-
|
108
|
+
x_logi("Stopping game!");
|
109
|
+
|
109
110
|
set_phase(:idle);
|
110
111
|
sleep 1;
|
111
112
|
@currentGame = nil;
|
@@ -122,12 +123,15 @@ module LZRTag
|
|
122
123
|
# A list of games is published to Lasertag/Game/KnownGames
|
123
124
|
# @param gameTag [String] Cleartext name of the game
|
124
125
|
# @param game [LZRTag::Game::Base] The game class to register
|
126
|
+
# @see start_game
|
125
127
|
def register_game(gameTag, game)
|
126
128
|
raise ArgumentError, "Game Tag must be a string!" unless gameTag.is_a? String
|
127
129
|
raise ArgumentError, "Game must be a LZRTag::Game class" unless game <= LZRTag::Game::Base
|
128
130
|
|
129
131
|
@knownGames[gameTag] = game;
|
130
132
|
|
133
|
+
x_logi("Game registered: #{gameTag}");
|
134
|
+
|
131
135
|
@mqtt.publish_to "Lasertag/Game/KnownGames", @knownGames.keys.to_json, retain: true;
|
132
136
|
end
|
133
137
|
|
@@ -143,6 +147,10 @@ module LZRTag
|
|
143
147
|
# This function will take either a String (as registered with register_game),
|
144
148
|
# or a LZRTag::Game::Base class, instantiate it, and start it.
|
145
149
|
# If no fitting game was found, the game is instead stopped.
|
150
|
+
#
|
151
|
+
# @note The first phase that is started by default is :starting, the Game
|
152
|
+
# class must define at least a phase_prep hook to change the phase and
|
153
|
+
# configure the game!
|
146
154
|
# @param game [String,LZRTag::Game::Base] The game, or game name, to start
|
147
155
|
def start_game(game = @lastGame)
|
148
156
|
@lastGame = game;
|
@@ -156,7 +164,7 @@ module LZRTag
|
|
156
164
|
|
157
165
|
if(gKey = @knownGames.key(game))
|
158
166
|
@mqtt.publish_to "Lasertag/Game/CurrentGame", gKey, retain: true
|
159
|
-
|
167
|
+
x_logi("Starting game #{gKey}");
|
160
168
|
else
|
161
169
|
@mqtt.publish_to "Lasertag/Game/CurrentGame", "", retain: true
|
162
170
|
end
|
@@ -202,7 +210,7 @@ module LZRTag
|
|
202
210
|
|
203
211
|
raise ArgumentError, "Phase must be valid!" unless allowedPhases.include? nextPhase
|
204
212
|
|
205
|
-
|
213
|
+
x_logi("Starting phase #{nextPhase}");
|
206
214
|
|
207
215
|
oldPhase = @gamePhase
|
208
216
|
send_event(:gamePhaseEnds, oldPhase, nextPhase)
|
@@ -221,24 +229,24 @@ module LZRTag
|
|
221
229
|
# @param [Array<LZRTag::Player::Base] Array of active players
|
222
230
|
def gamePlayers=(newPlayers)
|
223
231
|
raise ArgumentError, "Game player list shall be an array!" unless newPlayers.is_a? Array
|
232
|
+
oldGamePlayers = @gamePlayers.dup
|
224
233
|
@gamePlayers = newPlayers.dup;
|
225
234
|
|
226
235
|
@playerNames = Array.new();
|
227
236
|
plNameArray = Array.new();
|
228
237
|
@gamePlayers.each do |pl|
|
229
|
-
plNameArray << pl.
|
238
|
+
plNameArray << pl.DeviceID();
|
230
239
|
end
|
231
240
|
|
232
|
-
newPlayers = @gamePlayers -
|
241
|
+
newPlayers = @gamePlayers - oldGamePlayers;
|
233
242
|
newPlayers.each do |pl|
|
234
243
|
send_event :playerEnteredGame, pl;
|
235
244
|
end
|
236
|
-
oldPlayers =
|
245
|
+
oldPlayers = oldGamePlayers - @gamePlayers;
|
237
246
|
oldPlayers.each do |pl|
|
238
247
|
send_event :playerLeftGame, pl;
|
239
248
|
end
|
240
249
|
|
241
|
-
@oldGamePlayers = @gamePlayers.dup;
|
242
250
|
@mqtt.publish_to "Lasertag/Game/ParticipatingPlayers", plNameArray.to_json(), retain: true
|
243
251
|
end
|
244
252
|
|
@@ -22,13 +22,11 @@ module LZRTag
|
|
22
22
|
def initialize(*data, **options)
|
23
23
|
super(*data, **options);
|
24
24
|
|
25
|
-
@mqtt.subscribe_to "Lasertag/Game/Events" do |data|
|
25
|
+
@mqtt.subscribe_to "Lasertag/Game/Events/Hits" do |data|
|
26
26
|
begin
|
27
27
|
data = JSON.parse(data, symbolize_names: true);
|
28
28
|
|
29
|
-
|
30
|
-
_handle_hitArb(data);
|
31
|
-
end
|
29
|
+
_handle_hitArb(data);
|
32
30
|
rescue JSON::ParserError
|
33
31
|
end
|
34
32
|
end
|
@@ -38,6 +36,15 @@ module LZRTag
|
|
38
36
|
return true;
|
39
37
|
end
|
40
38
|
|
39
|
+
def consume_event(evt, data)
|
40
|
+
super(evt, data)
|
41
|
+
if(evt == :slowTick)
|
42
|
+
self.each do |pl|
|
43
|
+
pl.check_beacons();
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
41
48
|
def _handle_hitArb(data)
|
42
49
|
unless (hitPlayer = get_player(data[:target])) and
|
43
50
|
(sourcePlayer = get_player(data[:shooterID])) and
|
@@ -53,9 +60,9 @@ module LZRTag
|
|
53
60
|
hookList = Array.new();
|
54
61
|
hookList << @hooks;
|
55
62
|
if(@currentGame)
|
56
|
-
hookList << @currentGame.hookList
|
63
|
+
hookList << @currentGame.hookList.values
|
57
64
|
end
|
58
|
-
hookList.flatten
|
65
|
+
hookList.flatten!
|
59
66
|
|
60
67
|
hookList.each do |h|
|
61
68
|
begin
|
@@ -1,4 +1,6 @@
|
|
1
1
|
|
2
|
+
require 'xasin_logger'
|
3
|
+
|
2
4
|
module LZRTag
|
3
5
|
module Hook
|
4
6
|
=begin
|
@@ -40,6 +42,8 @@ module LZRTag
|
|
40
42
|
handler.add_hook(MyHook);
|
41
43
|
=end
|
42
44
|
class Base
|
45
|
+
include XasLogger::Mix
|
46
|
+
|
43
47
|
def self.getCBs()
|
44
48
|
@globalCBList ||= Hash.new();
|
45
49
|
return @globalCBList;
|
@@ -49,10 +53,12 @@ module LZRTag
|
|
49
53
|
return @globalOptionDescriptions
|
50
54
|
end
|
51
55
|
|
52
|
-
def initialize(handler)
|
56
|
+
def initialize(handler, logName = self)
|
53
57
|
@localCBList = Hash.new();
|
54
58
|
|
55
59
|
@handler = handler
|
60
|
+
|
61
|
+
init_x_log(logName.to_s, nil);
|
56
62
|
end
|
57
63
|
|
58
64
|
# DSL function to describe an option of this hook.
|
@@ -7,11 +7,11 @@ module LZRTag
|
|
7
7
|
attr_accessor :eventWhitelist
|
8
8
|
attr_accessor :eventBlacklist
|
9
9
|
|
10
|
-
def initialize()
|
11
|
-
super();
|
10
|
+
def initialize(handler)
|
11
|
+
super(handler, "DBG");
|
12
12
|
|
13
13
|
@eventWhitelist = Array.new();
|
14
|
-
@eventBlacklist =
|
14
|
+
@eventBlacklist = [:slowTick, :gameTick, :playerInBeacon];
|
15
15
|
end
|
16
16
|
|
17
17
|
def consume_event(evtName, data)
|
@@ -22,7 +22,7 @@ module LZRTag
|
|
22
22
|
return unless @eventWhitelist.include? evtName
|
23
23
|
end
|
24
24
|
|
25
|
-
|
25
|
+
x_logd "Event: #{evtName} with data: #{data}";
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
@@ -32,23 +32,35 @@ module LZRTag
|
|
32
32
|
}
|
33
33
|
|
34
34
|
def initialize(handler, possibleTeams: [1, 2, 3, 4])
|
35
|
-
super(handler);
|
35
|
+
super(handler, "Team Selector");
|
36
36
|
|
37
37
|
@possibleTeams = possibleTeams;
|
38
38
|
end
|
39
39
|
|
40
|
+
def in_phase
|
41
|
+
return @handler.gamePhase == :teamSelect;
|
42
|
+
end
|
43
|
+
def is_selecting(pl)
|
44
|
+
return ([:idle, :teamSelect].include? pl.brightness)
|
45
|
+
end
|
46
|
+
|
40
47
|
on :gamePhaseEnds do |oldPhase, nextPhase|
|
41
48
|
if((oldPhase == :teamSelect) && (nextPhase != :idle))
|
42
|
-
|
49
|
+
x_logi("Selecting active players!");
|
43
50
|
|
44
|
-
|
51
|
+
nextPlayers = Array.new();
|
45
52
|
@handler.each do |pl|
|
46
|
-
if(pl.brightness
|
47
|
-
|
53
|
+
if([:active, :teamSelect].include? pl.brightness)
|
54
|
+
nextPlayers << pl;
|
55
|
+
else
|
56
|
+
pl.team = 0;
|
57
|
+
pl.brightness = :idle;
|
48
58
|
end
|
49
59
|
end
|
50
60
|
|
51
|
-
|
61
|
+
@handler.gamePlayers = nextPlayers;
|
62
|
+
|
63
|
+
x_logd("Participating players are: #{@handler.gamePlayers}")
|
52
64
|
end
|
53
65
|
end
|
54
66
|
|
@@ -58,27 +70,22 @@ module LZRTag
|
|
58
70
|
@handler.each do |pl|
|
59
71
|
pl.brightness = :idle;
|
60
72
|
|
61
|
-
|
73
|
+
unless(@possibleTeams.include?(pl.team))
|
62
74
|
pl.team = @possibleTeams.sample();
|
63
75
|
end
|
64
76
|
end
|
65
|
-
when :idle
|
66
|
-
@handler.each do |pl|
|
67
|
-
pl.brightness = :idle;
|
68
|
-
end
|
69
77
|
end
|
70
78
|
end
|
71
79
|
|
72
80
|
on :poseChanged do |pl, nPose|
|
73
|
-
next
|
74
|
-
next
|
81
|
+
next unless in_phase
|
82
|
+
next unless is_selecting(pl)
|
75
83
|
|
76
84
|
pl.brightness = (pl.gyroPose == :laidDown) ? :idle : :teamSelect;
|
77
85
|
end
|
78
86
|
|
79
87
|
on :navSwitchPressed do |player, dir|
|
80
|
-
next
|
81
|
-
next unless [:teamSelect, :idle].include? player.brightness
|
88
|
+
next unless in_phase
|
82
89
|
|
83
90
|
newTeam = @possibleTeams.find_index(player.team) || 0;
|
84
91
|
|
@@ -92,6 +99,26 @@ module LZRTag
|
|
92
99
|
player.brightness = :teamSelect
|
93
100
|
end
|
94
101
|
end
|
102
|
+
|
103
|
+
on :playerEnteredBeacon do |pl, beacon|
|
104
|
+
next unless in_phase
|
105
|
+
|
106
|
+
next unless is_selecting(pl)
|
107
|
+
next unless(@possibleTeams.include? beacon)
|
108
|
+
|
109
|
+
pl.team = beacon;
|
110
|
+
pl.brightness = :teamSelect;
|
111
|
+
end
|
112
|
+
|
113
|
+
on :playerLeftBeacon do |pl, beacon|
|
114
|
+
next unless in_phase
|
115
|
+
|
116
|
+
next unless(pl.team == beacon)
|
117
|
+
next unless is_selecting(pl)
|
118
|
+
|
119
|
+
pl.team = 0;
|
120
|
+
pl.brightness = :idle
|
121
|
+
end
|
95
122
|
end
|
96
123
|
|
97
124
|
class Regenerator < Base
|
@@ -139,7 +166,7 @@ module LZRTag
|
|
139
166
|
describe_option :dmgPerShot, "Base damage per shot"
|
140
167
|
describe_option :useDamageMultiplier, "Shall shots be adjusted per-gun?"
|
141
168
|
describe_option :friendlyFire, "Shall friendly-fire be enabled"
|
142
|
-
describe_option :hitThreshold, "Limit below dead players will not be hit"
|
169
|
+
describe_option :hitThreshold, "Limit below which dead players will not be hit"
|
143
170
|
|
144
171
|
def initialize(handler, **options)
|
145
172
|
super(handler);
|
@@ -170,5 +197,33 @@ module LZRTag
|
|
170
197
|
hitPlayer.hit();
|
171
198
|
end
|
172
199
|
end
|
200
|
+
|
201
|
+
class GunSelector < Base
|
202
|
+
describe_option :phaseFilter, "Which phase to be active during"
|
203
|
+
describe_option :teamFilter, "Which team to be active for"
|
204
|
+
|
205
|
+
def initialize(handler, **opts)
|
206
|
+
super(handler);
|
207
|
+
|
208
|
+
@phaseFilter = opts[:phaseFilter] || [:running]
|
209
|
+
@teamFilter = opts[:teamFilter] || (0..7).to_a
|
210
|
+
|
211
|
+
@guns = [1, 2];
|
212
|
+
end
|
213
|
+
|
214
|
+
on :navSwitchPressed do |pl, dir|
|
215
|
+
next unless @phaseFilter.include? @handler.gamePhase
|
216
|
+
next unless @teamFilter.include? pl.team
|
217
|
+
|
218
|
+
if(dir == 1)
|
219
|
+
pl.reload
|
220
|
+
elsif dir == 2
|
221
|
+
pl.gunNo = 3;
|
222
|
+
elsif dir == 3
|
223
|
+
oldInd = @guns.find_index(pl.gunNo) || 0;
|
224
|
+
pl.gunNo = @guns[(1+oldInd) % @guns.length] || 1
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
173
228
|
end
|
174
229
|
end
|
@@ -19,6 +19,11 @@ module LZRTag
|
|
19
19
|
# @return [String] status-string of the player. Should be "OK"
|
20
20
|
attr_reader :status
|
21
21
|
|
22
|
+
attr_reader :connected
|
23
|
+
|
24
|
+
# @return [Time] Time at which the player status was last updated
|
25
|
+
attr_reader :last_status_update
|
26
|
+
|
22
27
|
# @return [Integer] 0..255, shot ID of the player
|
23
28
|
attr_reader :id
|
24
29
|
# @return [Hash<Time>] Hash of the last few recorded shot times,
|
@@ -34,11 +39,14 @@ module LZRTag
|
|
34
39
|
@status = "";
|
35
40
|
@name = "";
|
36
41
|
|
42
|
+
@last_status_update = Time.at(0);
|
43
|
+
@connected = false;
|
44
|
+
|
37
45
|
@hitIDTimetable = Hash.new(Time.new(0));
|
38
46
|
end
|
39
47
|
|
40
48
|
def _pub_to(key, data, retain: false)
|
41
|
-
@mqtt.publish_to("Lasertag/Players/#{@DeviceID}/#{key}", data, retain: retain);
|
49
|
+
@mqtt.publish_to("Lasertag/Players/#{@DeviceID}/#{key}", data, retain: retain, qos: 1);
|
42
50
|
end
|
43
51
|
private :_pub_to
|
44
52
|
|
@@ -47,21 +55,38 @@ module LZRTag
|
|
47
55
|
case topic[1..topic.length].join("/")
|
48
56
|
when "Connection"
|
49
57
|
return if @status == data;
|
50
|
-
oldStatus = @status;
|
51
58
|
@status = data;
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
59
|
+
|
60
|
+
return if @status == "OK"
|
61
|
+
return if @status == ""
|
62
|
+
return if !@connected
|
63
|
+
@connected = false;
|
64
|
+
@handler.send_event(:playerDisconnected, self);
|
65
|
+
|
57
66
|
when "CFG/Name"
|
58
67
|
@name = data;
|
68
|
+
when "Ping"
|
69
|
+
@last_status_update = Time.now();
|
70
|
+
|
71
|
+
if(@status == "OK" && (!@connected))
|
72
|
+
@connected = true
|
73
|
+
@handler.send_event(:playerConnected, self);
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def _tick_connection()
|
79
|
+
return unless @connected
|
80
|
+
|
81
|
+
if((Time.now() - @last_status_update) > 60)
|
82
|
+
@connected = false;
|
83
|
+
@handler.send_event(:playerDisconnected, self);
|
59
84
|
end
|
60
85
|
end
|
61
86
|
|
62
87
|
# @return [Boolean] Whether this player is connected
|
63
88
|
def connected?()
|
64
|
-
return @
|
89
|
+
return @connected
|
65
90
|
end
|
66
91
|
|
67
92
|
# Set the Shot ID of the player.
|
@@ -41,16 +41,22 @@ module LZRTag
|
|
41
41
|
# Especially useful to determine when to revive a player
|
42
42
|
attr_reader :deathChangeTime
|
43
43
|
|
44
|
-
# Current ammo of the weapon.
|
45
|
-
# TODO one day this should be settable. Right now, it's just reading
|
46
|
-
attr_reader :ammo
|
47
|
-
# Maximum ammo the weapon can have with the currently equipped gun.
|
48
|
-
attr_reader :maxAmmo
|
49
44
|
# Number of the current gun.
|
50
45
|
# The application can freely choose which gun profile the set is using,
|
51
46
|
# which influences shot speeds, sounds, reloading, etc.
|
52
47
|
attr_reader :gunNo
|
53
48
|
|
49
|
+
# Current amount of reserve ammo (i.e. clips the player can reload with)
|
50
|
+
# Can be set to -1 to enable infinite reserve ammo (default), or
|
51
|
+
# any other value to give the player limited ammo
|
52
|
+
attr_reader :reserveAmmo
|
53
|
+
# Current ammo in the clip. Can be set to -1 for infinite shots (no
|
54
|
+
# reloading necessary at all), or any other numeric value. Default is
|
55
|
+
# a single clip (gun-dependant)
|
56
|
+
attr_reader :clipAmmo
|
57
|
+
# Size of the clip of the currently equipped gun. Can not be set!
|
58
|
+
attr_reader :clipSize
|
59
|
+
|
54
60
|
# Returns the gyro pose of the set.
|
55
61
|
# This is either:
|
56
62
|
# - :active
|
@@ -61,6 +67,9 @@ module LZRTag
|
|
61
67
|
# The :poseChanged event is sent on change with [player, newPose] data
|
62
68
|
attr_reader :gyroPose
|
63
69
|
|
70
|
+
# Returns a Hash of the last timestamps when a beacon was detected
|
71
|
+
attr_reader :beaconTimes
|
72
|
+
|
64
73
|
attr_reader :battery, :ping, :heap
|
65
74
|
|
66
75
|
def self.getBrightnessKeys()
|
@@ -76,8 +85,10 @@ module LZRTag
|
|
76
85
|
@dead = false;
|
77
86
|
@deathChangeTime = Time.now();
|
78
87
|
|
79
|
-
@
|
80
|
-
@
|
88
|
+
@reserveAmmo = 0;
|
89
|
+
@clipAmmo = 0;
|
90
|
+
@clipSize = 0;
|
91
|
+
|
81
92
|
@gunNo = 0;
|
82
93
|
|
83
94
|
@gyroPose = :unknown;
|
@@ -85,6 +96,9 @@ module LZRTag
|
|
85
96
|
@position = {x: 0, y: 0}
|
86
97
|
@zoneIDs = Hash.new();
|
87
98
|
|
99
|
+
@beaconTimes = Hash.new();
|
100
|
+
@BeaconTimeout = 3;
|
101
|
+
|
88
102
|
@battery = 0; @ping = 0; @heap = 0;
|
89
103
|
|
90
104
|
@BrightnessMap = self.class.getBrightnessKeys();
|
@@ -120,11 +134,12 @@ module LZRTag
|
|
120
134
|
|
121
135
|
@handler.send_event(@dead ? :playerKilled : :playerRevived, self);
|
122
136
|
when "Stats/Ammo"
|
123
|
-
return if(data.size !=
|
137
|
+
return if(data.size != 12)
|
124
138
|
|
125
139
|
outData = data.unpack("L<*");
|
126
|
-
@
|
127
|
-
@
|
140
|
+
@clipAmmo = outData[0];
|
141
|
+
@clipSize = outData[1];
|
142
|
+
@reserveAmmo = outData[2];
|
128
143
|
when "Position"
|
129
144
|
begin
|
130
145
|
@position = JSON.parse(data, symbolize_names: true);
|
@@ -135,6 +150,13 @@ module LZRTag
|
|
135
150
|
when "HW/Gyro"
|
136
151
|
@gyroPose = data.to_sym
|
137
152
|
@handler.send_event(:poseChanged, self, @gyroPose);
|
153
|
+
when "HW/BeaconDetect"
|
154
|
+
beaconID = data.to_i;
|
155
|
+
unless(@beaconTimes[beaconID])
|
156
|
+
@handler.send_event(:playerEnteredBeacon, self, beaconID);
|
157
|
+
end
|
158
|
+
@beaconTimes[beaconID] = Time.now();
|
159
|
+
@handler.send_event(:playerInBeacon, self, beaconID);
|
138
160
|
when "ZoneUpdate"
|
139
161
|
begin
|
140
162
|
data = JSON.parse(data, symbolize_names: true);
|
@@ -184,13 +206,14 @@ module LZRTag
|
|
184
206
|
|
185
207
|
def _set_dead(d, player = nil)
|
186
208
|
dead = (d ? true : false);
|
187
|
-
return if @dead == dead;
|
209
|
+
return false if @dead == dead;
|
188
210
|
@dead = dead;
|
189
211
|
|
190
212
|
@deathChangeTime = Time.now();
|
191
213
|
|
192
214
|
_pub_to "CFG/Dead", @dead ? "1" : "0", retain: true;
|
193
215
|
@handler.send_event(@dead ? :playerKilled : :playerRevived, self, player);
|
216
|
+
return true;
|
194
217
|
end
|
195
218
|
def dead=(d)
|
196
219
|
_set_dead(d);
|
@@ -204,14 +227,19 @@ module LZRTag
|
|
204
227
|
_set_dead(false, player)
|
205
228
|
end
|
206
229
|
|
207
|
-
def
|
208
|
-
unless (n.is_a?(Integer)
|
209
|
-
raise ArgumentError, "Ammo amount needs to be a
|
230
|
+
def reserveAmmo=(n)
|
231
|
+
unless (n.is_a?(Integer))
|
232
|
+
raise ArgumentError, "Ammo amount needs to be a number!"
|
210
233
|
end
|
211
234
|
|
212
|
-
|
235
|
+
_pub_to("Stats/Ammo/SetReserve", n);
|
236
|
+
end
|
237
|
+
def clipAmmo=(n)
|
238
|
+
unless (n.is_a?(Integer))
|
239
|
+
raise ArgumentError, "Ammo amount needs to be a number!"
|
240
|
+
end
|
213
241
|
|
214
|
-
_pub_to("Stats/Ammo/
|
242
|
+
_pub_to("Stats/Ammo/SetClip", n);
|
215
243
|
end
|
216
244
|
|
217
245
|
def gunNo=(n)
|
@@ -239,6 +267,20 @@ module LZRTag
|
|
239
267
|
return @GunDamageMultipliers[number-1] || 1;
|
240
268
|
end
|
241
269
|
|
270
|
+
def reload()
|
271
|
+
_pub_to("CFG/Reload", "1");
|
272
|
+
end
|
273
|
+
|
274
|
+
def check_beacons()
|
275
|
+
bIDs = @beaconTimes.keys;
|
276
|
+
bIDs.each do |bID|
|
277
|
+
if((Time.now() - @beaconTimes[bID]) > @BeaconTimeout)
|
278
|
+
@handler.send_event(:playerLeftBeacon, self, bID);
|
279
|
+
@beaconTimes.delete(bID)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
242
284
|
def clear_all_topics()
|
243
285
|
super();
|
244
286
|
|
@@ -18,7 +18,7 @@ module LZRTag
|
|
18
18
|
|
19
19
|
# Returns the last time the player was damaged.
|
20
20
|
# This can be useful to apply buffs and other data, as well as
|
21
|
-
# "post-damage
|
21
|
+
# "post-damage regeneration delay"
|
22
22
|
attr_reader :lastDamageTime
|
23
23
|
|
24
24
|
def initialize(*data)
|
@@ -45,17 +45,21 @@ module LZRTag
|
|
45
45
|
|
46
46
|
nLife = @life + amount;
|
47
47
|
nLife = @maxLife if(nLife > @maxLife)
|
48
|
-
return if nLife == @life;
|
48
|
+
return 0 if nLife == @life;
|
49
49
|
|
50
50
|
oLife = @life;
|
51
51
|
@life = nLife;
|
52
52
|
|
53
|
-
|
53
|
+
lifeDiff = @life - oLife;
|
54
|
+
|
55
|
+
@handler.send_event(:playerRegenerated, self, lifeDiff, source);
|
54
56
|
if(@life == maxLife)
|
55
57
|
@handler.send_event(:playerFullyRegenerated, self, source);
|
56
58
|
end
|
57
59
|
|
58
60
|
_pub_to("Stats/HP", @life.to_s, retain: true);
|
61
|
+
|
62
|
+
return lifeDiff
|
59
63
|
end
|
60
64
|
|
61
65
|
# Damage a player by a given amount with given source.
|
@@ -0,0 +1,107 @@
|
|
1
|
+
|
2
|
+
require_relative 'life_player.rb'
|
3
|
+
|
4
|
+
module LZRTag
|
5
|
+
module Player
|
6
|
+
class Statistics < Life
|
7
|
+
attr_reader :stats
|
8
|
+
|
9
|
+
def initialize(*args)
|
10
|
+
@stats = {
|
11
|
+
"Kills" => 0,
|
12
|
+
"Deaths" => 0,
|
13
|
+
"DamageDone" => 0,
|
14
|
+
"DamageReceived" => 0,
|
15
|
+
"Healed" => 0,
|
16
|
+
}
|
17
|
+
|
18
|
+
super(*args);
|
19
|
+
end
|
20
|
+
|
21
|
+
def _update_stat(key, value)
|
22
|
+
return unless(@stats.keys.include? key);
|
23
|
+
return if(@stats[key] == value);
|
24
|
+
|
25
|
+
@stats[key] = value;
|
26
|
+
_pub_to("Stats/#{key}", value, retain: true);
|
27
|
+
end
|
28
|
+
def _increment_stat(key, value)
|
29
|
+
_update_stat(key, @stats[key] + value);
|
30
|
+
end
|
31
|
+
|
32
|
+
def reset()
|
33
|
+
@stats.keys.each do |k|
|
34
|
+
@stats[k] = 0;
|
35
|
+
_pub_to("Stats/#{k}", 0, retain: true);
|
36
|
+
end
|
37
|
+
|
38
|
+
# super(); // TO DO!
|
39
|
+
end
|
40
|
+
|
41
|
+
def regenerate(*args)
|
42
|
+
healDone = super(*args);
|
43
|
+
|
44
|
+
_increment_stat("Healed", healDone);
|
45
|
+
end
|
46
|
+
def damage_by(*args)
|
47
|
+
dmg_done = super(*args);
|
48
|
+
|
49
|
+
_increment_stat("DamageReceived", dmg_done);
|
50
|
+
args[1]._increment_stat("DamageDone", dmg_done) if(args[1])
|
51
|
+
end
|
52
|
+
|
53
|
+
def _set_dead(d, player = nil)
|
54
|
+
return unless super(d, player);
|
55
|
+
return unless d;
|
56
|
+
|
57
|
+
player._increment_stat("Kills", 1) if(player);
|
58
|
+
|
59
|
+
_increment_stat("Deaths", 1);
|
60
|
+
end
|
61
|
+
|
62
|
+
def ratio_kd()
|
63
|
+
return @stats["Kills"]/([1, @stats["Deaths"]].max);
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
def self.print_start_line()
|
68
|
+
stats = ["Kills", "Deaths", "DMG Done", "DMG Rec", "Healed"]
|
69
|
+
sep = "\u2501" * 10;
|
70
|
+
|
71
|
+
puts "\u250F" + sep + ("\u252F" + sep) * (stats.count) + "\u2513";
|
72
|
+
puts "\u2503" + (" %8s \u2502" * (stats.count) + " %8s \u2503") % ["Name", stats].flatten;
|
73
|
+
puts "\u2523" + sep + ("\u253F" + sep)*(stats.count) + "\u252B";
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.print_end_line()
|
77
|
+
stats = ["Kills", "Deaths", "DMG Done", "DMG Rec", "Healed"]
|
78
|
+
sep = "\u2501" * 10;
|
79
|
+
|
80
|
+
puts "\u2517" + sep + ("\u2537" + sep)*(stats.count) + "\u251B";
|
81
|
+
end
|
82
|
+
|
83
|
+
def print_stat_line()
|
84
|
+
outStr = "\u2503 %8s ";
|
85
|
+
strArgs = [@name];
|
86
|
+
|
87
|
+
@stats.each do |key, val|
|
88
|
+
strArgs << val;
|
89
|
+
outStr += "\u2502 %8d ";
|
90
|
+
end
|
91
|
+
outStr += "\u2503";
|
92
|
+
|
93
|
+
puts outStr % strArgs;
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
|
98
|
+
def clear_all_topics()
|
99
|
+
super();
|
100
|
+
|
101
|
+
@stats.keys.each do |k|
|
102
|
+
_pub_to("Stats/#{k}", "", retain: true);
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
metadata
CHANGED
@@ -1,79 +1,65 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lzrtag-base
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Xasin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-10
|
11
|
+
date: 2019-11-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: json
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: '2.2'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: '2.2'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: mqtt-sub_handler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 0.1.6
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: minitest
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ">="
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - ">="
|
38
|
+
- - "~>"
|
53
39
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
40
|
+
version: 0.1.6
|
55
41
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
42
|
+
name: xasin-logger
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
58
44
|
requirements:
|
59
|
-
- - "
|
45
|
+
- - "~>"
|
60
46
|
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
62
|
-
type: :
|
47
|
+
version: '0.1'
|
48
|
+
type: :runtime
|
63
49
|
prerelease: false
|
64
50
|
version_requirements: !ruby/object:Gem::Requirement
|
65
51
|
requirements:
|
66
|
-
- - "
|
52
|
+
- - "~>"
|
67
53
|
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
54
|
+
version: '0.1'
|
69
55
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
56
|
+
name: xml-simple
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
72
58
|
requirements:
|
73
59
|
- - ">="
|
74
60
|
- !ruby/object:Gem::Version
|
75
61
|
version: '0'
|
76
|
-
type: :
|
62
|
+
type: :runtime
|
77
63
|
prerelease: false
|
78
64
|
version_requirements: !ruby/object:Gem::Requirement
|
79
65
|
requirements:
|
@@ -104,6 +90,7 @@ files:
|
|
104
90
|
- lib/lzrtag/player/effects_player.rb
|
105
91
|
- lib/lzrtag/player/hardware_player.rb
|
106
92
|
- lib/lzrtag/player/life_player.rb
|
93
|
+
- lib/lzrtag/player/stats_player.rb
|
107
94
|
homepage: https://github.com/XasWorks/LZRTag/
|
108
95
|
licenses:
|
109
96
|
- GPL-3.0
|
@@ -123,8 +110,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
123
110
|
- !ruby/object:Gem::Version
|
124
111
|
version: '0'
|
125
112
|
requirements: []
|
126
|
-
|
127
|
-
rubygems_version: 2.5.2.1
|
113
|
+
rubygems_version: 3.0.6
|
128
114
|
signing_key:
|
129
115
|
specification_version: 4
|
130
116
|
summary: Base classes for Xasin's LZRTag system
|