alchemist-core 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/Rakefile +1 -0
- data/alchemist-core.gemspec +24 -0
- data/lib/alchemist-core.rb +6 -0
- data/lib/alchemist-core/version.rb +5 -0
- data/lib/alchemist/EastAsianWidth.txt +24466 -0
- data/lib/alchemist/event_machine/client_protocol.rb +166 -0
- data/lib/alchemist/glyphs.rb +88 -0
- data/lib/alchemist/unicode_monospace.rb +53 -0
- metadata +55 -0
@@ -0,0 +1,166 @@
|
|
1
|
+
module Alchemist
|
2
|
+
module EventMachine
|
3
|
+
module ClientProtocol
|
4
|
+
# Clients should implement the various handle_* methods to
|
5
|
+
# take action in response to serve updates
|
6
|
+
#
|
7
|
+
def handle_welcome;end
|
8
|
+
def handle_hello;end
|
9
|
+
def handle_appeared;end
|
10
|
+
def handle_see(message);end
|
11
|
+
def handle_inventory(message);end
|
12
|
+
def handle_basics(message);end
|
13
|
+
def handle_compounds(message);end
|
14
|
+
def handle_messages(message);end
|
15
|
+
def handel_avatars(message);end
|
16
|
+
def handel_location(message);end
|
17
|
+
def handle_error(message);end
|
18
|
+
def handle_element(message);end
|
19
|
+
def handle_noelement(message);end
|
20
|
+
|
21
|
+
# Clients can call these methods to send commands to the server
|
22
|
+
#
|
23
|
+
def login(name)
|
24
|
+
send_data name
|
25
|
+
send_data "\n"
|
26
|
+
end
|
27
|
+
|
28
|
+
def appear
|
29
|
+
send_data "appear\n"
|
30
|
+
end
|
31
|
+
|
32
|
+
def request_location
|
33
|
+
send_data "location\n"
|
34
|
+
end
|
35
|
+
|
36
|
+
def look
|
37
|
+
send_data "look\n"
|
38
|
+
end
|
39
|
+
|
40
|
+
def read
|
41
|
+
send_data "read\n"
|
42
|
+
end
|
43
|
+
|
44
|
+
def request_inventory
|
45
|
+
send_data "inventory\n"
|
46
|
+
end
|
47
|
+
|
48
|
+
def request_basics
|
49
|
+
send_data "basics\n"
|
50
|
+
end
|
51
|
+
|
52
|
+
def request_compounds
|
53
|
+
send_data "compounds\n"
|
54
|
+
end
|
55
|
+
|
56
|
+
def who
|
57
|
+
send_data "who\n"
|
58
|
+
end
|
59
|
+
|
60
|
+
def move(direction)
|
61
|
+
send_data direction
|
62
|
+
send_data "\n"
|
63
|
+
end
|
64
|
+
|
65
|
+
def north
|
66
|
+
move 'north'
|
67
|
+
end
|
68
|
+
|
69
|
+
def south
|
70
|
+
move 'south'
|
71
|
+
end
|
72
|
+
|
73
|
+
def east
|
74
|
+
move 'east'
|
75
|
+
end
|
76
|
+
|
77
|
+
def west
|
78
|
+
move 'west'
|
79
|
+
end
|
80
|
+
|
81
|
+
def put(element)
|
82
|
+
send_data "put #{element}\n"
|
83
|
+
end
|
84
|
+
|
85
|
+
def create(element)
|
86
|
+
send_data "create #{element}\n"
|
87
|
+
end
|
88
|
+
|
89
|
+
def element(symbol, name)
|
90
|
+
send_data "element #{symbol} #{name}\n"
|
91
|
+
end
|
92
|
+
|
93
|
+
def describe(symbol)
|
94
|
+
send_data "describe #{symbol}\n"
|
95
|
+
end
|
96
|
+
|
97
|
+
def forge(ingred_1, ingred_2, result)
|
98
|
+
send_data "forge #{ingred_1} #{ingred_2} #{result}\n"
|
99
|
+
end
|
100
|
+
|
101
|
+
def formulate(ingred_1, ingred_2, result, name)
|
102
|
+
send_data "formulate #{ingred_1} #{ingred_2} #{result} #{name}\n"
|
103
|
+
end
|
104
|
+
|
105
|
+
def message(number, string)
|
106
|
+
send_data "message #{name} #{string}"
|
107
|
+
end
|
108
|
+
|
109
|
+
def take
|
110
|
+
send_data "take\n"
|
111
|
+
end
|
112
|
+
|
113
|
+
def receive_data(data)
|
114
|
+
@buffer ||= ''
|
115
|
+
@buffer << data
|
116
|
+
|
117
|
+
while @buffer =~ /^.*?\n/
|
118
|
+
line = $&
|
119
|
+
receive_line line
|
120
|
+
@buffer[0,line.length] = ''
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# Command framing and dispatch
|
125
|
+
#
|
126
|
+
def receive_line(line)
|
127
|
+
if @lines_to_read
|
128
|
+
@response << line
|
129
|
+
@lines_to_read -= 1
|
130
|
+
|
131
|
+
if @lines_to_read <= 0
|
132
|
+
@lines_to_read = nil
|
133
|
+
dispatch_command @command, @response
|
134
|
+
@command = nil
|
135
|
+
@response = nil
|
136
|
+
end
|
137
|
+
elsif line =~ /^(see|messages|avatars) (\d+)$/
|
138
|
+
@command = $1
|
139
|
+
@lines_to_read = $2.to_i
|
140
|
+
@response = ''
|
141
|
+
else
|
142
|
+
dispatch_command *line.split(' ',2)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def dispatch_command(command, data = nil)
|
147
|
+
case command
|
148
|
+
when "Welcome" then handle_welcome
|
149
|
+
when "hello" then handle_hello
|
150
|
+
when "appeared" then handle_appeared
|
151
|
+
when "see" then handle_see data
|
152
|
+
when "inventory" then handle_inventory data
|
153
|
+
when "basics" then handle_basics data
|
154
|
+
when "compounds" then handle_compounds data
|
155
|
+
when "error" then handle_error data
|
156
|
+
when "messages" then handle_messages data
|
157
|
+
when "avatars" then handle_avatars data
|
158
|
+
when "location" then handle_location data
|
159
|
+
when "element" then handle_element data
|
160
|
+
when "noelement" then handle_noelement data
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Alchemist
|
2
|
+
module Glyphs
|
3
|
+
def self.strings
|
4
|
+
@chars ||= codes.map {|i| [i].pack("U*") }
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.codes
|
8
|
+
@codes ||= code_blocks.flat_map(&:to_a)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.code_blocks
|
12
|
+
@code_blocks ||= [
|
13
|
+
0x0021..0x0024,
|
14
|
+
0x0026..0x007e,
|
15
|
+
0x0100..0x0220,
|
16
|
+
0x0222..0x0233,
|
17
|
+
0x0250..0x02ad,
|
18
|
+
0x0374..0x0375,
|
19
|
+
0x037e..0x037e,
|
20
|
+
0x0384..0x038a,
|
21
|
+
0x038c..0x038c,
|
22
|
+
0x038e..0x03a1,
|
23
|
+
0x03a3..0x03ce,
|
24
|
+
0x03d0..0x03f6,
|
25
|
+
0x0400..0x0482,
|
26
|
+
0x0488..0x04ac,
|
27
|
+
0x04af..0x04ce,
|
28
|
+
0x04d0..0x04f5,
|
29
|
+
0x04f8..0x04f9,
|
30
|
+
0x0500..0x050f,
|
31
|
+
0x20a0..0x20b1,
|
32
|
+
0x2100..0x213a,
|
33
|
+
0x213d..0x214b,
|
34
|
+
0x2153..0x2183,
|
35
|
+
0x2190..0x21ff,
|
36
|
+
0x2200..0x22ff,
|
37
|
+
0x2300..0x23ce,
|
38
|
+
0x2460..0x24fe,
|
39
|
+
0x2500..0x257f,
|
40
|
+
0x2580..0x259f,
|
41
|
+
0x2600..0x2613,
|
42
|
+
0x2616..0x2617,
|
43
|
+
0x2619..0x267d,
|
44
|
+
0x2680..0x2689,
|
45
|
+
0x2701..0x2704,
|
46
|
+
0x2706..0x2709,
|
47
|
+
0x270c..0x2727,
|
48
|
+
0x2729..0x274b,
|
49
|
+
0x274d..0x274d,
|
50
|
+
0x274f..0x2752,
|
51
|
+
0x2756..0x2756,
|
52
|
+
0x2758..0x275e,
|
53
|
+
0x2761..0x2794,
|
54
|
+
0x2798..0x27af,
|
55
|
+
0x27b1..0x27bd,
|
56
|
+
0x27f0..0x27ff,
|
57
|
+
0x2800..0x28ff,
|
58
|
+
0x2900..0x297f,
|
59
|
+
0x2980..0x29ff,
|
60
|
+
0x2a00..0x2aff,
|
61
|
+
0x2e80..0x2e99,
|
62
|
+
0x2e9b..0x2ef3,
|
63
|
+
0x2f00..0x2fd5,
|
64
|
+
0x2ff0..0x2ffb,
|
65
|
+
0x3001..0x3020,
|
66
|
+
0x3030..0x303f,
|
67
|
+
0x3041..0x3054,
|
68
|
+
0x305b..0x3096,
|
69
|
+
0x309d..0x30ff,
|
70
|
+
0x3105..0x312c,
|
71
|
+
0x3131..0x318e,
|
72
|
+
0x3190..0x319f,
|
73
|
+
0x31a0..0x31b7,
|
74
|
+
0x3200..0x321c,
|
75
|
+
0x3220..0x3244,
|
76
|
+
0x3251..0x327b,
|
77
|
+
0x327f..0x32cb,
|
78
|
+
0x32d0..0x32fe,
|
79
|
+
0x3300..0x3377,
|
80
|
+
0x337b..0x33dd,
|
81
|
+
0x33e0..0x33fe,
|
82
|
+
0xa000..0xa48c,
|
83
|
+
0x4e00..0x9fff,
|
84
|
+
]
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Alchemist
|
2
|
+
module UnicodeMonospace
|
3
|
+
module StringExtensions
|
4
|
+
def pad_to_unicode_monospace
|
5
|
+
unpack('U*').flat_map do |c|
|
6
|
+
next c if c == "\n".ord
|
7
|
+
|
8
|
+
case UnicodeMonospace.east_asian_width(c)
|
9
|
+
when /^F|W$/ then c
|
10
|
+
else [c, ' '.ord]
|
11
|
+
end
|
12
|
+
end.pack('U*')
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.east_asian_width(c)
|
17
|
+
east_asian_widths[c]
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.east_asian_widths
|
21
|
+
@east_asian_widths ||= build_east_asian_widths
|
22
|
+
end
|
23
|
+
|
24
|
+
DATA_FILE = File.join(File.dirname(__FILE__), 'EastAsianWidth.txt')
|
25
|
+
|
26
|
+
def self.build_east_asian_widths
|
27
|
+
widths = {}
|
28
|
+
File.open(DATA_FILE) do |io|
|
29
|
+
io.each_line do |line|
|
30
|
+
next if line =~ /^#/
|
31
|
+
code_spec, width, _ = line.split(/;|#/)
|
32
|
+
|
33
|
+
codes = if code_spec =~ /\.\./
|
34
|
+
min,max = code_spec.split '..'
|
35
|
+
(min.to_i(16)..max.to_i(16)).to_a
|
36
|
+
else
|
37
|
+
[code_spec.to_i(16)]
|
38
|
+
end
|
39
|
+
|
40
|
+
codes.each do |code|
|
41
|
+
widths[code] = width && width.strip
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
widths
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
String.class_eval do
|
52
|
+
include Alchemist::UnicodeMonospace::StringExtensions
|
53
|
+
end
|
metadata
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: alchemist-core
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- David Vollbracht
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-10-17 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: See http://github.com/flipstone/alchemist-server
|
15
|
+
email:
|
16
|
+
- david.vollbracht@gmail.com
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- .gitignore
|
22
|
+
- Gemfile
|
23
|
+
- Rakefile
|
24
|
+
- alchemist-core.gemspec
|
25
|
+
- lib/alchemist-core.rb
|
26
|
+
- lib/alchemist-core/version.rb
|
27
|
+
- lib/alchemist/EastAsianWidth.txt
|
28
|
+
- lib/alchemist/event_machine/client_protocol.rb
|
29
|
+
- lib/alchemist/glyphs.rb
|
30
|
+
- lib/alchemist/unicode_monospace.rb
|
31
|
+
homepage: http://github.com/flipstone/alchemist-core
|
32
|
+
licenses: []
|
33
|
+
post_install_message:
|
34
|
+
rdoc_options: []
|
35
|
+
require_paths:
|
36
|
+
- lib
|
37
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ! '>='
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '0'
|
43
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
44
|
+
none: false
|
45
|
+
requirements:
|
46
|
+
- - ! '>='
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
requirements: []
|
50
|
+
rubyforge_project: alchemist-core
|
51
|
+
rubygems_version: 1.8.6
|
52
|
+
signing_key:
|
53
|
+
specification_version: 3
|
54
|
+
summary: Alchemist snippets useful for most clients
|
55
|
+
test_files: []
|