craftbook-nbt 1.0.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 +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
|