Module: Quake::EntityParser
- Defined in:
- lib/quake/entity.rb
Overview
Parses the BSP entity string into an array of Entity objects.
Constant Summary collapse
- SINGLE_CHAR_TOKENS =
"{})(:'"- FIELD_NAMES =
%w[ absmax absmin aflag aiment air_finished ammo_cells ammo_nails ammo_rockets ammo_shells angles armortype armorvalue attack_finished attack_state avelocity axhitme blocked bubble_count button0 button1 button2 chain classname cnt colormap count currentammo deadflag deathtype delay dest dest1 dest2 distance dmg dmg_inflictor dmg_save dmg_take effects enemy finalangle finaldest fixangle flags fly_sound frags frame goalentity gravity groundentity health height ideal_yaw impulse invincible_finished invincible_sound invincible_time invisible_finished invisible_sound invisible_time items jump_flag killtarget lastruntime lefty light_lev lip ltime mangle map max_health maxs maxspeed mdl message mins model modelindex movedir movetarget movetype netname nextthink noise noise1 noise2 noise3 noise4 oldenemy oldorigin origin owner pain_finished pausetime pos1 pos2 rad_time radsuit_finished search_time show_hostile size skin solid sounds spawnflags speed state style super_damage_finished super_sound super_time swim_flag t_length t_width takedamage target targetname team teleport_time think touch trigger_field use v_angle velocity view_ofs voided volume wad wait waitmax waitmin walkframe waterlevel watertype weapon weaponframe weaponmodel worldtype yaw_speed ].each_with_object({}) { |name, fields| fields[name] = true }.freeze
Class Method Summary collapse
-
.build_target_map(entities) ⇒ Object
Build a lookup table: targetname -> [Entity].
- .decode_string(value) ⇒ Object
- .normalize_key(key) ⇒ Object
- .parse(entity_string) ⇒ Object
- .tokenize(data) ⇒ Object
Class Method Details
.build_target_map(entities) ⇒ Object
Build a lookup table: targetname -> [Entity]
496 497 498 499 500 501 502 |
# File 'lib/quake/entity.rb', line 496 def self.build_target_map(entities) map = Hash.new { |h, k| h[k] = [] } entities.each do |ent| map[ent.targetname] << ent if ent.targetname end map end |
.decode_string(value) ⇒ Object
491 492 493 |
# File 'lib/quake/entity.rb', line 491 def self.decode_string(value) value.gsub(/\\./) { |match| match == "\\n" ? "\n" : "\\" } end |
.normalize_key(key) ⇒ Object
486 487 488 489 |
# File 'lib/quake/entity.rb', line 486 def self.normalize_key(key) key = "light_lev" if key == "light" key.rstrip end |
.parse(entity_string) ⇒ Object
393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 |
# File 'lib/quake/entity.rb', line 393 def self.parse(entity_string) return [] if entity_string.nil? entities = [] current = nil tokens = tokenize(entity_string) index = 0 while index < tokens.length token = tokens[index] if current.nil? raise "ED_LoadFromFile: found #{token} when expecting {" unless token == "{" current = {} index += 1 next end if token == "}" entities << Entity.new(current) if current["classname"] current = nil index += 1 next end key = normalize_key(token) index += 1 raise "ED_ParseEntity: EOF without closing brace" if index >= tokens.length value = tokens[index] raise "ED_ParseEntity: closing brace without data" if value == "}" value = decode_string(value) unless key.start_with?("_") || (key != "angle" && !FIELD_NAMES[key]) if key == "angle" current["angles"] = "0 #{value} 0" else current[key] = value end end index += 1 end raise "ED_ParseEntity: EOF without closing brace" if current entities end |
.tokenize(data) ⇒ Object
442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 |
# File 'lib/quake/entity.rb', line 442 def self.tokenize(data) tokens = [] index = 0 while index < data.length char = data[index] break if char == "\0" if char.ord <= 32 index += 1 next end if char == "/" && data[index + 1] == "/" index += 2 index += 1 while index < data.length && data[index] != "\n" next end if char == '"' index += 1 start = index index += 1 while index < data.length && data[index] != '"' tokens << data[start...index] index += 1 next end if SINGLE_CHAR_TOKENS.include?(char) tokens << char index += 1 next end start = index while index < data.length && data[index].ord > 32 && !SINGLE_CHAR_TOKENS.include?(data[index]) index += 1 end tokens << data[start...index] end tokens end |