forked from EXTERNAL/bareiron
handle breaking columns of blocks
This commit is contained in:
@@ -48,6 +48,8 @@ uint8_t clientSlotToServerSlot (int window_id, uint8_t slot);
|
||||
uint8_t getBlockChange (short x, uint8_t y, short z);
|
||||
void makeBlockChange (short x, uint8_t y, short z, uint8_t block);
|
||||
|
||||
uint16_t getMiningResult (int client_fd, uint8_t block);
|
||||
uint16_t getMiningResult (PlayerData *player, uint8_t block);
|
||||
uint8_t isInstantlyMined (PlayerData *player, uint8_t block);
|
||||
void handlePlayerAction (PlayerData *player, int action, short x, short y, short z);
|
||||
|
||||
#endif
|
||||
|
@@ -438,24 +438,10 @@ int cs_playerAction (int client_fd) {
|
||||
int sequence = readVarInt(client_fd);
|
||||
sc_acknowledgeBlockChange(client_fd, sequence);
|
||||
|
||||
if ((action == 0 && GAMEMODE == 1)) {
|
||||
// block was mined in creative
|
||||
makeBlockChange(x, y, z, 0);
|
||||
} else if (action == 2) {
|
||||
// block was mined in survival
|
||||
PlayerData *player;
|
||||
if (getPlayerData(client_fd, &player)) return 1;
|
||||
|
||||
uint8_t block = getBlockAt(x, y, z);
|
||||
uint16_t item = getMiningResult(client_fd, block);
|
||||
|
||||
makeBlockChange(x, y, z, 0);
|
||||
|
||||
if (item) {
|
||||
PlayerData *player;
|
||||
if (getPlayerData(client_fd, &player)) return 1;
|
||||
givePlayerItem(player, item, 1);
|
||||
}
|
||||
|
||||
}
|
||||
handlePlayerAction(player, action, x, y, z);
|
||||
|
||||
return 0;
|
||||
|
||||
|
60
src/tools.c
60
src/tools.c
@@ -424,10 +424,8 @@ void makeBlockChange (short x, uint8_t y, short z, uint8_t block) {
|
||||
|
||||
// Returns the result of mining a block, taking into account the block type and tools
|
||||
// Probability numbers obtained with this formula: N = floor(P * 32 ^ 2)
|
||||
uint16_t getMiningResult (int client_fd, uint8_t block) {
|
||||
uint16_t getMiningResult (PlayerData *player, uint8_t block) {
|
||||
|
||||
PlayerData *player;
|
||||
if (getPlayerData(client_fd, &player)) return 0;
|
||||
uint16_t held_item = player->inventory_items[player->hotbar];
|
||||
|
||||
// In order to avoid storing durability data, items break randomly with
|
||||
@@ -443,7 +441,7 @@ uint16_t getMiningResult (int client_fd, uint8_t block) {
|
||||
) {
|
||||
player->inventory_items[player->hotbar] = 0;
|
||||
player->inventory_count[player->hotbar] = 0;
|
||||
sc_setContainerSlot(client_fd, 0, serverSlotToClientSlot(0, player->hotbar), 0, 0);
|
||||
sc_setContainerSlot(player->client_fd, 0, serverSlotToClientSlot(0, player->hotbar), 0, 0);
|
||||
}
|
||||
|
||||
switch (block) {
|
||||
@@ -488,3 +486,57 @@ uint16_t getMiningResult (int client_fd, uint8_t block) {
|
||||
return B_to_I[block];
|
||||
|
||||
}
|
||||
|
||||
// Checks whether the given block would be mined instantly with the held tool
|
||||
uint8_t isInstantlyMined (PlayerData *player, uint8_t block) {
|
||||
|
||||
if (block == B_dead_bush) return true;
|
||||
if (block == B_short_grass) return true;
|
||||
|
||||
uint16_t held_item = player->inventory_items[player->hotbar];
|
||||
|
||||
if (block == B_snow) return (
|
||||
held_item == I_stone_shovel ||
|
||||
held_item == I_iron_shovel ||
|
||||
held_item == I_diamond_shovel ||
|
||||
held_item == I_netherite_shovel ||
|
||||
held_item == I_golden_shovel
|
||||
);
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
void handlePlayerAction (PlayerData *player, int action, short x, short y, short z) {
|
||||
|
||||
// In creative, only the "start mining" action is sent
|
||||
// No additional verification is performed, the block is simply removed
|
||||
if (action == 0 && GAMEMODE == 1) {
|
||||
makeBlockChange(x, y, z, 0);
|
||||
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
|
||||
if (action == 0 && !isInstantlyMined(player, block)) return;
|
||||
|
||||
makeBlockChange(x, y, z, 0);
|
||||
|
||||
uint16_t item = getMiningResult(player, block);
|
||||
if (item) givePlayerItem(player, item, 1);
|
||||
|
||||
// Check if any blocks above this should break
|
||||
uint8_t block_above = getBlockAt(x, y + 1, z);
|
||||
if (
|
||||
block_above == B_snow ||
|
||||
block_above == B_moss_carpet ||
|
||||
block_above == B_cactus ||
|
||||
block_above == B_short_grass ||
|
||||
block_above == B_dead_bush
|
||||
) return handlePlayerAction(player, 2, x, y + 1, z);
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user