Initial implementation
BIN
Icons/PNG/Boolean.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
Icons/PNG/Byte.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
Icons/PNG/ByteArray.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
Icons/PNG/Compound.png
Normal file
After Width: | Height: | Size: 2 KiB |
BIN
Icons/PNG/Double.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
Icons/PNG/Float.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
Icons/PNG/Integer.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
Icons/PNG/IntegerArray.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
Icons/PNG/List.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
Icons/PNG/Long.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
Icons/PNG/LongArray.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
Icons/PNG/Short.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
Icons/PNG/String.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
140
Icons/SVG/Boolean.svg
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
version="1.1"
|
||||||
|
viewBox="0.00 0.00 32.00 32.00"
|
||||||
|
id="svg20"
|
||||||
|
sodipodi:docname="Boolean.svg"
|
||||||
|
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs20" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview20"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#000000"
|
||||||
|
borderopacity="0.25"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
inkscape:zoom="34.84375"
|
||||||
|
inkscape:cx="16"
|
||||||
|
inkscape:cy="16"
|
||||||
|
inkscape:window-width="2560"
|
||||||
|
inkscape:window-height="1319"
|
||||||
|
inkscape:window-x="1920"
|
||||||
|
inkscape:window-y="60"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="g13" />
|
||||||
|
<g
|
||||||
|
stroke-width="2.00"
|
||||||
|
fill="none"
|
||||||
|
stroke-linecap="butt"
|
||||||
|
id="g13">
|
||||||
|
<path
|
||||||
|
stroke="#43411b"
|
||||||
|
vector-effect="non-scaling-stroke"
|
||||||
|
d=" M 31.25 0.00 L 29.54 1.90"
|
||||||
|
id="path1" />
|
||||||
|
<path
|
||||||
|
stroke="#5c492c"
|
||||||
|
vector-effect="non-scaling-stroke"
|
||||||
|
d=" M 29.54 1.90 Q 29.08 2.03 29.08 2.26"
|
||||||
|
id="path2" />
|
||||||
|
<path
|
||||||
|
stroke="#0e9f33"
|
||||||
|
vector-effect="non-scaling-stroke"
|
||||||
|
d=" M 29.08 2.26 Q 28.97 2.16 28.91 2.05 Q 28.79 1.80 28.51 1.80 L 2.35 2.10 A 0.37 0.37 0.0 0 0 1.98 2.47 L 1.96 28.88 Q 1.96 28.97 2.04 29.02 Q 2.13 29.07 2.27 29.14"
|
||||||
|
id="path3" />
|
||||||
|
<path
|
||||||
|
stroke="#5c492c"
|
||||||
|
vector-effect="non-scaling-stroke"
|
||||||
|
d=" M 2.27 29.14 Q 2.18 29.00 1.92 29.51"
|
||||||
|
id="path4" />
|
||||||
|
<path
|
||||||
|
stroke="#43411b"
|
||||||
|
vector-effect="non-scaling-stroke"
|
||||||
|
d=" M 1.92 29.51 L 0.00 31.38"
|
||||||
|
id="path5" />
|
||||||
|
<path
|
||||||
|
stroke="#980c1c"
|
||||||
|
vector-effect="non-scaling-stroke"
|
||||||
|
d=" M 1.92 29.51 Q 1.78 30.11 2.25 30.13 Q 10.00 30.33 17.75 30.13 Q 19.12 30.10 19.46 29.30"
|
||||||
|
id="path6" />
|
||||||
|
<path
|
||||||
|
stroke="#bf8285"
|
||||||
|
vector-effect="non-scaling-stroke"
|
||||||
|
d=" M 19.46 29.30 L 21.86 29.18"
|
||||||
|
id="path7" />
|
||||||
|
<path
|
||||||
|
stroke="#980c1c"
|
||||||
|
vector-effect="non-scaling-stroke"
|
||||||
|
d=" M 21.86 29.18 L 22.18 29.67 Q 22.43 30.05 22.89 30.07 L 29.61 30.34 A 0.62 0.62 0.0 0 0 30.26 29.71 Q 30.07 16.86 30.18 2.78 Q 30.18 2.08 29.54 1.90"
|
||||||
|
id="path8" />
|
||||||
|
<path
|
||||||
|
stroke="#646a33"
|
||||||
|
vector-effect="non-scaling-stroke"
|
||||||
|
d=" M 29.08 2.26 L 2.27 29.14"
|
||||||
|
id="path9" />
|
||||||
|
<path
|
||||||
|
stroke="#349347"
|
||||||
|
vector-effect="non-scaling-stroke"
|
||||||
|
d=" M 8.35 16.99 Q 9.30 18.24 11.08 17.90 A 1.21 1.20 84.6 0 0 12.07 16.70 L 11.96 7.61 A 0.74 0.74 0.0 0 1 12.70 6.86 Q 13.98 6.85 15.19 6.76 Q 15.90 6.71 16.18 6.33 Q 16.66 5.67 15.54 5.02"
|
||||||
|
id="path10" />
|
||||||
|
<path
|
||||||
|
stroke="#8bdf9d"
|
||||||
|
vector-effect="non-scaling-stroke"
|
||||||
|
d=" M 15.54 5.02 Q 15.42 4.41 15.17 3.97 Q 14.93 3.57 14.47 3.57 L 4.74 3.55 A 0.72 0.72 0.0 0 0 4.01 4.26 L 3.99 5.34 Q 3.98 5.94 4.59 5.94 L 7.78 5.96 Q 8.30 5.96 8.30 6.48 L 8.35 16.99"
|
||||||
|
id="path11" />
|
||||||
|
<path
|
||||||
|
stroke="#a9b3a9"
|
||||||
|
vector-effect="non-scaling-stroke"
|
||||||
|
d="m 15.54,5.02 q 0.1,0.81 -0.67,0.86 -1.64,0.11 -3.3,0.06 a 0.6,0.6 0 0 0 -0.62,0.6 v 9.79 A 0.7,0.68 82.3 0 1 10.45,17 Q 9.6,17.26 8.35,16.99"
|
||||||
|
id="path12"
|
||||||
|
style="display:inline" />
|
||||||
|
<path
|
||||||
|
stroke="#d88a96"
|
||||||
|
vector-effect="non-scaling-stroke"
|
||||||
|
d="m 21.86,29.18 -0.03,-5.36 a 0.66,0.66 0 0 1 0.67,-0.66 l 3.1,0.02 q 1.03,0 1.08,-1.03 l 0.03,-0.42 q 0.04,-0.76 -0.73,-0.79 l -3.49,-0.17 q -0.5,-0.02 -0.5,-0.53 L 21.96,18.5 q -0.01,-0.54 0.54,-0.53 l 5.29,0.12 q 0.65,0.01 0.59,-0.63 L 28.29,16.49 Q 28.2,15.55 27.24,15.55 l -7.47,0.01 q -0.5,0 -0.49,0.49 l 0.18,13.25"
|
||||||
|
id="path13"
|
||||||
|
style="display:inline" />
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
fill="#067e2b"
|
||||||
|
d="M 0,0 H 31.25 L 29.54,1.9 Q 29.08,2.03 29.08,2.26 28.97,2.16 28.91,2.05 28.79,1.8 28.51,1.8 L 2.35,2.1 A 0.37,0.37 0 0 0 1.98,2.47 L 1.96,28.88 q 0,0.09 0.08,0.14 0.09,0.05 0.23,0.12 Q 2.18,29 1.92,29.51 L 0,31.38 Z"
|
||||||
|
id="path14"
|
||||||
|
style="display:inline" />
|
||||||
|
<path
|
||||||
|
fill="#7f040b"
|
||||||
|
d="M 31.25,0 H 32 V 32 H 0 v -0.62 l 1.92,-1.87 q -0.14,0.6 0.33,0.62 7.75,0.2 15.5,0 1.37,-0.03 1.71,-0.83 l 2.4,-0.12 0.32,0.49 q 0.25,0.38 0.71,0.4 l 6.72,0.27 a 0.62,0.62 0 0 0 0.65,-0.63 Q 30.07,16.86 30.18,2.78 q 0,-0.7 -0.64,-0.88 z"
|
||||||
|
id="path15"
|
||||||
|
style="display:inline" />
|
||||||
|
<path
|
||||||
|
fill="#16bf3a"
|
||||||
|
d="M 29.08,2.26 2.27,29.14 Q 2.13,29.07 2.04,29.02 1.96,28.97 1.96,28.88 L 1.98,2.47 A 0.37,0.37 0 0 1 2.35,2.1 L 28.51,1.8 q 0.28,0 0.4,0.25 0.06,0.11 0.17,0.21 z M 8.35,16.99 q 0.95,1.25 2.73,0.91 a 1.21,1.2 84.6 0 0 0.99,-1.2 L 11.96,7.61 A 0.74,0.74 0 0 1 12.7,6.86 Q 13.98,6.85 15.19,6.76 15.9,6.71 16.18,6.33 16.66,5.67 15.54,5.02 15.42,4.41 15.17,3.97 14.93,3.57 14.47,3.57 L 4.74,3.55 A 0.72,0.72 0 0 0 4.01,4.26 L 3.99,5.34 q -0.01,0.6 0.6,0.6 l 3.19,0.02 q 0.52,0 0.52,0.52 z"
|
||||||
|
id="path16"
|
||||||
|
style="display:inline" />
|
||||||
|
<path
|
||||||
|
fill="#b1142c"
|
||||||
|
d="m 29.54,1.9 q 0.64,0.18 0.64,0.88 -0.11,14.08 0.08,26.93 a 0.62,0.62 0 0 1 -0.65,0.63 l -6.72,-0.27 q -0.46,-0.02 -0.71,-0.4 l -0.32,-0.49 -0.03,-5.36 a 0.66,0.66 0 0 1 0.67,-0.66 l 3.1,0.02 q 1.03,0 1.08,-1.03 l 0.03,-0.42 q 0.04,-0.76 -0.73,-0.79 l -3.49,-0.17 q -0.5,-0.02 -0.5,-0.53 L 21.96,18.5 q -0.01,-0.54 0.54,-0.53 l 5.29,0.12 q 0.65,0.01 0.59,-0.63 L 28.29,16.49 Q 28.2,15.55 27.24,15.55 l -7.47,0.01 q -0.5,0 -0.49,0.49 l 0.18,13.25 q -0.34,0.8 -1.71,0.83 -7.75,0.2 -15.5,0 Q 1.78,30.11 1.92,29.51 2.18,29 2.27,29.14 L 29.08,2.26 q 0,-0.23 0.46,-0.36 z"
|
||||||
|
id="path17"
|
||||||
|
style="display:inline" />
|
||||||
|
<path
|
||||||
|
fill="#ffffff"
|
||||||
|
d="m 15.54,5.02 q 0.1,0.81 -0.67,0.86 -1.64,0.11 -3.3,0.06 a 0.6,0.6 0 0 0 -0.62,0.6 v 9.79 A 0.7,0.68 82.3 0 1 10.45,17 Q 9.6,17.26 8.35,16.99 L 8.3,6.48 Q 8.3,5.96 7.78,5.96 L 4.59,5.94 q -0.61,0 -0.6,-0.6 L 4.01,4.26 A 0.72,0.72 0 0 1 4.74,3.55 l 9.73,0.02 q 0.46,0 0.7,0.4 0.25,0.44 0.37,1.05 z"
|
||||||
|
id="path18"
|
||||||
|
style="display:inline" />
|
||||||
|
<path
|
||||||
|
fill="#526653"
|
||||||
|
d="m 15.54,5.02 q 1.12,0.65 0.64,1.31 -0.28,0.38 -0.99,0.43 -1.21,0.09 -2.49,0.1 a 0.74,0.74 0 0 0 -0.74,0.75 l 0.11,9.09 a 1.21,1.2 84.6 0 1 -0.99,1.2 Q 9.3,18.24 8.35,16.99 9.6,17.26 10.45,17 a 0.7,0.68 82.3 0 0 0.5,-0.67 V 6.54 a 0.6,0.6 0 0 1 0.62,-0.6 q 1.66,0.05 3.3,-0.06 0.77,-0.05 0.67,-0.86 z"
|
||||||
|
id="path19"
|
||||||
|
style="display:inline" />
|
||||||
|
<path
|
||||||
|
fill="#ffffff"
|
||||||
|
d=" M 21.86 29.18 L 19.46 29.30 L 19.28 16.05 Q 19.27 15.56 19.77 15.56 L 27.24 15.55 Q 28.20 15.55 28.29 16.49 L 28.38 17.46 Q 28.44 18.10 27.79 18.09 L 22.50 17.97 Q 21.95 17.96 21.96 18.50 L 21.99 20.24 Q 21.99 20.75 22.49 20.77 L 25.98 20.94 Q 26.75 20.97 26.71 21.73 L 26.68 22.15 Q 26.63 23.18 25.60 23.18 L 22.50 23.16 A 0.66 0.66 0.0 0 0 21.83 23.82 L 21.86 29.18 Z"
|
||||||
|
id="path20"
|
||||||
|
style="opacity:1" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 7 KiB |
1027
Icons/SVG/Byte.svg
Normal file
After Width: | Height: | Size: 58 KiB |
1027
Icons/SVG/ByteArray.svg
Normal file
After Width: | Height: | Size: 58 KiB |
1027
Icons/SVG/Compound.svg
Normal file
After Width: | Height: | Size: 58 KiB |
1027
Icons/SVG/Double.svg
Normal file
After Width: | Height: | Size: 58 KiB |
1027
Icons/SVG/Float.svg
Normal file
After Width: | Height: | Size: 58 KiB |
1027
Icons/SVG/IntArray.svg
Normal file
After Width: | Height: | Size: 58 KiB |
1027
Icons/SVG/Integer.svg
Normal file
After Width: | Height: | Size: 58 KiB |
1027
Icons/SVG/List.svg
Normal file
After Width: | Height: | Size: 58 KiB |
1027
Icons/SVG/Long.svg
Normal file
After Width: | Height: | Size: 58 KiB |
1027
Icons/SVG/LongArray.svg
Normal file
After Width: | Height: | Size: 58 KiB |
1027
Icons/SVG/Short.svg
Normal file
After Width: | Height: | Size: 58 KiB |
1027
Icons/SVG/String.svg
Normal file
After Width: | Height: | Size: 58 KiB |
|
@ -2,4 +2,5 @@ import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class Constants {
|
class Constants {
|
||||||
static const Color TITLEBAR_COLOR = Color.fromARGB(255, 80, 0, 0);
|
static const Color TITLEBAR_COLOR = Color.fromARGB(255, 80, 0, 0);
|
||||||
|
static const Color DRAWER_COLOR = Color.fromARGB(255, 0, 75, 75);
|
||||||
}
|
}
|
||||||
|
|
129
lib/Editor.dart
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
import 'package:file_picker/file_picker.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_treeview/flutter_treeview.dart';
|
||||||
|
import 'package:nbteditor/Constants.dart';
|
||||||
|
import 'package:nbteditor/tags/CompoundTag.dart';
|
||||||
|
import 'package:nbteditor/tags/NbtIo.dart';
|
||||||
|
import 'package:nbteditor/tags/Tag.dart';
|
||||||
|
|
||||||
|
class Editor extends StatefulWidget {
|
||||||
|
Editor({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
EditorState createState() => EditorState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class EditorState extends State<Editor> {
|
||||||
|
List<Node> nodes = [CompoundTag().getNode("/")];
|
||||||
|
bool compressed = false;
|
||||||
|
|
||||||
|
late TreeViewController controller;
|
||||||
|
|
||||||
|
String appendCompressed() {
|
||||||
|
if (compressed) {
|
||||||
|
return " - Compressed";
|
||||||
|
} else
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
controller = TreeViewController(children: nodes);
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
backgroundColor: Constants.TITLEBAR_COLOR,
|
||||||
|
title: Text("Named Binary Tag Editor${appendCompressed()}"),
|
||||||
|
),
|
||||||
|
drawer: Drawer(
|
||||||
|
backgroundColor: Constants.DRAWER_COLOR,
|
||||||
|
child: Column(children: [
|
||||||
|
DrawerHeader(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Text("Named Binary Tag Editor"),
|
||||||
|
Text("Created by Tara Piccari")
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
ListTile(
|
||||||
|
title: Text("N E W"),
|
||||||
|
subtitle: Text("Create a new NBT Document"),
|
||||||
|
leading: Icon(Icons.add),
|
||||||
|
onTap: () {
|
||||||
|
setState(() {
|
||||||
|
nodes.clear();
|
||||||
|
|
||||||
|
// Add a new compound tag as the root
|
||||||
|
Tag tag = CompoundTag();
|
||||||
|
nodes.add(tag.getNode("/"));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
title: Text("O P E N"),
|
||||||
|
leading: Icon(Icons.folder),
|
||||||
|
subtitle: Text("Open an existing NBT Document for editing"),
|
||||||
|
onTap: () async {
|
||||||
|
FilePickerResult? result = await FilePicker.platform.pickFiles();
|
||||||
|
String? filePath;
|
||||||
|
if (result != null) {
|
||||||
|
filePath = result.files.single.path;
|
||||||
|
// Do something with the selected file path
|
||||||
|
print('Selected file path: $filePath');
|
||||||
|
} else {
|
||||||
|
// User canceled the picker
|
||||||
|
print('File selection canceled.');
|
||||||
|
}
|
||||||
|
if (filePath == null) {
|
||||||
|
// cancelled
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// String!!
|
||||||
|
compressed = await NbtIo.read(filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
nodes.clear();
|
||||||
|
nodes.add(Tag.read(NbtIo.getStream()).getNode("/"));
|
||||||
|
|
||||||
|
controller = TreeViewController(children: nodes);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
)
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
body: TreeView(
|
||||||
|
nodeBuilder: (context, node) {
|
||||||
|
return (node.data as Tag).render();
|
||||||
|
},
|
||||||
|
controller: controller,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FileSelectionScreen extends StatelessWidget {
|
||||||
|
Future<void> openFilePicker(BuildContext context) async {
|
||||||
|
try {} catch (e) {
|
||||||
|
// Handle errors
|
||||||
|
print('Error selecting file: $e');
|
||||||
|
}
|
||||||
|
|
||||||
|
Navigator.pop(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text('File Selection'),
|
||||||
|
),
|
||||||
|
body: Center(
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: () => openFilePicker(context),
|
||||||
|
child: Text('Select File'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:nbteditor/Editor.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
runApp(const MainApp());
|
runApp(const MainApp());
|
||||||
|
@ -9,12 +10,12 @@ class MainApp extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return const MaterialApp(
|
return MaterialApp(
|
||||||
home: Scaffold(
|
theme: ThemeData.dark(),
|
||||||
body: Center(
|
routes: {
|
||||||
child: Text('Hello World!'),
|
"/": (context) => Editor(),
|
||||||
),
|
"/select_file": (context) => FileSelectionScreen()
|
||||||
),
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
67
lib/tags/ByteArrayTag.dart
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/src/widgets/framework.dart';
|
||||||
|
import 'package:flutter_treeview/src/models/node.dart';
|
||||||
|
import 'package:nbteditor/tags/NbtIo.dart';
|
||||||
|
import 'package:nbteditor/tags/Tag.dart';
|
||||||
|
import 'package:nbteditor/tags/TagType.dart';
|
||||||
|
|
||||||
|
class ByteArrayTag extends Tag {
|
||||||
|
List<int> _value = [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
Node getNode(String path) {
|
||||||
|
List<Node> entries = [];
|
||||||
|
int count = 0;
|
||||||
|
for (var element in _value) {
|
||||||
|
entries.add(Node(key: "$path/${count}", label: "${element}"));
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Node(key: path, label: Name, data: this, children: entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void readHeader(ByteLayer layer) {
|
||||||
|
setName(layer.readTagName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void readValue(ByteLayer layer) {
|
||||||
|
int count = layer.readInt();
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
_value.add(layer.readByte());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget render() {
|
||||||
|
return ListTile(
|
||||||
|
title: Text("TAG_ByteArray (${Name})"),
|
||||||
|
subtitle: Text("${_value.length} entries"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeHeader(ByteLayer layer) {
|
||||||
|
layer.writeTagName(Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeTagType(ByteLayer layer) {
|
||||||
|
layer.writeByte(TagType.ByteArray.toByte());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeValue(ByteLayer layer) {
|
||||||
|
layer.writeInt(_value.length);
|
||||||
|
|
||||||
|
for (var element in _value) {
|
||||||
|
layer.writeByte(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
TagType getTagType() {
|
||||||
|
return TagType.ByteArray;
|
||||||
|
}
|
||||||
|
}
|
53
lib/tags/ByteTag.dart
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/src/widgets/framework.dart';
|
||||||
|
import 'package:flutter_treeview/src/models/node.dart';
|
||||||
|
import 'package:nbteditor/tags/NbtIo.dart';
|
||||||
|
import 'package:nbteditor/tags/Tag.dart';
|
||||||
|
import 'package:nbteditor/tags/TagType.dart';
|
||||||
|
|
||||||
|
class ByteTag extends Tag {
|
||||||
|
int _value = 0;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Node getNode(String path) {
|
||||||
|
return Node(key: path, label: "TAG_Byte ${Name}", data: this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void readHeader(ByteLayer layer) {
|
||||||
|
setName(layer.readTagName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void readValue(ByteLayer layer) {
|
||||||
|
this._value = layer.readByte();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget render() {
|
||||||
|
return ListTile(
|
||||||
|
title: Text("TAG_Byte (${Name})"),
|
||||||
|
subtitle: Text("${_value}"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeHeader(ByteLayer layer) {
|
||||||
|
layer.writeTagName(Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeTagType(ByteLayer layer) {
|
||||||
|
layer.writeByte(TagType.Byte.toByte());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeValue(ByteLayer layer) {
|
||||||
|
layer.writeByte(this._value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
TagType getTagType() {
|
||||||
|
return TagType.Byte;
|
||||||
|
}
|
||||||
|
}
|
91
lib/tags/CompoundTag.dart
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_treeview/flutter_treeview.dart';
|
||||||
|
import 'package:nbteditor/tags/NbtIo.dart';
|
||||||
|
import 'package:nbteditor/tags/Tag.dart';
|
||||||
|
import 'package:nbteditor/tags/TagType.dart';
|
||||||
|
import 'package:uuid/v4.dart';
|
||||||
|
|
||||||
|
class CompoundTag extends Tag {
|
||||||
|
UuidV4 v4 = UuidV4();
|
||||||
|
Map<String, Tag> _children = {};
|
||||||
|
|
||||||
|
CompoundTag() {
|
||||||
|
setKey(v4.generate());
|
||||||
|
|
||||||
|
setName("root");
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget render() {
|
||||||
|
return ListTile(
|
||||||
|
title: Text("TAG_Compound (${Name})"),
|
||||||
|
subtitle:
|
||||||
|
Text("${_children.length} tag${_children.length > 1 ? "s" : ""}"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Node getNode(String path) {
|
||||||
|
List<Node> childTags = [];
|
||||||
|
|
||||||
|
for (var element in _children.entries) {
|
||||||
|
childTags.add(element.value.getNode(path + "/${element.key}"));
|
||||||
|
}
|
||||||
|
Node me = Node(key: path, label: Name, data: this, children: childTags);
|
||||||
|
return me;
|
||||||
|
}
|
||||||
|
|
||||||
|
void put(String name, Tag child) {
|
||||||
|
_children[name] = child.withNick(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
Tag? get(String name) {
|
||||||
|
return _children[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove(String name) {
|
||||||
|
_children.remove(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void readValue(ByteLayer layer) {
|
||||||
|
TagType type;
|
||||||
|
while (true) {
|
||||||
|
type = Tag.readTagType(layer);
|
||||||
|
if (type == TagType.End) break;
|
||||||
|
|
||||||
|
Tag tag = Tag.readTag(layer, type, false);
|
||||||
|
put(tag.Name, tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeValue(ByteLayer layer) {
|
||||||
|
for (var entry in _children.entries) {
|
||||||
|
layer.writeTagName(entry.key);
|
||||||
|
entry.value.writeValue(layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
layer.writeByte(TagType.End.toByte());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void readHeader(ByteLayer layer) {
|
||||||
|
setName(layer.readTagName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeHeader(ByteLayer layer) {
|
||||||
|
layer.writeTagName(Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeTagType(ByteLayer layer) {
|
||||||
|
layer.writeByte(TagType.Compound.toByte());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
TagType getTagType() {
|
||||||
|
return TagType.Compound;
|
||||||
|
}
|
||||||
|
}
|
53
lib/tags/DoubleTag.dart
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/src/widgets/framework.dart';
|
||||||
|
import 'package:flutter_treeview/src/models/node.dart';
|
||||||
|
import 'package:nbteditor/tags/NbtIo.dart';
|
||||||
|
import 'package:nbteditor/tags/Tag.dart';
|
||||||
|
import 'package:nbteditor/tags/TagType.dart';
|
||||||
|
|
||||||
|
class DoubleTag extends Tag {
|
||||||
|
double _value = 0.0;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Node getNode(String path) {
|
||||||
|
return Node(key: path, label: "", data: this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void readHeader(ByteLayer layer) {
|
||||||
|
setName(layer.readTagName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void readValue(ByteLayer layer) {
|
||||||
|
_value = layer.readDouble();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget render() {
|
||||||
|
return ListTile(
|
||||||
|
title: Text("TAG_Double (${Name})"),
|
||||||
|
subtitle: Text("${_value}"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeHeader(ByteLayer layer) {
|
||||||
|
layer.writeTagName(Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeTagType(ByteLayer layer) {
|
||||||
|
layer.writeByte(TagType.Double.toByte());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeValue(ByteLayer layer) {
|
||||||
|
layer.writeDouble(_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
TagType getTagType() {
|
||||||
|
return TagType.Double;
|
||||||
|
}
|
||||||
|
}
|
53
lib/tags/FloatTag.dart
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/src/widgets/framework.dart';
|
||||||
|
import 'package:flutter_treeview/src/models/node.dart';
|
||||||
|
import 'package:nbteditor/tags/NbtIo.dart';
|
||||||
|
import 'package:nbteditor/tags/Tag.dart';
|
||||||
|
import 'package:nbteditor/tags/TagType.dart';
|
||||||
|
|
||||||
|
class FloatTag extends Tag {
|
||||||
|
double _value = 0.0;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Node getNode(String path) {
|
||||||
|
return Node(key: path, label: "$_value", data: this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void readHeader(ByteLayer layer) {
|
||||||
|
setName(layer.readTagName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void readValue(ByteLayer layer) {
|
||||||
|
_value = layer.readFloat();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget render() {
|
||||||
|
return ListTile(
|
||||||
|
title: Text("TAG_Float (${Name})"),
|
||||||
|
subtitle: Text("${_value}"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeHeader(ByteLayer layer) {
|
||||||
|
layer.writeTagName(Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeTagType(ByteLayer layer) {
|
||||||
|
layer.writeByte(TagType.Float.toByte());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeValue(ByteLayer layer) {
|
||||||
|
layer.writeFloat(_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
TagType getTagType() {
|
||||||
|
return TagType.Float;
|
||||||
|
}
|
||||||
|
}
|
67
lib/tags/IntArrayTag.dart
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/src/widgets/framework.dart';
|
||||||
|
import 'package:flutter_treeview/src/models/node.dart';
|
||||||
|
import 'package:nbteditor/tags/NbtIo.dart';
|
||||||
|
import 'package:nbteditor/tags/Tag.dart';
|
||||||
|
import 'package:nbteditor/tags/TagType.dart';
|
||||||
|
|
||||||
|
class IntArrayTag extends Tag {
|
||||||
|
List<int> _value = [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
Node getNode(String path) {
|
||||||
|
List<Node> entries = [];
|
||||||
|
int count = 0;
|
||||||
|
for (var element in _value) {
|
||||||
|
entries.add(Node(key: "$path/${count}", label: "${element}"));
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Node(key: path, label: Name, data: this, children: entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void readHeader(ByteLayer layer) {
|
||||||
|
setName(layer.readTagName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void readValue(ByteLayer layer) {
|
||||||
|
int count = layer.readInt();
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
_value.add(layer.readInt());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget render() {
|
||||||
|
return ListTile(
|
||||||
|
title: Text("TAG_IntArray (${Name})"),
|
||||||
|
subtitle: Text("${_value.length} entries"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeHeader(ByteLayer layer) {
|
||||||
|
layer.writeTagName(Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeTagType(ByteLayer layer) {
|
||||||
|
layer.writeByte(TagType.IntArray.toByte());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeValue(ByteLayer layer) {
|
||||||
|
layer.writeInt(_value.length);
|
||||||
|
|
||||||
|
for (var element in _value) {
|
||||||
|
layer.writeInt(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
TagType getTagType() {
|
||||||
|
return TagType.IntArray;
|
||||||
|
}
|
||||||
|
}
|
52
lib/tags/IntTag.dart
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/src/widgets/framework.dart';
|
||||||
|
import 'package:flutter_treeview/src/models/node.dart';
|
||||||
|
import 'package:nbteditor/tags/NbtIo.dart';
|
||||||
|
import 'package:nbteditor/tags/Tag.dart';
|
||||||
|
import 'package:nbteditor/tags/TagType.dart';
|
||||||
|
|
||||||
|
class IntTag extends Tag {
|
||||||
|
int _value = 0;
|
||||||
|
@override
|
||||||
|
Node getNode(String path) {
|
||||||
|
return Node(key: path, label: "$_value", data: this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void readHeader(ByteLayer layer) {
|
||||||
|
setName(layer.readTagName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void readValue(ByteLayer layer) {
|
||||||
|
_value = layer.readInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget render() {
|
||||||
|
return ListTile(
|
||||||
|
title: Text("TAG_Int (${Name})"),
|
||||||
|
subtitle: Text("${_value}"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeHeader(ByteLayer layer) {
|
||||||
|
layer.writeTagName(Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeTagType(ByteLayer layer) {
|
||||||
|
layer.writeByte(TagType.Int.toByte());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeValue(ByteLayer layer) {
|
||||||
|
layer.writeInt(_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
TagType getTagType() {
|
||||||
|
return TagType.Int;
|
||||||
|
}
|
||||||
|
}
|
100
lib/tags/ListTag.dart
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/src/widgets/framework.dart';
|
||||||
|
import 'package:flutter_treeview/src/models/node.dart';
|
||||||
|
import 'package:nbteditor/tags/NbtIo.dart';
|
||||||
|
import 'package:nbteditor/tags/Tag.dart';
|
||||||
|
import 'package:nbteditor/tags/TagType.dart';
|
||||||
|
|
||||||
|
class ListTag extends Tag {
|
||||||
|
List<Tag> _value = [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
Node getNode(String path) {
|
||||||
|
List<Node> nodes = [];
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
for (var element in _value) {
|
||||||
|
nodes.add(element.getNode("$path/$count"));
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Node(key: path, label: Name, data: this, children: nodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void readHeader(ByteLayer layer) {
|
||||||
|
setName(layer.readTagName());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool add(Tag tag) {
|
||||||
|
if (_value.length > 0) {
|
||||||
|
if (tag.getTagType() == _value[0].getTagType()) {
|
||||||
|
_value.add(tag);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_value.add(tag);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void readValue(ByteLayer layer) {
|
||||||
|
TagType type = Tag.readTagType(layer);
|
||||||
|
int count = layer.readInt();
|
||||||
|
|
||||||
|
if (count == 0) return;
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
add(Tag.readTag(layer, type, true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget render() {
|
||||||
|
return ListTile(
|
||||||
|
title: Text("TAG_List (${Name}) (${getListTagType()})"),
|
||||||
|
subtitle: Text("${_value.length} entries"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeHeader(ByteLayer layer) {
|
||||||
|
layer.writeTagName(Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeTagType(ByteLayer layer) {
|
||||||
|
layer.writeByte(TagType.List.toByte());
|
||||||
|
}
|
||||||
|
|
||||||
|
TagType getListTagType() {
|
||||||
|
if (_value.length > 0) {
|
||||||
|
return TagType.End;
|
||||||
|
} else
|
||||||
|
return _value[0].getTagType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeValue(ByteLayer layer) {
|
||||||
|
if (_value.length > 0) {
|
||||||
|
_value[0].writeTagType(layer);
|
||||||
|
} else {
|
||||||
|
layer.writeByte(TagType.End.toByte());
|
||||||
|
}
|
||||||
|
|
||||||
|
layer.writeInt(_value.length);
|
||||||
|
|
||||||
|
for (var element in _value) {
|
||||||
|
element.writeValue(layer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
TagType getTagType() {
|
||||||
|
return TagType.List;
|
||||||
|
}
|
||||||
|
}
|
67
lib/tags/LongArrayTag.dart
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/src/widgets/framework.dart';
|
||||||
|
import 'package:flutter_treeview/src/models/node.dart';
|
||||||
|
import 'package:nbteditor/tags/NbtIo.dart';
|
||||||
|
import 'package:nbteditor/tags/Tag.dart';
|
||||||
|
import 'package:nbteditor/tags/TagType.dart';
|
||||||
|
|
||||||
|
class LongArrayTag extends Tag {
|
||||||
|
List<int> _value = [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
Node getNode(String path) {
|
||||||
|
List<Node> entries = [];
|
||||||
|
int count = 0;
|
||||||
|
for (var element in _value) {
|
||||||
|
entries.add(Node(key: "$path/${count}", label: "${element}"));
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Node(key: path, label: Name, data: this, children: entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void readHeader(ByteLayer layer) {
|
||||||
|
setName(layer.readTagName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void readValue(ByteLayer layer) {
|
||||||
|
int count = layer.readInt();
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
_value.add(layer.readLong());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget render() {
|
||||||
|
return ListTile(
|
||||||
|
title: Text("TAG_LongArray (${Name})"),
|
||||||
|
subtitle: Text("${_value.length} entries"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeHeader(ByteLayer layer) {
|
||||||
|
layer.writeTagName(Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeTagType(ByteLayer layer) {
|
||||||
|
layer.writeByte(TagType.LongArray.toByte());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeValue(ByteLayer layer) {
|
||||||
|
layer.writeInt(_value.length);
|
||||||
|
|
||||||
|
for (var element in _value) {
|
||||||
|
layer.writeLong(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
TagType getTagType() {
|
||||||
|
return TagType.LongArray;
|
||||||
|
}
|
||||||
|
}
|
53
lib/tags/LongTag.dart
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/src/widgets/framework.dart';
|
||||||
|
import 'package:flutter_treeview/src/models/node.dart';
|
||||||
|
import 'package:nbteditor/tags/NbtIo.dart';
|
||||||
|
import 'package:nbteditor/tags/Tag.dart';
|
||||||
|
import 'package:nbteditor/tags/TagType.dart';
|
||||||
|
|
||||||
|
class LongTag extends Tag {
|
||||||
|
int _value = 0;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Node getNode(String path) {
|
||||||
|
return Node(key: path, label: "$_value", data: this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void readHeader(ByteLayer layer) {
|
||||||
|
setName(layer.readTagName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void readValue(ByteLayer layer) {
|
||||||
|
_value = layer.readLong();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget render() {
|
||||||
|
return ListTile(
|
||||||
|
title: Text("TAG_Long (${Name})"),
|
||||||
|
subtitle: Text("${_value}"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeHeader(ByteLayer layer) {
|
||||||
|
layer.writeTagName(Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeTagType(ByteLayer layer) {
|
||||||
|
layer.writeByte(TagType.Long.toByte());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeValue(ByteLayer layer) {
|
||||||
|
layer.writeLong(_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
TagType getTagType() {
|
||||||
|
return TagType.Long;
|
||||||
|
}
|
||||||
|
}
|
285
lib/tags/NbtIo.dart
Normal file
|
@ -0,0 +1,285 @@
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:ffi';
|
||||||
|
import 'dart:io';
|
||||||
|
import 'dart:typed_data';
|
||||||
|
|
||||||
|
import 'package:nbteditor/tags/TagType.dart';
|
||||||
|
|
||||||
|
class ByteLayer {
|
||||||
|
Uint8List _byteBuffer = Uint8List(0);
|
||||||
|
int _position = 0;
|
||||||
|
|
||||||
|
ByteLayer() {
|
||||||
|
_byteBuffer = Uint8List(0); // Initial size, can be adjusted
|
||||||
|
_position = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get length => _byteBuffer.length;
|
||||||
|
|
||||||
|
int get currentPosition => _position;
|
||||||
|
|
||||||
|
Uint8List get bytes => _byteBuffer.sublist(0, _position);
|
||||||
|
|
||||||
|
void _ensureCapacity(int additionalBytes) {
|
||||||
|
final requiredCapacity = _position + additionalBytes;
|
||||||
|
if (requiredCapacity > _byteBuffer.length) {
|
||||||
|
final newCapacity =
|
||||||
|
_position * 2 + additionalBytes; // Adjust capacity as needed
|
||||||
|
final newBuffer = Uint8List(newCapacity);
|
||||||
|
newBuffer.setAll(0, _byteBuffer);
|
||||||
|
_byteBuffer = newBuffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeInt(int value) {
|
||||||
|
_ensureCapacity(4);
|
||||||
|
_byteBuffer.buffer.asByteData().setInt32(_position, value, Endian.big);
|
||||||
|
_position += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeDouble(double value) {
|
||||||
|
_ensureCapacity(8);
|
||||||
|
_byteBuffer.buffer.asByteData().setFloat64(_position, value, Endian.big);
|
||||||
|
_position += 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeString(String value) {
|
||||||
|
final encoded = utf8.encode(value);
|
||||||
|
writeShort(encoded.length);
|
||||||
|
_ensureCapacity(encoded.length);
|
||||||
|
_byteBuffer.setAll(_position, encoded);
|
||||||
|
_position += encoded.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
int readInt() {
|
||||||
|
final value =
|
||||||
|
_byteBuffer.buffer.asByteData().getInt32(_position, Endian.big);
|
||||||
|
_position += 4;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
double readDouble() {
|
||||||
|
final value =
|
||||||
|
_byteBuffer.buffer.asByteData().getFloat64(_position, Endian.big);
|
||||||
|
_position += 8;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
String readString() {
|
||||||
|
final length = readShort();
|
||||||
|
final encoded = _byteBuffer.sublist(_position, _position + length);
|
||||||
|
_position += length;
|
||||||
|
return utf8.decode(encoded);
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeIntZigZag(int value) {
|
||||||
|
final zigzag = (value << 1) ^ (value >> 31);
|
||||||
|
writeInt(zigzag);
|
||||||
|
}
|
||||||
|
|
||||||
|
int readIntZigZag() {
|
||||||
|
final zigzag = readInt();
|
||||||
|
final value = (zigzag >> 1) ^ -(zigzag & 1);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeByte(int value) {
|
||||||
|
_ensureCapacity(1);
|
||||||
|
_byteBuffer[_position] = value & 0xFF;
|
||||||
|
_position++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int readByte() {
|
||||||
|
final value = _byteBuffer[_position];
|
||||||
|
_position++;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeVarInt(int value) {
|
||||||
|
while ((value & ~0x7F) != 0) {
|
||||||
|
writeByte((value & 0x7F) | 0x80);
|
||||||
|
value = (value >> 7) & 0x1FFFFFFF;
|
||||||
|
}
|
||||||
|
writeByte(value & 0x7F);
|
||||||
|
}
|
||||||
|
|
||||||
|
int readVarInt() {
|
||||||
|
int result = 0;
|
||||||
|
int shift = 0;
|
||||||
|
int byte;
|
||||||
|
do {
|
||||||
|
byte = readByte();
|
||||||
|
result |= (byte & 0x7F) << shift;
|
||||||
|
if ((byte & 0x80) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
shift += 7;
|
||||||
|
} while (true);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeVarIntNoZigZag(int value) {
|
||||||
|
while ((value & ~0x7F) != 0) {
|
||||||
|
writeByte((value & 0x7F) | 0x80);
|
||||||
|
value >>= 7;
|
||||||
|
}
|
||||||
|
writeByte(value & 0x7F);
|
||||||
|
}
|
||||||
|
|
||||||
|
int readVarIntNoZigZag() {
|
||||||
|
int result = 0;
|
||||||
|
int shift = 0;
|
||||||
|
int byte;
|
||||||
|
do {
|
||||||
|
byte = readByte();
|
||||||
|
result |= (byte & 0x7F) << shift;
|
||||||
|
if ((byte & 0x80) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
shift += 7;
|
||||||
|
} while (true);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeShort(int value) {
|
||||||
|
_ensureCapacity(2);
|
||||||
|
_byteBuffer.buffer.asByteData().setInt16(_position, value, Endian.big);
|
||||||
|
_position += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int readShort() {
|
||||||
|
final value =
|
||||||
|
_byteBuffer.buffer.asByteData().getInt16(_position, Endian.big);
|
||||||
|
_position += 2;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeFloat(double value) {
|
||||||
|
_ensureCapacity(4);
|
||||||
|
_byteBuffer.buffer.asByteData().setFloat32(_position, value, Endian.big);
|
||||||
|
_position += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
double readFloat() {
|
||||||
|
final value =
|
||||||
|
_byteBuffer.buffer.asByteData().getFloat32(_position, Endian.big);
|
||||||
|
|
||||||
|
_position += 2;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeTagName(String name) {
|
||||||
|
final encodedName = utf8.encode(name);
|
||||||
|
writeShort(encodedName.length);
|
||||||
|
_ensureCapacity(encodedName.length);
|
||||||
|
_byteBuffer.setAll(_position, encodedName);
|
||||||
|
_position += encodedName.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
String readTagName() {
|
||||||
|
final length = readShort();
|
||||||
|
final encodedName = _byteBuffer.sublist(_position, _position + length);
|
||||||
|
_position += length;
|
||||||
|
return utf8.decode(encodedName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void resetPosition() {
|
||||||
|
_position = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
resetPosition();
|
||||||
|
_byteBuffer = Uint8List(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> writeToFile(String filePath) async {
|
||||||
|
final file = File(filePath);
|
||||||
|
await file.writeAsBytes(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> readFromFile(String filePath) async {
|
||||||
|
final file = File(filePath);
|
||||||
|
final exists = await file.exists();
|
||||||
|
if (!exists) {
|
||||||
|
print('File does not exist.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_byteBuffer = await file.readAsBytes();
|
||||||
|
resetPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> compress() async {
|
||||||
|
final gzip = GZipCodec();
|
||||||
|
final compressedData = gzip.encode(_byteBuffer);
|
||||||
|
_byteBuffer = Uint8List.fromList(compressedData);
|
||||||
|
_position = _byteBuffer.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> decompress() async {
|
||||||
|
final gzip = GZipCodec();
|
||||||
|
final decompressedData = gzip.decode(_byteBuffer);
|
||||||
|
_byteBuffer = Uint8List.fromList(decompressedData);
|
||||||
|
_position = _byteBuffer.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeLong(int value) {
|
||||||
|
_ensureCapacity(8);
|
||||||
|
_byteBuffer.buffer.asByteData().setInt64(_position, value, Endian.big);
|
||||||
|
_position += 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
int readLong() {
|
||||||
|
final value =
|
||||||
|
_byteBuffer.buffer.asByteData().getInt64(_position, Endian.big);
|
||||||
|
_position += 8;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NbtIo {
|
||||||
|
static ByteLayer _io = ByteLayer();
|
||||||
|
|
||||||
|
// Handle various helper functions here!
|
||||||
|
|
||||||
|
static Future<void> _read(String file) async {
|
||||||
|
_io = ByteLayer();
|
||||||
|
|
||||||
|
await _io.readFromFile(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function will read the file and check if it is infact gzipped
|
||||||
|
static Future<bool> read(String file) async {
|
||||||
|
await _read(file);
|
||||||
|
if (_io.readByte() == TagType.Compound.toByte()) {
|
||||||
|
_io.resetPosition();
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
// Is likely gzip compressed
|
||||||
|
await _readCompressed(file);
|
||||||
|
_io.resetPosition();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<void> _readCompressed(String file) async {
|
||||||
|
_io = ByteLayer();
|
||||||
|
await _io.readFromFile(file);
|
||||||
|
await _io.decompress();
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<void> write(String file) async {
|
||||||
|
await _io.writeToFile(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<void> writeCompressed(String file) async {
|
||||||
|
await _io.compress();
|
||||||
|
await _io.writeToFile(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ByteLayer getStream() {
|
||||||
|
return _io;
|
||||||
|
}
|
||||||
|
}
|
53
lib/tags/ShortTag.dart
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/src/widgets/framework.dart';
|
||||||
|
import 'package:flutter_treeview/src/models/node.dart';
|
||||||
|
import 'package:nbteditor/tags/NbtIo.dart';
|
||||||
|
import 'package:nbteditor/tags/Tag.dart';
|
||||||
|
import 'package:nbteditor/tags/TagType.dart';
|
||||||
|
|
||||||
|
class ShortTag extends Tag {
|
||||||
|
int _value = 0;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Node getNode(String path) {
|
||||||
|
return Node(key: path, label: "$_value", data: this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void readHeader(ByteLayer layer) {
|
||||||
|
setName(layer.readTagName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void readValue(ByteLayer layer) {
|
||||||
|
_value = layer.readShort();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget render() {
|
||||||
|
return ListTile(
|
||||||
|
title: Text("TAG_Short (${Name})"),
|
||||||
|
subtitle: Text("${_value}"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeHeader(ByteLayer layer) {
|
||||||
|
layer.writeTagName(Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeTagType(ByteLayer layer) {
|
||||||
|
layer.writeByte(TagType.Short.toByte());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeValue(ByteLayer layer) {
|
||||||
|
layer.writeShort(_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
TagType getTagType() {
|
||||||
|
return TagType.Short;
|
||||||
|
}
|
||||||
|
}
|
52
lib/tags/StringTag.dart
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/src/widgets/framework.dart';
|
||||||
|
import 'package:flutter_treeview/src/models/node.dart';
|
||||||
|
import 'package:nbteditor/tags/NbtIo.dart';
|
||||||
|
import 'package:nbteditor/tags/Tag.dart';
|
||||||
|
import 'package:nbteditor/tags/TagType.dart';
|
||||||
|
|
||||||
|
class StringTag extends Tag {
|
||||||
|
String _value = "";
|
||||||
|
@override
|
||||||
|
Node getNode(String path) {
|
||||||
|
return Node(key: path, label: "$_value", data: this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void readHeader(ByteLayer layer) {
|
||||||
|
setName(layer.readTagName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void readValue(ByteLayer layer) {
|
||||||
|
_value = layer.readString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget render() {
|
||||||
|
return ListTile(
|
||||||
|
title: Text("TAG_String (${Name})"),
|
||||||
|
subtitle: Text("${_value}"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeHeader(ByteLayer layer) {
|
||||||
|
layer.writeTagName(Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeTagType(ByteLayer layer) {
|
||||||
|
layer.writeByte(TagType.String.toByte());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void writeValue(ByteLayer layer) {
|
||||||
|
layer.writeString(_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
TagType getTagType() {
|
||||||
|
return TagType.String;
|
||||||
|
}
|
||||||
|
}
|
229
lib/tags/Tag.dart
Normal file
|
@ -0,0 +1,229 @@
|
||||||
|
import 'dart:ffi';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_treeview/flutter_treeview.dart';
|
||||||
|
import 'package:nbteditor/tags/ByteArrayTag.dart';
|
||||||
|
import 'package:nbteditor/tags/ByteTag.dart';
|
||||||
|
import 'package:nbteditor/tags/CompoundTag.dart';
|
||||||
|
import 'package:nbteditor/tags/DoubleTag.dart';
|
||||||
|
import 'package:nbteditor/tags/FloatTag.dart';
|
||||||
|
import 'package:nbteditor/tags/IntArrayTag.dart';
|
||||||
|
import 'package:nbteditor/tags/IntTag.dart';
|
||||||
|
import 'package:nbteditor/tags/ListTag.dart';
|
||||||
|
import 'package:nbteditor/tags/LongArrayTag.dart';
|
||||||
|
import 'package:nbteditor/tags/LongTag.dart';
|
||||||
|
import 'package:nbteditor/tags/NbtIo.dart';
|
||||||
|
import 'package:nbteditor/tags/ShortTag.dart';
|
||||||
|
import 'package:nbteditor/tags/StringTag.dart';
|
||||||
|
import 'package:nbteditor/tags/TagType.dart';
|
||||||
|
|
||||||
|
abstract class Tag {
|
||||||
|
String Name = "";
|
||||||
|
Tag();
|
||||||
|
|
||||||
|
late String key;
|
||||||
|
|
||||||
|
void setKey(String key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget render();
|
||||||
|
|
||||||
|
Node getNode(String path);
|
||||||
|
|
||||||
|
ByteTag asByte() {
|
||||||
|
if (this is ByteTag)
|
||||||
|
return this as ByteTag;
|
||||||
|
else
|
||||||
|
return ByteTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
ShortTag asShort() {
|
||||||
|
if (this is ShortTag)
|
||||||
|
return this as ShortTag;
|
||||||
|
else
|
||||||
|
return ShortTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
IntTag asInt() {
|
||||||
|
if (this is IntTag)
|
||||||
|
return this as IntTag;
|
||||||
|
else
|
||||||
|
return IntTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
LongTag asLong() {
|
||||||
|
if (this is LongTag)
|
||||||
|
return this as LongTag;
|
||||||
|
else
|
||||||
|
return LongTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
FloatTag asFloat() {
|
||||||
|
if (this is FloatTag)
|
||||||
|
return this as FloatTag;
|
||||||
|
else
|
||||||
|
return FloatTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
DoubleTag asDouble() {
|
||||||
|
if (this is DoubleTag)
|
||||||
|
return this as DoubleTag;
|
||||||
|
else
|
||||||
|
return DoubleTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteArrayTag asByteArray() {
|
||||||
|
if (this is ByteArrayTag)
|
||||||
|
return this as ByteArrayTag;
|
||||||
|
else
|
||||||
|
return ByteArrayTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
StringTag asString() {
|
||||||
|
if (this is StringTag)
|
||||||
|
return this as StringTag;
|
||||||
|
else
|
||||||
|
return StringTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
ListTag asListTag() {
|
||||||
|
if (this is ListTag)
|
||||||
|
return this as ListTag;
|
||||||
|
else
|
||||||
|
return ListTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
CompoundTag asCompoundTag() {
|
||||||
|
if (this is CompoundTag)
|
||||||
|
return this as CompoundTag;
|
||||||
|
else
|
||||||
|
return CompoundTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
IntArrayTag asIntArrayTag() {
|
||||||
|
if (this is IntArrayTag)
|
||||||
|
return this as IntArrayTag;
|
||||||
|
else
|
||||||
|
return IntArrayTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
LongArrayTag asLongArrayTag() {
|
||||||
|
if (this is LongArrayTag)
|
||||||
|
return this as LongArrayTag;
|
||||||
|
else
|
||||||
|
return LongArrayTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
Tag withNick(String name) {
|
||||||
|
Name = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setName(String name) {
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Tag read(ByteLayer layer) {
|
||||||
|
TagType tagType = readTagType(layer);
|
||||||
|
return readTag(layer, tagType, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Tag readTag(ByteLayer layer, TagType tagType, bool isList) {
|
||||||
|
Tag tag;
|
||||||
|
switch (tagType) {
|
||||||
|
case TagType.Byte:
|
||||||
|
{
|
||||||
|
tag = ByteTag();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TagType.Short:
|
||||||
|
{
|
||||||
|
tag = ShortTag();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TagType.Int:
|
||||||
|
{
|
||||||
|
tag = IntTag();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TagType.Long:
|
||||||
|
{
|
||||||
|
tag = LongTag();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TagType.Float:
|
||||||
|
{
|
||||||
|
tag = FloatTag();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TagType.Double:
|
||||||
|
{
|
||||||
|
tag = DoubleTag();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TagType.ByteArray:
|
||||||
|
{
|
||||||
|
tag = ByteArrayTag();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TagType.String:
|
||||||
|
{
|
||||||
|
tag = StringTag();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TagType.List:
|
||||||
|
{
|
||||||
|
tag = ListTag();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TagType.Compound:
|
||||||
|
{
|
||||||
|
tag = CompoundTag();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TagType.IntArray:
|
||||||
|
{
|
||||||
|
tag = IntArrayTag();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TagType.LongArray:
|
||||||
|
{
|
||||||
|
tag = LongArrayTag();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
print(
|
||||||
|
"Unknown tag: ${tagType}, aborting read at ${layer.currentPosition - 1} bytes");
|
||||||
|
|
||||||
|
throw Exception("Unknown tag, could not deserialize");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
print("Read ${tagType}");
|
||||||
|
|
||||||
|
if (!isList) tag.readHeader(layer);
|
||||||
|
|
||||||
|
print("Name: ${tag.Name}");
|
||||||
|
|
||||||
|
tag.readValue(layer);
|
||||||
|
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
static TagType readTagType(ByteLayer layer) {
|
||||||
|
int type = layer.readByte();
|
||||||
|
TagType tagType = TagTypeExtension.fromByte(type);
|
||||||
|
|
||||||
|
return tagType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void readHeader(ByteLayer layer);
|
||||||
|
void readValue(ByteLayer layer);
|
||||||
|
|
||||||
|
TagType getTagType();
|
||||||
|
void writeTagType(ByteLayer layer);
|
||||||
|
void writeHeader(ByteLayer layer);
|
||||||
|
void writeValue(ByteLayer layer);
|
||||||
|
}
|
83
lib/tags/TagType.dart
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
enum TagType {
|
||||||
|
End,
|
||||||
|
Byte,
|
||||||
|
Short,
|
||||||
|
Int,
|
||||||
|
Long,
|
||||||
|
Float,
|
||||||
|
Double,
|
||||||
|
ByteArray,
|
||||||
|
String,
|
||||||
|
List,
|
||||||
|
Compound,
|
||||||
|
IntArray,
|
||||||
|
LongArray
|
||||||
|
}
|
||||||
|
|
||||||
|
extension TagTypeExtension on TagType {
|
||||||
|
int toByte() {
|
||||||
|
switch (this) {
|
||||||
|
case TagType.End:
|
||||||
|
return 0;
|
||||||
|
case TagType.Byte:
|
||||||
|
return 1;
|
||||||
|
case TagType.Short:
|
||||||
|
return 2;
|
||||||
|
case TagType.Int:
|
||||||
|
return 3;
|
||||||
|
case TagType.Long:
|
||||||
|
return 4;
|
||||||
|
case TagType.Float:
|
||||||
|
return 5;
|
||||||
|
case TagType.Double:
|
||||||
|
return 6;
|
||||||
|
case TagType.ByteArray:
|
||||||
|
return 7;
|
||||||
|
case TagType.String:
|
||||||
|
return 8;
|
||||||
|
case TagType.List:
|
||||||
|
return 9;
|
||||||
|
case TagType.Compound:
|
||||||
|
return 10;
|
||||||
|
case TagType.IntArray:
|
||||||
|
return 11;
|
||||||
|
case TagType.LongArray:
|
||||||
|
return 12;
|
||||||
|
default:
|
||||||
|
throw Exception('Unknown TagType: $this');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static TagType fromByte(int type) {
|
||||||
|
switch (type) {
|
||||||
|
case 0:
|
||||||
|
return TagType.End;
|
||||||
|
case 1:
|
||||||
|
return TagType.Byte;
|
||||||
|
case 2:
|
||||||
|
return TagType.Short;
|
||||||
|
case 3:
|
||||||
|
return TagType.Int;
|
||||||
|
case 4:
|
||||||
|
return TagType.Long;
|
||||||
|
case 5:
|
||||||
|
return TagType.Float;
|
||||||
|
case 6:
|
||||||
|
return TagType.Double;
|
||||||
|
case 7:
|
||||||
|
return TagType.ByteArray;
|
||||||
|
case 8:
|
||||||
|
return TagType.String;
|
||||||
|
case 9:
|
||||||
|
return TagType.List;
|
||||||
|
case 10:
|
||||||
|
return TagType.Compound;
|
||||||
|
case 11:
|
||||||
|
return TagType.IntArray;
|
||||||
|
case 12:
|
||||||
|
return TagType.LongArray;
|
||||||
|
default:
|
||||||
|
throw Exception("Unknown TagType $type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,8 +7,11 @@ environment:
|
||||||
sdk: '>=3.1.5 <4.0.0'
|
sdk: '>=3.1.5 <4.0.0'
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
|
file_picker: ^6.1.1
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
flutter_treeview: ^1.0.7+1
|
||||||
|
uuid: ^4.2.2
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|