|
@@ -1,912 +0,0 @@
|
|
|
-#include "Dimension.h"
|
|
|
-
|
|
|
-#include "Constants.h"
|
|
|
-#include "Datei.h"
|
|
|
-#include "Game.h"
|
|
|
-#include "NoBlock.h"
|
|
|
-
|
|
|
-using namespace Framework;
|
|
|
-
|
|
|
-Dimension::Dimension(int id)
|
|
|
- : Thread(),
|
|
|
- nextStructureId(0),
|
|
|
- dimensionId(id),
|
|
|
- gravity(9.8f),
|
|
|
- chunks(new Trie<Chunk>()),
|
|
|
- entities(new RCArray<Entity>()),
|
|
|
- map(new DimensionMap(id)),
|
|
|
- stop(0)
|
|
|
-{
|
|
|
- Datei d;
|
|
|
- d.setDatei(
|
|
|
- Game::INSTANCE->getWorldDirectory() + "/dim/" + Text(id) + "/nst.id");
|
|
|
- if (d.existiert())
|
|
|
- {
|
|
|
- d.open(Datei::Style::lesen);
|
|
|
- d.lese((char*)&nextStructureId, 8);
|
|
|
- d.close();
|
|
|
- }
|
|
|
- start();
|
|
|
-}
|
|
|
-
|
|
|
-Dimension::~Dimension()
|
|
|
-{
|
|
|
- entities->release();
|
|
|
- chunks->release();
|
|
|
- map->release();
|
|
|
-}
|
|
|
-
|
|
|
-void Dimension::api(Framework::InMemoryBuffer* zRequest,
|
|
|
- NetworkMessage* zResponse,
|
|
|
- Entity* zSource)
|
|
|
-{
|
|
|
- DoLaterHandler laterHandler;
|
|
|
- char type;
|
|
|
- zRequest->lese(&type, 1);
|
|
|
- switch (type)
|
|
|
- {
|
|
|
- case 0:
|
|
|
- {
|
|
|
- Punkt center;
|
|
|
- zRequest->lese((char*)¢er.x, 4);
|
|
|
- zRequest->lese((char*)¢er.y, 4);
|
|
|
- cs.lock();
|
|
|
- Chunk* cC = zChunk(Game::getChunkCenter(center.x, center.y));
|
|
|
- if (!cC)
|
|
|
- {
|
|
|
-
|
|
|
- waitingRequests.add(
|
|
|
- {dynamic_cast<InMemoryBuffer*>(zRequest->getThis()),
|
|
|
- center,
|
|
|
- zSource->getId()});
|
|
|
- Game::INSTANCE->requestArea({center.x - CHUNK_SIZE / 2,
|
|
|
- center.y - CHUNK_SIZE / 2,
|
|
|
- center.x + CHUNK_SIZE / 2 - 1,
|
|
|
- center.y + CHUNK_SIZE / 2 - 1,
|
|
|
- dimensionId});
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- cC->api(zRequest, zSource, laterHandler);
|
|
|
- }
|
|
|
- cs.unlock();
|
|
|
- break;
|
|
|
- }
|
|
|
- case 1:
|
|
|
- {
|
|
|
- Vec3<int> location;
|
|
|
- zRequest->lese((char*)&location.x, 4);
|
|
|
- zRequest->lese((char*)&location.y, 4);
|
|
|
- zRequest->lese((char*)&location.z, 4);
|
|
|
- Framework::Either<Block*, int> block = zBlock(location);
|
|
|
- if (block.isA())
|
|
|
- {
|
|
|
- block.getA()->api(zRequest, zResponse);
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
- case 2:
|
|
|
- {
|
|
|
- Framework::Punkt location;
|
|
|
- zRequest->lese((char*)&location.x, 4);
|
|
|
- zRequest->lese((char*)&location.y, 4);
|
|
|
- location = Game::getChunkCenter(location.x, location.y);
|
|
|
- char addr[8];
|
|
|
- getAddrOfWorld(location, addr);
|
|
|
- ChunkMap* res = map->getMap(addr, 8, location);
|
|
|
-
|
|
|
- if (!res) res = new ChunkMap(location);
|
|
|
- zResponse->sendMap(res);
|
|
|
- zResponse->setUseBackground();
|
|
|
- res->release();
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-void Dimension::tickEntities()
|
|
|
-{
|
|
|
- for (auto entity : *entities)
|
|
|
- {
|
|
|
- if (!entity->isRemoved()
|
|
|
- && (entity->isMoving()
|
|
|
- || zChunk(Game::getChunkCenter((int)entity->getPosition().x,
|
|
|
- (int)entity->getPosition().y))))
|
|
|
- entity->prepareTick(this);
|
|
|
- }
|
|
|
- int index = 0;
|
|
|
- for (auto entity : *entities)
|
|
|
- {
|
|
|
- if (!entity->isRemoved()
|
|
|
- && (entity->isMoving()
|
|
|
- || zChunk(Game::getChunkCenter((int)entity->getPosition().x,
|
|
|
- (int)entity->getPosition().y))))
|
|
|
- entity->tick(this);
|
|
|
- index++;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-void Dimension::thread()
|
|
|
-{
|
|
|
-
|
|
|
- int index = 0;
|
|
|
- ZeitMesser messer;
|
|
|
- messer.messungStart();
|
|
|
- double time = 0;
|
|
|
- bool isForeground = 0;
|
|
|
- Framework::Array<Framework::Vec3<int>> internalLightUpdateQueue;
|
|
|
- while (!stop)
|
|
|
- {
|
|
|
- Vec3<int> position;
|
|
|
- if (internalLightUpdateQueue.getEintragAnzahl())
|
|
|
- {
|
|
|
- position = internalLightUpdateQueue.get(0);
|
|
|
- internalLightUpdateQueue.remove(0);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- removedChunksCs.lock();
|
|
|
- if (removedChunks.getEintragAnzahl() > 0)
|
|
|
- {
|
|
|
- Chunk* removedChunk = removedChunks.z(0);
|
|
|
- removedChunksCs.unlock();
|
|
|
- Text filePath = Game::INSTANCE->getWorldDirectory() + "/dim/"
|
|
|
- + getDimensionId() + "/";
|
|
|
- filePath.appendHex(removedChunk->getCenter().x);
|
|
|
- filePath += "_";
|
|
|
- filePath.appendHex(removedChunk->getCenter().y);
|
|
|
- filePath += ".chunk";
|
|
|
- Datei d;
|
|
|
- d.setDatei(filePath);
|
|
|
- d.erstellen();
|
|
|
- d.open(Datei::Style::schreiben);
|
|
|
- removedChunk->save(&d);
|
|
|
- char addr[8];
|
|
|
- getAddrOfWorld(removedChunk->getCenter(), addr);
|
|
|
- map->removeMap(addr, 8);
|
|
|
- d.close();
|
|
|
- removedChunksCs.lock();
|
|
|
- removedChunks.remove(0);
|
|
|
- }
|
|
|
- removedChunksCs.unlock();
|
|
|
- if (priorizedLightUpdateQueue.getEintragAnzahl())
|
|
|
- {
|
|
|
- prioLightCs.lock();
|
|
|
- position = priorizedLightUpdateQueue.get(0);
|
|
|
- priorizedLightUpdateQueue.remove(0);
|
|
|
- prioLightCs.unlock();
|
|
|
- isForeground = 1;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- if (!lightUpdateQueue.getEintragAnzahl())
|
|
|
- {
|
|
|
- messer.messungEnde();
|
|
|
- time += messer.getSekunden();
|
|
|
- Sleep(500);
|
|
|
- messer.messungStart();
|
|
|
- continue;
|
|
|
- }
|
|
|
- lightCs.lock();
|
|
|
- position = lightUpdateQueue.get(0);
|
|
|
- lightUpdateQueue.remove(0);
|
|
|
- lightCs.unlock();
|
|
|
- isForeground = 0;
|
|
|
- }
|
|
|
- }
|
|
|
- Chunk* chunk
|
|
|
- = zChunk(Game::INSTANCE->getChunkCenter(position.x, position.y));
|
|
|
- if (position.z >= 0 && position.z < WORLD_HEIGHT)
|
|
|
- {
|
|
|
- if (chunk)
|
|
|
- {
|
|
|
- int x = position.x % CHUNK_SIZE;
|
|
|
- int y = position.y % CHUNK_SIZE;
|
|
|
- if (x < 0) x += CHUNK_SIZE;
|
|
|
- if (y < 0) y += CHUNK_SIZE;
|
|
|
- unsigned char* light
|
|
|
- = chunk->getLightData(Vec3<int>(x, y, position.z));
|
|
|
- unsigned char dayLight[6] = {255, 255, 255, 0, 0, 0};
|
|
|
- unsigned char noLight[6] = {0, 0, 0, 0, 0, 0};
|
|
|
- unsigned char newLight[6] = {0, 0, 0, 0, 0, 0};
|
|
|
-
|
|
|
- for (int i = 0; i < 6; i++)
|
|
|
- {
|
|
|
- unsigned char* neighborLeight;
|
|
|
- Vec3<int> neighborPos
|
|
|
- = position + getDirection(getDirectionFromIndex(i));
|
|
|
- if (neighborPos.z < 0)
|
|
|
- {
|
|
|
- neighborLeight = noLight;
|
|
|
- }
|
|
|
- else if (neighborPos.z >= WORLD_HEIGHT)
|
|
|
- {
|
|
|
- neighborLeight = dayLight;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- Chunk* neighborChunk
|
|
|
- = zChunk(Game::INSTANCE->getChunkCenter(
|
|
|
- neighborPos.x, neighborPos.y));
|
|
|
- int x = neighborPos.x % CHUNK_SIZE;
|
|
|
- int y = neighborPos.y % CHUNK_SIZE;
|
|
|
- if (x < 0) x += CHUNK_SIZE;
|
|
|
- if (y < 0) y += CHUNK_SIZE;
|
|
|
- if (neighborChunk)
|
|
|
- neighborLeight = neighborChunk->getLightData(
|
|
|
- Vec3<int>(x, y, neighborPos.z));
|
|
|
- else
|
|
|
- neighborLeight = noLight;
|
|
|
- }
|
|
|
- for (int j = 0; j < 3; j++)
|
|
|
- newLight[j] = (unsigned char)MAX(newLight[j],
|
|
|
- i == getDirectionIndex(TOP)
|
|
|
- ? neighborLeight[j]
|
|
|
- : (unsigned char)((float)neighborLeight[j]
|
|
|
- * 0.8f));
|
|
|
- for (int j = 3; j < 6; j++)
|
|
|
- newLight[j] = (unsigned char)MAX(newLight[j],
|
|
|
- (unsigned char)((float)neighborLeight[j] * 0.85f));
|
|
|
- }
|
|
|
- const Block* current = zBlockOrDefault(position);
|
|
|
-
|
|
|
- for (int j = 3; j < 6; j++)
|
|
|
- newLight[j] = (unsigned char)MAX(
|
|
|
- newLight[j], current->getLightEmisionColor()[j - 3]);
|
|
|
- current->filterPassingLight(newLight);
|
|
|
- current->filterPassingLight(newLight + 3);
|
|
|
- for (int i = 0; i < 6; i++)
|
|
|
- {
|
|
|
- if (newLight[i] != light[i])
|
|
|
- {
|
|
|
- chunk->setLightData(Vec3<int>(x, y, position.z),
|
|
|
- newLight,
|
|
|
- isForeground);
|
|
|
- for (int j = 0; j < 6; j++)
|
|
|
- internalLightUpdateQueue.add(
|
|
|
- position
|
|
|
- + getDirection(getDirectionFromIndex(j)),
|
|
|
- 0);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- index++;
|
|
|
- if (index > 100000)
|
|
|
- {
|
|
|
- messer.messungEnde();
|
|
|
- time += messer.getSekunden();
|
|
|
- std::cout << "100000 light updates needed " << time << " seconds\n";
|
|
|
- time = 0;
|
|
|
- index = 0;
|
|
|
- Sleep(250);
|
|
|
- messer.messungStart();
|
|
|
- }
|
|
|
- }
|
|
|
- std::cout << Text("Dimension ") + this->getDimensionId()
|
|
|
- + " update Thread exited.\n";
|
|
|
-}
|
|
|
-
|
|
|
-void Dimension::getAddrOf(Punkt cPos, char* addr) const
|
|
|
-{
|
|
|
- *(int*)addr = cPos.x;
|
|
|
- *((int*)addr + 1) = cPos.y;
|
|
|
-}
|
|
|
-
|
|
|
-void Dimension::getAddrOfWorld(Punkt wPos, char* addr) const
|
|
|
-{
|
|
|
- if (wPos.x < 0) wPos.x -= CHUNK_SIZE;
|
|
|
- if (wPos.y < 0)
|
|
|
-
|
|
|
- wPos.y -= CHUNK_SIZE;
|
|
|
- wPos /= CHUNK_SIZE;
|
|
|
- getAddrOf(wPos, addr);
|
|
|
-}
|
|
|
-
|
|
|
-void Dimension::saveStructure(MultiblockStructure* zStructure) const
|
|
|
-{
|
|
|
- Datei d;
|
|
|
- Text path = Game::INSTANCE->getWorldDirectory() + "/dim/"
|
|
|
- + Text(dimensionId) + "/structures/";
|
|
|
- path.appendHex(zStructure->getStructureId());
|
|
|
- path += ".str";
|
|
|
- d.setDatei(path);
|
|
|
- d.erstellen();
|
|
|
- d.open(Datei::Style::schreiben);
|
|
|
- auto uPos = zStructure->getUniquePosition();
|
|
|
- d.schreibe((char*)&uPos.x, 4);
|
|
|
- d.schreibe((char*)&uPos.y, 4);
|
|
|
- d.schreibe((char*)&uPos.z, 4);
|
|
|
- int typeId = zStructure->getStructureTypeId();
|
|
|
- d.schreibe((char*)&typeId, 4);
|
|
|
- __int64 strId = zStructure->getStructureId();
|
|
|
- d.schreibe((char*)&strId, 8);
|
|
|
- StaticRegistry<MultiblockStructureType>::INSTANCE
|
|
|
- .zElement(zStructure->getStructureTypeId())
|
|
|
- ->saveStructure(zStructure, &d);
|
|
|
- d.close();
|
|
|
-}
|
|
|
-
|
|
|
-Chunk* Dimension::zChunk(Punkt wPos) const
|
|
|
-{
|
|
|
- char addr[8];
|
|
|
- getAddrOfWorld(wPos, addr);
|
|
|
- return chunks->z(addr, 8);
|
|
|
-}
|
|
|
-
|
|
|
-Framework::Either<Block*, int> Dimension::zBlock(Vec3<int> location)
|
|
|
-{
|
|
|
- Chunk* c = zChunk(Game::INSTANCE->getChunkCenter(location.x, location.y));
|
|
|
- if (c)
|
|
|
- {
|
|
|
- int x = location.x % CHUNK_SIZE;
|
|
|
- int y = location.y % CHUNK_SIZE;
|
|
|
- if (x < 0) x += CHUNK_SIZE;
|
|
|
- if (y < 0) y += CHUNK_SIZE;
|
|
|
- return c->zBlockAt(Vec3<int>(x, y, location.z));
|
|
|
- }
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-Block* Dimension::zRealBlockInstance(Framework::Vec3<int> location)
|
|
|
-{
|
|
|
- Chunk* c = zChunk(Game::INSTANCE->getChunkCenter(location.x, location.y));
|
|
|
- if (c)
|
|
|
- {
|
|
|
- int x = location.x % CHUNK_SIZE;
|
|
|
- int y = location.y % CHUNK_SIZE;
|
|
|
- if (x < 0) x += CHUNK_SIZE;
|
|
|
- if (y < 0) y += CHUNK_SIZE;
|
|
|
- c->instantiateBlock(Vec3<int>(x, y, location.z));
|
|
|
- auto result = c->zBlockAt(Vec3<int>(x, y, location.z));
|
|
|
- return result.isA() ? result.getA() : 0;
|
|
|
- }
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-const Block* Dimension::zBlockOrDefault(Framework::Vec3<int> location)
|
|
|
-{
|
|
|
- Chunk* c = zChunk(Game::INSTANCE->getChunkCenter(location.x, location.y));
|
|
|
- if (c)
|
|
|
- {
|
|
|
- int x = location.x % CHUNK_SIZE;
|
|
|
- int y = location.y % CHUNK_SIZE;
|
|
|
- if (x < 0) x += CHUNK_SIZE;
|
|
|
- if (y < 0) y += CHUNK_SIZE;
|
|
|
- return c->zBlockConst(Vec3<int>(x, y, location.z));
|
|
|
- }
|
|
|
- return &NoBlock::INSTANCE;
|
|
|
-}
|
|
|
-
|
|
|
-void Dimension::placeBlock(
|
|
|
- Framework::Vec3<int> location, Framework::Either<Block*, int> block)
|
|
|
-{
|
|
|
- Chunk* c = zChunk(Game::getChunkCenter(location.x, location.y));
|
|
|
- if (c)
|
|
|
- {
|
|
|
- int x = location.x % CHUNK_SIZE;
|
|
|
- int y = location.y % CHUNK_SIZE;
|
|
|
- if (x < 0) x += CHUNK_SIZE;
|
|
|
- if (y < 0) y += CHUNK_SIZE;
|
|
|
- if (block.isA())
|
|
|
- c->putBlockAt(Vec3<int>(x, y, location.z), block);
|
|
|
- else
|
|
|
- {
|
|
|
- c->putBlockAt(Vec3<int>(x, y, location.z), 0);
|
|
|
- c->putBlockTypeAt(Vec3<int>(x, y, location.z), block);
|
|
|
- }
|
|
|
- }
|
|
|
- else if (block.isA())
|
|
|
- block.getA()->release();
|
|
|
-}
|
|
|
-
|
|
|
-void Dimension::sendBlockInfo(Framework::Vec3<int> location)
|
|
|
-{
|
|
|
- Chunk* c = zChunk(Game::getChunkCenter(location.x, location.y));
|
|
|
- if (c)
|
|
|
- {
|
|
|
- int x = location.x % CHUNK_SIZE;
|
|
|
- int y = location.y % CHUNK_SIZE;
|
|
|
- if (x < 0) x += CHUNK_SIZE;
|
|
|
- if (y < 0) y += CHUNK_SIZE;
|
|
|
- c->sendBlockInfo(Vec3<int>(x, y, location.z));
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-void Dimension::addEntity(Entity* entity)
|
|
|
-{
|
|
|
- entities->add(entity);
|
|
|
-}
|
|
|
-
|
|
|
-void Dimension::setChunk(Chunk* chunk, Punkt center)
|
|
|
-{
|
|
|
- char addr[8];
|
|
|
- getAddrOfWorld(center, addr);
|
|
|
- if (chunk) map->loadMap(addr, 8, chunk);
|
|
|
- chunkCs.lock();
|
|
|
- Chunk* old = chunks->get(addr, 8);
|
|
|
- if (old)
|
|
|
- {
|
|
|
- Game::INSTANCE->zTickOrganizer()->removeTickSource(old);
|
|
|
- old->prepareRemove();
|
|
|
- for (int i = 0; i < chunkList.getEintragAnzahl(); i++)
|
|
|
- {
|
|
|
- if (chunkList.get(i) == old)
|
|
|
- {
|
|
|
- chunkList.remove(i);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- chunks->set(addr, 8, chunk);
|
|
|
- if (chunk)
|
|
|
- {
|
|
|
- chunkList.add(chunk);
|
|
|
- chunk->setAdded();
|
|
|
- }
|
|
|
- getAddrOfWorld(center + Punkt(CHUNK_SIZE, 0), addr);
|
|
|
- Chunk* zChunk = chunks->z(addr, 8);
|
|
|
- if (zChunk)
|
|
|
- {
|
|
|
- zChunk->setNeighbor(WEST, chunk);
|
|
|
- if (chunk)
|
|
|
- {
|
|
|
- chunk->setNeighbor(EAST, zChunk);
|
|
|
- }
|
|
|
- }
|
|
|
- getAddrOfWorld(center + Punkt(-CHUNK_SIZE, 0), addr);
|
|
|
- zChunk = chunks->z(addr, 8);
|
|
|
- if (zChunk)
|
|
|
- {
|
|
|
- zChunk->setNeighbor(EAST, chunk);
|
|
|
- if (chunk) chunk->setNeighbor(WEST, zChunk);
|
|
|
- }
|
|
|
- getAddrOfWorld(center + Punkt(0, CHUNK_SIZE), addr);
|
|
|
- zChunk = chunks->z(addr, 8);
|
|
|
- if (zChunk)
|
|
|
- {
|
|
|
- zChunk->setNeighbor(NORTH, chunk);
|
|
|
- if (chunk) chunk->setNeighbor(SOUTH, zChunk);
|
|
|
- }
|
|
|
- getAddrOfWorld(center + Punkt(0, -CHUNK_SIZE), addr);
|
|
|
- zChunk = chunks->z(addr, 8);
|
|
|
- if (zChunk)
|
|
|
- {
|
|
|
- zChunk->setNeighbor(SOUTH, chunk);
|
|
|
- if (chunk) chunk->setNeighbor(NORTH, zChunk);
|
|
|
- }
|
|
|
- DoLaterHandler laterHandler;
|
|
|
- if (chunk)
|
|
|
- {
|
|
|
- cs.lock();
|
|
|
- int index = 0;
|
|
|
- for (Iterator<RequestQueue> iterator = waitingRequests.begin();
|
|
|
- iterator;)
|
|
|
- {
|
|
|
- Entity* zE = Game::INSTANCE->zEntity(iterator.val().sourceId);
|
|
|
- if (zE)
|
|
|
- {
|
|
|
- if (iterator.val().chunkCenter == chunk->getCenter())
|
|
|
- {
|
|
|
- chunk->api(iterator.val().request, zE, laterHandler);
|
|
|
- iterator.val().request->release();
|
|
|
- iterator.remove();
|
|
|
- continue;
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- iterator.val().request->release();
|
|
|
- iterator.remove();
|
|
|
- continue;
|
|
|
- }
|
|
|
- iterator++;
|
|
|
- index++;
|
|
|
- }
|
|
|
- cs.unlock();
|
|
|
- Game::INSTANCE->zTickOrganizer()->addTickSource(chunk);
|
|
|
- }
|
|
|
- chunkCs.unlock();
|
|
|
- if (old)
|
|
|
- {
|
|
|
- old->onUnloaded();
|
|
|
- removedChunksCs.lock();
|
|
|
- removedChunks.add(old);
|
|
|
- removedChunksCs.unlock();
|
|
|
- }
|
|
|
- if (chunk) chunk->onLoaded();
|
|
|
- updateLightAtChunkBorders(center);
|
|
|
-}
|
|
|
-
|
|
|
-void Dimension::save(Text worldDir) const
|
|
|
-{
|
|
|
- Datei d;
|
|
|
- d.setDatei(Game::INSTANCE->getWorldDirectory() + "/dim/" + Text(dimensionId)
|
|
|
- + "/nst.id");
|
|
|
- d.erstellen();
|
|
|
- d.open(Datei::Style::schreiben);
|
|
|
- d.schreibe((char*)&nextStructureId, 8);
|
|
|
- d.close();
|
|
|
- for (auto chunk = chunkList.begin(); chunk; chunk++)
|
|
|
- {
|
|
|
- if (!chunk._) continue;
|
|
|
- Datei* file = new Datei();
|
|
|
- Text filePath = worldDir + "/dim/" + dimensionId + "/";
|
|
|
- filePath.appendHex(chunk->getCenter().x);
|
|
|
- filePath += "_";
|
|
|
- filePath.appendHex(chunk->getCenter().y);
|
|
|
- filePath += ".chunk";
|
|
|
- file->setDatei(filePath);
|
|
|
- if (file->open(Datei::Style::schreiben)) chunk->save(file);
|
|
|
- file->close();
|
|
|
- file->release();
|
|
|
- char addr[8];
|
|
|
- getAddrOfWorld(chunk->getCenter(), addr);
|
|
|
- map->saveMap(addr, 8);
|
|
|
- }
|
|
|
- Text filePath = worldDir + "/dim/" + dimensionId + "/entities";
|
|
|
- Datei* file = new Datei();
|
|
|
- file->setDatei(filePath);
|
|
|
- if (file->open(Datei::Style::schreiben))
|
|
|
- {
|
|
|
- for (Entity* entity : *entities)
|
|
|
- {
|
|
|
- if (entity->zType()->getId() != EntityTypeEnum::PLAYER)
|
|
|
- {
|
|
|
- if (!entity->isRemoved())
|
|
|
- {
|
|
|
- int type = entity->zType()->getId();
|
|
|
- file->schreibe((char*)&type, 4);
|
|
|
- StaticRegistry<EntityType>::INSTANCE.zElement(type)
|
|
|
- ->saveEntity(entity, file);
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- Datei pFile;
|
|
|
- pFile.setDatei(worldDir + "/player/"
|
|
|
- + Game::INSTANCE->getPlayerId(
|
|
|
- ((Player*)entity)->getName()));
|
|
|
- if (pFile.open(Datei::Style::schreiben))
|
|
|
- StaticRegistry<EntityType>::INSTANCE
|
|
|
- .zElement(EntityTypeEnum::PLAYER)
|
|
|
- ->saveEntity(entity, &pFile);
|
|
|
- }
|
|
|
- }
|
|
|
- file->close();
|
|
|
- }
|
|
|
- for (MultiblockStructure* structure : structures)
|
|
|
- {
|
|
|
- saveStructure(structure);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-int Dimension::getDimensionId() const
|
|
|
-{
|
|
|
- return dimensionId;
|
|
|
-}
|
|
|
-
|
|
|
-bool Dimension::hasChunck(int x, int y)
|
|
|
-{
|
|
|
- if (zChunk(Punkt(x, y))) return 1;
|
|
|
- removedChunksCs.lock();
|
|
|
- for (Chunk* c : removedChunks)
|
|
|
- {
|
|
|
- if (c->getCenter().x == x && c->getCenter().y == y)
|
|
|
- {
|
|
|
- removedChunksCs.unlock();
|
|
|
- return 1;
|
|
|
- }
|
|
|
- }
|
|
|
- removedChunksCs.unlock();
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-bool Dimension::reviveChunk(int x, int y)
|
|
|
-{
|
|
|
- chunkCs.lock();
|
|
|
- if (zChunk(Punkt(x, y)))
|
|
|
- {
|
|
|
- chunkCs.unlock();
|
|
|
- return 1;
|
|
|
- }
|
|
|
- removedChunksCs.lock();
|
|
|
- int index = 0;
|
|
|
- for (Iterator<Chunk*> i = removedChunks.begin(); i; i++)
|
|
|
- {
|
|
|
- if (i->getCenter().x == x && i->getCenter().y == y)
|
|
|
- {
|
|
|
- setChunk(dynamic_cast<Chunk*>(i->getThis()), Punkt(x, y));
|
|
|
- if (index > 0) i.remove();
|
|
|
- removedChunksCs.unlock();
|
|
|
- chunkCs.unlock();
|
|
|
- return 1;
|
|
|
- }
|
|
|
- index++;
|
|
|
- }
|
|
|
- removedChunksCs.unlock();
|
|
|
- chunkCs.unlock();
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-float Dimension::getGravity() const
|
|
|
-{
|
|
|
- return gravity;
|
|
|
-}
|
|
|
-
|
|
|
-void Dimension::removeOldChunks()
|
|
|
-{
|
|
|
- chunkCs.lock();
|
|
|
- int index = 0;
|
|
|
- for (Chunk* chunk : chunkList)
|
|
|
- {
|
|
|
- if (!chunk->hasObservers()) setChunk(0, chunk->getCenter());
|
|
|
- index++;
|
|
|
- }
|
|
|
- chunkCs.unlock();
|
|
|
- structurCs.lock();
|
|
|
- Iterator<MultiblockStructure*> i = structures.begin();
|
|
|
- while (i)
|
|
|
- {
|
|
|
- if (i->isEmpty())
|
|
|
- {
|
|
|
- i.remove();
|
|
|
- continue;
|
|
|
- }
|
|
|
- else if (i->isFullyUnloaded())
|
|
|
- {
|
|
|
- saveStructure(i);
|
|
|
- i.remove();
|
|
|
- continue;
|
|
|
- }
|
|
|
- i++;
|
|
|
- }
|
|
|
- structurCs.unlock();
|
|
|
-}
|
|
|
-
|
|
|
-Entity* Dimension::zEntity(int id)
|
|
|
-{
|
|
|
- for (auto entity : *entities)
|
|
|
- {
|
|
|
- if (!entity->isRemoved() && entity->getId() == id) return entity;
|
|
|
- }
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-Entity* Dimension::zNearestEntity(
|
|
|
- Framework::Vec3<float> pos, std::function<bool(Entity*)> filter)
|
|
|
-{
|
|
|
- Entity* result = 0;
|
|
|
- float sqDist = 0;
|
|
|
- for (auto entity : *entities)
|
|
|
- {
|
|
|
- if (!entity->isRemoved() && filter(entity))
|
|
|
- {
|
|
|
- float d = pos.abstandSq(entity->getPosition());
|
|
|
- if (!result || d < sqDist)
|
|
|
- {
|
|
|
- result = entity;
|
|
|
- sqDist = d;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return result;
|
|
|
-}
|
|
|
-
|
|
|
-void Dimension::removeEntity(int id)
|
|
|
-{
|
|
|
- int index = 0;
|
|
|
- for (auto entity : *entities)
|
|
|
- {
|
|
|
- if (entity->getId() == id)
|
|
|
- {
|
|
|
- entities->remove(index);
|
|
|
- return;
|
|
|
- }
|
|
|
- index++;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-void Dimension::removeSubscriptions(Entity* zEntity)
|
|
|
-{
|
|
|
- for (Chunk* chunk : chunkList)
|
|
|
- chunk->removeObserver(zEntity);
|
|
|
-}
|
|
|
-
|
|
|
-void Dimension::updateLightning(Vec3<int> location)
|
|
|
-{
|
|
|
- lightCs.lock();
|
|
|
- lightUpdateQueue.add(location, 0);
|
|
|
- lightCs.unlock();
|
|
|
-}
|
|
|
-
|
|
|
-void Dimension::updateLightningWithoutWait(Framework::Vec3<int> location)
|
|
|
-{
|
|
|
- prioLightCs.lock();
|
|
|
- priorizedLightUpdateQueue.add(location, 0);
|
|
|
- prioLightCs.unlock();
|
|
|
-}
|
|
|
-
|
|
|
-void Dimension::updateLightAtChunkBorders(Punkt chunkCenter)
|
|
|
-{
|
|
|
- if (lightUpdateQueue.getEintragAnzahl() > 300000)
|
|
|
- {
|
|
|
- std::cout
|
|
|
- << "warning: light calculation queue is over 300000 blocks long";
|
|
|
- }
|
|
|
- for (int i = WORLD_HEIGHT - 1; i >= 0; i--)
|
|
|
- {
|
|
|
- for (int j = 0; j < CHUNK_SIZE; j++)
|
|
|
- {
|
|
|
- updateLightning(Vec3<int>(chunkCenter.x - CHUNK_SIZE / 2 - 1,
|
|
|
- chunkCenter.y - CHUNK_SIZE / 2 + j,
|
|
|
- i));
|
|
|
- updateLightning(Vec3<int>(chunkCenter.x - CHUNK_SIZE / 2,
|
|
|
- chunkCenter.y - CHUNK_SIZE / 2 + j,
|
|
|
- i));
|
|
|
- updateLightning(Vec3<int>(chunkCenter.x + CHUNK_SIZE / 2 - 1,
|
|
|
- chunkCenter.y - CHUNK_SIZE / 2 + j,
|
|
|
- i));
|
|
|
- updateLightning(Vec3<int>(chunkCenter.x + CHUNK_SIZE / 2,
|
|
|
- chunkCenter.y - CHUNK_SIZE / 2 + j,
|
|
|
- i));
|
|
|
- updateLightning(Vec3<int>(chunkCenter.x - CHUNK_SIZE / 2 + j,
|
|
|
- chunkCenter.y - CHUNK_SIZE / 2 - 1,
|
|
|
- i));
|
|
|
- updateLightning(Vec3<int>(chunkCenter.x - CHUNK_SIZE / 2 + j,
|
|
|
- chunkCenter.y - CHUNK_SIZE / 2,
|
|
|
- i));
|
|
|
- updateLightning(Vec3<int>(chunkCenter.x - CHUNK_SIZE / 2 + j,
|
|
|
- chunkCenter.y + CHUNK_SIZE / 2 - 1,
|
|
|
- i));
|
|
|
- updateLightning(Vec3<int>(chunkCenter.x - CHUNK_SIZE / 2 + j,
|
|
|
- chunkCenter.y + CHUNK_SIZE / 2,
|
|
|
- i));
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-__int64 Dimension::getNextStructureId()
|
|
|
-{
|
|
|
- return nextStructureId++;
|
|
|
-}
|
|
|
-
|
|
|
-void Dimension::addStructure(MultiblockStructure* structure)
|
|
|
-{
|
|
|
- structurCs.lock();
|
|
|
- structures.add(structure);
|
|
|
- structurCs.unlock();
|
|
|
-}
|
|
|
-
|
|
|
-MultiblockStructure* Dimension::zStructureByPosition(
|
|
|
- Framework::Vec3<int> uniquePosition)
|
|
|
-{
|
|
|
- structurCs.lock();
|
|
|
- for (MultiblockStructure* str : structures)
|
|
|
- {
|
|
|
- if (str->getUniquePosition() == uniquePosition)
|
|
|
- {
|
|
|
- structurCs.unlock();
|
|
|
- return str;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- Datei dir(Game::INSTANCE->getWorldDirectory() + "/dim/" + Text(dimensionId)
|
|
|
- + "/structures");
|
|
|
- RCArray<Text>* names = dir.getDateiListe();
|
|
|
- if (names)
|
|
|
- {
|
|
|
- Vec3<int> uPos;
|
|
|
- for (Text* name : *names)
|
|
|
- {
|
|
|
- Datei d(Text(dir.zPfad()->getText()) + "/" + name->getText());
|
|
|
- if (d.open(Datei::Style::lesen))
|
|
|
- {
|
|
|
- d.lese((char*)&uPos.x, 4);
|
|
|
- d.lese((char*)&uPos.y, 4);
|
|
|
- d.lese((char*)&uPos.z, 4);
|
|
|
- if (uPos == uniquePosition)
|
|
|
- {
|
|
|
- int type;
|
|
|
- d.lese((char*)&type, 4);
|
|
|
- __int64 strId;
|
|
|
- d.lese((char*)&strId, 8);
|
|
|
- MultiblockStructure* str
|
|
|
- = StaticRegistry<MultiblockStructureType>::INSTANCE
|
|
|
- .zElement(type)
|
|
|
- ->loadStructure(
|
|
|
- dimensionId, strId, uniquePosition, &d);
|
|
|
- d.close();
|
|
|
- structures.add(str);
|
|
|
- names->release();
|
|
|
- structurCs.unlock();
|
|
|
- return str;
|
|
|
- }
|
|
|
- d.close();
|
|
|
- }
|
|
|
- }
|
|
|
- names->release();
|
|
|
- }
|
|
|
- structurCs.unlock();
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-MultiblockStructure* Dimension::zStructureById(__int64 id)
|
|
|
-{
|
|
|
- structurCs.lock();
|
|
|
- for (MultiblockStructure* str : structures)
|
|
|
- {
|
|
|
- if (str->getStructureId() == id)
|
|
|
- {
|
|
|
- structurCs.unlock();
|
|
|
- return str;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- Text path = Game::INSTANCE->getWorldDirectory() + "/dim/"
|
|
|
- + Text(dimensionId) + "/structures/";
|
|
|
- path.appendHex(id);
|
|
|
- path += ".str";
|
|
|
- Datei d(path);
|
|
|
- Vec3<int> uPos;
|
|
|
- if (d.open(Datei::Style::lesen))
|
|
|
- {
|
|
|
- d.lese((char*)&uPos.x, 4);
|
|
|
- d.lese((char*)&uPos.y, 4);
|
|
|
- d.lese((char*)&uPos.z, 4);
|
|
|
- int type;
|
|
|
- d.lese((char*)&type, 4);
|
|
|
- __int64 strId;
|
|
|
- d.lese((char*)&strId, 8);
|
|
|
- MultiblockStructure* str
|
|
|
- = StaticRegistry<MultiblockStructureType>::INSTANCE.zElement(type)
|
|
|
- ->loadStructure(dimensionId, strId, uPos, &d);
|
|
|
- d.close();
|
|
|
- structures.add(str);
|
|
|
- structurCs.unlock();
|
|
|
- return str;
|
|
|
- }
|
|
|
- std::cout << "WARNING: did not find Structure information file '" << path
|
|
|
- << "'.\n";
|
|
|
- structurCs.unlock();
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-void Dimension::requestStopAndWait()
|
|
|
-{
|
|
|
- stop = 1;
|
|
|
- warteAufThread(1000000);
|
|
|
-}
|
|
|
-
|
|
|
-void Dimension::updateMap(int x, int y, int height)
|
|
|
-{
|
|
|
- chunkCs.lock();
|
|
|
- int h1 = height % 2 == 0 ? height : height - 1;
|
|
|
- int h2 = h1 + 1;
|
|
|
- const Block* b1 = zBlockOrDefault({x, y, h1});
|
|
|
- const Block* b2 = zBlockOrDefault({x, y, h2});
|
|
|
- bool visible = 1;
|
|
|
- if (h2 != WORLD_HEIGHT - 1)
|
|
|
- {
|
|
|
- const Block* b3 = zBlockOrDefault({x, y, h2 + 1});
|
|
|
- visible = b3->isPassable() || b3->isTransparent();
|
|
|
- }
|
|
|
- int color1
|
|
|
- = (b2->isPassable() || b2->isTransparent()) ? b1->getMapColor() : 0;
|
|
|
- int color2 = visible ? b2->getMapColor() : 0;
|
|
|
- char addr[8];
|
|
|
- Punkt center = Game::INSTANCE->getChunkCenter(x, y);
|
|
|
- getAddrOfWorld(center, addr);
|
|
|
- ChunkMap* cMap = map->getMap(addr, 8, center);
|
|
|
- if (cMap)
|
|
|
- {
|
|
|
- x = x % CHUNK_SIZE;
|
|
|
- y = y % CHUNK_SIZE;
|
|
|
- if (x < 0) x += CHUNK_SIZE;
|
|
|
- if (y < 0) y += CHUNK_SIZE;
|
|
|
- cMap->update(
|
|
|
- (char)x, (char)y, (unsigned char)(height / 2), color1, color2);
|
|
|
- }
|
|
|
- chunkCs.unlock();
|
|
|
-}
|