nbt_utils 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,2 @@
1
+ .bundle/
2
+ .idea/
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,18 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ nbt_utils (0.0.1)
5
+ bindata (~> 1.2)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ bindata (1.2.1)
11
+
12
+ PLATFORMS
13
+ ruby
14
+
15
+ DEPENDENCIES
16
+ bindata (~> 1.2)
17
+ bundler (>= 1.0.0)
18
+ nbt_utils!
@@ -0,0 +1,28 @@
1
+ nbt_utils
2
+ =========
3
+
4
+ Some classes for handling Minecraft .nbt files.
5
+
6
+ See http://www.minecraft.net/docs/NBT.txt for specification info, also mirred in the doc directory.
7
+
8
+ Installation
9
+ ============
10
+
11
+ Requires ruby 1.9 minimum. Tested with 1.9.2.
12
+
13
+ gem install nbt_utils
14
+
15
+ Use
16
+ ===
17
+
18
+ require 'nbt_utils'
19
+
20
+ @tag = NBTUtils::File.new.read('some_nbt_file.nbt')
21
+ puts @tag.to_s
22
+
23
+ Copyright
24
+ =========
25
+
26
+ Copyright (c) 2010 Michael Dungan, mpd@jesters-court.net, released under the MIT license.
27
+
28
+ The files `NBT.txt`, `test.nbt`, and `bigtest.nbt` in the `doc` directory are mirred from the Minecraft website.
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,149 @@
1
+ Named Binary Tag specification
2
+
3
+ NBT (Named Binary Tag) is a tag based binary format designed to carry large amounts of binary data with smaller amounts of additional data.
4
+ An NBT file consists of a single GZIPped Named Tag of type TAG_Compound.
5
+
6
+ A Named Tag has the following format:
7
+
8
+ byte tagType
9
+ TAG_String name
10
+ [payload]
11
+
12
+ The tagType is a single byte defining the contents of the payload of the tag.
13
+
14
+ The name is a descriptive name, and can be anything (eg "cat", "banana", "Hello World!"). It has nothing to do with the tagType.
15
+ The purpose for this name is to name tags so parsing is easier and can be made to only look for certain recognized tag names.
16
+ Exception: If tagType is TAG_End, the name is skipped and assumed to be "".
17
+
18
+ The [payload] varies by tagType.
19
+
20
+ Note that ONLY Named Tags carry the name and tagType data. Explicitly identified Tags (such as TAG_String above) only contains the payload.
21
+
22
+
23
+ The tag types and respective payloads are:
24
+
25
+ TYPE: 0 NAME: TAG_End
26
+ Payload: None.
27
+ Note: This tag is used to mark the end of a list.
28
+ Cannot be named! If type 0 appears where a Named Tag is expected, the name is assumed to be "".
29
+ (In other words, this Tag is always just a single 0 byte when named, and nothing in all other cases)
30
+
31
+ TYPE: 1 NAME: TAG_Byte
32
+ Payload: A single signed byte (8 bits)
33
+
34
+ TYPE: 2 NAME: TAG_Short
35
+ Payload: A signed short (16 bits, big endian)
36
+
37
+ TYPE: 3 NAME: TAG_Int
38
+ Payload: A signed short (32 bits, big endian)
39
+
40
+ TYPE: 4 NAME: TAG_Long
41
+ Payload: A signed long (64 bits, big endian)
42
+
43
+ TYPE: 5 NAME: TAG_Float
44
+ Payload: A floating point value (32 bits, big endian, IEEE 754-2008, binary32)
45
+
46
+ TYPE: 6 NAME: TAG_Double
47
+ Payload: A floating point value (64 bits, big endian, IEEE 754-2008, binary64)
48
+
49
+ TYPE: 7 NAME: TAG_Byte_Array
50
+ Payload: TAG_Int length
51
+ An array of bytes of unspecified format. The length of this array is <length> bytes
52
+
53
+ TYPE: 8 NAME: TAG_String
54
+ Payload: TAG_Short length
55
+ An array of bytes defining a string in UTF-8 format. The length of this array is <length> bytes
56
+
57
+ TYPE: 9 NAME: TAG_List
58
+ Payload: TAG_Byte tagId
59
+ TAG_Int length
60
+ A sequential list of Tags (not Named Tags), of type <typeId>. The length of this array is <length> Tags
61
+ Notes: All tags share the same type.
62
+
63
+ TYPE: 10 NAME: TAG_Compound
64
+ Payload: A sequential list of Named Tags. This array keeps going until a TAG_End is found.
65
+ TAG_End end
66
+ Notes: If there's a nested TAG_Compound within this tag, that one will also have a TAG_End, so simply reading until the next TAG_End will not work.
67
+ The names of the named tags have to be unique within each TAG_Compound
68
+ The order of the tags is not guaranteed.
69
+
70
+
71
+
72
+
73
+
74
+ Decoding example:
75
+ (Use http://www.minecraft.net/docs/test.nbt to test your implementation)
76
+
77
+
78
+ First we start by reading a Named Tag.
79
+ After unzipping the stream, the first byte is a 10. That means the tag is a TAG_Compound (as expected by the specification).
80
+
81
+ The next two bytes are 0 and 11, meaning the name string consists of 11 UTF-8 characters. In this case, they happen to be "hello world".
82
+ That means our root tag is named "hello world". We can now move on to the payload.
83
+
84
+ From the specification, we see that TAG_Compound consists of a series of Named Tags, so we read another byte to find the tagType.
85
+ It happens to be an 8. The name is 4 letters long, and happens to be "name". Type 8 is TAG_String, meaning we read another two bytes to get the length,
86
+ then read that many bytes to get the contents. In this case, it's "Bananrama".
87
+
88
+ So now we know the TAG_Compound contains a TAG_String named "name" with the content "Bananrama"
89
+
90
+ We move on to reading the next Named Tag, and get a 0. This is TAG_End, which always has an implied name of "". That means that the list of entries
91
+ in the TAG_Compound is over, and indeed all of the NBT file.
92
+
93
+ So we ended up with this:
94
+
95
+ TAG_Compound("hello world"): 1 entries
96
+ {
97
+ TAG_String("name"): Bananrama
98
+ }
99
+
100
+
101
+
102
+ For a slightly longer test, download http://www.minecraft.net/docs/bigtest.nbt
103
+ You should end up with this:
104
+
105
+ TAG_Compound("Level"): 11 entries
106
+ {
107
+ TAG_Short("shortTest"): 32767
108
+ TAG_Long("longTest"): 9223372036854775807
109
+ TAG_Float("floatTest"): 0.49823147
110
+ TAG_String("stringTest"): HELLO WORLD THIS IS A TEST STRING ���!
111
+ TAG_Int("intTest"): 2147483647
112
+ TAG_Compound("nested compound test"): 2 entries
113
+ {
114
+ TAG_Compound("ham"): 2 entries
115
+ {
116
+ TAG_String("name"): Hampus
117
+ TAG_Float("value"): 0.75
118
+ }
119
+ TAG_Compound("egg"): 2 entries
120
+ {
121
+ TAG_String("name"): Eggbert
122
+ TAG_Float("value"): 0.5
123
+ }
124
+ }
125
+ TAG_List("listTest (long)"): 5 entries of type TAG_Long
126
+ {
127
+ TAG_Long: 11
128
+ TAG_Long: 12
129
+ TAG_Long: 13
130
+ TAG_Long: 14
131
+ TAG_Long: 15
132
+ }
133
+ TAG_Byte("byteTest"): 127
134
+ TAG_List("listTest (compound)"): 2 entries of type TAG_Compound
135
+ {
136
+ TAG_Compound: 2 entries
137
+ {
138
+ TAG_String("name"): Compound tag #0
139
+ TAG_Long("created-on"): 1264099775885
140
+ }
141
+ TAG_Compound: 2 entries
142
+ {
143
+ TAG_String("name"): Compound tag #1
144
+ TAG_Long("created-on"): 1264099775885
145
+ }
146
+ }
147
+ TAG_Byte_Array("byteArrayTest (the first 1000 values of (n*n*255+n*7)%100, starting with n=0 (0, 62, 34, 16, 8, ...))"): [1000 bytes]
148
+ TAG_Double("doubleTest"): 0.4931287132182315
149
+ }
Binary file
Binary file
@@ -0,0 +1,19 @@
1
+ require 'zlib'
2
+ require 'bindata'
3
+
4
+ require File.expand_path('nbt_utils/tag/exceptions', File.dirname(__FILE__))
5
+
6
+ require File.expand_path('nbt_utils/file', File.dirname(__FILE__))
7
+ require File.expand_path('nbt_utils/tag_name', File.dirname(__FILE__))
8
+ require File.expand_path('nbt_utils/tag', File.dirname(__FILE__))
9
+ require File.expand_path('nbt_utils/tag/end', File.dirname(__FILE__))
10
+ require File.expand_path('nbt_utils/tag/byte', File.dirname(__FILE__))
11
+ require File.expand_path('nbt_utils/tag/short', File.dirname(__FILE__))
12
+ require File.expand_path('nbt_utils/tag/int', File.dirname(__FILE__))
13
+ require File.expand_path('nbt_utils/tag/long', File.dirname(__FILE__))
14
+ require File.expand_path('nbt_utils/tag/float', File.dirname(__FILE__))
15
+ require File.expand_path('nbt_utils/tag/double', File.dirname(__FILE__))
16
+ require File.expand_path('nbt_utils/tag/byte_array', File.dirname(__FILE__))
17
+ require File.expand_path('nbt_utils/tag/string', File.dirname(__FILE__))
18
+ require File.expand_path('nbt_utils/tag/list', File.dirname(__FILE__))
19
+ require File.expand_path('nbt_utils/tag/compound', File.dirname(__FILE__))
@@ -0,0 +1,25 @@
1
+ module NBTUtils
2
+ class File
3
+ def initialize(path = nil)
4
+ @path = path
5
+ end
6
+
7
+ def read(path = @path)
8
+ Zlib::GzipReader.open(path) do |f|
9
+ # ostensibly this will always be a single TAG_Compound, per the spec
10
+ last_byte = f.read(1).bytes.first
11
+ klass = NBTUtils::Tag.tag_type_to_class(last_byte)
12
+
13
+ @tag = klass.new(f, true)
14
+ end
15
+
16
+ @tag
17
+ end
18
+
19
+ def write(path = @path, tag = @tag)
20
+ Zlib::GzipWriter.open(path) do |gz|
21
+ gz.write tag.to_nbt_string
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,77 @@
1
+ module NBTUtils
2
+ module Tag
3
+ attr_reader :name
4
+ attr_reader :payload
5
+
6
+ def self.included(base)
7
+ base.extend ClassMethods
8
+ end
9
+
10
+ def initialize(io, named = true)
11
+ read_name(io) if named
12
+ @payload = self.class.payload_class.new.read(io)
13
+ end
14
+
15
+ def type_id
16
+ self.class.type_id
17
+ end
18
+
19
+ def binary_type_id
20
+ # I hope i'm doing this wrong.
21
+ byte = ::BinData::Int8be.new
22
+ byte.value = type_id
23
+ byte.to_binary_s
24
+ end
25
+
26
+ def to_s(indent = 0)
27
+ klass = self.class.to_s.split('::').last
28
+ (' ' * indent) + "TAG_#{klass}#{@name ? "(\"#{@name}\")" : ''}: #{@payload.value}"
29
+ end
30
+
31
+ def to_nbt_string(named = true)
32
+ result = named ? binary_type_id + name_to_nbt_string : ''
33
+ result + @payload.to_binary_s
34
+ end
35
+
36
+ def read_name(io)
37
+ @name = NBTUtils::TagName.new.read(io).data
38
+ end
39
+
40
+ def name_to_nbt_string
41
+ nm = NBTUtils::TagName.new
42
+ nm.data = @name
43
+ nm.to_binary_s
44
+ end
45
+
46
+ def tag_type_to_class(tag_type)
47
+ NBTUtils::Tag.tag_type_to_class(tag_type)
48
+ end
49
+
50
+ module ClassMethods
51
+ def type_id(new_id = nil)
52
+ if new_id
53
+ @type_id = new_id
54
+ NBTUtils::Tag.add_tag_type(new_id, self)
55
+ end
56
+
57
+ @type_id
58
+ end
59
+
60
+ def payload_class(new_klass = nil)
61
+ @payload_class = new_klass if new_klass
62
+ @payload_class
63
+ end
64
+ end
65
+
66
+ def self.tag_type_to_class(tag_type)
67
+ @tag_types[tag_type.to_i]
68
+ end
69
+
70
+ protected
71
+
72
+ def self.add_tag_type(index, tag_type)
73
+ @tag_types ||= []
74
+ @tag_types[index] = tag_type
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,10 @@
1
+ module NBTUtils
2
+ module Tag
3
+ class Byte # signed, per spec
4
+ include NBTUtils::Tag
5
+
6
+ type_id 1
7
+ payload_class ::BinData::Int8be
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,29 @@
1
+ module NBTUtils
2
+ module Tag
3
+ class ByteArray
4
+ include NBTUtils::Tag
5
+
6
+ type_id 7
7
+
8
+ def initialize(io, named = true)
9
+ read_name(io) if named
10
+
11
+ len = ::BinData::Int32be.new.read(io).value
12
+ # signedness of the bytes in the array is not defined in the spec.
13
+ @payload = ::BinData::Array.new(:type => :uint8, :initial_length => len).read(io)
14
+ end
15
+
16
+ def to_s(indent = 0)
17
+ (' ' * indent) + "TAG_Byte_Array#{@name ? "(\"#{@name}\")" : ''}: [#{@payload.length} bytes]"
18
+ end
19
+
20
+ def to_nbt_string(named = true)
21
+ result = named ? binary_type_id + name_to_nbt_string : ''
22
+ len = ::BinData::Int32be.new
23
+ len.value = @payload.length
24
+ result += len.to_binary_s
25
+ result + @payload.to_binary_s
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,56 @@
1
+ module NBTUtils
2
+ module Tag
3
+ class Compound
4
+ include NBTUtils::Tag
5
+
6
+ type_id 10
7
+
8
+ def initialize(io, named = true)
9
+ @payload = []
10
+ @tag_names = []
11
+ read_name(io) if named
12
+
13
+ until (last_byte = io.read(1).bytes.first) == NBTUtils::Tag::End.type_id
14
+ klass = tag_type_to_class(last_byte)
15
+ add_tag klass.new(io, true)
16
+ end
17
+ end
18
+
19
+ def to_s(indent = 0)
20
+ ret = (' ' * indent) + "TAG_Compound#{@name ? "(\"#{@name}\")" : ''}: #{@payload.length} entries\n"
21
+ ret += (' ' * indent) + "{\n"
22
+ @payload.each do |load|
23
+ ret += "#{load.to_s(indent + 2)}\n"
24
+ end
25
+ ret += (' ' * indent) + "}"
26
+
27
+ ret
28
+ end
29
+
30
+ def to_nbt_string(named = true)
31
+ result = named ? binary_type_id + name_to_nbt_string : ''
32
+
33
+ result = @payload.inject(result) do |r, load|
34
+ r + load.to_nbt_string(true)
35
+ end
36
+
37
+ result + NBTUtils::Tag::End.new(nil).to_nbt_string
38
+ end
39
+
40
+ def find_tag(name)
41
+ @payload.detect { |tag| tag.name =~ /#{name}/ }
42
+ end
43
+
44
+ def find_tags(name)
45
+ @payload.select { |tag| tag.name =~ /#{name}/ }
46
+ end
47
+
48
+ def add_tag(tag)
49
+ raise MissingCompoundPayloadTagNameError if tag.name.nil?
50
+ raise DuplicateCompoundPayloadTagNameError if @tag_names.include?(tag.name)
51
+ @tag_names << tag.name
52
+ @payload << tag
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,10 @@
1
+ module NBTUtils
2
+ module Tag
3
+ class Double # signed, per spec
4
+ include NBTUtils::Tag
5
+
6
+ type_id 6
7
+ payload_class ::BinData::DoubleBe
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,21 @@
1
+ module NBTUtils
2
+ module Tag
3
+ class End
4
+ include NBTUtils::Tag
5
+
6
+ type_id 0
7
+
8
+ def initialize(input, named = false)
9
+ @name = ''
10
+ end
11
+
12
+ def to_s(indent = 0)
13
+ ''
14
+ end
15
+
16
+ def to_nbt_string(named = false)
17
+ binary_type_id
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,2 @@
1
+ class DuplicateCompoundPayloadTagNameError < StandardError; end
2
+ class MissingCompoundPayloadTagNameError < StandardError; end
@@ -0,0 +1,10 @@
1
+ module NBTUtils
2
+ module Tag
3
+ class Float # signed, per spec
4
+ include NBTUtils::Tag
5
+
6
+ type_id 5
7
+ payload_class ::BinData::FloatBe
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module NBTUtils
2
+ module Tag
3
+ class Int # signed, per spec
4
+ include NBTUtils::Tag
5
+
6
+ type_id 3
7
+ payload_class ::BinData::Int32be
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,44 @@
1
+ module NBTUtils
2
+ module Tag
3
+ class List
4
+ include NBTUtils::Tag
5
+
6
+ type_id 9
7
+
8
+ def initialize(io, named = true)
9
+ @payload = []
10
+ read_name(io) if named
11
+
12
+ tag_id = io.read(1).bytes.first.to_i
13
+ @tag_type = NBTUtils::Tag.tag_type_to_class(tag_id)
14
+ len = ::BinData::Int32be.new.read(io).value
15
+ len.times do
16
+ @payload << @tag_type.new(io, false)
17
+ end
18
+ end
19
+
20
+ def to_s(indent = 0)
21
+ ret = (' ' * indent) + "TAG_List#{@name ? "(\"#{@name}\")" : ''}: #{@payload.length} entries of type TAG_#{@tag_type.to_s.split('::').last}\n"
22
+ ret += (' ' * indent) + "{\n"
23
+ @payload.each do |load|
24
+ ret += "#{load.to_s(indent + 2)}\n"
25
+ end
26
+ ret += (' ' * indent) + "}"
27
+ ret
28
+ end
29
+
30
+ def to_nbt_string(named = true)
31
+ result = named ? binary_type_id + name_to_nbt_string : ''
32
+ type =::BinData::Int8be.new
33
+ type.value = @tag_type.type_id
34
+ result += type.to_binary_s
35
+ len = ::BinData::Int32be.new
36
+ len.value = @payload.length
37
+ result += len.to_binary_s
38
+ @payload.inject(result) do |r, load|
39
+ r + load.to_nbt_string(false)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,10 @@
1
+ module NBTUtils
2
+ module Tag
3
+ class Long # signed, per spec
4
+ include NBTUtils::Tag
5
+
6
+ type_id 4
7
+ payload_class ::BinData::Int64be
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module NBTUtils
2
+ module Tag
3
+ class Short # signed, per spec
4
+ include NBTUtils::Tag
5
+
6
+ type_id 2
7
+ payload_class ::BinData::Int16be
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module NBTUtils
2
+ module Tag
3
+ class String
4
+ include NBTUtils::Tag
5
+
6
+ type_id 8
7
+ payload_class NBTUtils::TagName
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,13 @@
1
+ module NBTUtils
2
+ class TagName < ::BinData::Record
3
+ # Spec says this is a TAG_Short, which is signed. Staying strict
4
+ # though this may really be unsigned in practice.
5
+ int16be :len, :value => Proc.new { data.length }
6
+ string :data, :read_length => :len
7
+
8
+ # things break for some reason if you just call the string :value
9
+ def value
10
+ data
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ module NBTUtils
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path("../lib/nbt_utils/version", __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "nbt_utils"
6
+ s.version = NBTUtils::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = ['Michael Dungan']
9
+ s.email = ['mpd@jesters-court.net']
10
+ s.homepage = "http://rubygems.org/gems/nbt_utils"
11
+ s.summary = "Set of classes to read and write Minecraft .nbt files"
12
+ s.description = "Some classes to read and write Minecraft .nbt files. See http://www.minecraft.net/docs/NBT.txt for format description."
13
+
14
+ s.required_rubygems_version = ">= 1.3.6"
15
+
16
+ s.add_dependency "bindata", "~> 1.2"
17
+ s.add_development_dependency "bundler", ">= 1.0.0"
18
+
19
+ s.required_ruby_version = "~> 1.9"
20
+
21
+ s.files = `git ls-files`.split("\n")
22
+ s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
23
+ s.require_path = 'lib'
24
+ end
@@ -0,0 +1,31 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'bundler'
4
+ Bundler.require :default
5
+
6
+ require File.expand_path('./lib/nbt_utils', File.dirname(__FILE__))
7
+ require 'zlib'
8
+
9
+ @compound = nil
10
+
11
+ file = NBTUtils::File.new('doc/test.nbt')
12
+ @compound = file.read
13
+
14
+ puts @compound.to_s
15
+
16
+ #puts @compound.to_nbt_string
17
+ #Zlib::GzipWriter.open('lolwut.nbt') do |gz|
18
+ # gz.write @compound.to_nbt_string
19
+ #end
20
+
21
+ @compound = NBTUtils::File.new.read('doc/bigtest.nbt')
22
+ puts @compound.to_s
23
+
24
+ #puts @compound.to_nbt_string
25
+ #Zlib::GzipWriter.open('biglolwut.nbt') do |gz|
26
+ # gz.write @compound.to_nbt_string
27
+ #end
28
+
29
+ puts @compound.find_tag('Test')
30
+ #puts @compound.find_tags(/(?:byte|int)Test/)
31
+ #puts @compound.find_tags 'intasdf'
metadata ADDED
@@ -0,0 +1,122 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nbt_utils
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Michael Dungan
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-09-23 00:00:00 -07:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: bindata
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 1
30
+ - 2
31
+ version: "1.2"
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: bundler
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ segments:
43
+ - 1
44
+ - 0
45
+ - 0
46
+ version: 1.0.0
47
+ type: :development
48
+ version_requirements: *id002
49
+ description: Some classes to read and write Minecraft .nbt files. See http://www.minecraft.net/docs/NBT.txt for format description.
50
+ email:
51
+ - mpd@jesters-court.net
52
+ executables: []
53
+
54
+ extensions: []
55
+
56
+ extra_rdoc_files: []
57
+
58
+ files:
59
+ - .gitignore
60
+ - Gemfile
61
+ - Gemfile.lock
62
+ - README.md
63
+ - Rakefile
64
+ - doc/NBT.txt
65
+ - doc/bigtest.nbt
66
+ - doc/test.nbt
67
+ - lib/nbt_utils.rb
68
+ - lib/nbt_utils/file.rb
69
+ - lib/nbt_utils/tag.rb
70
+ - lib/nbt_utils/tag/byte.rb
71
+ - lib/nbt_utils/tag/byte_array.rb
72
+ - lib/nbt_utils/tag/compound.rb
73
+ - lib/nbt_utils/tag/double.rb
74
+ - lib/nbt_utils/tag/end.rb
75
+ - lib/nbt_utils/tag/exceptions.rb
76
+ - lib/nbt_utils/tag/float.rb
77
+ - lib/nbt_utils/tag/int.rb
78
+ - lib/nbt_utils/tag/list.rb
79
+ - lib/nbt_utils/tag/long.rb
80
+ - lib/nbt_utils/tag/short.rb
81
+ - lib/nbt_utils/tag/string.rb
82
+ - lib/nbt_utils/tag_name.rb
83
+ - lib/nbt_utils/version.rb
84
+ - nbt_utils.gemspec
85
+ - script.rb
86
+ has_rdoc: true
87
+ homepage: http://rubygems.org/gems/nbt_utils
88
+ licenses: []
89
+
90
+ post_install_message:
91
+ rdoc_options: []
92
+
93
+ require_paths:
94
+ - lib
95
+ required_ruby_version: !ruby/object:Gem::Requirement
96
+ none: false
97
+ requirements:
98
+ - - ~>
99
+ - !ruby/object:Gem::Version
100
+ segments:
101
+ - 1
102
+ - 9
103
+ version: "1.9"
104
+ required_rubygems_version: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ segments:
110
+ - 1
111
+ - 3
112
+ - 6
113
+ version: 1.3.6
114
+ requirements: []
115
+
116
+ rubyforge_project:
117
+ rubygems_version: 1.3.7
118
+ signing_key:
119
+ specification_version: 3
120
+ summary: Set of classes to read and write Minecraft .nbt files
121
+ test_files: []
122
+