entity refactoring

This commit is contained in:
Protryon 2019-05-04 19:38:57 -07:00
parent 749cc72b59
commit 6f2a750652
7 changed files with 206 additions and 229 deletions

View File

@ -455,7 +455,7 @@ void entitymeta_read(struct entity* ent, uint8_t* meta, size_t size);
void entitymeta_write(struct entity* entity, uint8_t** data, size_t* size, struct mempool* pool);
void updateMetadata(struct entity* ent);
void entity_broadcast_metadata(struct entity* entity);
void entity_jump(struct entity* entity);
@ -471,12 +471,8 @@ double entity_dist_block(struct entity* ent1, double x, double y, double z);
void entity_collision_bounding_box(struct entity* entity, struct boundingbox* bb);
int moveEntity(struct entity* entity, double* mx, double* my, double* mz, float shrink);
int tick_itemstack(struct world* world, struct entity* entity);
int entity_move(struct entity* entity, double* motionX, double* motionY, double* motionZ, float shrink);
void tick_entity(struct world* world, struct entity* entity);
void freeEntity(struct entity* entity);
#endif /* BASIN_ENTITY_H_ */

View File

@ -1,7 +1,11 @@
#ifndef BASIN_ENTITY_IMPL_H
#define BASIN_ENTITY_IMPL_H
#include "entity_impl.h"
#include <basin/world.h>
#include <basin/entity.h>
#include <basin/player.h>
#include <basin/inventory.h>
#include <stdint.h>
void onSpawned_minecart(struct world* world, struct entity* entity);

View File

@ -17,7 +17,7 @@ void player_openInventory(struct player* player, struct inventory* inv);
float game_rand_float();
void playSound(struct world* world, int32_t soundID, int32_t soundCategory, float x, float y, float z, float volume, float pitch);
void playSound(struct world* world, int32_t soundID, int32_t soundCategory, double x, double y, double z, float volume, float pitch);
void dropPlayerItem(struct player* player, struct slot* drop);

View File

@ -450,46 +450,45 @@ void entitymeta_write(struct entity* entity, uint8_t** data, size_t* size, struc
(*data)[(*size)++] = 0xFF;
}
void updateMetadata(struct entity* ent) {
BEGIN_BROADCAST(ent->loadingPlayers)
struct packet* pkt = xmalloc(sizeof(struct packet));
pkt->id = PKT_PLAY_CLIENT_ENTITYMETADATA;
pkt->data.play_client.entitymetadata.entity_id = ent->id;
entitymeta_write(ent, &pkt->data.play_client.entitymetadata.metadata.metadata, &pkt->data.play_client.entitymetadata.metadata.metadata_size);
add_queue(bc_player->outgoing_packets, pkt);
END_BROADCAST(ent->loadingPlayers)
void entity_broadcast_metadata(struct entity* entity) {
BEGIN_BROADCAST(entity->loadingPlayers)
struct packet* packet = packet_new(mempool_new(), PKT_PLAY_CLIENT_ENTITYMETADATA);
packet->data.play_client.entitymetadata.entity_id = entity->id;
entitymeta_write(entity, &packet->data.play_client.entitymetadata.metadata.metadata, &packet->data.play_client.entitymetadata.metadata.metadata_size, packet->pool);
queue_push(bc_player->outgoing_packets, packet);
END_BROADCAST(entity->loadingPlayers)
}
int getSwingTime(struct entity* ent) {
for (size_t i = 0; i < ent->effect_count; i++) {
if (ent->effects[i].effectID == 3) {
return 6 - (1 + ent->effects[i].amplifier);
} else if (ent->effects[i].effectID == 4) {
return 6 + (1 + ent->effects[i].amplifier) * 2;
int entity_swing_time(struct entity* entity) {
for (size_t i = 0; i < entity->effect_count; i++) {
if (entity->effects[i].effectID == 3) {
return 6 - (1 + entity->effects[i].amplifier);
} else if (entity->effects[i].effectID == 4) {
return 6 + (1 + entity->effects[i].amplifier) * 2;
}
}
return 6;
}
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 world_get_block_guess(world, ch, x, y - 1, z);
block entity_adjustCollision(struct world* world, struct entity* entity, struct chunk* chunk, block block, int32_t x, int32_t y, int32_t z) {
if (block >> 4 == BLK_DOORIRON >> 4 || block >> 4 == BLK_DOOROAK >> 4 || block >> 4 == BLK_DOORSPRUCE >> 4 || block >> 4 == BLK_DOORBIRCH >> 4 || block >> 4 == BLK_DOORJUNGLE >> 4 || block >> 4 == BLK_DOORACACIA >> 4 || block >> 4 == BLK_DOORDARKOAK >> 4) {
if (block & 0b1000) return world_get_block_guess(world, chunk, x, y - 1, z);
}
return b;
return block;
}
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) {
void entity_adjustBoundingBox(struct world* world, struct entity* entity, struct chunk* ch, block block, 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 = world_get_block_guess(world, ch, x, y - 1, z);
if (block >> 4 == BLK_DOORIRON >> 4 || block >> 4 == BLK_DOOROAK >> 4 || block >> 4 == BLK_DOORSPRUCE >> 4 || block >> 4 == BLK_DOORBIRCH >> 4 || block >> 4 == BLK_DOORJUNGLE >> 4 || block >> 4 == BLK_DOORACACIA >> 4 || block >> 4 == BLK_DOORDARKOAK >> 4) {
block low_block = block;
block high_block = block;
if (block & 0b1000) {
low_block = world_get_block_guess(world, ch, x, y - 1, z);
} else {
ub = world_get_block_guess(world, ch, x, y + 1, z);
high_block = world_get_block_guess(world, ch, x, y + 1, z);
}
if ((lb & 0b0010) && (ub & 0b0001)) {
uint8_t face = lb & 0b0011;
if ((low_block & 0b0010) && (high_block & 0b0001)) {
uint8_t face = (uint8_t) (low_block & 0b0011);
if (face == 3 || face == 1) {
out->maxZ = 1. - in->maxZ;
out->minZ = 1. - in->minZ;
@ -501,14 +500,14 @@ void entity_adjustBoundingBox(struct world* world, struct entity* ent, struct ch
}
}
int moveEntity(struct entity* entity, double* mx, double* my, double* mz, float shrink) {
int entity_move(struct entity* entity, double* motionX, double* motionY, double* motionZ, float shrink) {
if (entity->immovable) return 0;
struct boundingbox obb;
entity_collision_bounding_box(entity, &obb);
if (entity->type == ENT_ARROW || entity->type == ENT_SPECTRALARROW || obb.minX == obb.maxX || obb.minZ == obb.maxZ || obb.minY == obb.maxY) {
entity->x += *mx;
entity->y += *my;
entity->z += *mz;
entity->x += *motionX;
entity->y += *motionY;
entity->z += *motionZ;
return 0;
}
obb.minX += shrink;
@ -517,20 +516,20 @@ int moveEntity(struct entity* entity, double* mx, double* my, double* mz, float
obb.maxY -= shrink;
obb.minZ += shrink;
obb.maxZ -= shrink;
if (*mx < 0.) {
obb.minX += *mx;
if (*motionX < 0.) {
obb.minX += *motionX;
} else {
obb.maxX += *mx;
obb.maxX += *motionX;
}
if (*my < 0.) {
obb.minY += *my;
if (*motionY < 0.) {
obb.minY += *motionY;
} else {
obb.maxY += *my;
obb.maxY += *motionY;
}
if (*mz < 0.) {
obb.minZ += *mz;
if (*motionZ < 0.) {
obb.minZ += *motionZ;
} else {
obb.maxZ += *mz;
obb.maxZ += *motionZ;
}
struct boundingbox pbb;
entity_collision_bounding_box(entity, &pbb);
@ -540,7 +539,7 @@ int moveEntity(struct entity* entity, double* mx, double* my, double* mz, float
pbb.maxY -= shrink;
pbb.minZ += shrink;
pbb.maxZ -= shrink;
double ny = *my;
double ny = *motionY;
struct chunk* ch = world_get_chunk(entity->world, (int32_t) entity->x / 16, (int32_t) entity->z / 16);
for (int32_t x = (int32_t) floor(obb.minX); x < floor(obb.maxX + 1.); x++) {
for (int32_t z = (int32_t) floor(obb.minZ); z < floor(obb.maxZ + 1.); z++) {
@ -580,7 +579,7 @@ int moveEntity(struct entity* entity, double* mx, double* my, double* mz, float
entity->y += ny;
pbb.minY += ny;
pbb.maxY += ny;
double nx = *mx;
double nx = *motionX;
for (int32_t x = (int32_t) floor(obb.minX); x < floor(obb.maxX + 1.); x++) {
for (int32_t z = (int32_t) floor(obb.minZ); z < floor(obb.maxZ + 1.); z++) {
for (int32_t y = (int32_t) floor(obb.minY); y < floor(obb.maxY + 1.); y++) {
@ -619,7 +618,7 @@ int moveEntity(struct entity* entity, double* mx, double* my, double* mz, float
entity->x += nx;
pbb.minX += nx;
pbb.maxX += nx;
double nz = *mz;
double nz = *motionZ;
for (int32_t x = (int32_t) floor(obb.minX); x < floor(obb.maxX + 1.); x++) {
for (int32_t z = (int32_t) floor(obb.minZ); z < floor(obb.maxZ + 1.); z++) {
for (int32_t y = (int32_t) floor(obb.minY); y < floor(obb.maxY + 1.); y++) {
@ -659,9 +658,9 @@ int moveEntity(struct entity* entity, double* mx, double* my, double* mz, float
entity->z += nz;
pbb.minZ += nz;
pbb.maxZ += nz;
entity->collidedHorizontally = *mx != nx || *mz != nz;
entity->collidedVertically = *my != ny;
entity->on_ground = entity->collidedVertically && *my < 0.;
entity->collidedHorizontally = *motionX != nx || *motionZ != nz;
entity->collidedVertically = *motionY != ny;
entity->on_ground = entity->collidedVertically && *motionY < 0.;
int32_t bx = (int32_t) floor(entity->x);
int32_t by = (int32_t) floor(entity->y - .20000000298023224);
int32_t bz = (int32_t) floor(entity->z);
@ -674,77 +673,80 @@ int moveEntity(struct entity* entity, double* mx, double* my, double* mz, float
by--;
}
}
if (*mx != nx) *mx = 0.;
if (*mz != nz) *mz = 0.;
if (*my != ny) {
if (*motionX != nx) *motionX = 0.;
if (*motionZ != nz) *motionZ = 0.;
if (*motionY != ny) {
if (lb != BLK_SLIME || entity->sneaking) {
*my = 0.;
*motionY = 0.;
} else {
*my = -(*my);
*motionY = -(*motionY);
}
}
return ny != *my || nx != *mx || nz != *mz;
return ny != *motionY || nx != *motionX || nz != *motionZ;
}
void applyVelocity(struct entity* entity, double x, double y, double z) {
void entity_apply_velocity(struct entity* entity, double x, double y, double z) {
entity->motX += x;
entity->motY += y;
entity->motZ += z;
BEGIN_BROADCAST(entity->loadingPlayers)
struct packet* pkt = xmalloc(sizeof(struct packet));
pkt->id = PKT_PLAY_CLIENT_ENTITYVELOCITY;
pkt->data.play_client.entityvelocity.entity_id = entity->id;
pkt->data.play_client.entityvelocity.velocity_x = (int16_t)(entity->motX * 8000.);
pkt->data.play_client.entityvelocity.velocity_y = (int16_t)(entity->motY * 8000.);
pkt->data.play_client.entityvelocity.velocity_z = (int16_t)(entity->motZ * 8000.);
add_queue(bc_player->outgoing_packets, pkt);
END_BROADCAST(entity->loadingPlayers)
BEGIN_BROADCAST(entity->loadingPlayers) {
struct packet* packet = packet_new(mempool_new(), PKT_PLAY_CLIENT_ENTITYVELOCITY);
packet->data.play_client.entityvelocity.entity_id = entity->id;
packet->data.play_client.entityvelocity.velocity_x = (int16_t) (entity->motX * 8000.);
packet->data.play_client.entityvelocity.velocity_y = (int16_t) (entity->motY * 8000.);
packet->data.play_client.entityvelocity.velocity_z = (int16_t) (entity->motZ * 8000.);
queue_push(bc_player->outgoing_packets, packet);
END_BROADCAST(entity->loadingPlayers)
}
if (entity->type == ENT_PLAYER) {
struct packet* pkt = xmalloc(sizeof(struct packet));
pkt->id = PKT_PLAY_CLIENT_ENTITYVELOCITY;
pkt->data.play_client.entityvelocity.entity_id = entity->id;
pkt->data.play_client.entityvelocity.velocity_x = (int16_t)(entity->motX * 8000.);
pkt->data.play_client.entityvelocity.velocity_y = (int16_t)(entity->motY * 8000.);
pkt->data.play_client.entityvelocity.velocity_z = (int16_t)(entity->motZ * 8000.);
add_queue(entity->data.player.player->outgoing_packets, pkt);
struct packet* packet = packet_new(mempool_new(), PKT_PLAY_CLIENT_ENTITYVELOCITY);
packet->data.play_client.entityvelocity.entity_id = entity->id;
packet->data.play_client.entityvelocity.velocity_x = (int16_t)(entity->motX * 8000.);
packet->data.play_client.entityvelocity.velocity_y = (int16_t)(entity->motY * 8000.);
packet->data.play_client.entityvelocity.velocity_z = (int16_t)(entity->motZ * 8000.);
queue_push(entity->data.player.player->outgoing_packets, packet);
}
}
void applyKnockback(struct entity* entity, float yaw, float strength) {
float kb_resistance = 0.;
void entity_apply_knockback(struct entity* entity, float yaw, float strength) {
float kb_resistance = 0f;
if (game_rand_float() > kb_resistance) {
float xr = sinf(yaw / 360. * 2 * M_PI);
float zr = -cosf(yaw / 360. * 2 * M_PI);
float m = sqrtf(xr * xr + zr * zr);
float x_component = sinf((float) (yaw / 360f * 2f * M_PI));
float z_component = -cosf((float) (yaw / 360f * 2f * M_PI));
float m = sqrtf(x_component * x_component + z_component * z_component);
entity->motX /= 2.;
entity->motZ /= 2.;
entity->motX -= xr / m * strength;
entity->motZ -= zr / m * strength;
entity->motX -= x_component / m * strength;
entity->motZ -= z_component / m * strength;
if (entity->on_ground) {
entity->motY /= 2.;
entity->motY += strength;
if (entity->motY > .4) entity->motY = .4;
}
applyVelocity(entity, 0., 0., 0.);
entity_apply_velocity(entity, 0., 0., 0.);
}
}
int damageEntityWithItem(struct entity* attacked, struct entity* attacker, uint8_t slot_index, struct slot* item) {
if (attacked == NULL || attacked->invincibilityTicks > 0 || !entity_has_flag(entity_get_info(attacked->type), "livingbase") || attacked->health <= 0.) return 0;
if (attacked->type == ENT_PLAYER && attacked->data.player.player->gamemode == 1) return 0;
float damage = 1.;
if (attacked == NULL || attacked->invincibilityTicks > 0 || !hashset_has(attacked->info->flags, "livingbase") || attacked->health <= 0.) {
return 0;
}
if (attacked->type == ENT_PLAYER && attacked->data.player.player->gamemode == 1) {
return 0;
}
float damage = 1f;
if (item != NULL) {
struct item_info* ii = getItemInfo(item->item);
if (ii != NULL) {
damage = ii->damage;
struct item_info* info = getItemInfo(item->item);
if (info != NULL) {
damage = info->damage;
if (attacker->type == ENT_PLAYER) {
if (ii->onItemAttacked != NULL) {
damage = (*ii->onItemAttacked)(attacker->world, attacker->data.player.player, attacker->data.player.player->currentItem + 36, item, attacked);
if (info->onItemAttacked != NULL) {
damage = (*info->onItemAttacked)(attacker->world, attacker->data.player.player, (uint8_t) (attacker->data.player.player->currentItem + 36), item, attacked);
}
}
}
}
float knockback_strength = 1.;
float knockback_strength = 1f;
if (attacker->sprinting) knockback_strength++;
if (attacker->type == ENT_PLAYER) {
struct player* player = attacker->data.player.player;
@ -755,15 +757,18 @@ int damageEntityWithItem(struct entity* attacked, struct entity* attacker, uint8
if (attacker->y > attacked->y && (attacker->last_y - attacker->y) > 0 && !attacker->on_ground && !attacker->sprinting) { // todo water/ladder
damage *= 1.5;
}
BEGIN_HASHMAP_ITERATION (plugins)
struct plugin* plugin = value;
if (plugin->onEntityAttacked != NULL) damage = (*plugin->onEntityAttacked)(attacker->world, attacker, slot_index, item, attacked, damage);
END_HASHMAP_ITERATION (plugins)
if (damage == 0.) return 0;
ITER_MAP(plugins) {
struct plugin* plugin = value;
if (plugin->onEntityAttacked != NULL) damage = (*plugin->onEntityAttacked)(attacker->world, attacker, slot_index, item, attacked, damage);
ITER_MAP_END();
}
if (damage == 0.) {
return 0;
}
damageEntity(attacked, damage, 1);
//TODO: enchantment
knockback_strength *= .2;
applyKnockback(attacked, attacker->yaw, knockback_strength);
entity_apply_knockback(attacked, attacker->yaw, knockback_strength);
if (attacker->type == ENT_PLAYER) {
attacker->data.player.player->foodExhaustion += .1;
}
@ -771,7 +776,7 @@ int damageEntityWithItem(struct entity* attacked, struct entity* attacker, uint8
}
int damageEntity(struct entity* attacked, float damage, int armorable) {
if (attacked == NULL || damage <= 0. || attacked->invincibilityTicks > 0 || !entity_has_flag(entity_get_info(attacked->type), "livingbase") || attacked->health <= 0.) return 0;
if (attacked == NULL || damage <= 0. || attacked->invincibilityTicks > 0 || !hashset_has(attacked->info->flags, "livingbase") || attacked->health <= 0.) return 0;
float armor = 0;
if (attacked->type == ENT_PLAYER) {
struct player* player = attacked->data.player.player;
@ -787,10 +792,10 @@ int damageEntity(struct entity* attacked, float damage, int armorable) {
}
}
if (armorable) {
float f = armor - damage / 2.;
if (f < armor * .2) f = armor * .2;
if (f > 20.) f = 20.;
damage *= 1. - (f) / 25.;
float mod = armor - damage / 2f;
if (mod < armor * .2) mod = armor * .2f;
if (mod > 20.) mod = 20f;
damage *= 1. - mod / 25.;
}
if (attacked->type == ENT_PLAYER) {
struct player* player = attacked->data.player.player;
@ -798,9 +803,9 @@ int damageEntity(struct entity* attacked, float damage, int armorable) {
if (armorable) for (int i = 5; i <= 8; i++) {
struct slot* sl = inventory_get(player, player->inventory, i);
if (sl != NULL) {
struct item_info* ii = getItemInfo(sl->item);
if (ii != NULL && ii->onEntityHitWhileWearing != NULL) {
damage = (*ii->onEntityHitWhileWearing)(player->world, player, i, sl, damage);
struct item_info* info = getItemInfo(sl->item);
if (info != NULL && info->onEntityHitWhileWearing != NULL) {
damage = (*info->onEntityHitWhileWearing)(player->world, player, i, sl, damage);
}
}
}
@ -808,74 +813,68 @@ int damageEntity(struct entity* attacked, float damage, int armorable) {
attacked->health -= damage;
attacked->invincibilityTicks = 10;
if (attacked->type == ENT_PLAYER) {
struct packet* pkt = xmalloc(sizeof(struct packet));
pkt->id = PKT_PLAY_CLIENT_UPDATEHEALTH;
pkt->data.play_client.updatehealth.health = attacked->health;
pkt->data.play_client.updatehealth.food = attacked->data.player.player->food;
pkt->data.play_client.updatehealth.food_saturation = attacked->data.player.player->saturation;
add_queue(attacked->data.player.player->outgoing_packets, pkt);
struct packet* packet = packet_new(mempool_new(), PKT_PLAY_CLIENT_UPDATEHEALTH);
packet->data.play_client.updatehealth.health = attacked->health;
packet->data.play_client.updatehealth.food = attacked->data.player.player->food;
packet->data.play_client.updatehealth.food_saturation = attacked->data.player.player->saturation;
queue_push(attacked->data.player.player->outgoing_packets, packet);
}
if (attacked->health <= 0.) {
if (attacked->type == ENT_PLAYER) {
struct player* player = attacked->data.player.player;
broadcastf("default", "%s died", player->name);
for (size_t i = 0; i < player->inventory->slot_count; i++) {
struct slot* slot = inventory_get(player, player->inventory, i);
struct slot* slot = inventory_get(player, player->inventory, (int) i);
if (slot != NULL) dropEntityItem_explode(player->entity, slot);
inventory_set_slot(player, player->inventory, i, 0, 0, 1);
inventory_set_slot(player, player->inventory, (int) i, 0, 1);
}
if (player->inventory_holding != NULL) {
dropEntityItem_explode(player->entity, player->inventory_holding);
freeSlot(player->inventory_holding);
xfree(player->inventory_holding);
player->inventory_holding = NULL;
}
if (player->open_inventory != NULL) player_closeWindow(player, player->open_inventory->windowID);
if (player->open_inventory != NULL) {
player_closeWindow(player, (uint16_t) player->open_inventory->window);
}
} else {
struct entity_info* ei = entity_get_info(attacked->type);
if (ei != NULL) for (size_t i = 0; i < ei->loot_count; i++) {
struct entity_loot* el = &ei->loots[i];
int amt = el->amountMax == el->amountMin ? el->amountMax : (rand() % (el->amountMax - el->amountMin) + el->amountMin);
if (amt <= 0) continue;
struct slot it;
it.item = el->id;
it.count = amt;
it.damage = el->metaMax == el->metaMin ? el->metaMax : (rand() % (el->metaMax - el->metaMin) + el->metaMin);
it.nbt = NULL;
dropEntityItem_explode(attacked, &it);
struct entity_info* info = entity_get_info(attacked->type);
if (info != NULL) {
for (size_t i = 0; i < info->loot_count; i++) {
struct entity_loot* el = &info->loots[i];
int amt = el->amountMax == el->amountMin ? el->amountMax : (rand() % (el->amountMax - el->amountMin) + el->amountMin);
if (amt <= 0) continue;
struct slot it;
it.item = el->id;
it.count = (unsigned char) amt;
it.damage = (int16_t) (el->metaMax == el->metaMin ? el->metaMax : (rand() % (el->metaMax - el->metaMin) + el->metaMin));
it.nbt = NULL;
dropEntityItem_explode(attacked, &it);
}
}
}
}
BEGIN_BROADCAST_DIST(attacked, 128.)
struct packet* pkt = xmalloc(sizeof(struct packet));
pkt->id = PKT_PLAY_CLIENT_ANIMATION;
pkt->data.play_client.animation.entity_id = attacked->id;
pkt->data.play_client.animation.animation = 1;
add_queue(bc_player->outgoing_packets, pkt);
entity_animation(attacked, 1);
if (attacked->health <= 0.) {
pkt = xmalloc(sizeof(struct packet));
pkt->id = PKT_PLAY_CLIENT_ENTITYMETADATA;
pkt->data.play_client.entitymetadata.entity_id = attacked->id;
entitymeta_write(attacked, &pkt->data.play_client.entitymetadata.metadata.metadata, &pkt->data.play_client.entitymetadata.metadata.metadata_size);
add_queue(bc_player->outgoing_packets, pkt);
entity_broadcast_metadata(attacked);
}
END_BROADCAST(attacked->world->players)
if (attacked->type == ENT_PLAYER) playSound(attacked->world, 316, 8, attacked->x, attacked->y, attacked->z, 1., 1.);
if (attacked->type == ENT_PLAYER) playSound(attacked->world, 316, 8, attacked->x, attacked->y, attacked->z, 1f, 1f);
return 1;
}
void healEntity(struct entity* healed, float amount) {
if (healed == NULL || amount <= 0. || healed->health <= 0. || !entity_has_flag(entity_get_info(healed->type), "livingbase")) return;
float oh = healed->health;
if (healed == NULL || amount <= 0. || healed->health <= 0. || !hashset_has(healed->info->flags, "livingbase")) {
return;
}
float original_health = healed->health;
healed->health += amount;
if (healed->health > healed->maxHealth) healed->health = 20.;
if (healed->type == ENT_PLAYER && oh != healed->health) {
struct packet* pkt = xmalloc(sizeof(struct packet));
pkt->id = PKT_PLAY_CLIENT_UPDATEHEALTH;
pkt->data.play_client.updatehealth.health = healed->health;
pkt->data.play_client.updatehealth.food = healed->data.player.player->food;
pkt->data.play_client.updatehealth.food_saturation = healed->data.player.player->saturation;
add_queue(healed->data.player.player->outgoing_packets, pkt);
if (healed->health > healed->maxHealth) {
healed->health = 20f;
}
if (healed->type == ENT_PLAYER && original_health != healed->health) {
struct packet* packet = packet_new(mempool_new(), PKT_PLAY_CLIENT_UPDATEHEALTH);
packet->data.play_client.updatehealth.health = healed->health;
packet->data.play_client.updatehealth.food = healed->data.player.player->food;
packet->data.play_client.updatehealth.food_saturation = healed->data.player.player->saturation;
queue_push(healed->data.player.player->outgoing_packets, packet);
}
}
@ -914,7 +913,6 @@ int entity_inFluid(struct entity* entity, uint16_t blk, float ydown, int meta_ch
return 0;
}
int entity_inBlock(struct entity* ent, block blk) { // blk = 0 for any block
struct boundingbox obb;
entity_collision_bounding_box(ent, &obb);
@ -951,8 +949,10 @@ int entity_inBlock(struct entity* ent, block blk) { // blk = 0 for any block
return 0;
}
void pushOutOfBlocks(struct entity* ent) {
if (!entity_inBlock(ent, 0)) return;
void entity_push_out_of_blocks(struct entity* ent) {
if (!entity_inBlock(ent, 0)) {
return;
}
struct boundingbox ebb;
entity_collision_bounding_box(ent, &ebb);
double x = ent->x;
@ -965,40 +965,40 @@ void pushOutOfBlocks(struct entity* ent) {
double dy = y - (double) by;
double dz = z - (double) bz;
double ld = 100.;
float fbx = 0.;
float fby = 0.;
float fbz = 0.;
float fbx = 0f;
float fby = 0f;
float fbz = 0f;
if (dx < ld && !isNormalCube(getBlockInfo(world_get_block(ent->world, bx - 1, by, bz)))) {
ld = dx;
fbx = -1.;
fby = 0.;
fbz = 0.;
fbx = -1f;
fby = 0f;
fbz = 0f;
}
if ((1. - dx) < ld && !isNormalCube(getBlockInfo(world_get_block(ent->world, bx + 1, by, bz)))) {
ld = 1. - dx;
fbx = 1.;
fby = 0.;
fbz = 0.;
fbx = 1f;
fby = 0f;
fbz = 0f;
}
if (dz < ld && !isNormalCube(getBlockInfo(world_get_block(ent->world, bx, by, bz - 1)))) {
ld = dx;
fbx = 0.;
fby = 0.;
fbz = -1.;
fbx = 0f;
fby = 0f;
fbz = -1f;
}
if ((1. - dz) < ld && !isNormalCube(getBlockInfo(world_get_block(ent->world, bx, by, bz + 1)))) {
ld = 1. - dz;
fbx = 0.;
fby = 0.;
fbz = 1.;
fbx = 0f;
fby = 0f;
fbz = 1f;
}
if ((1. - dy) < ld && !isNormalCube(getBlockInfo(world_get_block(ent->world, bx, by + 1, bz)))) {
ld = 1. - dy;
fbx = 0.;
fby = 1.;
fbz = 0.;
fbx = 0f;
fby = 1f;
fbz = 0f;
}
float mag = game_rand_float() * .2 + .1;
float mag = game_rand_float() * .2f + .1f;
if (fbx == 0. && fbz == 0.) {
ent->motX *= .75;
ent->motY = mag * fby;
@ -1038,13 +1038,11 @@ void tick_entity(struct world* world, struct entity* entity) {
}
}
if (entity->type > ENT_PLAYER) {
if (entity->motX != 0. || entity->motY != 0. || entity->motZ != 0.) moveEntity(entity, &entity->motX, &entity->motY, &entity->motZ, 0.);
if (entity->motX != 0. || entity->motY != 0. || entity->motZ != 0.) entity_move(entity, &entity->motX, &entity->motY, &entity->motZ, 0.);
double gravity = 0.;
int ar = entity->type == ENT_ARROW || entity->type == ENT_SPECTRALARROW;
int is_arrow = entity->type == ENT_ARROW || entity->type == ENT_SPECTRALARROW;
float friction = .98;
if (ar) {
//printf("ymot %f pit %f\n", entity->motY, entity->pitch);
//printf("af %.17f, %.17f --- %.17f, %.17f, %.17f\n", entity->yaw, entity->pitch, entity->motX, entity->motY, entity->motZ);
if (is_arrow) {
friction = .99;
if (entity->inWater) friction = .6;
entity->motX *= friction;
@ -1052,8 +1050,8 @@ void tick_entity(struct world* world, struct entity* entity) {
entity->motZ *= friction;
}
if (entity->type == ENT_ITEM) gravity = .04;
else if (ar) gravity = .05;
else if (entity_has_flag(entity_get_info(entity->type), "livingbase")) {
else if (is_arrow) gravity = .05;
else if (hashset_has(entity->info->flags, "livingbase")) {
if (entity->inLava) {
entity->motX *= .5;
entity->motY *= .5;
@ -1072,7 +1070,7 @@ void tick_entity(struct world* world, struct entity* entity) {
gravity = .04;
}
if (gravity != 0. && !entity->immovable) entity->motY -= gravity;
if (!ar) {
if (!is_arrow) {
if (entity->on_ground) {
struct block_info* bi = getBlockInfo(world_get_block(entity->world, (int32_t) floor(entity->x), (int32_t) floor(entity->y) - 1, (int32_t) floor(entity->z)));
if (bi != NULL) friction = bi->slipperiness * .98;
@ -1086,28 +1084,27 @@ void tick_entity(struct world* world, struct entity* entity) {
if (fabs(entity->motZ) < .0001) entity->motZ = 0.;
if (entity->type == ENT_ITEM && entity->on_ground && entity->motX == 0. && entity->motY == 0. && entity->motZ == 0.) entity->motY *= -.5;
}
if (entity->type == ENT_ITEM || entity->type == ENT_XPORB) pushOutOfBlocks(entity);
if (entity_has_flag(entity_get_info(entity->type), "livingbase")) {
entity->inWater = entity_inFluid(entity, BLK_WATER, .2, 0) || entity_inFluid(entity, BLK_WATER_1, .2, 0);
entity->inLava = entity_inFluid(entity, BLK_LAVA, .2, 0) || entity_inFluid(entity, BLK_LAVA_1, .2, 0);
if ((entity->inWater || entity->inLava) && entity->type == ENT_PLAYER) entity->data.player.player->llTick = tick_counter;
if (entity->type == ENT_ITEM || entity->type == ENT_XPORB) entity_push_out_of_blocks(entity);
if (hashset_has(entity->info->flags, "livingbase")) {
entity->inWater = (uint8_t) (entity_inFluid(entity, BLK_WATER, .2, 0) || entity_inFluid(entity, BLK_WATER_1, .2, 0));
entity->inLava = (uint8_t) (entity_inFluid(entity, BLK_LAVA, .2, 0) || entity_inFluid(entity, BLK_LAVA_1, .2, 0));
//TODO: ladders
if (entity->type == ENT_PLAYER && entity->data.player.player->gamemode == 1) goto bfd;
if (entity->inLava) {
damageEntity(entity, 4., 1);
//TODO: fire
damageEntity(entity, 4f, 1);
//TODO: fire
}
if (!entity->on_ground) {
float dy = entity->last_y - entity->y;
double dy = entity->last_y - entity->y;
if (dy > 0.) {
entity->fallDistance += dy;
}
} else if (entity->fallDistance > 0.) {
if (entity->fallDistance > 3. && !entity->inWater && !entity->inLava) {
damageEntity(entity, entity->fallDistance - 3., 0);
playSound(entity->world, 312, 8, entity->x, entity->y, entity->z, 1., 1.);
damageEntity(entity, entity->fallDistance - 3f, 0);
playSound(entity->world, 312, 8, entity->x, entity->y, entity->z, 1f, 1f);
}
entity->fallDistance = 0.;
entity->fallDistance = 0f;
}
bfd: ;
}
@ -1115,33 +1112,13 @@ void tick_entity(struct world* world, struct entity* entity) {
double md = entity_distsq_block(entity, entity->last_x, entity->last_y, entity->last_z);
double mp = (entity->yaw - entity->last_yaw) * (entity->yaw - entity->last_yaw) + (entity->pitch - entity->last_pitch) * (entity->pitch - entity->last_pitch);
if (md > .001 || mp > .01) {
BEGIN_HASHMAP_ITERATION(entity->loadingPlayers);
player_send_entity_move(value, entity);
END_HASHMAP_ITERATION(entity->loadingPlayers);
pthread_rwlock_rdlock(&entity->loadingPlayers->rwlock);
ITER_MAP(entity->loadingPlayers) {
player_send_entity_move(value, entity);
ITER_MAP_END();
}
pthread_rwlock_unlock(&entity->loadingPlayers->rwlock);
}
}
/*int32_t chunk_x = ((int32_t) entity->x) >> 4;
int32_t chunk_z = ((int32_t) entity->z) >> 4;
int32_t lcx = ((int32_t) entity->lx) >> 4;
int32_t lcz = ((int32_t) entity->lz) >> 4;
if (chunk_x != lcx || chunk_z != lcz) {
struct chunk* lch = getChunk(entity->world, lcx, lcz);
struct chunk* cch = world_get_chunk(entity->world, chunk_x, chunk_z);
put_hashmap(lch->entities, entity->id, NULL);
put_hashmap(cch->entities, entity->id, entity);
}*/
}
void freeEntity(struct entity* entity) {
del_hashmap(entity->loadingPlayers);
if (entity->type == ENT_ITEM) {
if (entity->data.itemstack.slot != NULL) {
freeSlot(entity->data.itemstack.slot);
xfree(entity->data.itemstack.slot);
}
}
if (entity->type == ENT_PAINTING) {
if (entity->data.painting.title != NULL) xfree(entity->data.painting.title);
}
xfree(entity);
}

View File

@ -209,7 +209,7 @@ void dropPlayerItem(struct player* player, struct slot* drop) {
END_BROADCAST(player->world->players)
}
void playSound(struct world* world, int32_t soundID, int32_t soundCategory, float x, float y, float z, float volume, float pitch) {
void playSound(struct world* world, int32_t soundID, int32_t soundCategory, double x, double y, double z, float volume, float pitch) {
BEGIN_BROADCAST_DISTXYZ(x, y, z, world->players, 64.)
struct packet* pkt = xmalloc(sizeof(struct packet));
pkt->id = PKT_PLAY_CLIENT_SOUNDEFFECT;

View File

@ -303,13 +303,13 @@ void player_tick(struct player* player) {
player->itemUseDuration = 0;
player->entity->usingItemMain = 0;
player->entity->usingItemOff = 0;
updateMetadata(player->entity);
entity_broadcast_metadata(player->entity);
} else if (ihi->maxUseDuration <= player->itemUseDuration) {
if (ihi->onItemUse != NULL) (*ihi->onItemUse)(player->world, player, (uint8_t) (player->itemUseHand ? 45 : (36 + player->currentItem)), ihs, player->itemUseDuration);
player->itemUseDuration = 0;
player->entity->usingItemMain = 0;
player->entity->usingItemOff = 0;
updateMetadata(player->entity);
entity_broadcast_metadata(player->entity);
} else {
if (ihi->onItemUseTick != NULL) (*ihi->onItemUseTick)(player->world, player, (uint8_t) (player->itemUseHand ? 45 : (36 + player->currentItem)), ihs, player->itemUseDuration);
player->itemUseDuration++;

View File

@ -624,7 +624,7 @@ void player_packet_handle_playerposition(struct player* player, struct mempool*
double moveX = packet->x - lastX;
double moveY = packet->feet_y - lastY;
double moveZ = packet->z - lastZ;
if (moveEntity(player->entity, &moveX, &moveY, &moveZ, .05)) {
if (entity_move(player->entity, &moveX, &moveY, &moveZ, .05)) {
player_teleport(player, lastX, lastY, lastZ);
} else {
player->entity->last_x = lastX;
@ -660,7 +660,7 @@ void player_packet_handle_playerpositionandlook(struct player* player, struct me
double moveX = packet->x - lastX;
double moveY = packet->feet_y - lastY;
double moveZ = packet->z - lastZ;
if (moveEntity(player->entity, &moveX, &moveY, &moveZ, .05)) {
if (entity_move(player->entity, &moveX, &moveY, &moveZ, .05)) {
player_teleport(player, lastX, lastY, lastZ);
} else {
player->entity->last_x = lastX;
@ -861,13 +861,13 @@ void player_packet_handle_playerdigging(struct player* player, struct mempool* p
player->itemUseDuration = 0;
player->entity->usingItemMain = 0;
player->entity->usingItemOff = 0;
updateMetadata(player->entity);
entity_broadcast_metadata(player->entity);
}
if (item_info != NULL && item_info->onItemUse != NULL) (*item_info->onItemUse)(player->world, player, player->itemUseHand ? 45 : (36 + player->currentItem), item_in_hand, player->itemUseDuration);
player->entity->usingItemMain = 0;
player->entity->usingItemOff = 0;
player->itemUseDuration = 0;
updateMetadata(player->entity);
entity_broadcast_metadata(player->entity);
}
pthread_mutex_unlock(&player->inventory->mutex);
} else if (packet->status == 6) {
@ -881,7 +881,7 @@ void player_packet_handle_entityaction(struct player* player, struct mempool* po
else if (packet->action_id == 1) player->entity->sneaking = 0;
else if (packet->action_id == 3) player->entity->sprinting = 1;
else if (packet->action_id == 4) player->entity->sprinting = 0;
updateMetadata(player->entity);
entity_broadcast_metadata(player->entity);
}
void player_packet_handle_steervehicle(struct player* player, struct mempool* pool, struct pkt_play_server_steervehicle* packet) {
@ -1061,7 +1061,7 @@ void player_packet_handle_useitem(struct player* player, struct mempool* pool, s
player->itemUseHand = (uint8_t) (packet->hand ? 1 : 0);
player->entity->usingItemMain = !player->itemUseHand;
player->entity->usingItemOff = player->itemUseHand;
updateMetadata(player->entity);
entity_broadcast_metadata(player->entity);
}
}
}