Reviewed-on: #8
This commit is contained in:
commit
2f3991b97c
21 changed files with 831 additions and 21 deletions
119
lib/nbt/NbtUtils.dart
Normal file
119
lib/nbt/NbtUtils.dart
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
import 'package:libac_flutter/nbt/impl/ByteTag.dart';
|
||||||
|
import 'package:libac_flutter/nbt/impl/CompoundTag.dart';
|
||||||
|
import 'package:libac_flutter/nbt/impl/DoubleTag.dart';
|
||||||
|
import 'package:libac_flutter/nbt/impl/IntArrayTag.dart';
|
||||||
|
import 'package:libac_flutter/nbt/impl/IntTag.dart';
|
||||||
|
import 'package:libac_flutter/nbt/impl/ListTag.dart';
|
||||||
|
import 'package:libac_flutter/utils/Vector3.dart';
|
||||||
|
|
||||||
|
import '../utils/Vector2.dart';
|
||||||
|
import '../utils/uuid/UUID.dart';
|
||||||
|
|
||||||
|
class NbtUtils {
|
||||||
|
static void writeBoolean(CompoundTag tag, String name, bool b) {
|
||||||
|
tag.put(name, ByteTag.valueOf(b ? 1 : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool readBoolean(CompoundTag tag, String name) {
|
||||||
|
if (tag.contains(name)) {
|
||||||
|
return tag.get(name)!.asByte() == 1 ? true : false;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void writeVector2d(CompoundTag tag, String name, Vector2d pos) {
|
||||||
|
ListTag posTag = ListTag();
|
||||||
|
posTag.add(DoubleTag.valueOf(pos.X));
|
||||||
|
posTag.add(DoubleTag.valueOf(pos.Z));
|
||||||
|
tag.put(name, posTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Vector2d readVector2d(CompoundTag tag, String name) {
|
||||||
|
if (tag.contains(name)) {
|
||||||
|
ListTag lst = tag.get(name)! as ListTag;
|
||||||
|
return Vector2d(X: lst.get(0).asDouble(), Z: lst.get(1).asDouble());
|
||||||
|
} else {
|
||||||
|
return Vector2d.ZERO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void writeVector2i(CompoundTag tag, String name, Vector2i pos) {
|
||||||
|
ListTag posTag = ListTag();
|
||||||
|
posTag.add(IntTag.valueOf(pos.X));
|
||||||
|
posTag.add(IntTag.valueOf(pos.Z));
|
||||||
|
tag.put(name, posTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Vector2i readVector2i(CompoundTag tag, String name) {
|
||||||
|
if (tag.contains(name)) {
|
||||||
|
ListTag lst = tag.get(name)! as ListTag;
|
||||||
|
return Vector2i(X: lst.get(0).asInt(), Z: lst.get(1).asInt());
|
||||||
|
} else {
|
||||||
|
return Vector2i.ZERO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void writeVector3d(CompoundTag tag, String name, Vector3d pos) {
|
||||||
|
ListTag posTag = ListTag();
|
||||||
|
posTag.add(DoubleTag.valueOf(pos.X));
|
||||||
|
posTag.add(DoubleTag.valueOf(pos.Y));
|
||||||
|
posTag.add(DoubleTag.valueOf(pos.Z));
|
||||||
|
tag.put(name, posTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Vector3d readVector3d(CompoundTag tag, String name) {
|
||||||
|
if (tag.contains(name)) {
|
||||||
|
ListTag lst = tag.get(name)! as ListTag;
|
||||||
|
return Vector3d(
|
||||||
|
X: lst.get(0).asDouble(),
|
||||||
|
Y: lst.get(1).asDouble(),
|
||||||
|
Z: lst.get(2).asDouble());
|
||||||
|
} else {
|
||||||
|
return Vector3d.ZERO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void writeVector3i(CompoundTag tag, String name, Vector3i pos) {
|
||||||
|
ListTag posTag = ListTag();
|
||||||
|
posTag.add(IntTag.valueOf(pos.X));
|
||||||
|
posTag.add(IntTag.valueOf(pos.Y));
|
||||||
|
posTag.add(IntTag.valueOf(pos.Z));
|
||||||
|
tag.put(name, posTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Vector3i readVector3i(CompoundTag tag, String name) {
|
||||||
|
if (tag.contains(name)) {
|
||||||
|
ListTag lst = tag.get(name)! as ListTag;
|
||||||
|
return Vector3i(
|
||||||
|
X: lst.get(0).asInt(), Y: lst.get(1).asInt(), Z: lst.get(2).asInt());
|
||||||
|
} else {
|
||||||
|
return Vector3i.ZERO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<int> _msbLsbToIntArray(int msb, int lsb) {
|
||||||
|
return [msb >> 32, msb, lsb >> 32, lsb];
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<int> _uuidToIntArray(UUID ID) {
|
||||||
|
return _msbLsbToIntArray(
|
||||||
|
ID.getMostSignificantBits(), ID.getLeastSignificantBits());
|
||||||
|
}
|
||||||
|
|
||||||
|
static UUID _uuidFromIntArray(List<int> values) {
|
||||||
|
return UUID((values[0] << 32 | values[1] & 4294967295),
|
||||||
|
(values[2] << 32 | values[3] & 4294967295));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void writeUUID(CompoundTag tag, String name, UUID ID) {
|
||||||
|
tag.put(name, IntArrayTag.valueOf(_uuidToIntArray(ID)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static UUID readUUID(CompoundTag tag, String name) {
|
||||||
|
if (!tag.contains(name))
|
||||||
|
return UUID.ZERO;
|
||||||
|
else
|
||||||
|
return _uuidFromIntArray(tag.get(name)!.asIntArray());
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,7 +21,7 @@ class ByteLayer {
|
||||||
final requiredCapacity = _position + additionalBytes;
|
final requiredCapacity = _position + additionalBytes;
|
||||||
if (requiredCapacity > _byteBuffer.length) {
|
if (requiredCapacity > _byteBuffer.length) {
|
||||||
final newCapacity =
|
final newCapacity =
|
||||||
_position * 2 + additionalBytes; // Adjust capacity as needed
|
_position + additionalBytes; // Adjust capacity as needed
|
||||||
final newBuffer = Uint8List(newCapacity);
|
final newBuffer = Uint8List(newCapacity);
|
||||||
newBuffer.setAll(0, _byteBuffer);
|
newBuffer.setAll(0, _byteBuffer);
|
||||||
_byteBuffer = newBuffer;
|
_byteBuffer = newBuffer;
|
||||||
|
@ -86,12 +86,24 @@ class ByteLayer {
|
||||||
_position++;
|
_position++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void writeUnsignedByte(int value) {
|
||||||
|
_ensureCapacity(1);
|
||||||
|
_byteBuffer.buffer.asByteData().setUint8(_position, value);
|
||||||
|
_position++;
|
||||||
|
}
|
||||||
|
|
||||||
int readByte() {
|
int readByte() {
|
||||||
final value = _byteBuffer[_position];
|
final value = _byteBuffer[_position];
|
||||||
_position++;
|
_position++;
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int readUnsignedByte() {
|
||||||
|
final value = _byteBuffer.buffer.asByteData().getUint8(_position);
|
||||||
|
_position++;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
void writeVarInt(int value) {
|
void writeVarInt(int value) {
|
||||||
while ((value & ~0x7F) != 0) {
|
while ((value & ~0x7F) != 0) {
|
||||||
writeByte((value & 0x7F) | 0x80);
|
writeByte((value & 0x7F) | 0x80);
|
||||||
|
@ -232,6 +244,12 @@ class ByteLayer {
|
||||||
_position += 8;
|
_position += 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void writeUnsignedLong(int value) {
|
||||||
|
_ensureCapacity(8);
|
||||||
|
_byteBuffer.buffer.asByteData().setUint64(_position, value, Endian.big);
|
||||||
|
_position += 8;
|
||||||
|
}
|
||||||
|
|
||||||
int readLong() {
|
int readLong() {
|
||||||
final value =
|
final value =
|
||||||
_byteBuffer.buffer.asByteData().getInt64(_position, Endian.big);
|
_byteBuffer.buffer.asByteData().getInt64(_position, Endian.big);
|
||||||
|
@ -239,6 +257,13 @@ class ByteLayer {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int readUnsignedLong() {
|
||||||
|
final value =
|
||||||
|
_byteBuffer.buffer.asByteData().getUint64(_position, Endian.big);
|
||||||
|
_position += 8;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
void writeVarLongNoZigZag(int value) {
|
void writeVarLongNoZigZag(int value) {
|
||||||
while (true) {
|
while (true) {
|
||||||
if ((value & ~0x7F) == 0) {
|
if ((value & ~0x7F) == 0) {
|
||||||
|
@ -283,4 +308,71 @@ class ByteLayer {
|
||||||
int value = readLong();
|
int value = readLong();
|
||||||
return (value >> 1) ^ (-(value & 1));
|
return (value >> 1) ^ (-(value & 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void writeBytes(Iterable<int> bytes) {
|
||||||
|
for (int byte in bytes) {
|
||||||
|
writeUnsignedByte(byte);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<int> readBytes(int num) {
|
||||||
|
List<int> lst = [];
|
||||||
|
for (int i = 0; i < num; i++) {
|
||||||
|
lst.add(readUnsignedByte());
|
||||||
|
}
|
||||||
|
|
||||||
|
return lst;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setBit(int position, int maskToSet) {
|
||||||
|
if (position < _byteBuffer.length) {
|
||||||
|
// Set the value now
|
||||||
|
seek(position);
|
||||||
|
int current = readUnsignedByte();
|
||||||
|
seek(position);
|
||||||
|
current |= maskToSet;
|
||||||
|
writeUnsignedByte(current);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearBit(int position, int maskToClear) {
|
||||||
|
if (position < _byteBuffer.length) {
|
||||||
|
// Lets clear the bit
|
||||||
|
seek(position);
|
||||||
|
int current = readUnsignedByte();
|
||||||
|
current = current & ~maskToClear;
|
||||||
|
seek(position);
|
||||||
|
writeUnsignedByte(current);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool checkBit(int position, int mask) {
|
||||||
|
if (position < _byteBuffer.length) {
|
||||||
|
seek(position);
|
||||||
|
int current = readUnsignedByte();
|
||||||
|
return (current & mask) == mask;
|
||||||
|
} else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getBit(int position) {
|
||||||
|
if (position < _byteBuffer.length) {
|
||||||
|
seek(position);
|
||||||
|
return readUnsignedByte();
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void seek(int position) {
|
||||||
|
_position = 0;
|
||||||
|
_ensureCapacity(position);
|
||||||
|
_position = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Unsets a mask, then sets a mask
|
||||||
|
void unsetSetBit(int position, int maskToClear, int maskToSet) {
|
||||||
|
clearBit(position, maskToClear);
|
||||||
|
setBit(position, maskToSet);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -279,10 +279,10 @@ class NBTAccountant {
|
||||||
static void leaveTag(Tag tag) {
|
static void leaveTag(Tag tag) {
|
||||||
if (tag is CompoundTag || tag is ListTag) {
|
if (tag is CompoundTag || tag is ListTag) {
|
||||||
if (tag is CompoundTag) {
|
if (tag is CompoundTag) {
|
||||||
CompoundTag ct = tag as CompoundTag;
|
CompoundTag ct = tag;
|
||||||
ct.endPrettyPrint(_prettyIndex);
|
ct.endPrettyPrint(_prettyIndex);
|
||||||
} else if (tag is ListTag) {
|
} else if (tag is ListTag) {
|
||||||
ListTag lt = tag as ListTag;
|
ListTag lt = tag;
|
||||||
lt.endPrettyPrint(_prettyIndex);
|
lt.endPrettyPrint(_prettyIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,11 +39,11 @@ class ByteArrayTag extends Tag {
|
||||||
void prettyPrint(int indent, bool recurse) {
|
void prettyPrint(int indent, bool recurse) {
|
||||||
String array = "";
|
String array = "";
|
||||||
for (int b in value) {
|
for (int b in value) {
|
||||||
array += "${b}, ";
|
array += "$b, ";
|
||||||
}
|
}
|
||||||
array = array.substring(0, array.length - 2);
|
array = array.substring(0, array.length - 2);
|
||||||
|
|
||||||
print(
|
print(
|
||||||
"${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}: [${array}]");
|
"${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}: [$array]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,6 @@ class ByteTag extends Tag {
|
||||||
@override
|
@override
|
||||||
void prettyPrint(int indent, bool recurse) {
|
void prettyPrint(int indent, bool recurse) {
|
||||||
print(
|
print(
|
||||||
"${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}: ${value}");
|
"${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}: $value");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,24 +10,24 @@ class CompoundTag extends Tag {
|
||||||
void readValue(ByteLayer data) {
|
void readValue(ByteLayer data) {
|
||||||
value.clear();
|
value.clear();
|
||||||
|
|
||||||
NBTAccountant.visitTag();
|
//NBTAccountant.visitTag();
|
||||||
NBTAccountant.printRead(this);
|
//NBTAccountant.printRead(this);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
Tag tag = Tag.readNamedTag(data);
|
Tag tag = Tag.readNamedTag(data);
|
||||||
if (tag.getType() == 0) {
|
if (tag.getType() == 0) {
|
||||||
NBTAccountant.leaveTag(this);
|
//NBTAccountant.leaveTag(this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
put(tag.getKey(), tag);
|
put(tag.getKey(), tag);
|
||||||
|
/*
|
||||||
if (tag.getTagType() != TagType.Compound &&
|
if (tag.getTagType() != TagType.Compound &&
|
||||||
tag.getTagType() != TagType.List) {
|
tag.getTagType() != TagType.List) {
|
||||||
NBTAccountant.visitTag();
|
NBTAccountant.visitTag();
|
||||||
NBTAccountant.printRead(tag);
|
NBTAccountant.printRead(tag);
|
||||||
NBTAccountant.leaveTag(tag);
|
NBTAccountant.leaveTag(tag);
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,6 @@ class DoubleTag extends Tag {
|
||||||
@override
|
@override
|
||||||
void prettyPrint(int indent, bool recurse) {
|
void prettyPrint(int indent, bool recurse) {
|
||||||
print(
|
print(
|
||||||
"${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}: ${value}");
|
"${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}: $value");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,6 @@ class FloatTag extends Tag {
|
||||||
@override
|
@override
|
||||||
void prettyPrint(int indent, bool recurse) {
|
void prettyPrint(int indent, bool recurse) {
|
||||||
print(
|
print(
|
||||||
"${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}: ${value}");
|
"${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}: $value");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,10 @@ class IntArrayTag extends Tag {
|
||||||
this.value.addAll(value);
|
this.value.addAll(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static IntArrayTag valueOf(List<int> value) {
|
||||||
|
return IntArrayTag._(value);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void readValue(ByteLayer data) {
|
void readValue(ByteLayer data) {
|
||||||
int count = data.readInt();
|
int count = data.readInt();
|
||||||
|
@ -34,11 +38,11 @@ class IntArrayTag extends Tag {
|
||||||
void prettyPrint(int indent, bool recurse) {
|
void prettyPrint(int indent, bool recurse) {
|
||||||
String array = "";
|
String array = "";
|
||||||
for (int b in value) {
|
for (int b in value) {
|
||||||
array += "${b}, ";
|
array += "$b, ";
|
||||||
}
|
}
|
||||||
array = array.substring(0, array.length - 2);
|
array = array.substring(0, array.length - 2);
|
||||||
|
|
||||||
print(
|
print(
|
||||||
"${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}: [${array}]");
|
"${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}: [$array]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,6 @@ class IntTag extends Tag {
|
||||||
@override
|
@override
|
||||||
void prettyPrint(int indent, bool recurse) {
|
void prettyPrint(int indent, bool recurse) {
|
||||||
print(
|
print(
|
||||||
"${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}: ${value}");
|
"${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}: $value");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import 'package:libac_flutter/nbt/Stream.dart';
|
import 'package:libac_flutter/nbt/Stream.dart';
|
||||||
import 'package:libac_flutter/nbt/Tag.dart';
|
import 'package:libac_flutter/nbt/Tag.dart';
|
||||||
|
|
||||||
|
import 'EndTag.dart';
|
||||||
|
|
||||||
class ListTag extends Tag {
|
class ListTag extends Tag {
|
||||||
List<Tag> value = [];
|
List<Tag> value = [];
|
||||||
|
|
||||||
|
@ -42,6 +44,14 @@ class ListTag extends Tag {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Tag get(int index) {
|
||||||
|
if (size() > index) {
|
||||||
|
return value[index];
|
||||||
|
} else {
|
||||||
|
return EndTag();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void remove(Tag tag) {
|
void remove(Tag tag) {
|
||||||
value.remove(tag);
|
value.remove(tag);
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,11 +42,11 @@ class LongArrayTag extends Tag {
|
||||||
void prettyPrint(int indent, bool recurse) {
|
void prettyPrint(int indent, bool recurse) {
|
||||||
String array = "";
|
String array = "";
|
||||||
for (int b in value) {
|
for (int b in value) {
|
||||||
array += "${b}, ";
|
array += "$b, ";
|
||||||
}
|
}
|
||||||
array = array.substring(0, array.length - 2);
|
array = array.substring(0, array.length - 2);
|
||||||
|
|
||||||
print(
|
print(
|
||||||
"${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}: [${array}]");
|
"${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}: [$array]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,6 @@ class LongTag extends Tag {
|
||||||
@override
|
@override
|
||||||
void prettyPrint(int indent, bool recurse) {
|
void prettyPrint(int indent, bool recurse) {
|
||||||
print(
|
print(
|
||||||
"${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}: ${value}");
|
"${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}: $value");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,6 @@ class ShortTag extends Tag {
|
||||||
@override
|
@override
|
||||||
void prettyPrint(int indent, bool recurse) {
|
void prettyPrint(int indent, bool recurse) {
|
||||||
print(
|
print(
|
||||||
"${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}: ${value}");
|
"${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}: $value");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,6 @@ class StringTag extends Tag {
|
||||||
@override
|
@override
|
||||||
void prettyPrint(int indent, bool recurse) {
|
void prettyPrint(int indent, bool recurse) {
|
||||||
print(
|
print(
|
||||||
"${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}: ${value}");
|
"${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}: $value");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
151
lib/utils/Vector2.dart
Normal file
151
lib/utils/Vector2.dart
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
class Vector2d {
|
||||||
|
static final Vector2d ZERO = Vector2d(X: 0, Z: 0);
|
||||||
|
double X = 0.0;
|
||||||
|
double Z = 0.0;
|
||||||
|
|
||||||
|
Vector2d({this.X = 0.0, this.Z = 0.0});
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object otherz) {
|
||||||
|
if (otherz is Vector2d) {
|
||||||
|
Vector2d other = otherz;
|
||||||
|
return X == other.X && Z == other.Z;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2d operator +(Vector2d other) {
|
||||||
|
Vector2d n = Clone();
|
||||||
|
n.X += other.X;
|
||||||
|
n.Z += other.Z;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2d operator -(Vector2d other) {
|
||||||
|
Vector2d n = Clone();
|
||||||
|
n.X -= other.X;
|
||||||
|
n.Z -= other.Z;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2d operator *(Vector2d other) {
|
||||||
|
Vector2d n = Clone();
|
||||||
|
n.X *= other.X;
|
||||||
|
n.Z *= other.Z;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2d operator /(Vector2d other) {
|
||||||
|
Vector2d n = Clone();
|
||||||
|
n.X /= other.X;
|
||||||
|
n.Z /= other.Z;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator >(Vector2d other) {
|
||||||
|
return (X > other.X) || (X > other.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator <(Vector2d other) {
|
||||||
|
return (X < other.X) || (X < other.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2d Clone() {
|
||||||
|
return Vector2d(X: X, Z: Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return "<$X, $Z>";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool inside(Vector2d min, Vector2d max) {
|
||||||
|
if (min.X <= X && max.X >= X) {
|
||||||
|
if (min.Z <= Z && max.Z >= Z) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Vector2i {
|
||||||
|
static final Vector2i ZERO = Vector2i(X: 0, Z: 0);
|
||||||
|
int X = 0;
|
||||||
|
int Z = 0;
|
||||||
|
|
||||||
|
Vector2i({this.X = 0, this.Z = 0});
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object otherz) {
|
||||||
|
if (otherz is Vector2i) {
|
||||||
|
Vector2i other = otherz;
|
||||||
|
return X == other.X && Z == other.Z;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2i operator +(Vector2i other) {
|
||||||
|
Vector2i n = Clone();
|
||||||
|
n.X += other.X;
|
||||||
|
n.Z += other.Z;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2i operator -(Vector2i other) {
|
||||||
|
Vector2i n = Clone();
|
||||||
|
n.X -= other.X;
|
||||||
|
n.Z -= other.Z;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2i operator *(Vector2i other) {
|
||||||
|
Vector2i n = Clone();
|
||||||
|
n.X *= other.X;
|
||||||
|
n.Z *= other.Z;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2i operator /(Vector2i other) {
|
||||||
|
Vector2i n = Clone();
|
||||||
|
n.X = (n.X / other.X).round();
|
||||||
|
n.Z = (n.Z / other.Z).round();
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator >(Vector2i other) {
|
||||||
|
return (X > other.X) || (X > other.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator <(Vector2i other) {
|
||||||
|
return (X < other.X) || (X < other.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2i Clone() {
|
||||||
|
return Vector2i(X: X, Z: Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return "<$X, $Z>";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool inside(Vector2i min, Vector2i max) {
|
||||||
|
if (min.X <= X && max.X >= X) {
|
||||||
|
if (min.Z <= Z && max.Z >= Z) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
165
lib/utils/Vector3.dart
Normal file
165
lib/utils/Vector3.dart
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
class Vector3d {
|
||||||
|
static final Vector3d ZERO = Vector3d(X: 0, Y: 0, Z: 0);
|
||||||
|
double X = 0.0;
|
||||||
|
double Y = 0.0;
|
||||||
|
double Z = 0.0;
|
||||||
|
|
||||||
|
Vector3d({this.X = 0.0, this.Y = 0.0, this.Z = 0.0});
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object otherz) {
|
||||||
|
if (otherz is Vector3d) {
|
||||||
|
Vector3d other = otherz;
|
||||||
|
return X == other.X && Y == other.Y && Z == other.Z;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3d operator +(Vector3d other) {
|
||||||
|
Vector3d n = Clone();
|
||||||
|
n.X += other.X;
|
||||||
|
n.Y += other.Y;
|
||||||
|
n.Z += other.Z;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3d operator -(Vector3d other) {
|
||||||
|
Vector3d n = Clone();
|
||||||
|
n.X -= other.X;
|
||||||
|
n.Y -= other.Y;
|
||||||
|
n.Z -= other.Z;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3d operator *(Vector3d other) {
|
||||||
|
Vector3d n = Clone();
|
||||||
|
n.X *= other.X;
|
||||||
|
n.Y *= other.Y;
|
||||||
|
n.Z *= other.Z;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3d operator /(Vector3d other) {
|
||||||
|
Vector3d n = Clone();
|
||||||
|
n.X /= other.X;
|
||||||
|
n.Y /= other.Y;
|
||||||
|
n.Z /= other.Z;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator >(Vector3d other) {
|
||||||
|
return (X > other.X) || (Y > other.Y) || (X > other.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator <(Vector3d other) {
|
||||||
|
return (X < other.X) || (Y < other.Y) || (X < other.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3d Clone() {
|
||||||
|
return Vector3d(X: X, Y: Y, Z: Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return "<$X, $Y, $Z>";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool inside(Vector3d min, Vector3d max) {
|
||||||
|
if (min.X <= X && max.X >= X) {
|
||||||
|
if (min.Y <= Y && max.Y >= Y) {
|
||||||
|
if (min.Z <= Z && max.Z >= Z) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Vector3i {
|
||||||
|
static final Vector3i ZERO = Vector3i(X: 0, Y: 0, Z: 0);
|
||||||
|
int X = 0;
|
||||||
|
int Y = 0;
|
||||||
|
int Z = 0;
|
||||||
|
|
||||||
|
Vector3i({this.X = 0, this.Y = 0, this.Z = 0});
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object otherz) {
|
||||||
|
if (otherz is Vector3i) {
|
||||||
|
Vector3i other = otherz;
|
||||||
|
return X == other.X && Y == other.Y && Z == other.Z;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3i operator +(Vector3i other) {
|
||||||
|
Vector3i n = Clone();
|
||||||
|
n.X += other.X;
|
||||||
|
n.Y += other.Y;
|
||||||
|
n.Z += other.Z;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3i operator -(Vector3i other) {
|
||||||
|
Vector3i n = Clone();
|
||||||
|
n.X -= other.X;
|
||||||
|
n.Y -= other.Y;
|
||||||
|
n.Z -= other.Z;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3i operator *(Vector3i other) {
|
||||||
|
Vector3i n = Clone();
|
||||||
|
n.X *= other.X;
|
||||||
|
n.Y *= other.Y;
|
||||||
|
n.Z *= other.Z;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3i operator /(Vector3i other) {
|
||||||
|
Vector3i n = Clone();
|
||||||
|
n.X = (n.X / other.X).round();
|
||||||
|
n.Y = (n.Y / other.Y).round();
|
||||||
|
n.Z = (n.Z / other.Z).round();
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator >(Vector3i other) {
|
||||||
|
return (X > other.X) || (Y > other.Y) || (X > other.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator <(Vector3i other) {
|
||||||
|
return (X < other.X) || (Y < other.Y) || (X < other.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3i Clone() {
|
||||||
|
return Vector3i(X: X, Y: Y, Z: Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return "<$X, $Y, $Z>";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool inside(Vector3i min, Vector3i max) {
|
||||||
|
if (min.X <= X && max.X >= X) {
|
||||||
|
if (min.Y <= Y && max.Y >= Y) {
|
||||||
|
if (min.Z <= Z && max.Z >= Z) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
179
lib/utils/uuid/UUID.dart
Normal file
179
lib/utils/uuid/UUID.dart
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:crypto/crypto.dart';
|
||||||
|
import 'package:libac_flutter/nbt/Stream.dart';
|
||||||
|
|
||||||
|
class UUID {
|
||||||
|
late final int LSB;
|
||||||
|
late final int MSB;
|
||||||
|
late final List<int> _bytes;
|
||||||
|
|
||||||
|
UUID(int msb, int lsb) {
|
||||||
|
MSB = msb;
|
||||||
|
LSB = lsb;
|
||||||
|
|
||||||
|
ByteLayer layer = ByteLayer();
|
||||||
|
layer.writeLong(MSB);
|
||||||
|
layer.writeLong(LSB);
|
||||||
|
layer.resetPosition();
|
||||||
|
|
||||||
|
_bytes = layer.readBytes(16);
|
||||||
|
}
|
||||||
|
|
||||||
|
static final UUID ZERO = UUID.generate(0);
|
||||||
|
|
||||||
|
/// Validates whether the given [uuid] is a valid UUID.
|
||||||
|
static bool validate(String uuid) {
|
||||||
|
if (uuid.length == ((16 * 2) + 4)) {
|
||||||
|
return true; // Likely is true. This is just a surface level check
|
||||||
|
} else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parses the given [uuid] string and returns a UUID object.
|
||||||
|
static UUID parse(String uuid) {
|
||||||
|
if (validate(uuid)) {
|
||||||
|
final segments = uuid.split('-');
|
||||||
|
if (segments.length != 5) {
|
||||||
|
throw const FormatException('Invalid UUID format');
|
||||||
|
}
|
||||||
|
|
||||||
|
final msbString = segments.sublist(0, 3).join('');
|
||||||
|
final lsbString = segments.sublist(3, 5).join('');
|
||||||
|
|
||||||
|
int msb = 0;
|
||||||
|
int lsb = 0;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
ByteLayer layer = ByteLayer();
|
||||||
|
for (i = 0; i < msbString.length; i += 2) {
|
||||||
|
String hex = "${msbString.substring(i, i + 2)}";
|
||||||
|
int byte = int.parse(hex, radix: 16);
|
||||||
|
layer.writeByte(byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < lsbString.length; i += 2) {
|
||||||
|
String hex = "${lsbString.substring(i, i + 2)}";
|
||||||
|
int byte = int.parse(hex, radix: 16);
|
||||||
|
layer.writeByte(byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
layer.resetPosition();
|
||||||
|
msb = layer.readLong();
|
||||||
|
lsb = layer.readLong();
|
||||||
|
|
||||||
|
return UUID(msb, lsb);
|
||||||
|
} else
|
||||||
|
return UUID.ZERO;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
String hexBuilder = "";
|
||||||
|
for (int byte in _bytes) {
|
||||||
|
hexBuilder += byte.toRadixString(16).padLeft(2, '0');
|
||||||
|
}
|
||||||
|
return '${hexBuilder.substring(0, 8)}-${hexBuilder.substring(8, 12)}-${hexBuilder.substring(12, 16)}-${hexBuilder.substring(16, 20)}-${hexBuilder.substring(20, 32)}';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the Most Significant Bits (MSB) long value of the UUID.
|
||||||
|
int getMostSignificantBits() => MSB;
|
||||||
|
|
||||||
|
/// Returns the Least Significant Bits (LSB) long value of the UUID.
|
||||||
|
int getLeastSignificantBits() => LSB;
|
||||||
|
|
||||||
|
/// Factory method to generate UUID of the specific version.
|
||||||
|
factory UUID.generate(int version, {List<Object>? parameters}) {
|
||||||
|
List<Object> params = [];
|
||||||
|
if (parameters == null) {
|
||||||
|
if (version != 4) {
|
||||||
|
return UUID.generate(4);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
params = parameters!;
|
||||||
|
switch (version) {
|
||||||
|
case 0:
|
||||||
|
return UUID(0, 0);
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
if (params.length != 2)
|
||||||
|
throw Exception(
|
||||||
|
"UUID v3 requires two parameters, [namespace,name]");
|
||||||
|
String namespace = params[0] as String;
|
||||||
|
String name = params[1] as String;
|
||||||
|
|
||||||
|
ByteLayer layer = ByteLayer();
|
||||||
|
|
||||||
|
final namespaceBytes = utf8.encode(namespace);
|
||||||
|
layer.writeBytes(namespaceBytes);
|
||||||
|
final nameBytes = utf8.encode(name);
|
||||||
|
layer.writeBytes(nameBytes);
|
||||||
|
|
||||||
|
var bytes = md5.convert(List.from(layer.bytes)).bytes;
|
||||||
|
layer.clear();
|
||||||
|
layer.writeBytes(bytes);
|
||||||
|
|
||||||
|
layer.unsetSetBit(6, 0xF0, 0x30);
|
||||||
|
layer.unsetSetBit(8, 0xC0, 0x80);
|
||||||
|
|
||||||
|
layer.resetPosition();
|
||||||
|
|
||||||
|
var msb = layer.readUnsignedLong();
|
||||||
|
var lsb = layer.readUnsignedLong();
|
||||||
|
|
||||||
|
layer.resetPosition();
|
||||||
|
return UUID(msb, lsb);
|
||||||
|
}
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
ByteLayer layer = ByteLayer();
|
||||||
|
final random = Random.secure();
|
||||||
|
|
||||||
|
layer.writeLong(
|
||||||
|
(random.nextInt(0xFFFFFFFF) << 32) | random.nextInt(0xFFFFFFFF));
|
||||||
|
layer.writeLong(
|
||||||
|
(random.nextInt(0xFFFFFFFF) << 32) | random.nextInt(0xFFFFFFFF));
|
||||||
|
|
||||||
|
layer.unsetSetBit(6, 0xF0, 0x40);
|
||||||
|
layer.unsetSetBit(8, 0xC0, 0x80);
|
||||||
|
|
||||||
|
layer.resetPosition();
|
||||||
|
|
||||||
|
return UUID(layer.readUnsignedLong(), layer.readUnsignedLong());
|
||||||
|
}
|
||||||
|
case 5:
|
||||||
|
{
|
||||||
|
ByteLayer layer = ByteLayer();
|
||||||
|
if (params.length != 2)
|
||||||
|
throw Exception(
|
||||||
|
"UUID v5 requires two parameters, [namespace,name]");
|
||||||
|
String namespace = params[0] as String;
|
||||||
|
String name = params[1] as String;
|
||||||
|
|
||||||
|
if (!namespace.isEmpty) {
|
||||||
|
final namespaceBytes = utf8.encode(namespace);
|
||||||
|
layer.writeBytes(namespaceBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!name.isEmpty) {
|
||||||
|
final nameBytes = utf8.encode(name);
|
||||||
|
layer.writeBytes(nameBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
final hashBytes = sha1.convert(List.from(layer.bytes)).bytes;
|
||||||
|
layer.clear();
|
||||||
|
layer.writeBytes(hashBytes);
|
||||||
|
|
||||||
|
layer.unsetSetBit(6, 0xF0, 0x50);
|
||||||
|
layer.unsetSetBit(8, 0xC0, 0x80);
|
||||||
|
|
||||||
|
layer.resetPosition();
|
||||||
|
|
||||||
|
return UUID(layer.readUnsignedLong(), layer.readUnsignedLong());
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw ArgumentError('Unsupported UUID version: $version');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ environment:
|
||||||
flutter: ">=1.17.0"
|
flutter: ">=1.17.0"
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
|
crypto: ^3.0.3
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,10 @@ import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:libac_flutter/nbt/NbtIo.dart';
|
import 'package:libac_flutter/nbt/NbtIo.dart';
|
||||||
|
import 'package:libac_flutter/nbt/NbtUtils.dart';
|
||||||
import 'package:libac_flutter/nbt/impl/CompoundTag.dart';
|
import 'package:libac_flutter/nbt/impl/CompoundTag.dart';
|
||||||
import 'package:libac_flutter/nbt/impl/StringTag.dart';
|
import 'package:libac_flutter/nbt/impl/StringTag.dart';
|
||||||
|
import 'package:libac_flutter/utils/uuid/UUID.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
test('read non-compressed helloworld NBT', () async {
|
test('read non-compressed helloworld NBT', () async {
|
||||||
|
@ -44,4 +46,13 @@ void main() {
|
||||||
expect(tag.get("doubleTest")!.asDouble(), 0.4931287132182315);
|
expect(tag.get("doubleTest")!.asDouble(), 0.4931287132182315);
|
||||||
expect(tag.get("floatTest")!.asFloat(), 0.49823147);
|
expect(tag.get("floatTest")!.asFloat(), 0.49823147);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("Generate a UUID v4, save to NBT, and read it back again", () async {
|
||||||
|
var id = UUID.generate(4);
|
||||||
|
CompoundTag tag = CompoundTag();
|
||||||
|
NbtUtils.writeUUID(tag, "test", id);
|
||||||
|
|
||||||
|
var newID = NbtUtils.readUUID(tag, "test");
|
||||||
|
expect(id.toString(), newID.toString());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
78
test/uuid_test.dart
Normal file
78
test/uuid_test.dart
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:libac_flutter/nbt/Stream.dart';
|
||||||
|
import 'package:libac_flutter/utils/uuid/UUID.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
test("Store a 64bit value in int", () {
|
||||||
|
int X = 9223372036854775807;
|
||||||
|
expect(X.toString(), "9223372036854775807");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Generate a UUID v4", () {
|
||||||
|
var ID = UUID.generate(4);
|
||||||
|
expect(UUID.validate(ID.toString()), true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Generate 10 UUIDv4", () {
|
||||||
|
List<UUID> ID = [];
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
ID.add(UUID.generate(4));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (UUID sID in ID) {
|
||||||
|
print("ID : ${sID}}");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Check UUIDv4 for validity", () {
|
||||||
|
var ID = UUID.generate(4);
|
||||||
|
ByteLayer layer = ByteLayer();
|
||||||
|
layer.writeLong(ID.getMostSignificantBits().toInt());
|
||||||
|
layer.writeLong(ID.getLeastSignificantBits().toInt());
|
||||||
|
|
||||||
|
print(
|
||||||
|
"Checking version bit: ${layer.checkBit(6, 0x40)} - ${layer.getBit(6)}");
|
||||||
|
expect(layer.checkBit(6, 0x40), true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Generate and check a UUIDv3", () {
|
||||||
|
var ID3 = UUID.generate(3, parameters: ["Test", "Test2"]);
|
||||||
|
ByteLayer layer = ByteLayer();
|
||||||
|
layer.writeLong(ID3.getMostSignificantBits().toInt());
|
||||||
|
layer.writeLong(ID3.getLeastSignificantBits().toInt());
|
||||||
|
|
||||||
|
print(
|
||||||
|
"Checking version bit: ${layer.checkBit(6, 0x30)} - ${layer.getBit(6)}");
|
||||||
|
expect(layer.checkBit(6, 0x30), true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Test stream bitflipping", () {
|
||||||
|
ByteLayer layer = ByteLayer();
|
||||||
|
layer.writeBytes({0, 255, 80});
|
||||||
|
layer.setBit(0, 0x10);
|
||||||
|
layer.unsetSetBit(1, 0x0F, 0x50);
|
||||||
|
|
||||||
|
expect(layer.checkBit(0, 0x10), true);
|
||||||
|
expect(layer.checkBit(1, 0x50), true);
|
||||||
|
expect(layer.getBit(2), 80);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Test v3 implementation", () {
|
||||||
|
var expected =
|
||||||
|
"3e1b8c8a-efab-381b-ab57-4764c45b0889"; // Minecraft offline UUID : zontreck
|
||||||
|
var ID3 = UUID.generate(3, parameters: ["OfflinePlayer:zontreck", ""]);
|
||||||
|
|
||||||
|
expect(ID3.toString(), expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Parse a v3 and compare", () {
|
||||||
|
var asString = "3e1b8c8a-efab-381b-ab57-4764c45b0889";
|
||||||
|
var ID3 = UUID.parse(asString);
|
||||||
|
var ID3X = UUID.generate(3, parameters: ["OfflinePlayer:zontreck", ""]);
|
||||||
|
|
||||||
|
expect(ID3.MSB, ID3X.MSB);
|
||||||
|
expect(ID3.LSB, ID3X.LSB);
|
||||||
|
|
||||||
|
expect(ID3.toString(), asString);
|
||||||
|
});
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue