Port NBT impl from LibAC Dart
This commit is contained in:
parent
0a022634c1
commit
ad7b619706
55 changed files with 3226 additions and 2983 deletions
280
NBT/API/Tag.cs
Normal file
280
NBT/API/Tag.cs
Normal file
|
@ -0,0 +1,280 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace LibAC.NBT.API;
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
public abstract class Tag
|
||||
{
|
||||
private TagType _parentTagType = TagType.End;
|
||||
private Tag _parentTag;
|
||||
private string _key;
|
||||
|
||||
public byte GetType()
|
||||
{
|
||||
return (byte)GetTagType();
|
||||
}
|
||||
|
||||
public abstract TagType GetTagType();
|
||||
|
||||
public bool HasParent => _parentTag != null;
|
||||
|
||||
public void UpdateParent(Tag tag)
|
||||
{
|
||||
if (tag == null)
|
||||
{
|
||||
_parentTag = null;
|
||||
SetParentTagType(TagType.End);
|
||||
}
|
||||
else
|
||||
{
|
||||
_parentTag = tag;
|
||||
SetParentTagType(tag.GetTagType());
|
||||
}
|
||||
}
|
||||
|
||||
public Tag GetParent => _parentTag;
|
||||
|
||||
public TagType ParentTagType => _parentTagType;
|
||||
|
||||
public void SetParentTagType(TagType type)
|
||||
{
|
||||
_parentTagType = type;
|
||||
}
|
||||
|
||||
public abstract void WriteValue(ByteLayer data);
|
||||
public abstract void ReadValue(ByteLayer data);
|
||||
|
||||
public string GetKey()
|
||||
{
|
||||
return _key ?? string.Empty;
|
||||
}
|
||||
|
||||
public void SetKey(string key)
|
||||
{
|
||||
_key = key;
|
||||
}
|
||||
|
||||
public abstract dynamic GetValue();
|
||||
public abstract void SetValue(dynamic val);
|
||||
|
||||
public static Tag ReadNamedTag(ByteLayer data)
|
||||
{
|
||||
var type = data.ReadByte();
|
||||
if (type == 0)
|
||||
{
|
||||
return new EndTag();
|
||||
}
|
||||
else
|
||||
{
|
||||
Tag tag = MakeTagOfType(TagTypeExtensions.GetTagTypeFromByte(type));
|
||||
tag._key = data.ReadString();
|
||||
tag.ReadValue(data);
|
||||
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
|
||||
public static void WriteNamedTag(Tag tag, ByteLayer data)
|
||||
{
|
||||
data.WriteByte(tag.GetType());
|
||||
if (tag.GetType() != 0)
|
||||
{
|
||||
data.WriteString(tag.GetKey());
|
||||
tag.WriteValue(data);
|
||||
}
|
||||
}
|
||||
|
||||
public static void WriteStringifiedNamedTag(Tag tag, StringBuilder builder, int indents)
|
||||
{
|
||||
if (tag.GetType() != 0)
|
||||
{
|
||||
if (builder.Length > 0)
|
||||
{
|
||||
if (string.IsNullOrEmpty(tag.GetKey()))
|
||||
{
|
||||
builder.Append(new string('\t', indents));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tag.ShouldQuoteName())
|
||||
{
|
||||
builder.Append(new string('\t', indents) + $"\"{tag.GetKey()}\": ");
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.Append(new string('\t', indents) + $"{tag.GetKey()}: ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tag.WriteStringifiedValue(builder, indents + 1, false);
|
||||
}
|
||||
}
|
||||
|
||||
public static Tag ReadStringifiedNamedTag(StringReader stringReader)
|
||||
{
|
||||
string name = stringReader.Peek() == '{' || stringReader.Peek() == '[' ? "" : stringReader.ReadString();
|
||||
if (!string.IsNullOrEmpty(name)) stringReader.Expect(':');
|
||||
|
||||
TagType type = TagTypeExtensions.GetStringifiedTagType(stringReader);
|
||||
Tag tag = MakeTagOfType(type);
|
||||
tag._key = name;
|
||||
tag.ReadStringifiedValue(stringReader);
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
public bool ShouldQuoteName()
|
||||
{
|
||||
if (string.IsNullOrEmpty(GetKey()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
string letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
foreach (char c in GetKey())
|
||||
{
|
||||
if (!letters.Contains(c.ToString())) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ShouldQuote(string value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value)) return true;
|
||||
|
||||
string letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
foreach (char c in value)
|
||||
{
|
||||
if (!letters.Contains(c.ToString())) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public abstract void WriteStringifiedValue(StringBuilder builder, int indent, bool isList);
|
||||
public abstract void ReadStringifiedValue(StringReader reader);
|
||||
|
||||
public bool Equals(object obj)
|
||||
{
|
||||
if (obj == null || !(obj is Tag)) return false;
|
||||
|
||||
var tag = (Tag)obj;
|
||||
if (tag.GetType() != GetType()) return false;
|
||||
if (GetKey() != tag.GetKey()) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static Tag MakeTagOfType(TagType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case TagType.Byte: return new ByteTag();
|
||||
case TagType.ByteArray: return new ByteArrayTag();
|
||||
case TagType.Compound: return new CompoundTag();
|
||||
case TagType.Double: return new DoubleTag();
|
||||
case TagType.End: return new EndTag();
|
||||
case TagType.Short: return new ShortTag();
|
||||
case TagType.Int: return new IntTag();
|
||||
case TagType.Long: return new LongTag();
|
||||
case TagType.Float: return new FloatTag();
|
||||
case TagType.IntArray: return new IntArrayTag();
|
||||
case TagType.LongArray: return new LongArrayTag();
|
||||
case TagType.List: return new ListTag();
|
||||
case TagType.String: return new StringTag();
|
||||
default: throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
public int AsByte()
|
||||
{
|
||||
if (this is ByteTag byteTag) return byteTag.Value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public List<byte> AsByteArray()
|
||||
{
|
||||
if (this is ByteArrayTag byteArrayTag) return byteArrayTag.Value;
|
||||
return new List<byte>();
|
||||
}
|
||||
|
||||
public double AsDouble()
|
||||
{
|
||||
if (this is DoubleTag doubleTag) return doubleTag.Value;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
public double AsFloat()
|
||||
{
|
||||
if (this is FloatTag floatTag) return floatTag.value;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
public List<int> AsIntArray()
|
||||
{
|
||||
if (this is IntArrayTag intArrayTag) return intArrayTag.Value;
|
||||
return new List<int>();
|
||||
}
|
||||
|
||||
public int AsInt()
|
||||
{
|
||||
if (this is IntTag intTag) return intTag.Value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public List<long> AsLongArray()
|
||||
{
|
||||
if (this is LongArrayTag longArrayTag) return longArrayTag.value;
|
||||
return new List<long>();
|
||||
}
|
||||
|
||||
public long AsLong()
|
||||
{
|
||||
if (this is LongTag longTag) return longTag.value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public short AsShort()
|
||||
{
|
||||
if (this is ShortTag shortTag) return shortTag.value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public string AsString()
|
||||
{
|
||||
if (this is StringTag stringTag) return stringTag.value;
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public CompoundTag AsCompoundTag()
|
||||
{
|
||||
return this is CompoundTag compoundTag ? compoundTag : new CompoundTag();
|
||||
}
|
||||
|
||||
public abstract void PrettyPrint(int indent, bool recurse);
|
||||
|
||||
public static string GetCanonicalName(TagType type)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
TagType.String => "TAG_String",
|
||||
TagType.List => "TAG_List",
|
||||
TagType.LongArray => "TAG_LongArray",
|
||||
TagType.Long => "TAG_Long",
|
||||
TagType.IntArray => "TAG_IntArray",
|
||||
TagType.Int => "TAG_Int",
|
||||
TagType.Compound => "TAG_Compound",
|
||||
TagType.ByteArray => "TAG_ByteArray",
|
||||
TagType.Byte => "TAG_Byte",
|
||||
TagType.Double => "TAG_Double",
|
||||
TagType.Float => "TAG_Float",
|
||||
TagType.Short => "TAG_Short",
|
||||
TagType.End => "TAG_End",
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue