#include "World.h" #include #include #include #include #include #include #include "Constants.h" #include "Game.h" #include "Globals.h" #include "Registries.h" #include "WorldUpdate.h" using namespace Network; using namespace Framework; World* World::INSTANCE = 0; World::World(Bildschirm3D* zScreen, FactoryClient* client) : Thread(), client(client) { renderedWorld = new Welt3D(); renderedWorld->addDiffuseLight(DiffuseLight{ Vec3(0.5f, 0.5f, -1.f), Vec3(1.f, 1.f, 1.f)}); currentDimension = new Dimension(); renderedWorld->addCollection( dynamic_cast(currentDimension->getThis())); zScreenPtr = zScreen; kam = new PlayerKam(zScreen); kam->setWelt(renderedWorld); zScreen->addKamera(kam); firstMessage = 1; ownEntityId = -1; currentTarget = 0; dayLightFactor = 1; time = 0; dayLength = 1000; transitionLength = 0; nightLength = 0; fallbackVertexLightBuffer = zScreen->zGraphicsApi()->createStructuredBuffer(16); char data[16]; memset(data, 0, 16); *(int*)data = 0xFFFFFF00; fallbackVertexLightBuffer->setData(data); fallbackVertexLightBuffer->setLength(16); fallbackVertexLightBuffer->copieren(); selectionModel = new FactoryCraftModel(); selectionModel->setModelDaten(zScreen->zGraphicsApi()->getModel("cube")); selectionModel->setSize(1.005f); selectionModel->setVisible(0); selectionModel->setModelTextur(new Model3DTextur()); for (int i = 0; i < 6; i++) { selectionModel->zTextur()->setPolygonTextur(i, zScreen->zGraphicsApi()->createOrGetTextur( "blocks.ltdb/selectedblock.p")); } selectionModel->setAlpha(1); selectionModel->setUseEffectAlpha(1); renderedWorld->addZeichnung(selectionModel); start(); } World::~World() { zScreenPtr->removeKamera(kam); currentDimension->release(); if (currentTarget) currentTarget->release(); client->release(); World::INSTANCE = 0; } void World::update(bool background) { NetworkReader* serverMessageReader = 0; unsigned char type = 0; while (background ? serverMessageReader = client->getNextBackgroundMessage() : serverMessageReader = client->getNextForegroundMessage()) { serverMessageReader->lese((char*)&type, 1); if (type == 2) // WORLD UPDATE { int id = 0; serverMessageReader->lese((char*)&id, 4); STATIC_REGISTRY(WorldUpdateType) .zElement(id) ->applyUpdateAndCheck(serverMessageReader); } if (type == 3) // API MESSAGE { int length; serverMessageReader->lese((char*)&length, 4); char* data = new char[length]; serverMessageReader->lese(data, length); switch (data[0]) { case 1: // dimension message { int dimId = *(int*)(data + 1); if (dimId == currentDimension->getId()) { currentDimension->api(data + 5); } break; } case 2: // gui message ((Game*)(Menu*)menuRegister->get("game"))->api(data + 1); break; case 3: // set target { switch (data[1]) { case 0: setTarget(0); ((Game*)(Menu*)menuRegister->get("game")) ->setTargetUIML(""); break; case 1: setTarget(zEntity(*(int*)(data + 2))); ((Game*)(Menu*)menuRegister->get("game")) ->setTargetUIML(""); break; case 2: setTarget(zBlockAt(Vec3(*(int*)(data + 2), *(int*)(data + 6), *(int*)(data + 10)))); int side = *(int*)(data + 14); short len = *(short*)(data + 18); char* uiml = new char[len + 1]; memcpy(uiml, data + 20, len); uiml[len] = 0; ((Game*)(Menu*)menuRegister->get("game")) ->setTargetUIML(uiml); delete[] uiml; break; } break; } case 4: // chat message { ((Game*)(Menu*)menuRegister->get("game")) ->zChat() ->addMessage(data + 1); break; } case 5: // chat options { ((Game*)(Menu*)menuRegister->get("game")) ->zChat() ->initOptions(data + 1); break; } case 6: // map data { ByteArrayReader reader(data + 1, length - 1, 0); ChunkMap* map = new ChunkMap(&reader); ((Game*)(Menu*)menuRegister->get("game")) ->zMap() ->addChunk(map); break; } case 7: // map player data { ((Game*)(Menu*)menuRegister->get("game")) ->zMap() ->updatePlayerData(data + 1); break; } case 8: // time sync { nightLength = *(double*)(data + 9); transitionLength = *(double*)(data + 17); dayLength = *(double*)(data + 25); time = *(double*)(data + 1); break; } } delete[] data; } if (type == 4) // POSITION UPDATE { int old = ownEntityId; serverMessageReader->lese((char*)&ownEntityId, 4); int dimensionId = 0; serverMessageReader->lese((char*)&dimensionId, 4); currentDimension->setId(dimensionId); kam->setEntityId(ownEntityId); Entity* p = zEntity(ownEntityId); if (p) p->setPlayerControlled(); if (old != ownEntityId) client->sendPlayerAction("\5", 1); } client->endMessageReading(background); } client->endMessageReading(background); Entity* player = getCurrentPlayerEntity(); if (player) { renderedWorld->lock(); currentDimension->removeDistantChunks( {(int)player->getPos().x, (int)player->getPos().y}); Punkt currentChunk = getChunkCenter((int)player->getX(), (int)player->getY()); for (int x = 0; x <= CHUNK_VISIBILITY_RANGE; x++) { for (int y = 0; y <= CHUNK_VISIBILITY_RANGE; y++) { std::function requestChunk = [this](Punkt center) { Chunk* zC = currentDimension->zChunk(center); if (!zC) { char msg[1]; msg[0] = 0; // add observer and request chaunk data Punkt pos = center; subLock.lock(); bool found = 0; for (Punkt p : subscriptions) { if (p == pos) { found = 1; break; } } if (!found) { client->chunkAPIRequest(pos, msg, 1); subscriptions.add(pos); } subLock.unlock(); } }; requestChunk( currentChunk + Punkt(x * CHUNK_SIZE, y * CHUNK_SIZE)); if (y > 0) requestChunk( currentChunk + Punkt(x * CHUNK_SIZE, -y * CHUNK_SIZE)); if (x > 0) { requestChunk( currentChunk + Punkt(-x * CHUNK_SIZE, y * CHUNK_SIZE)); if (y > 0) requestChunk(currentChunk + Punkt(-x * CHUNK_SIZE, -y * CHUNK_SIZE)); } } } renderedWorld->unlock(); } } void World::onTick(double time) { selectionModel->tick(0.1); this->time += time; if (this->time >= dayLength + nightLength + transitionLength * 2) { this->time -= dayLength + nightLength + transitionLength * 2; } if (this->time > dayLength && this->time < dayLength + transitionLength) { dayLightFactor = 1.f - (float)((this->time - dayLength) / transitionLength) * 0.95f; } else if (this->time > dayLength + transitionLength && this->time < dayLength + transitionLength + nightLength) { // night dayLightFactor = 0.05f; if (renderedWorld->getDiffuseLightCount() > 0) { renderedWorld->removeDiffuseLight(0); } } else if (this->time > dayLength + transitionLength + nightLength) { dayLightFactor = (float)((this->time - dayLength - nightLength - transitionLength) / transitionLength) * 0.95f + 0.05f; } else { dayLightFactor = 1.f; } if (this->time < dayLength + transitionLength || this->time > dayLength + transitionLength + nightLength) { float currentDayTime = (float)(this->time < dayLength + transitionLength ? this->time + transitionLength : this->time - dayLength + transitionLength + nightLength); Vec3 sunPos = Vec3(-200.f, 50.f, 0.f); sunPos.rotateY(( float)((currentDayTime / (dayLength + transitionLength * 2)) * PI)); sunPos.normalize(); if (!renderedWorld->getDiffuseLightCount()) { renderedWorld->addDiffuseLight( {-sunPos, Vec3(1.0, 1.0, 1.0)}); } else { renderedWorld->getDiffuseLight(0).direction = -sunPos; } } } void World::setChunk(Chunk* chunk) { zScreenPtr->lock(); renderedWorld->lock(); currentDimension->setChunk(chunk, chunk->getCenter()); renderedWorld->unlock(); zScreenPtr->unlock(); } void World::thread() { new AsynchronCall("World Update", [this]() { while (client->isConnected()) { zScreenPtr->lock(); if (World::INSTANCE != this) { zScreenPtr->unlock(); return; } zScreenPtr->unlock(); update(0); Sleep(10); } std::cout << "foreground connection lost\n"; }); while (client->isConnected()) { zScreenPtr->lock(); if (World::INSTANCE != this) { zScreenPtr->unlock(); return; } zScreenPtr->unlock(); update(1); Sleep(10); } Sleep(1000); zScreenPtr->lock(); std::cout << "background connection lost\n"; menuRegister->get("game")->hide(); menuRegister->get("serverSelection")->show(); zScreenPtr->unlock(); zScreenPtr->postAction([this]() { if (World::INSTANCE == this) { World::INSTANCE = 0; release(); } }); } Block* World::zBlockAt(Framework::Vec3 location) const { return currentDimension->zBlock(location); } Block* World::getBlockAt(Framework::Vec3 location) const { return currentDimension->getBlock(location); } Dimension* World::zDimension() const { return currentDimension; } void World::setVisibility(Entity* zEntity, bool visible) { renderedWorld->lock(); if (visible) renderedWorld->addZeichnung( dynamic_cast(zEntity->getThis())); else renderedWorld->removeZeichnung(zEntity); renderedWorld->unlock(); } Framework::Punkt World::getChunkCenter(int x, int y) const { return Punkt(((x < 0 ? x + 1 : x) / CHUNK_SIZE) * CHUNK_SIZE + (x < 0 ? -CHUNK_SIZE : CHUNK_SIZE) / 2, ((y < 0 ? y + 1 : y) / CHUNK_SIZE) * CHUNK_SIZE + (y < 0 ? -CHUNK_SIZE : CHUNK_SIZE) / 2); } Entity* World::zEntity(int id) const { Entity* e = currentDimension->zEntity(id); if (e) return e; return 0; } Entity* World::getEntity(int id) const { Entity* e = currentDimension->getEntity(id); if (e) return e; return 0; } void World::removeEntity(int id) { currentDimension->removeEntity(id); } PlayerKam* World::zKamera() const { return kam; } int World::getCurrentPlayerId() const { return ownEntityId; } Entity* World::getCurrentPlayerEntity() const { return zEntity(ownEntityId); } void World::setTarget(Framework::Model3D* zTarget) { if (zTarget != currentTarget) { targetLock.lock(); if (!zTarget) { selectionModel->setVisible(0); } else { selectionModel->setPosition( zTarget->getPos().x, zTarget->getPos().y, zTarget->getPos().z); Block* b = dynamic_cast(zTarget); if (b && b->getPartOfModels()) { selectionModel->setDestroyedState(b->getEffectPercentage()); } else { selectionModel->setDestroyedState(0); } selectionModel->setVisible(1); } if (currentTarget) { currentTarget->setAmbientFactor( currentTarget->getAmbientFactor() - 0.2f); currentTarget->release(); currentTarget = 0; } if (zTarget) { currentTarget = dynamic_cast(zTarget->getThis()); if (currentTarget) currentTarget->setAmbientFactor( currentTarget->getAmbientFactor() + 0.2f); } targetLock.unlock(); } } void World::lockWorld() { renderedWorld->lock(); } void World::unlockWorld() { renderedWorld->unlock(); } void World::onChunkAdded(Punkt pos) { subLock.lock(); int index = 0; for (Punkt p : subscriptions) { if (p == pos) { subscriptions.remove(index); break; } index++; } subLock.unlock(); } Framework::Model3D* World::getCurrentTarget() const { while (targetLock.isLocked()) Sleep(1); return currentTarget ? dynamic_cast(currentTarget->getThis()) : 0; } FactoryCraftModel* World::zSelectedEffectModel() const { return selectionModel; } Chunk* World::zChunk(Punkt center) { return currentDimension->zChunk(center); } FactoryClient* World::zClient() const { return client; } float World::getDayLightFactor() const { return dayLightFactor; } Framework::DXBuffer* World::zFallbackVertexLightBuffer() { return fallbackVertexLightBuffer; }