Browse Source

send light data to clients

Kolja Strohm 2 years ago
parent
commit
72ece6a5b2
3 changed files with 107 additions and 22 deletions
  1. 102 19
      FactoryCraft/Chunk.cpp
  2. 2 0
      FactoryCraft/Chunk.h
  3. 3 3
      FactoryCraft/Dimension.cpp

+ 102 - 19
FactoryCraft/Chunk.cpp

@@ -64,6 +64,51 @@ void Chunk::removeLightSource(int index)
 	}
 }
 
+void Chunk::sendLightToClient(Entity* zPlayer)
+{
+	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 != NoBlockBlockType::ID && type != AirBlockBlockType::ID;
+							if (needSend)
+								break;
+						}
+						else
+						{
+							needSend = 1; // TODO: check if the block is visible
+						}
+					}
+				}
+				if (needSend)
+				{
+					NetworkMessage msg;
+					msg.addressChunck(this);
+					char message[11];
+					message[0] = 1;
+					int index = (x * CHUNK_SIZE + y) * WORLD_HEIGHT + z;
+					*(int*)(message + 1) = index;
+					memcpy(message + 5, lightData + index * 6, 6);
+					msg.setMessage(message, 11, 0);
+					Game::INSTANCE->sendMessage(&msg, zPlayer);
+				}
+			}
+		}
+	}
+}
+
 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)
@@ -116,6 +161,7 @@ void Chunk::addObserver(Entity* zEntity)
 	msg.setMessage(message, (int)buffer.getSize(), 1);
 	msg.setUseBackground();
 	Game::INSTANCE->sendMessage(&msg, zEntity);
+	sendLightToClient(zEntity);
 }
 
 void Chunk::removeObserver(Entity* zEntity)
@@ -197,6 +243,7 @@ void Chunk::initializeLightning()
 					{
 						if (newLight[i] != light[i])
 						{
+							changes = 1;
 							memcpy(light, newLight, 6);
 						}
 					}
@@ -315,16 +362,16 @@ void Chunk::putBlockAt(Framework::Vec3<int> location, Block* block)
 		}
 		if (added)
 		{
+			char msg[9];
+			msg[0] = 0; // set block
+			*(int*)(msg + 1) = index;
+			*(int*)(msg + 5) = block ? block->zBlockType()->getId() : NoBlockBlockType::ID;
+			NetworkMessage message;
+			message.addressChunck(this);
+			message.setMessage(msg, 9, 0);
+			notifyObservers(message);
 			Game::INSTANCE->updateLightning(getDimensionId(), Vec3<int>(location.x + this->location.x - CHUNK_SIZE / 2, location.y + this->location.y - CHUNK_SIZE / 2, location.z));
 		}
-		char msg[9];
-		msg[0] = 0; // set block
-		*(int*)(msg + 1) = index;
-		*(int*)(msg + 5) = block ? block->zBlockType()->getId() : NoBlockBlockType::ID;
-		NetworkMessage message;
-		message.addressChunck(this);
-		message.setMessage(msg, 9, 0);
-		notifyObservers(message);
 	}
 }
 
@@ -364,16 +411,16 @@ void Chunk::putBlockTypeAt(Framework::Vec3<int> location, int type)
 		}
 		if (added)
 		{
+			char msg[9];
+			msg[0] = 0; // set block
+			*(int*)(msg + 1) = index;
+			*(int*)(msg + 5) = type;
+			NetworkMessage message;
+			message.addressChunck(this);
+			message.setMessage(msg, 9, 0);
+			notifyObservers(message);
 			Game::INSTANCE->updateLightning(getDimensionId(), Vec3<int>(location.x + this->location.x - CHUNK_SIZE / 2, location.y + this->location.y - CHUNK_SIZE / 2, location.z));
 		}
-		char msg[9];
-		msg[0] = 0; // set block
-		*(int*)(msg + 1) = index;
-		*(int*)(msg + 5) = type;
-		NetworkMessage message;
-		message.addressChunck(this);
-		message.setMessage(msg, 9, 0);
-		notifyObservers(message);
 	}
 }
 
@@ -541,9 +588,7 @@ void Chunk::sendToClient(Framework::StreamWriter* zWriter)
 					if (visible && (blocks[index] || blockType != AirBlockBlockType::ID))
 					{
 						zWriter->schreibe((char*)&blockType, 2);
-						zWriter->schreibe((char*)&x, 4);
-						zWriter->schreibe((char*)&y, 4);
-						zWriter->schreibe((char*)&z, 4);
+						zWriter->schreibe((char*)&index, 4);
 					}
 				}
 			}
@@ -651,4 +696,42 @@ 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)
+{
+	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 != NoBlockBlockType::ID && type != AirBlockBlockType::ID;
+				if (needSend)
+					break;
+			}
+			else
+			{
+				needSend = 1; // TODO: check if the block is visible
+			}
+		}
+	}
+	if (needSend)
+	{
+		NetworkMessage msg;
+		msg.addressChunck(this);
+		char message[11];
+		message[0] = 1;
+		*(int*)(message + 1) = index / 6;
+		memcpy(message + 5, data, 6);
+		msg.setMessage(message, 11, 0);
+		notifyObservers(msg);
+	}
 }

+ 2 - 0
FactoryCraft/Chunk.h

@@ -26,6 +26,7 @@ private:
 
 	void addLightSource(int index);
 	void removeLightSource(int index);
+	void sendLightToClient(Entity* zPlayer);
 
 public:
 	Chunk(Framework::Punkt location, int dimensionId);
@@ -57,4 +58,5 @@ public:
 	void setAdded();
 	bool hasObservers() const;
 	unsigned char* getLightData(Framework::Vec3<int> location) const;
+	void setLightData(Framework::Vec3<int> location, unsigned char* data);
 };

+ 3 - 3
FactoryCraft/Dimension.cpp

@@ -122,8 +122,8 @@ void Dimension::thread()
 					else
 					{
 						Chunk* neighborChunk = zChunk(Game::INSTANCE->getChunkCenter(neighborPos.x, neighborPos.y));
-						x = neighborPos.x % CHUNK_SIZE;
-						y = neighborPos.y % CHUNK_SIZE;
+						int x = neighborPos.x % CHUNK_SIZE;
+						int y = neighborPos.y % CHUNK_SIZE;
 						if (x < 0)
 							x += CHUNK_SIZE;
 						if (y < 0)
@@ -150,7 +150,7 @@ void Dimension::thread()
 				{
 					if (newLight[i] != light[i])
 					{
-						memcpy(light, newLight, 6);
+						chunk->setLightData(Vec3<int>(x, y, position.z), newLight);
 						for (int j = 0; j < 6; j++)
 							updateLightning(position + getDirection(getDirectionFromIndex(j)));
 						break;