cranberry 0.0.1.alpha

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 45d5765f8fb9b824cef72f1c7afc4e73e29c0dae
4
+ data.tar.gz: 3703e3252b6ae3b029b2aff9ea7dbd2b9ad557ae
5
+ SHA512:
6
+ metadata.gz: 4b3340f503416aa2065e0dafe01a66b87e5a61b03470e3e8387cf2c89b42aa4d41b9e6da2c406646d7f047dbb218d5f10ba619ab2c1f083244568350d4201bd2
7
+ data.tar.gz: 9619ad55f4433842d28026baa450d32d78399187e24aba74ab30d06d9b96d66245da1d43d6601efebe4716c2354b45363f48dd0dc16235d7e080752044165721
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+
19
+ # Ignore these stupid files
20
+ .DS_Store
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'pry'
7
+ gem 'guard-rspec', require: false
8
+ gem 'terminal-notifier-guard' if RUBY_PLATFORM =~ /darwin/
9
+ end
@@ -0,0 +1,9 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :rspec do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+ end
9
+
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Caleb Tutty and Giles Thompson
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,60 @@
1
+ Cranberry Websocket Game Server
2
+ ===============================
3
+
4
+ _|_|_| _|
5
+ _| _| _|_| _|_|_| _|_|_| _|_|_| _|_| _| _|_| _| _|_| _| _|
6
+ _| _|_| _| _| _| _| _| _| _|_|_|_| _|_| _|_| _| _|
7
+ _| _| _| _| _| _| _| _| _| _| _| _| _|
8
+ _|_|_| _| _|_|_| _| _| _|_|_| _|_|_| _| _| _|_|_|
9
+ _|
10
+ _|_|
11
+
12
+ Cranberry is a WebSocket EventMachine-based server, that takes JSON strings as instructions.
13
+
14
+ This is not production ready, and still a work in progress. Check back soon!
15
+
16
+ ## Installation
17
+
18
+ Add this line to your application's Gemfile:
19
+
20
+ gem 'cranberry'
21
+
22
+ And then execute:
23
+
24
+ $ bundle
25
+
26
+ Or install it yourself as:
27
+
28
+ $ gem install cranberry
29
+
30
+ ## Usage
31
+
32
+ To use run:
33
+
34
+ bin/cranberry
35
+
36
+
37
+ to use the front-end client-side interface, open ``public/index.html``
38
+
39
+ ## Roadmap
40
+
41
+ 0.0.1 stable
42
+
43
+ [ ] build up spec coverage
44
+
45
+ [ ] implement a command router for the Websocket onmessage events
46
+
47
+ [ ] experiment with a DSL for other projects to use the gem with
48
+
49
+
50
+ 1.0.0
51
+
52
+ [ ] make it awesome
53
+
54
+ ## Contributing
55
+
56
+ 1. Fork it
57
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
58
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
59
+ 4. Push to the branch (`git push origin my-new-feature`)
60
+ 5. Create new Pull Request
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ # resolve bin path, ignoring symlinks
5
+ require 'pathname'
6
+ bin_file = Pathname.new(__FILE__).realpath
7
+
8
+ # add self to libpath
9
+ $:.unshift File.expand_path('../../lib', bin_file)
10
+
11
+ require 'cranberry'
12
+
13
+ Cranberry.run
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'cranberry/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'cranberry'
8
+ spec.version = Cranberry::VERSION
9
+ spec.authors = ['Caleb Tutty', 'Giles Thompson']
10
+ spec.email = ['caleb@prettymint.co.nz', 'iam@gilesthompson.co.nz']
11
+ spec.description = %q{Cranberry models game objects and maintains server-side state, allowing you to use client-side websockets to join and send JSON instructions}
12
+ spec.summary = %q{Cranberry is an EventMachine-driven Websockets multiplayer game server}
13
+ spec.homepage = ''
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_dependency 'eventmachine'
22
+ spec.add_dependency 'em-websocket'
23
+ spec.add_dependency 'json'
24
+ spec.add_dependency 'paint'
25
+
26
+ spec.add_development_dependency 'bundler', '~> 1.3'
27
+ spec.add_development_dependency 'rake'
28
+ spec.add_development_dependency 'rspec'
29
+ end
@@ -0,0 +1,13 @@
1
+ # Gem dependencies
2
+ require 'bundler/setup'
3
+ Bundler.setup
4
+ require 'eventmachine'
5
+ require 'em-websocket'
6
+ require 'json'
7
+ require 'paint'
8
+
9
+ # Cranberry files
10
+ Dir[File.dirname(__FILE__) + '/cranberry/**/*.rb'].each do |file|
11
+ require file
12
+ end
13
+
@@ -0,0 +1,9 @@
1
+ module Cranberry
2
+
3
+ Configuration = Struct.new(:columns, :rows, :host, :port)
4
+
5
+ def self.configuration
6
+ @@configuration ||= Configuration.new(88, 20, "0.0.0.0", 8080)
7
+ end
8
+
9
+ end
@@ -0,0 +1,11 @@
1
+ module Cranberry
2
+ module Handlers
3
+ class Log
4
+
5
+ def self.received_message(message, socket_id)
6
+ puts "#{message}"
7
+ end
8
+
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Cranberry
2
+ module Handlers
3
+ class Movement
4
+
5
+ def self.received_message(direction, socket_id)
6
+ puts "#{socket_id} wants to move #{direction}"
7
+ end
8
+
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,29 @@
1
+ module Cranberry
2
+ module Models
3
+ class Grid
4
+ attr_reader :rows, :columns
5
+
6
+ def initialize(rows, columns)
7
+ @rows, @columns = rows, columns
8
+ @grid = Array.new(rows) do
9
+ Array.new(columns)
10
+ end
11
+ end
12
+
13
+ def method_missing(method_name, *args, &block)
14
+ @grid.send method_name, *args, &block
15
+ end
16
+
17
+ def place(player)
18
+ x = rand(@columns)
19
+ y = rand(@rows)
20
+ if @grid[y][x]
21
+ place(player)
22
+ else
23
+ @grid[y][x] = player
24
+ end
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,16 @@
1
+ module Cranberry
2
+ module Models
3
+ class Player
4
+ attr_reader :socket_id, :socket
5
+ attr_accessor :name
6
+ attr_accessor :x_position, :y_position
7
+
8
+ def initialize(options = {})
9
+ @socket_id, @socket = options[:socket_id], options[:socket]
10
+ raise "Players require a socket id to be identifiable, and valid" unless @socket_id
11
+ @name = options[:name] || "anonymous user"
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,25 @@
1
+ module Cranberry
2
+ module Models
3
+ class World
4
+ attr_accessor :players
5
+ attr_reader :grid
6
+
7
+ # Singleton instance
8
+ def self.instance
9
+ @instance ||= new
10
+ end
11
+
12
+ private_class_method :new
13
+
14
+ private
15
+
16
+ def initialize
17
+ # Players exist on connection
18
+ @players = []
19
+ # The grid is a matrix - an array of arrays
20
+ @grid = Grid.new(Cranberry.configuration[:rows], Cranberry.configuration[:columns])
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,16 @@
1
+ module Cranberry
2
+
3
+ #
4
+ # Cranberry expects message handlers to be defined within the cranberry/handlers directory
5
+ #
6
+
7
+ def self.route_message(message)
8
+ parsed_message = begin
9
+ JSON.parse message
10
+ rescue JSON::ParserError
11
+ { message: message, handler: 'Log' }
12
+ end
13
+ Object.const_get("Cranberry::Handlers::#{parsed_message['handler']}").received_message(parsed_message['message'], parsed_message['socket_id'])
14
+ end
15
+
16
+ end
@@ -0,0 +1,21 @@
1
+ module Cranberry
2
+
3
+ def self.run
4
+
5
+ EventMachine.run do
6
+
7
+ trap("TERM") { self.stop }
8
+ trap("INT") { self.stop }
9
+
10
+ WebSocketServer.start
11
+
12
+ end
13
+ end
14
+
15
+ def self.stop
16
+ UI.clear_terminal_screen
17
+ UI.display_termination_message
18
+ EventMachine.stop
19
+ end
20
+
21
+ end
@@ -0,0 +1,35 @@
1
+ module Cranberry
2
+ module UI
3
+ def self.banner
4
+ <<-EOF
5
+
6
+ _|_|_| _|
7
+ _| _| _|_| _|_|_| _|_|_| _|_|_| _|_| _| _|_| _| _|_| _| _|
8
+ _| _|_| _| _| _| _| _| _| _|_|_|_| _|_| _|_| _| _|
9
+ _| _| _| _| _| _| _| _| _| _| _| _| _|
10
+ _|_|_| _| _|_|_| _| _| _|_|_| _|_|_| _| _| _|_|_|
11
+ _|
12
+ _|_|
13
+ EOF
14
+ end
15
+
16
+ def self.display_welcome_message
17
+ puts Paint[self.banner, :red]
18
+ puts "-" * 90
19
+ puts "Cranberry Game Server listening for WebSockets on #{Cranberry.configuration[:port]}"
20
+ puts "-" * 90
21
+ print "\n\n"
22
+ end
23
+
24
+ def self.display_termination_message
25
+ print "\n"
26
+ puts "-" * 90
27
+ puts "Terminating Cranberry Game Server"
28
+ puts "-" * 90
29
+ end
30
+
31
+ def self.clear_terminal_screen
32
+ puts "\e[H\e[2J" # this may not be very cross-platform...
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,45 @@
1
+ module Cranberry
2
+ module UI
3
+
4
+ class Console
5
+ def initialize(grid)
6
+ @grid, @columns, @rows = grid, grid.columns, grid.rows
7
+ end
8
+
9
+ def draw
10
+ print "\n"
11
+ draw_border
12
+ @rows.times.each_with_index do |row, row_index|
13
+ print '|'
14
+ @columns.times.each_with_index do |column, column_index|
15
+ cell = @grid[row_index][column_index]
16
+ if cell.nil?
17
+ print ' '
18
+ else
19
+ print 'x'
20
+ end
21
+ end
22
+ print '|'
23
+ print "\n"
24
+ end
25
+ draw_border
26
+ end
27
+
28
+ def draw_border
29
+ print '+'
30
+ @columns.times.each { print '-' }
31
+ print '+'
32
+ print "\n"
33
+ end
34
+
35
+ def reset_cursor
36
+ # http://stackoverflow.com/questions/14969458/deleting-multiple-lines-of-terminal-output-using-ruby
37
+ # Where \r moves the cursor to the start of the line, \e[A moves the cursor up one line, and \e[K
38
+ # clears from the cursor position to the end of the line. If you don't need anything further down
39
+ # the screen, you can also just send \e[J once you have the cursor where you want; that clears
40
+ # all the way to the end of the screen.
41
+ (@rows + 3).times { print "\e[A" }
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,3 @@
1
+ module Cranberry
2
+ VERSION = "0.0.1.alpha"
3
+ end
@@ -0,0 +1,36 @@
1
+ module Cranberry
2
+ module WebSocketServer
3
+ def self.start
4
+
5
+ console_ui = UI::Console.new(Models::World.instance.grid)
6
+ UI.display_welcome_message
7
+ console_ui.draw
8
+
9
+ EventMachine::WebSocket.run(host: Cranberry.configuration[:host], port: Cranberry.configuration[:port]) do |ws|
10
+
11
+ ws.onopen do |handshake|
12
+ world = Cranberry::Models::World.instance
13
+ player = Cranberry::Models::Player.new(socket_id: handshake.headers["Sec-WebSocket-Key"], socket: ws)
14
+ ws.send({ handler: 'Handshake', message: player.socket_id }.to_json)
15
+ world.grid.place player
16
+ world.players << player
17
+
18
+ console_ui.reset_cursor
19
+ console_ui.draw
20
+
21
+ end
22
+
23
+ ws.onmessage do |message|
24
+ Cranberry.route_message message
25
+ end
26
+
27
+ ws.onclose do
28
+ world = Cranberry::Models::World.instance
29
+ player = world.players.detect {|a| a.socket.signature == ws.signature}
30
+ world.players.delete player
31
+ end
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Cranberry</title>
6
+ <!-- <link type="text/css" rel="stylesheet" href="style.css"> -->
7
+ <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
8
+ <script src="js/handlers/handshake.js"></script>
9
+ <script src="js/input.js"></script>
10
+ <script src="js/socket.js"></script>
11
+ </head>
12
+ <body>
13
+ </body>
14
+ </html>
@@ -0,0 +1,7 @@
1
+ // TODO move init stuff like this to a global file
2
+ window.Cranberry = new Object();
3
+ Cranberry.Handlers = new Object();
4
+
5
+ Cranberry.Handlers.Handshake = function (socket_id) {
6
+ window.Cranberry.socket_id = socket_id;
7
+ };
@@ -0,0 +1,17 @@
1
+ // object to hold movement key information
2
+ inputs = new Object();
3
+ // add wasd inputs to object with a handler of movement
4
+ inputs[119] = { key: 'w', handler: 'Movement', message: 'up' }
5
+ inputs[115] = { key: 's', handler: 'Movement', message: 'down' }
6
+ inputs[97] = { key: 'a', handler: 'Movement', message: 'left' }
7
+ inputs[100] = { key: 'd', handler: 'Movement', message: 'right' }
8
+
9
+ // jquery bindings listening for keypress events
10
+ $(function() {
11
+ $( "body" ).keypress(function(event) {
12
+ if(event.which in inputs) { // check for key in inputs object before proceeding
13
+ var input = inputs[event.which]; // assign an input from our object
14
+ window.sendMessage(input.message, input.handler); // send a movement message to the server, of handler 'movement'
15
+ }
16
+ });
17
+ });
@@ -0,0 +1,32 @@
1
+ window.socket = new WebSocket('ws://localhost:8080');
2
+
3
+ // Open the socket
4
+ socket.onopen = function(event) {
5
+
6
+ console.log(event);
7
+
8
+ // Send an initial message
9
+ socket.send(JSON.stringify({message: 'Client here, I\'ve just connected!', handler: 'Log'}));
10
+
11
+ // Listen for messages
12
+ socket.onmessage = function(event) {
13
+ parsed_message = JSON.parse(event.data);
14
+ Cranberry.Handlers[parsed_message.handler](parsed_message.message);
15
+ };
16
+
17
+ // Listen for socket closes
18
+ socket.onclose = function(event) {
19
+ console.log('Client notified socket has closed', event);
20
+ };
21
+
22
+ // To close the socket....
23
+ //socket.close()
24
+ };
25
+
26
+ window.sendMessage = function (message, handler) {
27
+ if(Cranberry.socket_id === undefined) {
28
+ alert('Cannot send any data to the server, handshake has failed.');
29
+ } else {
30
+ window.socket.send(JSON.stringify({ message: message, handler: handler, socket_id: Cranberry.socket_id }));
31
+ }
32
+ };
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>QUnit Example</title>
6
+ <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.12.0.css">
7
+ <script src="../socket.io/socket.io.js"></script>
8
+ </head>
9
+ <body>
10
+ <div id="qunit"></div>
11
+ <div id="qunit-fixture"></div>
12
+ <script src="http://code.jquery.com/qunit/qunit-1.12.0.js"></script>
13
+ <script src="socket.js"></script>
14
+ </body>
15
+ </html>
@@ -0,0 +1,3 @@
1
+ test('connect to server', function() {
2
+ ok(1 == 1, 'indeed');
3
+ });
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cranberry do
4
+
5
+ describe "banner" do
6
+ it "works"
7
+ end
8
+
9
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cranberry::Models::Grid do
4
+
5
+ it "works"
6
+
7
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cranberry::Models::Player do
4
+
5
+ it "works"
6
+
7
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cranberry::Models::World do
4
+
5
+ it "is a singleton instance" do
6
+ world1, world2 = Cranberry::Models::World.instance, Cranberry::Models::World.instance
7
+ expect(world1.object_id).to eq(world2.object_id)
8
+ end
9
+
10
+ describe "it has a list of players" do
11
+
12
+ before :each do
13
+ @world = Cranberry::Models::World.instance
14
+ end
15
+
16
+ it "is an array" do
17
+ expect(@world.players).to be_a Array
18
+ end
19
+
20
+ end
21
+
22
+ describe "it has a grid" do
23
+
24
+ before :each do
25
+ @grid = Cranberry::Models::World.instance.grid
26
+ end
27
+
28
+ it "has a grid" do
29
+ expect(@grid).to be_a Cranberry::Models::Grid
30
+ end
31
+
32
+ end
33
+
34
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cranberry do
4
+
5
+ describe "server" do
6
+ it "works"
7
+ end
8
+
9
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cranberry::UI::Console do
4
+
5
+ it "works"
6
+
7
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cranberry::WebSocketServer do
4
+
5
+ describe "websocket" do
6
+ it "works"
7
+ end
8
+
9
+ end
@@ -0,0 +1,25 @@
1
+ ENV["RUBY_ENV"] ||= 'test'
2
+ require_relative '../lib/cranberry.rb'
3
+ require 'rspec/autorun'
4
+
5
+ # This file was generated by the `rspec --init` command. Conventionally, all
6
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
7
+ # Require this file using `require "spec_helper"` to ensure that it is only
8
+ # loaded once.
9
+ #
10
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
11
+
12
+ Dir[File.join(__FILE__, "support/*.rb")].each {|f| require f }
13
+
14
+ RSpec.configure do |config|
15
+ config.treat_symbols_as_metadata_keys_with_true_values = true
16
+ config.run_all_when_everything_filtered = true
17
+ config.filter_run :focus
18
+
19
+ # Run specs in random order to surface order dependencies. If you find an
20
+ # order dependency and want to debug it, you can fix the order by providing
21
+ # the seed, which is printed after each run.
22
+ # --seed 1234
23
+ config.order = 'random'
24
+ end
25
+
metadata ADDED
@@ -0,0 +1,192 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cranberry
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1.alpha
5
+ platform: ruby
6
+ authors:
7
+ - Caleb Tutty
8
+ - Giles Thompson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-10-29 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: eventmachine
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - '>='
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - '>='
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: em-websocket
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - '>='
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: json
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: paint
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: bundler
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ version: '1.3'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ~>
82
+ - !ruby/object:Gem::Version
83
+ version: '1.3'
84
+ - !ruby/object:Gem::Dependency
85
+ name: rake
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ - !ruby/object:Gem::Dependency
99
+ name: rspec
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - '>='
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - '>='
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ description: Cranberry models game objects and maintains server-side state, allowing
113
+ you to use client-side websockets to join and send JSON instructions
114
+ email:
115
+ - caleb@prettymint.co.nz
116
+ - iam@gilesthompson.co.nz
117
+ executables:
118
+ - cranberry
119
+ extensions: []
120
+ extra_rdoc_files: []
121
+ files:
122
+ - .gitignore
123
+ - .rspec
124
+ - Gemfile
125
+ - Gemfile.lock
126
+ - Guardfile
127
+ - LICENSE.txt
128
+ - README.md
129
+ - Rakefile
130
+ - bin/cranberry
131
+ - cranberry.gemspec
132
+ - lib/cranberry.rb
133
+ - lib/cranberry/configuration.rb
134
+ - lib/cranberry/handlers/log.rb
135
+ - lib/cranberry/handlers/movement.rb
136
+ - lib/cranberry/models/grid.rb
137
+ - lib/cranberry/models/player.rb
138
+ - lib/cranberry/models/world.rb
139
+ - lib/cranberry/router.rb
140
+ - lib/cranberry/server.rb
141
+ - lib/cranberry/ui/banner.rb
142
+ - lib/cranberry/ui/console.rb
143
+ - lib/cranberry/version.rb
144
+ - lib/cranberry/websocket_server.rb
145
+ - public/index.html
146
+ - public/js/handlers/handshake.js
147
+ - public/js/input.js
148
+ - public/js/socket.js
149
+ - public/js/spec/socket.html
150
+ - public/js/spec/socket.js
151
+ - spec/cranberry/banner_spec.rb
152
+ - spec/cranberry/models/grid_spec.rb
153
+ - spec/cranberry/models/player_spec.rb
154
+ - spec/cranberry/models/world_spec.rb
155
+ - spec/cranberry/server_spec.rb
156
+ - spec/cranberry/ui/console_spec.rb
157
+ - spec/cranberry/websocket_server_spec.rb
158
+ - spec/spec_helper.rb
159
+ homepage: ''
160
+ licenses:
161
+ - MIT
162
+ metadata: {}
163
+ post_install_message:
164
+ rdoc_options: []
165
+ require_paths:
166
+ - lib
167
+ required_ruby_version: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - '>='
170
+ - !ruby/object:Gem::Version
171
+ version: '0'
172
+ required_rubygems_version: !ruby/object:Gem::Requirement
173
+ requirements:
174
+ - - '>'
175
+ - !ruby/object:Gem::Version
176
+ version: 1.3.1
177
+ requirements: []
178
+ rubyforge_project:
179
+ rubygems_version: 2.0.3
180
+ signing_key:
181
+ specification_version: 4
182
+ summary: Cranberry is an EventMachine-driven Websockets multiplayer game server
183
+ test_files:
184
+ - spec/cranberry/banner_spec.rb
185
+ - spec/cranberry/models/grid_spec.rb
186
+ - spec/cranberry/models/player_spec.rb
187
+ - spec/cranberry/models/world_spec.rb
188
+ - spec/cranberry/server_spec.rb
189
+ - spec/cranberry/ui/console_spec.rb
190
+ - spec/cranberry/websocket_server_spec.rb
191
+ - spec/spec_helper.rb
192
+ has_rdoc: