Open Offroaders123 opened 4 months ago
So part of the concept here is around my new realization as to how NBT tags would be represented with markup languages. If it were with XML, I think it actually lines up very well with how the tags currently work, and were originally implemented years back.
JSX? More Discord thread discussions!
React NBTML JSX? JSNBTML? oh god 😂
export default function Hello() {
return (
<CompoundTag name="hello world">
<ByteTag name="result-of-something">25</ByteTag>
</CompoundTag>
);
}
I actually love the concept of this in a way! What if you programatically create NBT with functional components? Lol I'm not sure the need for this, but it does line up very well in terms of the actual editing work
I already like the TS type checking around using plain objects though
export default function Hello() {
return new CompoundTag("hello world", {
"result-of-something": new ByteTag(25)
});
}
So if the constructors for the tag classes were just rearranged to work with how JSX calls the components, it would actually work nicely
This does bring up another great point though Using something like SolidJS on top of NBT primitive JSX elements You could have reactive data structures built on top of plain NBT values 🤯
Info from Discord about the background on why this is fairly cool:
It's more for the compatibility of maybe being useful for other tools and building blocks, ones we might not have quite put together yet One idea I thought of is being able to render NBT with SVG maybe, or just to view it in the browser itself, with a nice tree view possibly Yeah this is pretty cool, here's how it renders in Chrome
[EternalModz]: Would it be similar to SNBT?
Yeah to some extent
It's not as easy for readability, but more tools might be able to edit it since XML is commonplace So say if you wanted to edit NBT with a non-NBT program, you could just convert it to XML, then back again, like we do currently for SNBT Not sure if it's really usable to any extent, but even using JSX to template NBT sounds kind of interesting to me
export default function Bigtest() {
return (
// <?xml version="1.0" encoding="UTF-8"?>
<CompoundTag name="Level">
<LongTag name="longTest">9223372036854775807</LongTag>
<ShortTag name="shortTest">32767</ShortTag>
<StringTag name="stringTest">HELLO WORLD THIS IS A TEST STRING ÅÄÖ!</StringTag>
<FloatTag name="floatTest">0.4982314705848694</FloatTag>
<IntTag name="intTest">2147483647</IntTag>
<CompoundTag name="nested compound test">
<CompoundTag name="ham">
<StringTag name="name">Hampus</StringTag>
<FloatTag name="value">0.75</FloatTag>
</CompoundTag>
<CompoundTag name="egg">
<StringTag name="name">Eggbert</StringTag>
<FloatTag name="value">0.5</FloatTag>
</CompoundTag>
</CompoundTag>
<ListTag name="listTest (long)">
<LongTag>11</LongTag>
<LongTag>12</LongTag>
<LongTag>13</LongTag>
<LongTag>14</LongTag>
<LongTag>15</LongTag>
</ListTag>
<ListTag name="listTest (compound)">
<CompoundTag>
<StringTag name="name">Compound tag #0</StringTag>
<LongTag name="created-on">1264099775885</LongTag>
</CompoundTag>
<CompoundTag>
<StringTag name="name">Compound tag #1</StringTag>
<LongTag name="created-on">1264099775885</LongTag>
</CompoundTag>
</ListTag>
<ByteTag name="byteTest">127</ByteTag>
<DoubleTag name="doubleTest">0.4931287132182315</DoubleTag>
<ByteArrayTag name="byteArrayTest">
<ByteTag>0</ByteTag>
<ByteTag>62</ByteTag>
<ByteTag>34</ByteTag>
<ByteTag>16</ByteTag>
<ByteTag>8</ByteTag>
</ByteArrayTag>
<IntArrayTag name="intArrayTest">
<IntTag>543</IntTag>
<IntTag>123</IntTag>
<IntTag>7567</IntTag>
<IntTag>244</IntTag>
</IntArrayTag>
<LongArrayTag name="longArrayTest">
<LongTag>7676</LongTag>
<LongTag>53534</LongTag>
<LongTag>34534</LongTag>
<LongTag>345345345</LongTag>
</LongArrayTag>
<StringTag name="escapedString">"noice, I gotchya"</StringTag>
{/* <StringTag name="escapeSequences">
 	"'\</StringTag> */}
<StringTag name="otherEscape">"</StringTag>
</CompoundTag>
);
}
I like the JS object setup more personally though, since it's more typesafe with TypeScript
import { Int8, Int16, Int32, Float32 } from "nbtify"
type Bigtest = ReturnType<typeof Bigtest>;
export default function Bigtest() {
return {
longTest: 9223372036854775807n,
shortTest: new Int16<number>(32767),
stringTest: "HELLO WORLD THIS IS A TEST STRING ÅÄÖ!",
floatTest: new Float32<number>(0.4982314705848694),
intTest: new Int32<number>(2147483647),
"nested compound test": {
ham: {
name: "Hampus",
value: new Float32<number>(0.75)
},
egg: {
name: "Eggbert",
value: new Float32<number>(0.5)
}
},
"listTest (long)": [11n, 12n, 13n, 14n, 15n],
"listTest (compound)": [
{
name: "Compound tag #0",
"created-on": 1264099775885n
},
{
name: "Compound tag #1",
"created-on": 1264099775885n
}
],
byteTest: new Int8<number>(127),
doubleTest: 0.4931287132182315,
byteArrayTest: new Int8Array([0,62,34,16,8]),
intArrayTest: new Int32Array([543,123,7567,244]),
longArrayTest: new BigInt64Array([7676n,53534n,34534n,345345345n]),
escapedString: '"noice, I gotchya"',
escapeSequences: '\b\f\n\r\t"\'\\',
otherEscape: "\""
};
}
[In reference to the JSX file code snippet above]
So if the JSX pragma for this was actually implemented, it would just resolve to the same object that you see in the file above, bigtest.ts
Come to think of it, I wonder if it would be cool to render these with Web Components themselves! Then you could write your NBT with HTML too 🫨 Or rather, you could use HTML to create NBT declaratively
It's a bit hacky, but yeah!
<!DOCTYPE html>
<html lang="en-US">
<head>
<title>Bigtest</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- <meta name="color-scheme" content="dark"> -->
<style>
:where(
byte-tag,
short-tag,
int-tag,
long-tag,
float-tag,
double-tag,
byte-array-tag,
string-tag,
list-tag,
compound-tag,
int-array-tag,
long-array-tag
) {
font-family: monospace;
display: list-item;
text-align: -webkit-match-parent;
unicode-bidi: isolate;
:not(
byte-array-tag,
list-tag,
int-array-tag,
long-array-tag
) > &::before {
content: attr(name) ": ";
}
}
:where(
byte-array-tag,
list-tag,
compound-tag,
int-array-tag,
long-array-tag
) {
display: block;
list-style-type: disc;
list-style-position: inside;
margin-block-start: 1em;
margin-block-end: 1em;
margin-inline-start: 0;
margin-inline-end: 0;
padding-inline-start: 40px;
border-left: 2px dashed black;
unicode-bidi: isolate;
}
</style>
</head>
<body>
<compound-tag name="Level">
<long-tag name="longTest">9223372036854775807</long-tag>
<short-tag name="shortTest">32767</short-tag>
<string-tag name="stringTest">HELLO WORLD THIS IS A TEST STRING ÅÄÖ!</string-tag>
<float-tag name="floatTest">0.4982314705848694</float-tag>
<int-tag name="intTest">2147483647</int-tag>
<compound-tag name="nested compound test">
<compound-tag name="ham">
<string-tag name="name">Hampus</string-tag>
<float-tag name="value">0.75</float-tag>
</compound-tag>
<compound-tag name="egg">
<string-tag name="name">Eggbert</string-tag>
<float-tag name="value">0.5</float-tag>
</compound-tag>
</compound-tag>
<list-tag name="listTest (long)">
<long-tag>11</long-tag>
<long-tag>12</long-tag>
<long-tag>13</long-tag>
<long-tag>14</long-tag>
<long-tag>15</long-tag>
</list-tag>
<list-tag name="listTest (compound)">
<compound-tag>
<string-tag name="name">Compound tag #0</string-tag>
<long-tag name="created-on">1264099775885</long-tag>
</compound-tag>
<compound-tag>
<string-tag name="name">Compound tag #1</string-tag>
<long-tag name="created-on">1264099775885</long-tag>
</compound-tag>
</list-tag>
<byte-tag name="byteTest">127</byte-tag>
<double-tag name="doubleTest">0.4931287132182315</double-tag>
<byte-array-tag name="byteArrayTest">
<byte-tag>0</byte-tag>
<byte-tag>62</byte-tag>
<byte-tag>34</byte-tag>
<byte-tag>16</byte-tag>
<byte-tag>8</byte-tag>
</byte-array-tag>
<int-array-tag name="intArrayTest">
<int-tag>543</int-tag>
<int-tag>123</int-tag>
<int-tag>7567</int-tag>
<int-tag>244</int-tag>
</int-array-tag>
<long-array-tag name="longArrayTest">
<long-tag>7676</long-tag>
<long-tag>53534</long-tag>
<long-tag>34534</long-tag>
<long-tag>345345345</long-tag>
</long-array-tag>
<string-tag name="escapedString">"noice, I gotchya"</string-tag>
<string-tag name="escapeSequences">
 	"'\</string-tag>
<string-tag name="otherEscape">"</string-tag>
</compound-tag>
</body>
</html>
(Initially copied this from a Discord thread)
I think I figured something out
I think NBT is indeed was originally meant to be typed as 'primitives, with attributes', compared to a plain 'key-value record'/'hashmap' setup It explains the need for the name at the top level of the file XML translates very well over between NBT/SNBT, in terms of conceptually explaining it I want to make a demo converter to show it now
So using something like SNBT or JSON to describe NBT is (possibly) counter to how the original concept was described Maybe it was more like a markup language afterall, to where the tags themselves could have been literal markup tags
I'm not sure how that would work for the more complex derived-types though, like
ByteArrayTag
,IntArrayTag
, orLongArrayTag
I guess technically it is just like thisSo maybe it's not complex afterall
[Generic PnP Monitor] well a LongArrayTag doesn't store LongTags it just stores plain longs
Yeah in terms of the binary format I'm curious how else it could be represented as plain text then? Does XML (or HTML, just for the sake of looking into it) have any list-based elements/tags that don't require a special child type for it to work?
[Generic PnP Monitor] hmm dunno maybe just having a LongValue element idk
Ok I think I'm going to try adding it into NBTify