|
@@ -1,786 +1,902 @@
|
|
-#include <InMemoryBuffer.h>
|
|
|
|
|
|
+#include "Chunk.h"
|
|
|
|
+
|
|
#include <AsynchronCall.h>
|
|
#include <AsynchronCall.h>
|
|
|
|
+#include <InMemoryBuffer.h>
|
|
|
|
|
|
-#include "Chunk.h"
|
|
|
|
#include "Constants.h"
|
|
#include "Constants.h"
|
|
#include "Game.h"
|
|
#include "Game.h"
|
|
#include "NoBlock.h"
|
|
#include "NoBlock.h"
|
|
|
|
|
|
-
|
|
|
|
Chunk::Chunk(Framework::Punkt location, int dimensionId)
|
|
Chunk::Chunk(Framework::Punkt location, int dimensionId)
|
|
- : ReferenceCounter(),
|
|
|
|
- dimensionId(dimensionId),
|
|
|
|
- location(location),
|
|
|
|
- added(0),
|
|
|
|
- currentlyLoading(1)
|
|
|
|
-{
|
|
|
|
- blocks = new Block * [CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT];
|
|
|
|
- blockIds = new unsigned short[CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT];
|
|
|
|
- lightData = new unsigned char[CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT * 6];
|
|
|
|
- memset(blocks, 0, CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT * sizeof(Block*));
|
|
|
|
- memset(blockIds, 0, CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT * sizeof(unsigned short));
|
|
|
|
- memset(lightData, 0, CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT * 6);
|
|
|
|
- zNeighbours[0] = 0;
|
|
|
|
- zNeighbours[1] = 0;
|
|
|
|
- zNeighbours[2] = 0;
|
|
|
|
- zNeighbours[3] = 0;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-Chunk::Chunk(Framework::Punkt location, int dimensionId, Framework::StreamReader* zReader)
|
|
|
|
- : Chunk(location, dimensionId)
|
|
|
|
-{
|
|
|
|
- load(zReader);
|
|
|
|
|
|
+ : ReferenceCounter(),
|
|
|
|
+ dimensionId(dimensionId),
|
|
|
|
+ location(location),
|
|
|
|
+ added(0),
|
|
|
|
+ currentlyLoading(1)
|
|
|
|
+{
|
|
|
|
+ blocks = new Block*[CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT];
|
|
|
|
+ blockIds = new unsigned short[CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT];
|
|
|
|
+ lightData = new unsigned char[CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT * 6];
|
|
|
|
+ memset(blocks, 0, CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT * sizeof(Block*));
|
|
|
|
+ memset(blockIds,
|
|
|
|
+ 0,
|
|
|
|
+ CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT * sizeof(unsigned short));
|
|
|
|
+ memset(lightData, 0, CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT * 6);
|
|
|
|
+ zNeighbours[0] = 0;
|
|
|
|
+ zNeighbours[1] = 0;
|
|
|
|
+ zNeighbours[2] = 0;
|
|
|
|
+ zNeighbours[3] = 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+Chunk::Chunk(Framework::Punkt location,
|
|
|
|
+ int dimensionId,
|
|
|
|
+ Framework::StreamReader* zReader)
|
|
|
|
+ : Chunk(location, dimensionId)
|
|
|
|
+{
|
|
|
|
+ load(zReader);
|
|
}
|
|
}
|
|
|
|
|
|
Chunk::~Chunk()
|
|
Chunk::~Chunk()
|
|
{
|
|
{
|
|
- for (int i = 0; i < CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT; i++)
|
|
|
|
- {
|
|
|
|
- if (blocks[i])
|
|
|
|
- blocks[i]->release();
|
|
|
|
- }
|
|
|
|
- delete[] blocks;
|
|
|
|
- delete[] blockIds;
|
|
|
|
- delete[] lightData;
|
|
|
|
|
|
+ for (int i = 0; i < CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT; i++)
|
|
|
|
+ {
|
|
|
|
+ if (blocks[i]) blocks[i]->release();
|
|
|
|
+ }
|
|
|
|
+ delete[] blocks;
|
|
|
|
+ delete[] blockIds;
|
|
|
|
+ delete[] lightData;
|
|
}
|
|
}
|
|
|
|
|
|
void Chunk::addLightSource(int index)
|
|
void Chunk::addLightSource(int index)
|
|
{
|
|
{
|
|
- for (int i : lightSources)
|
|
|
|
- {
|
|
|
|
- if (i == index)
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- lightSources.add(index);
|
|
|
|
|
|
+ for (int i : lightSources)
|
|
|
|
+ {
|
|
|
|
+ if (i == index) return;
|
|
|
|
+ }
|
|
|
|
+ lightSources.add(index);
|
|
}
|
|
}
|
|
|
|
|
|
void Chunk::removeLightSource(int index)
|
|
void Chunk::removeLightSource(int index)
|
|
{
|
|
{
|
|
- for (auto i = lightSources.begin(); i; i++)
|
|
|
|
- {
|
|
|
|
- if (i.val() == index)
|
|
|
|
- {
|
|
|
|
- i.remove();
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ for (auto i = lightSources.begin(); i; i++)
|
|
|
|
+ {
|
|
|
|
+ if (i.val() == index)
|
|
|
|
+ {
|
|
|
|
+ i.remove();
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
void Chunk::sendLightToClient(Framework::StreamWriter* zWriter)
|
|
void Chunk::sendLightToClient(Framework::StreamWriter* zWriter)
|
|
{
|
|
{
|
|
- for (int z = 0; z < WORLD_HEIGHT; z++)
|
|
|
|
- {
|
|
|
|
- for (int x = 0; x < CHUNK_SIZE; x++)
|
|
|
|
- {
|
|
|
|
- for (int y = 0; y < CHUNK_SIZE; y++)
|
|
|
|
- {
|
|
|
|
- bool needSend = 0;
|
|
|
|
- for (int i = 0; i < 6; i++)
|
|
|
|
- {
|
|
|
|
- Vec3<int> pos = Vec3<int>(x, y, z) + getDirection(getDirectionFromIndex(i));
|
|
|
|
- if (pos.z >= 0 && pos.z < WORLD_HEIGHT)
|
|
|
|
- {
|
|
|
|
- if (pos.x >= 0 && pos.x < CHUNK_SIZE && pos.y >= 0 && pos.y < CHUNK_SIZE)
|
|
|
|
- {
|
|
|
|
- int bi = (pos.x * CHUNK_SIZE + pos.y) * WORLD_HEIGHT + pos.z;
|
|
|
|
- int type = blockIds[bi];
|
|
|
|
|
|
+ for (int z = 0; z < WORLD_HEIGHT; z++)
|
|
|
|
+ {
|
|
|
|
+ for (int x = 0; x < CHUNK_SIZE; x++)
|
|
|
|
+ {
|
|
|
|
+ for (int y = 0; y < CHUNK_SIZE; y++)
|
|
|
|
+ {
|
|
|
|
+ bool needSend = 0;
|
|
|
|
+ for (int i = 0; i < 6; i++)
|
|
|
|
+ {
|
|
|
|
+ Vec3<int> pos = Vec3<int>(x, y, z)
|
|
|
|
+ + getDirection(getDirectionFromIndex(i));
|
|
|
|
+ if (pos.z >= 0 && pos.z < WORLD_HEIGHT)
|
|
|
|
+ {
|
|
|
|
+ if (pos.x >= 0 && pos.x < CHUNK_SIZE && pos.y >= 0
|
|
|
|
+ && pos.y < CHUNK_SIZE)
|
|
|
|
+ {
|
|
|
|
+ int bi = (pos.x * CHUNK_SIZE + pos.y) * WORLD_HEIGHT
|
|
|
|
+ + pos.z;
|
|
|
|
+ int type = blockIds[bi];
|
|
needSend |= type != BlockTypeEnum::NO_BLOCK
|
|
needSend |= type != BlockTypeEnum::NO_BLOCK
|
|
&& type != BlockTypeEnum::AIR;
|
|
&& type != BlockTypeEnum::AIR;
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- if (i < 4 && zNeighbours[i])
|
|
|
|
- {
|
|
|
|
- Vec3<int> offset = getDirection(getDirectionFromIndex(i)) * 16;
|
|
|
|
- int bi = ((pos.x - offset.x) * CHUNK_SIZE + (pos.y - offset.y)) * WORLD_HEIGHT + (pos.z - offset.z);
|
|
|
|
- int type = zNeighbours[i]->blockIds[bi];
|
|
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ if (i < 4 && zNeighbours[i])
|
|
|
|
+ {
|
|
|
|
+ Vec3<int> offset
|
|
|
|
+ = getDirection(getDirectionFromIndex(i))
|
|
|
|
+ * 16;
|
|
|
|
+ int bi = ((pos.x - offset.x) * CHUNK_SIZE
|
|
|
|
+ + (pos.y - offset.y))
|
|
|
|
+ * WORLD_HEIGHT
|
|
|
|
+ + (pos.z - offset.z);
|
|
|
|
+ int type = zNeighbours[i]->blockIds[bi];
|
|
needSend |= type != BlockTypeEnum::NO_BLOCK
|
|
needSend |= type != BlockTypeEnum::NO_BLOCK
|
|
&& type != BlockTypeEnum::AIR;
|
|
&& type != BlockTypeEnum::AIR;
|
|
- }
|
|
|
|
- }
|
|
|
|
- if (needSend)
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- if (needSend)
|
|
|
|
- {
|
|
|
|
- int index = (x * CHUNK_SIZE + y) * WORLD_HEIGHT + z;
|
|
|
|
- zWriter->schreibe((char*)&index, 4);
|
|
|
|
- zWriter->schreibe((char*)(lightData + index * 6), 6);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- int end = -1;
|
|
|
|
- zWriter->schreibe((char*)&end, 4);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-Framework::Either<Block*, int> Chunk::zBlockNeighbor(Framework::Vec3<int> location)
|
|
|
|
-{
|
|
|
|
- if (location.x >= 0 && location.x < CHUNK_SIZE && location.y >= 0 && location.y < CHUNK_SIZE && location.z >= 0 && location.z < WORLD_HEIGHT)
|
|
|
|
- {
|
|
|
|
- int index = (location.x * CHUNK_SIZE + location.y) * WORLD_HEIGHT + location.z;
|
|
|
|
- if (blocks[index])
|
|
|
|
- return blocks[index];
|
|
|
|
- else
|
|
|
|
- return (int)blockIds[index];
|
|
|
|
- }
|
|
|
|
- if (added && location.z >= 0 && location.z < WORLD_HEIGHT)
|
|
|
|
- return Game::INSTANCE->zBlockAt({ location.x + this->location.x - CHUNK_SIZE / 2, location.y + this->location.y - CHUNK_SIZE / 2, location.z }, dimensionId);
|
|
|
|
- return 0;
|
|
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (needSend) break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (needSend)
|
|
|
|
+ {
|
|
|
|
+ int index = (x * CHUNK_SIZE + y) * WORLD_HEIGHT + z;
|
|
|
|
+ zWriter->schreibe((char*)&index, 4);
|
|
|
|
+ zWriter->schreibe((char*)(lightData + index * 6), 6);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ int end = -1;
|
|
|
|
+ zWriter->schreibe((char*)&end, 4);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+Framework::Either<Block*, int> Chunk::zBlockNeighbor(
|
|
|
|
+ Framework::Vec3<int> location)
|
|
|
|
+{
|
|
|
|
+ if (location.x >= 0 && location.x < CHUNK_SIZE && location.y >= 0
|
|
|
|
+ && location.y < CHUNK_SIZE && location.z >= 0
|
|
|
|
+ && location.z < WORLD_HEIGHT)
|
|
|
|
+ {
|
|
|
|
+ int index = (location.x * CHUNK_SIZE + location.y) * WORLD_HEIGHT
|
|
|
|
+ + location.z;
|
|
|
|
+ if (blocks[index])
|
|
|
|
+ return blocks[index];
|
|
|
|
+ else
|
|
|
|
+ return (int)blockIds[index];
|
|
|
|
+ }
|
|
|
|
+ if (added && location.z >= 0 && location.z < WORLD_HEIGHT)
|
|
|
|
+ return Game::INSTANCE->zBlockAt(
|
|
|
|
+ {location.x + this->location.x - CHUNK_SIZE / 2,
|
|
|
|
+ location.y + this->location.y - CHUNK_SIZE / 2,
|
|
|
|
+ location.z},
|
|
|
|
+ dimensionId);
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
void Chunk::notifyObservers(NetworkMessage* msg)
|
|
void Chunk::notifyObservers(NetworkMessage* msg)
|
|
{
|
|
{
|
|
- Array<int> remove;
|
|
|
|
- int index = 0;
|
|
|
|
- for (int id : observers)
|
|
|
|
- {
|
|
|
|
- Entity* zE = Game::INSTANCE->zEntity(id);
|
|
|
|
- if (!zE)
|
|
|
|
- remove.add(index, 0);
|
|
|
|
- else
|
|
|
|
- Game::INSTANCE->sendMessage(dynamic_cast<NetworkMessage*>(msg->getThis()), zE);
|
|
|
|
- index++;
|
|
|
|
- }
|
|
|
|
- for (int i : remove)
|
|
|
|
- observers.remove(i);
|
|
|
|
- msg->release();
|
|
|
|
|
|
+ Array<int> remove;
|
|
|
|
+ int index = 0;
|
|
|
|
+ for (int id : observers)
|
|
|
|
+ {
|
|
|
|
+ Entity* zE = Game::INSTANCE->zEntity(id);
|
|
|
|
+ if (!zE)
|
|
|
|
+ remove.add(index, 0);
|
|
|
|
+ else
|
|
|
|
+ Game::INSTANCE->sendMessage(
|
|
|
|
+ dynamic_cast<NetworkMessage*>(msg->getThis()), zE);
|
|
|
|
+ index++;
|
|
|
|
+ }
|
|
|
|
+ for (int i : remove)
|
|
|
|
+ observers.remove(i);
|
|
|
|
+ msg->release();
|
|
}
|
|
}
|
|
|
|
|
|
void Chunk::addObserver(Entity* zEntity, DoLaterHandler& laterHandler)
|
|
void Chunk::addObserver(Entity* zEntity, DoLaterHandler& laterHandler)
|
|
{
|
|
{
|
|
- for (int id : observers)
|
|
|
|
- {
|
|
|
|
- if (id == zEntity->getId())
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- int id = zEntity->getId();
|
|
|
|
- observers.add(id);
|
|
|
|
- laterHandler.addTodo([this, id]()
|
|
|
|
- {
|
|
|
|
- InMemoryBuffer buffer;
|
|
|
|
- buffer.schreibe("\4", 1);
|
|
|
|
- buffer.schreibe((char*)&location.x, 4);
|
|
|
|
- buffer.schreibe((char*)&location.y, 4);
|
|
|
|
- sendToClient(&buffer);
|
|
|
|
- sendLightToClient(&buffer);
|
|
|
|
- NetworkMessage* msg = new NetworkMessage();
|
|
|
|
- msg->addressDimension();
|
|
|
|
- std::cout << "chunk size: " << buffer.getSize() << "b\n";
|
|
|
|
- char* message = new char[buffer.getSize()];
|
|
|
|
- buffer.lese(message, (int)buffer.getSize());
|
|
|
|
- msg->setMessage(message, (int)buffer.getSize());
|
|
|
|
- msg->setUseBackground();
|
|
|
|
- Entity* e = Game::INSTANCE->zEntity(id);
|
|
|
|
- if (e)
|
|
|
|
- {
|
|
|
|
- Game::INSTANCE->sendMessage(msg, e);
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- msg->release();
|
|
|
|
- });
|
|
|
|
|
|
+ for (int id : observers)
|
|
|
|
+ {
|
|
|
|
+ if (id == zEntity->getId()) return;
|
|
|
|
+ }
|
|
|
|
+ int id = zEntity->getId();
|
|
|
|
+ observers.add(id);
|
|
|
|
+ laterHandler.addTodo([this, id]() {
|
|
|
|
+ InMemoryBuffer buffer;
|
|
|
|
+ buffer.schreibe("\4", 1);
|
|
|
|
+ buffer.schreibe((char*)&location.x, 4);
|
|
|
|
+ buffer.schreibe((char*)&location.y, 4);
|
|
|
|
+ sendToClient(&buffer);
|
|
|
|
+ sendLightToClient(&buffer);
|
|
|
|
+ NetworkMessage* msg = new NetworkMessage();
|
|
|
|
+ msg->addressDimension();
|
|
|
|
+ std::cout << "chunk size: " << buffer.getSize() << "b\n";
|
|
|
|
+ char* message = new char[buffer.getSize()];
|
|
|
|
+ buffer.lese(message, (int)buffer.getSize());
|
|
|
|
+ msg->setMessage(message, (int)buffer.getSize());
|
|
|
|
+ msg->setUseBackground();
|
|
|
|
+ Entity* e = Game::INSTANCE->zEntity(id);
|
|
|
|
+ if (e)
|
|
|
|
+ {
|
|
|
|
+ Game::INSTANCE->sendMessage(msg, e);
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ msg->release();
|
|
|
|
+ });
|
|
}
|
|
}
|
|
|
|
|
|
void Chunk::removeObserver(Entity* zEntity)
|
|
void Chunk::removeObserver(Entity* zEntity)
|
|
{
|
|
{
|
|
- int index = 0;
|
|
|
|
- for (int id : observers)
|
|
|
|
- {
|
|
|
|
- if (id == zEntity->getId())
|
|
|
|
- {
|
|
|
|
- observers.remove(index);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- index++;
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-void Chunk::api(Framework::StreamReader* zRequest, Entity* zSource, DoLaterHandler& laterHandler)
|
|
|
|
-{
|
|
|
|
- // TODO: answer api messages
|
|
|
|
- char type;
|
|
|
|
- zRequest->lese(&type, 1);
|
|
|
|
- switch (type)
|
|
|
|
- {
|
|
|
|
- case 0:
|
|
|
|
- // register observer
|
|
|
|
- addObserver(zSource, laterHandler);
|
|
|
|
- break;
|
|
|
|
- case 1:
|
|
|
|
- // unsubscribe
|
|
|
|
- removeObserver(zSource);
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
|
|
+ int index = 0;
|
|
|
|
+ for (int id : observers)
|
|
|
|
+ {
|
|
|
|
+ if (id == zEntity->getId())
|
|
|
|
+ {
|
|
|
|
+ observers.remove(index);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ index++;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void Chunk::api(Framework::StreamReader* zRequest,
|
|
|
|
+ Entity* zSource,
|
|
|
|
+ DoLaterHandler& laterHandler)
|
|
|
|
+{
|
|
|
|
+ // TODO: answer api messages
|
|
|
|
+ char type;
|
|
|
|
+ zRequest->lese(&type, 1);
|
|
|
|
+ switch (type)
|
|
|
|
+ {
|
|
|
|
+ case 0:
|
|
|
|
+ // register observer
|
|
|
|
+ addObserver(zSource, laterHandler);
|
|
|
|
+ break;
|
|
|
|
+ case 1:
|
|
|
|
+ // unsubscribe
|
|
|
|
+ removeObserver(zSource);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
void Chunk::initializeLightning()
|
|
void Chunk::initializeLightning()
|
|
{
|
|
{
|
|
- unsigned char dayLight[6] = { 255, 255, 255, 0, 0, 0 };
|
|
|
|
- unsigned char noLight[6] = { 0, 0, 0, 0, 0, 0 };
|
|
|
|
- while (true)
|
|
|
|
- {
|
|
|
|
- bool changes = false;
|
|
|
|
- for (int z = WORLD_HEIGHT - 1; z >= 0; z--)
|
|
|
|
- {
|
|
|
|
- for (int x = 0; x < CHUNK_SIZE; x++)
|
|
|
|
- {
|
|
|
|
- for (int y = 0; y < CHUNK_SIZE; y++)
|
|
|
|
- {
|
|
|
|
- int index = (x * CHUNK_SIZE + y) * WORLD_HEIGHT + z;
|
|
|
|
- unsigned char* light = getLightData(Vec3<int>(x, y, z));
|
|
|
|
- unsigned char newLight[6] = { 0, 0, 0, 0, 0, 0 };
|
|
|
|
- for (int i = 0; i < 6; i++)
|
|
|
|
- {
|
|
|
|
- unsigned char* neighborLeight;
|
|
|
|
- Vec3<int> neighborPos = Vec3<int>(x, y, z) + getDirection(getDirectionFromIndex(i));
|
|
|
|
- if (neighborPos.z < 0 || neighborPos.x < 0 || neighborPos.y < 0 || neighborPos.x >= CHUNK_SIZE || neighborPos.y >= CHUNK_SIZE)
|
|
|
|
- {
|
|
|
|
- neighborLeight = noLight;
|
|
|
|
- }
|
|
|
|
- else if (neighborPos.z >= WORLD_HEIGHT)
|
|
|
|
- {
|
|
|
|
- neighborLeight = dayLight;
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- neighborLeight = getLightData(neighborPos);
|
|
|
|
- }
|
|
|
|
- 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 = blocks[index] ? blocks[index] : StaticRegistry<BlockType>::INSTANCE.zElement(blockIds[index])->zDefault();
|
|
|
|
- // 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])
|
|
|
|
- {
|
|
|
|
- changes = 1;
|
|
|
|
- memcpy(light, newLight, 6);
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- if (!changes)
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-Framework::Either<Block*, int> Chunk::zBlockAt(Framework::Vec3<int> location) const
|
|
|
|
-{
|
|
|
|
- int index = (location.x * CHUNK_SIZE + location.y) * WORLD_HEIGHT + location.z;
|
|
|
|
- assert(index < CHUNK_SIZE* CHUNK_SIZE* WORLD_HEIGHT);
|
|
|
|
- if (blocks[index])
|
|
|
|
- return blocks[index];
|
|
|
|
- else
|
|
|
|
- return (int)blockIds[index];
|
|
|
|
|
|
+ unsigned char dayLight[6] = {255, 255, 255, 0, 0, 0};
|
|
|
|
+ unsigned char noLight[6] = {0, 0, 0, 0, 0, 0};
|
|
|
|
+ while (true)
|
|
|
|
+ {
|
|
|
|
+ bool changes = false;
|
|
|
|
+ for (int z = WORLD_HEIGHT - 1; z >= 0; z--)
|
|
|
|
+ {
|
|
|
|
+ for (int x = 0; x < CHUNK_SIZE; x++)
|
|
|
|
+ {
|
|
|
|
+ for (int y = 0; y < CHUNK_SIZE; y++)
|
|
|
|
+ {
|
|
|
|
+ int index = (x * CHUNK_SIZE + y) * WORLD_HEIGHT + z;
|
|
|
|
+ unsigned char* light = getLightData(Vec3<int>(x, y, z));
|
|
|
|
+ unsigned char newLight[6] = {0, 0, 0, 0, 0, 0};
|
|
|
|
+ for (int i = 0; i < 6; i++)
|
|
|
|
+ {
|
|
|
|
+ unsigned char* neighborLeight;
|
|
|
|
+ Vec3<int> neighborPos
|
|
|
|
+ = Vec3<int>(x, y, z)
|
|
|
|
+ + getDirection(getDirectionFromIndex(i));
|
|
|
|
+ if (neighborPos.z < 0 || neighborPos.x < 0
|
|
|
|
+ || neighborPos.y < 0 || neighborPos.x >= CHUNK_SIZE
|
|
|
|
+ || neighborPos.y >= CHUNK_SIZE)
|
|
|
|
+ {
|
|
|
|
+ neighborLeight = noLight;
|
|
|
|
+ }
|
|
|
|
+ else if (neighborPos.z >= WORLD_HEIGHT)
|
|
|
|
+ {
|
|
|
|
+ neighborLeight = dayLight;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ neighborLeight = getLightData(neighborPos);
|
|
|
|
+ }
|
|
|
|
+ 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
|
|
|
|
+ = blocks[index] ? blocks[index]
|
|
|
|
+ : StaticRegistry<BlockType>::INSTANCE
|
|
|
|
+ .zElement(blockIds[index])
|
|
|
|
+ ->zDefault();
|
|
|
|
+ // 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])
|
|
|
|
+ {
|
|
|
|
+ changes = 1;
|
|
|
|
+ memcpy(light, newLight, 6);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (!changes) break;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+Framework::Either<Block*, int> Chunk::zBlockAt(
|
|
|
|
+ Framework::Vec3<int> location) const
|
|
|
|
+{
|
|
|
|
+ int index
|
|
|
|
+ = (location.x * CHUNK_SIZE + location.y) * WORLD_HEIGHT + location.z;
|
|
|
|
+ assert(index < CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT);
|
|
|
|
+ if (blocks[index])
|
|
|
|
+ return blocks[index];
|
|
|
|
+ else
|
|
|
|
+ return (int)blockIds[index];
|
|
}
|
|
}
|
|
|
|
|
|
const Block* Chunk::zBlockConst(Framework::Vec3<int> location) const
|
|
const Block* Chunk::zBlockConst(Framework::Vec3<int> location) const
|
|
{
|
|
{
|
|
- auto b = zBlockAt(location);
|
|
|
|
- if (b.isA())
|
|
|
|
- return b;
|
|
|
|
- if (b.getB())
|
|
|
|
- return StaticRegistry<BlockType>::INSTANCE.zElement(b.getB())->zDefault();
|
|
|
|
- return 0;
|
|
|
|
|
|
+ auto b = zBlockAt(location);
|
|
|
|
+ if (b.isA()) return b;
|
|
|
|
+ if (b.getB())
|
|
|
|
+ return StaticRegistry<BlockType>::INSTANCE.zElement(b.getB())
|
|
|
|
+ ->zDefault();
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
void Chunk::instantiateBlock(Framework::Vec3<int> location)
|
|
void Chunk::instantiateBlock(Framework::Vec3<int> location)
|
|
{
|
|
{
|
|
- auto b = zBlockAt(location);
|
|
|
|
- if (b.isA())
|
|
|
|
- return;
|
|
|
|
- if (!b.getB())
|
|
|
|
- generateBlock(location);
|
|
|
|
- b = zBlockAt(location);
|
|
|
|
- if (b.isB())
|
|
|
|
- putBlockAt(location, StaticRegistry<BlockType>::INSTANCE.zElement(b.getB())->createBlockAt({ location.x + this->location.x - CHUNK_SIZE / 2, location.y + this->location.y - CHUNK_SIZE / 2, location.z }, 0));
|
|
|
|
|
|
+ auto b = zBlockAt(location);
|
|
|
|
+ if (b.isA()) return;
|
|
|
|
+ if (!b.getB()) generateBlock(location);
|
|
|
|
+ b = zBlockAt(location);
|
|
|
|
+ if (b.isB())
|
|
|
|
+ putBlockAt(location,
|
|
|
|
+ StaticRegistry<BlockType>::INSTANCE.zElement(b.getB())
|
|
|
|
+ ->createBlockAt(
|
|
|
|
+ {location.x + this->location.x - CHUNK_SIZE / 2,
|
|
|
|
+ location.y + this->location.y - CHUNK_SIZE / 2,
|
|
|
|
+ location.z},
|
|
|
|
+ 0));
|
|
}
|
|
}
|
|
|
|
|
|
void Chunk::generateBlock(Framework::Vec3<int> location)
|
|
void Chunk::generateBlock(Framework::Vec3<int> location)
|
|
{
|
|
{
|
|
- int index = (location.x * CHUNK_SIZE + location.y) * WORLD_HEIGHT + location.z;
|
|
|
|
- if (blockIds[index])
|
|
|
|
- return;
|
|
|
|
- auto generated = Game::INSTANCE->zGenerator()->generateSingleBlock({ location.x + this->location.x - CHUNK_SIZE / 2, location.y + this->location.y - CHUNK_SIZE / 2, location.z }, dimensionId);
|
|
|
|
- if (generated.isA())
|
|
|
|
- putBlockAt(location, generated);
|
|
|
|
- else
|
|
|
|
- putBlockTypeAt(location, generated);
|
|
|
|
|
|
+ int index
|
|
|
|
+ = (location.x * CHUNK_SIZE + location.y) * WORLD_HEIGHT + location.z;
|
|
|
|
+ if (blockIds[index]) return;
|
|
|
|
+ auto generated = Game::INSTANCE->zGenerator()->generateSingleBlock(
|
|
|
|
+ {location.x + this->location.x - CHUNK_SIZE / 2,
|
|
|
|
+ location.y + this->location.y - CHUNK_SIZE / 2,
|
|
|
|
+ location.z},
|
|
|
|
+ dimensionId);
|
|
|
|
+ if (generated.isA())
|
|
|
|
+ putBlockAt(location, generated);
|
|
|
|
+ else
|
|
|
|
+ putBlockTypeAt(location, generated);
|
|
}
|
|
}
|
|
|
|
|
|
void Chunk::putBlockAt(Framework::Vec3<int> location, Block* block)
|
|
void Chunk::putBlockAt(Framework::Vec3<int> location, Block* block)
|
|
{
|
|
{
|
|
- int index = (location.x * CHUNK_SIZE + location.y) * WORLD_HEIGHT + location.z;
|
|
|
|
- assert(index < CHUNK_SIZE* CHUNK_SIZE* WORLD_HEIGHT&& index >= 0);
|
|
|
|
- Block* old = blocks[index];
|
|
|
|
- bool change = 0;
|
|
|
|
- bool wasLightSource = old ? old->zBlockType()->isLightSource() : StaticRegistry<BlockType>::INSTANCE.zElement(blockIds[index])->isLightSource();
|
|
|
|
- bool isLightSource = 0;
|
|
|
|
- if (block)
|
|
|
|
- {
|
|
|
|
- change = blockIds[index] != (unsigned short)block->zBlockType()->getId();
|
|
|
|
- blockIds[index] = (unsigned short)block->zBlockType()->getId();
|
|
|
|
- isLightSource = block->zBlockType()->isLightSource();
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- change = old != 0;
|
|
|
|
- }
|
|
|
|
- blocks[index] = block;
|
|
|
|
- for (int i = 0; i < 6; i++)
|
|
|
|
- {
|
|
|
|
- Direction d = getDirectionFromIndex(i);
|
|
|
|
- Either<Block*, int> neighbor = zBlockNeighbor(location + getDirection(d));
|
|
|
|
- if (neighbor.isA())
|
|
|
|
- ((Block*)neighbor)->setNeighbour(getOppositeDirection(d), block);
|
|
|
|
- if (block)
|
|
|
|
- block->setNeighbour(d, neighbor);
|
|
|
|
- }
|
|
|
|
- if (old)
|
|
|
|
- old->release();
|
|
|
|
- if (change)
|
|
|
|
- {
|
|
|
|
- if (isLightSource != wasLightSource)
|
|
|
|
- {
|
|
|
|
- if (isLightSource)
|
|
|
|
- addLightSource(index);
|
|
|
|
- else
|
|
|
|
- removeLightSource(index);
|
|
|
|
- }
|
|
|
|
- if (added)
|
|
|
|
- {
|
|
|
|
- char* msg = new char[9];
|
|
|
|
- msg[0] = 0; // set block
|
|
|
|
- *(int*)(msg + 1) = index;
|
|
|
|
- *(int*)(msg + 5)
|
|
|
|
- = block ? block->zBlockType()->getId() : BlockTypeEnum::NO_BLOCK;
|
|
|
|
- NetworkMessage* message = new NetworkMessage();
|
|
|
|
- message->addressChunck(this);
|
|
|
|
- message->setMessage(msg, 9);
|
|
|
|
- notifyObservers(message);
|
|
|
|
- for (int i = 0; i < 6; i++)
|
|
|
|
- {
|
|
|
|
- Direction d = getDirectionFromIndex(i);
|
|
|
|
- Framework::Vec3<int> loc = location + getDirection(d);
|
|
|
|
- if (loc.x >= 0 && loc.x < CHUNK_SIZE && loc.y >= 0 && loc.y < CHUNK_SIZE && loc.z >= 0 && loc.z < WORLD_HEIGHT)
|
|
|
|
- {
|
|
|
|
- NetworkMessage* msg = new NetworkMessage();
|
|
|
|
- msg->addressChunck(this);
|
|
|
|
- char* message = new char[11];
|
|
|
|
- message[0] = 1;
|
|
|
|
- int index = ((loc.x * CHUNK_SIZE + loc.y) * WORLD_HEIGHT + loc.z) * 6;
|
|
|
|
- *(int*)(message + 1) = index / 6;
|
|
|
|
- memcpy(message + 5, lightData + index, 6);
|
|
|
|
- msg->setMessage(message, 11);
|
|
|
|
- notifyObservers(msg);
|
|
|
|
- }
|
|
|
|
- else if (loc.z >= 0 && loc.z < WORLD_HEIGHT && i < 4 && zNeighbours[i])
|
|
|
|
- {
|
|
|
|
- NetworkMessage* msg = new NetworkMessage();
|
|
|
|
- msg->addressChunck(zNeighbours[i]);
|
|
|
|
- char* message = new char[11];
|
|
|
|
- message[0] = 1;
|
|
|
|
- loc -= getDirection(d) * CHUNK_SIZE;
|
|
|
|
- int index = ((loc.x * CHUNK_SIZE + loc.y) * WORLD_HEIGHT + loc.z) * 6;
|
|
|
|
- *(int*)(message + 1) = index / 6;
|
|
|
|
- memcpy(message + 5, zNeighbours[i]->getLightData(loc), 6);
|
|
|
|
- msg->setMessage(message, 11);
|
|
|
|
- notifyObservers(msg);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- Game::INSTANCE->updateLightningWithoutWait(getDimensionId(), Vec3<int>(location.x + this->location.x - CHUNK_SIZE / 2, location.y + this->location.y - CHUNK_SIZE / 2, location.z));
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ int index
|
|
|
|
+ = (location.x * CHUNK_SIZE + location.y) * WORLD_HEIGHT + location.z;
|
|
|
|
+ assert(index < CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT && index >= 0);
|
|
|
|
+ Block* old = blocks[index];
|
|
|
|
+ bool change = 0;
|
|
|
|
+ bool wasLightSource
|
|
|
|
+ = old ? old->zBlockType()->isLightSource()
|
|
|
|
+ : StaticRegistry<BlockType>::INSTANCE.zElement(blockIds[index])
|
|
|
|
+ ->isLightSource();
|
|
|
|
+ bool isLightSource = 0;
|
|
|
|
+ if (block)
|
|
|
|
+ {
|
|
|
|
+ change
|
|
|
|
+ = blockIds[index] != (unsigned short)block->zBlockType()->getId();
|
|
|
|
+ blockIds[index] = (unsigned short)block->zBlockType()->getId();
|
|
|
|
+ isLightSource = block->zBlockType()->isLightSource();
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ change = old != 0;
|
|
|
|
+ }
|
|
|
|
+ blocks[index] = block;
|
|
|
|
+ for (int i = 0; i < 6; i++)
|
|
|
|
+ {
|
|
|
|
+ Direction d = getDirectionFromIndex(i);
|
|
|
|
+ Either<Block*, int> neighbor
|
|
|
|
+ = zBlockNeighbor(location + getDirection(d));
|
|
|
|
+ if (neighbor.isA())
|
|
|
|
+ ((Block*)neighbor)->setNeighbour(getOppositeDirection(d), block);
|
|
|
|
+ if (block) block->setNeighbour(d, neighbor);
|
|
|
|
+ }
|
|
|
|
+ if (old) old->release();
|
|
|
|
+ if (change)
|
|
|
|
+ {
|
|
|
|
+ if (isLightSource != wasLightSource)
|
|
|
|
+ {
|
|
|
|
+ if (isLightSource)
|
|
|
|
+ addLightSource(index);
|
|
|
|
+ else
|
|
|
|
+ removeLightSource(index);
|
|
|
|
+ }
|
|
|
|
+ if (added)
|
|
|
|
+ {
|
|
|
|
+ char* msg = new char[9];
|
|
|
|
+ msg[0] = 0; // set block
|
|
|
|
+ *(int*)(msg + 1) = index;
|
|
|
|
+ *(int*)(msg + 5) = block ? block->zBlockType()->getId()
|
|
|
|
+ : BlockTypeEnum::NO_BLOCK;
|
|
|
|
+ NetworkMessage* message = new NetworkMessage();
|
|
|
|
+ message->addressChunck(this);
|
|
|
|
+ message->setMessage(msg, 9);
|
|
|
|
+ notifyObservers(message);
|
|
|
|
+ for (int i = 0; i < 6; i++)
|
|
|
|
+ {
|
|
|
|
+ Direction d = getDirectionFromIndex(i);
|
|
|
|
+ Framework::Vec3<int> loc = location + getDirection(d);
|
|
|
|
+ if (loc.x >= 0 && loc.x < CHUNK_SIZE && loc.y >= 0
|
|
|
|
+ && loc.y < CHUNK_SIZE && loc.z >= 0 && loc.z < WORLD_HEIGHT)
|
|
|
|
+ {
|
|
|
|
+ NetworkMessage* msg = new NetworkMessage();
|
|
|
|
+ msg->addressChunck(this);
|
|
|
|
+ char* message = new char[11];
|
|
|
|
+ message[0] = 1;
|
|
|
|
+ int index
|
|
|
|
+ = ((loc.x * CHUNK_SIZE + loc.y) * WORLD_HEIGHT + loc.z)
|
|
|
|
+ * 6;
|
|
|
|
+ *(int*)(message + 1) = index / 6;
|
|
|
|
+ memcpy(message + 5, lightData + index, 6);
|
|
|
|
+ msg->setMessage(message, 11);
|
|
|
|
+ notifyObservers(msg);
|
|
|
|
+ }
|
|
|
|
+ else if (loc.z >= 0 && loc.z < WORLD_HEIGHT && i < 4
|
|
|
|
+ && zNeighbours[i])
|
|
|
|
+ {
|
|
|
|
+ NetworkMessage* msg = new NetworkMessage();
|
|
|
|
+ msg->addressChunck(zNeighbours[i]);
|
|
|
|
+ char* message = new char[11];
|
|
|
|
+ message[0] = 1;
|
|
|
|
+ loc -= getDirection(d) * CHUNK_SIZE;
|
|
|
|
+ int index
|
|
|
|
+ = ((loc.x * CHUNK_SIZE + loc.y) * WORLD_HEIGHT + loc.z)
|
|
|
|
+ * 6;
|
|
|
|
+ *(int*)(message + 1) = index / 6;
|
|
|
|
+ memcpy(message + 5, zNeighbours[i]->getLightData(loc), 6);
|
|
|
|
+ msg->setMessage(message, 11);
|
|
|
|
+ notifyObservers(msg);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ Game::INSTANCE->updateLightningWithoutWait(getDimensionId(),
|
|
|
|
+ Vec3<int>(location.x + this->location.x - CHUNK_SIZE / 2,
|
|
|
|
+ location.y + this->location.y - CHUNK_SIZE / 2,
|
|
|
|
+ location.z));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
void Chunk::putBlockTypeAt(Framework::Vec3<int> location, int type)
|
|
void Chunk::putBlockTypeAt(Framework::Vec3<int> location, int type)
|
|
{
|
|
{
|
|
- int index = (location.x * CHUNK_SIZE + location.y) * WORLD_HEIGHT + location.z;
|
|
|
|
- assert(index < CHUNK_SIZE* CHUNK_SIZE* WORLD_HEIGHT);
|
|
|
|
- bool wasLightSource = StaticRegistry<BlockType>::INSTANCE.zElement(blockIds[index])->isLightSource();
|
|
|
|
- bool isLightSource = StaticRegistry<BlockType>::INSTANCE.zElement(type)->isLightSource();
|
|
|
|
- if (blockIds[index] != (unsigned short)type)
|
|
|
|
- {
|
|
|
|
- blockIds[index] = (unsigned short)type;
|
|
|
|
- for (int i = 0; i < 6; i++)
|
|
|
|
- {
|
|
|
|
- Direction d = getDirectionFromIndex(i);
|
|
|
|
- Either<Block*, int> neighbor = zBlockNeighbor(location + getDirection(d));
|
|
|
|
- if (neighbor.isA())
|
|
|
|
- ((Block*)neighbor)->setNeighbourType(getOppositeDirection(d), type);
|
|
|
|
- }
|
|
|
|
- if (isLightSource != wasLightSource)
|
|
|
|
- {
|
|
|
|
- if (isLightSource)
|
|
|
|
- addLightSource(index);
|
|
|
|
- else
|
|
|
|
- removeLightSource(index);
|
|
|
|
- }
|
|
|
|
- if (added)
|
|
|
|
- {
|
|
|
|
- char* msg = new char[9];
|
|
|
|
- msg[0] = 0; // set block
|
|
|
|
- *(int*)(msg + 1) = index;
|
|
|
|
- *(int*)(msg + 5) = type;
|
|
|
|
- NetworkMessage* message = new NetworkMessage();
|
|
|
|
- message->addressChunck(this);
|
|
|
|
- message->setMessage(msg, 9);
|
|
|
|
- notifyObservers(message);
|
|
|
|
- for (int i = 0; i < 6; i++)
|
|
|
|
- {
|
|
|
|
- Direction d = getDirectionFromIndex(i);
|
|
|
|
- Framework::Vec3<int> loc = location + getDirection(d);
|
|
|
|
- if (loc.x >= 0 && loc.x < CHUNK_SIZE && loc.y >= 0 && loc.y < CHUNK_SIZE && loc.z >= 0 && loc.z < WORLD_HEIGHT)
|
|
|
|
- {
|
|
|
|
- NetworkMessage* msg = new NetworkMessage();
|
|
|
|
- msg->addressChunck(this);
|
|
|
|
- char* message = new char[11];
|
|
|
|
- message[0] = 1;
|
|
|
|
- int index = ((loc.x * CHUNK_SIZE + loc.y) * WORLD_HEIGHT + loc.z) * 6;
|
|
|
|
- *(int*)(message + 1) = index / 6;
|
|
|
|
- memcpy(message + 5, lightData + index, 6);
|
|
|
|
- msg->setMessage(message, 11);
|
|
|
|
- notifyObservers(msg);
|
|
|
|
- }
|
|
|
|
- else if (loc.z >= 0 && loc.z < WORLD_HEIGHT && i < 4 && zNeighbours[i])
|
|
|
|
- {
|
|
|
|
- NetworkMessage* msg = new NetworkMessage();
|
|
|
|
- msg->addressChunck(zNeighbours[i]);
|
|
|
|
- char* message = new char[11];
|
|
|
|
- message[0] = 1;
|
|
|
|
- loc -= getDirection(d) * CHUNK_SIZE;
|
|
|
|
- int index = ((loc.x * CHUNK_SIZE + loc.y) * WORLD_HEIGHT + loc.z) * 6;
|
|
|
|
- *(int*)(message + 1) = index / 6;
|
|
|
|
- memcpy(message + 5, zNeighbours[i]->getLightData(loc), 6);
|
|
|
|
- msg->setMessage(message, 11);
|
|
|
|
- notifyObservers(msg);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- Game::INSTANCE->updateLightningWithoutWait(getDimensionId(), Vec3<int>(location.x + this->location.x - CHUNK_SIZE / 2, location.y + this->location.y - CHUNK_SIZE / 2, location.z));
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ int index
|
|
|
|
+ = (location.x * CHUNK_SIZE + location.y) * WORLD_HEIGHT + location.z;
|
|
|
|
+ assert(index < CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT);
|
|
|
|
+ bool wasLightSource
|
|
|
|
+ = StaticRegistry<BlockType>::INSTANCE.zElement(blockIds[index])
|
|
|
|
+ ->isLightSource();
|
|
|
|
+ bool isLightSource
|
|
|
|
+ = StaticRegistry<BlockType>::INSTANCE.zElement(type)->isLightSource();
|
|
|
|
+ if (blockIds[index] != (unsigned short)type)
|
|
|
|
+ {
|
|
|
|
+ blockIds[index] = (unsigned short)type;
|
|
|
|
+ for (int i = 0; i < 6; i++)
|
|
|
|
+ {
|
|
|
|
+ Direction d = getDirectionFromIndex(i);
|
|
|
|
+ Either<Block*, int> neighbor
|
|
|
|
+ = zBlockNeighbor(location + getDirection(d));
|
|
|
|
+ if (neighbor.isA())
|
|
|
|
+ ((Block*)neighbor)
|
|
|
|
+ ->setNeighbourType(getOppositeDirection(d), type);
|
|
|
|
+ }
|
|
|
|
+ if (isLightSource != wasLightSource)
|
|
|
|
+ {
|
|
|
|
+ if (isLightSource)
|
|
|
|
+ addLightSource(index);
|
|
|
|
+ else
|
|
|
|
+ removeLightSource(index);
|
|
|
|
+ }
|
|
|
|
+ if (added)
|
|
|
|
+ {
|
|
|
|
+ char* msg = new char[9];
|
|
|
|
+ msg[0] = 0; // set block
|
|
|
|
+ *(int*)(msg + 1) = index;
|
|
|
|
+ *(int*)(msg + 5) = type;
|
|
|
|
+ NetworkMessage* message = new NetworkMessage();
|
|
|
|
+ message->addressChunck(this);
|
|
|
|
+ message->setMessage(msg, 9);
|
|
|
|
+ notifyObservers(message);
|
|
|
|
+ for (int i = 0; i < 6; i++)
|
|
|
|
+ {
|
|
|
|
+ Direction d = getDirectionFromIndex(i);
|
|
|
|
+ Framework::Vec3<int> loc = location + getDirection(d);
|
|
|
|
+ if (loc.x >= 0 && loc.x < CHUNK_SIZE && loc.y >= 0
|
|
|
|
+ && loc.y < CHUNK_SIZE && loc.z >= 0 && loc.z < WORLD_HEIGHT)
|
|
|
|
+ {
|
|
|
|
+ NetworkMessage* msg = new NetworkMessage();
|
|
|
|
+ msg->addressChunck(this);
|
|
|
|
+ char* message = new char[11];
|
|
|
|
+ message[0] = 1;
|
|
|
|
+ int index
|
|
|
|
+ = ((loc.x * CHUNK_SIZE + loc.y) * WORLD_HEIGHT + loc.z)
|
|
|
|
+ * 6;
|
|
|
|
+ *(int*)(message + 1) = index / 6;
|
|
|
|
+ memcpy(message + 5, lightData + index, 6);
|
|
|
|
+ msg->setMessage(message, 11);
|
|
|
|
+ notifyObservers(msg);
|
|
|
|
+ }
|
|
|
|
+ else if (loc.z >= 0 && loc.z < WORLD_HEIGHT && i < 4
|
|
|
|
+ && zNeighbours[i])
|
|
|
|
+ {
|
|
|
|
+ NetworkMessage* msg = new NetworkMessage();
|
|
|
|
+ msg->addressChunck(zNeighbours[i]);
|
|
|
|
+ char* message = new char[11];
|
|
|
|
+ message[0] = 1;
|
|
|
|
+ loc -= getDirection(d) * CHUNK_SIZE;
|
|
|
|
+ int index
|
|
|
|
+ = ((loc.x * CHUNK_SIZE + loc.y) * WORLD_HEIGHT + loc.z)
|
|
|
|
+ * 6;
|
|
|
|
+ *(int*)(message + 1) = index / 6;
|
|
|
|
+ memcpy(message + 5, zNeighbours[i]->getLightData(loc), 6);
|
|
|
|
+ msg->setMessage(message, 11);
|
|
|
|
+ notifyObservers(msg);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ Game::INSTANCE->updateLightningWithoutWait(getDimensionId(),
|
|
|
|
+ Vec3<int>(location.x + this->location.x - CHUNK_SIZE / 2,
|
|
|
|
+ location.y + this->location.y - CHUNK_SIZE / 2,
|
|
|
|
+ location.z));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
void Chunk::setNeighbor(Direction dir, Chunk* zChunk)
|
|
void Chunk::setNeighbor(Direction dir, Chunk* zChunk)
|
|
{
|
|
{
|
|
- zNeighbours[getDirectionIndex(dir)] = zChunk;
|
|
|
|
- for (int i = 0; i < CHUNK_SIZE; i++)
|
|
|
|
- {
|
|
|
|
- for (int z = 0; z < WORLD_HEIGHT; z++)
|
|
|
|
- {
|
|
|
|
- if (dir == NORTH)
|
|
|
|
- {
|
|
|
|
- int index = i * CHUNK_SIZE * WORLD_HEIGHT + z;
|
|
|
|
- if (blocks[index])
|
|
|
|
- {
|
|
|
|
- int j = (i * CHUNK_SIZE + CHUNK_SIZE - 1) * WORLD_HEIGHT + z;
|
|
|
|
- if (zChunk && zChunk->blocks[j])
|
|
|
|
- blocks[index]->setNeighbour(NORTH, zChunk->blocks[j]);
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- blocks[index]->setNeighbour(NORTH, 0);
|
|
|
|
- blocks[index]->setNeighbourType(NORTH, zChunk ? zChunk->blockIds[j] : 0);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- else if (dir == EAST)
|
|
|
|
- {
|
|
|
|
- int index = ((CHUNK_SIZE - 1) * CHUNK_SIZE + i) * WORLD_HEIGHT + z;
|
|
|
|
- if (blocks[index])
|
|
|
|
- {
|
|
|
|
- int j = i * WORLD_HEIGHT + z;
|
|
|
|
- if (zChunk && zChunk->blocks[j])
|
|
|
|
- blocks[index]->setNeighbour(EAST, zChunk->blocks[j]);
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- blocks[index]->setNeighbour(EAST, 0);
|
|
|
|
- blocks[index]->setNeighbourType(EAST, zChunk ? zChunk->blockIds[j] : 0);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- else if (dir == SOUTH)
|
|
|
|
- {
|
|
|
|
- int index = (i * CHUNK_SIZE + CHUNK_SIZE - 1) * WORLD_HEIGHT + z;
|
|
|
|
- if (blocks[index])
|
|
|
|
- {
|
|
|
|
- int j = i * CHUNK_SIZE * WORLD_HEIGHT + z;
|
|
|
|
- if (zChunk && zChunk->blocks[j])
|
|
|
|
- blocks[index]->setNeighbour(SOUTH, zChunk->blocks[j]);
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- blocks[index]->setNeighbour(SOUTH, 0);
|
|
|
|
- blocks[index]->setNeighbourType(SOUTH, zChunk ? zChunk->blockIds[j] : 0);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- else if (dir == WEST)
|
|
|
|
- {
|
|
|
|
- int index = i * WORLD_HEIGHT + z;
|
|
|
|
- if (blocks[index])
|
|
|
|
- {
|
|
|
|
- int j = ((CHUNK_SIZE - 1) * CHUNK_SIZE + i) * WORLD_HEIGHT + z;
|
|
|
|
- if (zChunk && zChunk->blocks[j])
|
|
|
|
- blocks[index]->setNeighbour(WEST, zChunk->blocks[j]);
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- blocks[index]->setNeighbour(WEST, 0);
|
|
|
|
- blocks[index]->setNeighbourType(WEST, zChunk ? zChunk->blockIds[j] : 0);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ zNeighbours[getDirectionIndex(dir)] = zChunk;
|
|
|
|
+ for (int i = 0; i < CHUNK_SIZE; i++)
|
|
|
|
+ {
|
|
|
|
+ for (int z = 0; z < WORLD_HEIGHT; z++)
|
|
|
|
+ {
|
|
|
|
+ if (dir == NORTH)
|
|
|
|
+ {
|
|
|
|
+ int index = i * CHUNK_SIZE * WORLD_HEIGHT + z;
|
|
|
|
+ if (blocks[index])
|
|
|
|
+ {
|
|
|
|
+ int j
|
|
|
|
+ = (i * CHUNK_SIZE + CHUNK_SIZE - 1) * WORLD_HEIGHT + z;
|
|
|
|
+ if (zChunk && zChunk->blocks[j])
|
|
|
|
+ blocks[index]->setNeighbour(NORTH, zChunk->blocks[j]);
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ blocks[index]->setNeighbour(NORTH, 0);
|
|
|
|
+ blocks[index]->setNeighbourType(
|
|
|
|
+ NORTH, zChunk ? zChunk->blockIds[j] : 0);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else if (dir == EAST)
|
|
|
|
+ {
|
|
|
|
+ int index
|
|
|
|
+ = ((CHUNK_SIZE - 1) * CHUNK_SIZE + i) * WORLD_HEIGHT + z;
|
|
|
|
+ if (blocks[index])
|
|
|
|
+ {
|
|
|
|
+ int j = i * WORLD_HEIGHT + z;
|
|
|
|
+ if (zChunk && zChunk->blocks[j])
|
|
|
|
+ blocks[index]->setNeighbour(EAST, zChunk->blocks[j]);
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ blocks[index]->setNeighbour(EAST, 0);
|
|
|
|
+ blocks[index]->setNeighbourType(
|
|
|
|
+ EAST, zChunk ? zChunk->blockIds[j] : 0);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else if (dir == SOUTH)
|
|
|
|
+ {
|
|
|
|
+ int index
|
|
|
|
+ = (i * CHUNK_SIZE + CHUNK_SIZE - 1) * WORLD_HEIGHT + z;
|
|
|
|
+ if (blocks[index])
|
|
|
|
+ {
|
|
|
|
+ int j = i * CHUNK_SIZE * WORLD_HEIGHT + z;
|
|
|
|
+ if (zChunk && zChunk->blocks[j])
|
|
|
|
+ blocks[index]->setNeighbour(SOUTH, zChunk->blocks[j]);
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ blocks[index]->setNeighbour(SOUTH, 0);
|
|
|
|
+ blocks[index]->setNeighbourType(
|
|
|
|
+ SOUTH, zChunk ? zChunk->blockIds[j] : 0);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else if (dir == WEST)
|
|
|
|
+ {
|
|
|
|
+ int index = i * WORLD_HEIGHT + z;
|
|
|
|
+ if (blocks[index])
|
|
|
|
+ {
|
|
|
|
+ int j = ((CHUNK_SIZE - 1) * CHUNK_SIZE + i) * WORLD_HEIGHT
|
|
|
|
+ + z;
|
|
|
|
+ if (zChunk && zChunk->blocks[j])
|
|
|
|
+ blocks[index]->setNeighbour(WEST, zChunk->blocks[j]);
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ blocks[index]->setNeighbour(WEST, 0);
|
|
|
|
+ blocks[index]->setNeighbourType(
|
|
|
|
+ WEST, zChunk ? zChunk->blockIds[j] : 0);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
void Chunk::load(Framework::StreamReader* zReader)
|
|
void Chunk::load(Framework::StreamReader* zReader)
|
|
{
|
|
{
|
|
- for (int index = 0; index < WORLD_HEIGHT * CHUNK_SIZE * CHUNK_SIZE; index++)
|
|
|
|
- {
|
|
|
|
- unsigned short blockType;
|
|
|
|
- zReader->lese((char*)&blockType, 2);
|
|
|
|
- if (blockType)
|
|
|
|
- {
|
|
|
|
- Framework::Vec3<int> pos = Framework::Vec3<int>((index / WORLD_HEIGHT) / CHUNK_SIZE, (index / WORLD_HEIGHT) % CHUNK_SIZE, index % WORLD_HEIGHT);
|
|
|
|
- bool d;
|
|
|
|
- zReader->lese((char*)&d, 1);
|
|
|
|
- if (d)
|
|
|
|
- {
|
|
|
|
- putBlockAt(pos, StaticRegistry<BlockType>::INSTANCE.zElement(blockType)->loadBlock(Framework::Vec3<int>(pos.x + location.x - CHUNK_SIZE / 2, pos.y + location.y - CHUNK_SIZE / 2, pos.z), zReader, dimensionId));
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- putBlockTypeAt(pos, blockType);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- initializeLightning();
|
|
|
|
|
|
+ for (int index = 0; index < WORLD_HEIGHT * CHUNK_SIZE * CHUNK_SIZE; index++)
|
|
|
|
+ {
|
|
|
|
+ unsigned short blockType;
|
|
|
|
+ zReader->lese((char*)&blockType, 2);
|
|
|
|
+ if (blockType)
|
|
|
|
+ {
|
|
|
|
+ Framework::Vec3<int> pos
|
|
|
|
+ = Framework::Vec3<int>((index / WORLD_HEIGHT) / CHUNK_SIZE,
|
|
|
|
+ (index / WORLD_HEIGHT) % CHUNK_SIZE,
|
|
|
|
+ index % WORLD_HEIGHT);
|
|
|
|
+ bool d;
|
|
|
|
+ zReader->lese((char*)&d, 1);
|
|
|
|
+ if (d)
|
|
|
|
+ {
|
|
|
|
+ putBlockAt(pos,
|
|
|
|
+ StaticRegistry<BlockType>::INSTANCE.zElement(blockType)
|
|
|
|
+ ->loadBlock(Framework::Vec3<int>(
|
|
|
|
+ pos.x + location.x - CHUNK_SIZE / 2,
|
|
|
|
+ pos.y + location.y - CHUNK_SIZE / 2,
|
|
|
|
+ pos.z),
|
|
|
|
+ zReader,
|
|
|
|
+ dimensionId));
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ putBlockTypeAt(pos, blockType);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ initializeLightning();
|
|
}
|
|
}
|
|
|
|
|
|
void Chunk::save(Framework::StreamWriter* zWriter)
|
|
void Chunk::save(Framework::StreamWriter* zWriter)
|
|
{
|
|
{
|
|
- for (int index = 0; index < WORLD_HEIGHT * CHUNK_SIZE * CHUNK_SIZE; index++)
|
|
|
|
- {
|
|
|
|
- unsigned short blockType = blocks[index] ? (unsigned short)blocks[index]->zBlockType()->getId() : blockIds[index];
|
|
|
|
- zWriter->schreibe((char*)&blockType, 2);
|
|
|
|
- if (blockType)
|
|
|
|
- {
|
|
|
|
- if (blocks[index])
|
|
|
|
- {
|
|
|
|
- bool d = 1;
|
|
|
|
- zWriter->schreibe((char*)&d, 1);
|
|
|
|
- StaticRegistry<BlockType>::INSTANCE.zElement(blockType)->saveBlock(blocks[index], zWriter);
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- bool d = 0;
|
|
|
|
- zWriter->schreibe((char*)&d, 1);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ for (int index = 0; index < WORLD_HEIGHT * CHUNK_SIZE * CHUNK_SIZE; index++)
|
|
|
|
+ {
|
|
|
|
+ unsigned short blockType
|
|
|
|
+ = blocks[index]
|
|
|
|
+ ? (unsigned short)blocks[index]->zBlockType()->getId()
|
|
|
|
+ : blockIds[index];
|
|
|
|
+ zWriter->schreibe((char*)&blockType, 2);
|
|
|
|
+ if (blockType)
|
|
|
|
+ {
|
|
|
|
+ if (blocks[index])
|
|
|
|
+ {
|
|
|
|
+ bool d = 1;
|
|
|
|
+ zWriter->schreibe((char*)&d, 1);
|
|
|
|
+ StaticRegistry<BlockType>::INSTANCE.zElement(blockType)
|
|
|
|
+ ->saveBlock(blocks[index], zWriter);
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ bool d = 0;
|
|
|
|
+ zWriter->schreibe((char*)&d, 1);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
void Chunk::sendToClient(Framework::StreamWriter* zWriter)
|
|
void Chunk::sendToClient(Framework::StreamWriter* zWriter)
|
|
{
|
|
{
|
|
- for (int x = 0; x < CHUNK_SIZE; x++)
|
|
|
|
- {
|
|
|
|
- for (int y = 0; y < CHUNK_SIZE; y++)
|
|
|
|
- {
|
|
|
|
- for (int z = 0; z < WORLD_HEIGHT; z++)
|
|
|
|
- {
|
|
|
|
- int index = (x * CHUNK_SIZE + y) * WORLD_HEIGHT + z;
|
|
|
|
- unsigned short blockType = blocks[index] ? (unsigned short)blocks[index]->zBlockType()->getId() : blockIds[index];
|
|
|
|
- if (blockType)
|
|
|
|
- {
|
|
|
|
- bool visible = 0;
|
|
|
|
- if (!visible)
|
|
|
|
- {
|
|
|
|
- if (!blocks[index])
|
|
|
|
- {
|
|
|
|
- if (CONST_BLOCK(0, blockIds[index])->isTransparent() || CONST_BLOCK(0, blockIds[index])->isPassable())
|
|
|
|
- visible = 1;
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- for (int d = 0; d < 6 && !visible; d++)
|
|
|
|
- {
|
|
|
|
- auto n = zBlockNeighbor(getDirection((Directions)getDirectionFromIndex(d)) + Framework::Vec3<int>(x, y, z));
|
|
|
|
- if (n.isA() && (((Block*)n)->isPassable() || ((Block*)n)->isTransparent()))
|
|
|
|
- visible = 1;
|
|
|
|
- if (n.isB() && (CONST_BLOCK(0, n)->isTransparent() || CONST_BLOCK(0, n)->isPassable()))
|
|
|
|
- visible = 1;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- visible = blocks[index]->isVisible();
|
|
|
|
- }
|
|
|
|
- if (visible && (blocks[index] || blockType != BlockTypeEnum::AIR))
|
|
|
|
- {
|
|
|
|
- zWriter->schreibe((char*)&blockType, 2);
|
|
|
|
- zWriter->schreibe((char*)&index, 4);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- unsigned short end = 0;
|
|
|
|
- zWriter->schreibe((char*)&end, 2);
|
|
|
|
|
|
+ for (int x = 0; x < CHUNK_SIZE; x++)
|
|
|
|
+ {
|
|
|
|
+ for (int y = 0; y < CHUNK_SIZE; y++)
|
|
|
|
+ {
|
|
|
|
+ for (int z = 0; z < WORLD_HEIGHT; z++)
|
|
|
|
+ {
|
|
|
|
+ int index = (x * CHUNK_SIZE + y) * WORLD_HEIGHT + z;
|
|
|
|
+ unsigned short blockType
|
|
|
|
+ = blocks[index]
|
|
|
|
+ ? (unsigned short)blocks[index]->zBlockType()->getId()
|
|
|
|
+ : blockIds[index];
|
|
|
|
+ if (blockType)
|
|
|
|
+ {
|
|
|
|
+ bool visible = 0;
|
|
|
|
+ if (!visible)
|
|
|
|
+ {
|
|
|
|
+ if (!blocks[index])
|
|
|
|
+ {
|
|
|
|
+ if (CONST_BLOCK(0, blockIds[index])->isTransparent()
|
|
|
|
+ || CONST_BLOCK(0, blockIds[index])
|
|
|
|
+ ->isPassable())
|
|
|
|
+ visible = 1;
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ for (int d = 0; d < 6 && !visible; d++)
|
|
|
|
+ {
|
|
|
|
+ auto n = zBlockNeighbor(
|
|
|
|
+ getDirection((
|
|
|
|
+ Directions)getDirectionFromIndex(d))
|
|
|
|
+ + Framework::Vec3<int>(x, y, z));
|
|
|
|
+ if (n.isA()
|
|
|
|
+ && (((Block*)n)->isPassable()
|
|
|
|
+ || ((Block*)n)->isTransparent()))
|
|
|
|
+ visible = 1;
|
|
|
|
+ if (n.isB()
|
|
|
|
+ && (CONST_BLOCK(0, n)->isTransparent()
|
|
|
|
+ || CONST_BLOCK(0, n)->isPassable()))
|
|
|
|
+ visible = 1;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ visible = blocks[index]->isVisible();
|
|
|
|
+ }
|
|
|
|
+ if (visible
|
|
|
|
+ && (blocks[index] || blockType != BlockTypeEnum::AIR))
|
|
|
|
+ {
|
|
|
|
+ zWriter->schreibe((char*)&blockType, 2);
|
|
|
|
+ zWriter->schreibe((char*)&index, 4);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ unsigned short end = 0;
|
|
|
|
+ zWriter->schreibe((char*)&end, 2);
|
|
}
|
|
}
|
|
|
|
|
|
void Chunk::removeUnusedBlocks()
|
|
void Chunk::removeUnusedBlocks()
|
|
{
|
|
{
|
|
- for (int i = 0; i < CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT; i++)
|
|
|
|
- {
|
|
|
|
- if (!blocks[i] && blockIds[i])
|
|
|
|
- {
|
|
|
|
- int x = (i / WORLD_HEIGHT) / CHUNK_SIZE;
|
|
|
|
- int y = (i / WORLD_HEIGHT) % CHUNK_SIZE;
|
|
|
|
- int z = i % WORLD_HEIGHT;
|
|
|
|
- bool visible = 0;
|
|
|
|
- if (CONST_BLOCK(0, blockIds[i])->isTransparent() || CONST_BLOCK(0, blockIds[i])->isPassable())
|
|
|
|
- visible = 1;
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- for (int d = 0; d < 6 && !visible; d++)
|
|
|
|
- {
|
|
|
|
- auto n = zBlockNeighbor(getDirection((Directions)getDirectionFromIndex(d)) + Framework::Vec3<int>(x, y, z));
|
|
|
|
- if (n.isA() && (((Block*)n)->isPassable() || ((Block*)n)->isTransparent()))
|
|
|
|
- visible = 1;
|
|
|
|
- if (n.isB() && (CONST_BLOCK(0, n)->isTransparent() || CONST_BLOCK(0, n)->isPassable()))
|
|
|
|
- visible = 1;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- if (!visible)
|
|
|
|
- {
|
|
|
|
- putBlockAt({ x,y,z }, 0);
|
|
|
|
- putBlockTypeAt({ x, y, z }, BlockTypeEnum::NO_BLOCK);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- int count = 0;
|
|
|
|
- for (int i = 0; i < CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT; i++)
|
|
|
|
- {
|
|
|
|
- if (blockIds[i] && blockIds[i] != BlockTypeEnum::AIR)
|
|
|
|
- count++;
|
|
|
|
- }
|
|
|
|
- std::cout << "chunk " << location.x << ", " << location.y << " was generated with " << count << " blocks.\n";
|
|
|
|
|
|
+ for (int i = 0; i < CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT; i++)
|
|
|
|
+ {
|
|
|
|
+ if (!blocks[i] && blockIds[i])
|
|
|
|
+ {
|
|
|
|
+ int x = (i / WORLD_HEIGHT) / CHUNK_SIZE;
|
|
|
|
+ int y = (i / WORLD_HEIGHT) % CHUNK_SIZE;
|
|
|
|
+ int z = i % WORLD_HEIGHT;
|
|
|
|
+ bool visible = 0;
|
|
|
|
+ if (CONST_BLOCK(0, blockIds[i])->isTransparent()
|
|
|
|
+ || CONST_BLOCK(0, blockIds[i])->isPassable())
|
|
|
|
+ visible = 1;
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ for (int d = 0; d < 6 && !visible; d++)
|
|
|
|
+ {
|
|
|
|
+ auto n = zBlockNeighbor(
|
|
|
|
+ getDirection((Directions)getDirectionFromIndex(d))
|
|
|
|
+ + Framework::Vec3<int>(x, y, z));
|
|
|
|
+ if (n.isA()
|
|
|
|
+ && (((Block*)n)->isPassable()
|
|
|
|
+ || ((Block*)n)->isTransparent()))
|
|
|
|
+ visible = 1;
|
|
|
|
+ if (n.isB()
|
|
|
|
+ && (CONST_BLOCK(0, n)->isTransparent()
|
|
|
|
+ || CONST_BLOCK(0, n)->isPassable()))
|
|
|
|
+ visible = 1;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (!visible)
|
|
|
|
+ {
|
|
|
|
+ putBlockAt({x, y, z}, 0);
|
|
|
|
+ putBlockTypeAt({x, y, z}, BlockTypeEnum::NO_BLOCK);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ int count = 0;
|
|
|
|
+ for (int i = 0; i < CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT; i++)
|
|
|
|
+ {
|
|
|
|
+ if (blockIds[i] && blockIds[i] != BlockTypeEnum::AIR) count++;
|
|
|
|
+ }
|
|
|
|
+ std::cout << "chunk " << location.x << ", " << location.y
|
|
|
|
+ << " was generated with " << count << " blocks.\n";
|
|
}
|
|
}
|
|
|
|
|
|
int Chunk::getDimensionId() const
|
|
int Chunk::getDimensionId() const
|
|
{
|
|
{
|
|
- return dimensionId;
|
|
|
|
|
|
+ return dimensionId;
|
|
}
|
|
}
|
|
|
|
|
|
void Chunk::onLoaded()
|
|
void Chunk::onLoaded()
|
|
{
|
|
{
|
|
- for (int i = 0; i < CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT; i++)
|
|
|
|
- {
|
|
|
|
- if (blocks[i])
|
|
|
|
- blocks[i]->onLoaded();
|
|
|
|
- }
|
|
|
|
- currentlyLoading = 0;
|
|
|
|
|
|
+ for (int i = 0; i < CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT; i++)
|
|
|
|
+ {
|
|
|
|
+ if (blocks[i]) blocks[i]->onLoaded();
|
|
|
|
+ }
|
|
|
|
+ currentlyLoading = 0;
|
|
}
|
|
}
|
|
|
|
|
|
void Chunk::onUnloaded()
|
|
void Chunk::onUnloaded()
|
|
{
|
|
{
|
|
- for (int i = 0; i < CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT; i++)
|
|
|
|
- {
|
|
|
|
- if (blocks[i])
|
|
|
|
- blocks[i]->onUnloaded();
|
|
|
|
- }
|
|
|
|
|
|
+ for (int i = 0; i < CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT; i++)
|
|
|
|
+ {
|
|
|
|
+ if (blocks[i]) blocks[i]->onUnloaded();
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
Framework::Punkt Chunk::getCenter() const
|
|
Framework::Punkt Chunk::getCenter() const
|
|
{
|
|
{
|
|
- return location;
|
|
|
|
|
|
+ return location;
|
|
}
|
|
}
|
|
|
|
|
|
Framework::Vec3<int> Chunk::getMin() const
|
|
Framework::Vec3<int> Chunk::getMin() const
|
|
{
|
|
{
|
|
- return { location.x - CHUNK_SIZE / 2, location.y - CHUNK_SIZE / 2, 0 };
|
|
|
|
|
|
+ return {location.x - CHUNK_SIZE / 2, location.y - CHUNK_SIZE / 2, 0};
|
|
}
|
|
}
|
|
|
|
|
|
Framework::Vec3<int> Chunk::getMax() const
|
|
Framework::Vec3<int> Chunk::getMax() const
|
|
{
|
|
{
|
|
- return { location.x + CHUNK_SIZE / 2, location.y + CHUNK_SIZE / 2, WORLD_HEIGHT };
|
|
|
|
|
|
+ return {
|
|
|
|
+ location.x + CHUNK_SIZE / 2, location.y + CHUNK_SIZE / 2, WORLD_HEIGHT};
|
|
}
|
|
}
|
|
|
|
|
|
void Chunk::prepareRemove()
|
|
void Chunk::prepareRemove()
|
|
{
|
|
{
|
|
- added = 0;
|
|
|
|
- for (int i = 0; i < 4; i++)
|
|
|
|
- {
|
|
|
|
- if (zNeighbours[i])
|
|
|
|
- {
|
|
|
|
- zNeighbours[i]->setNeighbor(getOppositeDirection(getDirectionFromIndex(i)), 0);
|
|
|
|
- zNeighbours[i] = 0;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ added = 0;
|
|
|
|
+ for (int i = 0; i < 4; i++)
|
|
|
|
+ {
|
|
|
|
+ if (zNeighbours[i])
|
|
|
|
+ {
|
|
|
|
+ zNeighbours[i]->setNeighbor(
|
|
|
|
+ getOppositeDirection(getDirectionFromIndex(i)), 0);
|
|
|
|
+ zNeighbours[i] = 0;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
void Chunk::setAdded()
|
|
void Chunk::setAdded()
|
|
{
|
|
{
|
|
- added = 1;
|
|
|
|
|
|
+ added = 1;
|
|
}
|
|
}
|
|
|
|
|
|
bool Chunk::hasObservers() const
|
|
bool Chunk::hasObservers() const
|
|
{
|
|
{
|
|
- return observers.getEintragAnzahl() > 0 || currentlyLoading;
|
|
|
|
|
|
+ return observers.getEintragAnzahl() > 0 || currentlyLoading;
|
|
}
|
|
}
|
|
|
|
|
|
unsigned char* Chunk::getLightData(Framework::Vec3<int> location) const
|
|
unsigned char* Chunk::getLightData(Framework::Vec3<int> location) const
|
|
{
|
|
{
|
|
- int index = ((location.x * CHUNK_SIZE + location.y) * WORLD_HEIGHT + location.z) * 6;
|
|
|
|
- assert(index < CHUNK_SIZE* CHUNK_SIZE* WORLD_HEIGHT);
|
|
|
|
- return lightData + index;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-void Chunk::setLightData(Framework::Vec3<int> location, unsigned char* data, bool foreground)
|
|
|
|
-{
|
|
|
|
- int index = ((location.x * CHUNK_SIZE + location.y) * WORLD_HEIGHT + location.z) * 6;
|
|
|
|
- memcpy(lightData + index, data, 6);
|
|
|
|
- // check if neighbor is a visible block and send update to clients
|
|
|
|
- bool needSend = 0;
|
|
|
|
- for (int i = 0; i < 6; i++)
|
|
|
|
- {
|
|
|
|
- Vec3<int> pos = location + getDirection(getDirectionFromIndex(i));
|
|
|
|
- if (pos.z >= 0 && pos.z < WORLD_HEIGHT)
|
|
|
|
- {
|
|
|
|
- if (pos.x >= 0 && pos.x < CHUNK_SIZE && pos.y >= 0 && pos.y < CHUNK_SIZE)
|
|
|
|
- {
|
|
|
|
- int bi = (pos.x * CHUNK_SIZE + pos.y) * WORLD_HEIGHT + pos.z;
|
|
|
|
- int type = blockIds[bi];
|
|
|
|
- needSend |= type != BlockTypeEnum::NO_BLOCK && type != BlockTypeEnum::AIR;
|
|
|
|
- if (needSend)
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- needSend = 1; // TODO: check if the block is visible
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- if (needSend)
|
|
|
|
- {
|
|
|
|
- NetworkMessage* msg = new NetworkMessage();
|
|
|
|
- msg->addressChunck(this);
|
|
|
|
- char* message = new char[11];
|
|
|
|
- message[0] = 1;
|
|
|
|
- *(int*)(message + 1) = index / 6;
|
|
|
|
- memcpy(message + 5, data, 6);
|
|
|
|
- msg->setMessage(message, 11);
|
|
|
|
- if (!foreground)
|
|
|
|
- msg->setUseBackground();
|
|
|
|
- notifyObservers(msg);
|
|
|
|
- }
|
|
|
|
|
|
+ int index
|
|
|
|
+ = ((location.x * CHUNK_SIZE + location.y) * WORLD_HEIGHT + location.z)
|
|
|
|
+ * 6;
|
|
|
|
+ assert(index < CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT);
|
|
|
|
+ return lightData + index;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void Chunk::setLightData(
|
|
|
|
+ Framework::Vec3<int> location, unsigned char* data, bool foreground)
|
|
|
|
+{
|
|
|
|
+ int index
|
|
|
|
+ = ((location.x * CHUNK_SIZE + location.y) * WORLD_HEIGHT + location.z)
|
|
|
|
+ * 6;
|
|
|
|
+ memcpy(lightData + index, data, 6);
|
|
|
|
+ // check if neighbor is a visible block and send update to clients
|
|
|
|
+ bool needSend = 0;
|
|
|
|
+ for (int i = 0; i < 6; i++)
|
|
|
|
+ {
|
|
|
|
+ Vec3<int> pos = location + getDirection(getDirectionFromIndex(i));
|
|
|
|
+ if (pos.z >= 0 && pos.z < WORLD_HEIGHT)
|
|
|
|
+ {
|
|
|
|
+ if (pos.x >= 0 && pos.x < CHUNK_SIZE && pos.y >= 0
|
|
|
|
+ && pos.y < CHUNK_SIZE)
|
|
|
|
+ {
|
|
|
|
+ int bi = (pos.x * CHUNK_SIZE + pos.y) * WORLD_HEIGHT + pos.z;
|
|
|
|
+ int type = blockIds[bi];
|
|
|
|
+ needSend |= type != BlockTypeEnum::NO_BLOCK
|
|
|
|
+ && type != BlockTypeEnum::AIR;
|
|
|
|
+ if (needSend) break;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ needSend = 1; // TODO: check if the block is visible
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (needSend)
|
|
|
|
+ {
|
|
|
|
+ NetworkMessage* msg = new NetworkMessage();
|
|
|
|
+ msg->addressChunck(this);
|
|
|
|
+ char* message = new char[11];
|
|
|
|
+ message[0] = 1;
|
|
|
|
+ *(int*)(message + 1) = index / 6;
|
|
|
|
+ memcpy(message + 5, data, 6);
|
|
|
|
+ msg->setMessage(message, 11);
|
|
|
|
+ if (!foreground) msg->setUseBackground();
|
|
|
|
+ notifyObservers(msg);
|
|
|
|
+ }
|
|
}
|
|
}
|