mirror of
https://github.com/p2r3/bareiron.git
synced 2025-10-02 07:35:08 +02:00
rewrite sand ticking
This commit is contained in:
@@ -199,11 +199,20 @@ typedef struct {
|
|||||||
uint8_t block;
|
uint8_t block;
|
||||||
} BlockChange;
|
} BlockChange;
|
||||||
|
|
||||||
|
#define UPDATE_BASIC (1 << 0)
|
||||||
|
// the sand at this position will be moved down immediately when this is processed
|
||||||
|
#define UPDATE_FALL_SAND (1 << 1)
|
||||||
|
// the sand below this block will fall soon
|
||||||
|
#define UPDATE_CHECK_SAND_FALL (1 << 2)
|
||||||
|
|
||||||
|
#define UPDATE_NOW (UPDATE_BASIC | UPDATE_CHECK_SAND_FALL)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
short update_kind;
|
||||||
short x;
|
short x;
|
||||||
short z;
|
short z;
|
||||||
uint8_t y;
|
uint8_t y;
|
||||||
uint8_t awaitTicks;
|
uint8_t await_ticks;
|
||||||
} DeferredBlockUpdate;
|
} DeferredBlockUpdate;
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
|
@@ -32,6 +32,7 @@ uint8_t makeBlockChange (short x, uint8_t y, short z, 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);
|
uint8_t isColumnBlock (uint8_t block);
|
||||||
|
uint8_t isFallingBlock (uint8_t block);
|
||||||
uint8_t isPassableBlock (uint8_t block);
|
uint8_t isPassableBlock (uint8_t block);
|
||||||
uint8_t isPassableSpawnBlock (uint8_t block);
|
uint8_t isPassableSpawnBlock (uint8_t block);
|
||||||
uint8_t isReplaceableBlock (uint8_t block);
|
uint8_t isReplaceableBlock (uint8_t block);
|
||||||
@@ -43,9 +44,10 @@ 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);
|
||||||
void handlePlayerUseItem (PlayerData *player, short x, short y, short z, uint8_t face);
|
void handlePlayerUseItem (PlayerData *player, short x, short y, short z, uint8_t face);
|
||||||
|
|
||||||
void checkFluidUpdate (short x, uint8_t y, short z, uint8_t block);
|
void processBlockUpdate (short x, uint8_t y, short z, uint8_t block, short update_kind);
|
||||||
void processBlockUpdate (short x, uint8_t y, short z, uint8_t block);
|
void updateXZNeighbors (short x, uint8_t y, short z, short update_kind);
|
||||||
void deferBlockUpdate (short x, uint8_t y, short z, uint8_t awaitTicks);
|
void updateXYZNeighbors (short x, uint8_t y, short z, short update_kind);
|
||||||
|
void deferBlockUpdate (short x, uint8_t y, short z, uint8_t await_ticks, short update_kind);
|
||||||
|
|
||||||
void spawnMob (uint8_t type, short x, uint8_t y, short z, uint8_t health);
|
void spawnMob (uint8_t type, short x, uint8_t y, short z, uint8_t health);
|
||||||
void interactEntity (int entity_id, int interactor_id);
|
void interactEntity (int entity_id, int interactor_id);
|
||||||
|
136
src/procedures.c
136
src/procedures.c
@@ -1,3 +1,4 @@
|
|||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -761,6 +762,20 @@ uint8_t isInstantlyMined (PlayerData *player, uint8_t block) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Checks whether the given block can fall down (like sand, anvils, ...)
|
||||||
|
uint8_t isFallingBlock (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 ||
|
||||||
|
block == B_oak_sapling
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Checks whether the given block has to have something beneath it
|
// Checks whether the given block has to have something beneath it
|
||||||
uint8_t isColumnBlock (uint8_t block) {
|
uint8_t isColumnBlock (uint8_t block) {
|
||||||
return (
|
return (
|
||||||
@@ -1030,6 +1045,7 @@ uint8_t handlePlayerEating (PlayerData *player, uint8_t just_check) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
void handleFluidMovement (short x, uint8_t y, short z, uint8_t fluid, uint8_t block) {
|
void handleFluidMovement (short x, uint8_t y, short z, uint8_t fluid, uint8_t block) {
|
||||||
|
|
||||||
// Get fluid level (0-7)
|
// Get fluid level (0-7)
|
||||||
@@ -1108,19 +1124,16 @@ void handleFluidMovement (short x, uint8_t y, short z, uint8_t fluid, uint8_t bl
|
|||||||
makeBlockChange(x, y, z - 1, block + 1);
|
makeBlockChange(x, y, z - 1, block + 1);
|
||||||
deferBlockUpdate(x, y, z - 1, flow_speed);
|
deferBlockUpdate(x, y, z - 1, flow_speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkFluidUpdate (short x, uint8_t y, short z, uint8_t block) {
|
uint8_t getFluid(uint8_t block) {
|
||||||
|
if (block >= B_water && block < B_water + 8)
|
||||||
uint8_t fluid;
|
return B_water;
|
||||||
if (block >= B_water && block < B_water + 8) fluid = B_water;
|
else if (block >= B_lava && block < B_lava + 4)
|
||||||
else if (block >= B_lava && block < B_lava + 4) fluid = B_lava;
|
return B_lava;
|
||||||
else return;
|
return 0;
|
||||||
|
|
||||||
handleFluidMovement(x, y, z, fluid, block);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
#ifdef ENABLE_PICKUP_ANIMATION
|
#ifdef ENABLE_PICKUP_ANIMATION
|
||||||
// Plays the item pickup animation with the given item at the given coordinates
|
// Plays the item pickup animation with the given item at the given coordinates
|
||||||
@@ -1157,28 +1170,74 @@ void playPickupAnimation (PlayerData *player, uint16_t item, double x, double y,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void processBlockUpdate (short x, uint8_t y, short z, uint8_t block) {
|
// can not be zero!!
|
||||||
#ifdef DO_FLUID_FLOW
|
#define SAND_FALL_T 15
|
||||||
checkFluidUpdate(x, y, z, block);
|
#define SAND_FALL_PROPAGATE_T 2
|
||||||
#endif
|
|
||||||
|
|
||||||
if (isColumnBlock(block) && y) {
|
void processBlockUpdate (short x, uint8_t y, short z, uint8_t block, short update_kind) {
|
||||||
uint8_t below = getBlockAt(x, y - 1, z);
|
if (update_kind & UPDATE_BASIC) {
|
||||||
// TODO: if below block breaks sand
|
// TODO: water
|
||||||
if (isReplaceableBlock(below)) {
|
}
|
||||||
// TODO: drop item of below block
|
|
||||||
makeBlockChange(x, y, z, B_air);
|
if (update_kind & UPDATE_CHECK_SAND_FALL) {
|
||||||
makeBlockChange(x, y - 1, z, B_air);
|
// we have a separate UPDATE_CHECK_SAND_FALL,
|
||||||
makeBlockChange(x, y - 1, z, block);
|
// to make chains of falling sand fall as one,
|
||||||
// update this now moved block at the sand fall speed
|
// with less delay between each
|
||||||
deferBlockUpdate(x, y - 1, z, 15);
|
|
||||||
// update the block above next tick
|
if (isFallingBlock(block) && y) {
|
||||||
deferBlockUpdate(x, y + 1, z, 0);
|
uint8_t below = getBlockAt(x, y - 1, z);
|
||||||
|
if (isReplaceableBlock(below)) {
|
||||||
|
// move the sand down in 15 ticks
|
||||||
|
deferBlockUpdate(x, y, z, SAND_FALL_T - 1, UPDATE_FALL_SAND);
|
||||||
|
|
||||||
|
if (y != 255 && isFallingBlock(getBlockAt(x, y + 1, z))) {
|
||||||
|
// also tell the block above that the sand will be gone soon
|
||||||
|
deferBlockUpdate(x, y + 1, z, SAND_FALL_PROPAGATE_T, UPDATE_CHECK_SAND_FALL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (update_kind & UPDATE_FALL_SAND) {
|
||||||
|
// make sure that is a fallable:tm: block, and we are not in the floor
|
||||||
|
if (isFallingBlock(block) && y) {
|
||||||
|
uint8_t below = getBlockAt(x, y - 1, z);
|
||||||
|
// TODO: what to do if below block breaks sand
|
||||||
|
if (isReplaceableBlock(below)) {
|
||||||
|
// TODO: drop item of below block
|
||||||
|
makeBlockChange(x, y, z, B_air);
|
||||||
|
makeBlockChange(x, y - 1, z, B_air);
|
||||||
|
makeBlockChange(x, y - 1, z, block);
|
||||||
|
// update this block after moved
|
||||||
|
processBlockUpdate (x, y - 1, z, block, UPDATE_NOW);
|
||||||
|
// also update the neighbors
|
||||||
|
updateXZNeighbors(x, y, z, UPDATE_NOW);
|
||||||
|
updateXZNeighbors(x, y - 1, z, UPDATE_NOW);
|
||||||
|
if (y != 255) {
|
||||||
|
processBlockUpdate(x, y + 1, z, getBlockAt(x, y + 1, z), UPDATE_NOW);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void deferBlockUpdate (short x, uint8_t y, short z, uint8_t awaitTicks) {
|
void updateXZNeighbors (short x, uint8_t y, short z, short update_kind) {
|
||||||
|
processBlockUpdate(x - 1, y, z, getBlockAt(x - 1, y, z), update_kind);
|
||||||
|
processBlockUpdate(x + 1, y, z, getBlockAt(x + 1, y, z), update_kind);
|
||||||
|
processBlockUpdate(x, y, z - 1, getBlockAt(x, y, z - 1), update_kind);
|
||||||
|
processBlockUpdate(x, y, z + 1, getBlockAt(x, y, z + 1), update_kind);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateXYZNeighbors (short x, uint8_t y, short z, short update_kind) {
|
||||||
|
processBlockUpdate(x - 1, y, z, getBlockAt(x - 1, y, z), update_kind);
|
||||||
|
processBlockUpdate(x + 1, y, z, getBlockAt(x + 1, y, z), update_kind);
|
||||||
|
processBlockUpdate(x, y, z - 1, getBlockAt(x, y, z - 1), update_kind);
|
||||||
|
processBlockUpdate(x, y, z + 1, getBlockAt(x, y, z + 1), update_kind);
|
||||||
|
processBlockUpdate(x, y - 1, z, getBlockAt(x, y - 1, z), update_kind);
|
||||||
|
processBlockUpdate(x, y + 1, z, getBlockAt(x, y + 1, z), update_kind);
|
||||||
|
}
|
||||||
|
|
||||||
|
void deferBlockUpdate (short x, uint8_t y, short z, uint8_t await_ticks, short update_kind) {
|
||||||
if (deferred_block_updates_count == MAX_DEFERRED_BLOCK_UPDATES) {
|
if (deferred_block_updates_count == MAX_DEFERRED_BLOCK_UPDATES) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1187,7 +1246,8 @@ void deferBlockUpdate (short x, uint8_t y, short z, uint8_t awaitTicks) {
|
|||||||
u->x = x;
|
u->x = x;
|
||||||
u->y = y;
|
u->y = y;
|
||||||
u->z = z;
|
u->z = z;
|
||||||
u->awaitTicks = awaitTicks + is_processing_deferred_block_updates;
|
u->await_ticks = await_ticks + is_processing_deferred_block_updates;
|
||||||
|
u->update_kind = update_kind;
|
||||||
}
|
}
|
||||||
|
|
||||||
void handlePlayerAction (PlayerData *player, int action, short x, short y, short z) {
|
void handlePlayerAction (PlayerData *player, int action, short x, short y, short z) {
|
||||||
@@ -1240,11 +1300,7 @@ void handlePlayerAction (PlayerData *player, int action, short x, short y, short
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update nearby blocks
|
// Update nearby blocks
|
||||||
deferBlockUpdate(x, y + 1, z, 0);
|
updateXYZNeighbors(x, y, z, UPDATE_NOW);
|
||||||
deferBlockUpdate(x - 1, y, z, 0);
|
|
||||||
deferBlockUpdate(x + 1, y, z, 0);
|
|
||||||
deferBlockUpdate(x, y, z - 1, 0);
|
|
||||||
deferBlockUpdate(x, y, z + 1, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void handlePlayerUseItem (PlayerData *player, short x, short y, short z, uint8_t face) {
|
void handlePlayerUseItem (PlayerData *player, short x, short y, short z, uint8_t face) {
|
||||||
@@ -1389,12 +1445,8 @@ void handlePlayerUseItem (PlayerData *player, short x, short y, short z, uint8_t
|
|||||||
// 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;
|
||||||
// Send updates
|
// Send updates
|
||||||
processBlockUpdate(x, y, z, block);
|
processBlockUpdate(x, y, z, block, UPDATE_NOW);
|
||||||
deferBlockUpdate(x, y + 1, z, 0);
|
updateXYZNeighbors(x, y, z, UPDATE_NOW);
|
||||||
deferBlockUpdate(x - 1, y, z, 0);
|
|
||||||
deferBlockUpdate(x + 1, y, z, 0);
|
|
||||||
deferBlockUpdate(x, y, z - 1, 0);
|
|
||||||
deferBlockUpdate(x, y, z + 1, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync hotbar contents to player
|
// Sync hotbar contents to player
|
||||||
@@ -1719,11 +1771,11 @@ void handleServerTick (int64_t time_since_last_tick) {
|
|||||||
int next_update_idx = 0;
|
int next_update_idx = 0;
|
||||||
for (int i = 0; i < deferred_block_updates_count; i ++) {
|
for (int i = 0; i < deferred_block_updates_count; i ++) {
|
||||||
DeferredBlockUpdate *u = &deferred_block_updates[i];
|
DeferredBlockUpdate *u = &deferred_block_updates[i];
|
||||||
if (u->awaitTicks) {
|
if (u->await_ticks) {
|
||||||
u->awaitTicks --;
|
u->await_ticks --;
|
||||||
deferred_block_updates[next_update_idx ++] = *u;
|
deferred_block_updates[next_update_idx ++] = *u;
|
||||||
} else {
|
} else {
|
||||||
processBlockUpdate(u->x, u->y, u->z, getBlockAt(u->x, u->y, u->z));
|
processBlockUpdate(u->x, u->y, u->z, getBlockAt(u->x, u->y, u->z), u->update_kind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
deferred_block_updates_count = next_update_idx;
|
deferred_block_updates_count = next_update_idx;
|
||||||
|
Reference in New Issue
Block a user