Skip to content

Commit

Permalink
Added support for minecraft region files (.mca)
Browse files Browse the repository at this point in the history
  • Loading branch information
Howaner committed Feb 11, 2018
1 parent 9e41816 commit c8b076a
Show file tree
Hide file tree
Showing 20 changed files with 321 additions and 23 deletions.
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.1.0)

project(nbteditor VERSION 1.1)
set (NBTEDITOR_VERSION 1.1)
project(nbteditor VERSION 1.2)
set (NBTEDITOR_VERSION 1.2)

find_package(Qt5Widgets)

Expand Down
8 changes: 8 additions & 0 deletions src/File/ByteBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ namespace File {
return (((unsigned short) reader->ReadByte()) << 8) | reader->ReadByte();
}

jint ByteBuffer::ReadThreeBytesInt() {
Byte* bytes = ReadBytes(3);
jint number = ((bytes[0] & 0x0F) << 16) | ((bytes[1] & 0xFF) << 8) | ((bytes[2] & 0xFF));

delete[] bytes;
return number;
}

jint ByteBuffer::ReadInt() {
Byte* bytes = ReadBytes(4);
std::reverse(bytes, bytes + 4); // Big-Endian to Little-Endian
Expand Down
1 change: 1 addition & 0 deletions src/File/ByteBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ namespace File {
jbyte ReadSignedByte();
jshort ReadShort();
unsigned short ReadUShort();
jint ReadThreeBytesInt(); // Used in minecraft level format
jint ReadInt();
jlong ReadLong();
jdouble ReadDouble();
Expand Down
5 changes: 3 additions & 2 deletions src/File/GzipByteReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#include <algorithm>

namespace File {
GzipByteReader::GzipByteReader(Byte* data, uint dataLength) : finishedRead(false), bufferLength(0), offset(0), bufferOffset(0) {
GzipByteReader::GzipByteReader(Byte* data, uint dataLength, bool gzip) : gzip(gzip), finishedRead(false), bufferLength(0), offset(0), bufferOffset(0) {
memset(&stream, 0, sizeof stream);
stream.zalloc = (alloc_func)0;
stream.zfree = (free_func)0;
Expand All @@ -18,7 +18,8 @@ namespace File {

buffer = new Byte[GZIP_BUFFER_SIZE];

int result = inflateInit2(&stream, MAX_WBITS | 16);
int zlibFlags = (gzip ? (MAX_WBITS | 16) : MAX_WBITS);
int result = inflateInit2(&stream, zlibFlags);
if (result != 0)
throw Exception::GzipException("ZLIB init failed: " + std::to_string(result));
FillNextBuffer();
Expand Down
7 changes: 3 additions & 4 deletions src/File/GzipByteReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
namespace File {
class GzipByteReader : public ByteReader {
public:
GzipByteReader(Byte* data, uint dataLength);
GzipByteReader(Byte* data, uint dataLength, bool gzip = true);
~GzipByteReader();
Byte ReadByte();
Byte* ReadBytes(uint length);
Expand All @@ -15,10 +15,9 @@ namespace File {
void FillNextBuffer();
Byte* GetBuffer() { return buffer; }

protected:
// void FillNextBuffer();

private:
bool gzip;

z_stream stream;
bool finishedRead;

Expand Down
5 changes: 3 additions & 2 deletions src/File/GzipByteWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace File {

GzipByteWriter::GzipByteWriter(ByteWriter* parentWriter) : bufferLength(0), bufferOffset(0), parentWriter(parentWriter) {
GzipByteWriter::GzipByteWriter(ByteWriter* parentWriter, bool gzip) : gzip(gzip), bufferLength(0), bufferOffset(0), parentWriter(parentWriter) {
memset(&stream, 0, sizeof stream);
stream.zalloc = (alloc_func)0;
stream.zfree = (free_func)0;
Expand All @@ -19,7 +19,8 @@ namespace File {
stream.avail_in = bufferOffset;
stream.next_in = buffer;

int result = deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, MAX_WBITS + 16, 8, Z_DEFAULT_STRATEGY);
int zlibFlags = (gzip ? (MAX_WBITS | 16) : MAX_WBITS);
int result = deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, zlibFlags, 8, Z_DEFAULT_STRATEGY);
if (result != 0)
throw Exception::GzipException("ZLIB deflate init failed: " + std::to_string(result));
}
Expand Down
3 changes: 2 additions & 1 deletion src/File/GzipByteWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
namespace File {
class GzipByteWriter : public ByteWriter {
public:
GzipByteWriter(ByteWriter* parentWriter);
GzipByteWriter(ByteWriter* parentWriter, bool gzip = true);
~GzipByteWriter();

void WriteByte(const Byte byte);
Expand All @@ -19,6 +19,7 @@ namespace File {
void DoGzipCompression(int mode, int expectedResult);

private:
bool gzip;
z_stream stream;

Byte* buffer;
Expand Down
62 changes: 62 additions & 0 deletions src/File/MemoryByteWriter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include "MemoryByteWriter.h"
#include "Exception/StreamOverflowException.h"
#include <cstring>
#include <algorithm>

namespace File {

MemoryByteWriter::MemoryByteWriter() : bufferOffset(0) {
buffer = new Byte[WRITE_BUFFER_SIZE];
bufferSize = WRITE_BUFFER_SIZE;
}

MemoryByteWriter::~MemoryByteWriter() {
delete[] buffer;
bufferOffset = 0;
bufferSize = 0;
}

void MemoryByteWriter::WriteByte(const Byte byte) {
if (bufferOffset >= bufferSize)
IncreaseBufferSize();

buffer[bufferOffset++] = byte;
}

void MemoryByteWriter::WriteBytes(const Byte* bytes, uint length) {
uint writtenBytes = 0;
while (writtenBytes < length) {
if (bufferOffset >= bufferSize)
IncreaseBufferSize();

uint bytesToWrite = std::min(bufferSize - bufferOffset, length - writtenBytes);
std::memcpy(buffer + bufferOffset, bytes + writtenBytes, bytesToWrite);

bufferOffset += bytesToWrite;
writtenBytes += bytesToWrite;
}
}

NBT::NBTArray<Byte> MemoryByteWriter::GetByteArray() {
Byte* resultArray = new Byte[bufferOffset];
std::memcpy(resultArray, buffer, bufferOffset);

NBT::NBTArray<Byte> returnArray((int)bufferOffset, resultArray);
return returnArray;
}

void MemoryByteWriter::SetBufferByte(uint offset, const Byte byte) {
if (offset >= bufferSize)
throw Exception::StreamOverflowException(offset, 1, bufferSize);
buffer[offset] = byte;
}

void MemoryByteWriter::IncreaseBufferSize() {
int newSize = bufferSize * 2;
Byte* newBuffer = new Byte[newSize];
std::memcpy(newBuffer, buffer, bufferSize);

buffer = newBuffer;
bufferSize = newSize;
}
}
18 changes: 14 additions & 4 deletions src/File/MemoryByteWriter.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once
#include "Globals.h"
#include "ByteWriter.h"
#include "NBT/NBTEntry.h"

namespace File {
class MemoryByteWriter : public ByteWriter {
Expand All @@ -9,11 +11,19 @@ namespace File {

void WriteByte(const Byte byte);
void WriteBytes(const Byte* bytes, uint length);
void Flush();
void Flush() {}

NBT::NBTArray<Byte> GetByteArray();
uint GetOffset() { return bufferOffset; }

void SetBufferByte(uint offset, const Byte byte);

protected:
void IncreaseBufferSize();

private:
Byte* data;
uint dataLength;
uint dataOffset;
Byte* buffer;
uint bufferOffset;
uint bufferSize;
};
}
6 changes: 6 additions & 0 deletions src/File/WriteBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ namespace File {
WriteByte(val & 0xFF);
}

void WriteBuffer::WriteThreeBytesInt(jint val) {
WriteByte((val >> 16) & 0x0F);
WriteByte((val >> 8) & 0xFF);
WriteByte(val & 0xFF);
}

void WriteBuffer::WriteInt(jint val) {
Byte bytes[4];
memcpy(bytes, &val, 4);
Expand Down
1 change: 1 addition & 0 deletions src/File/WriteBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ namespace File {

void WriteSignedByte(jbyte val);
void WriteShort(jshort val);
void WriteThreeBytesInt(jint val);
void WriteInt(jint val);
void WriteLong(jlong val);
void WriteDouble(jdouble val);
Expand Down
1 change: 1 addition & 0 deletions src/Globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ static_assert(sizeof(double) == 8, "Assuming that a double is 8 byte long");
typedef unsigned char Byte;
typedef unsigned int uint;
const unsigned int GZIP_BUFFER_SIZE = 128;
const unsigned int WRITE_BUFFER_SIZE = 256;
const unsigned int MIN_TAG = 1;
const unsigned int MAX_TAG = 11;

Expand Down
12 changes: 11 additions & 1 deletion src/NBT/NBTCompound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,18 @@

namespace NBT {

NBTCompound::NBTCompound() : noFree(false) {
}

NBTCompound::NBTCompound(NBTCompound* oldCompound) : noFree(true) {
for (auto& entry : oldCompound->entries) {
entries.push_back(entry);
}
}

NBTCompound::~NBTCompound() {
Free();
if (!noFree)
Free();
}

void NBTCompound::Free() {
Expand Down
6 changes: 3 additions & 3 deletions src/NBT/NBTCompound.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
#include "NBTEntry.h"
#include "Globals.h"
#include <vector>
#include <QModelIndex>

namespace File {
class ByteBuffer;
Expand All @@ -14,7 +13,8 @@ namespace NBT {

class NBTCompound {
public:
NBTCompound() {}
NBTCompound();
NBTCompound(NBTCompound* oldCompound); // Create a copy
~NBTCompound();

void Free();
Expand All @@ -29,7 +29,7 @@ namespace NBT {
bool RemoveEntry(NBTEntry* entry);

private:
bool noFree;
std::vector<NBTEntry*> entries;
static const NBTTag** tagsByType;
};
}
10 changes: 9 additions & 1 deletion src/NBT/NBTEntry.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#pragma once
#include <vector>
#include "NBTType.h"
#include <QModelIndex>
#include <QString>
#include "Globals.h"

namespace NBT {

Expand Down Expand Up @@ -41,4 +41,12 @@ namespace NBT {
type = NbtEnd;
}
};

struct RegionChunkInformation {
int relX;
int relZ;
int offset;
int lastChange;
Byte roundedSize;
};
}
Loading

0 comments on commit c8b076a

Please sign in to comment.