Implement basic NBT PODO
This commit is contained in:
parent
80ab4ad0e5
commit
79c14b9097
17 changed files with 518 additions and 19 deletions
|
@ -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
237
lib/nbt/Stream.dart
Normal 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
35
lib/nbt/Tag.dart
Normal 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
20
lib/nbt/impl/ByteTag.dart
Normal 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
|
||||
}
|
||||
}
|
19
lib/nbt/impl/TagByteArray.dart
Normal file
19
lib/nbt/impl/TagByteArray.dart
Normal 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
|
||||
}
|
||||
}
|
21
lib/nbt/impl/TagCompound.dart
Normal file
21
lib/nbt/impl/TagCompound.dart
Normal 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
|
||||
}
|
||||
}
|
19
lib/nbt/impl/TagDouble.dart
Normal file
19
lib/nbt/impl/TagDouble.dart
Normal 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
14
lib/nbt/impl/TagEnd.dart
Normal 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) {}
|
||||
}
|
19
lib/nbt/impl/TagFloat.dart
Normal file
19
lib/nbt/impl/TagFloat.dart
Normal 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
19
lib/nbt/impl/TagInt.dart
Normal 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
|
||||
}
|
||||
}
|
19
lib/nbt/impl/TagIntArray.dart
Normal file
19
lib/nbt/impl/TagIntArray.dart
Normal 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
20
lib/nbt/impl/TagList.dart
Normal 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
19
lib/nbt/impl/TagLong.dart
Normal 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
|
||||
}
|
||||
}
|
19
lib/nbt/impl/TagLongArray.dart
Normal file
19
lib/nbt/impl/TagLongArray.dart
Normal 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
|
||||
}
|
||||
}
|
19
lib/nbt/impl/TagShort.dart
Normal file
19
lib/nbt/impl/TagShort.dart
Normal 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
|
||||
}
|
||||
}
|
19
lib/nbt/impl/TagString.dart
Normal file
19
lib/nbt/impl/TagString.dart
Normal 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
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
});
|
||||
}
|
Loading…
Reference in a new issue