Compare commits
10 Commits
bcd41b37f0
...
ca2d7f49e1
| Author | SHA1 | Date |
|---|---|---|
|
|
ca2d7f49e1 | |
|
|
760c75cadc | |
|
|
bd80810e2c | |
|
|
ad4dcf63f3 | |
|
|
7f020e1c51 | |
|
|
d6e0075b74 | |
|
|
964821d1fc | |
|
|
190b694668 | |
|
|
82399f243b | |
|
|
f22ae236b6 |
|
|
@ -0,0 +1,28 @@
|
|||
# This workflow will build a .NET project
|
||||
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net
|
||||
|
||||
name: .NET
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
pull_request:
|
||||
branches: [ "master" ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 9.0.x
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore
|
||||
- name: Build
|
||||
run: dotnet build --no-restore
|
||||
- name: Test
|
||||
run: dotnet test --no-build --verbosity normal
|
||||
|
|
@ -1,75 +1,16 @@
|
|||
# Contributor Covenant Code of Conduct
|
||||
# This is Just a Code Repo Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
This is:
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, gender identity and expression, level of experience,
|
||||
nationality, personal appearance, race, religion, or sexual identity and
|
||||
orientation.
|
||||
* A public repository to share code and track issues
|
||||
|
||||
## Our Standards
|
||||
This is NOT:
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
* Your priest
|
||||
* Your parent
|
||||
* Your moral guide
|
||||
* Anything that has any authority over you whatsoever
|
||||
|
||||
* Use commonsense, which by definition does not need explanation
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Not feeling compelled to try and use a "group" you choose to identify with to elevate your position
|
||||
As such, it pure silliness to issue a "code of conduct", but alas, GitHub really wants us to put them here. Conduct yourself however you see fit to conduct yourself, the same as you do in every other interaction in life.
|
||||
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Pushing your political ideologies onto others
|
||||
* Trolling, insulting/derogatory comments, and personal attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at efreed09@gmail.com. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
If the very idea that a code repository can be considered "unsafe", then I strongly suggest you not interact with it. I don't even know what that means, nor do I wish to adopt the modern-era madness of pretending I do. I can assure you of one thing: in all of history, a code repository has never hurt anyone. I don't believe that this one will be an exception.
|
||||
10
README.md
10
README.md
|
|
@ -16,15 +16,7 @@ A CLS-compliant implementation of the Named Binary Tag (NBT) specifications (Jav
|
|||
* **Ease-of-use:** An intuitive API design, following the style and conventions of the .NET runtime, with full Intellisense for every member: Spend more time being productive and less time digging through documentation.
|
||||
* **Performance:** Leverages the power of modern C# language features, including `Span` with `stackalloc`, `MemoryMarshal`, etc. This allows for a type-safe way to reinterpret raw buffers without pointers or making unnecessary copies of buffers, a common pitfall with serialization in type-safe languages.
|
||||
* **Concurrency:** Includes standard async/await concurrency patterns for reading and writing.
|
||||
* **Cross-platform and cross-language support:** Fully CLR compliant and build against .NET Standard 2.1, allowing support for any CLR language (i.e. C#, Visual Basic, F#, etc.) for the following runtime versions or greater:
|
||||
* .NET Standard 2.1
|
||||
* .NET 5.0
|
||||
* .NET Core 3.0
|
||||
* Mono 6.4
|
||||
* Xamarin.iOS 12.16
|
||||
* Xamarin.Mac 5.16
|
||||
* Xamarin.Android 10.0
|
||||
* Unity 2021.2.0b6
|
||||
* **Cross-language support:** Fully CLR compliant and build against .NET 7.0, allowing support for any CLR language (i.e. C#, Visual Basic, F#, etc.) with the supported runtime version.
|
||||
* **Callbacks:** Can subscribe to events that get a callback as the parser steps through a stream to get immediate feedback without waiting for document completion. This allows subscribers to even parse the payload themselves and handle the event entirely.
|
||||
* **String NBT**: Supports both generating and parsing arbitrary SNBT strings.
|
||||
|
||||
|
|
|
|||
|
|
@ -175,8 +175,8 @@ public static class NbtFile
|
|||
return compression switch
|
||||
{
|
||||
CompressionType.None => stream,
|
||||
CompressionType.GZip => new GZipStream(stream, CompressionMode.Decompress, false),
|
||||
CompressionType.ZLib => new ZLibStream(stream, CompressionMode.Decompress),
|
||||
CompressionType.GZip => new BufferedStream(new GZipStream(stream, CompressionMode.Decompress, false)),
|
||||
CompressionType.ZLib => new BufferedStream(new ZLibStream(stream, CompressionMode.Decompress)),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(compression), compression, null)
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
../README.md
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Data;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text;
|
||||
|
||||
|
|
@ -44,12 +45,26 @@ internal ref struct Scanner
|
|||
SyntaxError("Unexpected end of input.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (skipWhitespace && char.IsWhiteSpace(Current))
|
||||
//Debug.Write(Current);
|
||||
if (skipWhitespace && string.IsNullOrWhiteSpace(Current.ToString()))
|
||||
goto ReadChar;
|
||||
return true;
|
||||
}
|
||||
public bool MoveNext(bool fail)
|
||||
{
|
||||
ReadChar:
|
||||
Position++;
|
||||
if (Position >= Source.Length)
|
||||
{
|
||||
if (fail)
|
||||
SyntaxError("Unexpected end of input.");
|
||||
return false;
|
||||
}
|
||||
//Debug.Write(Current);
|
||||
if (char.IsWhiteSpace(Current) && Current != '\n')
|
||||
goto ReadChar;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void AssertChar(char c)
|
||||
{
|
||||
if (Current != c)
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
using JetBrains.Annotations;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace SharpNBT.SNBT;
|
||||
|
||||
|
|
@ -83,6 +84,12 @@ public static class StringNbt
|
|||
|
||||
while (!scanner.IsEndOfInput)
|
||||
{
|
||||
// Closing brace encountered, break loop.
|
||||
if (scanner.Current == '}')
|
||||
{
|
||||
// scanner.MoveNext(true, false);
|
||||
break;
|
||||
}
|
||||
// Read the name of the tag
|
||||
var childName = ParseString(ref scanner, out _);
|
||||
|
||||
|
|
@ -94,22 +101,22 @@ public static class StringNbt
|
|||
scanner.MoveNext(true, true);
|
||||
var tag = ParseTag(childName, ref scanner);
|
||||
result.Add(tag);
|
||||
scanner.MoveNext(true, true);
|
||||
scanner.MoveNext( true);
|
||||
|
||||
// Comma encountered, read another tag.
|
||||
if (scanner.Current == ',')
|
||||
if (IsLineEnd(scanner.Current))
|
||||
{
|
||||
scanner.MoveNext(true, true);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Closing brace encountered, break loop.
|
||||
if (scanner.Current == '}')
|
||||
{
|
||||
// scanner.MoveNext(true, false);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Invalid character
|
||||
scanner.SyntaxError($"Expected ',' or '}}', got '{scanner.Current}'.");
|
||||
}
|
||||
|
|
@ -309,24 +316,28 @@ public static class StringNbt
|
|||
var list = new List<Tag>();
|
||||
while (true)
|
||||
{
|
||||
var child = ParseTag(null, ref scanner);
|
||||
list.Add(child);
|
||||
|
||||
scanner.MoveNext(true, true);
|
||||
|
||||
// Comma encountered, read another tag.
|
||||
if (scanner.Current == ',')
|
||||
{
|
||||
scanner.MoveNext(true, true);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Closing brace encountered, break loop.
|
||||
if (scanner.Current == ']')
|
||||
{
|
||||
break;
|
||||
}
|
||||
var child = ParseTag(null, ref scanner);
|
||||
list.Add(child);
|
||||
|
||||
scanner.MoveNext(true);
|
||||
|
||||
// Comma encountered, read another tag.
|
||||
if (IsLineEnd(scanner.Current))
|
||||
{
|
||||
scanner.MoveNext(true, true);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (scanner.Current == ']')
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Invalid character
|
||||
scanner.SyntaxError($"Expected ',' or ']', got '{scanner.Current}'.");
|
||||
}
|
||||
|
|
@ -349,7 +360,7 @@ public static class StringNbt
|
|||
var c = char.ToLowerInvariant(scanner.Current);
|
||||
if (c == ']')
|
||||
break;
|
||||
if (char.IsNumber(c) || c == ',')
|
||||
if (char.IsNumber(c) ||c == ',' || c == '-')
|
||||
continue;
|
||||
if (c is not ('b' or 'l'))
|
||||
scanner.SyntaxError($"Invalid character '{c}' in integer array.");
|
||||
|
|
@ -366,5 +377,62 @@ public static class StringNbt
|
|||
}
|
||||
|
||||
private const StringSplitOptions SplitOpts = StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries;
|
||||
private static readonly char[] SplitSeparators = new[] { ',', 'b', 'B', 'l', 'L' };
|
||||
private static readonly char[] SplitSeparators = new[] { ',', 'b', 'B', 'l', 'L','\n' };
|
||||
|
||||
private static bool IsLineEnd(char c)
|
||||
{
|
||||
return c == ',' || c == '\n' || c == '\r';
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Saves a <see cref="CompoundTag"/> to a file in SNBT format.
|
||||
/// </summary>
|
||||
/// <param name="tag">The <see cref="CompoundTag"/> to save.</param>
|
||||
/// <param name="filePath">The path to the file where the SNBT data will be saved.</param>
|
||||
/// <param name="prettyPrint">Whether to format the output in a human-readable format.</param>
|
||||
/// <exception cref="ArgumentNullException">When <paramref name="tag"/> is <see langword="null"/>.</exception>
|
||||
/// <exception cref="IOException">When there is an error writing to the file.</exception>
|
||||
public static void SaveToFile(CompoundTag tag, string filePath, bool prettyPrint = false)
|
||||
{
|
||||
if (tag == null)
|
||||
throw new ArgumentNullException(nameof(tag));
|
||||
|
||||
string snbt = prettyPrint ? tag.PrettyPrinted() : tag.Stringify(true);
|
||||
|
||||
try
|
||||
{
|
||||
File.WriteAllText(filePath, snbt, Encoding.UTF8);
|
||||
}
|
||||
catch (Exception ex) when (ex is IOException or UnauthorizedAccessException or DirectoryNotFoundException)
|
||||
{
|
||||
throw new IOException($"Failed to write SNBT to file '{filePath}': {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves a <see cref="CompoundTag"/> to a file in SNBT format.
|
||||
/// </summary>
|
||||
/// <param name="tag">The <see cref="CompoundTag"/> to save.</param>
|
||||
/// <param name="stream">The stream where the SNBT data will be written.</param>
|
||||
/// <param name="prettyPrint">Whether to format the output in a human-readable format.</param>
|
||||
/// <param name="encoding">The text encoding to use. Defaults to UTF-8 if null.</param>
|
||||
/// <exception cref="ArgumentNullException">When <paramref name="tag"/> or <paramref name="stream"/> is <see langword="null"/>.</exception>
|
||||
/// <exception cref="IOException">When there is an error writing to the stream.</exception>
|
||||
public static void SaveToStream(CompoundTag tag, Stream stream, bool prettyPrint = false, Encoding? encoding = null)
|
||||
{
|
||||
if (tag == null)
|
||||
throw new ArgumentNullException(nameof(tag));
|
||||
if (stream == null)
|
||||
throw new ArgumentNullException(nameof(stream));
|
||||
if (!stream.CanWrite)
|
||||
throw new IOException("Cannot write to the specified stream.");
|
||||
|
||||
string snbt = prettyPrint ? tag.PrettyPrinted() : tag.Stringify(true);
|
||||
encoding ??= Encoding.UTF8;
|
||||
|
||||
using var writer = new StreamWriter(stream, encoding, leaveOpen: true);
|
||||
writer.Write(snbt);
|
||||
writer.Flush();
|
||||
}
|
||||
}
|
||||
|
|
@ -13,11 +13,13 @@
|
|||
<PackageTags>nbt;named binary tag;minecraft;serialization;java;bedrock;pocket edition;varint;varlong;zlib</PackageTags>
|
||||
<Copyright>Copyright © Eric Freed 2021</Copyright>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<PackageVersion>1.2.0</PackageVersion>
|
||||
<AssemblyVersion>1.2.0</AssemblyVersion>
|
||||
<FileVersion>1.2.0</FileVersion>
|
||||
<PackageVersion>1.3.1</PackageVersion>
|
||||
<AssemblyVersion>1.3.1</AssemblyVersion>
|
||||
<FileVersion>1.3.1</FileVersion>
|
||||
<LangVersion>latestmajor</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<PackageReleaseNotes>Hotfix to correct bug with Stringified output.</PackageReleaseNotes>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
|
|
@ -25,6 +27,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="README.md" Pack="true" Visible="true" PackagePath="/"/>
|
||||
<None Include="icon.png" Pack="true" Visible="true" PackagePath="" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -437,8 +437,7 @@ public class TagBuilder
|
|||
/// <summary>Closes this context.</summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Console.WriteLine(Tag);
|
||||
closeHandler.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -306,7 +306,10 @@ public class TagWriter : TagIO
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void WriteTypeAndName(Tag tag)
|
||||
{
|
||||
if (tag.Parent is ListTag || string.IsNullOrEmpty(tag.Name))
|
||||
if (tag.Parent is ListTag)
|
||||
return;
|
||||
|
||||
if (string.IsNullOrEmpty(tag.Name) && !(tag is CompoundTag && tag.Parent is null))
|
||||
return;
|
||||
|
||||
BaseStream.WriteByte((byte) tag.Type);
|
||||
|
|
@ -384,4 +387,4 @@ public class TagWriter : TagIO
|
|||
else
|
||||
BaseStream.Write(GetBytes(count), 0, sizeof(int));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,10 +82,12 @@ public abstract class ArrayTag<T> : Tag, IReadOnlyList<T> where T : unmanaged, I
|
|||
/// <returns>A reference to the first value in the underlying array.</returns>
|
||||
public ref T GetPinnableReference() => ref array[0] ;
|
||||
|
||||
private protected string Stringify(char prefix, char? suffix)
|
||||
private protected string Stringify(bool named, char prefix, char? suffix)
|
||||
{
|
||||
var sb = new StringBuilder(32 + array.Length * 4);
|
||||
sb.Append($"{StringifyName}:[{prefix};");
|
||||
if (named)
|
||||
sb.Append($"{StringifyName}:");
|
||||
sb.Append($"[{prefix};");
|
||||
|
||||
for (var i = 0; i < array.Length; i++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -49,12 +49,12 @@ public class BoolTag : Tag
|
|||
/// <param name="tag">The tag to convert.</param>
|
||||
/// <returns>The tag represented as a <see cref="byte"/>.</returns>
|
||||
public static implicit operator bool(BoolTag tag) => tag.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <i>string</i> representation of this NBT tag (SNBT).
|
||||
/// </summary>
|
||||
/// <returns>This NBT tag in SNBT format.</returns>
|
||||
/// <seealso href="https://minecraft.fandom.com/wiki/NBT_format#SNBT_format"/>
|
||||
public override string Stringify() => $"{StringifyName}:{(Value ? "true" : "false")}";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Stringify(bool named = true)
|
||||
{
|
||||
var value = Value ? "true" : "false";
|
||||
return named ? $"{StringifyName}:{value}" : value;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -75,11 +75,7 @@ public class ByteArrayTag : ArrayTag<byte>
|
|||
var word = Count == 1 ? Strings.WordElement : Strings.WordElements;
|
||||
return $"TAG_Byte_Array({PrettyName}): [{Count} {word}]";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <i>string</i> representation of this NBT tag (SNBT).
|
||||
/// </summary>
|
||||
/// <returns>This NBT tag in SNBT format.</returns>
|
||||
/// <seealso href="https://minecraft.fandom.com/wiki/NBT_format#SNBT_format"/>
|
||||
public override string Stringify() => Stringify('B', 'b');
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Stringify(bool named = true) => Stringify(named, 'B', 'b');
|
||||
}
|
||||
|
|
@ -132,10 +132,6 @@ public class ByteTag : NumericTag<byte>
|
|||
[CLSCompliant(false)]
|
||||
public static implicit operator sbyte(ByteTag tag) => unchecked((sbyte)tag.Value);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <i>string</i> representation of this NBT tag (SNBT).
|
||||
/// </summary>
|
||||
/// <returns>This NBT tag in SNBT format.</returns>
|
||||
/// <seealso href="https://minecraft.fandom.com/wiki/NBT_format#SNBT_format"/>
|
||||
public override string Stringify() => $"{StringifyName}:{Value}B";
|
||||
/// <inheritdoc />
|
||||
public override string Stringify(bool named = true) => named ? $"{StringifyName}:{Value}B" : $"{Value}B";
|
||||
}
|
||||
|
|
@ -242,36 +242,35 @@ public class CompoundTag : Tag, IDictionary<string, Tag>, ICollection<Tag>
|
|||
buffer.AppendLine(space + "}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <i>string</i> representation of this NBT tag (SNBT).
|
||||
/// </summary>
|
||||
/// <returns>This NBT tag in SNBT format.</returns>
|
||||
/// <seealso href="https://minecraft.fandom.com/wiki/NBT_format#SNBT_format"/>
|
||||
public override string Stringify()
|
||||
/// <inheritdoc />
|
||||
public override string Stringify(bool named = true)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.Append($"{StringifyName}:{{");
|
||||
if (named)
|
||||
sb.Append($"{StringifyName}:");
|
||||
sb.Append('{');
|
||||
|
||||
var i = 0;
|
||||
foreach (var value in dict.Values)
|
||||
{
|
||||
if (i++ > 0)
|
||||
sb.Append(',');
|
||||
sb.Append(value);
|
||||
sb.Append(value.Stringify(true));
|
||||
}
|
||||
sb.Append('}');
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <i>string</i> representation of this NBT tag (SNBT).
|
||||
/// </summary>
|
||||
/// <param name="topLevel">Flag indicating if this is the top-level tag that should be wrapped in braces.</param>
|
||||
/// <param name="named">Flag indicating if the name of the NBT should be written.</param>
|
||||
/// <returns>This NBT tag in SNBT format.</returns>
|
||||
/// <seealso href="https://minecraft.fandom.com/wiki/NBT_format#SNBT_format"/>
|
||||
public string Stringify(bool topLevel)
|
||||
public string Stringify(bool topLevel, bool named)
|
||||
{
|
||||
var str = Stringify();
|
||||
var str = Stringify(named);
|
||||
return topLevel ? $"{{{str}}}" : str;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,10 +41,6 @@ public class DoubleTag : NumericTag<double>
|
|||
/// <returns>The tag represented as a <see cref="double"/>.</returns>
|
||||
public static implicit operator double(DoubleTag tag) => tag.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <i>string</i> representation of this NBT tag (SNBT).
|
||||
/// </summary>
|
||||
/// <returns>This NBT tag in SNBT format.</returns>
|
||||
/// <seealso href="https://minecraft.fandom.com/wiki/NBT_format#SNBT_format"/>
|
||||
public override string Stringify() => $"{StringifyName}:{Value:0.0}D";
|
||||
/// <inheritdoc />
|
||||
public override string Stringify(bool named = true) => named ? $"{StringifyName}:{Value}D" : $"{Value}D";
|
||||
}
|
||||
|
|
@ -31,11 +31,7 @@ public sealed class EndTag : Tag
|
|||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <i>string</i> representation of this NBT tag (SNBT).
|
||||
/// </summary>
|
||||
/// <returns>This NBT tag in SNBT format.</returns>
|
||||
/// <seealso href="https://minecraft.fandom.com/wiki/NBT_format#SNBT_format"/>
|
||||
public override string Stringify() => string.Empty;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Stringify(bool named = true) => string.Empty;
|
||||
}
|
||||
|
|
@ -41,10 +41,6 @@ public class FloatTag : NumericTag<float>
|
|||
/// <returns>The tag represented as a <see cref="float"/>.</returns>
|
||||
public static implicit operator float(FloatTag tag) => tag.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <i>string</i> representation of this NBT tag (SNBT).
|
||||
/// </summary>
|
||||
/// <returns>This NBT tag in SNBT format.</returns>
|
||||
/// <seealso href="https://minecraft.fandom.com/wiki/NBT_format#SNBT_format"/>
|
||||
public override string Stringify() => $"{StringifyName}:{Value:0.0}F";
|
||||
/// <inheritdoc />
|
||||
public override string Stringify(bool named = true) => named ? $"{StringifyName}:{Value}F" : $"{Value}F";
|
||||
}
|
||||
|
|
@ -73,11 +73,7 @@ public class IntArrayTag : ArrayTag<int>
|
|||
var word = Count == 1 ? Strings.WordElement : Strings.WordElements;
|
||||
return $"TAG_Int_Array({PrettyName}): [{Count} {word}]";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <i>string</i> representation of this NBT tag (SNBT).
|
||||
/// </summary>
|
||||
/// <returns>This NBT tag in SNBT format.</returns>
|
||||
/// <seealso href="https://minecraft.fandom.com/wiki/NBT_format#SNBT_format"/>
|
||||
public override string Stringify() => Stringify('I', null);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Stringify(bool named = true) => Stringify(named, 'I', null);
|
||||
}
|
||||
|
|
@ -69,10 +69,6 @@ public class IntTag : NumericTag<int>
|
|||
[CLSCompliant(false)]
|
||||
public static implicit operator uint(IntTag tag) => unchecked((uint)tag.Value);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <i>string</i> representation of this NBT tag (SNBT).
|
||||
/// </summary>
|
||||
/// <returns>This NBT tag in SNBT format.</returns>
|
||||
/// <seealso href="https://minecraft.fandom.com/wiki/NBT_format#SNBT_format"/>
|
||||
public override string Stringify() => $"{StringifyName}:{Value}";
|
||||
/// <inheritdoc />
|
||||
public override string Stringify(bool named = true) => named ? $"{StringifyName}:{Value}" : $"{Value}";
|
||||
}
|
||||
|
|
@ -175,15 +175,21 @@ public class ListTag : Tag, IList<Tag>
|
|||
/// </summary>
|
||||
/// <returns>This NBT tag in SNBT format.</returns>
|
||||
/// <seealso href="https://minecraft.fandom.com/wiki/NBT_format#SNBT_format"/>
|
||||
public override string Stringify()
|
||||
public override string Stringify(bool named = true)
|
||||
{
|
||||
var strings = new string[Count];
|
||||
for (var i = 0; i < strings.Length; i++)
|
||||
strings[i] = this[i].Stringify();
|
||||
|
||||
// TODO: Use StringBuilder
|
||||
|
||||
return $"{StringifyName}:[{string.Join(',', strings)}]";
|
||||
var sb = new StringBuilder();
|
||||
if (named)
|
||||
sb.Append($"{StringifyName}:");
|
||||
|
||||
sb.Append('[');
|
||||
for (var i = 0; i < list.Count; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
sb.Append(',');
|
||||
sb.Append(list[i].Stringify(false));
|
||||
}
|
||||
sb.Append(']');
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
|
|
|
|||
|
|
@ -71,10 +71,6 @@ public class LongArrayTag : ArrayTag<long>
|
|||
return $"TAG_Long_Array({PrettyName}): [{Count} {word}]";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <i>string</i> representation of this NBT tag (SNBT).
|
||||
/// </summary>
|
||||
/// <returns>This NBT tag in SNBT format.</returns>
|
||||
/// <seealso href="https://minecraft.fandom.com/wiki/NBT_format#SNBT_format"/>
|
||||
public override string Stringify() => Stringify('L', 'l');
|
||||
/// <inheritdoc />
|
||||
public override string Stringify(bool named = true) => Stringify(named, 'L', 'l');
|
||||
}
|
||||
|
|
@ -69,10 +69,6 @@ public class LongTag : NumericTag<long>
|
|||
[CLSCompliant(false)]
|
||||
public static implicit operator ulong(LongTag tag) => unchecked((ulong)tag.Value);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <i>string</i> representation of this NBT tag (SNBT).
|
||||
/// </summary>
|
||||
/// <returns>This NBT tag in SNBT format.</returns>
|
||||
/// <seealso href="https://minecraft.fandom.com/wiki/NBT_format#SNBT_format"/>
|
||||
public override string Stringify() => $"{StringifyName}:{Value}L";
|
||||
/// <inheritdoc />
|
||||
public override string Stringify(bool named = true) => named ? $"{StringifyName}:{Value}L" : $"{Value}L";
|
||||
}
|
||||
|
|
@ -75,10 +75,6 @@ public class ShortTag : NumericTag<short>
|
|||
[CLSCompliant(false)]
|
||||
public static implicit operator ushort(ShortTag tag) => unchecked((ushort)tag.Value);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <i>string</i> representation of this NBT tag (SNBT).
|
||||
/// </summary>
|
||||
/// <returns>This NBT tag in SNBT format.</returns>
|
||||
/// <seealso href="https://minecraft.fandom.com/wiki/NBT_format#SNBT_format"/>
|
||||
public override string Stringify() => $"{StringifyName}:{Value}S";
|
||||
/// <inheritdoc />
|
||||
public override string Stringify(bool named = true) => named ? $"{StringifyName}:{Value}S" : $"{Value}S";
|
||||
}
|
||||
|
|
@ -47,13 +47,12 @@ public class StringTag : Tag, IEquatable<StringTag>
|
|||
/// <param name="tag">The tag to convert.</param>
|
||||
/// <returns>The tag represented as a <see cref="string"/>.</returns>
|
||||
public static implicit operator string(StringTag tag) => tag.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <i>string</i> representation of this NBT tag (SNBT).
|
||||
/// </summary>
|
||||
/// <returns>This NBT tag in SNBT format.</returns>
|
||||
/// <seealso href="https://minecraft.fandom.com/wiki/NBT_format#SNBT_format"/>
|
||||
public override string Stringify() => $"{StringifyName}:\"{Value}\""; // TODO: Does this get properly escaped?
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Stringify(bool named = true)
|
||||
{
|
||||
return named ? $"{StringifyName}:\"{Value}\"" : $"\"{Value}\"";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Equals(StringTag? other)
|
||||
|
|
|
|||
|
|
@ -212,9 +212,10 @@ public abstract class Tag : IEquatable<Tag>, ICloneable
|
|||
/// <summary>
|
||||
/// Gets the <i>string</i> representation of this NBT tag (SNBT).
|
||||
/// </summary>
|
||||
/// <param name="named">Flag indicating if the name of the tag should be written.</param>
|
||||
/// <returns>This NBT tag in SNBT format.</returns>
|
||||
/// <seealso href="https://minecraft.fandom.com/wiki/NBT_format#SNBT_format"/>
|
||||
public abstract string Stringify();
|
||||
public abstract string Stringify(bool named = true);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name in a formatted properly for SNBT.
|
||||
|
|
|
|||
Loading…
Reference in New Issue