krakenlab 2018.01.07

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.
@@ -0,0 +1,15 @@
1
+ require 'kraken/version'
2
+
3
+ # Main module from Kraken Framework
4
+ module Kraken
5
+ end
6
+
7
+ require 'kraken/core/client'
8
+ require 'kraken/core/config'
9
+ require 'kraken/core/listener'
10
+ require 'kraken/core/log'
11
+ require 'kraken/core/app'
12
+
13
+ require 'kraken/models/model'
14
+
15
+ require 'kraken/triggers/trigger'
@@ -0,0 +1,64 @@
1
+ module Kraken
2
+ APP_FILE = "require 'yaml'\n
3
+ Kraken::Config.instance.setup do |config|
4
+ config.server name: 'app name', version: '1.0', handler: :godot_30
5
+ config.add_trigger klass: Kraken::Trigger
6
+ end\n
7
+ Kraken::Migrations.configure do |c|
8
+ c.schema_format = :ruby
9
+ c.db_dir = 'db'
10
+ c.yaml_config = 'config/db.yml'
11
+ c.migrations_paths = ['db/migrate']
12
+ end
13
+ ".freeze
14
+
15
+ CONNECTION_FILE = "class Kraken::Connection < Kraken::MemoryModel
16
+ def on_delete; end\n
17
+ def authenticate
18
+ true
19
+ end
20
+ end".freeze
21
+
22
+ DB_FILE = "server:
23
+ adapter: postgresql
24
+ database: kraken
25
+ encoding: utf8
26
+ host: localhost
27
+ username: postgres
28
+ password: postgres".freeze
29
+
30
+ RAKEFILE_FILE = "require 'kraken'\n
31
+ Kraken::App.load_app
32
+ Kraken::Migrations.load_tasks\n
33
+ task :default do
34
+ sh 'bundle exec kraken -s'
35
+ end\n
36
+ task :console do
37
+ sh 'bundle exec kraken -d'
38
+ end\n
39
+ task :test do
40
+ sh 'rubocop'
41
+ sh 'bundle exec rspec'
42
+ end\n
43
+ task :migrate do
44
+ sh 'bundle exec kraken -m'
45
+ end".freeze
46
+
47
+ GEMFILE_FILE = "source 'https://rubygems.org' do
48
+ gem 'krakenlab', '#{Kraken::VERSION}'\n
49
+ gem 'rspec'
50
+ gem 'rubocop'
51
+ end
52
+ ".freeze
53
+
54
+ GITIGNORE_FILE = '*.lock'.freeze
55
+
56
+ PROJECT_TREE = {
57
+ 'app' => { 'triggers' => {}, 'validators' => {}, 'models' => { 'database' => {}, 'memory' => {} } },
58
+ 'config' => { 'app.rb' => APP_FILE, 'connection.rb' => CONNECTION_FILE, 'db.yml' => DB_FILE },
59
+ 'db' => { 'seeds.rb' => '', 'migrate' => {} },
60
+ 'Rakefile' => RAKEFILE_FILE,
61
+ 'Gemfile' => GEMFILE_FILE,
62
+ '.gitignore' => GITIGNORE_FILE
63
+ }.freeze
64
+ end
@@ -0,0 +1,46 @@
1
+ require 'irb'
2
+ require 'require_all'
3
+ require 'project_creator'
4
+ require 'kraken/constants/project'
5
+
6
+ module Kraken
7
+ # This class are used for load and create kraken applications!
8
+ class App
9
+ def self.load_app
10
+ require_all 'app/validators' if File.exist? 'app/validators'
11
+ require_all 'app' if File.exist? 'app'
12
+ require_all 'config' if File.exist? 'config'
13
+ end
14
+
15
+ def self.create_app(name)
16
+ { name.to_s => PROJECT_TREE }.create_project
17
+ exit 0
18
+ end
19
+
20
+ def self.print_version
21
+ puts 'KrakenLab'
22
+ puts "-v #{Kraken::VERSION}"
23
+ exit 0
24
+ end
25
+
26
+ def self.print_help
27
+ print_version
28
+ puts 'kraken -n app_name: Create a new kraken app'
29
+ puts 'kraken -s: start the created app'
30
+ puts 'kraken -v: show the version'
31
+ puts 'kraken -d: start a console'
32
+ puts ''
33
+
34
+ puts 'rake db:* for migrations operations. See more about ActiveRecord'
35
+ end
36
+
37
+ def self.start_console
38
+ IRB.start(__FILE__)
39
+ exit 0
40
+ end
41
+
42
+ def self.start_server
43
+ Kraken::Listener.new.join
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,108 @@
1
+ require 'socket'
2
+
3
+ module Kraken
4
+ # A simple client for KrakenLab server.
5
+ # You can use this class to Debug the server with `kraken -c`
6
+ # or implements your game using gosu gem!
7
+ #
8
+ # a = Kraken::Client.new 'user', 'pass'
9
+ # a.connect 'localhost'
10
+ # a.call 'module::krakentrigger', {a: 2, b: [2,3,4], c: 'haha'}
11
+ # a.call 'module::krakentrigger', 'call only this'
12
+ # a.call 'module::krakentrigger', ['or this', 3]
13
+ class Client
14
+ def initialize(user, pass, version)
15
+ @user = user
16
+ @pass = pass
17
+ @version = version
18
+ end
19
+
20
+ def close
21
+ @socket.close unless @socket.nil?
22
+ end
23
+
24
+ def connect(host, port = 3030)
25
+ @socket = TCPSocket.new(host, port)
26
+ write @version
27
+ write @user
28
+ write @pass
29
+ raise 'connection refused' unless read == 'ok'
30
+ rescue StandardError
31
+ raise 'connection refused'
32
+ end
33
+
34
+ def call(method, params)
35
+ write method
36
+ write to_args(params)
37
+ read_args
38
+ end
39
+
40
+ private
41
+
42
+ def read
43
+ r = @socket.gets
44
+ raise 'connection lost' if r.nil?
45
+ r.chomp
46
+ end
47
+
48
+ def read_args
49
+ type = read
50
+ case type
51
+ when 'h'
52
+ return read_hash
53
+ when 'v'
54
+ return read_vector
55
+ when 'n'
56
+ return nil
57
+ when 'a'
58
+ return read
59
+ end
60
+ end
61
+
62
+ def read_hash
63
+ n = read.to_i
64
+ awns = {}
65
+ n.times { awns[read.to_sym] = read_args }
66
+ awns
67
+ end
68
+
69
+ def read_vector
70
+ n = read.to_i
71
+ awns = []
72
+ n.times { awns << read_args }
73
+ awns
74
+ end
75
+
76
+ def write(txt)
77
+ @socket.puts txt.chomp
78
+ end
79
+
80
+ def to_args(obj)
81
+ case obj
82
+ when Hash
83
+ return "h\n#{obj.size}\n#{hash_protocol obj}"
84
+ when Array
85
+ return "v\n#{obj.size}\n#{vector_protocol obj}"
86
+ when NilClass
87
+ return 'n'
88
+ end
89
+ absolute_value(obj)
90
+ end
91
+
92
+ def hash_protocol(obj)
93
+ ret = ''
94
+ obj.each_pair { |key, value| ret += "#{key}\n#{to_args value}\n" }
95
+ ret.chomp
96
+ end
97
+
98
+ def vector_protocol(obj)
99
+ ret = ''
100
+ obj.each { |value| ret += "#{to_args value}\n" }
101
+ ret.chomp
102
+ end
103
+
104
+ def absolute_value(obj)
105
+ "a\n#{obj}"
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,39 @@
1
+ require 'singleton'
2
+
3
+ module Kraken
4
+ # Configure the kraken framework.
5
+ # You can configure the server, postgre and redis.
6
+ # You can configure the events in server.
7
+ # Yes! You can configure other plugins here!
8
+ #
9
+ # Kraken::Config.instance.setup do |config|
10
+ # config.server name: 'hehe'
11
+ # end
12
+ class Config
13
+ include Singleton
14
+
15
+ attr_reader :server_name, :server_version, :server_handler
16
+ attr_reader :triggers
17
+
18
+ def setup
19
+ yield self
20
+ end
21
+
22
+ def server(name: 'kraken app', version: 'valid version', handler: :default)
23
+ @server_name = name
24
+ @server_version = version
25
+
26
+ raise 'invalid parser' unless HANDLERS.include? handler
27
+
28
+ @server_handler = handler
29
+ end
30
+
31
+ def add_trigger(klass: Kraken::Trigger)
32
+ raise 'Klass needs to inherit Kraken::Trigger' unless klass <= Kraken::Trigger
33
+
34
+ @triggers ||= {}
35
+ @triggers[klass.to_s.downcase] = klass
36
+ Kraken::Log.info "trigger [#{klass.to_s.downcase}] loaded"
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,21 @@
1
+ require 'kraken/models/model'
2
+
3
+ module Kraken
4
+ # The most trivial node
5
+ class Connection < MemoryModel
6
+ attribute :user
7
+ attribute :pass
8
+
9
+ index :user
10
+
11
+ # How are defined it is a uniq user authenticated in Kraken Network
12
+ def single_user?
13
+ Kraken::Connection.find(user: user).size <= 1
14
+ end
15
+
16
+ # Validate if the credentials are correct
17
+ def authenticate
18
+ true
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,14 @@
1
+ require 'kraken/core/handlers/handler'
2
+ require 'kraken/core/handlers/godot30_handler'
3
+
4
+ module Kraken
5
+ # This class create the handler defined at Config
6
+ class HandlerFactory
7
+ def self.create(socket)
8
+ parser = Kraken::Config.instance.server_handler
9
+
10
+ return Kraken::Godot30Handler.new(socket) if parser == :godot_30
11
+ Kraken::Handler.new(socket)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,16 @@
1
+ require 'kraken/core/handlers/handler'
2
+
3
+ module Kraken
4
+ # This class made the handler with godot 3.0
5
+ # To use this handler, setup this line in config file:
6
+ # config.server name: 'app name', version: '1.0', handler: :godot_30
7
+ class Godot30Handler < Kraken::Handler
8
+ def read
9
+ string_length = @socket.read(4).unpack('L<').first
10
+ raise 'connection lost' if string_length.nil?
11
+ line = @socket.read(string_length)
12
+ raise 'connection lost' if line.nil?
13
+ line.chomp
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,150 @@
1
+ require 'socket'
2
+ require 'thread'
3
+
4
+ require 'kraken/core/connection'
5
+
6
+ module Kraken
7
+ HANDLERS = %i[godot_30 default].freeze
8
+
9
+ # This class handle a Socket.
10
+ class Handler
11
+ attr_accessor :connection
12
+
13
+ def initialize(socket)
14
+ return if socket.nil?
15
+
16
+ @socket = socket
17
+ @thread = Thread.new do
18
+ begin
19
+ start
20
+ rescue StandardError => e
21
+ Kraken::Log.error e
22
+ close
23
+ end
24
+ end
25
+ end
26
+
27
+ def close
28
+ @connection.delete unless @connection.nil?
29
+
30
+ Kraken::Log.info 'bye bye socket'
31
+
32
+ @socket.close
33
+ @thread.kill
34
+ end
35
+
36
+ def read_trigger
37
+ trigger = read
38
+ args = read_args
39
+ [Kraken::Config.instance.triggers[trigger.downcase], args]
40
+ end
41
+
42
+ private
43
+
44
+ def start
45
+ version, user, pass = read_authentication_info
46
+
47
+ raise 'invalid version' unless Kraken::Config.instance.server_version == version
48
+
49
+ @connection = Connection.create(user: user, pass: pass)
50
+ @connection.save
51
+
52
+ raise 'only one connection by user' unless @connection.single_user?
53
+
54
+ if @connection.authenticate
55
+ write 'ok'
56
+ else
57
+ write 'nop'
58
+ raise 'can not authenticate'
59
+ end
60
+
61
+ work
62
+ close
63
+ end
64
+
65
+ def read_authentication_info
66
+ version = read
67
+ user = read
68
+ pass = read
69
+ [version, user, pass]
70
+ end
71
+
72
+ def work
73
+ loop do
74
+ trigger, args = read_trigger
75
+
76
+ shot = trigger.new(self, args)
77
+ shot.run
78
+ callback = shot.callback
79
+
80
+ write to_args(callback)
81
+ end
82
+ end
83
+
84
+ def read
85
+ r = @socket.gets
86
+ raise 'connection lost' if r.nil?
87
+ r.chomp
88
+ end
89
+
90
+ def read_args
91
+ type = read
92
+ case type
93
+ when 'h'
94
+ return read_hash
95
+ when 'v'
96
+ return read_vector
97
+ when 'n'
98
+ return nil
99
+ when 'a'
100
+ return read
101
+ end
102
+ end
103
+
104
+ def read_hash
105
+ n = read.to_i
106
+ awns = {}
107
+ n.times { awns[read.to_sym] = read_args }
108
+ awns
109
+ end
110
+
111
+ def read_vector
112
+ n = read.to_i
113
+ awns = []
114
+ n.times { awns << read_args }
115
+ awns
116
+ end
117
+
118
+ def write(txt)
119
+ @socket.puts txt.chomp
120
+ end
121
+
122
+ def to_args(obj)
123
+ case obj
124
+ when Hash
125
+ return "h\n#{obj.size}\n#{hash_protocol obj}"
126
+ when Array
127
+ return "v\n#{obj.size}\n#{vector_protocol obj}"
128
+ when NilClass
129
+ return 'n'
130
+ end
131
+ absolute_value(obj)
132
+ end
133
+
134
+ def hash_protocol(obj)
135
+ ret = ''
136
+ obj.each_pair { |key, value| ret += "#{key}\n#{to_args value}\n" }
137
+ ret.chomp
138
+ end
139
+
140
+ def vector_protocol(obj)
141
+ ret = ''
142
+ obj.each { |value| ret += "#{to_args value}\n" }
143
+ ret.chomp
144
+ end
145
+
146
+ def absolute_value(obj)
147
+ "a\n#{obj}"
148
+ end
149
+ end
150
+ end