1
0
mirror of https://github.com/p2r3/bareiron.git synced 2025-10-01 23:25:09 +02:00

handle column blocks more consistently

This commit is contained in:
p2r3
2025-08-21 13:32:40 +03:00
parent c8ee2c6bf1
commit 2a0d465ad7
3 changed files with 92 additions and 41 deletions

View File

@@ -53,8 +53,10 @@ uint8_t clientSlotToServerSlot (int window_id, uint8_t slot);
uint8_t getBlockChange (short x, uint8_t y, short z); uint8_t getBlockChange (short x, uint8_t y, short z);
void makeBlockChange (short x, uint8_t y, short z, uint8_t block); void makeBlockChange (short x, uint8_t y, short z, uint8_t block);
uint16_t getMiningResult (PlayerData *player, uint8_t block);
uint8_t isInstantlyMined (PlayerData *player, uint8_t block); uint8_t isInstantlyMined (PlayerData *player, uint8_t block);
uint8_t isColumnBlock (uint8_t block);
uint16_t getMiningResult (uint16_t held_item, uint8_t block);
void bumpToolDurability (PlayerData *player);
void handlePlayerAction (PlayerData *player, int action, short x, short y, short z); void handlePlayerAction (PlayerData *player, int action, short x, short y, short z);
#endif #endif

View File

@@ -509,9 +509,6 @@ int cs_useItemOn (int client_fd) {
PlayerData *player; PlayerData *player;
if (getPlayerData(client_fd, &player)) return 1; if (getPlayerData(client_fd, &player)) return 1;
// check if the player is in the way
if (x == player->x && (y == player->y || y == player->y + 1) && z == player->z) return 0;
uint16_t *item = &player->inventory_items[player->hotbar]; uint16_t *item = &player->inventory_items[player->hotbar];
uint8_t *count = &player->inventory_count[player->hotbar]; uint8_t *count = &player->inventory_count[player->hotbar];
uint8_t block = I_to_B(*item); uint8_t block = I_to_B(*item);
@@ -520,12 +517,22 @@ int cs_useItemOn (int client_fd) {
if (block == 0) return 0; if (block == 0) return 0;
// if the selected slot doesn't hold any items, exit // if the selected slot doesn't hold any items, exit
if (*count == 0) return 0; if (*count == 0) return 0;
// decrease item amount in selected slot
*count -= 1;
// clear item id in slot if amount is zero
if (*count == 0) *item = 0;
makeBlockChange(x, y, z, block); // check if the block's placement conditions are met
if (
!(x == player->x && (y == player->y || y == player->y + 1) && z == player->z) &&
(getBlockAt(x, y, z) == B_air) &&
(!isColumnBlock(block) || getBlockAt(x, y - 1, z) != B_air)
) {
// decrease item amount in selected slot
*count -= 1;
// clear item id in slot if amount is zero
if (*count == 0) *item = 0;
// apply server-side block change
makeBlockChange(x, y, z, block);
}
// sync hotbar contents to player
sc_setContainerSlot(client_fd, 0, serverSlotToClientSlot(0, player->hotbar), *count, *item); sc_setContainerSlot(client_fd, 0, serverSlotToClientSlot(0, player->hotbar), *count, *item);
return 0; return 0;

View File

@@ -424,29 +424,12 @@ 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 // 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) // Probability numbers obtained with this formula: N = floor(P * 32 ^ 2)
uint16_t getMiningResult (PlayerData *player, uint8_t block) { uint16_t getMiningResult (uint16_t held_item, uint8_t block) {
uint16_t held_item = player->inventory_items[player->hotbar];
// In order to avoid storing durability data, items break randomly with
// the probability weighted based on vanilla durability.
uint32_t r = fast_rand();
if (
((held_item == I_wooden_pickaxe || held_item == I_wooden_axe || held_item == I_wooden_shovel) && r < 72796055) ||
((held_item == I_stone_pickaxe || held_item == I_stone_axe || held_item == I_stone_shovel) && r < 32786009) ||
((held_item == I_iron_pickaxe || held_item == I_iron_axe || held_item == I_iron_shovel) && r < 17179869) ||
((held_item == I_golden_pickaxe || held_item == I_golden_axe || held_item == I_golden_shovel) && r < 134217728) ||
((held_item == I_diamond_pickaxe || held_item == I_diamond_axe || held_item == I_diamond_shovel) && r < 2751420) ||
((held_item == I_netherite_pickaxe || held_item == I_netherite_axe || held_item == I_netherite_shovel) && r < 2114705)
) {
player->inventory_items[player->hotbar] = 0;
player->inventory_count[player->hotbar] = 0;
sc_setContainerSlot(player->client_fd, 0, serverSlotToClientSlot(0, player->hotbar), 0, 0);
}
switch (block) { switch (block) {
case B_oak_leaves: case B_oak_leaves:
uint32_t r = fast_rand();
if (r < 21474836) return I_apple; // 0.5% if (r < 21474836) return I_apple; // 0.5%
if (r < 85899345) return I_stick; // 2% if (r < 85899345) return I_stick; // 2%
if (r < 214748364) return I_oak_sapling; // 5% if (r < 214748364) return I_oak_sapling; // 5%
@@ -480,6 +463,18 @@ uint16_t getMiningResult (PlayerData *player, uint8_t block) {
) return 0; ) return 0;
break; break;
case B_snow:
// Check if player is holding (any) shovel
if (
held_item != I_wooden_shovel &&
held_item != I_stone_shovel &&
held_item != I_iron_shovel &&
held_item != I_golden_shovel &&
held_item != I_diamond_shovel &&
held_item != I_netherite_shovel
) return 0;
break;
default: break; default: break;
} }
@@ -487,12 +482,32 @@ uint16_t getMiningResult (PlayerData *player, uint8_t block) {
} }
// Rolls a random number to determine whether the player's tool should break
void bumpToolDurability (PlayerData *player) {
uint16_t held_item = player->inventory_items[player->hotbar];
// In order to avoid storing durability data, items break randomly with
// the probability weighted based on vanilla durability.
uint32_t r = fast_rand();
if (
((held_item == I_wooden_pickaxe || held_item == I_wooden_axe || held_item == I_wooden_shovel) && r < 72796055) ||
((held_item == I_stone_pickaxe || held_item == I_stone_axe || held_item == I_stone_shovel) && r < 32786009) ||
((held_item == I_iron_pickaxe || held_item == I_iron_axe || held_item == I_iron_shovel) && r < 17179869) ||
((held_item == I_golden_pickaxe || held_item == I_golden_axe || held_item == I_golden_shovel) && r < 134217728) ||
((held_item == I_diamond_pickaxe || held_item == I_diamond_axe || held_item == I_diamond_shovel) && r < 2751420) ||
((held_item == I_netherite_pickaxe || held_item == I_netherite_axe || held_item == I_netherite_shovel) && r < 2114705)
) {
player->inventory_items[player->hotbar] = 0;
player->inventory_count[player->hotbar] = 0;
sc_setContainerSlot(player->client_fd, 0, serverSlotToClientSlot(0, player->hotbar), 0, 0);
}
}
// Checks whether the given block would be mined instantly with the held tool // Checks whether the given block would be mined instantly with the held tool
uint8_t isInstantlyMined (PlayerData *player, uint8_t block) { 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]; uint16_t held_item = player->inventory_items[player->hotbar];
if (block == B_snow) return ( if (block == B_snow) return (
@@ -503,7 +518,26 @@ uint8_t isInstantlyMined (PlayerData *player, uint8_t block) {
held_item == I_golden_shovel held_item == I_golden_shovel
); );
return false; return (
block == B_dead_bush ||
block == B_short_grass ||
block == B_torch
);
}
// Checks whether the given block has to have something beneath it
uint8_t isColumnBlock (uint8_t block) {
return (
block == B_snow ||
block == B_moss_carpet ||
block == B_cactus ||
block == B_short_grass ||
block == B_dead_bush ||
block == B_sand ||
block == B_torch
);
} }
@@ -526,17 +560,25 @@ void handlePlayerAction (PlayerData *player, int action, short x, short y, short
makeBlockChange(x, y, z, 0); makeBlockChange(x, y, z, 0);
uint16_t item = getMiningResult(player, block); uint16_t held_item = player->inventory_items[player->hotbar];
uint16_t item = getMiningResult(held_item, block);
if (item) givePlayerItem(player, item, 1); if (item) givePlayerItem(player, item, 1);
bumpToolDurability(player);
// Check if any blocks above this should break // Check if any blocks above this should break
uint8_t block_above = getBlockAt(x, y + 1, z); uint8_t y_offset = 1;
if ( uint8_t block_above = getBlockAt(x, y + y_offset, z);
block_above == B_snow ||
block_above == B_moss_carpet || // Iterate upward over all blocks in the column
block_above == B_cactus || while (isColumnBlock(block_above)) {
block_above == B_short_grass || // Destroy the next block
block_above == B_dead_bush makeBlockChange(x, y + y_offset, z, 0);
) return handlePlayerAction(player, 2, x, y + 1, z); // Check for item drops *without a tool*
uint16_t item = getMiningResult(0, block_above);
if (item) givePlayerItem(player, item, 1);
// Select the next block in the column
y_offset ++;
block_above = getBlockAt(x, y + y_offset, z);
}
} }