Skip to content

Commit

Permalink
Merge pull request #48 from phit/feature/longarray
Browse files Browse the repository at this point in the history
Added support for Long Arrays
  • Loading branch information
jaquadro authored Nov 24, 2017
2 parents c0c448b + ba55e47 commit 6f2f8b1
Show file tree
Hide file tree
Showing 8 changed files with 294 additions and 1 deletion.
58 changes: 58 additions & 0 deletions SubstrateCS/Source/Nbt/NbtTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ private TagNode ReadValue (TagType type)

case TagType.TAG_INT_ARRAY:
return ReadIntArray();

case TagType.TAG_LONG_ARRAY:
return ReadLongArray();

case TagType.TAG_SHORT_ARRAY:
return ReadShortArray();
Expand Down Expand Up @@ -353,6 +356,35 @@ private TagNode ReadIntArray ()
return val;
}

private TagNode ReadLongArray ()
{
byte[] lenBytes = new byte[4];
_stream.Read(lenBytes, 0, 4);

if (BitConverter.IsLittleEndian) {
Array.Reverse(lenBytes);
}

int length = BitConverter.ToInt32(lenBytes, 0);
if (length < 0) {
throw new NBTException(NBTException.MSG_READ_NEG);
}

long[] data = new long[length];
byte[] buffer = new byte[8];
for (int i = 0; i < length; i++) {
_stream.Read(buffer, 0, 8);
if (BitConverter.IsLittleEndian) {
Array.Reverse(buffer);
}
data[i] = BitConverter.ToInt64(buffer, 0);
}

TagNodeLongArray val = new TagNodeLongArray(data);

return val;
}

private TagNode ReadShortArray ()
{
byte[] lenBytes = new byte[4];
Expand Down Expand Up @@ -455,6 +487,10 @@ private void WriteValue (TagNode val)
WriteIntArray(val.ToTagIntArray());
break;

case TagType.TAG_LONG_ARRAY:
WriteLongArray(val.ToTagLongArray());
break;

case TagType.TAG_SHORT_ARRAY:
WriteShortArray(val.ToTagShortArray());
break;
Expand Down Expand Up @@ -596,6 +632,28 @@ private void WriteIntArray (TagNodeIntArray val)
_stream.Write(data, 0, data.Length);
}

private void WriteLongArray (TagNodeLongArray val)
{
byte[] lenBytes = BitConverter.GetBytes(val.Length);

if (BitConverter.IsLittleEndian) {
Array.Reverse(lenBytes);
}

_stream.Write(lenBytes, 0, 4);

byte[] data = new byte[val.Length * 8];
for (int i = 0; i < val.Length; i++) {
byte[] buffer = BitConverter.GetBytes(val.Data[i]);
if (BitConverter.IsLittleEndian) {
Array.Reverse(buffer);
}
Array.Copy(buffer, 0, data, i * 8, 8);
}

_stream.Write(data, 0, data.Length);
}

private void WriteShortArray (TagNodeShortArray val)
{
byte[] lenBytes = BitConverter.GetBytes(val.Length);
Expand Down
22 changes: 22 additions & 0 deletions SubstrateCS/Source/Nbt/NbtVerifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,11 @@ private bool Verify (TagNode parent, TagNode tag, SchemaNode schema)
return VerifyIntArray(tag, intarray);
}

SchemaNodeLongArray longarray = schema as SchemaNodeLongArray;
if (longarray != null) {
return VerifyLongArray(tag, longarray);
}

SchemaNodeShortArray shortarray = schema as SchemaNodeShortArray;
if (shortarray != null) {
return VerifyShortArray(tag, shortarray);
Expand Down Expand Up @@ -264,6 +269,23 @@ private bool VerifyIntArray (TagNode tag, SchemaNodeIntArray schema)
return true;
}

private bool VerifyLongArray (TagNode tag, SchemaNodeLongArray schema)
{
TagNodeLongArray atag = tag as TagNodeLongArray;
if (atag == null) {
if (!OnInvalidTagType(new TagEventArgs(schema, tag))) {
return false;
}
}
if (schema.Length > 0 && atag.Length != schema.Length) {
if (!OnInvalidTagValue(new TagEventArgs(schema, tag))) {
return false;
}
}

return true;
}

private bool VerifyShortArray (TagNode tag, SchemaNodeShortArray schema)
{
TagNodeShortArray atag = tag as TagNodeShortArray;
Expand Down
83 changes: 83 additions & 0 deletions SubstrateCS/Source/Nbt/SchemaNodeLongArray.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace Substrate.Nbt
{
/// <summary>
/// A concrete <see cref="SchemaNode"/> representing a <see cref="TagNodeLongArray"/>.
/// </summary>
public sealed class SchemaNodeLongArray : SchemaNode
{
private int _length;

/// <summary>
/// Gets the expected length of the corresponding long array.
/// </summary>
public int Length
{
get { return _length; }
}

/// <summary>
/// Indicates whether there is an expected length of the corresponding int array.
/// </summary>
public bool HasExpectedLength
{
get { return _length > 0; }
}

/// <summary>
/// Constructs a new <see cref="SchemaNodeLongArray"/> representing a <see cref="TagNodeLongArray"/> named <paramref name="name"/>.
/// </summary>
/// <param name="name">The name of the corresponding <see cref="TagNodeIntArray"/>.</param>
public SchemaNodeLongArray (string name)
: base(name)
{
_length = 0;
}

/// <summary>
/// Constructs a new <see cref="SchemaNodeLongArray"/> with additional options.
/// </summary>
/// <param name="name">The name of the corresponding <see cref="TagNodeLongArray"/>.</param>
/// <param name="options">One or more option flags modifying the processing of this node.</param>
public SchemaNodeLongArray (string name, SchemaOptions options)
: base(name, options)
{
_length = 0;
}

/// <summary>
/// Constructs a new <see cref="SchemaNodeLongArray"/> representing a <see cref="TagNodeLongArray"/> named <paramref name="name"/> with expected length <paramref name="length"/>.
/// </summary>
/// <param name="name">The name of the corresponding <see cref="TagNodeIntArray"/>.</param>
/// <param name="length">The expected length of corresponding byte array.</param>
public SchemaNodeLongArray (string name, int length)
: base(name)
{
_length = length;
}

/// <summary>
/// Constructs a new <see cref="SchemaNodeLongArray"/> with additional options.
/// </summary>
/// <param name="name">The name of the corresponding <see cref="TagNodeLongArray"/>.</param>
/// <param name="length">The expected length of corresponding byte array.</param>
/// <param name="options">One or more option flags modifying the processing of this node.</param>
public SchemaNodeLongArray (string name, int length, SchemaOptions options)
: base(name, options)
{
_length = length;
}

/// <summary>
/// Constructs a default <see cref="TagNodeLongArray"/> satisfying the constraints of this node.
/// </summary>
/// <returns>A <see cref="TagNodeString"/> with a sensible default value.</returns>
public override TagNode BuildDefaultTree ()
{
return new TagNodeLongArray(new long[_length]);
}
}
}
9 changes: 9 additions & 0 deletions SubstrateCS/Source/Nbt/TagNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,15 @@ public virtual TagNodeIntArray ToTagIntArray ()
throw new InvalidCastException();
}

/// <summary>
/// Conver this node to a long array tag type if supported.
/// </summary>
/// <returns>A new long array node.</returns>
public virtual TagNodeLongArray ToTagLongArray ()
{
throw new InvalidCastException();
}

/// <summary>
/// Conver this node to a short array tag type if supported.
/// </summary>
Expand Down
112 changes: 112 additions & 0 deletions SubstrateCS/Source/Nbt/TagNodeLongArray.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace Substrate.Nbt
{
public sealed class TagNodeLongArray : TagNode
{
private long[] _data = null;

/// <summary>
/// Converts the node to itself.
/// </summary>
/// <returns>A reference to itself.</returns>
public override TagNodeLongArray ToTagLongArray ()
{
return this;
}

/// <summary>
/// Gets the tag type of the node.
/// </summary>
/// <returns>The TAG_LONG_ARRAY tag type.</returns>
public override TagType GetTagType ()
{
return TagType.TAG_LONG_ARRAY;
}

/// <summary>
/// Gets or sets an long array of tag data.
/// </summary>
public long[] Data
{
get { return _data; }
set { _data = value; }
}

/// <summary>
/// Gets the length of the stored byte array.
/// </summary>
public int Length
{
get { return _data.Length; }
}

/// <summary>
/// Constructs a new byte array node with a null data value.
/// </summary>
public TagNodeLongArray() { }

/// <summary>
/// Constructs a new byte array node.
/// </summary>
/// <param name="d">The value to set the node's tag data value.</param>
public TagNodeLongArray(long[] d)
{
_data = d;
}

/// <summary>
/// Makes a deep copy of the node.
/// </summary>
/// <returns>A new long array node representing the same data.</returns>
public override TagNode Copy ()
{
long[] arr = new long[_data.Length];
_data.CopyTo(arr, 0);

return new TagNodeLongArray(arr);
}

/// <summary>
/// Gets a string representation of the node's data.
/// </summary>
/// <returns>String representation of the node's data.</returns>
public override string ToString ()
{
return _data.ToString();
}

/// <summary>
/// Gets or sets a single long at the specified index.
/// </summary>
/// <param name="index">Valid index within stored long array.</param>
/// <returns>The long value at the given index of the stored byte array.</returns>
public long this[int index]
{
get { return _data[index]; }
set { _data[index] = value; }
}

/// <summary>
/// Converts a system long array to a long array node representing the same data.
/// </summary>
/// <param name="i">A long array.</param>
/// <returns>A new long array node containing the given value.</returns>
public static implicit operator TagNodeLongArray(long[] i)
{
return new TagNodeLongArray(i);
}

/// <summary>
/// Converts an long array node to a system long array representing the same data.
/// </summary>
/// <param name="i">An long array node.</param>
/// <returns>A system long array set to the node's data.</returns>
public static implicit operator long[] (TagNodeLongArray i)
{
return i._data;
}
}
}
7 changes: 6 additions & 1 deletion SubstrateCS/Source/Nbt/TagType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,15 @@ public enum TagType
/// </summary>
TAG_INT_ARRAY = 11,

/// <summary>
/// A tag containing an array of signed 64-bit values.
/// </summary>
TAG_LONG_ARRAY = 12,

/// <summary>
/// A tag containing an array of signed 16-bit values. NON-STANDARD NBT.
/// <remarks>This tag is included to support modded Minecraft and in anticipation that it may become standard in the future.</remarks>
/// </summary>
TAG_SHORT_ARRAY = 12,
TAG_SHORT_ARRAY = 13,
}
}
2 changes: 2 additions & 0 deletions SubstrateCS/Substrate (NET2).csproj
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@
<Compile Include="Source\Core\FusedDataArray.cs" />
<Compile Include="Source\Nbt\SchemaNodeShortArray.cs" />
<Compile Include="Source\Nbt\TagNodeShortArray.cs" />
<Compile Include="Source\Nbt\SchemaNodeLongArray.cs" />
<Compile Include="Source\Nbt\TagNodeLongArray.cs" />
<Compile Include="Source\RegionChunkManager.cs" />
<Compile Include="Source\BetaRegion.cs" />
<Compile Include="Source\BetaWorld.cs" />
Expand Down
2 changes: 2 additions & 0 deletions SubstrateCS/Substrate (NET4).csproj
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@
<Compile Include="Source\Nbt\SchemaNodeList.cs" />
<Compile Include="Source\Nbt\SchemaNodeScaler.cs" />
<Compile Include="Source\Nbt\SchemaNodeShortArray.cs" />
<Compile Include="Source\Nbt\SchemaNodeLongArray.cs" />
<Compile Include="Source\Nbt\TagNodeLongArray.cs" />
<Compile Include="Source\Nbt\SchemaNodeString.cs" />
<Compile Include="Source\Nbt\SchemaOptions.cs" />
<Compile Include="Source\Nbt\TagNode.cs" />
Expand Down

0 comments on commit 6f2f8b1

Please sign in to comment.