krakenlab 2018.01.07

Sign up to get free protection for your applications and to get access to all the features.
@@ -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