| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058 |
- #include "Dimension.h"
- #include <AsynchronCall.h>
- #include <Logging.h>
- #include "ChunkMap.h"
- #include "Constants.h"
- #include "DimensionMap.h"
- #include "Entity.h"
- #include "EntityType.h"
- #include "File.h"
- #include "Game.h"
- #include "NoBlock.h"
- #include "Player.h"
- #include "TickOrganizer.h"
- #include "WorldGenerator.h"
- using namespace Framework;
- Dimension::Dimension(int id)
- : Thread(),
- nextStructureId(1),
- dimensionId(id),
- gravity(9.8f),
- chunks(new RCTrie<Chunk>()),
- entities(new RCArray<Entity>()),
- structureManager(new MultiblockStructureManager(id)),
- map(new DimensionMap(id)),
- stop(0),
- currentDayTime(0.0),
- nightDuration(300.0),
- nightTransitionDuration(30.0),
- dayDuration(600.0)
- {
- File d;
- d.setFile(
- Game::INSTANCE->getWorldDirectory() + "/dim/" + Text(id) + "/meta.dim");
- if (d.exists())
- {
- d.open(File::Style::read);
- d.read((char*)&nextStructureId, 8);
- d.read((char*)¤tDayTime, 8);
- d.close();
- }
- start();
- new AsynchronCall([this]() { this->entityTickLoop(); });
- }
- Dimension::~Dimension()
- {
- entities->release();
- chunks->release();
- map->release();
- delete structureManager;
- }
- 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->read(&type, 1);
- switch (type)
- {
- case 0: // chunk message
- {
- Point center;
- zRequest->read((char*)¢er.x, 4);
- zRequest->read((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->read((char*)&location.x, 4);
- zRequest->read((char*)&location.y, 4);
- zRequest->read((char*)&location.z, 4);
- Framework::Either<Block*, int> block = zBlock(location, 0);
- if (block.isA())
- {
- block.getA()->api(zRequest, zResponse, zSource);
- }
- break;
- }
- case 2: // map request
- {
- map->api(zRequest, zResponse, zSource, this);
- break;
- }
- }
- }
- void Dimension::tick()
- {
- this->currentDayTime += 1.0 / MAX_TICKS_PER_SECOND;
- if (this->currentDayTime
- > dayDuration + nightDuration + nightTransitionDuration * 2)
- {
- this->currentDayTime
- -= dayDuration + nightDuration + nightTransitionDuration * 2;
- }
- }
- void Dimension::thread()
- {
- // light calculation
- int index = 0;
- Timer messer;
- messer.measureStart();
- double time = 0;
- bool isForeground = 0;
- Framework::Array<Framework::Vec3<int>> internalLightUpdateQueue;
- unsigned char tmp[3];
- while (!stop)
- {
- Vec3<int> position;
- if (internalLightUpdateQueue.getEntryCount())
- {
- position = internalLightUpdateQueue.get(0);
- internalLightUpdateQueue.remove(0);
- }
- else
- {
- removedChunksCs.lock();
- if (removedChunks.getEntryCount() > 0)
- {
- Chunk* removedChunk = removedChunks.z(0);
- removedChunksCs.unlock();
- Array<Framework::Point> chunksToSave;
- Text filePath = Game::INSTANCE->getWorldDirectory() + "/dim/"
- + getDimensionId() + "/";
- filePath.appendHex(removedChunk->getCenter().x);
- filePath += "_";
- filePath.appendHex(removedChunk->getCenter().y);
- filePath += ".chunk";
- File d;
- d.setFile(filePath);
- d.create();
- d.open(File::Style::write);
- removedChunk->save(&d, chunksToSave);
- char addr[8];
- getAddrOfWorld(removedChunk->getCenter(), addr);
- map->removeMap(addr, 8);
- d.close();
- removedChunksCs.lock();
- removedChunks.remove(0);
- while (chunksToSave.getEntryCount() > 0)
- {
- Point cPos = chunksToSave.get(0);
- chunksToSave.remove(0);
- Chunk* c = zChunk(cPos);
- if (c)
- {
- Text filePath = Game::INSTANCE->getWorldDirectory()
- + "/dim/" + getDimensionId() + "/";
- filePath.appendHex(cPos.x);
- filePath += "_";
- filePath.appendHex(cPos.y);
- filePath += ".chunk";
- File d;
- d.setFile(filePath);
- d.create();
- d.open(File::Style::write);
- c->save(&d, chunksToSave);
- d.close();
- }
- }
- }
- removedChunksCs.unlock();
- if (priorizedLightUpdateQueue.getEntryCount())
- {
- prioLightCs.lock();
- position = priorizedLightUpdateQueue.get(0);
- priorizedLightUpdateQueue.remove(0);
- prioLightCs.unlock();
- isForeground = 1;
- }
- else
- {
- if (!lightUpdateQueue.getEntryCount())
- {
- messer.measureEnd();
- time += messer.getSekunden();
- Sleep(500);
- messer.measureStart();
- 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
- current->getLightEmisionColor(tmp);
- for (int j = 3; j < 6; j++)
- newLight[j] = (unsigned char)MAX(newLight[j], tmp[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.measureEnd();
- time += messer.getSekunden();
- Logging::debug()
- << "100000 light updates needed " << time << " seconds";
- time = 0;
- index = 0;
- messer.measureStart();
- }
- }
- Logging::info() << Text("Dimension ") + this->getDimensionId()
- + " update Thread exited.";
- }
- void Dimension::getAddrOf(Point cPos, char* addr) const
- {
- *(int*)addr = cPos.x;
- *((int*)addr + 1) = cPos.y;
- }
- void Dimension::getAddrOfWorld(Point 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
- {
- structureManager->saveStructure(zStructure);
- }
- void Dimension::entityTickLoop()
- {
- Timer zm;
- double ausgleich = 0.0;
- zm.measureStart();
- Sleep(16);
- while (!stop)
- {
- zm.measureEnd();
- double seconds = zm.getSekunden();
- zm.measureStart();
- {
- Framework::CriticalLock lock({&entityCs, &chunkCs});
- auto iterator = entities->begin();
- auto end = entities->end();
- while (iterator != end)
- {
- if (!iterator->isRemoved())
- {
- iterator->prepareTick(this, seconds);
- iterator++;
- }
- else
- {
- auto chunk = zChunk(
- Game::getChunkCenter((int)iterator->getPosition().x,
- (int)iterator->getPosition().y));
- if (chunk)
- {
- chunk->onEntityLeaves(iterator, 0);
- }
- iterator.remove();
- }
- }
- int index = 0;
- for (auto entity : *entities)
- {
- if (!entity->isRemoved())
- {
- entity->tick(this, seconds);
- }
- index++;
- }
- } // end of LOCK entityCs, chunkCs
- ausgleich += 1.0 / 30 - seconds;
- if (ausgleich > 0) Sleep((int)(ausgleich * 1000));
- }
- }
- Chunk* Dimension::zChunk(Point wPos) const
- {
- char addr[8];
- getAddrOfWorld(wPos, addr);
- return chunks->z(addr, 8);
- }
- Framework::Either<Block*, int> Dimension::zBlock(
- Vec3<int> location, OUT Chunk** zChunk) const
- {
- Chunk* c
- = this->zChunk(Game::INSTANCE->getChunkCenter(location.x, location.y));
- if (zChunk)
- {
- *zChunk = c;
- }
- if (c)
- {
- location = chunkCoordinates(location);
- return c->zBlockAt(location);
- }
- return 0;
- }
- Block* Dimension::zRealBlockInstance(Framework::Vec3<int> location) const
- {
- 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) const
- {
- 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) const
- {
- 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)
- {
- entityCs.lock();
- entities->add(entity);
- entityCs.unlock();
- }
- void Dimension::setChunk(Chunk* chunk, Point 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.getEntryCount(); i++)
- {
- if (chunkList.get(i) == old)
- {
- chunkList.remove(i);
- break;
- }
- }
- for (Entity* entity : old->getEntitiesInChunk())
- {
- removeEntity(entity->getId());
- }
- }
- chunks->set(addr, 8, chunk);
- if (chunk)
- {
- chunkList.add(chunk);
- }
- getAddrOfWorld(center + Point(CHUNK_SIZE, 0), addr);
- Chunk* zChunk = chunks->z(addr, 8);
- if (zChunk)
- {
- zChunk->setNeighbor(WEST, chunk);
- if (chunk)
- {
- chunk->setNeighbor(EAST, zChunk);
- Game::INSTANCE->zGenerator()->postprocessChunk(zChunk);
- }
- }
- getAddrOfWorld(center + Point(-CHUNK_SIZE, 0), addr);
- zChunk = chunks->z(addr, 8);
- if (zChunk)
- {
- zChunk->setNeighbor(EAST, chunk);
- if (chunk)
- {
- chunk->setNeighbor(WEST, zChunk);
- Game::INSTANCE->zGenerator()->postprocessChunk(zChunk);
- }
- }
- getAddrOfWorld(center + Point(0, CHUNK_SIZE), addr);
- zChunk = chunks->z(addr, 8);
- if (zChunk)
- {
- zChunk->setNeighbor(NORTH, chunk);
- if (chunk)
- {
- chunk->setNeighbor(SOUTH, zChunk);
- Game::INSTANCE->zGenerator()->postprocessChunk(zChunk);
- }
- }
- getAddrOfWorld(center + Point(0, -CHUNK_SIZE), addr);
- zChunk = chunks->z(addr, 8);
- if (zChunk)
- {
- zChunk->setNeighbor(SOUTH, chunk);
- if (chunk)
- {
- chunk->setNeighbor(NORTH, zChunk);
- Game::INSTANCE->zGenerator()->postprocessChunk(zChunk);
- }
- }
- DoLaterHandler laterHandler;
- if (chunk)
- {
- chunkCs.unlock();
- Game::INSTANCE->zGenerator()->postprocessChunk(chunk);
- chunk->setAdded();
- for (Entity* entity : chunk->getEntitiesInChunk())
- {
- addEntity(dynamic_cast<Entity*>(entity->getThis()));
- }
- 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);
- }
- else
- {
- chunkCs.unlock();
- }
- if (old)
- {
- old->onUnloaded();
- removedChunksCs.lock();
- removedChunks.add(old);
- removedChunksCs.unlock();
- }
- if (chunk) chunk->onLoaded();
- laterHandler.execute();
- if (chunk)
- {
- updateLightAtChunkBorders(chunk);
- chunk->updateLightSources();
- }
- }
- void Dimension::save(Text worldDir) const
- {
- File d;
- d.setFile(Game::INSTANCE->getWorldDirectory() + "/dim/" + Text(dimensionId)
- + "/meta.dim");
- d.create();
- d.open(File::Style::write);
- d.write((char*)&nextStructureId, 8);
- d.write((char*)¤tDayTime, 8);
- d.close();
- Array<Framework::Point> otherChunks;
- for (auto chunk = chunkList.begin(); chunk; chunk++)
- {
- if (!chunk._) continue;
- File* file = new File();
- Text filePath = worldDir + "/dim/" + dimensionId + "/";
- filePath.appendHex(chunk->getCenter().x);
- filePath += "_";
- filePath.appendHex(chunk->getCenter().y);
- filePath += ".chunk";
- file->setFile(filePath);
- if (file->open(File::Style::write)) chunk->save(file, otherChunks);
- file->close();
- file->release();
- char addr[8];
- getAddrOfWorld(chunk->getCenter(), addr);
- map->saveMap(addr, 8);
- }
- // since all chunks were saved otherChunks can be ignored
- entityCs.lock();
- for (Entity* entity : *entities)
- {
- if (entity->zType()->getId() == EntityTypeEnum::PLAYER)
- {
- File pFile;
- pFile.setFile(
- worldDir + "/player/"
- + Game::INSTANCE->getPlayerId(((Player*)entity)->getName()));
- pFile.create();
- if (pFile.open(File::Style::write))
- {
- Game::INSTANCE->zEntityType(EntityTypeEnum::PLAYER)
- ->saveEntity(entity, &pFile);
- pFile.close();
- }
- }
- }
- entityCs.unlock();
- for (MultiblockStructure* structure : structures)
- {
- saveStructure(structure);
- }
- }
- int Dimension::getDimensionId() const
- {
- return dimensionId;
- }
- bool Dimension::hasChunck(int x, int y) const
- {
- if (zChunk(Point(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(Point(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()), Point(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::zTarget(Framework::Vec3<float> pos,
- Vec3<float> direction,
- float maxDistanceSq) const
- {
- double minDist = 0;
- Entity* closestEntity = 0;
- entityCs.lock();
- for (auto entity : *entities)
- {
- if (!entity->isRemoved()
- && entity->getPosition().distanceSq(pos) <= maxDistanceSq)
- {
- double dist = entity->getHitDistance(pos, direction);
- if (!isnan(dist))
- {
- if (!closestEntity || dist < minDist)
- {
- closestEntity = entity;
- minDist = dist;
- }
- }
- }
- }
- entityCs.unlock();
- return closestEntity;
- }
- Entity* Dimension::zEntity(int id) const
- {
- entityCs.lock();
- for (auto entity : *entities)
- {
- if (!entity->isRemoved() && entity->getId() == id)
- {
- entityCs.unlock();
- return entity;
- }
- }
- entityCs.unlock();
- return 0;
- }
- Entity* Dimension::zNearestEntity(
- Framework::Vec3<float> pos, std::function<bool(Entity*)> filter) const
- {
- Entity* result = 0;
- float sqDist = 0;
- entityCs.lock();
- for (auto entity : *entities)
- {
- if (!entity->isRemoved() && filter(entity))
- {
- float d = pos.distanceSq(entity->getPosition());
- if (!result || d < sqDist)
- {
- result = entity;
- sqDist = d;
- }
- }
- }
- entityCs.unlock();
- return result;
- }
- void Dimension::removeEntity(int id)
- {
- int index = 0;
- entityCs.lock();
- for (auto entity : *entities)
- {
- if (entity->getId() == id)
- {
- entities->remove(index);
- entityCs.unlock();
- return;
- }
- index++;
- }
- entityCs.unlock();
- }
- 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(Chunk* zChunk)
- {
- if (lightUpdateQueue.getEntryCount() > 300000)
- {
- Logging::warning()
- << "light calculation queue is over 300000 blocks long";
- }
- Point center = zChunk->getCenter();
- Chunk* xn = this->zChunk(center - Point(CHUNK_SIZE, 0));
- Chunk* xp = this->zChunk(center + Point(CHUNK_SIZE, 0));
- Chunk* yn = this->zChunk(center - Point(0, CHUNK_SIZE));
- Chunk* yp = this->zChunk(center + Point(0, CHUNK_SIZE));
- for (int i = WORLD_HEIGHT - 1; i >= 0; i--)
- {
- for (int j = 0; j < CHUNK_SIZE; j++)
- {
- if (xn)
- {
- unsigned char* light
- = xn->getLightData(Vec3<int>(CHUNK_SIZE - 1, j, i));
- unsigned char* light2
- = zChunk->getLightData(Vec3<int>(0, j, i));
- if (*(int*)light != *(int*)light2
- || *(int*)(light + 2) != *(int*)(light2 + 2))
- {
- updateLightning(Vec3<int>(center.x - CHUNK_SIZE / 2 - 1,
- center.y - CHUNK_SIZE / 2 + j,
- i));
- updateLightning(Vec3<int>(center.x - CHUNK_SIZE / 2,
- center.y - CHUNK_SIZE / 2 + j,
- i));
- }
- }
- if (xp)
- {
- unsigned char* light = xp->getLightData(Vec3<int>(0, j, i));
- unsigned char* light2
- = zChunk->getLightData(Vec3<int>(CHUNK_SIZE - 1, j, i));
- if (*(int*)light != *(int*)light2
- || *(int*)(light + 2) != *(int*)(light2 + 2))
- {
- updateLightning(Vec3<int>(center.x + CHUNK_SIZE / 2 - 1,
- center.y - CHUNK_SIZE / 2 + j,
- i));
- updateLightning(Vec3<int>(center.x + CHUNK_SIZE / 2,
- center.y - CHUNK_SIZE / 2 + j,
- i));
- }
- }
- if (yn)
- {
- unsigned char* light
- = yn->getLightData(Vec3<int>(j, CHUNK_SIZE - 1, i));
- unsigned char* light2
- = zChunk->getLightData(Vec3<int>(j, 0, i));
- if (*(int*)light != *(int*)light2
- || *(int*)(light + 2) != *(int*)(light2 + 2))
- {
- updateLightning(Vec3<int>(center.x - CHUNK_SIZE / 2 + j,
- center.y - CHUNK_SIZE / 2 - 1,
- i));
- updateLightning(Vec3<int>(center.x - CHUNK_SIZE / 2 + j,
- center.y - CHUNK_SIZE / 2,
- i));
- }
- }
- if (yp)
- {
- unsigned char* light = yp->getLightData(Vec3<int>(j, 0, i));
- unsigned char* light2
- = zChunk->getLightData(Vec3<int>(j, CHUNK_SIZE - 1, i));
- if (*(int*)light != *(int*)light2
- || *(int*)(light + 2) != *(int*)(light2 + 2))
- {
- updateLightning(Vec3<int>(center.x - CHUNK_SIZE / 2 + j,
- center.y + CHUNK_SIZE / 2 - 1,
- i));
- updateLightning(Vec3<int>(center.x - CHUNK_SIZE / 2 + j,
- center.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)
- {
- __int64 id = structureManager->getStructureId(uniquePosition);
- if (id > 0)
- {
- return zStructureById(id);
- }
- return 0;
- }
- MultiblockStructure* Dimension::zStructureById(__int64 id)
- {
- structurCs.lock();
- for (MultiblockStructure* str : structures)
- {
- if (str->getStructureId() == id)
- {
- structurCs.unlock();
- return str;
- }
- }
- MultiblockStructure* structure = structureManager->loadStructure(id);
- if (structure)
- {
- structures.add(structure);
- structurCs.unlock();
- return structure;
- }
- Logging::warning() << "did not find Structure information file '"
- << std::hex << id << "'.";
- structurCs.unlock();
- return 0;
- }
- void Dimension::requestStopAndWait()
- {
- stop = 1;
- waitForThread(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];
- Point 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() const
- {
- return chunkList.getEntryCount();
- }
- double Dimension::getCurrentDayTime() const
- {
- return currentDayTime;
- }
- double Dimension::getNightDuration() const
- {
- return nightDuration;
- }
- double Dimension::getNightTransitionDuration() const
- {
- return nightTransitionDuration;
- }
- double Dimension::getDayDuration() const
- {
- return dayDuration;
- }
|