/
dispatcher.rb
142 lines (130 loc) · 4.97 KB
/
dispatcher.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
module AresMUSH
class Dispatcher
# Places a new command in the queue to be processed.
def queue_command(client, cmd)
EventMachine.next_tick do
AresMUSH.with_error_handling(client, "Queue command.") do
on_command(client, cmd)
end
end
end
# Place a new event in the queue to be processed.
def queue_event(event)
EventMachine.next_tick do
AresMUSH.with_error_handling(nil, "Queue event.") do
on_event(event)
end
end
end
# Place an action in the queue to be run after APPROXIMATELY the specified number of seconds.
# The dispatcher is not a precise timer.
def queue_timer(seconds, description, client, &block)
EventMachine.add_timer(seconds) do
AresMUSH.with_error_handling(client, description) do
yield block
end
end
end
# Places a new action in the queue to be processed.
def queue_action(client, &block)
EventMachine.next_tick do
AresMUSH.with_error_handling(client, "Queue action.") do
yield block
end
end
end
# Spawns a separate task to handle something in the background while doing other things.
# This is good for rendering templates and doing file IO. USE CAUTION to make sure the code
# called by your action is thread-safe. You can set a callback method that will be triggered
# with the return value of the block.
#
# For example, this will emit "Task complete!" after doing the long task.
#
# callback = Proc.new { |text| client.emit text }
# Global.dispatcher.spawn("Doing something", client, callback) do
# do_some_long_task
# "Task complete!"
# end
def spawn(description, client, callback = nil, &block)
EventMachine.defer do
AresMUSH.with_error_handling(client, description) do
return_val = yield block
callback.call return_val if callback
end
end
end
### IMPORTANT!!! Do not call from outside of the dispatcher.
### Use queue_command if you need to queue up a command to process
def on_command(client, cmd)
@handled = false
with_error_handling(client, cmd) do
enactor = client.find_char
if (enactor && enactor.is_statue?)
client.emit_failure t('dispatcher.you_are_statue')
return
end
CommandAliasParser.substitute_aliases(enactor, cmd, Global.plugin_manager.shortcuts)
Global.plugin_manager.plugins.each do |p|
next if !p.respond_to?(:get_cmd_handler)
AresMUSH.with_error_handling(client, cmd) do
handler_class = p.get_cmd_handler(client, cmd, enactor)
if (handler_class)
@handled = true
handler = handler_class.new(client, cmd, enactor)
handler.on_command
return
end # if
end # with error handling
end # each
if (!@handled)
client.emit_ooc t('dispatcher.huh')
end
end # with error handling
end
### IMPORTANT!!! Do not call from outside of the dispatcher.
### Use queue_event if you need to queue up an event
def on_event(event)
begin
event_name = event.class.to_s.gsub("AresMUSH::", "")
Global.plugin_manager.plugins.each do |p|
next if !p.respond_to?(:get_event_handler)
AresMUSH.with_error_handling(nil, "Handling #{event_name}.") do
handler_class = p.get_event_handler(event_name)
if (handler_class)
spawn("Handling #{event_name} with #{p}", nil) do
handler = handler_class.new
handler.on_event(event)
end
end # if
end # with error handling
end # each
rescue Exception => e
Global.logger.error("Error handling event: event=#{event} error=#{e} backtrace=#{e.backtrace[0,10]}")
end
end
### IMPORTANT!!! Do not call from outside of the event machine reactor loop!
def on_web_request(request)
handled = false
AresMUSH.with_error_handling(nil, "Web Request") do
Global.plugin_manager.plugins.each do |p|
next if !p.respond_to?(:get_web_request_handler)
handler_class = p.get_web_request_handler(request)
if (handler_class)
handled = true
handler = handler_class.new
return handler.handle(request)
end # if
end # each
end # with error handling
Global.logger.error("Unhandled web request: #{request.json}.")
return { error: "Oops! Something went wrong when the website talked to the game. Please try again and alert staff is the problem persists." }
end
private
def with_error_handling(client, cmd, &block)
return_val = AresMUSH.with_error_handling(client, "Command #{cmd.raw}", &block)
if (!return_val)
@handled = true
end
end
end
end