Implement basic NBT PODO

This commit is contained in:
zontreck 2024-05-04 19:41:19 -07:00
parent 80ab4ad0e5
commit 79c14b9097
17 changed files with 518 additions and 19 deletions

View file

@ -1,7 +0,0 @@
library libac;
/// A Calculator.
class Calculator {
/// Returns [value] plus 1.
int addOne(int value) => value + 1;
}

237
lib/nbt/Stream.dart Normal file
View file

@ -0,0 +1,237 @@
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
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;
}
}

35
lib/nbt/Tag.dart Normal file
View file

@ -0,0 +1,35 @@
import 'Stream.dart';
enum TagType {
End(0),
Byte(1),
Short(2),
Int(3),
Long(4),
Float(5),
Double(6),
ByteArray(7),
String(8),
List(9),
Compound(10),
IntArray(11),
LongArray(12);
final int byte;
const TagType(this.byte);
}
abstract class Tag {
late TagType type;
int getType() {
return type.byte;
}
TagType getTagType() {
return type;
}
void writeValue(ByteLayer data);
void readValue(ByteLayer data);
}

20
lib/nbt/impl/ByteTag.dart Normal file
View file

@ -0,0 +1,20 @@
import 'package:libac_flutter/nbt/Stream.dart';
import 'package:libac_flutter/nbt/Tag.dart';
class ByteTag extends Tag {
final int value;
ByteTag({required this.value}) {
type = TagType.Byte;
}
@override
void readValue(ByteLayer data) {
// TODO: implement readValue
}
@override
void writeValue(ByteLayer data) {
// TODO: implement writeValue
}
}

View file

@ -0,0 +1,19 @@
import 'package:libac_flutter/nbt/Stream.dart';
import 'package:libac_flutter/nbt/Tag.dart';
class TagByteArray extends Tag {
final List<int> value;
TagByteArray({required this.value}) {
type = TagType.ByteArray;
}
@override
void readValue(ByteLayer data) {
// TODO: implement readValue
}
@override
void writeValue(ByteLayer data) {
// TODO: implement writeValue
}
}

View file

@ -0,0 +1,21 @@
import 'package:libac_flutter/nbt/Stream.dart';
import 'package:libac_flutter/nbt/Tag.dart';
class TagCompound extends Tag {
late final Map<String, Tag> _value;
TagCompound() {
_value = new Map();
type = TagType.Compound;
}
@override
void readValue(ByteLayer data) {
// TODO: implement readValue
}
@override
void writeValue(ByteLayer data) {
// TODO: implement writeValue
}
}

View file

@ -0,0 +1,19 @@
import 'package:libac_flutter/nbt/Stream.dart';
import 'package:libac_flutter/nbt/Tag.dart';
class TagDouble extends Tag {
final double value;
TagDouble({required this.value}) {
type = TagType.Float;
}
@override
void readValue(ByteLayer data) {
// TODO: implement readValue
}
@override
void writeValue(ByteLayer data) {
// TODO: implement writeValue
}
}

14
lib/nbt/impl/TagEnd.dart Normal file
View file

@ -0,0 +1,14 @@
import 'package:libac_flutter/nbt/Stream.dart';
import 'package:libac_flutter/nbt/Tag.dart';
class TagEnd extends Tag {
TagEnd() {
type = TagType.End;
}
@override
void readValue(ByteLayer data) {}
@override
void writeValue(ByteLayer data) {}
}

View file

@ -0,0 +1,19 @@
import 'package:libac_flutter/nbt/Stream.dart';
import 'package:libac_flutter/nbt/Tag.dart';
class TagFloat extends Tag {
final double value;
TagFloat({required this.value}) {
type = TagType.Float;
}
@override
void readValue(ByteLayer data) {
// TODO: implement readValue
}
@override
void writeValue(ByteLayer data) {
// TODO: implement writeValue
}
}

19
lib/nbt/impl/TagInt.dart Normal file
View file

@ -0,0 +1,19 @@
import 'package:libac_flutter/nbt/Stream.dart';
import 'package:libac_flutter/nbt/Tag.dart';
class TagInt extends Tag {
final int value;
TagInt({required this.value}) {
type = TagType.Int;
}
@override
void readValue(ByteLayer data) {
// TODO: implement readValue
}
@override
void writeValue(ByteLayer data) {
// TODO: implement writeValue
}
}

View file

@ -0,0 +1,19 @@
import 'package:libac_flutter/nbt/Stream.dart';
import 'package:libac_flutter/nbt/Tag.dart';
class TagIntArray extends Tag {
final List<int> value;
TagIntArray({required this.value}) {
type = TagType.IntArray;
}
@override
void readValue(ByteLayer data) {
// TODO: implement readValue
}
@override
void writeValue(ByteLayer data) {
// TODO: implement writeValue
}
}

20
lib/nbt/impl/TagList.dart Normal file
View file

@ -0,0 +1,20 @@
import 'package:libac_flutter/nbt/Stream.dart';
import 'package:libac_flutter/nbt/Tag.dart';
class TagList extends Tag {
late final List<Tag> _value;
TagList() {
type = TagType.List;
_value = List.empty(growable: true);
}
@override
void readValue(ByteLayer data) {
// TODO: implement readValue
}
@override
void writeValue(ByteLayer data) {
// TODO: implement writeValue
}
}

19
lib/nbt/impl/TagLong.dart Normal file
View file

@ -0,0 +1,19 @@
import 'package:libac_flutter/nbt/Stream.dart';
import 'package:libac_flutter/nbt/Tag.dart';
class TagLong extends Tag {
final int value;
TagLong({required this.value}) {
type = TagType.Long;
}
@override
void readValue(ByteLayer data) {
// TODO: implement readValue
}
@override
void writeValue(ByteLayer data) {
// TODO: implement writeValue
}
}

View file

@ -0,0 +1,19 @@
import 'package:libac_flutter/nbt/Stream.dart';
import 'package:libac_flutter/nbt/Tag.dart';
class TagLongArray extends Tag {
final List<int> value;
TagLongArray({required this.value}) {
type = TagType.LongArray;
}
@override
void readValue(ByteLayer data) {
// TODO: implement readValue
}
@override
void writeValue(ByteLayer data) {
// TODO: implement writeValue
}
}

View file

@ -0,0 +1,19 @@
import 'package:libac_flutter/nbt/Stream.dart';
import 'package:libac_flutter/nbt/Tag.dart';
class TagShort extends Tag {
final int value;
TagShort({required this.value}) {
type = TagType.Short;
}
@override
void readValue(ByteLayer data) {
// TODO: implement readValue
}
@override
void writeValue(ByteLayer data) {
// TODO: implement writeValue
}
}

View file

@ -0,0 +1,19 @@
import 'package:libac_flutter/nbt/Stream.dart';
import 'package:libac_flutter/nbt/Tag.dart';
class TagString extends Tag {
final String value;
TagString({required this.value}) {
type = TagType.String;
}
@override
void readValue(ByteLayer data) {
// TODO: implement readValue
}
@override
void writeValue(ByteLayer data) {
// TODO: implement writeValue
}
}

View file

@ -1,12 +0,0 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:libac/libac.dart';
void main() {
test('adds one to input values', () {
final calculator = Calculator();
expect(calculator.addOne(2), 3);
expect(calculator.addOne(-7), -6);
expect(calculator.addOne(0), 1);
});
}