Browse Source

Fix "ghost" blocks if block update is "on wire" while player digs nodes

sapier 10 years ago
parent
commit
8e9d896f2d
3 changed files with 31 additions and 7 deletions
  1. 7 0
      src/clientiface.cpp
  2. 8 0
      src/clientiface.h
  3. 16 7
      src/server.cpp

+ 7 - 0
src/clientiface.cpp

@@ -52,6 +52,13 @@ std::string ClientInterface::state2Name(ClientState state)
 	return statenames[state];
 }
 
+void RemoteClient::ResendBlockIfOnWire(v3s16 p)
+{
+	// if this block is on wire, mark it for sending again as soon as possible
+	if (m_blocks_sending.find(p) != m_blocks_sending.end()) {
+		SetBlockNotSent(p);
+	}
+}
 
 void RemoteClient::GetNextBlocks(
 		ServerEnvironment *env,

+ 8 - 0
src/clientiface.h

@@ -238,6 +238,14 @@ public:
 	void SetBlockNotSent(v3s16 p);
 	void SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks);
 
+	/**
+	 * tell client about this block being modified right now.
+	 * this information is required to requeue the block in case it's "on wire"
+	 * while modification is processed by server
+	 * @param p position of modified block
+	 */
+	void ResendBlockIfOnWire(v3s16 p);
+
 	s32 SendingCount()
 	{
 		return m_blocks_sending.size();

+ 16 - 7
src/server.cpp

@@ -2545,14 +2545,17 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
 				if(is_valid_dig && n.getContent() != CONTENT_IGNORE)
 					m_script->node_on_dig(p_under, n, playersao);
 
+				v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
+				RemoteClient *client = getClient(peer_id);
 				// Send unusual result (that is, node not being removed)
 				if(m_env->getMap().getNodeNoEx(p_under).getContent() != CONTENT_AIR)
 				{
 					// Re-send block to revert change on client-side
-					RemoteClient *client = getClient(peer_id);
-					v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
 					client->SetBlockNotSent(blockpos);
 				}
+				else {
+					client->ResendBlockIfOnWire(blockpos);
+				}
 			}
 		} // action == 2
 
@@ -2594,15 +2597,21 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
 
 			// If item has node placement prediction, always send the
 			// blocks to make sure the client knows what exactly happened
-			if(item.getDefinition(m_itemdef).node_placement_prediction != ""){
-				RemoteClient *client = getClient(peer_id);
-				v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_above, BS));
+			RemoteClient *client = getClient(peer_id);
+			v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_above, BS));
+			v3s16 blockpos2 = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
+			if(item.getDefinition(m_itemdef).node_placement_prediction != "") {
 				client->SetBlockNotSent(blockpos);
-				v3s16 blockpos2 = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
-				if(blockpos2 != blockpos){
+				if(blockpos2 != blockpos) {
 					client->SetBlockNotSent(blockpos2);
 				}
 			}
+			else {
+				client->ResendBlockIfOnWire(blockpos);
+				if(blockpos2 != blockpos) {
+					client->ResendBlockIfOnWire(blockpos2);
+				}
+			}
 		} // action == 3
 
 		/*