fix door bugs

This commit is contained in:
JavaProphet 2018-01-18 20:06:47 -08:00
parent 50d2ba4607
commit 93b6a94125
6 changed files with 64 additions and 21 deletions

View File

@ -28,6 +28,16 @@
struct collection* block_infos;
struct collection* block_materials;
uint8_t getFaceFromPlayer(struct player* player) {
uint32_t h = (uint32_t) floor(player->entity->yaw / 90. + .5) & 3;
uint8_t f = 0;
if (h == 0) f = SOUTH;
else if (h == 1) f = WEST;
else if (h == 2) f = NORTH;
else if (h == 3) f = EAST;
return f;
}
void onBlockUpdate_checkPlace(struct world* world, block blk, int32_t x, int32_t y, int32_t z) {
struct block_info* bi = getBlockInfo(blk);
if (bi != NULL && bi->canBePlaced != NULL && !(*bi->canBePlaced)(world, blk, x, y, z)) {
@ -110,12 +120,7 @@ int canBePlaced_torch(struct world* world, block blk, int32_t x, int32_t y, int3
}
block onBlockPlacedPlayer_lever(struct player* player, struct world* world, block blk, int32_t x, int32_t y, int32_t z, uint8_t face) {
uint32_t h = (uint32_t) floor(player->entity->yaw / 90. + .5) & 3;
uint8_t f = 0;
if (h == 0) f = SOUTH;
else if (h == 1) f = WEST;
else if (h == 2) f = NORTH;
else if (h == 3) f = EAST;
uint8_t f = getFaceFromPlayer(player);
if (face == NORTH) return blk | 0x04;
else if (face == SOUTH) return blk | 0x03;
else if (face == EAST) return blk | 0x01;

View File

@ -510,6 +510,8 @@ struct block_info* getBlockInfo(block b);
struct block_info* getBlockInfoLoose(block b);
uint8_t getFaceFromPlayer(struct player* player);
item getItemFromName(const char* name);
struct block_info {

View File

@ -858,13 +858,36 @@ int getSwingTime(struct entity* ent) {
return 6;
}
block entity_adjustCollision(struct world* world, struct chunk* ch, block b, int32_t x, int32_t y, int32_t z) {
block entity_adjustCollision(struct world* world, struct entity* ent, struct chunk* ch, block b, int32_t x, int32_t y, int32_t z) {
if (b >> 4 == BLK_DOORIRON >> 4 || b >> 4 == BLK_DOOROAK >> 4 || b >> 4 == BLK_DOORSPRUCE >> 4 || b >> 4 == BLK_DOORBIRCH >> 4 || b >> 4 == BLK_DOORJUNGLE >> 4 || b >> 4 == BLK_DOORACACIA >> 4 || b >> 4 == BLK_DOORDARKOAK >> 4) {
if (b & 0b1000) return getBlockWorld_guess(world, ch, x, y - 1, z);
}
return b;
}
void entity_adjustBoundingBox(struct world* world, struct entity* ent, struct chunk* ch, block b, int32_t x, int32_t y, int32_t z, struct boundingbox* in, struct boundingbox* out) {
memcpy(in, out, sizeof(struct boundingbox));
if (b >> 4 == BLK_DOORIRON >> 4 || b >> 4 == BLK_DOOROAK >> 4 || b >> 4 == BLK_DOORSPRUCE >> 4 || b >> 4 == BLK_DOORBIRCH >> 4 || b >> 4 == BLK_DOORJUNGLE >> 4 || b >> 4 == BLK_DOORACACIA >> 4 || b >> 4 == BLK_DOORDARKOAK >> 4) {
block lb = b;
block ub = b;
if (b & 0b1000) {
lb = getBlockWorld_guess(world, ch, x, y - 1, z);
} else {
ub = getBlockWorld_guess(world, ch, x, y + 1, z);
}
if ((lb & 0b0010) && (ub & 0b0001)) {
uint8_t face = lb & 0b0011;
if (face == 3 || face == 1) {
out->maxZ = 1. - in->maxZ;
out->minZ = 1. - in->minZ;
} else {
out->maxX = 1. - in->maxX;
out->minX = 1. - in->minX;
}
}
}
}
int moveEntity(struct entity* entity, double* mx, double* my, double* mz, float shrink) {
if (entity->immovable) return 0;
struct boundingbox obb;
@ -911,11 +934,14 @@ int moveEntity(struct entity* entity, double* mx, double* my, double* mz, float
for (int32_t y = floor(obb.minY); y < floor(obb.maxY + 1.); y++) {
block b = getBlockWorld_guess(entity->world, ch, x, y, z);
if (b == 0) continue;
b = entity_adjustCollision(entity->world, ch, b, x, y, z);
b = entity_adjustCollision(entity->world, entity, ch, b, x, y, z);
struct block_info* bi = getBlockInfo(b);
if (bi == NULL) continue;
for (size_t i = 0; i < bi->boundingBox_count; i++) {
struct boundingbox* bb = &bi->boundingBoxes[i];
struct boundingbox* bbx = &bi->boundingBoxes[i];
struct boundingbox bbd;
struct boundingbox* bb = &bbd;
entity_adjustBoundingBox(entity->world, entity, ch, b, x, y, z, bbx, &bbd);
// if (!bi->fullCube) {
// for (double *d = (double *) &bi->boundingBoxes[0], idx = 0; idx < 6; idx++, d++)
// printf("%f ", *d);
@ -952,11 +978,14 @@ int moveEntity(struct entity* entity, double* mx, double* my, double* mz, float
for (int32_t y = floor(obb.minY); y < floor(obb.maxY + 1.); y++) {
block b = getBlockWorld_guess(entity->world, ch, x, y, z);
if (b == 0) continue;
b = entity_adjustCollision(entity->world, ch, b, x, y, z);
b = entity_adjustCollision(entity->world, entity, ch, b, x, y, z);
struct block_info* bi = getBlockInfo(b);
if (bi == NULL) continue;
for (size_t i = 0; i < bi->boundingBox_count; i++) {
struct boundingbox* bb = &bi->boundingBoxes[i];
struct boundingbox* bbx = &bi->boundingBoxes[i];
struct boundingbox bbd;
struct boundingbox* bb = &bbd;
entity_adjustBoundingBox(entity->world, entity, ch, b, x, y, z, bbx, &bbd);
if (bb != NULL && bb->minX != bb->maxX && bb->minY != bb->maxY && bb->minZ != bb->maxZ) {
if (bb->maxX + x > obb.minX && bb->minX + x < obb.maxX ? (bb->maxY + y > obb.minY && bb->minY + y < obb.maxY ? bb->maxZ + z > obb.minZ && bb->minZ + z < obb.maxZ : 0) : 0) {
if (pbb.maxY > bb->minY + y && pbb.minY < bb->maxY + y && pbb.maxZ > bb->minZ + z && pbb.minZ < bb->maxZ + z) {
@ -988,11 +1017,14 @@ int moveEntity(struct entity* entity, double* mx, double* my, double* mz, float
for (int32_t y = floor(obb.minY); y < floor(obb.maxY + 1.); y++) {
block b = getBlockWorld_guess(entity->world, ch, x, y, z);
if (b == 0) continue;
b = entity_adjustCollision(entity->world, ch, b, x, y, z);
b = entity_adjustCollision(entity->world, entity, ch, b, x, y, z);
struct block_info* bi = getBlockInfo(b);
if (bi == NULL) continue;
for (size_t i = 0; i < bi->boundingBox_count; i++) {
struct boundingbox* bb = &bi->boundingBoxes[i];
struct boundingbox* bbx = &bi->boundingBoxes[i];
struct boundingbox bbd;
struct boundingbox* bb = &bbd;
entity_adjustBoundingBox(entity->world, entity, ch, b, x, y, z, bbx, &bbd);
if (bb != NULL && bb->minX != bb->maxX && bb->minY != bb->maxY && bb->minZ != bb->maxZ) {
if (bb->maxX + x > obb.minX && bb->minX + x < obb.maxX ? (bb->maxY + y > obb.minY && bb->minY + y < obb.maxY ? bb->maxZ + z > obb.minZ && bb->minZ + z < obb.maxZ : 0) : 0) {
if (pbb.maxX > bb->minX + x && pbb.minX < bb->maxX + x && pbb.maxY > bb->minY + y && pbb.minY < bb->maxY + y) {

View File

@ -198,7 +198,7 @@ int onItemInteract_minecart(struct world* world, struct player* player, uint8_t
}
int onItemInteract_door(struct world* world, struct player* player, uint8_t slot_index, struct slot* slot, int32_t x, int32_t y, int32_t z, uint8_t face) {
int onItemInteract_door(struct world* world, struct player* player, uint8_t slot_index, struct slot* slot, int32_t x, int32_t y, int32_t z, uint8_t face, float cx, float cy, float cz) {
if (face != YP) return 0;
if (!getBlockInfo(getBlockWorld(world, x, y, z))->material->replacable) offsetCoordByFace(&x, &y, &z, face);
block pre = getBlockWorld(world, x, y, z);
@ -206,15 +206,19 @@ int onItemInteract_door(struct world* world, struct player* player, uint8_t slot
block b = BLK_DOOROAK;
if (slot->item == ITM_DOORSPRUCE) b = BLK_DOORSPRUCE;
else if (slot->item == ITM_DOORBIRCH) b = BLK_DOORBIRCH;
else if (slot->item == ITM_DOORJUNGLE) b = ITM_DOORJUNGLE;
else if (slot->item == ITM_DOORACACIA) b = ITM_DOORACACIA;
else if (slot->item == ITM_DOORDARKOAK) b = ITM_DOORDARKOAK;
else if (slot->item == ITM_DOORIRON) b = ITM_DOORIRON;
else if (slot->item == ITM_DOORJUNGLE) b = BLK_DOORJUNGLE;
else if (slot->item == ITM_DOORACACIA) b = BLK_DOORACACIA;
else if (slot->item == ITM_DOORDARKOAK) b = BLK_DOORDARKOAK;
else if (slot->item == ITM_DOORIRON) b = BLK_DOORIRON;
block b2 = b;
uint32_t h = (uint32_t) floor(player->entity->yaw / 90. + .5) & 3;
if (h == 0) b |= 1;
else if (h == 1) b |= 2;
else if (h == 2) b |= 3;
else if (h == 2) b |= 3; // should fold into "f" below
uint8_t f = getFaceFromPlayer(player);
if ((f == XN && cz < .5) || (f == XP && cz > .5) || (f == ZN && cx > .5) || (f == ZP && cx < .5)) {
b2 |= 0x01;
}
b2 |= 0b1000;
if (canPlayerPlaceBlock(player, b, x, y, z, face) && !setBlockWorld_noupdate(player->world, b, x, y, z)) {
if (!canPlayerPlaceBlock(player, b2, x, y + 1, z, face) || setBlockWorld(player->world, b2, x, y + 1, z)) {

View File

@ -264,7 +264,7 @@ struct item_info {
int (*canUseItem)(struct world* world, struct player* player, uint8_t slot_index, struct slot* slot);
void (*onItemUseTick)(struct world* world, struct player* player, uint8_t slot_index, struct slot* slot, int32_t ticksElapsed); // not in-world usage, nor called on last tick. ticksElapsed==0 on start., -1 on cancel
void (*onItemUse)(struct world* world, struct player* player, uint8_t slot_index, struct slot* slot, uint32_t ticks); // not in-world usage, when called with long use items, full duration not guaranteed
int (*onItemInteract)(struct world* world, struct player* player, uint8_t slot_index, struct slot* slot, int32_t x, int32_t y, int32_t z, uint8_t face); // in-world usage, called after onItemUse
int (*onItemInteract)(struct world* world, struct player* player, uint8_t slot_index, struct slot* slot, int32_t x, int32_t y, int32_t z, uint8_t face, float cx, float cy, float cz); // in-world usage, called after onItemUse
int (*onItemBreakBlock)(struct world* world, struct player* player, uint8_t slot_index, struct slot* slot, int32_t x, int32_t y, int32_t z); // in-world usage
float (*onItemAttacked)(struct world* world, struct player* player, uint8_t slot_index, struct slot* slot, struct entity* entity); // entity may be NULL
float (*onEntityHitWhileWearing)(struct world* world, struct player* player, uint8_t slot_index, struct slot* slot, float damage); // only called for armor/shields

View File

@ -468,7 +468,7 @@ void player_receive_packet(struct player* player, struct packet* inp) {
struct item_info* ii = getItemInfo(ci->item);
if (ii != NULL && ii->onItemInteract != NULL) {
pthread_mutex_unlock(&player->inventory->mut);
if ((*ii->onItemInteract)(player->world, player, player->currentItem + 36, ci, x, y, z, face)) goto pbp_cont;
if ((*ii->onItemInteract)(player->world, player, player->currentItem + 36, ci, x, y, z, face, inp->data.play_server.playerblockplacement.cursor_position_x, inp->data.play_server.playerblockplacement.cursor_position_y, inp->data.play_server.playerblockplacement.cursor_position_z)) goto pbp_cont;
pthread_mutex_lock(&player->inventory->mut);
ci = getSlot(player, player->inventory, 36 + player->currentItem);
}