craftbook-nbt 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.yardopts +5 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +420 -0
- data/Rakefile +5 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/craftbook-nbt.gemspec +34 -0
- data/lib/craftbook/nbt/byte_array_tag.rb +37 -0
- data/lib/craftbook/nbt/byte_tag.rb +61 -0
- data/lib/craftbook/nbt/compound_tag.rb +32 -0
- data/lib/craftbook/nbt/container_tag.rb +55 -0
- data/lib/craftbook/nbt/double_tag.rb +40 -0
- data/lib/craftbook/nbt/enumerable_tag.rb +106 -0
- data/lib/craftbook/nbt/float_tag.rb +35 -0
- data/lib/craftbook/nbt/int_array_tag.rb +38 -0
- data/lib/craftbook/nbt/int_tag.rb +49 -0
- data/lib/craftbook/nbt/list_tag.rb +69 -0
- data/lib/craftbook/nbt/long_array_tag.rb +37 -0
- data/lib/craftbook/nbt/long_tag.rb +50 -0
- data/lib/craftbook/nbt/short_tag.rb +48 -0
- data/lib/craftbook/nbt/snbt/lexer.rb +161 -0
- data/lib/craftbook/nbt/snbt/snbt.rb +121 -0
- data/lib/craftbook/nbt/snbt/snbt.rex +74 -0
- data/lib/craftbook/nbt/snbt.rb +2 -0
- data/lib/craftbook/nbt/string_tag.rb +40 -0
- data/lib/craftbook/nbt/tag.rb +197 -0
- data/lib/craftbook/nbt/tag_builder.rb +220 -0
- data/lib/craftbook/nbt/value_tag.rb +51 -0
- data/lib/craftbook/nbt/version.rb +10 -0
- data/lib/craftbook/nbt.rb +298 -0
- metadata +112 -0
@@ -0,0 +1,38 @@
|
|
1
|
+
|
2
|
+
module CraftBook
|
3
|
+
|
4
|
+
module NBT
|
5
|
+
##
|
6
|
+
# Represents a contiguous collection of signed 32-bit integers in the range of `-2147483648` to `2147483647`
|
7
|
+
# inclusive.
|
8
|
+
class IntArrayTag < EnumerableTag
|
9
|
+
|
10
|
+
##
|
11
|
+
# Creates a new instance of the {IntArrayTag} class.
|
12
|
+
#
|
13
|
+
# @param name [String,NilClass] The name of the tag, or `nil` when unnamed.
|
14
|
+
# @param values [Array<Numeric>] Zero or more values to add during initialization.
|
15
|
+
def initialize(name, *values)
|
16
|
+
super(TYPE_INT_ARRAY, name, *values)
|
17
|
+
end
|
18
|
+
|
19
|
+
##
|
20
|
+
# @return [Hash{Symbol => Object}] the hash-representation of this object.
|
21
|
+
def to_h
|
22
|
+
{ name: @name, type: @type, values: @values }
|
23
|
+
end
|
24
|
+
|
25
|
+
##
|
26
|
+
# @return [String] the NBT tag as a formatted and human-readable string.
|
27
|
+
def to_s
|
28
|
+
"TAG_Int_Array(#{@name ? "\"#{@name}\"" : 'None'}): #{size} #{size == 1 ? 'item' : 'items'}"
|
29
|
+
end
|
30
|
+
|
31
|
+
##
|
32
|
+
# @return [String] the NBT tag as an SNBT string.
|
33
|
+
def stringify
|
34
|
+
"#{snbt_prefix}[I;#{to_a.join(',')}]"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
|
2
|
+
module CraftBook
|
3
|
+
|
4
|
+
module NBT
|
5
|
+
|
6
|
+
##
|
7
|
+
# Represents a signed 32-bit integer in the range of `-2147483648` to `2147483647` inclusive.
|
8
|
+
class IntTag < ValueTag
|
9
|
+
|
10
|
+
##
|
11
|
+
# The minimum permissible value for this type.
|
12
|
+
MIN = -0x80000000
|
13
|
+
|
14
|
+
##
|
15
|
+
# The maximum permissible value for this type.
|
16
|
+
MAX = 0x7FFFFFFF
|
17
|
+
|
18
|
+
##
|
19
|
+
# @!attribute [rw] value
|
20
|
+
# @return [Numeric] the value of the tag.
|
21
|
+
|
22
|
+
##
|
23
|
+
# Creates a new instance of the {IntTag} class.
|
24
|
+
#
|
25
|
+
# @param name [String,NilClass] The name of the tag, or `nil` when unnamed.
|
26
|
+
# @param value [Numeric] The value of the tag.
|
27
|
+
def initialize(name, value = 0)
|
28
|
+
super(TYPE_INT, name, value)
|
29
|
+
end
|
30
|
+
|
31
|
+
def value=(value)
|
32
|
+
validate(value, MIN, MAX)
|
33
|
+
@value = Integer(value)
|
34
|
+
end
|
35
|
+
|
36
|
+
##
|
37
|
+
# @return [String] the NBT tag as a formatted and human-readable string.
|
38
|
+
def to_s
|
39
|
+
"TAG_Int(#{@name ? "\"#{@name}\"" : 'None'}): #{@value}"
|
40
|
+
end
|
41
|
+
|
42
|
+
##
|
43
|
+
# @return [String] the NBT tag as an SNBT string.
|
44
|
+
def stringify
|
45
|
+
"#{snbt_prefix}#{@value}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
|
2
|
+
module CraftBook
|
3
|
+
|
4
|
+
module NBT
|
5
|
+
|
6
|
+
##
|
7
|
+
# Represents a collection of **unnamed** tags of the same type.
|
8
|
+
class ListTag < ContainerTag
|
9
|
+
|
10
|
+
##
|
11
|
+
# @return [Integer] One of the `Tag::TYPE_*` constants indicating the primitive type of the child tags.
|
12
|
+
attr_reader :child_type
|
13
|
+
|
14
|
+
##
|
15
|
+
# Creates a new instance of the {ListTag} class.
|
16
|
+
#
|
17
|
+
# @param name [String,NilClass] The name of the tag, or `nil` when unnamed.
|
18
|
+
# @param child_type [Integer] One of the `Tag::TYPE_*` constants indicating the primitive type of the child tags.
|
19
|
+
# @param values [Array<Tag>] Zero or more values to add during initialization.
|
20
|
+
def initialize(name, child_type, *values)
|
21
|
+
super(TYPE_LIST, name, *values)
|
22
|
+
@child_type = Integer(child_type)
|
23
|
+
end
|
24
|
+
|
25
|
+
##
|
26
|
+
# @return [String] the NBT tag as a formatted and human-readable string.
|
27
|
+
def to_s
|
28
|
+
"TAG_List(#{@name ? "\"#{@name}\"" : 'None'}): #{size} #{size == 1 ? 'child' : 'children'}"
|
29
|
+
end
|
30
|
+
|
31
|
+
##
|
32
|
+
# @return [String] the NBT tag as an SNBT string.
|
33
|
+
def stringify
|
34
|
+
"#{snbt_prefix}[#{map(&:stringify).join(',')}]"
|
35
|
+
end
|
36
|
+
|
37
|
+
##
|
38
|
+
# @return [Hash{Symbol => Object}] the hash-representation of this object.
|
39
|
+
def to_h
|
40
|
+
children = @values.map do |obj|
|
41
|
+
child = obj.to_h
|
42
|
+
child.delete(:name)
|
43
|
+
child.delete(:type)
|
44
|
+
child
|
45
|
+
end
|
46
|
+
{ name: @name, type: @type, child_type: @child_type, values: children }
|
47
|
+
end
|
48
|
+
|
49
|
+
protected
|
50
|
+
|
51
|
+
def parse_hash(hash)
|
52
|
+
@values = []
|
53
|
+
values = hash[:values]
|
54
|
+
child_type = hash[:child_type]
|
55
|
+
raise(ParseError, "invalid array") unless values.is_a?(Array)
|
56
|
+
raise(ParseError, "invalid child type") unless !child_type.nil? & child_type.between?(TYPE_END, TYPE_LONG_ARRAY)
|
57
|
+
|
58
|
+
klass = Tag.class_from_type(child_type)
|
59
|
+
values.each do |value|
|
60
|
+
child = klass.allocate
|
61
|
+
child.instance_variable_set(:@name, nil)
|
62
|
+
child.instance_variable_set(:@type, child_type)
|
63
|
+
child.send(:parse_hash, value)
|
64
|
+
push(child)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
|
2
|
+
module CraftBook
|
3
|
+
module NBT
|
4
|
+
##
|
5
|
+
# cRepresents a contiguous collection of signed 64-bit integers in the range of `-9223372036854775808`
|
6
|
+
# and `9223372036854775807` inclusive.
|
7
|
+
class LongArrayTag < EnumerableTag
|
8
|
+
|
9
|
+
##
|
10
|
+
# Creates a new instance of the {LongArrayTag} class.
|
11
|
+
#
|
12
|
+
# @param name [String,NilClass] The name of the tag, or `nil` when unnamed.
|
13
|
+
# @param values [Array<Numeric>] Zero or more values to add during initialization.
|
14
|
+
def initialize(name, *values)
|
15
|
+
super(TYPE_LONG_ARRAY, name, *values)
|
16
|
+
end
|
17
|
+
|
18
|
+
##
|
19
|
+
# @return [Hash{Symbol => Object}] the hash-representation of this object.
|
20
|
+
def to_h
|
21
|
+
{ name: @name, type: @type, values: @values }
|
22
|
+
end
|
23
|
+
|
24
|
+
##
|
25
|
+
# @return [String] the NBT tag as a formatted and human-readable string.
|
26
|
+
def to_s
|
27
|
+
"TAG_Long_Array(#{@name ? "\"#{@name}\"" : 'None'}): #{size} #{size == 1 ? 'item' : 'items'}"
|
28
|
+
end
|
29
|
+
|
30
|
+
##
|
31
|
+
# @return [String] the NBT tag as an SNBT string.
|
32
|
+
def stringify
|
33
|
+
"#{snbt_prefix}[L;#{to_a.join(',')}]"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
|
2
|
+
module CraftBook
|
3
|
+
|
4
|
+
module NBT
|
5
|
+
|
6
|
+
##
|
7
|
+
# Represents a signed 64-bit integer in the range of `-9223372036854775808` and `9223372036854775807` inclusive.
|
8
|
+
class LongTag < ValueTag
|
9
|
+
|
10
|
+
##
|
11
|
+
# The minimum permissible value for this type.
|
12
|
+
MIN = -0x8000000000000000
|
13
|
+
|
14
|
+
##
|
15
|
+
# The maximum permissible value for this type.
|
16
|
+
MAX = 0x7FFFFFFFFFFFFFFF
|
17
|
+
|
18
|
+
##
|
19
|
+
# @!attribute [rw] value
|
20
|
+
# @return [Numeric] the value of the tag.
|
21
|
+
|
22
|
+
|
23
|
+
##
|
24
|
+
# Creates a new instance of the {LongTag} class.
|
25
|
+
#
|
26
|
+
# @param name [String,NilClass] The name of the tag, or `nil` when unnamed.
|
27
|
+
# @param value [Numeric] The value of the tag.
|
28
|
+
def initialize(name, value = 0)
|
29
|
+
super(TYPE_LONG, name, value)
|
30
|
+
end
|
31
|
+
|
32
|
+
def value=(value)
|
33
|
+
validate(value, MIN, MAX)
|
34
|
+
@value = Integer(value)
|
35
|
+
end
|
36
|
+
|
37
|
+
##
|
38
|
+
# @return [String] the NBT tag as a formatted and human-readable string.
|
39
|
+
def to_s
|
40
|
+
"TAG_Long(#{@name ? "\"#{@name}\"" : 'None'}): #{@value}"
|
41
|
+
end
|
42
|
+
|
43
|
+
##
|
44
|
+
# @return [String] the NBT tag as an SNBT string.
|
45
|
+
def stringify
|
46
|
+
"#{snbt_prefix}#{@value}L"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
|
2
|
+
module CraftBook
|
3
|
+
module NBT
|
4
|
+
|
5
|
+
##
|
6
|
+
# Represents a signed 16-bit integer in the range of `-32768` to `32767` inclusive.
|
7
|
+
class ShortTag < ValueTag
|
8
|
+
|
9
|
+
##
|
10
|
+
# The minimum permissible value for this type.
|
11
|
+
MIN = -0x8000
|
12
|
+
|
13
|
+
##
|
14
|
+
# The maximum permissible value for this type.
|
15
|
+
MAX = 0x7FFF
|
16
|
+
|
17
|
+
##
|
18
|
+
# @!attribute [rw] value
|
19
|
+
# @return [Numeric] the value of the tag.
|
20
|
+
|
21
|
+
##
|
22
|
+
# Creates a new instance of the {ShortTag} class.
|
23
|
+
#
|
24
|
+
# @param name [String,NilClass] The name of the tag, or `nil` when unnamed.
|
25
|
+
# @param value [Numeric] The value of the tag.
|
26
|
+
def initialize(name, value = 0)
|
27
|
+
super(TYPE_SHORT, name, value)
|
28
|
+
end
|
29
|
+
|
30
|
+
def value=(value)
|
31
|
+
validate(value, MIN, MAX)
|
32
|
+
@value = Integer(value)
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# @return [String] the NBT tag as a formatted and human-readable string.
|
37
|
+
def to_s
|
38
|
+
"TAG_Short(#{@name ? "\"#{@name}\"" : 'None'}): #{@value}"
|
39
|
+
end
|
40
|
+
|
41
|
+
##
|
42
|
+
# @return [String] the NBT tag as an SNBT string.
|
43
|
+
def stringify
|
44
|
+
"#{snbt_prefix}#{@value}S"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
#--
|
2
|
+
# DO NOT MODIFY!!!!
|
3
|
+
# This file is automatically generated by rex 1.0.7
|
4
|
+
# from lexical definition file "lib/craftbook/nbt/snbt/snbt.rex".
|
5
|
+
#++
|
6
|
+
|
7
|
+
require 'racc/parser'
|
8
|
+
module CraftBook
|
9
|
+
module NBT
|
10
|
+
class Tokenizer < Racc::Parser
|
11
|
+
require 'strscan'
|
12
|
+
|
13
|
+
class ScanError < StandardError ; end
|
14
|
+
|
15
|
+
attr_reader :lineno
|
16
|
+
attr_reader :filename
|
17
|
+
attr_accessor :state
|
18
|
+
|
19
|
+
def scan_setup(str)
|
20
|
+
@ss = StringScanner.new(str)
|
21
|
+
@lineno = 1
|
22
|
+
@state = nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def action
|
26
|
+
yield
|
27
|
+
end
|
28
|
+
|
29
|
+
def scan_str(str)
|
30
|
+
scan_setup(str)
|
31
|
+
do_parse
|
32
|
+
end
|
33
|
+
alias :scan :scan_str
|
34
|
+
|
35
|
+
def load_file( filename )
|
36
|
+
@filename = filename
|
37
|
+
File.open(filename, "r") do |f|
|
38
|
+
scan_setup(f.read)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def scan_file( filename )
|
43
|
+
load_file(filename)
|
44
|
+
do_parse
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
def next_token
|
49
|
+
return if @ss.eos?
|
50
|
+
|
51
|
+
# skips empty actions
|
52
|
+
until token = _next_token or @ss.eos?; end
|
53
|
+
token
|
54
|
+
end
|
55
|
+
|
56
|
+
def _next_token
|
57
|
+
text = @ss.peek(1)
|
58
|
+
@lineno += 1 if text == "\n"
|
59
|
+
token = case @state
|
60
|
+
when nil
|
61
|
+
case
|
62
|
+
when (text = @ss.scan(/\{[\s]*/))
|
63
|
+
action { [:COMPOUND_BEGIN] }
|
64
|
+
|
65
|
+
when (text = @ss.scan(/[\s]*\}/))
|
66
|
+
action { [:COMPOUND_END] }
|
67
|
+
|
68
|
+
when (text = @ss.scan(/".+?"(?=:)/))
|
69
|
+
action { [:IDENTIFIER, text.gsub!(/\A"|"\Z/, '') ] }
|
70
|
+
|
71
|
+
when (text = @ss.scan(/'.+?'(?=:)/))
|
72
|
+
action { [:IDENTIFIER, text.gsub!(/\A'|'\Z/, '') ] }
|
73
|
+
|
74
|
+
when (text = @ss.scan(/[A-Za-z0-9_-]+?(?=:)/))
|
75
|
+
action { [:IDENTIFIER, text] }
|
76
|
+
|
77
|
+
when (text = @ss.scan(/".*?"/))
|
78
|
+
action { [:STRING, text.gsub!(/\A"|"\Z/, '') ] }
|
79
|
+
|
80
|
+
when (text = @ss.scan(/'.*?'/))
|
81
|
+
action { [:STRING, text.gsub!(/\A'|'\Z/, '') ] }
|
82
|
+
|
83
|
+
when (text = @ss.scan(/[\s]*:[\s]*/))
|
84
|
+
action { [:SEPARATOR, text] }
|
85
|
+
|
86
|
+
when (text = @ss.scan(/[\s]*,[\s]*/))
|
87
|
+
action { [:COMMA, text] }
|
88
|
+
|
89
|
+
when (text = @ss.scan(/\[B;[\s]*?/))
|
90
|
+
action { [:BYTE_ARRAY, text] }
|
91
|
+
|
92
|
+
when (text = @ss.scan(/\[I;[\s]*?/))
|
93
|
+
action { [:INT_ARRAY, text] }
|
94
|
+
|
95
|
+
when (text = @ss.scan(/\[L;[\s]*?/))
|
96
|
+
action { [:LONG_ARRAY, text] }
|
97
|
+
|
98
|
+
when (text = @ss.scan(/\[[\s]*?/))
|
99
|
+
action { [:LIST_ARRAY, text] }
|
100
|
+
|
101
|
+
when (text = @ss.scan(/[\s]*\]/))
|
102
|
+
action { [:END_ARRAY, text] }
|
103
|
+
|
104
|
+
when (text = @ss.scan(/-?[0-9]*\.[0-9]+[Ff]/))
|
105
|
+
action { [:FLOAT, text.chop.to_f ] }
|
106
|
+
|
107
|
+
when (text = @ss.scan(/-?[0-9]*\.[0-9]+[Dd]?/))
|
108
|
+
action { [:DOUBLE, text.tr('Dd', '').to_f ] }
|
109
|
+
|
110
|
+
when (text = @ss.scan(/-?([0-9]+)[Bb]/))
|
111
|
+
action { [:BYTE, text.chop.to_i ] }
|
112
|
+
|
113
|
+
when (text = @ss.scan(/-?([0-9]+)[Ss]/))
|
114
|
+
action { [:SHORT, text.chop.to_i ] }
|
115
|
+
|
116
|
+
when (text = @ss.scan(/-?([0-9]+)[Ll]/))
|
117
|
+
action { [:LONG, text.chop.to_i ] }
|
118
|
+
|
119
|
+
when (text = @ss.scan(/-?([0-9]+)/))
|
120
|
+
action { [:INT, text.to_i ] }
|
121
|
+
|
122
|
+
when (text = @ss.scan(/[\s]+/))
|
123
|
+
action { [:WHITESPACE, text] }
|
124
|
+
|
125
|
+
when (text = @ss.scan(/[\S]+/))
|
126
|
+
action { [:STRING, text] }
|
127
|
+
|
128
|
+
when (text = @ss.scan(/./))
|
129
|
+
action { [:CHAR, text] }
|
130
|
+
|
131
|
+
|
132
|
+
else
|
133
|
+
text = @ss.string[@ss.pos .. -1]
|
134
|
+
raise ScanError, "can not match: '" + text + "'"
|
135
|
+
end # if
|
136
|
+
|
137
|
+
else
|
138
|
+
raise ScanError, "undefined state: '" + state.to_s + "'"
|
139
|
+
end # case state
|
140
|
+
token
|
141
|
+
end # def _next_token
|
142
|
+
|
143
|
+
Token = Struct.new(:type, :value)
|
144
|
+
def tokenize(code)
|
145
|
+
scan_setup(code)
|
146
|
+
if block_given?
|
147
|
+
while token = next_token
|
148
|
+
yield Token.new(*token)
|
149
|
+
end
|
150
|
+
return self
|
151
|
+
end
|
152
|
+
tokens = []
|
153
|
+
while token = next_token
|
154
|
+
tokens << Token.new(*token)
|
155
|
+
end
|
156
|
+
tokens
|
157
|
+
end
|
158
|
+
end # class
|
159
|
+
|
160
|
+
end
|
161
|
+
end
|