123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560 |
- #include "DimensionMap.h"
- #include <DateiSystem.h>
- #include "Constants.h"
- #include "Globals.h"
- #include "World.h"
- DimensionMap::DimensionMap(MapOptions* zOptions)
- : ZeichnungHintergrund(),
- zOptions(zOptions),
- originChunkCenter(0, 0),
- scrollOffset(0, 0),
- chunkCount(0),
- pixelsPerBlock(16),
- requestCount(0),
- drag(0),
- nextPlayersRequest(-1)
- {
- setStyle(Style::Sichtbar | Style::Erlaubt);
- chunks = new Framework::RCTrie<ChunkMap>();
- setMausEreignis(_ret1ME);
- requestNextChunk();
- char msg[2];
- msg[0] = 2; // subscribe to map changes
- msg[1] = 1;
- World::INSTANCE->zClient()->dimensionAPIRequest(msg, 2);
- LTDBDatei iconsDat;
- iconsDat.setDatei(new Text("data/images/gui_icons.ltdb"));
- iconsDat.leseDaten(0);
- playerIcon = iconsDat.laden(0, new Text("player.png"));
- }
- DimensionMap::~DimensionMap()
- {
- char msg[2];
- msg[0] = 2; // unsubscribe from map changes
- msg[1] = 2;
- World::INSTANCE->zClient()->dimensionAPIRequest(msg, 2);
- chunks->release();
- playerIcon->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;
- }
- void DimensionMap::removeUnused() const
- {
- Punkt tmp;
- Framework::Punkt min
- = getMinVisibleChunkCenter(tmp) - Punkt(CHUNK_SIZE, CHUNK_SIZE) * 5;
- Framework::Punkt max
- = getMaxVisibleChunkCenter(tmp) + Punkt(CHUNK_SIZE, CHUNK_SIZE) * 5;
- char addr[8];
- for (auto i = chunkList.begin(); i;)
- {
- if (i->getChunkCenter().x < min.x || i->getChunkCenter().y < min.y
- || i->getChunkCenter().x > max.x || i->getChunkCenter().y > max.y)
- {
- getAddrOfWorld(i->getChunkCenter(), addr);
- chunks->remove(addr, 8);
- i.remove();
- }
- else
- {
- ++i;
- }
- }
- }
- void DimensionMap::updatePlayers(char* data)
- {
- int count = *(int*)data;
- data += 4;
- cs.lock();
- players.leeren();
- // read player information from data buffer
- for (int i = 0; i < count; i++)
- {
- unsigned char nameLen = (unsigned char)*data;
- data++;
- char* name = new char[nameLen + 1];
- memcpy(name, data, nameLen);
- name[nameLen] = 0;
- data += nameLen;
- MapPlayer player;
- player.name = name;
- delete[] name;
- player.position.x = *(float*)data;
- player.position.y = *(float*)(data + 4);
- player.position.z = *(float*)(data + 8);
- data += 12;
- players.add(player);
- }
- cs.unlock();
- }
- void DimensionMap::requestNextChunk()
- {
- cs.lock();
- if (requestCount >= 20)
- {
- cs.unlock();
- return;
- }
- if (chunkCount == 0)
- {
- requestCount++;
- Vec3<float> playerPos
- = World::INSTANCE->getCurrentPlayerEntity()->getPos();
- char msg[10];
- msg[0] = 2;
- msg[1] = 0;
- *(int*)(msg + 2) = (int)playerPos.x;
- *(int*)(msg + 6) = (int)playerPos.y;
- World::INSTANCE->zClient()->dimensionAPIRequest(msg, 10);
- }
- else
- {
- while (requestCount < 20)
- {
- 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)
- {
- requestCount++;
- char msg[10];
- msg[0] = 2;
- msg[1] = 0;
- *(int*)(msg + 2) = (int)resultChunk.x;
- *(int*)(msg + 6) = (int)resultChunk.y;
- World::INSTANCE->zClient()->dimensionAPIRequest(msg, 10);
- getAddrOfWorld({resultChunk.x, resultChunk.y}, addr);
- chunks->set(addr, 8, new ChunkMap(resultChunk));
- }
- else
- {
- break;
- }
- }
- }
- cs.unlock();
- }
- void DimensionMap::addChunk(ChunkMap* chunk)
- {
- cs.lock();
- if (chunkCount == 0) originChunkCenter = chunk->getChunkCenter();
- char addr[8];
- getAddrOfWorld(chunk->getChunkCenter(), addr);
- ChunkMap* old = chunks->z(addr, 8);
- if (old) chunkList.removeValue(old);
- chunks->set(addr, 8, chunk);
- chunkList.add(chunk);
- chunkCount++;
- requestCount--;
- removeUnused();
- cs.unlock();
- requestNextChunk();
- }
- bool DimensionMap::tick(double time)
- {
- if (nextPlayersRequest < 0 && zOptions->isShowPlayers())
- {
- nextPlayersRequest = 2;
- char msg[2];
- msg[0] = 2; // request map players
- msg[1] = 3;
- if (World::INSTANCE)
- {
- World::INSTANCE->zClient()->dimensionAPIRequest(msg, 2);
- }
- }
- nextPlayersRequest -= time;
- if (lastSize != getSize())
- {
- lastSize = getSize();
- requestNextChunk();
- }
- return ZeichnungHintergrund::tick(time);
- }
- void DimensionMap::render(Framework::Bild& rObj)
- {
- ZeichnungHintergrund::render(rObj);
- if (!rObj.setDrawOptions(innenPosition, innenSize)) return;
- cs.lock();
- if (zOptions->isFollowPlayer())
- {
- Vec3<float> playerPos
- = World::INSTANCE->getCurrentPlayerEntity()->getPos();
- scrollOffset
- = (Punkt((int)playerPos.x, (int)playerPos.y) - originChunkCenter)
- * pixelsPerBlock;
- requestNextChunk();
- }
- Punkt minScreenPos;
- Punkt minVisibleChunk = getMinVisibleChunkCenter(minScreenPos);
- Punkt maxScreenPos;
- Punkt maxVisibleChunk = getMaxVisibleChunkCenter(maxScreenPos);
- char addr[8];
- // render chunks
- 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)
- {
- if (zOptions->isUnderground())
- {
- map->setMaxHeight(
- (int)(World::INSTANCE->getCurrentPlayerEntity()
- ->getPos()
- .z
- / 2));
- }
- else
- {
- map->setMaxHeight(255);
- }
- Punkt topLeft(screenPos.x - (pixelsPerBlock * CHUNK_SIZE) / 2,
- screenPos.y - (pixelsPerBlock * CHUNK_SIZE) / 2);
- rObj.drawBildSkall(topLeft.x,
- topLeft.y,
- pixelsPerBlock * CHUNK_SIZE,
- pixelsPerBlock * CHUNK_SIZE,
- map->getRenderedImage());
- }
- screenPos.y += pixelsPerBlock * CHUNK_SIZE;
- }
- screenPos.x += pixelsPerBlock * CHUNK_SIZE;
- screenPos.y = minScreenPos.y;
- }
- // render shadow and borders
- 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)
- {
- Punkt topLeft(screenPos.x - (pixelsPerBlock * CHUNK_SIZE) / 2,
- screenPos.y - (pixelsPerBlock * CHUNK_SIZE) / 2);
- getAddrOfWorld({x, y - CHUNK_SIZE}, addr);
- ChunkMap* tmp = chunks->z(addr, 8);
- unsigned char* heightMapTop = tmp ? tmp->getHeightMap() : 0;
- getAddrOfWorld({x + CHUNK_SIZE, y}, addr);
- tmp = chunks->z(addr, 8);
- unsigned char* heightMapRight = tmp ? tmp->getHeightMap() : 0;
- getAddrOfWorld({x, y + CHUNK_SIZE}, addr);
- tmp = chunks->z(addr, 8);
- unsigned char* heightMapBottom = tmp ? tmp->getHeightMap() : 0;
- getAddrOfWorld({x - CHUNK_SIZE, y}, addr);
- tmp = chunks->z(addr, 8);
- unsigned char* heightMapLeft = tmp ? tmp->getHeightMap() : 0;
- unsigned char* heightMap = map->getHeightMap();
- for (int xx = 0; xx < CHUNK_SIZE; xx++)
- {
- for (int yy = 0; yy < CHUNK_SIZE; yy++)
- {
- bool shadowR = 0;
- bool shadowB = 0;
- if (xx < CHUNK_SIZE - 1)
- {
- if (heightMap[yy * CHUNK_SIZE + xx]
- > heightMap[yy * CHUNK_SIZE + xx + 1])
- {
- rObj.drawLinieVAlpha((xx * pixelsPerBlock)
- + topLeft.x
- + pixelsPerBlock,
- (yy * pixelsPerBlock) + topLeft.y,
- pixelsPerBlock,
- 0x40000000);
- shadowR = 1;
- }
- }
- else if (heightMapRight)
- {
- if (heightMap[yy * CHUNK_SIZE + xx]
- > heightMapRight[yy * CHUNK_SIZE])
- {
- rObj.drawLinieVAlpha((xx * pixelsPerBlock)
- + topLeft.x
- + pixelsPerBlock,
- (yy * pixelsPerBlock) + topLeft.y,
- pixelsPerBlock,
- 0x40000000);
- shadowR = 1;
- }
- }
- if (yy < CHUNK_SIZE - 1)
- {
- if (heightMap[yy * CHUNK_SIZE + xx]
- > heightMap[(yy + 1) * CHUNK_SIZE + xx])
- {
- rObj.drawLinieHAlpha(
- (xx * pixelsPerBlock) + topLeft.x,
- (yy * pixelsPerBlock) + topLeft.y
- + pixelsPerBlock,
- pixelsPerBlock,
- 0x30000000);
- shadowB = 1;
- }
- }
- else if (heightMapBottom)
- {
- if (heightMap[yy * CHUNK_SIZE + xx]
- > heightMapBottom[xx])
- {
- rObj.drawLinieHAlpha(
- (xx * pixelsPerBlock) + topLeft.x,
- (yy * pixelsPerBlock) + topLeft.y
- + pixelsPerBlock,
- pixelsPerBlock,
- 0x30000000);
- shadowB = 1;
- }
- }
- if (xx > 0)
- {
- if (heightMap[yy * CHUNK_SIZE + xx]
- > heightMap[yy * CHUNK_SIZE + xx - 1])
- {
- rObj.drawLinieVAlpha(
- (xx * pixelsPerBlock) + topLeft.x,
- (yy * pixelsPerBlock) + topLeft.y,
- pixelsPerBlock - shadowB,
- 0x20FFFFFF);
- }
- }
- else if (heightMapLeft)
- {
- if (heightMap[yy * CHUNK_SIZE + xx]
- > heightMapLeft[yy * CHUNK_SIZE + CHUNK_SIZE
- - 1])
- {
- rObj.drawLinieVAlpha(
- (xx * pixelsPerBlock) + topLeft.x,
- (yy * pixelsPerBlock) + topLeft.y,
- pixelsPerBlock - shadowB,
- 0x20FFFFFF);
- }
- }
- if (yy > 0)
- {
- if (heightMap[yy * CHUNK_SIZE + xx]
- > heightMap[(yy - 1) * CHUNK_SIZE + xx])
- {
- rObj.drawLinieHAlpha(
- (xx * pixelsPerBlock) + topLeft.x,
- (yy * pixelsPerBlock) + topLeft.y,
- pixelsPerBlock - shadowR,
- 0x10FFFFFF);
- }
- }
- else if (heightMapTop)
- {
- if (heightMap[yy * CHUNK_SIZE + xx]
- > heightMapTop[(CHUNK_SIZE - 1) * CHUNK_SIZE
- + xx])
- {
- rObj.drawLinieHAlpha(
- (xx * pixelsPerBlock) + topLeft.x,
- (yy * pixelsPerBlock) + topLeft.y,
- pixelsPerBlock - shadowR,
- 0x10FFFFFF);
- }
- }
- }
- }
- if (zOptions->isShowChunkBorders())
- {
- rObj.drawLinieHAlpha(topLeft.x,
- topLeft.y,
- pixelsPerBlock * CHUNK_SIZE,
- 0x50FFFFFF);
- rObj.drawLinieVAlpha(topLeft.x,
- topLeft.y,
- pixelsPerBlock * CHUNK_SIZE,
- 0x50FFFFFF);
- }
- }
- screenPos.y += pixelsPerBlock * CHUNK_SIZE;
- }
- screenPos.x += pixelsPerBlock * CHUNK_SIZE;
- screenPos.y = minScreenPos.y;
- }
- // render players
- if (zOptions->isShowPlayers())
- {
- TextRenderer tm(
- dynamic_cast<Schrift*>(uiFactory.initParam.schrift->getThis()));
- tm.setSchriftSize(12);
- for (const MapPlayer& player : players)
- {
- Punkt screenPos
- = getSize() / 2 - scrollOffset
- + (Punkt((int)player.position.x, (int)player.position.y)
- - originChunkCenter)
- * pixelsPerBlock
- + Punkt(pixelsPerBlock, pixelsPerBlock) / 2
- - playerIcon->getSize() / 2;
- rObj.alphaBild(screenPos.x,
- screenPos.y,
- playerIcon->getBreite(),
- playerIcon->getHeight(),
- *playerIcon);
- int textWidth = tm.getTextBreite(player.name);
- int textheight = tm.getTextHeight(player.name);
- screenPos = screenPos + Punkt(playerIcon->getBreite(), 0) / 2
- - Punkt(textWidth / 2, textheight + 2);
- rObj.alphaRegion(
- screenPos.x, screenPos.y, textWidth, textheight, 0x70000000);
- tm.renderText(
- screenPos.x, screenPos.y, player.name, rObj, 0xFFFFFFFF);
- }
- }
- 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();
- }
- ZeichnungHintergrund::doMausEreignis(me, userRet);
- }
|