forked from EXTERNAL/bareiron
prevent players from dropping and losing items
This commit is contained in:
@@ -91,8 +91,10 @@ typedef struct {
|
||||
uint8_t hotbar;
|
||||
uint16_t inventory_items[41];
|
||||
uint16_t craft_items[9];
|
||||
uint16_t cursor_item;
|
||||
uint8_t inventory_count[41];
|
||||
uint8_t craft_count[9];
|
||||
uint8_t cursor_count;
|
||||
// 0x01 - attack cooldown
|
||||
// 0x02 - has not spawned yet
|
||||
// 0x04 - sneaking
|
||||
|
@@ -32,6 +32,7 @@ int sc_setCenterChunk (int client_fd, int x, int y);
|
||||
int sc_chunkDataAndUpdateLight (int client_fd, int _x, int _z);
|
||||
int sc_keepAlive (int client_fd);
|
||||
int sc_setContainerSlot (int client_fd, int window_id, uint16_t slot, uint8_t count, uint16_t item);
|
||||
int sc_setCursorItem (int client_fd, uint16_t item, uint8_t count);
|
||||
int sc_setHeldItem (int client_fd, uint8_t slot);
|
||||
int sc_blockUpdate (int client_fd, int64_t x, int64_t y, int64_t z, uint8_t block);
|
||||
int sc_openScreen (int client_fd, uint8_t window, const char *title, uint16_t length);
|
||||
|
@@ -26,6 +26,7 @@ ssize_t writeDouble (int client_fd, double num);
|
||||
|
||||
uint8_t readByte (int client_fd);
|
||||
uint16_t readUint16 (int client_fd);
|
||||
int16_t readInt16 (int client_fd);
|
||||
uint32_t readUint32 (int client_fd);
|
||||
uint64_t readUint64 (int client_fd);
|
||||
int64_t readInt64 (int client_fd);
|
||||
|
@@ -504,15 +504,37 @@ int cs_clickContainer (int client_fd) {
|
||||
int window_id = readVarInt(client_fd);
|
||||
|
||||
readVarInt(client_fd); // ignore state id
|
||||
readUint16(client_fd); // ignore clicked slot number
|
||||
readByte(client_fd); // ignore button
|
||||
readVarInt(client_fd); // ignore operation mode
|
||||
|
||||
int16_t clicked_slot = readInt16(client_fd);
|
||||
uint8_t button = readByte(client_fd);
|
||||
uint8_t mode = readVarInt(client_fd);
|
||||
|
||||
int changes_count = readVarInt(client_fd);
|
||||
|
||||
PlayerData *player;
|
||||
if (getPlayerData(client_fd, &player)) return 1;
|
||||
|
||||
uint8_t apply_changes = true;
|
||||
// prevent dropping items
|
||||
if (mode == 4 && clicked_slot != -999) {
|
||||
// when using drop button, re-sync the respective slot
|
||||
uint8_t slot = clientSlotToServerSlot(window_id, clicked_slot);
|
||||
sc_setContainerSlot(client_fd, window_id, clicked_slot, player->inventory_count[slot], player->inventory_items[slot]);
|
||||
apply_changes = false;
|
||||
} else if (mode == 0 && clicked_slot == -999) {
|
||||
// when clicking outside inventory, return the dropped item to the player
|
||||
if (button == 0) {
|
||||
givePlayerItem(player, player->cursor_item, player->cursor_count);
|
||||
player->cursor_item = 0;
|
||||
player->cursor_count = 0;
|
||||
} else {
|
||||
givePlayerItem(player, player->cursor_item, 1);
|
||||
player->cursor_count -= 1;
|
||||
if (player->cursor_count == 0) player->cursor_item = 0;
|
||||
}
|
||||
apply_changes = false;
|
||||
}
|
||||
|
||||
uint8_t slot, count, craft = false;
|
||||
uint16_t item;
|
||||
int tmp;
|
||||
@@ -521,10 +543,10 @@ int cs_clickContainer (int client_fd) {
|
||||
|
||||
slot = clientSlotToServerSlot(window_id, readUint16(client_fd));
|
||||
// slots outside of the inventory overflow into the crafting buffer
|
||||
if (slot > 40) craft = true;
|
||||
if (slot > 40 && apply_changes) craft = true;
|
||||
|
||||
if (!readByte(client_fd)) { // no item?
|
||||
if (slot != 255) {
|
||||
if (slot != 255 && apply_changes) {
|
||||
player->inventory_items[slot] = 0;
|
||||
player->inventory_count[slot] = 0;
|
||||
}
|
||||
@@ -540,7 +562,7 @@ int cs_clickContainer (int client_fd) {
|
||||
tmp = readVarInt(client_fd);
|
||||
recv_all(client_fd, recv_buffer, tmp, false);
|
||||
|
||||
if (count > 0) {
|
||||
if (count > 0 && apply_changes) {
|
||||
player->inventory_items[slot] = item;
|
||||
player->inventory_count[slot] = count;
|
||||
}
|
||||
@@ -558,20 +580,42 @@ int cs_clickContainer (int client_fd) {
|
||||
}
|
||||
}
|
||||
|
||||
// read but ignore carried item slot (for now)
|
||||
// assign cursor-carried item slot
|
||||
if (readByte(client_fd)) {
|
||||
readVarInt(client_fd);
|
||||
readVarInt(client_fd);
|
||||
player->cursor_item = readVarInt(client_fd);
|
||||
player->cursor_count = readVarInt(client_fd);
|
||||
// ignore components
|
||||
tmp = readVarInt(client_fd);
|
||||
recv_all(client_fd, recv_buffer, tmp, false);
|
||||
tmp = readVarInt(client_fd);
|
||||
recv_all(client_fd, recv_buffer, tmp, false);
|
||||
} else {
|
||||
player->cursor_item = 0;
|
||||
player->cursor_count = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
// S->C Set Cursor Item
|
||||
int sc_setCursorItem (int client_fd, uint16_t item, uint8_t count) {
|
||||
|
||||
writeVarInt(client_fd, 1 + sizeVarInt(count) + (count != 0 ? sizeVarInt(item) + 2 : 0));
|
||||
writeByte(client_fd, 0x59);
|
||||
|
||||
writeVarInt(client_fd, count);
|
||||
if (count == 0) return 0;
|
||||
|
||||
writeVarInt(client_fd, item);
|
||||
|
||||
// Skip components
|
||||
writeByte(client_fd, 0);
|
||||
writeByte(client_fd, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// C->S Set Player Position And Rotation
|
||||
int cs_setPlayerPositionAndRotation (int client_fd, double *x, double *y, double *z, float *yaw, float *pitch, uint8_t *on_ground) {
|
||||
|
||||
@@ -656,6 +700,11 @@ int cs_closeContainer (int client_fd) {
|
||||
if (client_slot != 255) sc_setContainerSlot(player->client_fd, window_id, client_slot, 0, 0);
|
||||
}
|
||||
|
||||
givePlayerItem(player, player->cursor_item, player->cursor_count);
|
||||
sc_setCursorItem(client_fd, 0, 0);
|
||||
player->cursor_item = 0;
|
||||
player->cursor_count = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -572,6 +572,20 @@ uint8_t getItemStackSize (uint16_t item) {
|
||||
|
||||
void handlePlayerAction (PlayerData *player, int action, short x, short y, short z) {
|
||||
|
||||
// Re-sync slot when player drops an item
|
||||
if (action == 3 || action == 4) {
|
||||
sc_setContainerSlot(
|
||||
player->client_fd, 0,
|
||||
serverSlotToClientSlot(0, player->hotbar),
|
||||
player->inventory_count[player->hotbar],
|
||||
player->inventory_items[player->hotbar]
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore further actions not pertaining to mining blocks
|
||||
if (action != 0 && action != 2) return;
|
||||
|
||||
// In creative, only the "start mining" action is sent
|
||||
// No additional verification is performed, the block is simply removed
|
||||
if (action == 0 && GAMEMODE == 1) {
|
||||
@@ -579,9 +593,6 @@ void handlePlayerAction (PlayerData *player, int action, short x, short y, short
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore actions not pertaining to mining blocks
|
||||
if (action != 0 && action != 2) return;
|
||||
|
||||
uint8_t block = getBlockAt(x, y, z);
|
||||
|
||||
// If this is a "start mining" packet, the block must be instamine
|
||||
|
@@ -134,6 +134,10 @@ uint16_t readUint16 (int client_fd) {
|
||||
recv_count = recv_all(client_fd, recv_buffer, 2, false);
|
||||
return ((uint16_t)recv_buffer[0] << 8) | recv_buffer[1];
|
||||
}
|
||||
int16_t readInt16 (int client_fd) {
|
||||
recv_count = recv_all(client_fd, recv_buffer, 2, false);
|
||||
return ((int16_t)recv_buffer[0] << 8) | (int16_t)recv_buffer[1];
|
||||
}
|
||||
uint32_t readUint32 (int client_fd) {
|
||||
recv_count = recv_all(client_fd, recv_buffer, 4, false);
|
||||
return ((uint32_t)recv_buffer[0] << 24) |
|
||||
|
Reference in New Issue
Block a user