game_machine 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (273) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +4 -0
  3. data/Gemfile.lock +72 -0
  4. data/Rakefile +38 -0
  5. data/bin/game_machine +79 -0
  6. data/config/cluster.conf +65 -0
  7. data/config/config.example.yml +93 -0
  8. data/config/game_messages.proto +45 -0
  9. data/config/messages.proto +339 -0
  10. data/config/regions.example.yml +9 -0
  11. data/config/standalone.conf +36 -0
  12. data/db/do_not_delete +0 -0
  13. data/game_machine.gemspec +38 -0
  14. data/games/example/boot.rb +6 -0
  15. data/games/example/data/game_data.yml +13 -0
  16. data/games/example/lib/aggressive_npc.rb +176 -0
  17. data/games/example/lib/authentication_handler.rb +69 -0
  18. data/games/example/lib/chatbot.rb +61 -0
  19. data/games/example/lib/combat_controller.rb +145 -0
  20. data/games/example/lib/example_controller.rb +21 -0
  21. data/games/example/lib/game.rb +85 -0
  22. data/games/example/lib/models/attack.rb +9 -0
  23. data/games/example/lib/models/combat_update.rb +11 -0
  24. data/games/example/lib/models/player_command.rb +7 -0
  25. data/games/example/lib/models/user.rb +11 -0
  26. data/games/example/lib/models/vitals.rb +17 -0
  27. data/games/example/lib/npc.rb +111 -0
  28. data/games/example/lib/npc_group.rb +42 -0
  29. data/games/example/lib/npc_movement.rb +116 -0
  30. data/games/example/lib/player_manager.rb +58 -0
  31. data/games/example/lib/player_register.rb +80 -0
  32. data/games/example/lib/tracking_handler.rb +17 -0
  33. data/games/example/lib/zone_manager.rb +57 -0
  34. data/games/preload.rb +8 -0
  35. data/integration_tests/basic_spec.rb +68 -0
  36. data/integration_tests/bot_spec.rb +18 -0
  37. data/integration_tests/chat_spec.rb +45 -0
  38. data/integration_tests/distributed_spec.rb +34 -0
  39. data/integration_tests/entity_tracking_spec.rb +48 -0
  40. data/integration_tests/mono_spec.rb +16 -0
  41. data/integration_tests/objectdb_spec.rb +55 -0
  42. data/integration_tests/tcp_client_spec.rb +71 -0
  43. data/integration_tests/udp_client_spec.rb +61 -0
  44. data/integration_tests/udp_spec.rb +20 -0
  45. data/integration_tests/udt_client_spec.rb +23 -0
  46. data/integration_tests/udt_spec.rb +31 -0
  47. data/java/.gitignore +1 -0
  48. data/java/build.gradle +93 -0
  49. data/java/component.erb +396 -0
  50. data/java/gradle.properties +6 -0
  51. data/java/gradle/wrapper/gradle-wrapper.jar +0 -0
  52. data/java/gradle/wrapper/gradle-wrapper.properties +6 -0
  53. data/java/gradlew +164 -0
  54. data/java/gradlew.bat +90 -0
  55. data/java/local_lib/protostuff-compiler-1.0.7-jarjar.jar +0 -0
  56. data/java/settings.gradle +2 -0
  57. data/java/src/main/java/com/game_machine/core/ActorFactory.java +25 -0
  58. data/java/src/main/java/com/game_machine/core/ActorUtil.java +39 -0
  59. data/java/src/main/java/com/game_machine/core/CommandProxy.java +9 -0
  60. data/java/src/main/java/com/game_machine/core/EntitySerializer.java +66 -0
  61. data/java/src/main/java/com/game_machine/core/EventStreamHandler.java +43 -0
  62. data/java/src/main/java/com/game_machine/core/GameMachineLoader.java +25 -0
  63. data/java/src/main/java/com/game_machine/core/Grid.java +195 -0
  64. data/java/src/main/java/com/game_machine/core/GridValue.java +30 -0
  65. data/java/src/main/java/com/game_machine/core/IActorFactory.java +7 -0
  66. data/java/src/main/java/com/game_machine/core/NetMessage.java +28 -0
  67. data/java/src/main/java/com/game_machine/core/UdpServer.java +97 -0
  68. data/java/src/main/java/com/game_machine/core/UdpServerHandler.java +90 -0
  69. data/java/src/main/resources/game_machine.java.stg +738 -0
  70. data/java/src/main/resources/logback.xml +14 -0
  71. data/java/src/main/resources/logging.properties +3 -0
  72. data/java/src/main/resources/protostuff.properties +7 -0
  73. data/lib/game_machine.rb +85 -0
  74. data/lib/game_machine/actor.rb +7 -0
  75. data/lib/game_machine/actor/base.rb +184 -0
  76. data/lib/game_machine/actor/builder.rb +108 -0
  77. data/lib/game_machine/actor/development.rb +31 -0
  78. data/lib/game_machine/actor/factory.rb +35 -0
  79. data/lib/game_machine/actor/mono_actor.rb +89 -0
  80. data/lib/game_machine/actor/ref.rb +81 -0
  81. data/lib/game_machine/actor/reloadable.rb +98 -0
  82. data/lib/game_machine/actor/system.rb +32 -0
  83. data/lib/game_machine/akka.rb +98 -0
  84. data/lib/game_machine/app_config.rb +49 -0
  85. data/lib/game_machine/application.rb +181 -0
  86. data/lib/game_machine/auth_handlers/base.rb +21 -0
  87. data/lib/game_machine/auth_handlers/public.rb +34 -0
  88. data/lib/game_machine/bot/chat.rb +66 -0
  89. data/lib/game_machine/bot/client.rb +54 -0
  90. data/lib/game_machine/client_manager.rb +204 -0
  91. data/lib/game_machine/clients.rb +4 -0
  92. data/lib/game_machine/clients/client.rb +45 -0
  93. data/lib/game_machine/clients/tcp_client.rb +25 -0
  94. data/lib/game_machine/clients/test_client.rb +151 -0
  95. data/lib/game_machine/clients/udp_client.rb +25 -0
  96. data/lib/game_machine/clients/udt_client.rb +34 -0
  97. data/lib/game_machine/cluster_monitor.rb +115 -0
  98. data/lib/game_machine/commands.rb +23 -0
  99. data/lib/game_machine/commands/base.rb +21 -0
  100. data/lib/game_machine/commands/chat_commands.rb +88 -0
  101. data/lib/game_machine/commands/datastore_commands.rb +60 -0
  102. data/lib/game_machine/commands/grid_commands.rb +35 -0
  103. data/lib/game_machine/commands/message_helper.rb +25 -0
  104. data/lib/game_machine/commands/misc_commands.rb +29 -0
  105. data/lib/game_machine/commands/navigation_commands.rb +24 -0
  106. data/lib/game_machine/commands/player_commands.rb +28 -0
  107. data/lib/game_machine/commands/proxy.rb +16 -0
  108. data/lib/game_machine/console.rb +3 -0
  109. data/lib/game_machine/console/build.rb +74 -0
  110. data/lib/game_machine/console/install.rb +92 -0
  111. data/lib/game_machine/console/server.rb +120 -0
  112. data/lib/game_machine/data_store.rb +52 -0
  113. data/lib/game_machine/data_stores/couchbase.rb +18 -0
  114. data/lib/game_machine/data_stores/mapdb.rb +49 -0
  115. data/lib/game_machine/data_stores/memory.rb +35 -0
  116. data/lib/game_machine/data_stores/redis.rb +46 -0
  117. data/lib/game_machine/endpoints.rb +6 -0
  118. data/lib/game_machine/endpoints/mono_gateway.rb +87 -0
  119. data/lib/game_machine/endpoints/tcp.rb +51 -0
  120. data/lib/game_machine/endpoints/tcp_handler.rb +75 -0
  121. data/lib/game_machine/endpoints/udp.rb +88 -0
  122. data/lib/game_machine/endpoints/udp_incoming.rb +113 -0
  123. data/lib/game_machine/endpoints/udp_outgoing.rb +46 -0
  124. data/lib/game_machine/game_loader.rb +46 -0
  125. data/lib/game_machine/game_systems.rb +14 -0
  126. data/lib/game_machine/game_systems/agents/controller.rb +118 -0
  127. data/lib/game_machine/game_systems/chat.rb +256 -0
  128. data/lib/game_machine/game_systems/chat_manager.rb +108 -0
  129. data/lib/game_machine/game_systems/chat_topic.rb +36 -0
  130. data/lib/game_machine/game_systems/devnull.rb +13 -0
  131. data/lib/game_machine/game_systems/entity_loader.rb +12 -0
  132. data/lib/game_machine/game_systems/entity_tracking.rb +133 -0
  133. data/lib/game_machine/game_systems/local_echo.rb +16 -0
  134. data/lib/game_machine/game_systems/objectdb_proxy.rb +61 -0
  135. data/lib/game_machine/game_systems/private_chat.rb +20 -0
  136. data/lib/game_machine/game_systems/region_manager.rb +91 -0
  137. data/lib/game_machine/game_systems/region_service.rb +94 -0
  138. data/lib/game_machine/game_systems/region_settings.rb +13 -0
  139. data/lib/game_machine/game_systems/remote_echo.rb +14 -0
  140. data/lib/game_machine/game_systems/stress_test.rb +21 -0
  141. data/lib/game_machine/grid.rb +60 -0
  142. data/lib/game_machine/grid_replicator.rb +31 -0
  143. data/lib/game_machine/handlers/authentication.rb +55 -0
  144. data/lib/game_machine/handlers/game.rb +63 -0
  145. data/lib/game_machine/handlers/request.rb +80 -0
  146. data/lib/game_machine/hashring.rb +48 -0
  147. data/lib/game_machine/helpers/game_message.rb +159 -0
  148. data/lib/game_machine/helpers/state_machine.rb +29 -0
  149. data/lib/game_machine/java_lib.rb +51 -0
  150. data/lib/game_machine/logger.rb +39 -0
  151. data/lib/game_machine/message_buffer.rb +58 -0
  152. data/lib/game_machine/message_queue.rb +63 -0
  153. data/lib/game_machine/model.rb +125 -0
  154. data/lib/game_machine/models.rb +3 -0
  155. data/lib/game_machine/models/player_status_update.rb +8 -0
  156. data/lib/game_machine/models/region.rb +9 -0
  157. data/lib/game_machine/mono_server.rb +20 -0
  158. data/lib/game_machine/navigation.rb +4 -0
  159. data/lib/game_machine/navigation/detour.rb +20 -0
  160. data/lib/game_machine/navigation/detour_navmesh.rb +53 -0
  161. data/lib/game_machine/navigation/detour_path.rb +53 -0
  162. data/lib/game_machine/navigation/path.rb +31 -0
  163. data/lib/game_machine/object_db.rb +67 -0
  164. data/lib/game_machine/protobuf.rb +6 -0
  165. data/lib/game_machine/protobuf/game_messages.rb +24 -0
  166. data/lib/game_machine/protobuf/generate.rb +113 -0
  167. data/lib/game_machine/protobuf_extensions/entity_helper.rb +11 -0
  168. data/lib/game_machine/reloadable_monitor.rb +26 -0
  169. data/lib/game_machine/restart_watcher.rb +17 -0
  170. data/lib/game_machine/ruby_extensions/nilclass.rb +10 -0
  171. data/lib/game_machine/ruby_extensions/string.rb +17 -0
  172. data/lib/game_machine/scheduler.rb +23 -0
  173. data/lib/game_machine/securerandom.rb +6 -0
  174. data/lib/game_machine/settings.rb +11 -0
  175. data/lib/game_machine/system_monitor.rb +19 -0
  176. data/lib/game_machine/system_stats.rb +24 -0
  177. data/lib/game_machine/uniqueid.rb +23 -0
  178. data/lib/game_machine/vector.rb +95 -0
  179. data/lib/game_machine/version.rb +3 -0
  180. data/lib/game_machine/write_behind_cache.rb +164 -0
  181. data/mono/bin/csharp/common.xslt +109 -0
  182. data/mono/bin/csharp/csharp.xslt +628 -0
  183. data/mono/bin/csharp/descriptor.proto +533 -0
  184. data/mono/bin/csharp/protobuf-net.dll +0 -0
  185. data/mono/bin/csharp/protobuf-net.pdb +0 -0
  186. data/mono/bin/csharp/protobuf-net.xml +2879 -0
  187. data/mono/bin/csharp/protogen.exe.config +3 -0
  188. data/mono/bin/csharp/protogen.pdb +0 -0
  189. data/mono/bin/csharp/protogen_csharp.exe +0 -0
  190. data/mono/bin/csharp/vb.xslt +745 -0
  191. data/mono/bin/csharp/xml.xslt +26 -0
  192. data/mono/server/Makefile +6 -0
  193. data/mono/server/NLog.config +12 -0
  194. data/mono/server/NLog.dll +0 -0
  195. data/mono/server/actor.cs +37 -0
  196. data/mono/server/build.bat +3 -0
  197. data/mono/server/cscompmgd.dll +0 -0
  198. data/mono/server/iactor.cs +11 -0
  199. data/mono/server/message_router.cs +67 -0
  200. data/mono/server/message_util.cs +29 -0
  201. data/mono/server/messages.cs +1888 -0
  202. data/mono/server/protobuf-net.dll +0 -0
  203. data/mono/server/proxy_client.cs +73 -0
  204. data/mono/server/proxy_server.cs +30 -0
  205. data/mono/server/test_actor.cs +33 -0
  206. data/pathfinding/bin/premake4 +0 -0
  207. data/pathfinding/include/mesh_loader.h +28 -0
  208. data/pathfinding/include/pathfind.h +167 -0
  209. data/pathfinding/main.cpp +39 -0
  210. data/pathfinding/mesh_loader.cpp +108 -0
  211. data/pathfinding/pathfind.cpp +174 -0
  212. data/pathfinding/pathfinder.cs +66 -0
  213. data/pathfinding/premake4.lua +109 -0
  214. data/script/server.sh +109 -0
  215. data/script/watch.sh +11 -0
  216. data/spec/actor/actor_spec.rb +73 -0
  217. data/spec/actor/builder_spec.rb +56 -0
  218. data/spec/actor/ref_spec.rb +83 -0
  219. data/spec/application_spec.rb +7 -0
  220. data/spec/client_manager_spec.rb +171 -0
  221. data/spec/commands/chat_commands_spec.rb +38 -0
  222. data/spec/commands/datastore_commands_spec.rb +91 -0
  223. data/spec/commands/grid_commands_spec.rb +37 -0
  224. data/spec/commands/navigation_commands_spec.rb +51 -0
  225. data/spec/commands/player_commands_spec.rb +48 -0
  226. data/spec/commands_spec.rb +38 -0
  227. data/spec/data_stores/mapdb_spec.rb +46 -0
  228. data/spec/data_stores/redis_spec.rb +44 -0
  229. data/spec/game_systems/agents/controller_spec.rb +84 -0
  230. data/spec/game_systems/agents/test_agent.rb +10 -0
  231. data/spec/game_systems/agents/test_agent_config.rb +29 -0
  232. data/spec/game_systems/chat_manager_spec.rb +66 -0
  233. data/spec/game_systems/chat_spec.rb +187 -0
  234. data/spec/game_systems/entity_tracking_spec.rb +64 -0
  235. data/spec/game_systems/region_manager_spec.rb +138 -0
  236. data/spec/grid_spec.rb +37 -0
  237. data/spec/handlers/authentication_spec.rb +36 -0
  238. data/spec/handlers/game_spec.rb +49 -0
  239. data/spec/handlers/request_spec.rb +65 -0
  240. data/spec/hashring_spec.rb +59 -0
  241. data/spec/integration_helper.rb +120 -0
  242. data/spec/java_grid_spec.rb +89 -0
  243. data/spec/message_buffer_spec.rb +67 -0
  244. data/spec/message_expectations.rb +47 -0
  245. data/spec/message_queue_spec.rb +23 -0
  246. data/spec/misc_spec.rb +71 -0
  247. data/spec/model_spec.rb +103 -0
  248. data/spec/mono_spec.rb +36 -0
  249. data/spec/mono_test.rb +18 -0
  250. data/spec/navigation/detour_navmesh_spec.rb +34 -0
  251. data/spec/navigation/detour_path_spec.rb +25 -0
  252. data/spec/spec_helper.rb +40 -0
  253. data/spec/udp_server_spec.rb +10 -0
  254. data/spec/write_behind_cache_spec.rb +109 -0
  255. data/web/app.rb +131 -0
  256. data/web/config/trinidad.yml +4 -0
  257. data/web/controllers/auth_controller.rb +19 -0
  258. data/web/controllers/base_controller.rb +16 -0
  259. data/web/controllers/index_controller.rb +7 -0
  260. data/web/controllers/log_controller.rb +47 -0
  261. data/web/controllers/messages_controller.rb +59 -0
  262. data/web/controllers/player_register_controller.rb +15 -0
  263. data/web/log/development.log +1339 -0
  264. data/web/tmp/restart.txt +0 -0
  265. data/web/views/game_messages.haml +45 -0
  266. data/web/views/index.haml +6 -0
  267. data/web/views/layout.haml +41 -0
  268. data/web/views/logs.haml +32 -0
  269. data/web/views/player_register.haml +22 -0
  270. data/web/views/player_registered.haml +2 -0
  271. data/web/views/register_layout.haml +22 -0
  272. data/web/views/restart.haml +35 -0
  273. metadata +576 -0
@@ -0,0 +1,9 @@
1
+ ---
2
+ development:
3
+ regions:
4
+ zone1: Example::ZoneManager
5
+ zone2: Example::ZoneManager
6
+ test:
7
+ regions:
8
+ zone1: GameMachine::GameSystems::Zone1Manager
9
+ zone2: GameMachine::GameSystems::Zone2Manager
@@ -0,0 +1,36 @@
1
+
2
+ standalone {
3
+ default-pinned-dispatcher {
4
+ executor = thread-pool-executor
5
+ type = PinnedDispatcher
6
+ thread-pool-executor.keep-alive-time = 315360000s
7
+ # note that disabling core timeout altogether doesn't work
8
+ # until ticket 2856 is fixed
9
+ thread-pool-executor.allow-core-timeout = off
10
+ }
11
+
12
+ akka {
13
+ actor.debug.unhandled = "on"
14
+ jvm-exit-on-fatal-error=false
15
+ loglevel = "WARNING"
16
+
17
+ actor {
18
+ serializers {
19
+ java = "akka.serialization.JavaSerializer"
20
+ bytes = "akka.serialization.ByteArraySerializer"
21
+ myown = "com.game_machine.core.EntitySerializer"
22
+ }
23
+
24
+ serialization-bindings {
25
+ "[B" = bytes
26
+ "java.io.Serializable" = java
27
+ "com.dyuproject.protostuff.Message" = myown
28
+ "GameMachine.Messages.ClientMessage" = myown
29
+ "GameMachine.Messages.Entity" = myown
30
+ "GameMachine.Messages.ObjectdbGet" = myown
31
+ "GameMachine.Messages.ObjectdbPut" = myown
32
+ "GameMachine.Messages.ObjectdbUpdate" = myown
33
+ }
34
+ }
35
+ }
36
+ }
data/db/do_not_delete ADDED
File without changes
@@ -0,0 +1,38 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'game_machine/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "game_machine"
8
+ gem.version = GameMachine::VERSION
9
+ gem.authors = ["Chris Ochs"]
10
+ gem.email = ["chris@ochsnet.com"]
11
+ gem.homepage = "https://github.com/gamemachine/gamemachine"
12
+ gem.summary = %q{Game Machine}
13
+ gem.description = %q{game server}
14
+
15
+ gem.files = `git ls-files`.split($/).reject { |f| f =~ /^(games\/physics_experiments)/ }
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features|integration_tests)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_dependency 'i18n'
21
+ gem.add_dependency 'rjack-logback'
22
+ gem.add_dependency 'settingslogic'
23
+ gem.add_dependency 'consistent-hashing'
24
+ gem.add_dependency 'json'
25
+ gem.add_dependency 'ffi'
26
+ gem.add_dependency 'sinatra'
27
+ gem.add_dependency 'sinatra-contrib'
28
+ gem.add_dependency 'haml'
29
+ gem.add_dependency 'webrick'
30
+
31
+ gem.add_development_dependency 'rake'
32
+ gem.add_development_dependency 'rspec'
33
+ gem.add_development_dependency 'rspec-mocks'
34
+ gem.add_development_dependency 'rspec-expectations'
35
+ gem.add_development_dependency 'descriptive_statistics'
36
+
37
+
38
+ end
@@ -0,0 +1,6 @@
1
+
2
+ require_relative 'lib/game'
3
+
4
+ game_root = File.dirname(__FILE__)
5
+ Example::Game.new(game_root).start
6
+
@@ -0,0 +1,13 @@
1
+ ---
2
+ zone1:
3
+ male: 200
4
+ viking: 200
5
+ golem: 200
6
+ worm: 200
7
+ zone2:
8
+ male: 100
9
+ viking: 100
10
+ golem: 100
11
+ worm: 100
12
+
13
+
@@ -0,0 +1,176 @@
1
+ require 'benchmark'
2
+ module Example
3
+ class AggressiveNpc < Npc
4
+ include GameMachine::Commands
5
+ include Models
6
+
7
+ attr_reader :target_id
8
+
9
+ def post_init
10
+ @target_id = nil
11
+ @check_home_counter = 0
12
+ @check_home_interval = 5
13
+ @acquire_target_counter = 0
14
+ @acquire_target_interval = 5
15
+ @agro_radius = 15
16
+ @leash_radius = 30
17
+
18
+ movement.speed_scale = 4
19
+ @last_attack = Time.now.to_i
20
+ @attack_interval = 2
21
+ end
22
+
23
+ def log(msg)
24
+ GameMachine.logger.info "#{id} #{msg}"
25
+ end
26
+
27
+ def set_spawn_point
28
+ position.x = rand(1000) + 1
29
+ position.y = rand(1000) + 1
30
+ #position.z = 40
31
+ end
32
+
33
+ def has_target?
34
+ target_id.nil? ? false : true
35
+ end
36
+
37
+ def update_target
38
+ if target = players.fetch(target_id,nil)
39
+ movement.update_target(target[:vector])
40
+ true
41
+ else
42
+ @target_id = nil
43
+ false
44
+ end
45
+ end
46
+
47
+ def choose_target
48
+ if player = sorted_players.first
49
+ if position.distance(player[:vector]) <= @agro_radius
50
+ movement.set_target(player[:vector])
51
+ @target_id = player[:id]
52
+ #log("target chosen #{@target_id}")
53
+ end
54
+ end
55
+ end
56
+
57
+ def leash?
58
+ if @check_home_counter >= @check_home_interval
59
+ @check_home_counter = 0
60
+ if movement.position.distance(home) > @leash_radius
61
+ return true
62
+ elsif movement.current_target &&
63
+ (movement.position.distance(movement.current_target) > @leash_radius)
64
+ return true
65
+ end
66
+ end
67
+ false
68
+ end
69
+
70
+ def go_home!
71
+ log("going home")
72
+ @target_id = 'home'
73
+ movement.set_target(@home)
74
+ end
75
+
76
+ def going_home?
77
+ @target_id == 'home'
78
+ end
79
+
80
+ def reached_home?
81
+ going_home? && movement.reached_target
82
+ end
83
+
84
+ def reset_target
85
+ movement.drop_target
86
+ @target_id = nil
87
+ end
88
+
89
+ def attack_target
90
+ if Time.now.to_i - @last_attack < @attack_interval
91
+ return
92
+ end
93
+
94
+ attack = Attack.new(
95
+ :target => target_id,
96
+ :attacker => id,
97
+ :combat_ability => 'bite'
98
+ )
99
+ CombatController.find.tell(attack)
100
+ #log("attacked target #{target_id}")
101
+ @last_attack = Time.now.to_i
102
+ end
103
+
104
+ def update
105
+ return if dead
106
+ if going_home?
107
+ if reached_home?
108
+ log("home reached")
109
+ reset_target
110
+ else
111
+ movement.update_target(home)
112
+ movement.update
113
+ end
114
+ return
115
+ end
116
+
117
+ if leash?
118
+ log("leashed!")
119
+ reset_target
120
+ go_home!
121
+ return
122
+ end
123
+
124
+ # if we have a target, acquire their location every tick, otherwise only
125
+ # check every acquire_target_interval updates
126
+ if has_target? || @acquire_target_counter >= @acquire_target_interval
127
+ movement.updates_between_move = 1
128
+ check_players
129
+ if has_players?
130
+ unless has_target?
131
+ choose_target
132
+ end
133
+ else
134
+ # No players but we have a player target? Player must have logged out
135
+ # or otherwise disappeared, so we need to reset
136
+ if @target_id && @target_id != 'home'
137
+ GameMachine.logger.info "#{id} No players but has target!?? (target: #{@target_id})"
138
+ reset_target
139
+ go_home!
140
+ elsif movement.position.distance(home) > 0
141
+ GameMachine.logger.info "#{id} No players but is #{position.distance(home)} from home (target: #{@target_id})"
142
+ reset_target
143
+ go_home!
144
+ end
145
+ end
146
+
147
+ @acquire_target_counter = 0
148
+ else
149
+ movement.updates_between_move = 20
150
+ end
151
+
152
+ if has_target?
153
+ if movement.distance_to_target <= 3
154
+ attack_target
155
+ end
156
+
157
+ if movement.reached_target
158
+ reset_target
159
+ else
160
+ if update_target
161
+ movement.update
162
+ else
163
+ # Target out of range for some reason (logged out, etc..)
164
+ GameMachine.logger.info "#{id} lost target! #{@target_id}"
165
+ reset_target
166
+ go_home!
167
+ end
168
+ end
169
+ end
170
+
171
+ @acquire_target_counter += 1
172
+ @check_home_counter += 1
173
+ end
174
+
175
+ end
176
+ end
@@ -0,0 +1,69 @@
1
+
2
+ # This class is set in the configuration.
3
+
4
+ # This is a simple implementation that works together with the built in
5
+ # user registration and login via http. User data is stored in the object database.
6
+
7
+ # The minimum necessary to implement is the authtoken_for method. That method can
8
+ # block as it is only called once when the client first connects and is cached
9
+ # internally after that. So you could make an external http call for example.
10
+ require 'digest/md5'
11
+ module Example
12
+ class AuthenticationHandler
13
+ include Models
14
+
15
+ def initialize
16
+ @sessions = {}
17
+ end
18
+
19
+ # Returns true is authorized, false if not
20
+ def authorize(username,password)
21
+ GameMachine.logger.info "authorize: #{username} #{password}"
22
+ if user = User.find(username,5000)
23
+ GameMachine.logger.info "user: #{user.id} #{user.password}"
24
+ if password == user.password
25
+ @sessions[username] = authtoken(username,password)
26
+ user.authtoken = @sessions[username]
27
+ user.save
28
+ return @sessions[username]
29
+ else
30
+ GameMachine.logger.info "user: #{user.id} password does not match"
31
+ false
32
+ end
33
+ else
34
+ GameMachine.logger.info "user: #{username} not found"
35
+ false
36
+ end
37
+ false
38
+ end
39
+
40
+ # Returns a session token for a logged in user. This must be a string and
41
+ # should not be too long, as it gets sent with every message.
42
+ def authtoken_for(username)
43
+ if authtoken = @sessions.fetch(username,nil)
44
+ return authtoken
45
+
46
+ # user authenticated on different server, we have to look up their authtoken
47
+ # and save it in the local sessions hash
48
+ elsif user = User.find(username)
49
+ if user.authtoken
50
+ @sessions[username] = authtoken
51
+ return user.authtoken
52
+ else
53
+ GameMachine.logger.info "Authoken for #{username} is nil"
54
+ nil
55
+ end
56
+ else
57
+ GameMachine.logger.info "User #{username} not found"
58
+ nil
59
+ end
60
+ end
61
+
62
+ private
63
+
64
+ def authtoken(username,password)
65
+ Digest::MD5.hexdigest("#{username}#{password}#{rand(10000)}")
66
+ end
67
+ end
68
+ end
69
+
@@ -0,0 +1,61 @@
1
+
2
+ # Shows how to use the messaging/chat system programmatically from the server.
3
+ # Also shows how to use the schedular to send ourselves a recurring message that
4
+ # we can use to trigger recurring actions.
5
+
6
+ module Example
7
+ class Chatbot < GameMachine::Actor::Base
8
+ include GameMachine
9
+ include GameMachine::Commands
10
+
11
+ attr_reader :topic, :chatbot_id
12
+ def post_init(*args)
13
+ @topic = args.first
14
+ @chatbot_id = 'overlord'
15
+
16
+ # On the server side we use register, which takes our chat id
17
+ # and the name of this actor.
18
+ commands.chat.register(chatbot_id,'Example::Chatbot')
19
+
20
+ # Then we send a regular join request
21
+ commands.chat.join('global',chatbot_id)
22
+
23
+ # Send ourselves a 'doit' message every few seconds
24
+ schedule_message('doit',50,:seconds)
25
+ end
26
+
27
+ def message_queue
28
+ MessageQueue.find
29
+ end
30
+
31
+ def on_receive(message)
32
+
33
+ # This is our scheduled message
34
+ if message.is_a?(String)
35
+ if message == 'doit'
36
+ commands.chat.send_group_message('global','Would you like to play a game?',chatbot_id)
37
+ end
38
+
39
+ # Status update we get from chat system, we don't care..
40
+ elsif message.has_chat_channels
41
+
42
+ # Must be a chat message
43
+ elsif message.has_chat_message
44
+
45
+ # ignore our own messages
46
+ sender_id = message.chat_message.sender_id
47
+ unless sender_id == chatbot_id
48
+ text = message.chat_message.message
49
+ GameMachine.logger.info "Chatbot received text #{text}"
50
+
51
+ # Respond with a private message
52
+ if text.match(/shut up/)
53
+ reply = 'Same to you!'
54
+ commands.chat.send_private_message(reply,sender_id)
55
+ end
56
+
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,145 @@
1
+
2
+ # Handles all the combat. Npc controllers and clients send Attack messages
3
+ # to this actor which calculates damage, persists any changes, and sends out
4
+ # combat updates to all players in the area as well as to any npc's that were
5
+ # hit.
6
+
7
+ # If the attack combat_ability is 'aoe', we use the aoe grid which is a
8
+ # secondary grid with a smaller radius. Currently we use the attacker as the
9
+ # point to query on, but it could be easily extended to use any point, so you
10
+ # could have aoe damage with a center anywhere you want it to be.
11
+
12
+
13
+ module Example
14
+ class CombatController < GameMachine::Actor::Base
15
+ include GameMachine::Commands
16
+ include Models
17
+
18
+ attr_reader :aoe_grid
19
+ def post_init(*args)
20
+ @aoe_grid = GameMachine::Grid.find_or_create('aoe')
21
+ end
22
+
23
+ def hit?
24
+ return true
25
+ chance = rand(0..10)
26
+ chance >= 5 ? true : false
27
+ end
28
+
29
+ def damage(entity_type)
30
+ if entity_type == 'player'
31
+ rand(1..8)
32
+ else
33
+ rand(20..120)
34
+ end
35
+ end
36
+
37
+ def on_receive(message)
38
+ if message.is_a?(Attack)
39
+ attack = message
40
+ attacker_vitals = Vitals.find(attack.attacker)
41
+
42
+ if attacker_vitals.entity_type == 'player'
43
+ player_id = attack.attacker
44
+ else
45
+ player_id = attack.target
46
+ end
47
+
48
+ # gets our targets. Does range query if aoe
49
+ targets = find_targets(attack,attacker_vitals)
50
+ #GameMachine.logger.info "targets #{targets.map{|target| target.id}.join(',')}"
51
+
52
+ # calculates/applies damage and returns a combat update for each hit
53
+ combat_updates = attack_targets(targets,attack)
54
+
55
+ # Get all players within our larger radius so we can send them the updates
56
+ neighbors = commands.grid.get_neighbors_for(attack.attacker)
57
+
58
+ combat_updates.each do |combat_update|
59
+ GameMachine.logger.info "#{combat_update.attacker} hit #{combat_update.target} for #{combat_update.damage} #{attack.combat_ability} damage"
60
+ commands.player.send_message(combat_update,player_id)
61
+
62
+ if neighbors
63
+ neighbors.each do |neighbor|
64
+ next if neighbor.id == player_id
65
+ commands.player.send_message(combat_update,neighbor.id)
66
+ end
67
+ end
68
+ end
69
+
70
+ end
71
+ end
72
+
73
+ def attack_targets(targets,attack)
74
+ combat_updates = []
75
+
76
+ targets.each do |target_vitals|
77
+
78
+ if target_vitals.entity_type.blank?
79
+ target_vitals.entity_type = 'npc'
80
+ GameMachine.logger.info "#{target_vitals.id} has no entity type, fixing"
81
+ end
82
+ if hit?
83
+ dmg = damage(target_vitals.entity_type)
84
+ next if dmg == 0
85
+ if target_vitals.health - dmg <= 0
86
+ target_vitals.health = 0
87
+ else
88
+ target_vitals.health -= dmg
89
+ end
90
+ target_vitals.save
91
+ #GameMachine.logger.info "#{target_vitals.id}(#{target_vitals.entity_type}) has #{target_vitals.health}"
92
+
93
+ combat_update = CombatUpdate.new(
94
+ :target => target_vitals.id,
95
+ :attacker => attack.attacker,
96
+ :damage => dmg,
97
+ :target_health => target_vitals.health
98
+ )
99
+ combat_updates << combat_update
100
+
101
+ if target_vitals.entity_type == 'npc'
102
+ if npc_group_actor = Game.npcs.fetch(target_vitals.id,nil)
103
+ GameMachine::Actor::Base.find(npc_group_actor).tell(combat_update)
104
+ else
105
+ GameMachine.logger.info "group actor for #{target_vitals.id} not found"
106
+ end
107
+ end
108
+
109
+ end
110
+ end
111
+ combat_updates
112
+ end
113
+
114
+ # If it's an aoe attack, use our aoe grid to find targets in range, otherwise
115
+ # use the specified target
116
+ def find_targets(attack,attacker)
117
+ targets = []
118
+
119
+ # npc's only hit players, players hit everything
120
+ if attacker.entity_type == 'npc'
121
+ search_type = 'player'
122
+ else
123
+ search_type = nil
124
+ end
125
+
126
+ if attack.combat_ability == 'aoe'
127
+ if grid_value = @aoe_grid.get(attack.attacker)
128
+ @aoe_grid.neighbors(grid_value.x,grid_value.y,search_type).each do |grid_value|
129
+ next if grid_value.id == attack.attacker
130
+ if target_vitals = Vitals.find(grid_value.id)
131
+ targets << target_vitals
132
+ end
133
+ end
134
+ end
135
+ else
136
+ if target_vitals = Vitals.find(attack.target)
137
+ targets << target_vitals
138
+ end
139
+ end
140
+ targets
141
+ end
142
+
143
+
144
+ end
145
+ end