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

@@ -509,9 +509,6 @@ int cs_useItemOn (int client_fd) {
PlayerData *player;
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];
uint8_t *count = &player->inventory_count[player->hotbar];
uint8_t block = I_to_B(*item);
@@ -520,12 +517,22 @@ int cs_useItemOn (int client_fd) {
if (block == 0) return 0;
// if the selected slot doesn't hold any items, exit
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);
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
// Probability numbers obtained with this formula: N = floor(P * 32 ^ 2)
uint16_t getMiningResult (PlayerData *player, 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);
}
uint16_t getMiningResult (uint16_t held_item, uint8_t block) {
switch (block) {
case B_oak_leaves:
uint32_t r = fast_rand();
if (r < 21474836) return I_apple; // 0.5%
if (r < 85899345) return I_stick; // 2%
if (r < 214748364) return I_oak_sapling; // 5%
@@ -480,6 +463,18 @@ uint16_t getMiningResult (PlayerData *player, uint8_t block) {
) return 0;
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;
}
@@ -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
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 (
@@ -503,7 +518,26 @@ uint8_t isInstantlyMined (PlayerData *player, uint8_t block) {
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);
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);
bumpToolDurability(player);
// 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);
uint8_t y_offset = 1;
uint8_t block_above = getBlockAt(x, y + y_offset, z);
// Iterate upward over all blocks in the column
while (isColumnBlock(block_above)) {
// Destroy the next block
makeBlockChange(x, y + y_offset, z, 0);
// 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);
}
}