#include "DimensionMap.h" #include "Constants.h" #include "World.h" DimensionMap::DimensionMap() : ZeichnungHintergrund(), originChunkCenter(0, 0), scrollOffset(0, 0), chunkCount(0), pixelsPerBlock(16), maxHeight(255), waitingForChunk(0), drag(0) { setStyle(Style::Sichtbar | Style::Erlaubt); chunks = new Framework::Trie<ChunkMap>(); setMausEreignis(_ret1ME); requestNextChunk(); } DimensionMap::~DimensionMap() { chunks->release(); } void DimensionMap::getAddrOf(Punkt cPos, char* addr) const { *(int*)addr = cPos.x; *((int*)addr + 1) = cPos.y; } void DimensionMap::getAddrOfWorld(Punkt wPos, char* addr) const { // needed because otherwise would (-8, -8) have the same // adress as (8, 8) if (wPos.x < 0) wPos.x -= CHUNK_SIZE; if (wPos.y < 0) wPos.y -= CHUNK_SIZE; wPos /= CHUNK_SIZE; getAddrOf(wPos, addr); } Framework::Punkt DimensionMap::getMinVisibleChunkCenter( Framework::Punkt& screenPos) const { screenPos = getSize() / 2 - scrollOffset; Punkt currentChunkCenter = originChunkCenter; while (screenPos.x + pixelsPerBlock * (CHUNK_SIZE / 2) >= 0) { screenPos.x -= pixelsPerBlock * CHUNK_SIZE; currentChunkCenter.x -= CHUNK_SIZE; } while (screenPos.y + pixelsPerBlock * (CHUNK_SIZE / 2) >= 0) { screenPos.y -= pixelsPerBlock * CHUNK_SIZE; currentChunkCenter.y -= CHUNK_SIZE; } while (screenPos.x + pixelsPerBlock * (CHUNK_SIZE / 2) < 0) { screenPos.x += pixelsPerBlock * CHUNK_SIZE; currentChunkCenter.x += CHUNK_SIZE; } while (screenPos.y + pixelsPerBlock * (CHUNK_SIZE / 2) < 0) { screenPos.y += pixelsPerBlock * CHUNK_SIZE; currentChunkCenter.y += CHUNK_SIZE; } return currentChunkCenter; } Framework::Punkt DimensionMap::getMaxVisibleChunkCenter( Framework::Punkt& screenPos) const { screenPos = getSize() / 2 - scrollOffset; Punkt currentChunkCenter = originChunkCenter; while (screenPos.x - pixelsPerBlock * (CHUNK_SIZE / 2) < getBreite()) { screenPos.x += pixelsPerBlock * CHUNK_SIZE; currentChunkCenter.x += CHUNK_SIZE; } while (screenPos.y - pixelsPerBlock * (CHUNK_SIZE / 2) < getHeight()) { screenPos.y += pixelsPerBlock * CHUNK_SIZE; currentChunkCenter.y += CHUNK_SIZE; } while (screenPos.x - pixelsPerBlock * (CHUNK_SIZE / 2) >= getBreite()) { screenPos.x -= pixelsPerBlock * CHUNK_SIZE; currentChunkCenter.x -= CHUNK_SIZE; } while (screenPos.y - pixelsPerBlock * (CHUNK_SIZE / 2) >= getHeight()) { screenPos.y -= pixelsPerBlock * CHUNK_SIZE; currentChunkCenter.y -= CHUNK_SIZE; } return currentChunkCenter; } bool DimensionMap::tick(double time) { if (lastSize != getSize()) { lastSize = getSize(); requestNextChunk(); } return ZeichnungHintergrund::tick(time); } void DimensionMap::requestNextChunk() { cs.lock(); if (waitingForChunk) { cs.unlock(); return; } if (chunkCount == 0) { waitingForChunk = 1; Vec3<float> playerPos = World::INSTANCE->getCurrentPlayerEntity()->getPos(); char msg[9]; msg[0] = 2; *(int*)(msg + 1) = (int)playerPos.x; *(int*)(msg + 5) = (int)playerPos.y; World::INSTANCE->zClient()->dimensionAPIRequest(msg, 9); } else { Punkt minScreenPos; Punkt minVisibleChunk = getMinVisibleChunkCenter(minScreenPos); Punkt maxScreenPos; Punkt maxVisibleChunk = getMaxVisibleChunkCenter(maxScreenPos); Punkt screenPos = minScreenPos; Punkt screenCenter = getSize() / 2; double minDist = -1; Punkt resultChunk(0, 0); char addr[8]; for (int x = minVisibleChunk.x; x <= maxVisibleChunk.x; x += CHUNK_SIZE) { for (int y = minVisibleChunk.y; y <= maxVisibleChunk.y; y += CHUNK_SIZE) { getAddrOfWorld({x, y}, addr); if (!chunks->z(addr, 8)) { if (minDist < 0 || (screenCenter - screenPos).getLengthSq() < minDist) { minDist = (screenCenter - screenPos).getLengthSq(); resultChunk = {x, y}; } } screenPos.y += pixelsPerBlock * CHUNK_SIZE; } screenPos.x += pixelsPerBlock * CHUNK_SIZE; screenPos.y = minScreenPos.y; } if (minDist >= 0) { waitingForChunk = 1; char msg[9]; msg[0] = 2; *(int*)(msg + 1) = (int)resultChunk.x; *(int*)(msg + 5) = (int)resultChunk.y; World::INSTANCE->zClient()->dimensionAPIRequest(msg, 9); } } cs.unlock(); } void DimensionMap::addChunk(ChunkMap* chunk) { cs.lock(); if (chunkCount == 0) originChunkCenter = chunk->getChunkCenter(); char addr[8]; getAddrOfWorld(chunk->getChunkCenter(), addr); chunks->set(addr, 8, chunk); chunkCount++; waitingForChunk = 0; cs.unlock(); requestNextChunk(); } void DimensionMap::render(Framework::Bild& rObj) { ZeichnungHintergrund::render(rObj); if (!rObj.setDrawOptions(innenPosition, innenSize)) return; cs.lock(); Punkt minScreenPos; Punkt minVisibleChunk = getMinVisibleChunkCenter(minScreenPos); Punkt maxScreenPos; Punkt maxVisibleChunk = getMaxVisibleChunkCenter(maxScreenPos); char addr[8]; Punkt screenPos = minScreenPos; for (int x = minVisibleChunk.x; x <= maxVisibleChunk.x; x += CHUNK_SIZE) { for (int y = minVisibleChunk.y; y <= maxVisibleChunk.y; y += CHUNK_SIZE) { getAddrOfWorld({x, y}, addr); ChunkMap* map = chunks->z(addr, 8); if (map) { map->setMaxHeight((unsigned char)maxHeight); rObj.drawBildSkall( screenPos.x - (pixelsPerBlock * CHUNK_SIZE) / 2, screenPos.y - (pixelsPerBlock * CHUNK_SIZE) / 2, pixelsPerBlock * CHUNK_SIZE, pixelsPerBlock * CHUNK_SIZE, map->getRenderedImage()); } screenPos.y += pixelsPerBlock * CHUNK_SIZE; } screenPos.x += pixelsPerBlock * CHUNK_SIZE; screenPos.y = minScreenPos.y; } cs.unlock(); rObj.releaseDrawOptions(); } void DimensionMap::doMausEreignis(Framework::MausEreignis& me, bool userRet) { if (me.id == ME_PLinks) { drag = 1; lastMouse = {me.mx, me.my}; } if (me.id == ME_RLinks || me.id == ME_Leaves) drag = 0; if (me.id == ME_Bewegung && drag) { scrollOffset -= Punkt(me.mx, me.my) - lastMouse; lastMouse = Punkt(me.mx, me.my); rend = 1; requestNextChunk(); } if (me.id == ME_DScroll && pixelsPerBlock > 1) { scrollOffset = (scrollOffset / pixelsPerBlock) * (pixelsPerBlock - 1); pixelsPerBlock--; rend = 1; requestNextChunk(); } if (me.id == ME_UScroll) { scrollOffset = (scrollOffset / pixelsPerBlock) * (pixelsPerBlock + 1); pixelsPerBlock++; rend = 1; requestNextChunk(); } if (me.id == ME_RRechts) { if (maxHeight != 255) { maxHeight = 255; } else { maxHeight = (int)(World::INSTANCE->getCurrentPlayerEntity()->getPos().z / 2); } rend = 1; } ZeichnungHintergrund::doMausEreignis(me, userRet); }