grueserve 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. data/bin/grueserve +6 -0
  2. data/bin/grueserve_path2lines +59 -0
  3. data/example/attributes.yaml +28 -0
  4. data/example/map.gif +0 -0
  5. data/example/sprites/black_soldier_dead.gif +0 -0
  6. data/example/sprites/black_soldier_dodging_0PI1_1.gif +0 -0
  7. data/example/sprites/black_soldier_dodging_0PI1_2.gif +0 -0
  8. data/example/sprites/black_soldier_dodging_0PI1_3.gif +0 -0
  9. data/example/sprites/black_soldier_dodging_1PI1_1.gif +0 -0
  10. data/example/sprites/black_soldier_dodging_1PI1_2.gif +0 -0
  11. data/example/sprites/black_soldier_dodging_1PI1_3.gif +0 -0
  12. data/example/sprites/black_soldier_dodging_1PI2_1.gif +0 -0
  13. data/example/sprites/black_soldier_dodging_1PI2_2.gif +0 -0
  14. data/example/sprites/black_soldier_dodging_1PI2_3.gif +0 -0
  15. data/example/sprites/black_soldier_dodging_3PI2_1.gif +0 -0
  16. data/example/sprites/black_soldier_dodging_3PI2_2.gif +0 -0
  17. data/example/sprites/black_soldier_dodging_3PI2_3.gif +0 -0
  18. data/example/sprites/black_soldier_standing_0PI1_1.gif +0 -0
  19. data/example/sprites/black_soldier_standing_0PI1_2.gif +0 -0
  20. data/example/sprites/black_soldier_standing_0PI1_3.gif +0 -0
  21. data/example/sprites/black_soldier_standing_1PI1_1.gif +0 -0
  22. data/example/sprites/black_soldier_standing_1PI1_2.gif +0 -0
  23. data/example/sprites/black_soldier_standing_1PI1_3.gif +0 -0
  24. data/example/sprites/black_soldier_standing_1PI2_1.gif +0 -0
  25. data/example/sprites/black_soldier_standing_1PI2_2.gif +0 -0
  26. data/example/sprites/black_soldier_standing_1PI2_3.gif +0 -0
  27. data/example/sprites/black_soldier_standing_3PI2_1.gif +0 -0
  28. data/example/sprites/black_soldier_standing_3PI2_2.gif +0 -0
  29. data/example/sprites/black_soldier_standing_3PI2_3.gif +0 -0
  30. data/example/sprites/brown_soldier_dead.gif +0 -0
  31. data/example/sprites/brown_soldier_dodging_0PI1_1.gif +0 -0
  32. data/example/sprites/brown_soldier_dodging_0PI1_2.gif +0 -0
  33. data/example/sprites/brown_soldier_dodging_0PI1_3.gif +0 -0
  34. data/example/sprites/brown_soldier_dodging_1PI1_1.gif +0 -0
  35. data/example/sprites/brown_soldier_dodging_1PI1_2.gif +0 -0
  36. data/example/sprites/brown_soldier_dodging_1PI1_3.gif +0 -0
  37. data/example/sprites/brown_soldier_dodging_1PI2_1.gif +0 -0
  38. data/example/sprites/brown_soldier_dodging_1PI2_2.gif +0 -0
  39. data/example/sprites/brown_soldier_dodging_1PI2_3.gif +0 -0
  40. data/example/sprites/brown_soldier_dodging_3PI2_1.gif +0 -0
  41. data/example/sprites/brown_soldier_dodging_3PI2_2.gif +0 -0
  42. data/example/sprites/brown_soldier_dodging_3PI2_3.gif +0 -0
  43. data/example/sprites/brown_soldier_standing_0PI1_1.gif +0 -0
  44. data/example/sprites/brown_soldier_standing_0PI1_2.gif +0 -0
  45. data/example/sprites/brown_soldier_standing_0PI1_3.gif +0 -0
  46. data/example/sprites/brown_soldier_standing_1PI1_1.gif +0 -0
  47. data/example/sprites/brown_soldier_standing_1PI1_2.gif +0 -0
  48. data/example/sprites/brown_soldier_standing_1PI1_3.gif +0 -0
  49. data/example/sprites/brown_soldier_standing_1PI2_1.gif +0 -0
  50. data/example/sprites/brown_soldier_standing_1PI2_2.gif +0 -0
  51. data/example/sprites/brown_soldier_standing_1PI2_3.gif +0 -0
  52. data/example/sprites/brown_soldier_standing_3PI2_1.gif +0 -0
  53. data/example/sprites/brown_soldier_standing_3PI2_2.gif +0 -0
  54. data/example/sprites/brown_soldier_standing_3PI2_3.gif +0 -0
  55. data/example/sprites/explosion_1.gif +0 -0
  56. data/example/sprites/explosion_10.gif +0 -0
  57. data/example/sprites/explosion_11.gif +0 -0
  58. data/example/sprites/explosion_12.gif +0 -0
  59. data/example/sprites/explosion_13.gif +0 -0
  60. data/example/sprites/explosion_14.gif +0 -0
  61. data/example/sprites/explosion_15.gif +0 -0
  62. data/example/sprites/explosion_16.gif +0 -0
  63. data/example/sprites/explosion_17.gif +0 -0
  64. data/example/sprites/explosion_18.gif +0 -0
  65. data/example/sprites/explosion_19.gif +0 -0
  66. data/example/sprites/explosion_2.gif +0 -0
  67. data/example/sprites/explosion_20.gif +0 -0
  68. data/example/sprites/explosion_21.gif +0 -0
  69. data/example/sprites/explosion_22.gif +0 -0
  70. data/example/sprites/explosion_23.gif +0 -0
  71. data/example/sprites/explosion_24.gif +0 -0
  72. data/example/sprites/explosion_25.gif +0 -0
  73. data/example/sprites/explosion_26.gif +0 -0
  74. data/example/sprites/explosion_27.gif +0 -0
  75. data/example/sprites/explosion_3.gif +0 -0
  76. data/example/sprites/explosion_4.gif +0 -0
  77. data/example/sprites/explosion_5.gif +0 -0
  78. data/example/sprites/explosion_6.gif +0 -0
  79. data/example/sprites/explosion_7.gif +0 -0
  80. data/example/sprites/explosion_8.gif +0 -0
  81. data/example/sprites/explosion_9.gif +0 -0
  82. data/example/sprites/green_soldier_dead.gif +0 -0
  83. data/example/sprites/green_soldier_dodging_0PI1_1.gif +0 -0
  84. data/example/sprites/green_soldier_dodging_0PI1_2.gif +0 -0
  85. data/example/sprites/green_soldier_dodging_0PI1_3.gif +0 -0
  86. data/example/sprites/green_soldier_dodging_1PI1_1.gif +0 -0
  87. data/example/sprites/green_soldier_dodging_1PI1_2.gif +0 -0
  88. data/example/sprites/green_soldier_dodging_1PI1_3.gif +0 -0
  89. data/example/sprites/green_soldier_dodging_1PI2_1.gif +0 -0
  90. data/example/sprites/green_soldier_dodging_1PI2_2.gif +0 -0
  91. data/example/sprites/green_soldier_dodging_1PI2_3.gif +0 -0
  92. data/example/sprites/green_soldier_dodging_3PI2_1.gif +0 -0
  93. data/example/sprites/green_soldier_dodging_3PI2_2.gif +0 -0
  94. data/example/sprites/green_soldier_dodging_3PI2_3.gif +0 -0
  95. data/example/sprites/green_soldier_standing_0PI1_1.gif +0 -0
  96. data/example/sprites/green_soldier_standing_0PI1_2.gif +0 -0
  97. data/example/sprites/green_soldier_standing_0PI1_3.gif +0 -0
  98. data/example/sprites/green_soldier_standing_1PI1_1.gif +0 -0
  99. data/example/sprites/green_soldier_standing_1PI1_2.gif +0 -0
  100. data/example/sprites/green_soldier_standing_1PI1_3.gif +0 -0
  101. data/example/sprites/green_soldier_standing_1PI2_1.gif +0 -0
  102. data/example/sprites/green_soldier_standing_1PI2_2.gif +0 -0
  103. data/example/sprites/green_soldier_standing_1PI2_3.gif +0 -0
  104. data/example/sprites/green_soldier_standing_3PI2_1.gif +0 -0
  105. data/example/sprites/green_soldier_standing_3PI2_2.gif +0 -0
  106. data/example/sprites/green_soldier_standing_3PI2_3.gif +0 -0
  107. data/ext/extconf.rb +93 -0
  108. data/ext/grueserve_ext.c +2083 -0
  109. data/lib/grueserve.rb +28 -0
  110. data/lib/grueserve/application.rb +72 -0
  111. data/lib/grueserve/client.rb +339 -0
  112. data/lib/grueserve/debuggable.rb +114 -0
  113. data/lib/grueserve/map.rb +178 -0
  114. data/lib/grueserve/rated.rb +44 -0
  115. data/lib/grueserve/server.rb +201 -0
  116. data/lib/grueserve/soldier.rb +181 -0
  117. metadata +179 -0
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'grueserve'
5
+
6
+ Grueserve::Application.new.go
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ if ARGV.size < 1 || !File.exists?(ARGV.first)
4
+ puts "Usage: #{$0} GIMP_POLYGON_PATH_EXPORT_FILE"
5
+ exit 1
6
+ end
7
+
8
+ require 'rexml/document'
9
+ require 'pp'
10
+
11
+ lines = []
12
+ current_points = []
13
+ d = REXML::Document.new(open(ARGV.first).read)
14
+ d.each_element("svg/path") do |element|
15
+ mode = :start
16
+ element.attributes["d"].split.each do |word|
17
+ pieces = [word]
18
+ if match = word.match(/([\d.,]+)M/)
19
+ pieces = [match[1], "M"]
20
+ end
21
+ for piece in pieces
22
+ if piece == "M"
23
+ unless current_points.empty?
24
+ lines << current_points
25
+ current_points = []
26
+ end
27
+ mode = :first_point
28
+ elsif mode == :first_point && (match = piece.match(/([\d.]+),([\d.]+)/))
29
+ current_points << [match[1].to_i, match[2].to_i]
30
+ mode = :first_point_control
31
+ elsif mode == :first_point_control && (match = piece.match(/([\d.]+),([\d.]+)/))
32
+ mode = :data
33
+ elsif mode == :data && (match = piece.match(/([\d.]+),([\d.]+)/))
34
+ current_points << [match[1].to_i, match[2].to_i]
35
+ mode = :control_1
36
+ elsif mode == :control_1 && piece =~ /([\d.]+),([\d.]+)/
37
+ mode = :control_2
38
+ elsif mode == :control_2 && (match = piece.match(/([\d.]+),([\d.]+)/))
39
+ mode = :data
40
+ elsif mode == :control_2 && piece == "Z"
41
+ current_points << :loop
42
+ mode = :start
43
+ end
44
+ end
45
+ end
46
+ unless current_points.empty?
47
+ lines << current_points
48
+ end
49
+ end
50
+ puts(lines.collect do |line|
51
+ line.collect do |point|
52
+ case point
53
+ when Symbol
54
+ point.to_s
55
+ when Array
56
+ "#{point.first},#{point.last}"
57
+ end
58
+ end.join(" ")
59
+ end.join(":"))
@@ -0,0 +1,28 @@
1
+ ---
2
+ map: map.gif
3
+ teams: green black
4
+ green_start_points: 144,396 72,80 280,64
5
+ black_start_points: 48,568 156,768 432,780
6
+ hearing_distance_cutoff: 100
7
+ viewing_distance_limit: 1000
8
+
9
+ movement_obstacles: 312,40 463,40 463,246 312,246 loop:691,60 955,60 955,514 691,514 loop:28,433 282,433 282,525 28,525 loop:685,703 925,703 925,855 685,855 loop:78,1111 319,1111 319,1263 78,1263 loop:181,1341 423,1341 423,1491 181,1491 loop:91,1636 333,1636 333,1786 91,1786 loop:690,1824 981,1824 981,1900 690,1900 loop:378,759 370,748 378,739 385,745 loop:201,736 190,723 202,714 210,723 loop:127,835 148,828 174,831 199,831 220,819 249,810 271,811 291,828 316,844 343,853 378,859 396,879 405,907 388,930 366,951 354,978 339,1006 313,1011 297,984 274,966 244,963 208,963 172,957 153,930 147,898 130,874 121,856 loop:846,964 862,978 879,999 880,1027 877,1065 870,1096 864,1132 859,1164 859,1189 856,1233 856,1297 864,1350 874,1408 885,1465 882,1537 867,1579 843,1623 822,1644 801,1650 784,1644 780,1624 778,1585 774,1528 762,1488 756,1428 754,1381 771,1333 787,1282 789,1252 780,1215 768,1164 772,1108 786,1059 792,1023 789,981 805,964 822,955 loop:0,0 1023,0 1023,2064 0,2064 loop
10
+
11
+ visibility_obstacles: 312,40 463,40 463,246 312,246 loop:691,60 955,60 955,514 691,514 loop:28,433 282,433 282,525 28,525 loop:685,703 925,703 925,855 685,855 loop:78,1111 319,1111 319,1263 78,1263 loop:181,1341 423,1341 423,1491 181,1491 loop:91,1636 333,1636 333,1786 91,1786 loop:690,1824 981,1824 981,1900 690,1900 loop:378,759 370,748 378,739 385,745 loop:201,736 190,723 202,714 210,723 loop
12
+
13
+ bullet_obstacles: 312,40 463,40 463,246 312,246 loop:691,60 955,60 955,514 691,514 loop:28,433 282,433 282,525 28,525 loop:685,703 925,703 925,855 685,855 loop:78,1111 319,1111 319,1263 78,1263 loop:181,1341 423,1341 423,1491 181,1491 loop:91,1636 333,1636 333,1786 91,1786 loop:690,1824 981,1824 981,1900 690,1900 loop:378,759 370,748 378,739 385,745 loop:201,736 190,723 202,714 210,723 loop
14
+
15
+ hearing_obstacles_default_value: 800
16
+ hearing_obstacles: 312,40 463,40 463,246 312,246 loop=500:691,60 955,60 955,514 691,514 loop:28,433 282,433 282,525 28,525 loop:685,703 925,703 925,855 685,855 loop:78,1111 319,1111 319,1263 78,1263 loop:181,1341 423,1341 423,1491 181,1491 loop:91,1636 333,1636 333,1786 91,1786 loop:690,1824 981,1824 981,1900 690,1900 loop:378,759 370,748 378,739 385,745 loop:201,736 190,723 202,714 210,723 loop=2000
17
+
18
+ fortifications_default_value: 500
19
+ fortifications: 383,488 502,489:391,649 511,649=800
20
+
21
+ speed_areas_default_value: 1500
22
+ speed_areas: 176,230 256,102 256,362 96,362 340,322 96,100 loop:340,322 258,350 256,300 370,300 370,574 314,574 576,604 314,348 loop:576,604 2,574 0,630 1018,630 574,554 1018,576 loop=1600:574,554 628,2 520,2 520,2054 628,2054 loop=1700
23
+
24
+ protection_areas_default_value: 500
25
+ protection_areas: 204,725 168,703 183,693 205,711 219,705 232,725 230,748 218,740 215,748 202,736 186,758 174,728 167,721 375,750 174,713 loop:375,750 343,747 358,731 374,736 402,721 421,730 408,739 424,756 414,757 398,786 379,761 362,773 357,767 340,776 347,753 loop=600
26
+
27
+ hidden_areas_default_value: 50000
28
+ hidden_areas: 204,725 168,703 183,693 205,711 219,705 232,725 230,748 218,740 215,748 202,736 186,758 174,728 167,721 375,750 174,713 loop:375,750 343,747 358,731 374,736 402,721 421,730 408,739 424,756 414,757 398,786 379,761 362,773 357,767 340,776 347,753 loop
Binary file
@@ -0,0 +1,93 @@
1
+ # grueserve - a game server in c and ruby for the gruesome game
2
+ # Copyright (C) 2008 Martin Kihlgren <zond at troja dot ath dot cx>
3
+ #
4
+ # This program is free software; you can redistribute it and/or
5
+ # modify it under the terms of the GNU General Public License
6
+ # as published by the Free Software Foundation; either version 2
7
+ # of the License, or (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program; if not, write to the Free Software
16
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
+
18
+ require 'mkmf'
19
+ require 'pathname'
20
+
21
+ def crash(s)
22
+ puts "--------------------------------------------------"
23
+ puts " extconf failure: #{s}"
24
+ puts "--------------------------------------------------"
25
+ exit 1
26
+ end
27
+
28
+ crash("pkg-config needed") unless find_executable("pkg-config")
29
+
30
+ crash "libglib-2.0 needed" unless have_library('glib-2.0')
31
+
32
+ $CFLAGS += " -std=c99 -Wall " + `pkg-config --cflags glib-2.0`.strip
33
+
34
+ gem = if find_executable("gem")
35
+ "gem"
36
+ elsif find_executable("gem1.8")
37
+ "gem1.8"
38
+ else
39
+ crash("gem needed")
40
+ end
41
+
42
+ geo_path = Pathname.glob(Pathname.new(`#{gem} environment`.match(/- GEM PATH.?:\s*- ([^\n]+)/)[1]).join("gems").join("geo-*")).sort.last
43
+
44
+ geo_include = geo_path.join("ext")
45
+ found_includes = false
46
+ Pathname.glob(geo_include.join("*.h")).each do |header|
47
+ crash("couldnt compile against #{header}") unless find_header(header.basename, geo_include)
48
+ found_includes = true
49
+ end
50
+ crash("couldnt find geo includes") unless found_includes
51
+
52
+ found_libs = false
53
+ Pathname.glob(geo_include.join("*.o")).each do |lib|
54
+ $LOCAL_LIBS += " #{lib}"
55
+ found_libs = true
56
+ end
57
+ Pathname.glob(geo_path.join("lib").join("*.so")).each do |lib|
58
+ $LOCAL_LIBS += " #{lib}"
59
+ found_libs = true
60
+ end
61
+ [
62
+ "rb_is_a", # common.c
63
+ "Init_geo", # geo.c
64
+ "geo_set_free", # geo_set.c
65
+ "free_intersection", # intersection.c
66
+ "line_free", # line.c
67
+ "line_set_mark", # line_set.c
68
+ "new_point", # point.c
69
+ "point_set_mark", # point_set.c
70
+ "triangle_inspect", # triangle.c
71
+ "triangle_set_mark" # triangle_set.c
72
+ ].each do |func|
73
+ puts "checking for #{func}"
74
+ crash("couldnt find #{func}") unless try_func(func, [])
75
+ puts "... yes"
76
+ end
77
+ crash("couldnt find geo libs") unless found_libs
78
+
79
+ if ARGV.include?("-d")
80
+ $CFLAGS += " -D GEO_DEBUG"
81
+ end
82
+
83
+ if ARGV.include?("-O0")
84
+ $CFLAGS.gsub!(/-O./, "-O0")
85
+ else
86
+ $CFLAGS.gsub!(/-O./, "-O3")
87
+ end
88
+
89
+ if ARGV.include?("-gdb")
90
+ $CFLAGS += " -g -gdwarf-2 -g3"
91
+ end
92
+
93
+ create_makefile("grueserve_ext")
@@ -0,0 +1,2083 @@
1
+ // grueserve - a game server in c and ruby for the gruesome game
2
+ // Copyright (C) 2008 Martin Kihlgren <zond at troja dot ath dot cx>
3
+ //
4
+ // This program is free software; you can redistribute it and/or
5
+ // modify it under the terms of the GNU General Public License
6
+ // as published by the Free Software Foundation; either version 2
7
+ // of the License, or (at your option) any later version.
8
+ //
9
+ // This program is distributed in the hope that it will be useful,
10
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ // GNU General Public License for more details.
13
+ //
14
+ // You should have received a copy of the GNU General Public License
15
+ // along with this program; if not, write to the Free Software
16
+ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
+
18
+ #define _POSIX_SOURCE
19
+
20
+ #include "ruby.h"
21
+ #include "rubyio.h"
22
+ #include "intern.h"
23
+ #include <stdlib.h>
24
+ #include <unistd.h>
25
+ #include <math.h>
26
+ #include <glib.h>
27
+ #include <common.h>
28
+ #include <time.h>
29
+ #include <stdio.h>
30
+
31
+ static VALUE rb_client;
32
+ static VALUE rb_command;
33
+ static VALUE rb_command_set;
34
+ static VALUE rb_body;
35
+ static VALUE rb_map;
36
+ static VALUE rb_e_terminated_connection;
37
+
38
+ static VALUE rb_standing;
39
+ static VALUE rb_dodging;
40
+ static VALUE rb_dead;
41
+
42
+ static char* standing = "standing";
43
+ static char* dodging = "dodging";
44
+ static char* dead = "dead";
45
+
46
+ #define RB_CLIENT(client_pointer,klass) ((client_pointer)->rbClient = Data_Wrap_Struct(klass, client_mark, client_free, (client_pointer)))
47
+ #define CLIENT(rb_client,client_pointer) Data_Get_Struct((rb_client), Client, (client_pointer))
48
+ #define RB_BODY(body_pointer,klass) ((body_pointer)->rbBody = Data_Wrap_Struct(klass, body_mark, free, (body_pointer)))
49
+ #define BODY(rb_body,body_pointer) Data_Get_Struct((rb_body), Body, (body_pointer))
50
+ #define RB_COMMAND(command_pointer,klass) ((command_pointer)->rbCommand = Data_Wrap_Struct(klass, NULL, command_free, (command_pointer)))
51
+ #define COMMAND(rb_command,command_pointer) Data_Get_Struct((rb_command), Command, (command_pointer))
52
+ #define RB_MAP(map_pointer,klass) ((map_pointer)->rbMap = Data_Wrap_Struct(klass, map_mark, map_free, (map_pointer)))
53
+ #define MAP(rb_map,map_pointer) Data_Get_Struct((rb_map), Map, (map_pointer))
54
+ #define RB_COMMAND_SET(command_set_pointer,klass) ((command_set_pointer)->rbCommandSet = Data_Wrap_Struct(klass, command_set_mark, command_set_free, (command_set_pointer)))
55
+ #define COMMAND_SET(rb_command_set,command_set_pointer) Data_Get_Struct((rb_command_set), CommandSet, (command_set_pointer))
56
+
57
+ #define COMMAND_P(l) (!NIL_P((l)) && rb_is_a((l), rb_command))
58
+ #define CHECK_COMMAND(l) if (!COMMAND_P((l))) rb_raise(rb_eTypeError, "Expected Grueserve::Client::Command!")
59
+ #define COMMAND_SET_P(l) (!NIL_P((l)) && rb_is_a((l), rb_command_set))
60
+ #define CHECK_COMMAND_SET(l) if (!COMMAND_SET_P((l))) rb_raise(rb_eTypeError, "Expected Grueserve::Client::CommandSet!")
61
+ #define MAP_P(l) (!NIL_P((l)) && rb_is_a((l), rb_map))
62
+ #define CHECK_MAP(l) if (!MAP_P((l))) rb_raise(rb_eTypeError, "Expected Grueserve::Map!")
63
+ #define CLIENT_P(l) (!NIL_P((l)) && rb_is_a((l), rb_client))
64
+ #define CHECK_CLIENT(l) if (!CLIENT_P((l))) rb_raise(rb_eTypeError, "Expected Grueserve::Client!")
65
+
66
+ #define COMMAND_SET_INCLUDES(command_set,name) (g_hash_table_lookup((command_set)->commands, (name)) != NULL)
67
+
68
+ #define SPRITE_WIDTH 16.0
69
+ #define SPRITE_HEIGHT 24.0
70
+
71
+ #define UP "UP"
72
+ #define DOWN "DOWN"
73
+ #define LEFT "LEFT"
74
+ #define RIGHT "RIGHT"
75
+ #define DODGE "DODGE"
76
+ #define LBUTTON "LBUTTON"
77
+
78
+ #define BUFFER_UNIT 1024
79
+
80
+ typedef struct {
81
+ GeoSet *movement_obstacles;
82
+ GeoSet *visibility_obstacles;
83
+ GeoSet *bullet_obstacles;
84
+ GeoSet *hearing_obstacles;
85
+ GeoSet *fortifications;
86
+ GeoSet *speed_areas;
87
+ GeoSet *protection_areas;
88
+ GeoSet *hidden_areas;
89
+ GHashTable *config_by_whatever;
90
+
91
+ GeoSet *bodies;
92
+ GeoSet *eyes;
93
+ GeoSet *body_parts;
94
+ GHashTable *client_by_whatever;
95
+
96
+ gint timeout;
97
+ gdouble viewing_distance_limit;
98
+
99
+ VALUE rbMap;
100
+ } Map;
101
+
102
+ typedef struct {
103
+ GHashTable *attributes;
104
+ gchar *name;
105
+ VALUE rbCommand;
106
+ } Command;
107
+
108
+ typedef struct {
109
+ GHashTable *commands;
110
+ VALUE rbCommandSet;
111
+ } CommandSet;
112
+
113
+ struct ClientStruct;
114
+
115
+ typedef struct {
116
+ Line *vertical_axis;
117
+ Line *horizontal_axis;
118
+ Point *origo;
119
+ VALUE rbBody;
120
+ struct ClientStruct *client;
121
+ } Body;
122
+
123
+ struct ClientStruct {
124
+ Body *body;
125
+ CommandSet *current_command;
126
+ GHashTable *last_command;
127
+ Map *map;
128
+ VALUE rbClient;
129
+ VALUE state;
130
+ time_t last_ping;
131
+ gdouble running_speed;
132
+ OpenFile *socket;
133
+ VALUE rbSocket;
134
+ gboolean socket_locked;
135
+ gchar *team;
136
+ gchar *behaviour;
137
+ gchar *nickname;
138
+ gboolean status_dirty;
139
+ gdouble score;
140
+ gdouble kills;
141
+ gdouble deaths;
142
+ gdouble hitpoints;
143
+ gchar *extra_status;
144
+ GHashTable *subscriptions;
145
+ };
146
+
147
+ typedef struct ClientStruct Client;
148
+
149
+ typedef gpointer
150
+ (*viewing_handler)(Client *viewer, Client *viewee, gpointer user_data);
151
+
152
+ typedef gpointer
153
+ (*client_handler)(Client *client, gpointer user_data);
154
+
155
+ static void
156
+ map_mark(Map *map) {
157
+ rb_gc_mark(map->movement_obstacles->rbGeoSet);
158
+ rb_gc_mark(map->visibility_obstacles->rbGeoSet);
159
+ rb_gc_mark(map->bullet_obstacles->rbGeoSet);
160
+ rb_gc_mark(map->hearing_obstacles->rbGeoSet);
161
+ rb_gc_mark(map->fortifications->rbGeoSet);
162
+ rb_gc_mark(map->speed_areas->rbGeoSet);
163
+ rb_gc_mark(map->protection_areas->rbGeoSet);
164
+ rb_gc_mark(map->hidden_areas->rbGeoSet);
165
+
166
+ rb_gc_mark(map->bodies->rbGeoSet);
167
+ rb_gc_mark(map->eyes->rbGeoSet);
168
+ rb_gc_mark(map->body_parts->rbGeoSet);
169
+ }
170
+
171
+ static void
172
+ map_free(Map *map) {
173
+ g_hash_table_destroy(map->client_by_whatever);
174
+ g_hash_table_destroy(map->config_by_whatever);
175
+ }
176
+
177
+ static void
178
+ client_free(Client *client) {
179
+ if (client->team != NULL)
180
+ free(client->team);
181
+ if (client->behaviour != NULL)
182
+ free(client->behaviour);
183
+ if (client->nickname != NULL)
184
+ free(client->nickname);
185
+ if (client->extra_status != NULL)
186
+ free(client->extra_status);
187
+ g_hash_table_destroy(client->subscriptions);
188
+ g_hash_table_destroy(client->last_command);
189
+ }
190
+
191
+ static void
192
+ client_mark(Client *client) {
193
+ rb_gc_mark(client->body->rbBody);
194
+ rb_gc_mark(client->current_command->rbCommandSet);
195
+ rb_gc_mark(client->map->rbMap);
196
+ rb_gc_mark(client->rbSocket);
197
+ }
198
+
199
+ static void
200
+ body_mark(Body *body) {
201
+ rb_gc_mark(body->vertical_axis->rbLine);
202
+ rb_gc_mark(body->horizontal_axis->rbLine);
203
+ rb_gc_mark(body->origo->rbPoint);
204
+ rb_gc_mark(body->client->rbClient);
205
+ }
206
+
207
+ static void
208
+ command_free(Command *command) {
209
+ free(command->name);
210
+ g_hash_table_destroy(command->attributes);
211
+ }
212
+
213
+ static void
214
+ g_hash_table_mark_command(gpointer name, gpointer command, gpointer null) {
215
+ rb_gc_mark(( (Command *) command )->rbCommand);
216
+ }
217
+
218
+ static void
219
+ command_set_mark(CommandSet *command_set) {
220
+ g_hash_table_foreach(command_set->commands, g_hash_table_mark_command, NULL);
221
+ }
222
+
223
+ static void
224
+ command_set_free(CommandSet *command_set) {
225
+ g_hash_table_destroy(command_set->commands);
226
+ free(command_set);
227
+ }
228
+
229
+ static CommandSet*
230
+ new_command_set() {
231
+ CommandSet *command_set = ALLOC(CommandSet);
232
+ command_set->commands = g_hash_table_new_full(g_str_hash, g_str_equal, free, NULL);
233
+ return command_set;
234
+ }
235
+
236
+ static Body*
237
+ new_body() {
238
+ Body *body = ALLOC(Body);
239
+ body->vertical_axis = new_line_with_coordinates(-SPRITE_WIDTH / 2, 0,
240
+ SPRITE_WIDTH / 2, 0);
241
+ body->horizontal_axis = new_line_with_coordinates(0,-SPRITE_HEIGHT / 2,
242
+ 0,SPRITE_HEIGHT / 2);
243
+ body->origo = new_point(0,0);
244
+ RB_BODY(body, rb_body);
245
+ RB_LINE(body->vertical_axis, rb_line);
246
+ RB_POINT(body->vertical_axis->p1, rb_point);
247
+ RB_POINT(body->vertical_axis->p2, rb_point);
248
+ RB_LINE(body->horizontal_axis, rb_line);
249
+ RB_POINT(body->horizontal_axis->p1, rb_point);
250
+ RB_POINT(body->horizontal_axis->p2, rb_point);
251
+ RB_POINT(body->origo, rb_point);
252
+ return body;
253
+ }
254
+
255
+ static VALUE
256
+ rb_client_alloc(VALUE class) {
257
+ Client *client = ALLOC(Client);
258
+ client->state = rb_standing;
259
+ client->last_ping = time(NULL);
260
+ client->running_speed = 1;
261
+ client->current_command = new_command_set();
262
+ RB_COMMAND_SET(client->current_command, rb_command_set);
263
+ client->last_command = g_hash_table_new_full(g_str_hash, g_str_equal, free, NULL);
264
+ client->map = NULL;
265
+ client->socket = NULL;
266
+ client->rbSocket = 0;
267
+ client->socket_locked = FALSE;
268
+ client->team = NULL;
269
+ client->behaviour = NULL;
270
+ client->nickname = NULL;
271
+ client->status_dirty = TRUE;
272
+ client->score = 0.0;
273
+ client->kills = 0.0;
274
+ client->deaths = 0.0;
275
+ client->hitpoints = 0.0;
276
+ client->extra_status = NULL;
277
+
278
+ client->body = new_body();
279
+ client->body->client = client;
280
+
281
+ client->subscriptions = g_hash_table_new_full(g_str_hash, g_str_equal, free, free);
282
+ return RB_CLIENT(client, class);
283
+ }
284
+
285
+ static void
286
+ map_register_body(Map *map, Body *body) {
287
+ g_hash_table_insert(map->bodies->table, body->origo, body->origo);
288
+ g_hash_table_insert(map->client_by_whatever, body->origo, body->client);
289
+
290
+ g_hash_table_insert(map->body_parts->table, body->vertical_axis, body->vertical_axis);
291
+ g_hash_table_insert(map->client_by_whatever, body->vertical_axis, body->client);
292
+ g_hash_table_insert(map->eyes->table, body->vertical_axis->p1, body->vertical_axis->p1);
293
+ g_hash_table_insert(map->client_by_whatever, body->vertical_axis->p1, body->client);
294
+ g_hash_table_insert(map->eyes->table, body->vertical_axis->p2, body->vertical_axis->p2);
295
+ g_hash_table_insert(map->client_by_whatever, body->vertical_axis->p2, body->client);
296
+
297
+ g_hash_table_insert(map->body_parts->table, body->horizontal_axis, body->horizontal_axis);
298
+ g_hash_table_insert(map->client_by_whatever, body->horizontal_axis, body->client);
299
+ g_hash_table_insert(map->eyes->table, body->horizontal_axis->p1, body->horizontal_axis->p1);
300
+ g_hash_table_insert(map->client_by_whatever, body->horizontal_axis->p1, body->client);
301
+ g_hash_table_insert(map->eyes->table, body->horizontal_axis->p2, body->horizontal_axis->p2);
302
+ g_hash_table_insert(map->client_by_whatever, body->horizontal_axis->p2, body->client);
303
+ }
304
+
305
+ static void
306
+ map_unregister_body(Map *map, Body *body) {
307
+ g_hash_table_remove(map->bodies->table, body->origo);
308
+ g_hash_table_remove(map->client_by_whatever, body->origo);
309
+
310
+ g_hash_table_remove(map->body_parts->table, body->vertical_axis);
311
+ g_hash_table_remove(map->client_by_whatever, body->vertical_axis);
312
+ g_hash_table_remove(map->eyes->table, body->vertical_axis->p1);
313
+ g_hash_table_remove(map->client_by_whatever, body->vertical_axis->p1);
314
+ g_hash_table_remove(map->eyes->table, body->vertical_axis->p2);
315
+ g_hash_table_remove(map->client_by_whatever, body->vertical_axis->p2);
316
+
317
+ g_hash_table_remove(map->body_parts->table, body->horizontal_axis);
318
+ g_hash_table_remove(map->client_by_whatever, body->horizontal_axis);
319
+ g_hash_table_remove(map->eyes->table, body->horizontal_axis->p1);
320
+ g_hash_table_remove(map->client_by_whatever, body->horizontal_axis->p1);
321
+ g_hash_table_remove(map->eyes->table, body->horizontal_axis->p2);
322
+ g_hash_table_remove(map->client_by_whatever, body->horizontal_axis->p2);
323
+ }
324
+
325
+ static VALUE
326
+ rb_command_alloc(VALUE class) {
327
+ Command *command = ALLOC(Command);
328
+ command->name = g_strndup("", 0);
329
+ command->attributes = g_hash_table_new_full(g_str_hash, g_str_equal, free, free);
330
+ return RB_COMMAND(command, class);
331
+ }
332
+
333
+ static VALUE
334
+ rb_command_set_alloc(VALUE class) {
335
+ CommandSet *command_set = new_command_set();
336
+ return RB_COMMAND_SET(command_set, class);
337
+ }
338
+
339
+ static VALUE
340
+ rb_command_set_name(VALUE self, VALUE name) {
341
+ Command *command;
342
+ Check_Type(name, T_STRING);
343
+ COMMAND(self, command);
344
+ command->name = g_strndup(RSTRING(name)->ptr, RSTRING(name)->len);
345
+ return name;
346
+ }
347
+
348
+ static VALUE
349
+ rb_command_get_name(VALUE self) {
350
+ Command *command;
351
+ COMMAND(self, command);
352
+ return rb_str_new2(command->name);
353
+ }
354
+
355
+ static VALUE
356
+ rb_command_insert(VALUE self, VALUE key, VALUE value) {
357
+ Command *command;
358
+ Check_Type(key, T_STRING);
359
+ Check_Type(value, T_STRING);
360
+ COMMAND(self, command);
361
+ g_hash_table_insert(command->attributes, g_strndup(RSTRING(key)->ptr, RSTRING(key)->len), g_strndup(RSTRING(value)->ptr, RSTRING(value)->len));
362
+ return value;
363
+ }
364
+
365
+ static VALUE
366
+ rb_command_get(VALUE self, VALUE key) {
367
+ Command *command;
368
+ gpointer value;
369
+ Check_Type(key, T_STRING);
370
+ COMMAND(self, command);
371
+ value = g_hash_table_lookup(command->attributes, RSTRING(key)->ptr);
372
+ if (value == NULL)
373
+ return Qnil;
374
+ else
375
+ return rb_str_new2((gchar *) value);
376
+ }
377
+
378
+ static VALUE
379
+ rb_command_set_get(VALUE self, VALUE key) {
380
+ CommandSet *command_set;
381
+ gpointer value;
382
+ Check_Type(key, T_STRING);
383
+ COMMAND_SET(self, command_set);
384
+ value = g_hash_table_lookup(command_set->commands, RSTRING(key)->ptr);
385
+ if (value == NULL)
386
+ return Qnil;
387
+ else
388
+ return ( (Command *) value )->rbCommand;
389
+ }
390
+
391
+ static VALUE
392
+ rb_command_set_push(VALUE self, VALUE command_value) {
393
+ CommandSet *command_set;
394
+ Command *command;
395
+ CHECK_COMMAND(command_value);
396
+ COMMAND_SET(self, command_set);
397
+ COMMAND(command_value, command);
398
+ g_hash_table_insert(command_set->commands, g_strdup(command->name), command);
399
+ return self;
400
+ }
401
+
402
+ static VALUE
403
+ rb_command_set_include(VALUE self, VALUE key) {
404
+ CommandSet *command_set;
405
+ Check_Type(key, T_STRING);
406
+ COMMAND_SET(self, command_set);
407
+ if (g_hash_table_lookup(command_set->commands, RSTRING(key)->ptr) == NULL)
408
+ return Qfalse;
409
+ else
410
+ return Qtrue;
411
+ }
412
+
413
+ static VALUE
414
+ rb_client_get_body(VALUE self) {
415
+ Client *client;
416
+ CLIENT(self, client);
417
+ return client->body->rbBody;
418
+ }
419
+
420
+ static VALUE
421
+ rb_body_get_origo(VALUE self) {
422
+ Body *body;
423
+ BODY(self, body);
424
+ return body->origo->rbPoint;
425
+ }
426
+
427
+ static VALUE
428
+ rb_body_get_vertical_axis(VALUE self) {
429
+ Body *body;
430
+ BODY(self, body);
431
+ return body->vertical_axis->rbLine;
432
+ }
433
+
434
+ static VALUE
435
+ rb_body_get_horizontal_axis(VALUE self) {
436
+ Body *body;
437
+ BODY(self, body);
438
+ return body->horizontal_axis->rbLine;
439
+ }
440
+
441
+ static void
442
+ body_relocate(Body *body, Point *point) {
443
+ gdouble width;
444
+ gdouble height;
445
+ if (body->client->state == rb_dodging && !DBL_EQL(point->x, body->origo->x)) {
446
+ width = SPRITE_HEIGHT;
447
+ height = SPRITE_WIDTH;
448
+ } else {
449
+ width = SPRITE_WIDTH;
450
+ height = SPRITE_HEIGHT;
451
+ }
452
+ body->origo->x = point->x;
453
+ body->origo->y = point->y;
454
+ body->vertical_axis->p1->x = point->x;
455
+ body->vertical_axis->p1->y = point->y - height / 2;
456
+ body->vertical_axis->p2->x = point->x;
457
+ body->vertical_axis->p2->y = point->y + height / 2;
458
+ body->horizontal_axis->p1->x = point->x - width / 2;
459
+ body->horizontal_axis->p1->y = point->y;
460
+ body->horizontal_axis->p2->x = point->x + width / 2;
461
+ body->horizontal_axis->p2->y = point->y;
462
+ }
463
+
464
+ static VALUE
465
+ rb_body_relocate(VALUE self, VALUE new_origo) {
466
+ Body *body;
467
+ Point *point;
468
+ CHECK_POINT(new_origo);
469
+ POINT(new_origo, point);
470
+ BODY(self, body);
471
+ body_relocate(body, point);
472
+ return new_origo;
473
+ }
474
+
475
+ static void
476
+ g_hash_table_insert_key_equals_value_into_string(gpointer key, gpointer value, gpointer user_data) {
477
+ gpointer *args = (gpointer *) user_data;
478
+ gchar *str = (gchar *) args[0];
479
+ gboolean *first = (gboolean *) args[1];
480
+ gchar neue[BUFFER_UNIT];
481
+ gint len = strlen(str);
482
+ gint neuelen = 0;
483
+ if (*first)
484
+ snprintf(neue, BUFFER_UNIT, "%s=%s", (gchar *) key, (gchar *) value);
485
+ else
486
+ snprintf(neue, BUFFER_UNIT, ", %s=%s", (gchar *) key, (gchar *) value);
487
+ *first = FALSE;
488
+ neuelen = strlen(neue);
489
+ str = realloc(str, sizeof(gchar) * (len + neuelen + 1));
490
+ strncpy(str + len, neue, neuelen);
491
+ }
492
+
493
+ static gchar*
494
+ command_inspect(Command *command) {
495
+ gchar *rval = calloc(BUFFER_UNIT, sizeof(gchar));
496
+ gboolean first = TRUE;
497
+ gpointer args[2] = { rval, &first };
498
+ gint new_len = 0;
499
+ snprintf(rval, BUFFER_UNIT, "<%s:%p name=%s attributes=[", rb_obj_classname(command->rbCommand), command, command->name);
500
+ g_hash_table_foreach(command->attributes, g_hash_table_insert_key_equals_value_into_string, args);
501
+ new_len = strlen(rval);
502
+ rval = realloc(rval, sizeof(gchar) * (new_len + 3));
503
+ snprintf(rval + new_len, 3, "]>");
504
+ return rval;
505
+ }
506
+
507
+ static VALUE
508
+ rb_command_inspect(VALUE self) {
509
+ gchar *str;
510
+ Command *command;
511
+ VALUE rval;
512
+ COMMAND(self, command);
513
+ str = command_inspect(command);
514
+ rval = rb_str_new2(str);
515
+ free(str);
516
+ return rval;
517
+ }
518
+
519
+ static void
520
+ g_hash_table_insert_command_into_string(gpointer key, gpointer value, gpointer user_data) {
521
+ gpointer *args = (gpointer *) user_data;
522
+ gchar *str = (gchar *) args[0];
523
+ gboolean *first = (gboolean *) args[1];
524
+ gchar neue[(BUFFER_UNIT * 2)];
525
+ gint len = strlen(str);
526
+ gint neuelen = 0;
527
+ gchar *command_str = command_inspect((Command *) value);
528
+ if (*first)
529
+ snprintf(neue, (BUFFER_UNIT * 2), "%s", command_str);
530
+ else
531
+ snprintf(neue, (BUFFER_UNIT * 2), ", %s", command_str);
532
+ free(command_str);
533
+ *first = FALSE;
534
+ neuelen = strlen(neue);
535
+ str = realloc(str, sizeof(gchar) * (len + neuelen + 1));
536
+ strncpy(str + len, neue, neuelen);
537
+ }
538
+
539
+ static gchar*
540
+ command_set_inspect(CommandSet *command_set) {
541
+ gchar *rval = calloc(BUFFER_UNIT, sizeof(gchar));
542
+ gboolean first = TRUE;
543
+ gpointer args[2] = { rval, &first };
544
+ gint new_len = 0;
545
+ snprintf(rval, BUFFER_UNIT, "<%s:%p commands=[", rb_obj_classname(command_set->rbCommandSet), command_set);
546
+ g_hash_table_foreach(command_set->commands, g_hash_table_insert_command_into_string, args);
547
+ new_len = strlen(rval);
548
+ rval = realloc(rval, sizeof(gchar) * (new_len + 3));
549
+ snprintf(rval + new_len, 3, "]>");
550
+ return rval;
551
+ }
552
+
553
+ static VALUE
554
+ rb_command_set_inspect(VALUE self) {
555
+ gchar *str;
556
+ CommandSet *command_set;
557
+ VALUE rval;
558
+ COMMAND_SET(self, command_set);
559
+ str = command_set_inspect(command_set);
560
+ rval = rb_str_new2(str);
561
+ free(str);
562
+ return rval;
563
+ }
564
+
565
+ static VALUE
566
+ rb_body_inspect(VALUE self) {
567
+ gchar rval[BUFFER_UNIT];
568
+ Body *b;
569
+ gchar *origo;
570
+ gchar *vert;
571
+ gchar *hori;
572
+ BODY(self, b);
573
+ origo = point_inspect(b->origo);
574
+ vert = line_inspect(b->vertical_axis);
575
+ hori = line_inspect(b->horizontal_axis);
576
+ snprintf(rval, BUFFER_UNIT, "<%s:%p origo=%s vertical_axis=%s horizontal_axis=%s>",
577
+ rb_obj_classname(self), b,
578
+ origo,
579
+ vert,
580
+ hori);
581
+ free(origo);
582
+ free(vert);
583
+ free(hori);
584
+ return rb_str_new2(rval);
585
+ }
586
+
587
+ static VALUE
588
+ rb_client_get_state(VALUE self) {
589
+ Client *client;
590
+ CLIENT(self, client);
591
+ return client->state;
592
+ }
593
+
594
+ static VALUE
595
+ rb_client_set_state(VALUE self, VALUE new_state) {
596
+ Client *client;
597
+ CLIENT(self, client);
598
+ if (client->state != new_state) {
599
+ client->status_dirty = TRUE;
600
+ client->state = new_state;
601
+ }
602
+ return new_state;
603
+ }
604
+
605
+ static VALUE
606
+ rb_client_set_current_command(VALUE self, VALUE new_command) {
607
+ Client *client;
608
+ CommandSet *command_set;
609
+ CHECK_COMMAND_SET(new_command);
610
+ CLIENT(self, client);
611
+ COMMAND_SET(new_command, command_set);
612
+ client->current_command = command_set;
613
+ return new_command;
614
+ }
615
+
616
+ static VALUE
617
+ rb_client_get_current_command(VALUE self) {
618
+ Client *client;
619
+ CLIENT(self, client);
620
+ return client->current_command->rbCommandSet;
621
+ }
622
+
623
+ static void
624
+ init_grueserve_globals() {
625
+ rb_standing = ID2SYM(rb_intern(standing));
626
+ rb_dodging = ID2SYM(rb_intern(dodging));
627
+ rb_dead = ID2SYM(rb_intern(dead));
628
+ }
629
+
630
+ static VALUE
631
+ rb_client_registered(VALUE self) {
632
+ Client *client;
633
+ CLIENT(self, client);
634
+ return GBOOL2RB(g_hash_table_lookup(client->map->bodies->table, client->body->origo) != NULL);
635
+ }
636
+
637
+ static VALUE
638
+ rb_client_moving(VALUE self) {
639
+ Client *client;
640
+ CLIENT(self, client);
641
+ return GBOOL2RB(g_hash_table_lookup(client->current_command->commands, UP) != NULL ||
642
+ g_hash_table_lookup(client->current_command->commands, DOWN) != NULL ||
643
+ g_hash_table_lookup(client->current_command->commands, LEFT) != NULL ||
644
+ g_hash_table_lookup(client->current_command->commands, RIGHT) != NULL);
645
+ }
646
+
647
+ static gpointer
648
+ map_yield_client(Client *client, gpointer user_data) {
649
+ rb_yield(( (Client *) client)->rbClient);
650
+ return NULL;
651
+ }
652
+
653
+ static gboolean
654
+ g_hash_table_call_handler_for_client_for_body_until(gpointer key, gpointer value, gpointer user_data) {
655
+ gpointer *args = (gpointer *) user_data;
656
+ Map *map = (Map *) args[0];
657
+ client_handler handler = (client_handler) args[1];
658
+ gpointer handler_args = args[2];
659
+ gpointer *rval = (gpointer *) args[3];
660
+ Client *client = (Client *) g_hash_table_lookup(map->client_by_whatever, key);
661
+ if (client == NULL)
662
+ rb_raise(rb_eRuntimeError, "%s: Weird! The body doesnt have a Client!", __PRETTY_FUNCTION__);
663
+ if (((*rval) = handler(client, handler_args)) != NULL)
664
+ return TRUE;
665
+ else
666
+ return FALSE;
667
+ }
668
+
669
+ static gpointer
670
+ map_each_client_until(Map *map, client_handler handler, gpointer handler_args) {
671
+ gpointer rval;
672
+ gpointer args[4] = { map, handler, handler_args, &rval };
673
+ g_hash_table_find(map->bodies->table, g_hash_table_call_handler_for_client_for_body_until, args);
674
+ return rval;
675
+ }
676
+
677
+ static VALUE
678
+ rb_map_each_client(VALUE self) {
679
+ Map *map;
680
+ MAP(self, map);
681
+ map_each_client_until(map, map_yield_client, NULL);
682
+ return Qnil;
683
+ }
684
+
685
+ static VALUE
686
+ rb_map_alloc(VALUE class) {
687
+ Map *map = ALLOC(Map);
688
+ map->movement_obstacles = new_geo_set();
689
+ RB_LINE_SET(map->movement_obstacles, rb_line_set);
690
+ map->visibility_obstacles = new_geo_set();
691
+ RB_LINE_SET(map->visibility_obstacles, rb_line_set);
692
+ map->bullet_obstacles = new_geo_set();
693
+ RB_LINE_SET(map->bullet_obstacles, rb_line_set);
694
+ map->hearing_obstacles = new_geo_set();
695
+ RB_LINE_SET(map->hearing_obstacles, rb_line_set);
696
+ map->fortifications = new_geo_set();
697
+ RB_LINE_SET(map->fortifications, rb_line_set);
698
+ map->speed_areas = new_geo_set();
699
+ RB_TRIANGLE_SET(map->speed_areas, rb_triangle_set);
700
+ map->protection_areas = new_geo_set();
701
+ RB_TRIANGLE_SET(map->protection_areas, rb_triangle_set);
702
+ map->hidden_areas = new_geo_set();
703
+ RB_TRIANGLE_SET(map->hidden_areas, rb_triangle_set);
704
+
705
+ map->config_by_whatever = g_hash_table_new(g_direct_hash, g_direct_equal);
706
+
707
+ map->bodies = new_geo_set();
708
+ map->bodies->indexed = FALSE;
709
+ RB_POINT_SET(map->bodies, rb_point_set);
710
+ map->eyes = new_geo_set();
711
+ map->eyes->indexed = FALSE;
712
+ RB_POINT_SET(map->eyes, rb_point_set);
713
+ map->body_parts = new_geo_set();
714
+ map->body_parts->indexed = FALSE;
715
+ RB_LINE_SET(map->body_parts, rb_line_set);
716
+
717
+ map->client_by_whatever = g_hash_table_new(g_direct_hash, g_direct_equal);
718
+
719
+ map->timeout = 10;
720
+ map->viewing_distance_limit = 1000.0;
721
+
722
+ return RB_MAP(map, class);
723
+ }
724
+
725
+ static VALUE
726
+ rb_map_set(VALUE self, VALUE key, VALUE value) {
727
+ Map *map;
728
+ gpointer key_p;
729
+ if (LINE_P(key)) {
730
+ LINE(key, key_p);
731
+ } else if (TRIANGLE_P(key)) {
732
+ TRIANGLE(key, key_p);
733
+ } else if (POINT_P(key)) {
734
+ POINT(key, key_p);
735
+ } else {
736
+ rb_raise(rb_eTypeError, "%s#[]= requires a Geo::Line, a Geo::Point or a Geo::Triangle as first parameter.", rb_obj_classname(self));
737
+ }
738
+ MAP(self, map);
739
+ Check_Type(value, T_FIXNUM);
740
+ g_hash_table_insert(map->config_by_whatever, key_p, GINT_TO_POINTER(NUM2INT(value)));
741
+ return value;
742
+ }
743
+
744
+ static VALUE
745
+ rb_map_get(VALUE self, VALUE key) {
746
+ gpointer key_p;
747
+ gpointer rval;
748
+ Map *map;
749
+ if (LINE_P(key)) {
750
+ LINE(key, key_p);
751
+ } else if (POINT_P(key)) {
752
+ POINT(key, key_p);
753
+ } else if (TRIANGLE_P(key)) {
754
+ TRIANGLE(key, key_p);
755
+ } else {
756
+ rb_raise(rb_eTypeError, "%s[] requires a Geo::Line, a Geo::Point or a Geo::Triangle as argument.", rb_obj_classname(self));
757
+ }
758
+ MAP(self, map);
759
+ if ((rval = g_hash_table_lookup(map->config_by_whatever, key_p)) != NULL) {
760
+ return INT2NUM(GPOINTER_TO_INT(rval));
761
+ } else if ((rval = g_hash_table_lookup(map->client_by_whatever, key_p)) != NULL) {
762
+ return ( (Client *) rval )->rbClient;
763
+ }
764
+ return Qnil;
765
+ }
766
+
767
+ static VALUE
768
+ rb_map_movement_obstacles(VALUE self) {
769
+ Map *map;
770
+ MAP(self, map);
771
+ return map->movement_obstacles->rbGeoSet;
772
+ }
773
+
774
+ static VALUE
775
+ rb_map_visibility_obstacles(VALUE self) {
776
+ Map *map;
777
+ MAP(self, map);
778
+ return map->visibility_obstacles->rbGeoSet;
779
+ }
780
+
781
+ static VALUE
782
+ rb_map_bullet_obstacles(VALUE self) {
783
+ Map *map;
784
+ MAP(self, map);
785
+ return map->bullet_obstacles->rbGeoSet;
786
+ }
787
+
788
+ static VALUE
789
+ rb_map_hearing_obstacles(VALUE self) {
790
+ Map *map;
791
+ MAP(self, map);
792
+ return map->hearing_obstacles->rbGeoSet;
793
+ }
794
+
795
+ static VALUE
796
+ rb_map_fortifications(VALUE self) {
797
+ Map *map;
798
+ MAP(self, map);
799
+ return map->fortifications->rbGeoSet;
800
+ }
801
+
802
+ static VALUE
803
+ rb_map_speed_areas(VALUE self) {
804
+ Map *map;
805
+ MAP(self, map);
806
+ return map->speed_areas->rbGeoSet;
807
+ }
808
+
809
+ static VALUE
810
+ rb_map_protection_areas(VALUE self) {
811
+ Map *map;
812
+ MAP(self, map);
813
+ return map->protection_areas->rbGeoSet;
814
+ }
815
+
816
+ static VALUE
817
+ rb_map_hidden_areas(VALUE self) {
818
+ Map *map;
819
+ MAP(self, map);
820
+ return map->hidden_areas->rbGeoSet;
821
+ }
822
+
823
+ static VALUE
824
+ rb_client_set_map(VALUE self, VALUE new_map) {
825
+ Client *client;
826
+ Map *map;
827
+ CHECK_MAP(new_map);
828
+ CLIENT(self, client);
829
+ MAP(new_map, map);
830
+ client->map = map;
831
+ return new_map;
832
+ }
833
+
834
+ static VALUE
835
+ rb_client_get_map(VALUE self) {
836
+ Client *client;
837
+ CLIENT(self, client);
838
+ if (client->map == NULL)
839
+ return Qnil;
840
+ return client->map->rbMap;
841
+ }
842
+
843
+ static VALUE
844
+ rb_client_client_id(VALUE self) {
845
+ Client *client;
846
+ gchar rval[BUFFER_UNIT];
847
+ CLIENT(self, client);
848
+ snprintf(rval, BUFFER_UNIT, "%p", client);
849
+ return rb_str_new2(rval);
850
+ }
851
+
852
+ static VALUE
853
+ rb_client_get_last_ping(VALUE self) {
854
+ Client *client;
855
+ CLIENT(self, client);
856
+ return INT2NUM((gint) client->last_ping);
857
+ }
858
+
859
+ static VALUE
860
+ rb_client_ping(VALUE self) {
861
+ Client *client;
862
+ CLIENT(self, client);
863
+ client->last_ping = time(NULL);
864
+ return INT2NUM((gint) client->last_ping);
865
+ }
866
+
867
+ static void
868
+ map_move(Map *map, Point *from, Point *to, Point *rval) {
869
+ Line *movement_line = new_line_with_coordinates(from->x, from->y,
870
+ to->x, to->y);
871
+ line_set_slide_point(map->movement_obstacles, movement_line, 3);
872
+ rval->x = movement_line->p2->x;
873
+ rval->y = movement_line->p2->y;
874
+ line_free(movement_line);
875
+ }
876
+
877
+ static gpointer
878
+ map_add_overlap_factor_to_virtual_length(GeoSet *set, gpointer triangle, gpointer user_data) {
879
+ gpointer *args = (gpointer *) user_data;
880
+ Line *line = (Line *) args[0];
881
+ gdouble *virtual_length = (gdouble *) args[1];
882
+ Map *map = (Map *) args[2];
883
+ Line *overlap = triangle_overlap((Triangle *) triangle, line);
884
+ gint triangle_value = GPOINTER_TO_INT(g_hash_table_lookup(map->config_by_whatever, triangle));
885
+ (*virtual_length) += (DISTANCE(overlap->p1, overlap->p2) * (triangle_value / 1000.0));
886
+ line_free(overlap);
887
+ return NULL;
888
+ }
889
+
890
+ static gboolean
891
+ map_line_hidden(Map *map, Line *line) {
892
+ gdouble virtual_length = DISTANCE(line->p1, line->p2);
893
+ gpointer args[3] = { line, &virtual_length, map };
894
+ triangle_set_each_intersector_until(map->hidden_areas, line, map_add_overlap_factor_to_virtual_length, args);
895
+ return virtual_length > map->viewing_distance_limit;
896
+ }
897
+
898
+ static gpointer
899
+ map_call_client_handler_if_within_visible_range(GeoSet *set, gpointer line, gpointer user_data) {
900
+ gpointer *args = (gpointer *) user_data;
901
+ client_handler handler = (client_handler) args[0];
902
+ gpointer handler_args = args[1];
903
+ Map *map = (Map *) args[2];
904
+ GHashTable *seen_clients = (GHashTable *) args[3];
905
+ Client *client = (Client *) g_hash_table_lookup(map->client_by_whatever, ( (Line *) line )->p2);
906
+ if (client == NULL) {
907
+ rb_raise(rb_eRuntimeError, "%s: Weird! The viewing Point doesnt seem to have a Client!", __PRETTY_FUNCTION__);
908
+ }
909
+ if (!map_line_hidden(map, (Line *) line)) {
910
+ if (g_hash_table_lookup(seen_clients, client) == NULL) {
911
+ handler(client, handler_args);
912
+ g_hash_table_insert(seen_clients, client, GINT_TO_POINTER(1));
913
+ }
914
+ }
915
+ return NULL;
916
+ }
917
+
918
+ static void
919
+ map_each_viewer_of(Map *map, Point *what, client_handler handler, gpointer user_data) {
920
+ GeoSet *what_set = new_geo_set();
921
+ GHashTable *seen_clients = g_hash_table_new(g_direct_hash, g_direct_equal);
922
+ gpointer args[4] = { handler, user_data, map, seen_clients };
923
+
924
+ g_hash_table_insert(what_set->table, what, what);
925
+
926
+ line_set_each_intersection_free_endpoint(map->visibility_obstacles,
927
+ what_set,
928
+ map->eyes,
929
+ map->viewing_distance_limit,
930
+ map_call_client_handler_if_within_visible_range,
931
+ args);
932
+ g_hash_table_destroy(seen_clients);
933
+ geo_set_free(what_set);
934
+ }
935
+
936
+ static gpointer
937
+ client_add_client_to_rb_ary(Client *client, gpointer user_data) {
938
+ rb_ary_push(*( (VALUE *) user_data), client->rbClient);
939
+ return NULL;
940
+ }
941
+
942
+ static VALUE
943
+ rb_map_viewers_of(VALUE self, VALUE p) {
944
+ Map *map;
945
+ Point *point;
946
+ VALUE rval;
947
+ CHECK_POINT(p);
948
+ MAP(self, map);
949
+ POINT(p, point);
950
+ rval = rb_ary_new();
951
+ map_each_viewer_of(map, point, client_add_client_to_rb_ary, &rval);
952
+ return rval;
953
+ }
954
+
955
+ static gpointer
956
+ client_call_viewing_handler_if_clients_within_visible_range(GeoSet *set, gpointer line, gpointer user_data) {
957
+ gpointer *args = (gpointer *) user_data;
958
+ viewing_handler handler = (viewing_handler) args[0];
959
+ gpointer handler_args = args[1];
960
+ Client *viewer = (Client *) args[2];
961
+ Client *viewee = (Client *) args[3];
962
+ GHashTable *seen_viewers = (GHashTable *) args[4];
963
+ GHashTable *seen_viewees = (GHashTable *) args[5];
964
+ Map *map = (Map *) args[6];
965
+ if (viewer != NULL) {
966
+ if (viewer->map == NULL)
967
+ rb_raise(rb_eRuntimeError, "%s: Weird! The viewer doesnt have a Map!", __PRETTY_FUNCTION__);
968
+ if ((viewee = (Client *) g_hash_table_lookup(viewer->map->client_by_whatever, ( (Line *) line )->p2)) != NULL) {
969
+ if (!map_line_hidden(map, (Line *) line)) {
970
+ if (g_hash_table_lookup(seen_viewees, viewee) == NULL) {
971
+ handler(viewer, viewee, handler_args);
972
+ g_hash_table_insert(seen_viewees, viewee, GINT_TO_POINTER(1));
973
+ }
974
+ }
975
+ } else {
976
+ rb_raise(rb_eRuntimeError, "%s: Weird! The viewed Point doesnt seem to have a Client!", __PRETTY_FUNCTION__);
977
+ }
978
+ } else if (viewee != NULL) {
979
+ if (viewee->map == NULL)
980
+ rb_raise(rb_eRuntimeError, "%s: Weird! The viewee doesnt have a Map!", __PRETTY_FUNCTION__);
981
+ if ((viewer = (Client *) g_hash_table_lookup(viewee->map->client_by_whatever, ( (Line *) line )->p2)) != NULL) {
982
+ if (!map_line_hidden(map, (Line *) line)) {
983
+ if (g_hash_table_lookup(seen_viewers, viewer) == NULL) {
984
+ handler(viewer, viewee, handler_args);
985
+ g_hash_table_insert(seen_viewers, viewer, GINT_TO_POINTER(1));
986
+ }
987
+ }
988
+ } else {
989
+ rb_raise(rb_eRuntimeError, "%s: Weird! The viewing Point doesnt seem to have a Client!", __PRETTY_FUNCTION__);
990
+ }
991
+ } else {
992
+ rb_raise(rb_eRuntimeError, "%s: Weird! map_call_viewing_handler should always have either viewer or viewee set!", __PRETTY_FUNCTION__);
993
+ }
994
+ return NULL;
995
+ }
996
+
997
+ static void
998
+ client_each_viewee(Client *viewer, viewing_handler handler, gpointer user_data) {
999
+ GeoSet *eyes = new_geo_set();
1000
+ GHashTable *seen_viewees = g_hash_table_new(g_direct_hash, g_direct_equal);
1001
+ gpointer args[7] = { handler, user_data, viewer, NULL, NULL, seen_viewees, viewer->map };
1002
+
1003
+ g_hash_table_insert(eyes->table, viewer->body->horizontal_axis->p1, viewer->body->horizontal_axis->p1);
1004
+ g_hash_table_insert(eyes->table, viewer->body->horizontal_axis->p2, viewer->body->horizontal_axis->p2);
1005
+ g_hash_table_insert(eyes->table, viewer->body->vertical_axis->p1, viewer->body->vertical_axis->p1);
1006
+ g_hash_table_insert(eyes->table, viewer->body->vertical_axis->p2, viewer->body->vertical_axis->p2);
1007
+
1008
+ line_set_each_intersection_free_endpoint(viewer->map->visibility_obstacles,
1009
+ eyes,
1010
+ viewer->map->bodies,
1011
+ viewer->map->viewing_distance_limit,
1012
+ client_call_viewing_handler_if_clients_within_visible_range,
1013
+ args);
1014
+
1015
+ g_hash_table_destroy(seen_viewees);
1016
+ geo_set_free(eyes);
1017
+ }
1018
+
1019
+ static void
1020
+ client_each_viewer(Client *viewee, viewing_handler handler, gpointer user_data) {
1021
+ GeoSet *body_set = new_geo_set();
1022
+ GHashTable *seen_viewers = g_hash_table_new(g_direct_hash, g_direct_equal);
1023
+ gpointer args[7] = { handler, user_data, NULL, viewee, seen_viewers, NULL, viewee->map };
1024
+
1025
+ g_hash_table_insert(body_set->table, viewee->body->origo, viewee->body->origo);
1026
+
1027
+ line_set_each_intersection_free_endpoint(viewee->map->visibility_obstacles,
1028
+ body_set,
1029
+ viewee->map->eyes,
1030
+ viewee->map->viewing_distance_limit,
1031
+ client_call_viewing_handler_if_clients_within_visible_range,
1032
+ args);
1033
+ g_hash_table_destroy(seen_viewers);
1034
+ geo_set_free(body_set);
1035
+ }
1036
+
1037
+ static gpointer
1038
+ client_add_viewer_to_rb_ary(Client *viewer, Client *viewee, gpointer user_data) {
1039
+ rb_ary_push(*( (VALUE *) user_data), viewer->rbClient);
1040
+ return NULL;
1041
+ }
1042
+
1043
+ static gpointer
1044
+ client_add_viewee_to_rb_ary(Client *viewer, Client *viewee, gpointer user_data) {
1045
+ rb_ary_push(*( (VALUE *) user_data), viewee->rbClient);
1046
+ return NULL;
1047
+ }
1048
+
1049
+ static VALUE
1050
+ rb_client_viewers(VALUE self) {
1051
+ Client *client;
1052
+ VALUE rval = rb_ary_new();
1053
+ CLIENT(self, client);
1054
+ client_each_viewer(client, client_add_viewer_to_rb_ary, &rval);
1055
+ return rval;
1056
+ }
1057
+
1058
+ static VALUE
1059
+ rb_client_viewees(VALUE self) {
1060
+ Client *client;
1061
+ VALUE rval = rb_ary_new();
1062
+ CLIENT(self, client);
1063
+ client_each_viewee(client, client_add_viewee_to_rb_ary, &rval);
1064
+ return rval;
1065
+ }
1066
+
1067
+ static gpointer
1068
+ map_increase_gdouble_with_config(GeoSet *set, gpointer triangle, gpointer user_data) {
1069
+ gpointer *args = (gpointer *) user_data;
1070
+ Map *map = (Map *) args[0];
1071
+ gdouble *to_increase = (gdouble *) args[1];
1072
+ gint config = GPOINTER_TO_INT(g_hash_table_lookup(map->config_by_whatever, triangle));
1073
+ if (*to_increase < (config / 1000.0))
1074
+ (*to_increase) = (config / 1000.0);
1075
+ return NULL;
1076
+ }
1077
+
1078
+ static gdouble
1079
+ map_speed_factor(Map *map, Point *point) {
1080
+ gdouble rval = 1.0;
1081
+ gpointer args[2] = { map, &rval };
1082
+ triangle_set_each_container_until(map->speed_areas, point, map_increase_gdouble_with_config, args);
1083
+ return rval;
1084
+ }
1085
+
1086
+ static gdouble
1087
+ client_speed(Client *client) {
1088
+ gdouble rval = client->running_speed;
1089
+ if (client->state == rb_dodging)
1090
+ rval /= 5.0;
1091
+ rval *= map_speed_factor(client->map, client->body->origo);
1092
+ return rval;
1093
+ }
1094
+
1095
+ static gpointer
1096
+ client_add_viewer_to_hash(Client *viewer, Client *viewee, gpointer user_data) {
1097
+ g_hash_table_insert((GHashTable *) user_data, viewer, viewer);
1098
+ return NULL;
1099
+ }
1100
+
1101
+ static gpointer
1102
+ client_add_viewee_to_hash(Client *viewer, Client *viewee, gpointer user_data) {
1103
+ g_hash_table_insert((GHashTable *) user_data, viewee, viewee);
1104
+ return NULL;
1105
+ }
1106
+
1107
+ static gboolean
1108
+ socket_send(gint fn, gchar *to_send, gint to_send_len, struct timeval wait_time) {
1109
+ gchar *position = to_send;
1110
+ gint write_rval;
1111
+ while (position < to_send + to_send_len) {
1112
+ write_rval = write(fn, position, to_send_len + to_send - position);
1113
+ if (write_rval != -1) {
1114
+ gchar blaj[to_send_len];
1115
+ snprintf(blaj, write_rval + 1, "%s", position);
1116
+ position += write_rval;
1117
+ } else if (errno == EAGAIN) {
1118
+ rb_thread_wait_for(wait_time);
1119
+ } else {
1120
+ return FALSE;
1121
+ }
1122
+ }
1123
+ return TRUE;
1124
+ }
1125
+
1126
+ static void
1127
+ client_send(Client *client, gchar *str, gint len) {
1128
+ FILE *file;
1129
+ gchar header[BUFFER_UNIT];
1130
+ gint fn;
1131
+ struct timeval wait_time = { 0, 1000 };
1132
+
1133
+ while (client->socket_locked)
1134
+ rb_thread_wait_for(wait_time);
1135
+
1136
+ client->socket_locked = TRUE;
1137
+
1138
+ file = GetWriteFile(client->socket);
1139
+ rb_io_set_nonblock(client->socket);
1140
+ fn = fileno(file);
1141
+
1142
+ snprintf(header, BUFFER_UNIT, "%i:", len);
1143
+ if (!socket_send(fn, header, strlen(header), wait_time)) {
1144
+ client->socket_locked = FALSE;
1145
+ rb_sys_fail(client->socket->path);
1146
+ }
1147
+
1148
+ if (!socket_send(fn, str, len, wait_time)) {
1149
+ client->socket_locked = FALSE;
1150
+ rb_sys_fail(client->socket->path);
1151
+ }
1152
+
1153
+ DEBUG("sent to %p: %s%s", client, header, str);
1154
+
1155
+ client->socket_locked = FALSE;
1156
+ }
1157
+
1158
+ static gpointer
1159
+ client_send_unscore_for(Client *recipient, gpointer other) {
1160
+ gchar msg[BUFFER_UNIT * 2];
1161
+ Client *client = (Client *) other;
1162
+ snprintf(msg, BUFFER_UNIT * 2, "xml:<MESSAGE><UNSCORE id=\"%p\"/></MESSAGE>",
1163
+ client);
1164
+ client_send(recipient, msg, strlen(msg));
1165
+ return NULL;
1166
+ }
1167
+
1168
+ static void
1169
+ client_broadcast_unscore(Client *client) {
1170
+ map_each_client_until(client->map, client_send_unscore_for, client);
1171
+ }
1172
+
1173
+ static VALUE
1174
+ rb_client_unregister(VALUE self) {
1175
+ Client *client;
1176
+ CLIENT(self, client);
1177
+ map_unregister_body(client->map, client->body);
1178
+ client_broadcast_unscore(client);
1179
+ return self;
1180
+ }
1181
+
1182
+ static gchar*
1183
+ client_model(Client *client) {
1184
+ gchar *rval = calloc(BUFFER_UNIT, sizeof(gchar));
1185
+ snprintf(rval, BUFFER_UNIT, "%s_%s", client->team, client->behaviour);
1186
+ return rval;
1187
+ }
1188
+
1189
+ static gpointer
1190
+ map_sum_score_for_team(Client *client, gpointer user_data) {
1191
+ gpointer *args = (gpointer *) user_data;
1192
+ gchar *team = (gchar *) args[0];
1193
+ gdouble *sum = (gdouble *) args[1];
1194
+ if (strcmp(team, client->team) == 0)
1195
+ (*sum) += client->score;
1196
+ return NULL;
1197
+ }
1198
+
1199
+ static gdouble
1200
+ map_team_score(Map *map, gchar *team) {
1201
+ gdouble sum = 0;
1202
+ gpointer args[2] = { team, &sum };
1203
+ map_each_client_until(map, map_sum_score_for_team, args);
1204
+ return sum;
1205
+ }
1206
+
1207
+ static char*
1208
+ client_state(Client *client) {
1209
+ return client->state == rb_standing ? standing : (client->state == rb_dodging ? dodging : dead);
1210
+ }
1211
+
1212
+ static void
1213
+ client_send_score(Client *recipient, Client *subject) {
1214
+ gchar msg[BUFFER_UNIT * 2];
1215
+ snprintf(msg, BUFFER_UNIT * 2, "xml:<MESSAGE><SCORE id=\"%p\" nickname=\"%s\" team=\"%s\" state=\"%s\" score=\"%.1f\" kills=\"%.0f\" deaths=\"%.0f\"/></MESSAGE>",
1216
+ subject,
1217
+ subject->nickname,
1218
+ subject->team,
1219
+ client_state(subject),
1220
+ subject->score,
1221
+ subject->kills,
1222
+ subject->deaths);
1223
+ client_send(recipient, msg, strlen(msg));
1224
+ }
1225
+
1226
+ static gpointer
1227
+ client_send_score_for(Client *recipient, gpointer other) {
1228
+ client_send_score(recipient, (Client *) other);
1229
+ return NULL;
1230
+ }
1231
+
1232
+ static void
1233
+ client_broadcast_score(Client *client) {
1234
+ map_each_client_until(client->map, client_send_score_for, client);
1235
+ }
1236
+
1237
+ static gpointer
1238
+ client_receive_score_for(Client *subject, gpointer recipient) {
1239
+ client_send_score((Client *) recipient, subject);
1240
+ return NULL;
1241
+ }
1242
+
1243
+ static void
1244
+ client_receive_scores(Client *client) {
1245
+ map_each_client_until(client->map, client_receive_score_for, client);
1246
+ }
1247
+
1248
+ static VALUE
1249
+ rb_client_register(VALUE self) {
1250
+ Client *client;
1251
+ CLIENT(self, client);
1252
+ map_register_body(client->map, client->body);
1253
+ client_receive_scores(client);
1254
+ client->status_dirty = TRUE;
1255
+ return self;
1256
+ }
1257
+
1258
+ static void
1259
+ client_send_status(Client *client) {
1260
+ if (client->status_dirty) {
1261
+ gchar msg[BUFFER_UNIT * 2];
1262
+ snprintf(msg, BUFFER_UNIT * 2, "xml:<MESSAGE><STATUS player_score=\"%.1f\" team_score=\"%.1f\" hitpoints=\"%.1f\" extra=\"%s\" id=\"%p\"/></MESSAGE>",
1263
+ client->score,
1264
+ map_team_score(client->map, client->team),
1265
+ client->hitpoints,
1266
+ client->extra_status != NULL ? client->extra_status : "",
1267
+ client);
1268
+ client_send(client, msg, strlen(msg));
1269
+
1270
+ client_broadcast_score(client);
1271
+
1272
+ client->status_dirty = FALSE;
1273
+ }
1274
+ }
1275
+
1276
+ static void
1277
+ client_send_sighting(Client *viewer, Client *viewee) {
1278
+ gchar msg[BUFFER_UNIT];
1279
+ gchar *model = client_model(viewee);
1280
+ snprintf(msg, BUFFER_UNIT, "xml:<MESSAGE><SIGHTING id=\"%p\" nickname=\"%s\" model=\"%s\" state=\"%s\" x=\"%i\" y=\"%i\"/></MESSAGE>",
1281
+ viewee,
1282
+ viewee->nickname,
1283
+ model,
1284
+ client_state(viewee),
1285
+ (gint) round(viewee->body->origo->x),
1286
+ (gint) round(viewee->body->origo->y));
1287
+ free(model);
1288
+ client_send(viewer, msg, strlen(msg));
1289
+ }
1290
+
1291
+ static VALUE
1292
+ rb_client_send_sighting(VALUE self, VALUE o) {
1293
+ Client *client;
1294
+ Client *other;
1295
+ CHECK_CLIENT(o);
1296
+ CLIENT(self, client);
1297
+ CLIENT(o, other);
1298
+ client_send_sighting(client, other);
1299
+ return o;
1300
+ }
1301
+
1302
+ static void
1303
+ client_send_disappearance(Client *viewer, Client *viewee) {
1304
+ gchar msg[BUFFER_UNIT];
1305
+ snprintf(msg, BUFFER_UNIT, "xml:<MESSAGE><DISAPPEARANCE id=\"%p\"/></MESSAGE>",
1306
+ viewee);
1307
+ client_send(viewer, msg, strlen(msg));
1308
+ }
1309
+
1310
+ static VALUE
1311
+ rb_client_send_disappearance(VALUE self, VALUE o) {
1312
+ Client *client;
1313
+ Client *other;
1314
+ CHECK_CLIENT(o);
1315
+ CLIENT(self, client);
1316
+ CLIENT(o, other);
1317
+ client_send_disappearance(client, other);
1318
+ return o;
1319
+ }
1320
+
1321
+ static gpointer
1322
+ client_send_sighting_and_remove_viewer_from_hash(Client *viewer, Client *viewee, gpointer user_data) {
1323
+ GHashTable *old_viewers = (GHashTable *) user_data;
1324
+ client_send_sighting(viewer, viewee);
1325
+ if (g_hash_table_lookup(old_viewers, viewer) != NULL)
1326
+ g_hash_table_remove(old_viewers, viewer);
1327
+ return NULL;
1328
+ }
1329
+
1330
+ static gpointer
1331
+ client_send_sighting_and_remove_viewee_from_hash(Client *viewer, Client *viewee, gpointer user_data) {
1332
+ gpointer *args = (gpointer *) user_data;
1333
+ GHashTable *old_viewees = (GHashTable *) args[0];
1334
+ Client *self = (Client *) args[1];
1335
+ if (viewee != self)
1336
+ client_send_sighting(viewer, viewee);
1337
+ if (g_hash_table_lookup(old_viewees, viewee) != NULL)
1338
+ g_hash_table_remove(old_viewees, viewee);
1339
+ return NULL;
1340
+ }
1341
+
1342
+ static void
1343
+ g_hash_table_send_disappearance_to_key(gpointer key, gpointer value, gpointer user_data) {
1344
+ client_send_disappearance((Client *) key, (Client *) user_data);
1345
+ }
1346
+
1347
+ static void
1348
+ g_hash_table_send_disappearance_to_user_data(gpointer key, gpointer value, gpointer user_data) {
1349
+ client_send_disappearance((Client *) user_data, (Client *) key);
1350
+ }
1351
+
1352
+ static void
1353
+ client_update_viewers(Client *client, GHashTable *old_viewers) {
1354
+ client_each_viewer(client, client_send_sighting_and_remove_viewer_from_hash, old_viewers);
1355
+ g_hash_table_foreach(old_viewers, g_hash_table_send_disappearance_to_key, client);
1356
+ }
1357
+
1358
+ static void
1359
+ client_update_viewees(Client *client, GHashTable *old_viewees) {
1360
+ gpointer args[2] = { old_viewees, client };
1361
+ client_each_viewee(client, client_send_sighting_and_remove_viewee_from_hash, args);
1362
+ g_hash_table_foreach(old_viewees, g_hash_table_send_disappearance_to_user_data, client);
1363
+ }
1364
+
1365
+ static void
1366
+ client_update_viewing(Client *client, GHashTable *old_viewers, GHashTable *old_viewees) {
1367
+ client_update_viewers(client, old_viewers);
1368
+ client_update_viewees(client, old_viewees);
1369
+ }
1370
+
1371
+ static VALUE
1372
+ rb_client_update_viewing(VALUE self) {
1373
+ Client *client;
1374
+ GHashTable *old_viewers = g_hash_table_new(g_direct_hash, g_direct_equal);
1375
+ GHashTable *old_viewees = g_hash_table_new(g_direct_hash, g_direct_equal);
1376
+ CLIENT(self, client);
1377
+ client_update_viewing(client, old_viewers, old_viewees);
1378
+ g_hash_table_destroy(old_viewers);
1379
+ g_hash_table_destroy(old_viewees);
1380
+ return self;
1381
+ }
1382
+
1383
+ static void
1384
+ client_set_position(Client *client, Point *new_location, VALUE new_state) {
1385
+ if (round(new_location->x) != round(client->body->origo->x) ||
1386
+ round(new_location->y) != round(client->body->origo->y) ||
1387
+ new_state != client->state) {
1388
+
1389
+ GHashTable *old_viewers = g_hash_table_new(g_direct_hash, g_direct_equal);
1390
+ GHashTable *old_viewees = g_hash_table_new(g_direct_hash, g_direct_equal);
1391
+
1392
+ client_each_viewer(client, client_add_viewer_to_hash, old_viewers);
1393
+ client_each_viewee(client, client_add_viewee_to_hash, old_viewees);
1394
+
1395
+ body_relocate(client->body, new_location);
1396
+ if (client->state != new_state)
1397
+ client->status_dirty = TRUE;
1398
+ client->state = new_state;
1399
+
1400
+ client_update_viewing(client, old_viewers, old_viewees);
1401
+
1402
+ g_hash_table_destroy(old_viewers);
1403
+ g_hash_table_destroy(old_viewees);
1404
+ } else {
1405
+ body_relocate(client->body, new_location);
1406
+ client->state = new_state;
1407
+ }
1408
+ }
1409
+
1410
+ static VALUE
1411
+ rb_client_set_position(VALUE self, VALUE new_loc_val, VALUE new_state) {
1412
+ Client *client;
1413
+ Point *new_loc;
1414
+ CHECK_POINT(new_loc_val);
1415
+ CLIENT(self, client);
1416
+ POINT(new_loc_val, new_loc);
1417
+ client_set_position(client, new_loc, new_state);
1418
+ return Qnil;
1419
+ }
1420
+
1421
+ static gboolean
1422
+ command_not_includes_attribute(gpointer key, gpointer value, gpointer other_command_gp) {
1423
+ Command *other_command = (Command *) other_command_gp;
1424
+ gchar *other_value;
1425
+ if ((other_value = (gchar *) g_hash_table_lookup(other_command->attributes, key)) == NULL)
1426
+ return TRUE;
1427
+ return strcmp(other_value, (gchar *) value) != 0;
1428
+ }
1429
+
1430
+ static gboolean
1431
+ command_set_not_includes_command(gpointer name, gpointer command, gpointer other_set_gp) {
1432
+ CommandSet *other_set = (CommandSet *) other_set_gp;
1433
+ Command *other_command;
1434
+ Command *this_command = (Command *) command;
1435
+ if ((other_command = (Command *) g_hash_table_lookup(other_set->commands, name)) == NULL)
1436
+ return TRUE;
1437
+ return (g_hash_table_find(this_command->attributes, command_not_includes_attribute, other_command) != NULL &&
1438
+ g_hash_table_find(other_command->attributes, command_not_includes_attribute, this_command) != NULL);
1439
+ }
1440
+
1441
+ static gboolean
1442
+ command_set_equal(CommandSet *set1, CommandSet *set2) {
1443
+ return (g_hash_table_find(set1->commands, command_set_not_includes_command, set2) == NULL &&
1444
+ g_hash_table_find(set2->commands, command_set_not_includes_command, set1) == NULL);
1445
+ }
1446
+
1447
+ static VALUE
1448
+ rb_command_set_equal(VALUE self, VALUE other) {
1449
+ CommandSet *me;
1450
+ CommandSet *o;
1451
+ CHECK_COMMAND_SET(other);
1452
+ COMMAND_SET(self, me);
1453
+ COMMAND_SET(other, o);
1454
+ return GBOOL2RB(command_set_equal(me, o));
1455
+ }
1456
+
1457
+ static void
1458
+ client_insert_into_last_command(gpointer name, gpointer command, gpointer client) {
1459
+ gchar *dup = g_strdup((gchar *) name);
1460
+ g_hash_table_insert(( (Client *) client)->last_command, dup, dup);
1461
+ }
1462
+
1463
+ static void
1464
+ client_save_current_command(Client *client) {
1465
+ g_hash_table_remove_all(client->last_command);
1466
+ g_hash_table_foreach(client->current_command->commands, client_insert_into_last_command, client);
1467
+ }
1468
+
1469
+ static VALUE
1470
+ rb_client_save_current_command(VALUE self) {
1471
+ Client *client;
1472
+ CLIENT(self, client);
1473
+ client_save_current_command(client);
1474
+ return self;
1475
+ }
1476
+
1477
+ static void
1478
+ g_hash_table_insert_string_into_rb_ary(gpointer key, gpointer value, gpointer ary) {
1479
+ rb_ary_push(*((VALUE *) ary), rb_str_new2((gchar *) key));
1480
+ }
1481
+
1482
+ static VALUE
1483
+ rb_client_last_command(VALUE self) {
1484
+ Client *client;
1485
+ VALUE rval;
1486
+ CLIENT(self, client);
1487
+ rval = rb_ary_new();
1488
+ g_hash_table_foreach(client->last_command, g_hash_table_insert_string_into_rb_ary, &rval);
1489
+ return rval;
1490
+ }
1491
+
1492
+ static void
1493
+ client_call_subscription_if_subscribed(gpointer key, gpointer value, gpointer client_gp) {
1494
+ Client *client = (Client *) client_gp;
1495
+ ID *meth;
1496
+ if ((meth = g_hash_table_lookup(client->subscriptions, key)) != NULL) {
1497
+ rb_funcall(client->rbClient, *meth, 1, ( (Command *) value )->rbCommand);
1498
+ }
1499
+ }
1500
+
1501
+ static void
1502
+ client_call_subscription_if_command_disappeared(gpointer key, gpointer value, gpointer client_gp) {
1503
+ Client *client = (Client *) client_gp;
1504
+ ID *meth;
1505
+ if ((meth = g_hash_table_lookup(client->subscriptions, key)) != NULL &&
1506
+ g_hash_table_lookup(client->current_command->commands, key) == NULL) {
1507
+ rb_funcall(client->rbClient, *meth, 1, Qnil);
1508
+ }
1509
+ }
1510
+
1511
+ static void
1512
+ client_call_subscriptions(Client *client) {
1513
+ g_hash_table_foreach(client->current_command->commands, client_call_subscription_if_subscribed, client);
1514
+ g_hash_table_foreach(client->last_command, client_call_subscription_if_command_disappeared, client);
1515
+ }
1516
+
1517
+ static void
1518
+ client_update(Client *client) {
1519
+ if (client->state != rb_dead) {
1520
+ Point new_location = { 0, 0, 0};
1521
+ gdouble direction = -1.0;
1522
+ VALUE new_state;
1523
+
1524
+ client_call_subscriptions(client);
1525
+
1526
+ new_location.x = client->body->origo->x;
1527
+ new_location.y = client->body->origo->y;
1528
+ new_state = client->state;
1529
+
1530
+ if (COMMAND_SET_INCLUDES(client->current_command, UP)) {
1531
+ if (COMMAND_SET_INCLUDES(client->current_command, LEFT)) {
1532
+ direction = 3.0 * M_PI_4;
1533
+ } else if (COMMAND_SET_INCLUDES(client->current_command, RIGHT)) {
1534
+ direction = 1.0 * M_PI_4;
1535
+ } else {
1536
+ direction = M_PI_2;
1537
+ }
1538
+ } else if (COMMAND_SET_INCLUDES(client->current_command, DOWN)) {
1539
+ if (COMMAND_SET_INCLUDES(client->current_command, LEFT)) {
1540
+ direction = 5.0 * M_PI_4;
1541
+ } else if (COMMAND_SET_INCLUDES(client->current_command, RIGHT)) {
1542
+ direction = 7.0 * M_PI_4;
1543
+ } else {
1544
+ direction = 3.0 * M_PI_2;
1545
+ }
1546
+ } else if (COMMAND_SET_INCLUDES(client->current_command, LEFT)) {
1547
+ direction = M_PI;
1548
+ } else if (COMMAND_SET_INCLUDES(client->current_command, RIGHT)) {
1549
+ direction = 0.0;
1550
+ }
1551
+
1552
+ if (COMMAND_SET_INCLUDES(client->current_command, DODGE)) {
1553
+ new_state = rb_dodging;
1554
+ } else {
1555
+ new_state = rb_standing;
1556
+ }
1557
+
1558
+ if (direction != -1) {
1559
+ gdouble speed = client_speed(client);
1560
+ Point wanted_new_destination = { client->body->origo->x + speed * cos(direction), client->body->origo->y - speed * sin(direction), 0 };
1561
+ map_move(client->map, client->body->origo, &wanted_new_destination, &new_location);
1562
+ }
1563
+
1564
+ client_set_position(client, &new_location, new_state);
1565
+ client_send_status(client);
1566
+
1567
+ client_save_current_command(client);
1568
+ }
1569
+ }
1570
+
1571
+ static gpointer
1572
+ map_update_client_until(Client *client, gpointer null) {
1573
+ client_update(client);
1574
+ return NULL;
1575
+ }
1576
+
1577
+ static VALUE
1578
+ rb_map_update(VALUE self) {
1579
+ Map *map;
1580
+ MAP(self, map);
1581
+ map_each_client_until(map, map_update_client_until, NULL);
1582
+ return Qnil;
1583
+ }
1584
+
1585
+ static VALUE
1586
+ rb_client_update(VALUE self) {
1587
+ Client *client;
1588
+ CLIENT(self, client);
1589
+
1590
+ client_update(client);
1591
+
1592
+ return Qnil;
1593
+ }
1594
+
1595
+ static VALUE
1596
+ rb_map_get_timeout(VALUE self) {
1597
+ Map *map;
1598
+ MAP(self, map);
1599
+ return INT2NUM(map->timeout);
1600
+ }
1601
+
1602
+ static VALUE
1603
+ rb_map_set_timeout(VALUE self, VALUE timeout) {
1604
+ Map *map;
1605
+ MAP(self, map);
1606
+ CHECK_NUMERICALITY(timeout);
1607
+ map->timeout = NUM2INT(timeout);
1608
+ return timeout;
1609
+ }
1610
+
1611
+ static VALUE
1612
+ rb_map_get_viewing_distance_limit(VALUE self) {
1613
+ Map *map;
1614
+ MAP(self, map);
1615
+ return INT2NUM(map->viewing_distance_limit);
1616
+ }
1617
+
1618
+ static VALUE
1619
+ rb_map_set_viewing_distance_limit(VALUE self, VALUE viewing_distance_limit) {
1620
+ Map *map;
1621
+ MAP(self, map);
1622
+ CHECK_NUMERICALITY(viewing_distance_limit);
1623
+ map->viewing_distance_limit = NUM2INT(viewing_distance_limit);
1624
+ return viewing_distance_limit;
1625
+ }
1626
+
1627
+ static VALUE
1628
+ rb_client_get_running_speed(VALUE self) {
1629
+ Client *client;
1630
+ CLIENT(self, client);
1631
+ return INT2NUM(client->running_speed);
1632
+ }
1633
+
1634
+ static VALUE
1635
+ rb_client_set_running_speed(VALUE self, VALUE running_speed) {
1636
+ Client *client;
1637
+ CLIENT(self, client);
1638
+ CHECK_NUMERICALITY(running_speed);
1639
+ client->running_speed = NUM2INT(running_speed);
1640
+ return running_speed;
1641
+ }
1642
+
1643
+ static VALUE
1644
+ rb_client_model(VALUE self) {
1645
+ Client *client;
1646
+ VALUE rval;
1647
+ gchar *str;
1648
+ CLIENT(self, client);
1649
+ str = client_model(client);
1650
+ rval = rb_str_new2(str);
1651
+ free(str);
1652
+ return rval;
1653
+ }
1654
+
1655
+ static VALUE
1656
+ rb_client_get_team(VALUE self) {
1657
+ Client *client;
1658
+ CLIENT(self, client);
1659
+ if (client->team == NULL)
1660
+ return Qnil;
1661
+ return rb_str_new2(client->team);
1662
+ }
1663
+
1664
+ static VALUE
1665
+ rb_client_set_team(VALUE self, VALUE v) {
1666
+ Client *client;
1667
+ Check_Type(v, T_STRING);
1668
+ CLIENT(self, client);
1669
+ if (client->team != NULL) {
1670
+ if (strcmp(client->extra_status, RSTRING(v)->ptr) != 0) {
1671
+ free(client->team);
1672
+ client->team = g_strndup(RSTRING(v)->ptr, RSTRING(v)->len);
1673
+ client->status_dirty = TRUE;
1674
+ }
1675
+ } else {
1676
+ client->team = g_strndup(RSTRING(v)->ptr, RSTRING(v)->len);
1677
+ client->status_dirty = TRUE;
1678
+ }
1679
+ return v;
1680
+ }
1681
+
1682
+ static VALUE
1683
+ rb_client_get_extra_status(VALUE self) {
1684
+ Client *client;
1685
+ CLIENT(self, client);
1686
+ if (client->extra_status == NULL)
1687
+ return Qnil;
1688
+ return rb_str_new2(client->extra_status);
1689
+ }
1690
+
1691
+ static VALUE
1692
+ rb_client_set_extra_status(VALUE self, VALUE v) {
1693
+ Client *client;
1694
+ Check_Type(v, T_STRING);
1695
+ CLIENT(self, client);
1696
+ if (client->extra_status != NULL) {
1697
+ if (strcmp(client->extra_status, RSTRING(v)->ptr) != 0) {
1698
+ free(client->extra_status);
1699
+ client->extra_status = g_strndup(RSTRING(v)->ptr, RSTRING(v)->len);
1700
+ client->status_dirty = TRUE;
1701
+ }
1702
+ } else {
1703
+ client->extra_status = g_strndup(RSTRING(v)->ptr, RSTRING(v)->len);
1704
+ client->status_dirty = TRUE;
1705
+ }
1706
+ return v;
1707
+ }
1708
+
1709
+ static VALUE
1710
+ rb_client_get_behaviour(VALUE self) {
1711
+ Client *client;
1712
+ CLIENT(self, client);
1713
+ if (client->behaviour == NULL)
1714
+ return Qnil;
1715
+ return rb_str_new2(client->behaviour);
1716
+ }
1717
+
1718
+ static VALUE
1719
+ rb_client_set_behaviour(VALUE self, VALUE v) {
1720
+ Client *client;
1721
+ Check_Type(v, T_STRING);
1722
+ CLIENT(self, client);
1723
+ if (client->behaviour != NULL) {
1724
+ if (strcmp(client->behaviour, RSTRING(v)->ptr) != 0) {
1725
+ free(client->behaviour);
1726
+ client->behaviour = g_strndup(RSTRING(v)->ptr, RSTRING(v)->len);
1727
+ client->status_dirty = TRUE;
1728
+ }
1729
+ } else {
1730
+ client->behaviour = g_strndup(RSTRING(v)->ptr, RSTRING(v)->len);
1731
+ client->status_dirty = TRUE;
1732
+ }
1733
+ return v;
1734
+ }
1735
+
1736
+ static VALUE
1737
+ rb_client_get_nickname(VALUE self) {
1738
+ Client *client;
1739
+ CLIENT(self, client);
1740
+ if (client->nickname == NULL)
1741
+ return Qnil;
1742
+ return rb_str_new2(client->nickname);
1743
+ }
1744
+
1745
+ static VALUE
1746
+ rb_client_set_nickname(VALUE self, VALUE v) {
1747
+ Client *client;
1748
+ Check_Type(v, T_STRING);
1749
+ CLIENT(self, client);
1750
+ if (client->nickname != NULL) {
1751
+ if (strcmp(client->nickname, RSTRING(v)->ptr) != 0) {
1752
+ free(client->nickname);
1753
+ client->nickname = g_strndup(RSTRING(v)->ptr, RSTRING(v)->len);
1754
+ client->status_dirty = TRUE;
1755
+ }
1756
+ } else {
1757
+ client->nickname = g_strndup(RSTRING(v)->ptr, RSTRING(v)->len);
1758
+ client->status_dirty = TRUE;
1759
+ }
1760
+ return v;
1761
+ }
1762
+
1763
+ static VALUE
1764
+ rb_client_get_socket(VALUE self) {
1765
+ Client *client;
1766
+ CLIENT(self, client);
1767
+ return client->rbSocket;
1768
+ }
1769
+
1770
+ static VALUE
1771
+ rb_client_set_socket(VALUE self, VALUE new_socket) {
1772
+ Client *client;
1773
+ OpenFile *fptr;
1774
+
1775
+ GetOpenFile(new_socket, fptr);
1776
+ rb_io_check_writable(fptr);
1777
+ CLIENT(self, client);
1778
+
1779
+ client->socket = fptr;
1780
+ client->rbSocket = new_socket;
1781
+
1782
+ return new_socket;
1783
+ }
1784
+
1785
+ static VALUE
1786
+ rb_client_send(VALUE self, VALUE str) {
1787
+ Client *client;
1788
+
1789
+ Check_Type(str, T_STRING);
1790
+ CLIENT(self, client);
1791
+ if (client->socket == NULL)
1792
+ rb_raise(rb_eRuntimeError, "Client %p does not have a socket!", client);
1793
+
1794
+ client_send(client, RSTRING(str)->ptr, RSTRING(str)->len);
1795
+
1796
+ return str;
1797
+ }
1798
+
1799
+ static VALUE
1800
+ rb_client_status_dirty(VALUE self) {
1801
+ Client *client;
1802
+ CLIENT(self, client);
1803
+ return GBOOL2RB(client->status_dirty);
1804
+ }
1805
+
1806
+ static VALUE
1807
+ rb_client_set_status_dirty(VALUE self) {
1808
+ Client *client;
1809
+ CLIENT(self, client);
1810
+ client->status_dirty = TRUE;
1811
+ return Qtrue;
1812
+ }
1813
+
1814
+ static VALUE
1815
+ rb_client_set_status_clean(VALUE self) {
1816
+ Client *client;
1817
+ CLIENT(self, client);
1818
+ client->status_dirty = FALSE;
1819
+ return Qfalse;
1820
+ }
1821
+
1822
+ static VALUE
1823
+ rb_map_body_parts(VALUE self) {
1824
+ Map *map;
1825
+ MAP(self, map);
1826
+ return map->body_parts->rbGeoSet;
1827
+ }
1828
+
1829
+ static VALUE
1830
+ rb_map_bodies(VALUE self) {
1831
+ Map *map;
1832
+ MAP(self, map);
1833
+ return map->bodies->rbGeoSet;
1834
+ }
1835
+
1836
+ static VALUE
1837
+ rb_map_eyes(VALUE self) {
1838
+ Map *map;
1839
+ MAP(self, map);
1840
+ return map->eyes->rbGeoSet;
1841
+ }
1842
+
1843
+ static VALUE
1844
+ rb_client_get_score(VALUE self) {
1845
+ Client *client;
1846
+ CLIENT(self, client);
1847
+ return rb_float_new(client->score);
1848
+ }
1849
+
1850
+ static VALUE
1851
+ rb_client_set_score(VALUE self, VALUE new_score) {
1852
+ Client *client;
1853
+ gdouble new_score_gdouble;
1854
+ CHECK_NUMERICALITY(new_score);
1855
+ CLIENT(self, client);
1856
+ new_score_gdouble = NUM2DBL(new_score);
1857
+ if (!DBL_EQL(new_score_gdouble, client->score)) {
1858
+ client->status_dirty = TRUE;
1859
+ client->score = new_score_gdouble;
1860
+ }
1861
+ return new_score;
1862
+ }
1863
+
1864
+ static VALUE
1865
+ rb_client_get_kills(VALUE self) {
1866
+ Client *client;
1867
+ CLIENT(self, client);
1868
+ return rb_float_new(client->kills);
1869
+ }
1870
+
1871
+ static VALUE
1872
+ rb_client_set_kills(VALUE self, VALUE new_kills) {
1873
+ Client *client;
1874
+ gdouble new_kills_gdouble;
1875
+ CHECK_NUMERICALITY(new_kills);
1876
+ CLIENT(self, client);
1877
+ new_kills_gdouble = NUM2DBL(new_kills);
1878
+ if (!DBL_EQL(new_kills_gdouble, client->kills)) {
1879
+ client->status_dirty = TRUE;
1880
+ client->kills = new_kills_gdouble;
1881
+ }
1882
+ return new_kills;
1883
+ }
1884
+
1885
+ static VALUE
1886
+ rb_client_get_deaths(VALUE self) {
1887
+ Client *client;
1888
+ CLIENT(self, client);
1889
+ return rb_float_new(client->deaths);
1890
+ }
1891
+
1892
+ static VALUE
1893
+ rb_client_set_deaths(VALUE self, VALUE new_deaths) {
1894
+ Client *client;
1895
+ gdouble new_deaths_gdouble;
1896
+ CHECK_NUMERICALITY(new_deaths);
1897
+ CLIENT(self, client);
1898
+ new_deaths_gdouble = NUM2DBL(new_deaths);
1899
+ if (!DBL_EQL(new_deaths_gdouble, client->deaths)) {
1900
+ client->status_dirty = TRUE;
1901
+ client->deaths = new_deaths_gdouble;
1902
+ }
1903
+ return new_deaths;
1904
+ }
1905
+
1906
+ static VALUE
1907
+ rb_client_get_hitpoints(VALUE self) {
1908
+ Client *client;
1909
+ CLIENT(self, client);
1910
+ return rb_float_new(client->hitpoints);
1911
+ }
1912
+
1913
+ static VALUE
1914
+ rb_client_set_hitpoints(VALUE self, VALUE new_hitpoints) {
1915
+ Client *client;
1916
+ gdouble new_hitpoints_gdouble;
1917
+ CHECK_NUMERICALITY(new_hitpoints);
1918
+ CLIENT(self, client);
1919
+ new_hitpoints_gdouble = NUM2DBL(new_hitpoints);
1920
+ if (!DBL_EQL(new_hitpoints_gdouble, client->hitpoints)) {
1921
+ client->status_dirty = TRUE;
1922
+ client->hitpoints = new_hitpoints_gdouble;
1923
+ }
1924
+ return new_hitpoints;
1925
+ }
1926
+
1927
+ static VALUE
1928
+ rb_client_subscribe(VALUE self, VALUE n, VALUE meth) {
1929
+ Client *client;
1930
+ ID *id;
1931
+ gchar *name;
1932
+ Check_Type(n, T_STRING);
1933
+ Check_Type(meth, T_SYMBOL);
1934
+ CLIENT(self, client);
1935
+ id = ALLOC(ID);
1936
+ *id = SYM2ID(meth);
1937
+ name = g_strndup(RSTRING(n)->ptr, RSTRING(n)->len);
1938
+ g_hash_table_insert(client->subscriptions, name, id);
1939
+ return self;
1940
+ }
1941
+
1942
+ static VALUE
1943
+ rb_client_unsubscribe(VALUE self, VALUE n) {
1944
+ Client *client;
1945
+ ID *id;
1946
+ VALUE rval = 0;
1947
+ Check_Type(n, T_STRING);
1948
+ CLIENT(self, client);
1949
+ id = g_hash_table_lookup(client->subscriptions, RSTRING(n)->ptr);
1950
+ if (id != NULL)
1951
+ rval = ID2SYM(*id);
1952
+ g_hash_table_remove(client->subscriptions, RSTRING(n)->ptr);
1953
+ if (rval != 0)
1954
+ return rval;
1955
+ else
1956
+ return Qnil;
1957
+ }
1958
+
1959
+ #ifdef __cplusplus
1960
+ extern "C" {
1961
+ #endif
1962
+ void Init_grueserve_ext() {
1963
+ init_grueserve_globals();
1964
+
1965
+ VALUE rb_grueserve = rb_define_module("Grueserve");
1966
+ rb_map = rb_define_class_under(rb_grueserve,
1967
+ "Map",
1968
+ rb_cObject);
1969
+ rb_client = rb_define_class_under(rb_grueserve,
1970
+ "Client",
1971
+ rb_cObject);
1972
+ rb_command = rb_define_class_under(rb_client,
1973
+ "Command",
1974
+ rb_cObject);
1975
+ rb_command_set = rb_define_class_under(rb_client,
1976
+ "CommandSet",
1977
+ rb_cObject);
1978
+ rb_body = rb_define_class_under(rb_client,
1979
+ "Body",
1980
+ rb_cObject);
1981
+ rb_e_terminated_connection = rb_define_class_under(rb_client,
1982
+ "TerminatedConnection",
1983
+ rb_eRuntimeError);
1984
+
1985
+ rb_define_alloc_func(rb_client, rb_client_alloc);
1986
+ rb_define_method(rb_client, "register!", rb_client_register, 0);
1987
+ rb_define_method(rb_client, "unregister!", rb_client_unregister, 0);
1988
+ rb_define_method(rb_client, "registered?", rb_client_registered, 0);
1989
+ rb_define_method(rb_client, "body", rb_client_get_body, 0);
1990
+ rb_define_method(rb_client, "state", rb_client_get_state, 0);
1991
+ rb_define_method(rb_client, "state=", rb_client_set_state, 1);
1992
+ rb_define_method(rb_client, "moving?", rb_client_moving, 0);
1993
+ rb_define_method(rb_client, "current_command", rb_client_get_current_command, 0);
1994
+ rb_define_method(rb_client, "current_command=", rb_client_set_current_command, 1);
1995
+ rb_define_method(rb_client, "last_command", rb_client_last_command, 0);
1996
+ rb_define_method(rb_client, "save_current_command!", rb_client_save_current_command, 0);
1997
+ rb_define_method(rb_client, "map", rb_client_get_map, 0);
1998
+ rb_define_method(rb_client, "map=", rb_client_set_map, 1);
1999
+ rb_define_method(rb_client, "client_id", rb_client_client_id, 0);
2000
+ rb_define_method(rb_client, "last_ping", rb_client_get_last_ping, 0);
2001
+ rb_define_method(rb_client, "ping!", rb_client_ping, 0);
2002
+ rb_define_method(rb_client, "update!", rb_client_update, 0);
2003
+ rb_define_method(rb_client, "running_speed", rb_client_get_running_speed, 0);
2004
+ rb_define_method(rb_client, "running_speed=", rb_client_set_running_speed, 1);
2005
+ rb_define_method(rb_client, "socket=", rb_client_set_socket, 1);
2006
+ rb_define_method(rb_client, "socket", rb_client_get_socket, 0);
2007
+ rb_define_method(rb_client, "send", rb_client_send, 1);
2008
+ rb_define_method(rb_client, "team", rb_client_get_team, 0);
2009
+ rb_define_method(rb_client, "team=", rb_client_set_team, 1);
2010
+ rb_define_method(rb_client, "extra_status", rb_client_get_extra_status, 0);
2011
+ rb_define_method(rb_client, "extra_status=", rb_client_set_extra_status, 1);
2012
+ rb_define_method(rb_client, "behaviour", rb_client_get_behaviour, 0);
2013
+ rb_define_method(rb_client, "behaviour=", rb_client_set_behaviour, 1);
2014
+ rb_define_method(rb_client, "nickname", rb_client_get_nickname, 0);
2015
+ rb_define_method(rb_client, "nickname=", rb_client_set_nickname, 1);
2016
+ rb_define_method(rb_client, "model", rb_client_model, 0);
2017
+ rb_define_method(rb_client, "send_sighting", rb_client_send_sighting, 1);
2018
+ rb_define_method(rb_client, "send_disappearance", rb_client_send_disappearance, 1);
2019
+ rb_define_method(rb_client, "viewers", rb_client_viewers, 0);
2020
+ rb_define_method(rb_client, "viewees", rb_client_viewees, 0);
2021
+ rb_define_method(rb_client, "update_viewing", rb_client_update_viewing, 0);
2022
+ rb_define_method(rb_client, "status_dirty?", rb_client_status_dirty, 0);
2023
+ rb_define_method(rb_client, "status_dirty!", rb_client_set_status_dirty, 0);
2024
+ rb_define_method(rb_client, "status_clean!", rb_client_set_status_clean, 0);
2025
+ rb_define_method(rb_client, "score", rb_client_get_score, 0);
2026
+ rb_define_method(rb_client, "score=", rb_client_set_score, 1);
2027
+ rb_define_method(rb_client, "kills", rb_client_get_kills, 0);
2028
+ rb_define_method(rb_client, "kills=", rb_client_set_kills, 1);
2029
+ rb_define_method(rb_client, "deaths", rb_client_get_deaths, 0);
2030
+ rb_define_method(rb_client, "deaths=", rb_client_set_deaths, 1);
2031
+ rb_define_method(rb_client, "hitpoints", rb_client_get_hitpoints, 0);
2032
+ rb_define_method(rb_client, "hitpoints=", rb_client_set_hitpoints, 1);
2033
+ rb_define_method(rb_client, "set_position", rb_client_set_position, 2);
2034
+ rb_define_method(rb_client, "subscribe", rb_client_subscribe, 2);
2035
+ rb_define_method(rb_client, "unsubscribe", rb_client_unsubscribe, 1);
2036
+
2037
+ rb_define_alloc_func(rb_map, rb_map_alloc);
2038
+ rb_define_method(rb_map, "movement_obstacles", rb_map_movement_obstacles, 0);
2039
+ rb_define_method(rb_map, "visibility_obstacles", rb_map_visibility_obstacles, 0);
2040
+ rb_define_method(rb_map, "bullet_obstacles", rb_map_bullet_obstacles, 0);
2041
+ rb_define_method(rb_map, "hearing_obstacles", rb_map_hearing_obstacles, 0);
2042
+ rb_define_method(rb_map, "fortifications", rb_map_fortifications, 0);
2043
+ rb_define_method(rb_map, "speed_areas", rb_map_speed_areas, 0);
2044
+ rb_define_method(rb_map, "protection_areas", rb_map_protection_areas, 0);
2045
+ rb_define_method(rb_map, "hidden_areas", rb_map_hidden_areas, 0);
2046
+ rb_define_method(rb_map, "body_parts", rb_map_body_parts, 0);
2047
+ rb_define_method(rb_map, "bodies", rb_map_bodies, 0);
2048
+ rb_define_method(rb_map, "eyes", rb_map_eyes, 0);
2049
+ rb_define_method(rb_map, "[]", rb_map_get, 1);
2050
+ rb_define_method(rb_map, "[]=", rb_map_set, 2);
2051
+ rb_define_method(rb_map, "timeout", rb_map_get_timeout, 0);
2052
+ rb_define_method(rb_map, "timeout=", rb_map_set_timeout, 1);
2053
+ rb_define_method(rb_map, "viewing_distance_limit", rb_map_get_viewing_distance_limit, 0);
2054
+ rb_define_method(rb_map, "viewing_distance_limit=", rb_map_set_viewing_distance_limit, 1);
2055
+ rb_define_method(rb_map, "each_client", rb_map_each_client, 0);
2056
+ rb_define_method(rb_map, "viewers_of", rb_map_viewers_of, 1);
2057
+ rb_define_method(rb_map, "update!", rb_map_update, 0);
2058
+
2059
+ rb_undef_method(rb_body, "initialize");
2060
+ rb_define_method(rb_body, "origo", rb_body_get_origo, 0);
2061
+ rb_define_method(rb_body, "vertical_axis", rb_body_get_vertical_axis, 0);
2062
+ rb_define_method(rb_body, "horizontal_axis", rb_body_get_horizontal_axis, 0);
2063
+ rb_define_method(rb_body, "relocate", rb_body_relocate, 1);
2064
+ rb_define_method(rb_body, "inspect", rb_body_inspect, 0);
2065
+
2066
+ rb_define_alloc_func(rb_command, rb_command_alloc);
2067
+ rb_define_method(rb_command, "[]", rb_command_get, 1);
2068
+ rb_define_method(rb_command, "[]=", rb_command_insert, 2);
2069
+ rb_define_method(rb_command, "name", rb_command_get_name, 0);
2070
+ rb_define_method(rb_command, "name=", rb_command_set_name, 1);
2071
+ rb_define_method(rb_command, "inspect", rb_command_inspect, 0);
2072
+
2073
+ rb_define_alloc_func(rb_command_set, rb_command_set_alloc);
2074
+ rb_define_method(rb_command_set, "[]", rb_command_set_get, 1);
2075
+ rb_define_method(rb_command_set, "<<", rb_command_set_push, 1);
2076
+ rb_define_method(rb_command_set, "include?", rb_command_set_include, 1);
2077
+ rb_define_method(rb_command_set, "inspect", rb_command_set_inspect, 0);
2078
+ rb_define_method(rb_command_set, "==", rb_command_set_equal, 1);
2079
+ }
2080
+ #ifdef __cplusplus
2081
+ }
2082
+ #endif
2083
+