123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960 |
- #include "Dimension.h"
- #include <Logging.h>
- #include "ChunkMap.h"
- #include "Constants.h"
- #include "Datei.h"
- #include "DimensionMap.h"
- #include "Entity.h"
- #include "EntityType.h"
- #include "Game.h"
- #include "NoBlock.h"
- #include "Player.h"
- #include "TickOrganizer.h"
- using namespace Framework;
- Dimension::Dimension(int id)
- : Thread(),
- nextStructureId(0),
- dimensionId(id),
- gravity(9.8f),
- chunks(new RCTrie<Chunk>()),
- entities(new RCArray<Entity>()),
- map(new DimensionMap(id)),
- stop(0),
- currentDayTime(0.0),
- nightDuration(300.0),
- nightTransitionDuration(30.0),
- dayDuration(600.0)
- {
- Datei d;
- d.setDatei(
- Game::INSTANCE->getWorldDirectory() + "/dim/" + Text(id) + "/meta.dim");
- if (d.existiert())
- {
- d.open(Datei::Style::lesen);
- d.lese((char*)&nextStructureId, 8);
- d.lese((char*)¤tDayTime, 8);
- d.close();
- }
- start();
- }
- Dimension::~Dimension()
- {
- entities->release();
- chunks->release();
- map->release();
- }
- void Dimension::configureDayNightCyncle(
- double nightDuration, double nightTransitionDuration, double dayDuration)
- {
- this->nightDuration = nightDuration;
- this->nightTransitionDuration = nightTransitionDuration;
- this->dayDuration = dayDuration;
- }
- void Dimension::api(Framework::InMemoryBuffer* zRequest,
- NetworkMessage* zResponse,
- Entity* zSource)
- {
- DoLaterHandler laterHandler;
- char type;
- zRequest->lese(&type, 1);
- switch (type)
- {
- case 0: // chunk message
- {
- 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)
- {
- // TODO: have a max amount of waiting requests per player
- 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: // block message
- {
- 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: // map request
- {
- map->api(zRequest, zResponse, zSource, this);
- break;
- }
- }
- }
- void Dimension::tickEntities()
- {
- this->currentDayTime += 1.0 / MAX_TICKS_PER_SECOND;
- if (this->currentDayTime
- > dayDuration + nightDuration + nightTransitionDuration * 2)
- {
- this->currentDayTime
- -= dayDuration + nightDuration + nightTransitionDuration * 2;
- }
- 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()
- {
- // light calculation
- 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)
- {
- Vec3<int> chunkPos = chunkCoordinates(position);
- unsigned char* light = chunk->getLightData(chunkPos);
- 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};
- // add neighbor light emission
- 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));
- if (neighborChunk)
- neighborLeight = neighborChunk->getLightData(
- chunkCoordinates(neighborPos));
- 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);
- // add own light emission
- 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(chunkPos, 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();
- Logging::debug()
- << "100000 light updates needed " << time << " seconds";
- time = 0;
- index = 0;
- messer.messungStart();
- }
- }
- Logging::info() << Text("Dimension ") + this->getDimensionId()
- + " update Thread exited.";
- }
- 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) // needed because otherwise would (-8, -8) have the same
- // adress as (8, 8)
- 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);
- Game::INSTANCE->zMultiblockStructureType(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)
- {
- location = chunkCoordinates(location);
- return c->zBlockAt(location);
- }
- return 0;
- }
- Block* Dimension::zRealBlockInstance(Framework::Vec3<int> location)
- {
- Chunk* c = zChunk(Game::INSTANCE->getChunkCenter(location.x, location.y));
- if (c)
- {
- location = chunkCoordinates(location);
- c->instantiateBlock(location);
- auto result = c->zBlockAt(location);
- 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)
- {
- location = chunkCoordinates(location);
- return c->zBlockConst(location);
- }
- return &NoBlock::INSTANCE;
- }
- int Dimension::getBlockType(Framework::Vec3<int> location)
- {
- Chunk* c = zChunk(Game::INSTANCE->getChunkCenter(location.x, location.y));
- if (c)
- {
- location = chunkCoordinates(location);
- return c->getBlockTypeAt(location);
- }
- return BlockTypeEnum::NO_BLOCK;
- }
- void Dimension::placeBlock(
- Framework::Vec3<int> location, Framework::Either<Block*, int> block)
- {
- if (block.isB() && block.getB() == BlockTypeEnum::NO_BLOCK) return;
- Chunk* c = zChunk(Game::getChunkCenter(location.x, location.y));
- if (c)
- {
- location = chunkCoordinates(location);
- if (block.isA())
- c->putBlockAt(location, block);
- else
- {
- c->putBlockAt(location, 0);
- c->putBlockTypeAt(location, 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)
- {
- location = chunkCoordinates(location);
- c->sendBlockInfo(location);
- }
- }
- 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 (ArrayIterator<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();
- laterHandler.execute();
- if (chunk) updateLightAtChunkBorders(center);
- }
- void Dimension::save(Text worldDir) const
- {
- Datei d;
- d.setDatei(Game::INSTANCE->getWorldDirectory() + "/dim/" + Text(dimensionId)
- + "/meta.dim");
- d.erstellen();
- d.open(Datei::Style::schreiben);
- d.schreibe((char*)&nextStructureId, 8);
- d.schreibe((char*)¤tDayTime, 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);
- Game::INSTANCE->zEntityType(type)->saveEntity(entity, file);
- }
- }
- else
- {
- Datei pFile;
- pFile.setDatei(worldDir + "/player/"
- + Game::INSTANCE->getPlayerId(
- ((Player*)entity)->getName()));
- if (pFile.open(Datei::Style::schreiben))
- Game::INSTANCE->zEntityType(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 (ArrayIterator<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();
- ArrayIterator<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)
- {
- Logging::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;
- }
- }
- // search for structure file
- 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
- = Game::INSTANCE->zMultiblockStructureType(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;
- }
- }
- // search for structure file
- 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
- = Game::INSTANCE->zMultiblockStructureType(type)->loadStructure(
- dimensionId, strId, uPos, &d);
- d.close();
- structures.add(str);
- structurCs.unlock();
- return str;
- }
- Logging::warning() << "did not find Structure information file '" << path
- << "'.";
- 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;
- int color1m = 0;
- int color2m = 0;
- if (h1 > 0)
- {
- const Block* b1m = zBlockOrDefault({x, y, h1 - 2});
- const Block* b2m = zBlockOrDefault({x, y, h1 - 1});
- color1m = (b2m->isPassable() || b2m->isTransparent())
- ? b1m->getMapColor()
- : 0;
- color2m = (b1->isPassable() || b1->isTransparent()) ? b2m->getMapColor()
- : 0;
- }
- char addr[8];
- Punkt center = Game::INSTANCE->getChunkCenter(x, y);
- getAddrOfWorld(center, addr);
- ChunkMap* cMap = map->getMap(addr, 8, center);
- if (cMap)
- {
- Framework::Vec3<int> chunkLocation = chunkCoordinates({x, y, height});
- if (cMap->update((char)chunkLocation.x,
- (char)chunkLocation.y,
- (unsigned char)(chunkLocation.z / 2),
- color1,
- color2)
- || (h1 > 0
- && cMap->update((char)chunkLocation.x,
- (char)chunkLocation.y,
- (unsigned char)(chunkLocation.z / 2 - 1),
- color1m,
- color2m)))
- {
- map->onMapUpdated(addr, 8);
- }
- }
- chunkCs.unlock();
- }
- int Dimension::getChunkCount()
- {
- return chunkList.getEintragAnzahl();
- }
- double Dimension::getCurrentDayTime() const
- {
- return currentDayTime;
- }
- double Dimension::getNightDuration() const
- {
- return nightDuration;
- }
- double Dimension::getNightTransitionDuration() const
- {
- return nightTransitionDuration;
- }
- double Dimension::getDayDuration() const
- {
- return dayDuration;
- }
|