game_machine 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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