|
@@ -112,7 +112,9 @@ void Chunk::sendLightToClient(Framework::StreamWriter* zWriter)
|
|
|
+ pos.z;
|
|
|
int type = blockIds[bi];
|
|
|
needSend |= type != BlockTypeEnum::NO_BLOCK
|
|
|
- && type != BlockTypeEnum::AIR;
|
|
|
+ && StaticRegistry<BlockType>::INSTANCE
|
|
|
+ .zElement(type)
|
|
|
+ ->doesNeedClientInstance();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
@@ -129,8 +131,10 @@ void Chunk::sendLightToClient(Framework::StreamWriter* zWriter)
|
|
|
* WORLD_HEIGHT
|
|
|
+ (pos.z - offset.z);
|
|
|
int type = zNeighbours[i]->blockIds[bi];
|
|
|
- needSend |= type != BlockTypeEnum::NO_BLOCK
|
|
|
- && type != BlockTypeEnum::AIR;
|
|
|
+ needSend
|
|
|
+ |= StaticRegistry<BlockType>::INSTANCE
|
|
|
+ .zElement(type)
|
|
|
+ ->doesNeedClientInstance();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -195,6 +199,62 @@ void Chunk::sendLightToClient(Framework::StreamWriter* zWriter)
|
|
|
zWriter->schreibe((char*)&end, 4);
|
|
|
}
|
|
|
|
|
|
+bool Chunk::isVisible(int index) const
|
|
|
+{
|
|
|
+ if (!blocks[index])
|
|
|
+ {
|
|
|
+ unsigned short blockType
|
|
|
+ = blocks[index]
|
|
|
+ ? (unsigned short)blocks[index]->zBlockType()->getId()
|
|
|
+ : blockIds[index];
|
|
|
+ if (blockType)
|
|
|
+ {
|
|
|
+ if (CONST_BLOCK(0, blockIds[index])->isTransparent()
|
|
|
+ || CONST_BLOCK(0, blockIds[index])->isPassable())
|
|
|
+ return 1;
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Vec3<int> indexPos = {(index / WORLD_HEIGHT) / CHUNK_SIZE,
|
|
|
+ (index / WORLD_HEIGHT) % CHUNK_SIZE,
|
|
|
+ index % WORLD_HEIGHT};
|
|
|
+ for (int d = 0; d < 6; d++)
|
|
|
+ {
|
|
|
+ Either<Block*, int> n = BlockTypeEnum::NO_BLOCK;
|
|
|
+ Vec3<int> pos
|
|
|
+ = getDirection((Directions)getDirectionFromIndex(d))
|
|
|
+ + indexPos;
|
|
|
+ if (pos.x >= 0 && pos.x < CHUNK_SIZE && pos.y >= 0
|
|
|
+ && pos.y < CHUNK_SIZE && pos.z >= 0
|
|
|
+ && pos.z < WORLD_HEIGHT)
|
|
|
+ {
|
|
|
+ n = zBlockAt(pos);
|
|
|
+ }
|
|
|
+ else if (pos.z >= 0 && pos.z < WORLD_HEIGHT && d < 4
|
|
|
+ && zNeighbours[d])
|
|
|
+ {
|
|
|
+ if (pos.x < 0) pos.x += CHUNK_SIZE;
|
|
|
+ if (pos.x >= CHUNK_SIZE) pos.x -= CHUNK_SIZE;
|
|
|
+ if (pos.y < 0) pos.y += CHUNK_SIZE;
|
|
|
+ if (pos.y >= CHUNK_SIZE) pos.y -= CHUNK_SIZE;
|
|
|
+ n = zNeighbours[d]->zBlockAt(pos);
|
|
|
+ }
|
|
|
+ if (n.isA()
|
|
|
+ && (((Block*)n)->isPassable()
|
|
|
+ || ((Block*)n)->isTransparent()))
|
|
|
+ return 1;
|
|
|
+ if (n.isB()
|
|
|
+ && (CONST_BLOCK(0, n)->isTransparent()
|
|
|
+ || CONST_BLOCK(0, n)->isPassable()))
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ return blocks[index]->isVisible();
|
|
|
+}
|
|
|
+
|
|
|
void Chunk::broadcastLightData(int index, bool foreground)
|
|
|
{
|
|
|
int x = (index / WORLD_HEIGHT) / CHUNK_SIZE;
|
|
@@ -261,9 +321,8 @@ void Chunk::addObserver(Entity* zEntity, DoLaterHandler& laterHandler)
|
|
|
if (observer->getEntityId() == zEntity->getId()) return;
|
|
|
}
|
|
|
int id = zEntity->getId();
|
|
|
- InformationObserver* observer = new InformationObserver(id);
|
|
|
- observers.add(observer);
|
|
|
- laterHandler.addTodo([this, id, observer]() {
|
|
|
+ observers.add(new InformationObserver(id));
|
|
|
+ laterHandler.addTodo([this, id]() {
|
|
|
InMemoryBuffer buffer;
|
|
|
buffer.schreibe("\4", 1);
|
|
|
buffer.schreibe((char*)&location.x, 4);
|
|
@@ -280,17 +339,6 @@ void Chunk::addObserver(Entity* zEntity, DoLaterHandler& laterHandler)
|
|
|
Entity* e = Game::INSTANCE->zEntity(id);
|
|
|
if (e)
|
|
|
{
|
|
|
- Punkt p = location;
|
|
|
- int dimId = dimensionId;
|
|
|
- msg->setOnAfterSend([this, p, dimId, observer]() {
|
|
|
- // check if chunk is still loaded
|
|
|
- if (Game::INSTANCE->zDimension(dimId)
|
|
|
- && Game::INSTANCE->zDimension(dimId)->zChunk(p) == this)
|
|
|
- {
|
|
|
- // send all waiting messages to the observer
|
|
|
- observer->setReady();
|
|
|
- }
|
|
|
- });
|
|
|
Game::INSTANCE->sendMessage(msg, e);
|
|
|
}
|
|
|
else
|
|
@@ -328,6 +376,15 @@ void Chunk::api(Framework::StreamReader* zRequest,
|
|
|
// unsubscribe
|
|
|
removeObserver(zSource);
|
|
|
break;
|
|
|
+ case 2:
|
|
|
+ // observer ready
|
|
|
+ for (InformationObserver* observer : observers)
|
|
|
+ {
|
|
|
+ if (observer->getEntityId() == zSource->getId())
|
|
|
+ {
|
|
|
+ observer->setReady();
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -423,6 +480,15 @@ const Block* Chunk::zBlockConst(Framework::Vec3<int> location) const
|
|
|
return StaticRegistry<BlockType>::INSTANCE.zElement(b.getB())->zDefault();
|
|
|
}
|
|
|
|
|
|
+const Block* Chunk::zBlockConst(int index) const
|
|
|
+{
|
|
|
+ if (blocks[index])
|
|
|
+ return blocks[index];
|
|
|
+ else
|
|
|
+ return StaticRegistry<BlockType>::INSTANCE.zElement(blockIds[index])
|
|
|
+ ->zDefault();
|
|
|
+}
|
|
|
+
|
|
|
void Chunk::instantiateBlock(Framework::Vec3<int> location)
|
|
|
{
|
|
|
auto b = zBlockAt(location);
|
|
@@ -630,7 +696,9 @@ void Chunk::sendBlockInfo(Framework::Vec3<int> location)
|
|
|
|
|
|
void Chunk::setNeighbor(Direction dir, Chunk* zChunk)
|
|
|
{
|
|
|
- zNeighbours[getDirectionIndex(dir)] = zChunk;
|
|
|
+ int dirIndex = getDirectionIndex(dir);
|
|
|
+ Chunk* old = zNeighbours[dirIndex];
|
|
|
+ zNeighbours[dirIndex] = zChunk;
|
|
|
for (int i = 0; i < CHUNK_SIZE; i++)
|
|
|
{
|
|
|
for (int z = 0; z < WORLD_HEIGHT; z++)
|
|
@@ -657,8 +725,10 @@ void Chunk::setNeighbor(Direction dir, Chunk* zChunk)
|
|
|
index = i * WORLD_HEIGHT + z;
|
|
|
j = ((CHUNK_SIZE - 1) * CHUNK_SIZE + i) * WORLD_HEIGHT + z;
|
|
|
}
|
|
|
+ bool needsTransmission = 0;
|
|
|
if (blocks[index])
|
|
|
{
|
|
|
+ bool visible = blocks[index]->isVisible();
|
|
|
if (zChunk && zChunk->blocks[j])
|
|
|
blocks[index]->setNeighbour(dir, zChunk->blocks[j]);
|
|
|
else
|
|
@@ -667,12 +737,26 @@ void Chunk::setNeighbor(Direction dir, Chunk* zChunk)
|
|
|
blocks[index]->setNeighbourType(
|
|
|
dir, zChunk ? zChunk->blockIds[j] : 0);
|
|
|
}
|
|
|
+ if (!visible && blocks[index]->isVisible())
|
|
|
+ {
|
|
|
+ needsTransmission = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ zNeighbours[dirIndex] = old;
|
|
|
+ bool visible = isVisible(index);
|
|
|
+ zNeighbours[dirIndex] = zChunk;
|
|
|
+ if (!visible && isVisible(index))
|
|
|
+ {
|
|
|
+ needsTransmission = 1;
|
|
|
+ }
|
|
|
}
|
|
|
if (zChunk)
|
|
|
{
|
|
|
if (!blocks[index])
|
|
|
{
|
|
|
- if (zChunk->blockIds[j] == BlockTypeEnum::AIR
|
|
|
+ if (zChunk->zBlockConst(j)->isTransparent()
|
|
|
&& !blockIds[index])
|
|
|
{
|
|
|
generateBlock(
|
|
@@ -681,11 +765,12 @@ void Chunk::setNeighbor(Direction dir, Chunk* zChunk)
|
|
|
index % WORLD_HEIGHT));
|
|
|
}
|
|
|
}
|
|
|
- if (blockIds[index] != BlockTypeEnum::AIR
|
|
|
- && blockIds[index] != BlockTypeEnum::NO_BLOCK)
|
|
|
- {
|
|
|
- zChunk->broadcastLightData(j, true);
|
|
|
- }
|
|
|
+ }
|
|
|
+ if (needsTransmission && added)
|
|
|
+ {
|
|
|
+ sendBlockInfo(Vec3<int>((index / WORLD_HEIGHT) / CHUNK_SIZE,
|
|
|
+ (index / WORLD_HEIGHT) % CHUNK_SIZE,
|
|
|
+ index % WORLD_HEIGHT));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -761,56 +846,18 @@ void Chunk::sendToClient(Framework::StreamWriter* zWriter)
|
|
|
for (int z = 0; z < WORLD_HEIGHT; z++)
|
|
|
{
|
|
|
int index = Chunk::index({x, y, z});
|
|
|
- unsigned short blockType
|
|
|
- = blocks[index]
|
|
|
- ? (unsigned short)blocks[index]->zBlockType()->getId()
|
|
|
- : blockIds[index];
|
|
|
- if (blockType)
|
|
|
+ if (isVisible(index)
|
|
|
+ && StaticRegistry<BlockType>::INSTANCE
|
|
|
+ .zElement(blockIds[index])
|
|
|
+ ->doesNeedClientInstance())
|
|
|
{
|
|
|
- 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++)
|
|
|
- {
|
|
|
- Vec3<int> pos
|
|
|
- = getDirection(
|
|
|
- (Directions)getDirectionFromIndex(
|
|
|
- d))
|
|
|
- + Framework::Vec3<int>(x, y, z);
|
|
|
- auto n = zBlockNeighbor(pos);
|
|
|
- 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 (pos.x < 0 || pos.y < 0 || pos.z < 0
|
|
|
- || pos.x >= CHUNK_SIZE
|
|
|
- || pos.y >= CHUNK_SIZE
|
|
|
- || pos.z >= WORLD_HEIGHT)
|
|
|
- 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 blockType = blocks[index]
|
|
|
+ ? (unsigned short)blocks[index]
|
|
|
+ ->zBlockType()
|
|
|
+ ->getId()
|
|
|
+ : blockIds[index];
|
|
|
+ zWriter->schreibe((char*)&blockType, 2);
|
|
|
+ zWriter->schreibe((char*)&index, 4);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -859,7 +906,9 @@ void Chunk::removeUnusedBlocks()
|
|
|
int count = 0;
|
|
|
for (int i = 0; i < CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT; i++)
|
|
|
{
|
|
|
- if (blockIds[i] && blockIds[i] != BlockTypeEnum::AIR) count++;
|
|
|
+ if (StaticRegistry<BlockType>::INSTANCE.zElement(blockIds[i])
|
|
|
+ ->doesNeedClientInstance())
|
|
|
+ count++;
|
|
|
}
|
|
|
std::cout << "chunk " << location.x << ", " << location.y
|
|
|
<< " was generated with " << count << " blocks.\n";
|
|
@@ -951,13 +1000,21 @@ void Chunk::setLightData(
|
|
|
{
|
|
|
int bi = (pos.x * CHUNK_SIZE + pos.y) * WORLD_HEIGHT + pos.z;
|
|
|
int type = blockIds[bi];
|
|
|
- needSend |= type != BlockTypeEnum::NO_BLOCK
|
|
|
- && type != BlockTypeEnum::AIR;
|
|
|
+ needSend |= StaticRegistry<BlockType>::INSTANCE.zElement(type)
|
|
|
+ ->doesNeedClientInstance();
|
|
|
if (needSend) break;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- needSend = 1; // TODO: check if the block is visible
|
|
|
+ int type = Game::INSTANCE->getBlockType(
|
|
|
+ pos
|
|
|
+ + Vec3<int>(this->location.x - CHUNK_SIZE / 2,
|
|
|
+ this->location.y - CHUNK_SIZE / 2,
|
|
|
+ 0),
|
|
|
+ dimensionId);
|
|
|
+ needSend |= StaticRegistry<BlockType>::INSTANCE.zElement(type)
|
|
|
+ ->doesNeedClientInstance();
|
|
|
+ if (needSend) break;
|
|
|
}
|
|
|
}
|
|
|
}
|