Class: Grueserve::Client

Inherits:
Object
  • Object
show all
Includes:
Debuggable, Rated
Defined in:
lib/grueserve/client.rb

Defined Under Namespace

Classes: Command, CommandSet, Location

Constant Summary

Constants included from Debuggable

Debuggable::LEVELS

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Rated

#max_rate_of

Methods included from Debuggable

format, level, level=, #method_missing, output, #report, #report_for, #reset, #reset_for, source_part, #time

Constructor Details

#initialize(options) ⇒ Client

Returns a new instance of Client.



60
61
62
63
64
65
66
67
68
# File 'lib/grueserve/client.rb', line 60

def initialize(options)
  self.socket = options.delete(:socket)
  @application = options.delete(:application)
  raise "Unknown options to #{self.class}.new: #{options.inspect}" unless options.empty?
  self.map = @application.map
  self.team = map.smallest_team
  @last_start_point = @application.map.start_point(self.team)
  @client_threads = Set.new
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Grueserve::Debuggable

Instance Attribute Details

#applicationObject

Returns the value of attribute application.



58
59
60
# File 'lib/grueserve/client.rb', line 58

def application
  @application
end

#client_threadsObject

Returns the value of attribute client_threads.



58
59
60
# File 'lib/grueserve/client.rb', line 58

def client_threads
  @client_threads
end

#last_start_pointObject

Returns the value of attribute last_start_point.



58
59
60
# File 'lib/grueserve/client.rb', line 58

def last_start_point
  @last_start_point
end

#readyObject

Returns the value of attribute ready.



58
59
60
# File 'lib/grueserve/client.rb', line 58

def ready
  @ready
end

Instance Method Details

#adjusted_damage(dmg) ⇒ Object



265
266
267
# File 'lib/grueserve/client.rb', line 265

def adjusted_damage(dmg)
  return dmg
end

#broadcast_message(m) ⇒ Object



198
199
200
201
202
# File 'lib/grueserve/client.rb', line 198

def broadcast_message(m)
  self.map.each_client do |client|
    client.send_message(m)
  end
end

#broadcast_noise(sound, source) ⇒ Object



190
191
192
193
194
195
196
# File 'lib/grueserve/client.rb', line 190

def broadcast_noise(sound, source)
  self.map.each_client do |client|
    noise_line = client.body.origo.to(source)
    noise_damp = application.map.noise_damp(noise_line)
    client.send_noise(sound, noise_damp, (noise_line.abs > 0 ? noise_line.angle : nil))
  end
end

#calculate_bullet_effects(bullet_line) ⇒ Object



144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/grueserve/client.rb', line 144

def calculate_bullet_effects(bullet_line)
  viewers = map.viewers_of(bullet_line.p1) + map.viewers_of(bullet_line.p2)
  viewers.each do |viewer|
    viewer.send_bullet(bullet_line)
  end
  broadcast_noise("shot", bullet_line.p1);
  Set.new(map.body_parts.intersections(bullet_line)).each do |intersection|
    unless (victim = map[intersection.last]) == self
      victim.shot_at(self, bullet_line)
    end
  end
end

#damageObject



311
312
313
# File 'lib/grueserve/client.rb', line 311

def damage
  0.0
end

#dead_timeObject



315
316
317
# File 'lib/grueserve/client.rb', line 315

def dead_time
  5
end

#fire_bullet(angle) ⇒ Object



137
138
139
140
141
142
# File 'lib/grueserve/client.rb', line 137

def fire_bullet(angle)
  bullet_line = body.origo.to(1000,0)
  bullet_line.angle = angle
  bullet_line.p2 = application.map.bullet_intersection(bullet_line)
  calculate_bullet_effects(bullet_line)
end

#fuzzObject

Uses the Box-Muller transform to generate a bit of normal distribution with variance 1



225
226
227
# File 'lib/grueserve/client.rb', line 225

def fuzz
  Math.sqrt(-2 * Math.log(rand)) * Math.cos(2 * Math::PI * rand)
end

#handle_helo(node) ⇒ Object



120
121
122
123
124
# File 'lib/grueserve/client.rb', line 120

def handle_helo(node)
  self.nickname = node["nickname"]
  self.nickname = "Anonymous" if self.nickname.empty?
  application.map.send_binaries(self)
end

#handle_input(message) ⇒ Object



229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'lib/grueserve/client.rb', line 229

def handle_input(message)
  case message.root.name
  when "MESSAGE"
    message.root.each_child do |child|
      case child.name
      when "HELO"
        extend(Soldier)
        handle_helo(child)
      when "READY"
        handle_ready
      when "COMMAND"
        self.current_command = CommandSet.new(child)
      when "PING"
        handle_ping
      end
    end
  else
    log_warn("Got unknown message: #{message.to_s}")
  end
end

#handle_pingObject



250
251
252
# File 'lib/grueserve/client.rb', line 250

def handle_ping
  self.ping!
end

#handle_policy_requestObject



109
110
111
112
113
114
115
116
117
118
# File 'lib/grueserve/client.rb', line 109

def handle_policy_request
  msg = XML::Document.new
  root = XML::Node.new("cross-domain-policy")
  access = XML::Node.new("allow-access-from")
  access["domain"] = "*"
  access["to-port"] = "*"
  root << access
  msg.root = root
  send_xml(msg.to_s)
end

#handle_readyObject



101
102
103
104
105
106
107
# File 'lib/grueserve/client.rb', line 101

def handle_ready
  self.body.relocate(last_start_point)
  refill
  self.register!
  broadcast_message("#{nickname} connected")
  update_viewing
end

#hit_me?(bullet_line) ⇒ Boolean

Returns:

  • (Boolean)


281
282
283
# File 'lib/grueserve/client.rb', line 281

def hit_me?(bullet_line)
  return !Map.blocks?(bullet_line.p1.to(body.origo).abs, 1.0 - profile)
end

#killed(client) ⇒ Object



285
286
287
288
289
290
291
292
293
294
# File 'lib/grueserve/client.rb', line 285

def killed(client)
  self.kills += 1
  if client.team == self.team
    broadcast_message("#{nickname} teamkilled #{client.nickname}")
    self.score -= 2
  else
    broadcast_message("#{nickname} killed #{client.nickname}")
    self.score += 2
  end
end

#killed_by(client) ⇒ Object



254
255
256
257
258
259
260
261
262
263
# File 'lib/grueserve/client.rb', line 254

def killed_by(client)
  self.score -= 1
  self.deaths += 1
  set_position(body.origo, :dead)
  broadcast_noise("scream", body.origo)
  thread_with_rescue do
    sleep(dead_time)
    revive
  end
end

#max_hitpointsObject



319
320
321
# File 'lib/grueserve/client.rb', line 319

def max_hitpoints
  10
end

#new_messageObject



70
71
72
73
74
75
# File 'lib/grueserve/client.rb', line 70

def new_message
  msg = XML::Document.new
  root = XML::Node.new("MESSAGE")
  msg.root = root
  return msg
end

#profileObject



330
331
332
333
334
335
# File 'lib/grueserve/client.rb', line 330

def profile
  rval = standing_profile
  rval /= 3.0 if state == :dodging
  rval *= application.map.protection_factor(body.origo)
  return rval
end

#refillObject



303
304
305
# File 'lib/grueserve/client.rb', line 303

def refill
  self.hitpoints = max_hitpoints
end

#reviveObject



296
297
298
299
300
301
# File 'lib/grueserve/client.rb', line 296

def revive
  new_position = application.map.start_point(self.team, self.last_start_point)
  set_position(new_position, :standing)
  self.last_start_point = new_position
  refill
end

#send_aim(x, y, radius) ⇒ Object



157
158
159
160
161
162
163
164
165
# File 'lib/grueserve/client.rb', line 157

def send_aim(x, y, radius)
  msg = new_message
  aim = XML::Node.new("AIM")
  aim["x"] = x.to_i.to_s
  aim["y"] = y.to_i.to_s
  aim["radius"] = radius.to_i.to_s
  msg.root << aim
  send_xml(msg.to_s)
end

#send_bin(key, val) ⇒ Object



126
127
128
129
130
# File 'lib/grueserve/client.rb', line 126

def send_bin(key, val)
  log_debug("Going to send bin to #{self}: #{key.inspect}") 
  log_trace(" => #{val.inspect}")
  send("bin:#{key}:#{val}")
end

#send_bullet(bullet_line) ⇒ Object



179
180
181
182
183
184
185
186
187
188
# File 'lib/grueserve/client.rb', line 179

def send_bullet(bullet_line)
  msg = new_message
  bullet = XML::Node.new("BULLET")
  bullet["x1"] = bullet_line.p1.x.to_i.to_s
  bullet["y1"] = bullet_line.p1.y.to_i.to_s
  bullet["x2"] = bullet_line.p2.x.to_i.to_s
  bullet["y2"] = bullet_line.p2.y.to_i.to_s
  msg.root << bullet
  send_xml(msg.to_s)
end

#send_message(m) ⇒ Object



204
205
206
207
208
209
210
# File 'lib/grueserve/client.rb', line 204

def send_message(m)
  msg = new_message
  broadcast = XML::Node.new("BROADCAST")
  broadcast["message"] = m
  msg.root << broadcast
  send_xml(msg.to_s)
end

#send_noise(sound, volume = 1.0, angle = nil) ⇒ Object



212
213
214
215
216
217
218
219
220
# File 'lib/grueserve/client.rb', line 212

def send_noise(sound, volume = 1.0, angle = nil)
  msg = new_message
  noise = XML::Node.new("NOISE")
  noise["angle"] = angle.to_s
  noise["volume"] = volume.to_s
  noise["sound"] = sound
  msg.root << noise
  send_xml(msg.to_s)
end

#send_throw(thro_line, speed) ⇒ Object



167
168
169
170
171
172
173
174
175
176
177
# File 'lib/grueserve/client.rb', line 167

def send_throw(thro_line, speed)
  msg = new_message
  thro = XML::Node.new("THROW")
  thro["x1"] = thro_line.p1.x.to_i.to_s
  thro["y1"] = thro_line.p1.y.to_i.to_s
  thro["x2"] = thro_line.p2.x.to_i.to_s
  thro["y2"] = thro_line.p2.y.to_i.to_s
  thro["speed"] = speed.to_i.to_s
  msg.root << thro
  send_xml(msg.to_s)
end

#send_xml(message) ⇒ Object



132
133
134
135
# File 'lib/grueserve/client.rb', line 132

def send_xml(message)
  log_debug("Going to send xml to #{self}: #{message.inspect}")
  send("xml:#{message}")
end

#shot_at(client, bullet_line) ⇒ Object



269
270
271
272
273
274
275
276
277
278
279
# File 'lib/grueserve/client.rb', line 269

def shot_at(client, bullet_line)
  if hit_me?(bullet_line)
    if self.state != :dead
      self.hitpoints -= adjusted_damage(client.damage)
      if self.hitpoints <= 0
        killed_by(client)
        client.killed(self)
      end
    end
  end
end

#shutdownObject



88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/grueserve/client.rb', line 88

def shutdown
  if registered?
    self.unregister!
    client_threads.each do |thread|
      thread.kill
    end
    viewers.each do |viewer|
      viewer.send_disappearance(self)
    end
    broadcast_message("#{nickname} disconnected")
  end
end

#speedObject



323
324
325
326
327
328
# File 'lib/grueserve/client.rb', line 323

def speed
  rval = running_speed
  rval /= 5.0 if state == :dodging
  rval *= application.map.speed_factor(body.origo)
  return rval
end

#standing_profileObject



307
308
309
# File 'lib/grueserve/client.rb', line 307

def standing_profile
  1.0
end

#thread_with_rescue(&block) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/grueserve/client.rb', line 76

def thread_with_rescue(&block)
  new_thread = Thread.new do
    begin
      yield
    rescue Exception => e
      log_fatal(e)
    ensure
      self.client_threads.delete(Thread.current)
    end
  end
  self.client_threads << new_thread
end