mirror of
https://github.com/luanti-org/luanti.git
synced 2025-09-30 19:22:14 +00:00
Merge 78a79b8ae9
into 5f5ea13251
This commit is contained in:
commit
cc833d563d
4 changed files with 63 additions and 88 deletions
|
@ -803,17 +803,20 @@ enum ToServerCommand : u16
|
||||||
|
|
||||||
TOSERVER_INTERACT = 0x39,
|
TOSERVER_INTERACT = 0x39,
|
||||||
/*
|
/*
|
||||||
[0] u16 command
|
u16 command
|
||||||
[2] u8 action
|
u8 action (InteractAction)
|
||||||
[3] u16 item
|
u16 item
|
||||||
[5] u32 length of the next item
|
u32 length of the next item
|
||||||
[9] serialized PointedThing
|
u8[length] serialized PointedThing
|
||||||
actions:
|
v3s32 player position multiplied by 100 and converted to integers
|
||||||
0: start digging (from undersurface) or use
|
v3s32 player speed multiplied by 100 and converted to integers
|
||||||
1: stop digging (all parameters ignored)
|
s32 player pitch multiplied by 100 and converted to an integer
|
||||||
2: digging completed
|
s32 player yaw multiplied by 100 and converted to an integer
|
||||||
3: place block or item (to abovesurface)
|
u32 keyPressed
|
||||||
4: use item
|
u8 fov
|
||||||
|
u8 wanted drawing range
|
||||||
|
optional:
|
||||||
|
u8 flags; it is 0x01 if the camera is inverted
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TOSERVER_REMOVED_SOUNDS = 0x3a,
|
TOSERVER_REMOVED_SOUNDS = 0x3a,
|
||||||
|
|
|
@ -871,15 +871,6 @@ static inline void getWieldedItem(const PlayerSAO *playersao, std::optional<Item
|
||||||
|
|
||||||
void Server::handleCommand_Interact(NetworkPacket *pkt)
|
void Server::handleCommand_Interact(NetworkPacket *pkt)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
[0] u16 command
|
|
||||||
[2] u8 action
|
|
||||||
[3] u16 item
|
|
||||||
[5] u32 length of the next item (plen)
|
|
||||||
[9] serialized PointedThing
|
|
||||||
[9 + plen] player position information
|
|
||||||
*/
|
|
||||||
|
|
||||||
InteractAction action;
|
InteractAction action;
|
||||||
u16 item_i;
|
u16 item_i;
|
||||||
|
|
||||||
|
@ -909,13 +900,7 @@ void Server::handleCommand_Interact(NetworkPacket *pkt)
|
||||||
if (playersao->isDead()) {
|
if (playersao->isDead()) {
|
||||||
actionstream << "Server: " << player->getName()
|
actionstream << "Server: " << player->getName()
|
||||||
<< " tried to interact while dead; ignoring." << std::endl;
|
<< " tried to interact while dead; ignoring." << std::endl;
|
||||||
if (pointed.type == POINTEDTHING_NODE) {
|
getClient(peer_id)->respondToInteraction(action, pointed, false);
|
||||||
// Re-send block to revert change on client-side
|
|
||||||
RemoteClient *client = getClient(peer_id);
|
|
||||||
v3s16 blockpos = getNodeBlockPos(pointed.node_undersurface);
|
|
||||||
client->SetBlockNotSent(blockpos);
|
|
||||||
}
|
|
||||||
// Call callbacks
|
|
||||||
m_script->on_cheat(playersao, "interacted_while_dead");
|
m_script->on_cheat(playersao, "interacted_while_dead");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -955,22 +940,7 @@ void Server::handleCommand_Interact(NetworkPacket *pkt)
|
||||||
if (!checkPriv(player->getName(), "interact")) {
|
if (!checkPriv(player->getName(), "interact")) {
|
||||||
actionstream << player->getName() << " attempted to interact with " <<
|
actionstream << player->getName() << " attempted to interact with " <<
|
||||||
pointed.dump() << " without 'interact' privilege" << std::endl;
|
pointed.dump() << " without 'interact' privilege" << std::endl;
|
||||||
|
getClient(peer_id)->respondToInteraction(action, pointed, false);
|
||||||
if (pointed.type != POINTEDTHING_NODE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Re-send block to revert change on client-side
|
|
||||||
RemoteClient *client = getClient(peer_id);
|
|
||||||
// Digging completed -> under
|
|
||||||
if (action == INTERACT_DIGGING_COMPLETED) {
|
|
||||||
v3s16 blockpos = getNodeBlockPos(pointed.node_undersurface);
|
|
||||||
client->SetBlockNotSent(blockpos);
|
|
||||||
}
|
|
||||||
// Placement -> above
|
|
||||||
else if (action == INTERACT_PLACE) {
|
|
||||||
v3s16 blockpos = getNodeBlockPos(pointed.node_abovesurface);
|
|
||||||
client->SetBlockNotSent(blockpos);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -998,12 +968,7 @@ void Server::handleCommand_Interact(NetworkPacket *pkt)
|
||||||
float d = playersao->getEyePosition().getDistanceFrom(target_pos);
|
float d = playersao->getEyePosition().getDistanceFrom(target_pos);
|
||||||
|
|
||||||
if (!checkInteractDistance(player, d, pointed.dump())) {
|
if (!checkInteractDistance(player, d, pointed.dump())) {
|
||||||
if (pointed.type == POINTEDTHING_NODE) {
|
getClient(peer_id)->respondToInteraction(action, pointed, false);
|
||||||
// Re-send block to revert change on client-side
|
|
||||||
RemoteClient *client = getClient(peer_id);
|
|
||||||
v3s16 blockpos = getNodeBlockPos(pointed.node_undersurface);
|
|
||||||
client->SetBlockNotSent(blockpos);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1156,14 +1121,12 @@ void Server::handleCommand_Interact(NetworkPacket *pkt)
|
||||||
if (is_valid_dig && n.getContent() != CONTENT_IGNORE)
|
if (is_valid_dig && n.getContent() != CONTENT_IGNORE)
|
||||||
m_script->node_on_dig(p_under, n, playersao);
|
m_script->node_on_dig(p_under, n, playersao);
|
||||||
|
|
||||||
v3s16 blockpos = getNodeBlockPos(p_under);
|
// For whatever reason we assume that the client always predicts that a
|
||||||
RemoteClient *client = getClient(peer_id);
|
// dug node is air irrespective of the node's node_dig_prediction
|
||||||
// Send unusual result (that is, node not being removed)
|
bool prediction_success =
|
||||||
if (m_env->getMap().getNode(p_under).getContent() != CONTENT_AIR)
|
m_env->getMap().getNode(p_under).getContent() == CONTENT_AIR;
|
||||||
// Re-send block to revert change on client-side
|
getClient(peer_id)->respondToInteraction(action, pointed,
|
||||||
client->SetBlockNotSent(blockpos);
|
prediction_success);
|
||||||
else
|
|
||||||
client->ResendBlockIfOnWire(blockpos);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} // action == INTERACT_DIGGING_COMPLETED
|
} // action == INTERACT_DIGGING_COMPLETED
|
||||||
|
@ -1207,24 +1170,11 @@ void Server::handleCommand_Interact(NetworkPacket *pkt)
|
||||||
SendInventory(player, true);
|
SendInventory(player, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pointed.type != POINTEDTHING_NODE)
|
// Since we do not known if the client has predicted the node at
|
||||||
return;
|
// pointed.above or pointed.under,
|
||||||
|
// we assume that a prediction is always wrong.
|
||||||
// If item has node placement prediction, always send the
|
getClient(peer_id)->respondToInteraction(action, pointed,
|
||||||
// blocks to make sure the client knows what exactly happened
|
!had_prediction);
|
||||||
RemoteClient *client = getClient(peer_id);
|
|
||||||
v3s16 blockpos = getNodeBlockPos(pointed.node_abovesurface);
|
|
||||||
v3s16 blockpos2 = getNodeBlockPos(pointed.node_undersurface);
|
|
||||||
if (had_prediction) {
|
|
||||||
client->SetBlockNotSent(blockpos);
|
|
||||||
if (blockpos2 != blockpos)
|
|
||||||
client->SetBlockNotSent(blockpos2);
|
|
||||||
} else {
|
|
||||||
client->ResendBlockIfOnWire(blockpos);
|
|
||||||
if (blockpos2 != blockpos)
|
|
||||||
client->ResendBlockIfOnWire(blockpos2);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} // action == INTERACT_PLACE
|
} // action == INTERACT_PLACE
|
||||||
|
|
||||||
|
|
|
@ -66,14 +66,6 @@ RemoteClient::RemoteClient() :
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static LuaEntitySAO *getAttachedObject(PlayerSAO *sao, ServerEnvironment *env)
|
static LuaEntitySAO *getAttachedObject(PlayerSAO *sao, ServerEnvironment *env)
|
||||||
{
|
{
|
||||||
ServerActiveObject *ao = sao;
|
ServerActiveObject *ao = sao;
|
||||||
|
@ -453,6 +445,30 @@ void RemoteClient::SetBlocksNotSent(const std::vector<v3s16> &blocks, bool low_p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RemoteClient::respondToInteraction(InteractAction action,
|
||||||
|
const PointedThing &pointed, bool prediction_success)
|
||||||
|
{
|
||||||
|
if ((action != INTERACT_PLACE && action != INTERACT_DIGGING_COMPLETED)
|
||||||
|
|| pointed.type != POINTEDTHING_NODE)
|
||||||
|
// The client has not predicted not node changes
|
||||||
|
return;
|
||||||
|
|
||||||
|
// The client may have an outdated mapblock if the placement or dig
|
||||||
|
// prediction was wrong or if an old mapblock is still being sent to it.
|
||||||
|
v3s16 blockpos = getNodeBlockPos(pointed.node_undersurface);
|
||||||
|
if (!prediction_success
|
||||||
|
|| m_blocks_sending.find(blockpos) != m_blocks_sending.end()) {
|
||||||
|
SetBlockNotSent(blockpos);
|
||||||
|
}
|
||||||
|
if (action != INTERACT_PLACE)
|
||||||
|
return;
|
||||||
|
v3s16 blockpos2 = getNodeBlockPos(pointed.node_abovesurface);
|
||||||
|
if (blockpos2 != blockpos && (!prediction_success
|
||||||
|
|| m_blocks_sending.find(blockpos2) != m_blocks_sending.end())) {
|
||||||
|
SetBlockNotSent(blockpos2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RemoteClient::notifyEvent(ClientStateEvent event)
|
void RemoteClient::notifyEvent(ClientStateEvent event)
|
||||||
{
|
{
|
||||||
std::ostringstream myerror;
|
std::ostringstream myerror;
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "porting.h"
|
#include "porting.h"
|
||||||
#include "threading/mutex_auto_lock.h"
|
#include "threading/mutex_auto_lock.h"
|
||||||
#include "clientdynamicinfo.h"
|
#include "clientdynamicinfo.h"
|
||||||
|
#include "util/pointedthing.h"
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -255,12 +256,17 @@ public:
|
||||||
void SetBlocksNotSent(const std::vector<v3s16> &blocks, bool low_priority = false);
|
void SetBlocksNotSent(const std::vector<v3s16> &blocks, bool low_priority = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tell client about this block being modified right now.
|
* Trigger block sending to undo client-side predicted node changes
|
||||||
* this information is required to requeue the block in case it's "on wire"
|
*
|
||||||
* while modification is processed by server
|
* \param action The interact action to determine which predictions the
|
||||||
* @param p position of modified block
|
* client could have made
|
||||||
|
* \param pointed The positions where the client has interacted
|
||||||
|
* \param prediction_success If true, assume that the client has made a
|
||||||
|
* correct prediction and send the mapblock only if an outdated mapblock
|
||||||
|
* is currently "on wire", which can erroneously override the prediction
|
||||||
*/
|
*/
|
||||||
void ResendBlockIfOnWire(v3s16 p);
|
void respondToInteraction(InteractAction action,
|
||||||
|
const PointedThing &pointed, bool prediction_success);
|
||||||
|
|
||||||
u32 getSendingCount() const { return m_blocks_sending.size(); }
|
u32 getSendingCount() const { return m_blocks_sending.size(); }
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue