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:
@@ -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
|
||||||
|
@@ -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;
|
||||||
|
|
||||||
|
// 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
|
// decrease item amount in selected slot
|
||||||
*count -= 1;
|
*count -= 1;
|
||||||
// clear item id in slot if amount is zero
|
// clear item id in slot if amount is zero
|
||||||
if (*count == 0) *item = 0;
|
if (*count == 0) *item = 0;
|
||||||
|
// apply server-side block change
|
||||||
makeBlockChange(x, y, z, block);
|
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;
|
||||||
|
106
src/tools.c
106
src/tools.c
@@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user