#include "ChunkMap.h" #include "Chunk.h" #include "Constants.h" #include "Game.h" ChunkMap::ChunkMap(Framework::Punkt chunkCenter) : ReferenceCounter(), chunkCenter(chunkCenter) { pixels = new MapPixel[CHUNK_SIZE * CHUNK_SIZE]; memset(pixels, 0, sizeof(MapPixel) * CHUNK_SIZE * CHUNK_SIZE); } ChunkMap::ChunkMap(Chunk* zChunk) : ReferenceCounter(), chunkCenter(zChunk->location) { pixels = new MapPixel[CHUNK_SIZE * CHUNK_SIZE]; memset(pixels, 0, sizeof(MapPixel) * CHUNK_SIZE * CHUNK_SIZE); MapBlock blocksBuffer[256]; for (int x = 0; x < CHUNK_SIZE; x++) { for (int y = 0; y < CHUNK_SIZE; y++) { int count = 0; bool visible = 1; for (int height = WORLD_HEIGHT / 2 - 1; height >= 0; height--) { int index = (x * CHUNK_SIZE + y) * WORLD_HEIGHT; const Block* block1 = CONST_BLOCK(zChunk->blocks[index + height * 2], zChunk->blockIds[index + height * 2]); const Block* block2 = CONST_BLOCK(zChunk->blocks[index + height * 2 + 1], zChunk->blockIds[index + height * 2 + 1]); int color1 = 0; int color2 = 0; if (visible) color2 = block2->getMapColor(); visible = block2->isPassable() || block2->isTransparent(); if (visible) color1 = block1->getMapColor(); visible = block1->isPassable() || block1->isTransparent(); if (color1 || color2) { MapBlock tmp = {(unsigned char)height, ((color1 >> 24) & 0xFF) > ((color2 >> 24) & 0xFF) ? color1 : color2}; blocksBuffer[256 - ++count] = tmp; } } int i = x * CHUNK_SIZE + y; pixels[i].blocks = new MapBlock[count]; memcpy(pixels[i].blocks, blocksBuffer + 256 - count, sizeof(MapBlock) * count); pixels[i].len = (unsigned char)count; } } } ChunkMap::ChunkMap(Framework::StreamReader* zReader) : ReferenceCounter() { zReader->lese((char*)&chunkCenter.x, 4); zReader->lese((char*)&chunkCenter.y, 4); pixels = new MapPixel[CHUNK_SIZE * CHUNK_SIZE]; memset(pixels, 0, sizeof(MapPixel) * CHUNK_SIZE * CHUNK_SIZE); for (int i = 0; i < CHUNK_SIZE * CHUNK_SIZE; i++) { zReader->lese((char*)&pixels[i].len, 1); if (pixels[i].len > 0) { pixels[i].blocks = new MapBlock[pixels[i].len]; zReader->lese( (char*)pixels[i].blocks, (int)sizeof(MapBlock) * pixels[i].len); } } } ChunkMap::~ChunkMap() { for (int i = 0; i < CHUNK_SIZE * CHUNK_SIZE; i++) { delete[] pixels[i].blocks; } delete[] pixels; } bool ChunkMap::update( char x, char y, unsigned char height, int color1, int color2) { cs.lock(); int index = x * CHUNK_SIZE + y; bool found = 0; int resultColor = ((color1 >> 24) & 0xFF) > ((color2 >> 24) & 0xFF) ? color1 : color2; bool removed = !((resultColor >> 24) & 0xFF); bool changed = 0; for (int i = 0; i < pixels[index].len; i++) { if (pixels[index].blocks[i].height == height) { changed = pixels[index].blocks[i].color != resultColor; pixels[index].blocks[i].color = resultColor; found = 1; } else if (!found && pixels[index].blocks[i].height > height) { break; } if (found && removed && i < pixels[index].len - 1) { pixels[index].blocks[i] = pixels[index].blocks[i + 1]; } } if (found && removed) { changed = 1; pixels[index].len--; } else if (!found && !removed) { MapBlock* blocks = new MapBlock[pixels[index].len + 1]; bool added = 0; for (int i = 0; i < pixels[index].len; i++) { if (pixels[index].blocks[i].height < height) { blocks[i] = pixels[index].blocks[i]; } else { if (!added) { blocks[i] = {height, resultColor}; added = 1; } blocks[i + 1] = pixels[index].blocks[i]; } } if (!added) { blocks[pixels[index].len] = {height, resultColor}; } changed = 1; pixels[index].len++; delete[] pixels[index].blocks; pixels[index].blocks = blocks; } cs.unlock(); return changed; } void ChunkMap::writeTo(Framework::StreamWriter* zWriter) const { zWriter->schreibe((char*)&chunkCenter.x, 4); zWriter->schreibe((char*)&chunkCenter.y, 4); for (int i = 0; i < CHUNK_SIZE * CHUNK_SIZE; i++) { zWriter->schreibe((char*)&pixels[i].len, 1); if (pixels[i].len > 0) { zWriter->schreibe( (char*)pixels[i].blocks, (int)sizeof(MapBlock) * pixels[i].len); } } } Framework::Punkt ChunkMap::getChunkCenter() const { return chunkCenter; }