termworld 0.1.3 → 0.2.0
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +9 -3
- data/lib/termworld.rb +14 -4
- data/lib/termworld/cli.rb +46 -2
- data/lib/termworld/commands/account.rb +35 -0
- data/lib/termworld/commands/daemon_operator.rb +50 -0
- data/lib/termworld/commands/user.rb +41 -0
- data/lib/termworld/commands/user_action.rb +58 -0
- data/lib/termworld/config.rb +8 -0
- data/lib/termworld/credential.rb +34 -0
- data/lib/termworld/daemon.rb +55 -0
- data/lib/termworld/db.rb +12 -0
- data/lib/termworld/models/user.rb +127 -0
- data/lib/termworld/resources/chip.rb +41 -0
- data/lib/termworld/resources/maps/town.rb +37 -0
- data/lib/termworld/terminal/controller.rb +74 -0
- data/lib/termworld/utils/api_client.rb +35 -0
- data/lib/termworld/utils/color.rb +20 -0
- data/lib/termworld/utils/option_parser_wrapper.rb +27 -0
- data/lib/termworld/{constants/version.rb → version.rb} +1 -1
- data/termworld.gemspec +3 -1
- metadata +46 -5
- data/lib/termworld/db/db.rb +0 -10
- data/lib/termworld/db/user.rb +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fdd1aafdb9205075fd1e3a25f335a02236fe901e455e9e36d173b8354a0b33b9
|
4
|
+
data.tar.gz: d953f8661dded33034572c8f3eb3100e38a1f77875f40a00ab77fe25064e6952
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 340f46ae87eec7fbc9482e0349e19fd980440d37eaf2e528fc613eeb806245be1c92518319ea0254af7d85fdc1d32191894cdb9ca8933b85a55d66b18d793b9d
|
7
|
+
data.tar.gz: 87fac115ba3651b040bc986deb7c06488fcde6c6cdf07e2511cd472675379eca09497e380de94ebf2671f170e548aa96ab954635d9264557566c8447236114aa
|
data/Gemfile.lock
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
termworld (0.
|
4
|
+
termworld (0.2.0)
|
5
|
+
httpclient
|
5
6
|
sequel
|
6
7
|
sqlite3
|
8
|
+
term_canvas (= 0.2.9)
|
7
9
|
thor
|
8
10
|
|
9
11
|
GEM
|
@@ -11,7 +13,9 @@ GEM
|
|
11
13
|
specs:
|
12
14
|
byebug (11.0.1)
|
13
15
|
coderay (1.1.2)
|
16
|
+
curses (1.3.1)
|
14
17
|
diff-lcs (1.3)
|
18
|
+
httpclient (2.8.3)
|
15
19
|
method_source (0.9.2)
|
16
20
|
pry (0.12.2)
|
17
21
|
coderay (~> 1.1.0)
|
@@ -24,17 +28,19 @@ GEM
|
|
24
28
|
rspec-core (~> 3.8.0)
|
25
29
|
rspec-expectations (~> 3.8.0)
|
26
30
|
rspec-mocks (~> 3.8.0)
|
27
|
-
rspec-core (3.8.
|
31
|
+
rspec-core (3.8.1)
|
28
32
|
rspec-support (~> 3.8.0)
|
29
33
|
rspec-expectations (3.8.4)
|
30
34
|
diff-lcs (>= 1.2.0, < 2.0)
|
31
35
|
rspec-support (~> 3.8.0)
|
32
|
-
rspec-mocks (3.8.
|
36
|
+
rspec-mocks (3.8.1)
|
33
37
|
diff-lcs (>= 1.2.0, < 2.0)
|
34
38
|
rspec-support (~> 3.8.0)
|
35
39
|
rspec-support (3.8.2)
|
36
40
|
sequel (5.21.0)
|
37
41
|
sqlite3 (1.4.1)
|
42
|
+
term_canvas (0.2.9)
|
43
|
+
curses
|
38
44
|
thor (0.20.3)
|
39
45
|
|
40
46
|
PLATFORMS
|
data/lib/termworld.rb
CHANGED
@@ -1,13 +1,23 @@
|
|
1
|
-
require "thor"
|
2
1
|
require "sequel"
|
3
2
|
|
4
|
-
require "termworld/
|
5
|
-
require "termworld/
|
3
|
+
require "termworld/config"
|
4
|
+
require "termworld/utils/color"
|
5
|
+
require "termworld/utils/api_client"
|
6
6
|
require "termworld/cli"
|
7
|
+
require "termworld/daemon"
|
7
8
|
|
8
9
|
module Termworld
|
9
10
|
def self.start
|
10
|
-
|
11
|
+
setup_termworld_directory
|
12
|
+
$api_client = Utils::ApiClient.new
|
13
|
+
$db = Sequel.sqlite(Termworld::DATABASE_NAME) if Daemon.new.alive?
|
11
14
|
CLI.start
|
12
15
|
end
|
16
|
+
|
17
|
+
def self.setup_termworld_directory
|
18
|
+
directory = Termworld::HOME_DIRECTORY_NAME
|
19
|
+
Dir::chdir(Dir::home)
|
20
|
+
Dir::mkdir(directory) unless Dir::exists?(directory)
|
21
|
+
Dir::chdir(directory)
|
22
|
+
end
|
13
23
|
end
|
data/lib/termworld/cli.rb
CHANGED
@@ -1,9 +1,53 @@
|
|
1
|
+
require "thor"
|
2
|
+
require "json"
|
3
|
+
|
4
|
+
require "termworld/db"
|
5
|
+
require "termworld/commands/account"
|
6
|
+
require "termworld/commands/daemon_operator"
|
7
|
+
require "termworld/commands/user"
|
8
|
+
require "termworld/commands/user_action"
|
9
|
+
require "termworld/credential"
|
10
|
+
require "termworld/utils/option_parser_wrapper"
|
11
|
+
|
1
12
|
module Termworld
|
2
13
|
class CLI < Thor
|
3
14
|
|
4
|
-
desc "
|
15
|
+
desc "login", "Login"
|
16
|
+
def login
|
17
|
+
Commands::Account.login
|
18
|
+
end
|
19
|
+
desc "logout", "Logout"
|
20
|
+
def logout
|
21
|
+
Commands::Account.logout
|
22
|
+
end
|
23
|
+
|
24
|
+
desc "start", "Start game client"
|
5
25
|
def start
|
6
|
-
|
26
|
+
Commands::DaemonOperator.start
|
27
|
+
end
|
28
|
+
desc "stop", "Stop game client"
|
29
|
+
def stop
|
30
|
+
Commands::DaemonOperator.stop
|
31
|
+
end
|
32
|
+
desc "status", "Check status"
|
33
|
+
def status
|
34
|
+
Commands::DaemonOperator.status
|
35
|
+
end
|
36
|
+
|
37
|
+
desc "user [COMMAND] <options>", "User actions"
|
38
|
+
subcommand "user", Commands::User
|
39
|
+
|
40
|
+
def method_missing(method, *arg, &block)
|
41
|
+
_method = method.to_s.split(?:)
|
42
|
+
begin
|
43
|
+
action_class = Object.const_get("Termworld::Commands::#{_method[0].capitalize}Action")
|
44
|
+
rescue
|
45
|
+
puts Utils::Color.reden "#{_method[0]} command not found"
|
46
|
+
return
|
47
|
+
end
|
48
|
+
action = action_class.new(_method[1])
|
49
|
+
return puts Utils::Color.reden "Enter any commands" if arg.empty?
|
50
|
+
action.send(arg[0], arg[1..-1])
|
7
51
|
end
|
8
52
|
end
|
9
53
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Termworld
|
2
|
+
module Commands
|
3
|
+
class Account
|
4
|
+
class << self
|
5
|
+
def login
|
6
|
+
credential = Credential.new
|
7
|
+
return puts Utils::Color.reden "Already logged in" if credential.logged_in?
|
8
|
+
print "email: "
|
9
|
+
email = $stdin.gets.chomp
|
10
|
+
res = $api_client.call(:post, '/token', {email: email})
|
11
|
+
return puts Utils::Color.reden "Invalid email" if res.code != 200
|
12
|
+
puts Utils::Color.greenen "Sent token to your email, please input below"
|
13
|
+
print "token: "
|
14
|
+
token = $stdin.gets.chomp
|
15
|
+
res = $api_client.call(:post, '/login', {email: email, token: token})
|
16
|
+
return puts Utils::Color.reden "Invalid token" if res.code != 200
|
17
|
+
File.write(Termworld::CREDENTIAL_FILE_NAME, "#{email}\n#{token}")
|
18
|
+
puts Utils::Color.greenen "Login successed!"
|
19
|
+
end
|
20
|
+
|
21
|
+
def logout
|
22
|
+
credential = Credential.new
|
23
|
+
return puts Utils::Color.reden "Not logged in" unless credential.logged_in?
|
24
|
+
email, token = Credential.get_credential
|
25
|
+
res = $api_client.call(:post, '/logout', {email: email, token: token})
|
26
|
+
return puts Utils::Color.reden "Logout failed" if res.code != 200
|
27
|
+
daemon = Daemon.new(:logout)
|
28
|
+
daemon.stop if daemon.alive?
|
29
|
+
File.delete(Termworld::CREDENTIAL_FILE_NAME) if File.exists?(Termworld::CREDENTIAL_FILE_NAME)
|
30
|
+
puts Utils::Color.greenen "Logout successed!"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Termworld
|
2
|
+
module Commands
|
3
|
+
class DaemonOperator
|
4
|
+
class << self
|
5
|
+
def start
|
6
|
+
credential = Credential.new
|
7
|
+
return puts credential.error_message unless credential.logged_in?
|
8
|
+
daemon = Daemon.new(:start)
|
9
|
+
return puts daemon.error_message if daemon.error_message
|
10
|
+
daemon.prepare
|
11
|
+
puts Utils::Color.greenen "Started!"
|
12
|
+
daemon.run
|
13
|
+
|
14
|
+
loop do
|
15
|
+
break unless daemon.alive?
|
16
|
+
sleep 1
|
17
|
+
end
|
18
|
+
daemon.stop
|
19
|
+
end
|
20
|
+
|
21
|
+
def stop
|
22
|
+
credential = Credential.new
|
23
|
+
daemon = Daemon.new(:stop)
|
24
|
+
unless credential.logged_in?
|
25
|
+
daemon.stop
|
26
|
+
return puts credential.error_message
|
27
|
+
end
|
28
|
+
if daemon.error_message
|
29
|
+
daemon.delete_files
|
30
|
+
return puts daemon.error_message
|
31
|
+
end
|
32
|
+
daemon.stop
|
33
|
+
puts Utils::Color.greenen "Stopped!"
|
34
|
+
end
|
35
|
+
|
36
|
+
def status
|
37
|
+
credential = Credential.new
|
38
|
+
return puts credential.error_message unless credential.logged_in?
|
39
|
+
daemon = Daemon.new(:status)
|
40
|
+
return puts daemon.error_message if daemon.error_message
|
41
|
+
if daemon.alive?
|
42
|
+
puts Utils::Color.bluen "Running!"
|
43
|
+
else
|
44
|
+
puts Utils::Color.bluen "Not running."
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Termworld
|
2
|
+
module Commands
|
3
|
+
class User < Thor
|
4
|
+
|
5
|
+
desc "create", "Create user"
|
6
|
+
def create(*options)
|
7
|
+
option_parser = Utils::OptionParserWrapper.new([
|
8
|
+
{option: ['-n', '--name [VALUE]', 'User name'], key: :name},
|
9
|
+
])
|
10
|
+
params = option_parser.parse!
|
11
|
+
return puts option_parser.error_message if option_parser.error_message
|
12
|
+
if params[:name].nil?
|
13
|
+
print "name: "
|
14
|
+
params[:name] = $stdin.gets.chomp
|
15
|
+
end
|
16
|
+
|
17
|
+
user = Models::User.new(params)
|
18
|
+
result = user.create
|
19
|
+
return puts Utils::Color.reden "Failed create user" unless result
|
20
|
+
puts Utils::Color.greenen "Successed create user!"
|
21
|
+
end
|
22
|
+
|
23
|
+
desc "list", "List users"
|
24
|
+
def list(*options)
|
25
|
+
option_parser = Utils::OptionParserWrapper.new([])
|
26
|
+
option_parser.parse!
|
27
|
+
return puts option_parser.error_message if option_parser.error_message
|
28
|
+
|
29
|
+
users = Models::User.all
|
30
|
+
if users.empty?
|
31
|
+
puts Utils::Color.bluen "No users. Please create user first"
|
32
|
+
puts "ex) $ termworld user create --name=<name>"
|
33
|
+
return
|
34
|
+
end
|
35
|
+
users.each do |user|
|
36
|
+
puts "id:#{user.id} #{user.name}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require "termworld/terminal/controller"
|
2
|
+
|
3
|
+
module Termworld
|
4
|
+
module Commands
|
5
|
+
class UserAction
|
6
|
+
def initialize(name)
|
7
|
+
@name = name
|
8
|
+
end
|
9
|
+
|
10
|
+
def wakeup(options)
|
11
|
+
res = $api_client.call_auth(:get, "/users/#{@name}")
|
12
|
+
puts Utils::Color.reden "Login required" if res.code == 401
|
13
|
+
puts Utils::Color.reden "User:#{@name} doesn't exsit" if res.code == 404
|
14
|
+
user = Models::User.new(JSON.parse(res.body, {symbolize_names: true})[:user])
|
15
|
+
user.initialize_position
|
16
|
+
user.save_local
|
17
|
+
if user.updated
|
18
|
+
puts Utils::Color.reden "User:#{user.name} already awake"
|
19
|
+
elsif user.created
|
20
|
+
puts Utils::Color.greenen "User:#{user.name} woke up!"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def sleep(options)
|
25
|
+
user = Models::User.new(name: @name)
|
26
|
+
user.delete_local(by: :name)
|
27
|
+
puts Utils::Color.greenen "User:#{user.name} slept!"
|
28
|
+
end
|
29
|
+
|
30
|
+
def terminal(options)
|
31
|
+
user = Models::User.new(name: @name)
|
32
|
+
if !user.bind_local_by_name
|
33
|
+
return puts Utils::Color.reden "User:#{@name} is not awake or doesn't exists"
|
34
|
+
end
|
35
|
+
terminal = Terminal::Controller.new(user)
|
36
|
+
terminal.run
|
37
|
+
end
|
38
|
+
|
39
|
+
def move(options)
|
40
|
+
if options.size != 1 || !%w(up down left right).include?(options.first)
|
41
|
+
puts Utils::Color.reden 'Direction must be only up, down, left or right'
|
42
|
+
puts "ex) $ termworld user:#{@name} move up"
|
43
|
+
return
|
44
|
+
end
|
45
|
+
direction = options.first.to_sym
|
46
|
+
user = Models::User.new(name: @name)
|
47
|
+
if !user.bind_local_by_name
|
48
|
+
return puts Utils::Color.reden "User:#{@name} is not awake or doesn't exists"
|
49
|
+
end
|
50
|
+
user.move(direction)
|
51
|
+
end
|
52
|
+
|
53
|
+
def method_missing(method, _)
|
54
|
+
puts Utils::Color.reden "#{method} command not found"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Termworld
|
2
|
+
class Credential
|
3
|
+
attr_reader :error_message
|
4
|
+
def logged_in?
|
5
|
+
if !File.exists?(Termworld::CREDENTIAL_FILE_NAME)
|
6
|
+
@error_message = Utils::Color.reden "Login required"
|
7
|
+
return false
|
8
|
+
end
|
9
|
+
email, token = Credential.get_credential
|
10
|
+
File.open(Termworld::CREDENTIAL_FILE_NAME) do |file|
|
11
|
+
email, token = file.read.split("\n")
|
12
|
+
end
|
13
|
+
res = $api_client.call(:post, '/login', {email: email, token: token})
|
14
|
+
if res.code != 200
|
15
|
+
@error_message = Utils::Color.reden "Wrong credential\nPlease login again"
|
16
|
+
return false
|
17
|
+
end
|
18
|
+
true
|
19
|
+
end
|
20
|
+
class << self
|
21
|
+
def get_credential
|
22
|
+
email, token = nil
|
23
|
+
begin
|
24
|
+
File.open(Termworld::CREDENTIAL_FILE_NAME) do |file|
|
25
|
+
email, token = file.read.split("\n")
|
26
|
+
end
|
27
|
+
rescue
|
28
|
+
return [nil, nil]
|
29
|
+
end
|
30
|
+
[email, token]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Termworld
|
2
|
+
class Daemon
|
3
|
+
attr_reader :error_message
|
4
|
+
def initialize(status = nil)
|
5
|
+
case status
|
6
|
+
when :start
|
7
|
+
@error_message = Utils::Color.reden "Already running" if alive?
|
8
|
+
when :stop
|
9
|
+
@error_message = Utils::Color.reden "Not running" unless alive?
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def prepare
|
14
|
+
delete_files
|
15
|
+
[:INT, :TERM].each do |key|
|
16
|
+
Signal.trap(key) {@killed = true}
|
17
|
+
end
|
18
|
+
DB.setup
|
19
|
+
Process.setproctitle(Termworld::PROCESS_NAME)
|
20
|
+
File.write(Termworld::DAEMON_FILE_NAME, nil)
|
21
|
+
end
|
22
|
+
|
23
|
+
def run
|
24
|
+
Process.daemon(true, false) # (nochdir, noclose)
|
25
|
+
end
|
26
|
+
|
27
|
+
def alive?
|
28
|
+
@killed.nil? && daemon_file_exists && daemon_process_exists
|
29
|
+
end
|
30
|
+
|
31
|
+
def stop
|
32
|
+
delete_files
|
33
|
+
kill_daemon_process
|
34
|
+
end
|
35
|
+
|
36
|
+
def delete_files
|
37
|
+
File.delete(Termworld::DAEMON_FILE_NAME) if File.exists?(Termworld::DAEMON_FILE_NAME)
|
38
|
+
File.delete(Termworld::DATABASE_NAME) if File.exists?(Termworld::DATABASE_NAME)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def kill_daemon_process
|
44
|
+
`ps aux | grep #{Termworld::PROCESS_NAME} | grep -v grep | awk '{print $2}' | xargs kill`
|
45
|
+
end
|
46
|
+
|
47
|
+
def daemon_file_exists
|
48
|
+
File.exists?(Termworld::DAEMON_FILE_NAME)
|
49
|
+
end
|
50
|
+
|
51
|
+
def daemon_process_exists
|
52
|
+
`ps aux | grep #{Termworld::PROCESS_NAME} | grep -v grep | wc -l`.delete(' ').to_i > 0
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/termworld/db.rb
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
module Termworld
|
2
|
+
module Models
|
3
|
+
class User
|
4
|
+
attr_reader :id, :name, :created, :updated, :positionx, :positiony
|
5
|
+
class << self
|
6
|
+
def create_table
|
7
|
+
$db.create_table :users do
|
8
|
+
primary_key :id
|
9
|
+
String :name
|
10
|
+
String :current_map_name
|
11
|
+
Integer :positionx
|
12
|
+
Integer :positiony
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def all
|
17
|
+
res = $api_client.call_auth(:get, '/users')
|
18
|
+
return [] if res.code != 200
|
19
|
+
JSON.parse(res.body, {symbolize_names: true})[:users].map do |user|
|
20
|
+
self.new(user)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def all_local
|
25
|
+
$db[:users].all.map do |user|
|
26
|
+
self.new(user)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def initialize(params)
|
32
|
+
params.each { |key, value| instance_variable_set("@#{key}", value) }
|
33
|
+
end
|
34
|
+
|
35
|
+
def bind_local_by_name
|
36
|
+
record = $db[:users].where(name: @name).first
|
37
|
+
return false if record.nil?
|
38
|
+
record.reject { |key, _| key == :name }.each { |key, value|
|
39
|
+
instance_variable_set("@#{key}", value)
|
40
|
+
}
|
41
|
+
true
|
42
|
+
end
|
43
|
+
|
44
|
+
def create
|
45
|
+
validate
|
46
|
+
return false unless @errors.empty?
|
47
|
+
res = $api_client.call_auth(:post, '/users', {name: @name})
|
48
|
+
return false if res.code != 201
|
49
|
+
true
|
50
|
+
end
|
51
|
+
def save_local
|
52
|
+
validate
|
53
|
+
return false unless @errors.empty?
|
54
|
+
if record = $db[:users].where(id: @id).first
|
55
|
+
@created, @updated = false, true
|
56
|
+
$db[:users].where(id: @id).update(attributes_without_id)
|
57
|
+
else
|
58
|
+
@created, @updated = true, false
|
59
|
+
$db[:users].insert(attributes)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
def delete_local(by: nil)
|
63
|
+
if by == :id
|
64
|
+
$db[:users].where(id: @id).delete
|
65
|
+
elsif by == :name
|
66
|
+
$db[:users].where(name: @name).delete
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def validate
|
71
|
+
@errors = []
|
72
|
+
if @name.nil? || @name.empty?
|
73
|
+
@errors << "Name is required"
|
74
|
+
elsif !@name.scan(/[^0-9a-z]+/i).empty?
|
75
|
+
@errors << "Name must be only alphanumeric"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def attributes
|
80
|
+
{
|
81
|
+
id: @id,
|
82
|
+
name: @name,
|
83
|
+
current_map_name: @current_map_name,
|
84
|
+
positionx: @positionx,
|
85
|
+
positiony: @positiony,
|
86
|
+
}
|
87
|
+
end
|
88
|
+
def attributes_without_id
|
89
|
+
attributes.reject { |k, _| k == :id }
|
90
|
+
end
|
91
|
+
|
92
|
+
def initialize_position
|
93
|
+
@current_map_name = 'town'
|
94
|
+
@positionx = 0
|
95
|
+
@positiony = 0
|
96
|
+
end
|
97
|
+
|
98
|
+
def move(direction)
|
99
|
+
supposed_position = {x: @positionx, y: @positiony}
|
100
|
+
case direction
|
101
|
+
when :up
|
102
|
+
supposed_position[:y] -= 1
|
103
|
+
when :down
|
104
|
+
supposed_position[:y] += 1
|
105
|
+
when :left
|
106
|
+
supposed_position[:x] -= 1
|
107
|
+
when :right
|
108
|
+
supposed_position[:x] += 1
|
109
|
+
else
|
110
|
+
return false
|
111
|
+
end
|
112
|
+
return false if supposed_position.any? { |_, v| v < 0 }
|
113
|
+
chip = current_map.get_chip(supposed_position)
|
114
|
+
return false if chip.nil? || !chip.movable
|
115
|
+
@positionx = supposed_position[:x]
|
116
|
+
@positiony = supposed_position[:y]
|
117
|
+
save_local
|
118
|
+
true
|
119
|
+
end
|
120
|
+
|
121
|
+
def current_map
|
122
|
+
@current_map ||= Object.const_get("Termworld::Resources::Maps::#{@current_map_name.capitalize}").new
|
123
|
+
@current_map
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require "term_canvas"
|
2
|
+
|
3
|
+
module Termworld
|
4
|
+
module Resources
|
5
|
+
class Chip
|
6
|
+
attr_reader :movable
|
7
|
+
def initialize(y: nil, x: nil, key:)
|
8
|
+
@y = y
|
9
|
+
@x = x
|
10
|
+
@key = key
|
11
|
+
data
|
12
|
+
end
|
13
|
+
|
14
|
+
def data
|
15
|
+
case @key
|
16
|
+
when "00"
|
17
|
+
@movable = true
|
18
|
+
{
|
19
|
+
background_color: {r: 300, g: 300, b: 300},
|
20
|
+
}
|
21
|
+
when "01"
|
22
|
+
@movable = false
|
23
|
+
{
|
24
|
+
background_color: {r: 0, g: 0, b: 0},
|
25
|
+
}
|
26
|
+
when "pl"
|
27
|
+
{
|
28
|
+
background_color: {r: 200, b: 200, g: 800},
|
29
|
+
}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def rect
|
34
|
+
TermCanvas::Rect.new(
|
35
|
+
x: @x, y: @y, width: 2, height: 1,
|
36
|
+
background_color: data[:background_color],
|
37
|
+
)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Termworld
|
2
|
+
module Resources
|
3
|
+
module Maps
|
4
|
+
class Town
|
5
|
+
def chip_numbers
|
6
|
+
return @chip_numbers_lines if @chip_numbers_lines
|
7
|
+
chip_numbers_lines = <<'EOS'
|
8
|
+
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
9
|
+
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
10
|
+
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
11
|
+
00 00 00 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
12
|
+
00 00 00 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
13
|
+
00 00 00 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
14
|
+
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
15
|
+
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
16
|
+
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
17
|
+
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
18
|
+
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
19
|
+
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
20
|
+
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
21
|
+
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
22
|
+
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
23
|
+
EOS
|
24
|
+
@chip_numbers_lines = chip_numbers_lines.lines(chomp: true)
|
25
|
+
.map { |chip_numbers_line| chip_numbers_line.split }
|
26
|
+
@chip_numbers_lines
|
27
|
+
end
|
28
|
+
def get_chip(y:, x:)
|
29
|
+
chip_number = chip_numbers[y] && chip_numbers[y][x]
|
30
|
+
return nil if chip_number.nil?
|
31
|
+
chip = Resources::Chip.new(y: y, x: x, key: chip_number)
|
32
|
+
chip
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require "term_canvas"
|
2
|
+
|
3
|
+
require "termworld/resources/chip"
|
4
|
+
require "termworld/resources/maps/town"
|
5
|
+
|
6
|
+
module Termworld
|
7
|
+
module Terminal
|
8
|
+
class Controller
|
9
|
+
def initialize(user)
|
10
|
+
@user = user
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
field = TermCanvas::Canvas.new(x: 0, y: 0, w: TermCanvas.width, h: TermCanvas.height)
|
15
|
+
|
16
|
+
map = Resources::Maps::Town.new
|
17
|
+
loop do
|
18
|
+
@user.bind_local_by_name
|
19
|
+
users = Models::User.all_local.reject { |user| user.name == @user.name }
|
20
|
+
|
21
|
+
break if handle_keys == :break
|
22
|
+
field.clear
|
23
|
+
|
24
|
+
height = field.height
|
25
|
+
width = field.width / 2 - 1
|
26
|
+
height.times do |y|
|
27
|
+
width.times do |x|
|
28
|
+
abs_position = {
|
29
|
+
x: @user.positionx - (width / 2) + x,
|
30
|
+
y: @user.positiony - (height / 2) + y,
|
31
|
+
}
|
32
|
+
user = users.find { |u|
|
33
|
+
u.positionx == abs_position[:x] && u.positiony == abs_position[:y]
|
34
|
+
}
|
35
|
+
if user
|
36
|
+
player_chip = Resources::Chip.new(x: x * 2 + 1, y: y, key: "pl")
|
37
|
+
field.rect(player_chip.rect)
|
38
|
+
next
|
39
|
+
end
|
40
|
+
next if abs_position.any? { |_, v| v < 0 }
|
41
|
+
next if (chip = map.get_chip(abs_position)).nil?
|
42
|
+
field.rect(chip.rect.position_override(x: x * 2 + 1, y: y))
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
player_chip = Resources::Chip.new(x: field.centerx, y: field.centery, key: "pl")
|
47
|
+
field.rect(player_chip.rect)
|
48
|
+
|
49
|
+
field.update
|
50
|
+
sleep 0.05
|
51
|
+
end
|
52
|
+
TermCanvas.close
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def handle_keys
|
58
|
+
key = TermCanvas.gets
|
59
|
+
case key
|
60
|
+
when ?q
|
61
|
+
return :break
|
62
|
+
when ?h
|
63
|
+
@user.move(:left)
|
64
|
+
when ?j
|
65
|
+
@user.move(:down)
|
66
|
+
when ?k
|
67
|
+
@user.move(:up)
|
68
|
+
when ?l
|
69
|
+
@user.move(:right)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "httpclient"
|
2
|
+
|
3
|
+
module Termworld
|
4
|
+
module Utils
|
5
|
+
class ApiClient
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@client = HTTPClient.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(method, url, params = nil)
|
12
|
+
if method == :get
|
13
|
+
res = @client.get(Termworld::API_ENDPOINT + url, query: params)
|
14
|
+
else
|
15
|
+
res = @client.send(method, Termworld::API_ENDPOINT + url, body: params)
|
16
|
+
end
|
17
|
+
res
|
18
|
+
end
|
19
|
+
|
20
|
+
def call_auth(method, url, params = nil)
|
21
|
+
email, token = Credential.get_credential
|
22
|
+
headers = {
|
23
|
+
'X-Termworld-Email': email,
|
24
|
+
'X-Termworld-Token': token,
|
25
|
+
}
|
26
|
+
if method == :get
|
27
|
+
res = @client.get(Termworld::API_ENDPOINT + url, query: params, header: headers)
|
28
|
+
else
|
29
|
+
res = @client.send(method, Termworld::API_ENDPOINT + url, body: params, header: headers)
|
30
|
+
end
|
31
|
+
res
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Termworld
|
2
|
+
module Utils
|
3
|
+
class Color
|
4
|
+
class << self
|
5
|
+
def reden(str)
|
6
|
+
"\e[31m#{str}\e[0m"
|
7
|
+
end
|
8
|
+
def greenen(str)
|
9
|
+
"\e[32m#{str}\e[0m"
|
10
|
+
end
|
11
|
+
def yellowen(str)
|
12
|
+
"\e[33m#{str}\e[0m"
|
13
|
+
end
|
14
|
+
def bluen(str)
|
15
|
+
"\e[34m#{str}\e[0m"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require "optparse"
|
2
|
+
|
3
|
+
module Termworld
|
4
|
+
module Utils
|
5
|
+
class OptionParserWrapper
|
6
|
+
attr_reader :error_message
|
7
|
+
def initialize(options)
|
8
|
+
@options = options
|
9
|
+
end
|
10
|
+
def parse!
|
11
|
+
params = {}
|
12
|
+
begin
|
13
|
+
OptionParser.new do |op|
|
14
|
+
@options.each do |option|
|
15
|
+
op.on(*option[:option]) { |v| params[option[:key]] = v }
|
16
|
+
end
|
17
|
+
op.parse!(params)
|
18
|
+
end
|
19
|
+
rescue OptionParser::InvalidOption => e
|
20
|
+
@error_message = Utils::Color.reden "Invalid options: #{e.args.first}"
|
21
|
+
return {}
|
22
|
+
end
|
23
|
+
params
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/termworld.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
lib = File.expand_path("../lib", __FILE__)
|
2
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
-
require "termworld"
|
3
|
+
require "termworld/version"
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = "termworld"
|
@@ -23,6 +23,8 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.add_dependency "thor"
|
24
24
|
spec.add_dependency "sequel"
|
25
25
|
spec.add_dependency "sqlite3"
|
26
|
+
spec.add_dependency "httpclient"
|
27
|
+
spec.add_dependency "term_canvas", "0.2.9"
|
26
28
|
|
27
29
|
spec.add_development_dependency "bundler", "~> 2.0"
|
28
30
|
spec.add_development_dependency "rake", "~> 10.0"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: termworld
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- kthatoto
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-06-
|
11
|
+
date: 2019-06-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -52,6 +52,34 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: httpclient
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: term_canvas
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.2.9
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.2.9
|
55
83
|
- !ruby/object:Gem::Dependency
|
56
84
|
name: bundler
|
57
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -132,9 +160,22 @@ files:
|
|
132
160
|
- exe/termworld
|
133
161
|
- lib/termworld.rb
|
134
162
|
- lib/termworld/cli.rb
|
135
|
-
- lib/termworld/
|
136
|
-
- lib/termworld/
|
137
|
-
- lib/termworld/
|
163
|
+
- lib/termworld/commands/account.rb
|
164
|
+
- lib/termworld/commands/daemon_operator.rb
|
165
|
+
- lib/termworld/commands/user.rb
|
166
|
+
- lib/termworld/commands/user_action.rb
|
167
|
+
- lib/termworld/config.rb
|
168
|
+
- lib/termworld/credential.rb
|
169
|
+
- lib/termworld/daemon.rb
|
170
|
+
- lib/termworld/db.rb
|
171
|
+
- lib/termworld/models/user.rb
|
172
|
+
- lib/termworld/resources/chip.rb
|
173
|
+
- lib/termworld/resources/maps/town.rb
|
174
|
+
- lib/termworld/terminal/controller.rb
|
175
|
+
- lib/termworld/utils/api_client.rb
|
176
|
+
- lib/termworld/utils/color.rb
|
177
|
+
- lib/termworld/utils/option_parser_wrapper.rb
|
178
|
+
- lib/termworld/version.rb
|
138
179
|
- termworld.gemspec
|
139
180
|
homepage: https://github.com/kthatoto/termworld
|
140
181
|
licenses:
|
data/lib/termworld/db/db.rb
DELETED