Skip to content
This repository was archived by the owner on May 8, 2023. It is now read-only.

Optimized memory consumption for full converted regions/chunks #28

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 36 additions & 19 deletions anvil/empty_region.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,28 @@ def from_inclusive(a, b):
class EmptyRegion:
"""
Used for making own regions

Attributes
----------
chunks: List[:class:`anvil.EmptyChunk`]
List of chunks in this region
chunks_data: List
List of packed chunks
x: :class:`int`
z: :class:`int`
"""
__slots__ = ('chunks', 'x', 'z')
__slots__ = ('chunks', 'chunks_data', 'x', 'z')
def __init__(self, x: int, z: int):
# Create a 1d list for the 32x32 chunks
self.chunks: List[EmptyChunk] = [None] * 1024
self.chunks_data = [None] * 1024
self.x = x
self.z = z

def inside(self, x: int, y: int, z: int, chunk: bool=False) -> bool:
"""
Returns if the given coordinates are inside this region

Parameters
----------
int x, y, z
Expand All @@ -51,7 +54,7 @@ def inside(self, x: int, y: int, z: int, chunk: bool=False) -> bool:
def get_chunk(self, x: int, z: int) -> EmptyChunk:
"""
Returns the chunk at given chunk coordinates

Parameters
----------
int x, z
Expand All @@ -68,23 +71,32 @@ def get_chunk(self, x: int, z: int) -> EmptyChunk:
raise OutOfBoundsCoordinates(f'Chunk ({x}, {z}) is not inside this region')
return self.chunks[z % 32 * 32 + x % 32]

def add_chunk(self, chunk: EmptyChunk):
def add_chunk(self, chunk: EmptyChunk, pack: bool):
"""
Adds given chunk to this region.
Will overwrite if a chunk already exists in this location

Parameters
----------
chunk: :class:`EmptyChunk`

pack: bool

Raises
------
anvil.OutOfBoundCoordidnates
If the chunk (x, z) is not inside this region
"""
if not self.inside(chunk.x, 0, chunk.z, chunk=True):
raise OutOfBoundsCoordinates(f'Chunk ({chunk.x}, {chunk.z}) is not inside this region')
self.chunks[chunk.z % 32 * 32 + chunk.x % 32] = chunk
if pack:
chunk_data = BytesIO()
nbt_data = chunk.save()
nbt_data.write_file(buffer=chunk_data)
chunk_data.seek(0)
chunk_data = zlib.compress(chunk_data.read())
self.chunks_data[chunk.z % 32 * 32 + chunk.x % 32] = chunk_data
else:
self.chunks[chunk.z % 32 * 32 + chunk.x % 32] = chunk

def add_section(self, section: EmptySection, x: int, z: int, replace: bool=True):
"""
Expand Down Expand Up @@ -204,20 +216,25 @@ def save(self, file: Union[str, BinaryIO]=None) -> bytes:
"""
# Store all the chunks data as zlib compressed nbt data
chunks_data = []
for chunk in self.chunks:
if chunk is None:
for i in range(len(self.chunks)):
if self.chunks[i] is not None:
chunk = self.chunks[i]
chunk_data = BytesIO()
if isinstance(chunk, Chunk):
nbt_data = nbt.NBTFile()
nbt_data.tags.append(nbt.TAG_Int(name='DataVersion', value=chunk.version))
nbt_data.tags.append(chunk.data)
else:
nbt_data = chunk.save()
nbt_data.write_file(buffer=chunk_data)
chunk_data.seek(0)
chunk_data = zlib.compress(chunk_data.read())
elif self.chunks_data[i] is not None:
chunk_data = self.chunks_data[i]
else:
chunks_data.append(None)
continue
chunk_data = BytesIO()
if isinstance(chunk, Chunk):
nbt_data = nbt.NBTFile()
nbt_data.tags.append(nbt.TAG_Int(name='DataVersion', value=chunk.version))
nbt_data.tags.append(chunk.data)
else:
nbt_data = chunk.save()
nbt_data.write_file(buffer=chunk_data)
chunk_data.seek(0)
chunk_data = zlib.compress(chunk_data.read())

chunks_data.append(chunk_data)

# This is what is added after the location and timestamp header
Expand Down