game_machine 0.0.11 → 1.0.2

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 (274) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +12 -1
  3. data/Gemfile.lock +32 -47
  4. data/Rakefile +0 -27
  5. data/bin/bundle_run.sh +1 -0
  6. data/bin/game_machine +29 -27
  7. data/config/cluster.conf +6 -5
  8. data/config/default.conf +164 -0
  9. data/config/game_machine.sql +33 -0
  10. data/config/game_messages.proto +87 -25
  11. data/config/gamecloud.conf +140 -0
  12. data/config/messages.proto +46 -53
  13. data/config/test.conf +149 -0
  14. data/game_machine.gemspec +10 -5
  15. data/games/boot.rb +3 -0
  16. data/games/example/data/game_data.yml +4 -4
  17. data/games/example/lib/aggressive_npc.rb +1 -1
  18. data/games/example/lib/game.rb +1 -2
  19. data/games/example/lib/player_register.rb +1 -1
  20. data/games/routes.rb +9 -0
  21. data/games/tutorial/boot.rb +12 -0
  22. data/games/tutorial/item_manager.rb +256 -0
  23. data/games/tutorial/object_store.rb +55 -0
  24. data/games/tutorial/seed.rb +52 -0
  25. data/games/tutorial/sql_store.rb +30 -0
  26. data/java/project/build.gradle +134 -0
  27. data/java/project/component.erb +719 -0
  28. data/java/{gradle.properties → project/gradle.properties} +1 -1
  29. data/java/project/gradle/wrapper/gradle-wrapper.jar +0 -0
  30. data/java/{gradle → project/gradle}/wrapper/gradle-wrapper.properties +2 -2
  31. data/java/{gradlew → project/gradlew} +0 -0
  32. data/java/{gradlew.bat → project/gradlew.bat} +0 -0
  33. data/java/project/local_lib/AdminUi.jar +0 -0
  34. data/java/{local_lib/protostuff-compiler-1.0.7-jarjar.jar → project/local_lib/protostuff-compiler-1.0.8-jarjar.jar} +0 -0
  35. data/java/project/local_lib/sigar/libsigar-amd64-freebsd-6.so +0 -0
  36. data/java/project/local_lib/sigar/libsigar-amd64-linux.so +0 -0
  37. data/java/project/local_lib/sigar/libsigar-amd64-solaris.so +0 -0
  38. data/java/project/local_lib/sigar/libsigar-ia64-hpux-11.sl +0 -0
  39. data/java/project/local_lib/sigar/libsigar-ia64-linux.so +0 -0
  40. data/java/project/local_lib/sigar/libsigar-pa-hpux-11.sl +0 -0
  41. data/java/project/local_lib/sigar/libsigar-ppc-aix-5.so +0 -0
  42. data/java/project/local_lib/sigar/libsigar-ppc-linux.so +0 -0
  43. data/java/project/local_lib/sigar/libsigar-ppc64-aix-5.so +0 -0
  44. data/java/project/local_lib/sigar/libsigar-ppc64-linux.so +0 -0
  45. data/java/project/local_lib/sigar/libsigar-s390x-linux.so +0 -0
  46. data/java/project/local_lib/sigar/libsigar-sparc-solaris.so +0 -0
  47. data/java/project/local_lib/sigar/libsigar-sparc64-solaris.so +0 -0
  48. data/java/project/local_lib/sigar/libsigar-universal-macosx.dylib +0 -0
  49. data/java/project/local_lib/sigar/libsigar-universal64-macosx.dylib +0 -0
  50. data/java/project/local_lib/sigar/libsigar-x86-freebsd-5.so +0 -0
  51. data/java/project/local_lib/sigar/libsigar-x86-freebsd-6.so +0 -0
  52. data/java/project/local_lib/sigar/libsigar-x86-linux.so +0 -0
  53. data/java/project/local_lib/sigar/libsigar-x86-solaris.so +0 -0
  54. data/java/project/local_lib/sigar/sigar-amd64-winnt.dll +0 -0
  55. data/java/project/local_lib/sigar/sigar-x86-winnt.dll +0 -0
  56. data/java/project/local_lib/sigar/sigar-x86-winnt.lib +0 -0
  57. data/java/project/model.erb +99 -0
  58. data/java/{settings.gradle → project/settings.gradle} +0 -0
  59. data/java/project/src/main/java/com/game_machine/authentication/DefaultAuthenticator.java +28 -0
  60. data/java/project/src/main/java/com/game_machine/authentication/PlayerAuthenticator.java +6 -0
  61. data/java/project/src/main/java/com/game_machine/authentication/PublicAuthenticator.java +20 -0
  62. data/java/{src → project/src}/main/java/com/game_machine/core/ActorFactory.java +0 -0
  63. data/java/{src → project/src}/main/java/com/game_machine/core/ActorUtil.java +13 -0
  64. data/java/project/src/main/java/com/game_machine/core/AuthorizedPlayers.java +23 -0
  65. data/java/project/src/main/java/com/game_machine/core/ClientMessageDecoder.java +36 -0
  66. data/java/project/src/main/java/com/game_machine/core/ClientMessageEncoder.java +19 -0
  67. data/java/project/src/main/java/com/game_machine/core/CloudClient.java +298 -0
  68. data/java/{src → project/src}/main/java/com/game_machine/core/CommandProxy.java +0 -0
  69. data/java/project/src/main/java/com/game_machine/core/Commands.java +20 -0
  70. data/java/project/src/main/java/com/game_machine/core/DatastoreCommands.java +43 -0
  71. data/java/project/src/main/java/com/game_machine/core/DbConnectionPool.java +72 -0
  72. data/java/project/src/main/java/com/game_machine/core/DefaultMovementVerifier.java +56 -0
  73. data/java/{src → project/src}/main/java/com/game_machine/core/EntitySerializer.java +0 -0
  74. data/java/project/src/main/java/com/game_machine/core/EntityTracking.java +119 -0
  75. data/java/{src → project/src}/main/java/com/game_machine/core/EventStreamHandler.java +1 -1
  76. data/java/project/src/main/java/com/game_machine/core/GameActor.java +73 -0
  77. data/java/project/src/main/java/com/game_machine/core/GameMachineLoader.java +43 -0
  78. data/java/project/src/main/java/com/game_machine/core/GameMessageActor.java +44 -0
  79. data/java/project/src/main/java/com/game_machine/core/Grid.java +255 -0
  80. data/java/{src → project/src}/main/java/com/game_machine/core/GridValue.java +0 -0
  81. data/java/project/src/main/java/com/game_machine/core/Hashring.java +66 -0
  82. data/java/{src → project/src}/main/java/com/game_machine/core/IActorFactory.java +0 -0
  83. data/java/project/src/main/java/com/game_machine/core/LocalLinkedBuffer.java +20 -0
  84. data/java/project/src/main/java/com/game_machine/core/MessageGateway.java +120 -0
  85. data/java/project/src/main/java/com/game_machine/core/MessagePersister.java +26 -0
  86. data/java/project/src/main/java/com/game_machine/core/MonoProxy.java +39 -0
  87. data/java/project/src/main/java/com/game_machine/core/MovementVerifier.java +7 -0
  88. data/java/{src → project/src}/main/java/com/game_machine/core/NetMessage.java +10 -6
  89. data/java/project/src/main/java/com/game_machine/core/PersistentMessage.java +9 -0
  90. data/java/project/src/main/java/com/game_machine/core/PlayerCommands.java +31 -0
  91. data/java/project/src/main/java/com/game_machine/core/TcpServer.java +100 -0
  92. data/java/project/src/main/java/com/game_machine/core/TcpServerHandler.java +54 -0
  93. data/java/project/src/main/java/com/game_machine/core/TcpServerInitializer.java +32 -0
  94. data/java/project/src/main/java/com/game_machine/core/UdpClient.java +86 -0
  95. data/java/{src → project/src}/main/java/com/game_machine/core/UdpServer.java +18 -27
  96. data/java/{src → project/src}/main/java/com/game_machine/core/UdpServerHandler.java +23 -26
  97. data/java/project/src/main/java/com/game_machine/core/Vector3.java +159 -0
  98. data/java/project/src/main/java/com/game_machine/orm/models/PlayerItem.java +118 -0
  99. data/java/project/src/main/java/com/game_machine/orm/models/TestObject.java +110 -0
  100. data/java/project/src/main/java/com/game_machine/tutorial/LootGenerator.java +26 -0
  101. data/java/{src → project/src}/main/resources/game_machine.java.stg +3 -1
  102. data/java/project/src/main/resources/logback.properties +13 -0
  103. data/java/project/src/main/resources/logback.xml +76 -0
  104. data/java/{src → project/src}/main/resources/protostuff.properties +0 -0
  105. data/java/src/main/java/game/MyGameActor.java +26 -0
  106. data/lib/game_machine.rb +17 -16
  107. data/lib/game_machine/actor.rb +1 -1
  108. data/lib/game_machine/actor/base.rb +8 -31
  109. data/lib/game_machine/actor/builder.rb +5 -6
  110. data/lib/game_machine/actor/game_actor.rb +55 -0
  111. data/lib/game_machine/actor/reloadable.rb +6 -1
  112. data/lib/game_machine/akka.rb +26 -32
  113. data/lib/game_machine/app_config.rb +39 -26
  114. data/lib/game_machine/application.rb +56 -62
  115. data/lib/game_machine/client_manager.rb +14 -8
  116. data/lib/game_machine/cloud_updater.rb +51 -0
  117. data/lib/game_machine/cluster_monitor.rb +3 -3
  118. data/lib/game_machine/commands.rb +1 -1
  119. data/lib/game_machine/commands/misc_commands.rb +4 -8
  120. data/lib/game_machine/commands/player_commands.rb +8 -0
  121. data/lib/game_machine/console.rb +1 -0
  122. data/lib/game_machine/console/build.rb +57 -24
  123. data/lib/game_machine/console/bundle.rb +95 -0
  124. data/lib/game_machine/console/deploy.rb +30 -0
  125. data/lib/game_machine/console/install.rb +70 -36
  126. data/lib/game_machine/console/server.rb +2 -69
  127. data/lib/game_machine/data_store.rb +111 -15
  128. data/lib/game_machine/data_stores/couchbase.rb +8 -3
  129. data/lib/game_machine/data_stores/gamecloud.rb +93 -0
  130. data/lib/game_machine/data_stores/jdbc.rb +98 -0
  131. data/lib/game_machine/default_handlers.rb +2 -0
  132. data/lib/game_machine/default_handlers/team_handler.rb +51 -0
  133. data/lib/game_machine/default_handlers/zone_manager.rb +30 -0
  134. data/lib/game_machine/endpoints.rb +0 -4
  135. data/lib/game_machine/endpoints/udp_incoming.rb +13 -5
  136. data/lib/game_machine/endpoints/udp_outgoing.rb +15 -9
  137. data/lib/game_machine/game_systems.rb +0 -2
  138. data/lib/game_machine/game_systems/agents/controller.rb +2 -2
  139. data/lib/game_machine/game_systems/entity_tracking.rb +0 -3
  140. data/lib/game_machine/game_systems/region_manager.rb +3 -2
  141. data/lib/game_machine/game_systems/region_service.rb +2 -2
  142. data/lib/game_machine/game_systems/remote_echo.rb +10 -0
  143. data/lib/game_machine/game_systems/team_manager.rb +2 -11
  144. data/lib/game_machine/grid.rb +5 -18
  145. data/lib/game_machine/handlers/authentication.rb +1 -9
  146. data/lib/game_machine/handlers/game.rb +27 -2
  147. data/lib/game_machine/handlers/player_authentication.rb +87 -0
  148. data/lib/game_machine/handlers/request.rb +9 -11
  149. data/lib/game_machine/hocon_config.rb +81 -0
  150. data/lib/game_machine/java_lib.rb +14 -1
  151. data/lib/game_machine/logger.rb +10 -23
  152. data/lib/game_machine/models.rb +1 -0
  153. data/lib/game_machine/mono_server.rb +6 -1
  154. data/lib/game_machine/object_db.rb +12 -6
  155. data/lib/game_machine/protobuf.rb +1 -1
  156. data/lib/game_machine/protobuf/game_messages.rb +13 -3
  157. data/lib/game_machine/protobuf/generate.rb +107 -5
  158. data/lib/game_machine/restart_watcher.rb +1 -1
  159. data/lib/game_machine/routes.rb +23 -0
  160. data/lib/game_machine/scheduler.rb +1 -1
  161. data/lib/game_machine/securerandom.rb +2 -0
  162. data/lib/game_machine/system_stats.rb +28 -7
  163. data/lib/game_machine/version.rb +1 -1
  164. data/lib/game_machine/wavefront_ext.rb +47 -0
  165. data/lib/game_machine/write_behind_cache.rb +24 -9
  166. data/mono/server/Makefile +1 -1
  167. data/mono/server/Newtonsoft.Json.dll +0 -0
  168. data/mono/server/build.bat +1 -1
  169. data/mono/server/callable.cs +9 -0
  170. data/mono/server/echo.cs +17 -0
  171. data/mono/server/message_router.cs +16 -23
  172. data/mono/server/messages.cs +1792 -417
  173. data/mono/server/protobuf-net.dll +0 -0
  174. data/mono/server/server.cs +120 -0
  175. data/mono/server/server.exe +0 -0
  176. data/pathfinding/astar.cpp +149 -0
  177. data/pathfinding/build.sh +6 -0
  178. data/pathfinding/build.txt +16 -0
  179. data/pathfinding/crowd.cpp +194 -0
  180. data/pathfinding/include/astar.h +49 -0
  181. data/pathfinding/include/common.h +5 -0
  182. data/pathfinding/include/crowd.h +43 -0
  183. data/pathfinding/include/micropather.h +511 -0
  184. data/pathfinding/include/navmesh.h +114 -0
  185. data/pathfinding/include/pathfinder.h +24 -0
  186. data/pathfinding/main.cpp +108 -17
  187. data/pathfinding/micropather.cpp +1062 -0
  188. data/pathfinding/navmesh.cpp +408 -0
  189. data/pathfinding/overrides/DetourCrowd.cpp +1446 -0
  190. data/pathfinding/overrides/DetourNavMeshQuery.cpp +3551 -0
  191. data/pathfinding/overrides/DetourNavMeshQuery.h +538 -0
  192. data/pathfinding/pathfinder.cpp +117 -0
  193. data/pathfinding/{bin → premake}/premake4 +0 -0
  194. data/pathfinding/premake/premake4.exe +0 -0
  195. data/pathfinding/premake4.lua +12 -3
  196. data/spec/actor/actor_spec.rb +0 -7
  197. data/spec/client_manager_spec.rb +1 -1
  198. data/spec/couchproxy_spec.rb +38 -0
  199. data/spec/entity_persistence_spec.rb +129 -0
  200. data/spec/game_systems/team_manager_spec.rb +2 -2
  201. data/spec/hashring_spec.rb +17 -39
  202. data/spec/java_grid_spec.rb +0 -2
  203. data/spec/misc_spec.rb +111 -0
  204. data/spec/mono_spec.rb +50 -3
  205. data/spec/reliable_message_spec.rb +38 -0
  206. data/spec/spec_helper.rb +4 -4
  207. data/spec/spec_helper_minimal.rb +10 -0
  208. data/web/app.rb +108 -86
  209. data/web/config/trinidad.yml +1 -0
  210. data/web/views/add_player.erb +25 -0
  211. data/web/views/index.erb +0 -0
  212. data/web/views/layout.erb +48 -0
  213. data/web/views/login.erb +25 -0
  214. data/web/views/players.erb +24 -0
  215. metadata +209 -94
  216. data/config/config.example.yml +0 -100
  217. data/config/regions.example.yml +0 -9
  218. data/games/example/lib/authentication_handler.rb +0 -69
  219. data/games/models.rb +0 -3
  220. data/games/models/clan_member.rb +0 -8
  221. data/games/models/clan_profile.rb +0 -9
  222. data/games/models/player.rb +0 -7
  223. data/games/plugins.rb +0 -1
  224. data/games/plugins/team_handler.rb +0 -49
  225. data/games/preload.rb +0 -13
  226. data/java/.gitignore +0 -1
  227. data/java/build.gradle +0 -95
  228. data/java/component.erb +0 -396
  229. data/java/gradle/wrapper/gradle-wrapper.jar +0 -0
  230. data/java/src/main/java/com/game_machine/core/GameMachineLoader.java +0 -25
  231. data/java/src/main/java/com/game_machine/core/Grid.java +0 -195
  232. data/java/src/main/resources/logback.xml +0 -14
  233. data/java/src/main/resources/logging.properties +0 -3
  234. data/lib/game_machine/actor/mono_actor.rb +0 -89
  235. data/lib/game_machine/auth_handlers/base.rb +0 -21
  236. data/lib/game_machine/auth_handlers/public.rb +0 -34
  237. data/lib/game_machine/endpoints/mono_gateway.rb +0 -87
  238. data/lib/game_machine/endpoints/tcp.rb +0 -51
  239. data/lib/game_machine/endpoints/tcp_handler.rb +0 -75
  240. data/lib/game_machine/endpoints/udp.rb +0 -88
  241. data/lib/game_machine/game_loader.rb +0 -46
  242. data/lib/game_machine/game_systems/region_settings.rb +0 -13
  243. data/lib/game_machine/hashring.rb +0 -48
  244. data/lib/game_machine/settings.rb +0 -11
  245. data/mono/server/actor.cs +0 -37
  246. data/mono/server/iactor.cs +0 -11
  247. data/mono/server/message_util.cs +0 -29
  248. data/mono/server/proxy_client.cs +0 -73
  249. data/mono/server/proxy_server.cs +0 -30
  250. data/mono/server/test_actor.cs +0 -33
  251. data/pathfinding/include/pathfind.h +0 -167
  252. data/pathfinding/pathfind.cpp +0 -174
  253. data/pathfinding/pathfinder.cs +0 -66
  254. data/script/server.sh +0 -109
  255. data/script/watch.sh +0 -11
  256. data/spec/commands/navigation_commands_spec.rb +0 -51
  257. data/spec/game_systems/entity_tracking_spec.rb +0 -64
  258. data/spec/navigation/detour_navmesh_spec.rb +0 -34
  259. data/spec/navigation/detour_path_spec.rb +0 -25
  260. data/spec/udp_server_spec.rb +0 -10
  261. data/web/controllers/auth_controller.rb +0 -19
  262. data/web/controllers/base_controller.rb +0 -16
  263. data/web/controllers/index_controller.rb +0 -7
  264. data/web/controllers/log_controller.rb +0 -47
  265. data/web/controllers/messages_controller.rb +0 -59
  266. data/web/controllers/player_register_controller.rb +0 -15
  267. data/web/views/game_messages.haml +0 -45
  268. data/web/views/index.haml +0 -6
  269. data/web/views/layout.haml +0 -41
  270. data/web/views/logs.haml +0 -32
  271. data/web/views/player_register.haml +0 -22
  272. data/web/views/player_registered.haml +0 -2
  273. data/web/views/register_layout.haml +0 -22
  274. data/web/views/restart.haml +0 -35
@@ -0,0 +1,149 @@
1
+
2
+ gamemachine {
3
+
4
+ environment = test
5
+ use_regions = true
6
+ orm = false
7
+ mono_enabled = false
8
+
9
+ client {
10
+
11
+ # Sets the protocol and host/port used by the client if set to TCP or UDP. ANY lets the client use it's own values
12
+ protocol = ANY
13
+ }
14
+
15
+ handlers {
16
+
17
+ # Team handler
18
+ team = "GameMachine::DefaultHandlers::TeamHandler"
19
+
20
+ # Authentication handlers.
21
+
22
+ #PublicAuthenticator allows any user/password combination to work
23
+ auth = "com.game_machine.authentication.PublicAuthenticator"
24
+
25
+ # The default. Uses salted password hash (bcrypt)
26
+ #auth = "com.game_machine.authentication.DefaultAuthenticator"
27
+
28
+ }
29
+
30
+ routers {
31
+ # Size of the router for incoming message from all clients
32
+ game_handler = 5
33
+
34
+ # Also in the pipeline for all incoming requests, should be set the same as
35
+ # game_handler_routers
36
+ request_handler = 5
37
+
38
+ # router size for the udp actor that handles all incoming upd messages
39
+ udp = 5
40
+
41
+ objectdb = 5
42
+ }
43
+
44
+ datastore {
45
+ # What data store the object database will use (one of memory, mapdb, or couchbase)
46
+ store = gamecloud
47
+
48
+ serialization = json
49
+
50
+ # minimum time in milliseconds between writes to the backing store of the same key. When a message
51
+ # exceeds the limit it is either enqueued, or if already enqueued, it's value is updated, it's
52
+ # value is updated. -1 disables caching. Default 1000
53
+ cache_write_interval = -1
54
+
55
+ # Total writes per second to the backing store that an actor will allow, across all keys. Note this is on a per actor
56
+ # basis. If you want to limit total writes per second to your database, this value should be a multiple of the number
57
+ # of write behind cache actors that are started. -1 disables caching. Default 100
58
+ cache_writes_per_second = -1
59
+ }
60
+
61
+
62
+ gamecloud {
63
+ #host = "localhost:9000"
64
+ #user = test
65
+ #api_key = 294122207690d6e93867c56fae265c24
66
+ #api_key = 20934a81ba104ad1936b8a3e9e7fdaef
67
+
68
+ user = chris
69
+ host = "cloud-dev.gamemachine.io:80"
70
+ api_key = 1a77d75e32767f89b0710311be1fd8a5
71
+ }
72
+
73
+ grids {
74
+ default = "4000, 50, 1"
75
+ aoe = "4000, 5, 1"
76
+ local_chat = "4000, 10, 10"
77
+ }
78
+
79
+ couchbase {
80
+ bucket = gamemachine
81
+ password = pass
82
+ servers = ["http://192.168.1.8:8091/pools"]
83
+ }
84
+
85
+ jdbc {
86
+
87
+ // Postgres
88
+ hostname = 127.0.0.1
89
+ port = 5432
90
+ database = gamemachine
91
+ url = "jdbc:postgresql://127.0.0.1:5432/gamemachine"
92
+ ds = "org.postgresql.ds.PGSimpleDataSource"
93
+ driver = "org.postgresql.Driver"
94
+ username = gamemachine
95
+ password = gamemachine
96
+
97
+ // Mysql
98
+ #hostname = 127.0.0.1
99
+ #port = 3306
100
+ #database = gamemachine
101
+ #url = "mysql://127.0.0.1:3306/game_machine"
102
+ #ds = "com.mysql.jdbc.jdbc2.optional.MysqlDataSource"
103
+ #driver = "com.mysql.jdbc.Driver"
104
+ #username = gamemachine
105
+ #password = gamemachine
106
+
107
+ }
108
+
109
+ http {
110
+ enabled = true
111
+ host = 0.0.0.0
112
+ port = 3000
113
+ }
114
+
115
+ udp {
116
+ enabled = true
117
+ host = 0.0.0.0
118
+ port = 24130
119
+ }
120
+
121
+ tcp {
122
+ enabled = true
123
+ host = 0.0.0.0
124
+ port = 8910
125
+ }
126
+
127
+ akka {
128
+ host = 127.0.0.1
129
+ port = 2551
130
+ }
131
+
132
+ # Seeds are akka nodes that should already be in the cluster. We use them as first points of contact to join against
133
+ # If there are no seeds, we start the cluster by joining to ourself
134
+ #seeds = ["127.0.0.1:9991","127.0.0.1:9992"]
135
+ seeds = []
136
+
137
+ admin {
138
+ user = admin
139
+ pass = pass
140
+ }
141
+
142
+ regions = [
143
+ ["zone1","GameMachine::DefaultHandlers::ZoneManager"],
144
+ ["zone2", "GameMachine::DefaultHandlers::ZoneManager"]
145
+ ]
146
+
147
+ }
148
+
149
+
@@ -18,17 +18,22 @@ Gem::Specification.new do |gem|
18
18
  gem.require_paths = ["lib"]
19
19
 
20
20
  gem.add_dependency 'i18n'
21
- gem.add_dependency 'rjack-logback'
22
- gem.add_dependency 'settingslogic'
23
- gem.add_dependency 'consistent-hashing'
24
21
  gem.add_dependency 'json'
25
22
  gem.add_dependency 'ffi'
26
23
  gem.add_dependency 'sinatra'
27
24
  gem.add_dependency 'sinatra-contrib'
28
- gem.add_dependency 'haml'
29
- gem.add_dependency 'webrick'
25
+ gem.add_dependency 'rack-flash3'
26
+ gem.add_dependency 'activesupport'
27
+ gem.add_dependency 'wavefront'
28
+ gem.add_dependency 'puma'
29
+ gem.add_dependency 'faraday'
30
+ gem.add_dependency 'bcrypt'
31
+ gem.add_dependency 'bundler'
32
+
30
33
 
31
34
  gem.add_development_dependency 'rake'
35
+ gem.add_development_dependency 'nanoc'
36
+ gem.add_development_dependency 'kramdown'
32
37
  gem.add_development_dependency 'rspec'
33
38
  gem.add_development_dependency 'rspec-mocks'
34
39
  gem.add_development_dependency 'rspec-expectations'
@@ -0,0 +1,3 @@
1
+
2
+ #require_relative 'example/boot'
3
+ require_relative 'tutorial/boot'
@@ -1,9 +1,9 @@
1
1
  ---
2
2
  zone1:
3
- male: 200
4
- viking: 200
5
- golem: 200
6
- worm: 200
3
+ male: 400
4
+ viking: 100
5
+ golem: 100
6
+ worm: 2000
7
7
  zone2:
8
8
  male: 100
9
9
  viking: 100
@@ -49,7 +49,7 @@ module Example
49
49
  if position.distance(player[:vector]) <= @agro_radius
50
50
  movement.set_target(player[:vector])
51
51
  @target_id = player[:id]
52
- #log("target chosen #{@target_id}")
52
+ log("target chosen #{@target_id}")
53
53
  end
54
54
  end
55
55
  end
@@ -4,9 +4,7 @@ require_relative 'models/attack'
4
4
  require_relative 'models/user'
5
5
  require_relative 'models/combat_update'
6
6
  require_relative 'models/player_command'
7
- require_relative 'authentication_handler'
8
7
  require_relative 'tracking_handler'
9
- require_relative 'player_register'
10
8
  require_relative 'example_controller'
11
9
  require_relative 'chatbot'
12
10
  require_relative 'combat_controller'
@@ -16,6 +14,7 @@ require_relative 'aggressive_npc'
16
14
  require_relative 'npc_group'
17
15
  require_relative 'player_manager'
18
16
  require_relative 'zone_manager'
17
+ require_relative 'player_register'
19
18
 
20
19
  module Example
21
20
  class Game
@@ -77,4 +77,4 @@ module Example
77
77
  end
78
78
 
79
79
  end
80
- end
80
+ end
@@ -0,0 +1,9 @@
1
+
2
+ GameMachine::Routes.game_messages do
3
+
4
+ # The route id and the to: parameter are both required. Everything else is optional
5
+ # route id's can be any positive integer. For ruby actors, to: should be the class. For java actors
6
+ # to: should be the string name of the actor (as defined in the java class)
7
+ route 1, to: 'Tutorial::ItemManager', distributed: true, name: 'item_manager'
8
+ route 2, to: 'loot_generator', name: 'loot_generator'
9
+ end
@@ -0,0 +1,12 @@
1
+
2
+ require_relative 'item_manager'
3
+
4
+ # For the inventory handler we use a distributed router. The routing system for game messages uses
5
+ # the player id to hash against which guarantees that player ids are mapped to specific actors.
6
+ # This lets us cache player specific data in the actor that the player is hashed to.
7
+ if GameMachine::Application.config.orm
8
+ require_relative 'seed'
9
+ GameMachine::Actor::Builder.new(Tutorial::ItemManager).distributed(3).start
10
+ end
11
+
12
+
@@ -0,0 +1,256 @@
1
+ require_relative 'object_store'
2
+ require_relative 'sql_store'
3
+
4
+ module Tutorial
5
+
6
+ # Provides item persistence and management. Choice of using object store or sql on a per item basis.
7
+ # Items that have a limited quantity or a cost involve updating multiple records. These items will benefit from
8
+ # using sql as the item manager wraps those updates in a transaction to ensure the updates are atomic. But that comes
9
+ # at a cost. Do not use sql for items just because you prefer sql.
10
+
11
+ # Items that are not limited quantity or have a cost, only require updating the item itself. These items are ideal for
12
+ # the object store. Because we use a distributed router for the item manager, even object store items are saved atomically.
13
+ # The limitation of the object store is that we cannot save multiple items atomically, but are limited to just one.
14
+
15
+ # This demo is designed to show the full persistence api and reliable messaging in a common use case. It should work
16
+ # fine as a starting point for your own item management.
17
+
18
+
19
+ # Design notes:
20
+ # - Item definitions are just items assigned to the 'global' user. Player items are created by cloning one of the global items.
21
+ #
22
+ # - Extending the system for more types of items should be done compositionally by adding new messages to PlayerItem. Think of it
23
+ # as an entity component system where PlayerItem is the entity, and all the messages it contains are the components.
24
+ #
25
+ # - We prefer to use nested messages instead of adding concrete fields to PlayerItem. It's a good way to keep encapsulation.
26
+
27
+ class ItemManager < GameMachine::Actor::GameActor
28
+ include GameMachine
29
+ attr_reader :player_item_cache, :catalog_list, :catalog_map, :object_store, :sql_store, :catalog_user
30
+
31
+ def awake(args)
32
+ @catalog_user = 'global'
33
+ @sql_store = SqlStore.new
34
+ @object_store = ObjectStore.new
35
+
36
+ @player_item_cache = {}
37
+
38
+ @catalog_list = MessageLib::PlayerItem.db_find_all(catalog_user)
39
+ @catalog_map = catalog_list.each_with_object({}) {|v,res| res[v.id] = v}
40
+ end
41
+
42
+ def on_game_message(game_message)
43
+ player_items_message = MessageLib::PlayerItems.new
44
+
45
+ # exactly_once returns true of the message is a reliable message, and it is the first time we have seen
46
+ # the message. Use set_reply instead of tell_player for reliable messages.
47
+ if exactly_once(game_message)
48
+ reply = new_game_message.set_player_items(player_items_message)
49
+
50
+ if game_message.has_add_player_item
51
+ add_player_item(game_message.add_player_item.player_item).each do |player_item|
52
+ reply.player_items.add_player_item(player_item)
53
+ end
54
+ end
55
+
56
+ if game_message.has_remove_player_item
57
+ if player_item = remove_player_item(game_message.remove_player_item.id,
58
+ game_message.remove_player_item.quantity
59
+ )
60
+ reply.player_items.add_player_item(player_item)
61
+ end
62
+ end
63
+
64
+ set_reply(reply)
65
+
66
+ elsif game_message.has_request_player_items
67
+
68
+ if game_message.request_player_items.catalog
69
+ player_items_message.set_player_item_list(catalog_list)
70
+ player_items_message.catalog = true
71
+ else
72
+ player_items.values.each {|pi| player_items_message.add_player_item(pi)}
73
+ end
74
+
75
+ player_message = new_game_message
76
+ player_message.set_player_items(player_items_message)
77
+ tell_player(player_message)
78
+ else
79
+ unhandled(game_message)
80
+ end
81
+ end
82
+
83
+ def on_player_disconnect(player_id)
84
+ player_item_cache.delete(player_id)
85
+ end
86
+
87
+ private
88
+
89
+ def player_items
90
+ unless player_item_cache.fetch(player_id,nil)
91
+ player_item_cache[player_id] = {}
92
+ sql_store.all_for_player(player_id).each do |player_item|
93
+ player_item_cache[player_id][player_item.id] = player_item
94
+ end
95
+ object_store.all_for_player(player_id).each do |player_item|
96
+ player_item_cache[player_id][player_item.id] = player_item
97
+ end
98
+ end
99
+ player_item_cache[player_id]
100
+ end
101
+
102
+ def add_player_item(player_item)
103
+ catalog_item = catalog_map.fetch(player_item.id,nil)
104
+ return nil if catalog_item.nil?
105
+
106
+ if object_store_item?(player_item)
107
+ return add_object_store_item(player_item,catalog_item)
108
+ else
109
+ return add_sql_item(player_item,catalog_item)
110
+ end
111
+ end
112
+
113
+ def remove_player_item(id,quantity)
114
+ if player_item = player_items.fetch(id,nil)
115
+ player_item.quantity -= quantity
116
+ if player_item.quantity >= 1
117
+ store_save_player_item(player_item,player_id)
118
+ else
119
+ store_delete_player_item(player_item,player_id)
120
+ player_items.delete(id)
121
+ end
122
+ player_item
123
+ end
124
+ end
125
+
126
+ # Retrieves current player item, or creates new one from catalog item
127
+ # new items are set to 0 quantity and stripped of components that we don't need
128
+ # to store on the player copy, such as the cost.
129
+ def player_item(id,catalog_item)
130
+ if current_player_item = player_items.fetch(id,nil)
131
+ current_player_item
132
+ else
133
+ current_player_item = catalog_item.clone
134
+ current_player_item.quantity = 0
135
+ current_player_item.set_cost(nil)
136
+ current_player_item
137
+ end
138
+ end
139
+
140
+ def deduct_item_cost(player_item,catalog_item)
141
+ currency = catalog_item.cost.currency
142
+ return nil unless player_items.has_key?(currency)
143
+
144
+ player_currency = player_items[currency].clone
145
+
146
+ currency_required = player_item.quantity * catalog_item.cost.amount
147
+ if player_currency.quantity >= currency_required
148
+ player_currency.quantity -= currency_required
149
+ store_save_player_item(player_currency,player_id,true)
150
+ return player_currency
151
+ else
152
+ nil
153
+ end
154
+ end
155
+
156
+ def add_object_store_item(player_item,catalog_item)
157
+ current_player_item = player_item(player_item.id,catalog_item)
158
+ current_player_item.quantity += player_item.quantity
159
+ player_items[current_player_item.id] = current_player_item
160
+
161
+ store_save_player_item(current_player_item,player_id)
162
+ return [current_player_item]
163
+ end
164
+
165
+ def add_sql_item(player_item,catalog_item)
166
+ state = OpenStruct.new
167
+ changed_items = []
168
+ state.player_item = player_item(player_item.id,catalog_item).clone
169
+
170
+ begin
171
+ ModelLib::PlayerItem.open_transaction
172
+
173
+ limited_item = catalog_item.quantity == -1 ? false : true
174
+
175
+ if limited_item
176
+ state.catalog_item = sql_store.find_by_id(catalog_item.id,catalog_user,true)
177
+ if state.catalog_item.quantity >= player_item.quantity
178
+ state.catalog_item.quantity -= player_item.quantity
179
+ store_save_player_item(state.catalog_item,catalog_user,true)
180
+ else
181
+ ModelLib::PlayerItem.rollback_transaction
182
+ GameMachine.logger.info "Insufficient quantity (#{current_catalog_item.quantity}) for #{player_item.id}"
183
+ return changed_items
184
+ end
185
+ end
186
+
187
+ if catalog_item.has_cost
188
+ state.player_currency = deduct_item_cost(player_item,catalog_item)
189
+ if state.player_currency.nil?
190
+ ModelLib::PlayerItem.rollback_transaction
191
+ GameMachine.logger.info "cost deduction failed #{player_item.id}"
192
+ return changed_items
193
+ end
194
+ end
195
+
196
+ state.player_item.quantity += player_item.quantity
197
+ store_save_player_item(state.player_item,player_id,true)
198
+
199
+ ModelLib::PlayerItem.commit_transaction
200
+
201
+ player_items[state.player_item.id] = state.player_item
202
+ changed_items << state.player_item
203
+
204
+ if state.catalog_item
205
+ catalog_item = state.catalog_item
206
+ end
207
+
208
+ if state.player_currency
209
+ player_items[state.player_currency.id] = state.player_currency
210
+ changed_items << state.player_currency
211
+ end
212
+
213
+ return changed_items
214
+ rescue Exception => e
215
+ GameMachine.logger.error "Error adding sql item #{player_item.id} #{e.to_s} \n #{e.backtrace.join("\n")}"
216
+ ModelLib::PlayerItem.rollback_transaction
217
+ end
218
+ end
219
+
220
+ # Use object store when:
221
+ # - item is not currency
222
+ # - item is not limited quantity
223
+ # - item does not have a cost
224
+
225
+ # Note that cost handling is not implemented for object store items.
226
+ def object_store_item?(player_item)
227
+ catalog_item = catalog_map.fetch(player_item.id)
228
+ if catalog_item.has_cost
229
+ false
230
+ elsif ['gold','silver'].include?(catalog_item.id)
231
+ false
232
+ elsif catalog_item.quantity = -1
233
+ true
234
+ else
235
+ false
236
+ end
237
+ end
238
+
239
+ def store_save_player_item(player_item,player_id,in_transaction=false)
240
+ if object_store_item?(player_item)
241
+ object_store.save_player_item(player_item,player_id)
242
+ else
243
+ sql_store.save_player_item(player_item,player_id,in_transaction)
244
+ end
245
+ end
246
+
247
+ def store_delete_player_item(player_item,player_id)
248
+ if object_store_item?(player_item)
249
+ object_store.delete_player_item(player_item.id,player_id)
250
+ else
251
+ sql_store.delete_player_item(player_item.id,player_id)
252
+ end
253
+ end
254
+
255
+ end
256
+ end