{"id":15383313,"url":"https://github.com/neolegends/enbt","last_synced_at":"2025-04-09T11:43:58.072Z","repository":{"id":31185744,"uuid":"34746315","full_name":"NeoLegends/ENbt","owner":"NeoLegends","description":"A structured binary format loosely based on Minecraft's NBT.","archived":false,"fork":false,"pushed_at":"2015-05-28T18:43:58.000Z","size":268,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-01T10:54:39.255Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://github.com/NeoLegends/ENbt/blob/master/README.md","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/NeoLegends.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-04-28T17:47:54.000Z","updated_at":"2015-05-01T18:11:32.000Z","dependencies_parsed_at":"2022-09-13T22:10:23.269Z","dependency_job_id":null,"html_url":"https://github.com/NeoLegends/ENbt","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NeoLegends%2FENbt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NeoLegends%2FENbt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NeoLegends%2FENbt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NeoLegends%2FENbt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/NeoLegends","download_url":"https://codeload.github.com/NeoLegends/ENbt/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248033403,"owners_count":21036785,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-01T14:36:51.450Z","updated_at":"2025-04-09T11:43:58.055Z","avatar_url":"https://github.com/NeoLegends.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ENbt\nA structured binary format loosely based on Minecraft's NBT.\n\n## Using ENbt\nUsing ENbt is simple. New tags can be created by `new`ing them, tags can be saved by calling `WriteTo`.\nLoading tags from `Stream`s is possible via `Tag.ReadFrom\u003cT\u003e`. There is no support for `async / await`\nsince `BinaryReader / -Writer` does not include support for it as well. The same reasons why they don't \nsupply support also apply for ENbt (lots of small operations -\u003e bad for `async / await`). Since most of\nthe work required to write a tag to a stream is setting some bytes and UTF-8-encoding strings, I suggest \nwriting to a temporary `MemoryStream` which you copy to your actual `Stream` via `CopyToAsync`, if you\nwanna stay async.\n\n## ENbt Specification\n\n### General\nENbt Trees are somewhat like JSON. They consist of Tags, which represent either a value itself \n(like a byte, a date, or a vector), or contain other Tags like a list or a map. Lists store their elements \nbased on an index, maps (or Objects, in ENbt notation) use names instead.\n\n### Structure of a Tag\nA tag always has the same, short structure. It only consists of the type of the tag and the payload. That \nis  \n\n     \u003cTag Type\u003e  \u003cPayload\u003e  \n    |  1 byte  || n bytes |  \n    \nfor a single tag.\n\nThe type of the tag has a very important role. Since the reader itself does not know what to do with the \npayload of a tag, it will read the tag and do a lookup for an instance that is capable of handling data of\nthat specified type. Since the lookup for the built-in types uses a `switch`-statement, it is very fast.\nIf a handler for the tag type cannot be found, the library will fall back to (more capable, albeit slow)\nreflection. If that lookup failed as well, an exception will be thrown indicating that there was no parser\nfor data of the specified type.\n\n----\n\nThe following tags are pre-defined in ENbt:\n\n- `End = 0`, End marker of object.\n- `Object = 1`, A tag containing other tags by name. Items may have different types.\n- `Array = 2`, A tag containing other tags by index. Items all have the same type.\n- `List = 3`, A tag containing other tags by index. Items may have different types.\n- `SByte = 4`, A signed 8-bit integer.\n- `Byte = 5`, An unsigned 8-bit integer.\n- `Int16 = 6`, A signed 16-bit integer.\n- `UInt16 = 7`, An unsigned 16-bit integer.\n- `Int32 = 8`, A signed 32-bit integer.\n- `UInt32 = 9`, An unsigned 32-bit integer.\n- `Int64 = 10`, A signed 64-bit integer.\n- `UInt64 = 11`, An unsigned 64-bit integer.\n- `Single = 12`, IEEE 754 32-bit floating point (single accuracy).\n- `Double = 13`, IEEE 754 64-bit floating point (double accuracy).\n- `String = 14`, 32-bit length prefixed, UTF-8 encoded string.\n- `Date = 15`, Date and time store, internally stored as UNIX time in milliseconds (Int64).\n- `TimeSpan = 16`, Duration store, internally stored as ticks, which represent 100 nanoseconds each (Int64).\n- `ByteVector2 = 17`, A two-component, 8-bit integer vector, XY.\n- `ByteVector3 = 18`, A three-component, 8-bit integer vector, XYZ.\n- `ByteVector4 = 19`, A four-component, 8-bit integer vector, XYZW.\n- `Int32Vector2 = 20`, A two-component, 32-bit integer vector, XY.\n- `Int32Vector3 = 21`, A three-component, 32-bit integer vector, XYZ.\n- `Int32Vector4 = 22`, A four-component, 32-bit integer vector, XYZW.\n- `SingleVector2 = 23`, A two-component, single accuracy floating point vector, XY.\n- `SingleVector3 = 24`, A three-component, single accuracy floating point vector, XYZ.\n- `SingleVector4 = 25`, A four-component, single accuracy floating point vector, XYZW.\n- `DoubleVector2 = 26`, A two-component, double accuracy floating point vector, XY.\n- `DoubleVector3 = 27`, A three-component, double accuracy floating point vector, XYZ.\n- `DoubleVector4 = 28`, A four-component, double accuracy floating point vector, XYZW.\n\nIn most cases, the payload is just what you expect of a binary format. So in case of a four-component\nsingle accuracy vector, the payload consists of 128 bit data or four `Single`s (without delimeter) in \norder XYZW.\n\n### Special Tags\nSpecial tags are `Object`, `End`, `Array` and `List`, since they are essential for representing a\ntree-like data structure like ENbt.\n\n#### Object\nAn `Object` is an ENbt tag that works like a map. It assigns tags to names. It possesses the regular tag \nheader which is followed by name / tag-pairs. A name / tag-pair consists of a `String`-tag directly \nfollowed by the named tag itself. The structure of a tag of type `Object` looks like this:\n\n     Tag Type Object [ Tag Type String  String Length in Bytes  UTF-8 Encoded String Data  \u003cTag Type\u003e  \u003cPayload\u003e ] Tag Type End\n    |    1 byte     |[|    1 byte     ||       4 bytes        ||         n bytes         ||  1 byte  || n bytes |]|   1 byte   |\n                     [                              as many times as there are children                          ]\n\nThe parser will continue to read name / tag-pairs until it has reached an `End`-tag. That marker \nmarks the end of an object and is _always_ required.\n\n#### End\nAn `End` tag is very simple. It consists just of the tag type (which is 0) without any payload. \nIt's only purpose is to mark the end of an `Object`.\n\n#### Array\nAn array contains a specified amount of elements. Specifically, `Array`s in ENbt are length- and\ntype-prefixed, meaning that the amount and the type of the items inside the list are written as \na byte / 32-bit integer before the items themselves are written. Since the items type is prefixed,\nthere is no need to prefix it to every array element and thus the array is more efficient than a\nlist, specifically if the items themselves are small. The structure of an `Array` looks like this:\n\n     Tag Type Array \u003cItems Type\u003e \u003cList Length\u003e [    \u003cPayload\u003e    ]\n    |   1 byte     |   1 byte   |   4 bytes   |[|    n bytes    |]\n                                               [ \u003cLength\u003e times\u003e ]\n\n#### List\nA list contains a specified amount of elements. Specifically, `List`s in ENbt are length-prefixed,\nmeaning that the amount of items inside the list is written as a 32-bit integer before the items \nthemselves are written. The structure of a `List` looks like this:\n\n     Tag Type List  \u003cList Length\u003e [ \u003cTag Type\u003e  \u003cPayload\u003e ]\n    |   1 byte    ||   4 bytes   |[|  1 byte  || n bytes |]\n                                  [    \u003cLength\u003e times     ]\n\n## Differences to Minecraft NBT\n1. In contrast to Minecraft NBT, ENbt (to which it is not binary-compatible) does not store the name\n   within a tag. Instead, names of the items will be stored by the parent which contains the Tag.\n   This simplifies the structure of the document tree, as there is no more decision to make in whether\n   a Tags name shall be written out or not. Objects simply write the name of the child to the output,\n   lists don't. It also allows for greater flexibility, since you can associate the same value to \n   different keys without mutating the value itself.\n2. ENbt does not require the tree root to be an object. You can use lists, objects, integers, floating \n   point numbers, dates, time ranges, vectors, or whatever object you desire as root. No restrictions!\n3. ENbt does not enforce a specific compression of the content. The format specification really only is\n   about the format itself and not about how it should be written to disk or transferred over the net.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fneolegends%2Fenbt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fneolegends%2Fenbt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fneolegends%2Fenbt/lists"}