Class: LZRTag::Handler::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/lzrtag/handler/base_handler.rb

Overview

The base handler class. This class code deals with the most rudimentary systems:

  • It handles the MQTT connection

  • It registers new players and distributes MQTT data to the respective class

  • It hands out Player IDs to connected players

  • It runs the event loop system and manages hooks

In it’s simplest form it can be instantiated with just a MQTT handler:

Examples:

# Using LZRTag.Handler instead of LZRTag::Handler::Base to fetch the latest handler
handler = LZRTag.Handler.new(mqttConn);

Direct Known Subclasses

HitArb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(mqtt, playerClass = Player::Life, clean_on_exit: true) ⇒ Base

Returns a new instance of Base.



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/lzrtag/handler/base_handler.rb', line 29

def initialize(mqtt, playerClass = Player::Life, clean_on_exit: true)
	@mqtt = mqtt;

	@playerClass = playerClass;

	@players = Hash.new();
	@idTable = Hash.new();

	@playerSynchMutex = Mutex.new();

	@hooks = [self];
	@eventQueue = Queue.new();

	@eventThread = Thread.new do
		loop do
			nextData = @eventQueue.pop;
			@hooks.each do |h|
				h.consume_event(nextData[0], nextData[1]);
			end
		end
	end
	@eventThread.abort_on_exception = true;

	@mqtt.subscribe_to "Lasertag/Players/#" do |data, topic|
		dID = topic[0];
		if(not @players.key? dID)
			@playerSynchMutex.synchronize {
				@players[dID] = @playerClass.new(dID, self);
			}
			send_event(:playerRegistered, @players[dID]);
		end

		@players[dID].on_mqtt_data(data, topic);
	end

	if(clean_on_exit)
		at_exit {
			@playerSynchMutex.synchronize {
				@players.each do |id, player|
					player.clear_all_topics();
					sleep 0.1;
				end
			}
			sleep 0.5;
		}
	end

	puts "I LZR::Handler init finished".green
end

Instance Attribute Details

#idTableObject (readonly)

Returns the ID-Table, a Hash of Players and their matched IDs



27
28
29
# File 'lib/lzrtag/handler/base_handler.rb', line 27

def idTable
  @idTable
end

#mqttObject (readonly)

Returns the MQTT connection



24
25
26
# File 'lib/lzrtag/handler/base_handler.rb', line 24

def mqtt
  @mqtt
end

Instance Method Details

#[](c) ⇒ Object Also known as: get_player

Return a player either by their ID or their DeviceID

Returns:

  • LZRTag::Player::Base

Raises:

  • (ArgumentError)


139
140
141
142
143
144
# File 'lib/lzrtag/handler/base_handler.rb', line 139

def [](c)
	return @players[c] if c.is_a? String
	return @idTable[c] if c.is_a? Integer

	raise ArgumentError, "Unknown identifier for the player id!"
end

#add_hook(hook) ⇒ Object

Add or instantiate a new hook. This function will take either a Class of Hook::Base or an instance of it, and add it to the current list of hooks, thusly including it in the event processing

Parameters:

Returns:

  • The added hook



111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/lzrtag/handler/base_handler.rb', line 111

def add_hook(hook)
	hook = hook.new(self) if hook.is_a? Class and hook <= LZRTag::Hook::Base;

	unless(hook.is_a? LZRTag::Hook::Base)
		raise ArgumentError, "Hook needs to be a Lasertag::EventHook!"
	end

	return if(@hooks.include? hook);
	hook.on_hookin(self);
	@hooks << hook;

	return hook;
end

#consume_event(evtName, data) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/lzrtag/handler/base_handler.rb', line 90

def consume_event(evtName, data)
	case evtName
	when :playerConnected
		player = data[0];
		i = 1;
		while(@idTable[i]) do i+=1; end
		@idTable[i] = player;
		player.id = i;
	when :playerDisconnected
		player = data[0];
		@idTable[player.id] = nil;
		player.id = nil;
	end
end

#each(connected: false) {|player| ... } ⇒ Object

Run the provided block on each registered player.

Parameters:

  • connected (defaults to: false)

    Only yield for connected players

Yields:

  • (player)

    Yields for every played. With connected = true, only yields connected players



151
152
153
154
155
156
157
# File 'lib/lzrtag/handler/base_handler.rb', line 151

def each(connected: false)
	@playerSynchMutex.synchronize {
		@players.each do |_, player|
			yield(player) if(player.connected? | !connected);
		end
	}
end

#num_connectedObject

Returns the number of currently connected players



160
161
162
163
164
165
166
# File 'lib/lzrtag/handler/base_handler.rb', line 160

def num_connected()
	n = 0;
	self.each_connected do
		n += 1;
	end
	return n;
end

#remove_hook(hook) ⇒ Object

Remove an existing hook from the system. This will remove the provided hook instance from the event handling

Parameters:



127
128
129
130
131
132
133
134
135
# File 'lib/lzrtag/handler/base_handler.rb', line 127

def remove_hook(hook)
	unless(hook.is_a? Lasertag::EventHook)
		raise ArgumentError, "Hook needs to be a Lasertag::EventHook!"
	end

	return unless @hooks.include? hook
	hook.on_hookout();
	@hooks.delete(hook);
end

#send_event(evtName, *data) ⇒ Object

Send an event into the event loop. Any events will be queued and will be executed in-order by a separate thread. The provided data will be passed along to the hooks

Parameters:

  • evtName (Symbol)

    Name of the event

  • *data

    Any additional data to send along with the event

Raises:

  • (ArgumentError)


84
85
86
87
# File 'lib/lzrtag/handler/base_handler.rb', line 84

def send_event(evtName, *data)
	raise ArgumentError, "Event needs to be a symbol!" unless evtName.is_a? Symbol;
	@eventQueue << [evtName, data];
end