2021-08-10 08:55:19 +00:00

253 lines
5.7 KiB
C++

#include "precompile.h"
#include "entity.h"
#include "collider.h"
#include "room.h"
#include "building.h"
#include "human.h"
#include "app.h"
#include "perfmonitor.h"
Entity::Entity()
{
entity_weak_ptr_chunk_.Set(this);
}
Entity::~Entity()
{
ClearColliders();
}
void Entity::Initialize()
{
}
void Entity::GetAabbBox(AabbCollider& aabb_box)
{
aabb_box.active = true;
aabb_box.owner = this;
}
void Entity::GetCircleBox(CircleCollider& circle_box)
{
circle_box.active = true;
circle_box.owner = this;
circle_box.rad = 1;
}
bool Entity::TestCollision(Room* room, Entity* b)
{
PerfMonitor::Instance()->test_times++;
if (b->IsDead(room)) {
return false;
}
OnPreCollision(room);
b->OnPreCollision(room);
for (auto& a_collider : colliders_) {
for (auto& b_collider : b->colliders_) {
if (a_collider->Intersect(b_collider)) {
return true;
}
}
}
return false;
}
ColliderComponent* Entity::TestCollisionAndGetCollider(Room* room, Entity* b)
{
PerfMonitor::Instance()->test_times++;
if (b->IsDead(room)) {
return nullptr;
}
OnPreCollision(room);
b->OnPreCollision(room);
for (auto& a_collider : colliders_) {
for (auto& b_collider : b->colliders_) {
if (a_collider->Intersect(b_collider)) {
return b_collider;
}
}
}
return nullptr;
}
bool Entity::TestCollision(Room* room, ColliderComponent* b)
{
if (b->owner->IsDead(room)) {
return false;
}
OnPreCollision(room);
b->owner->OnPreCollision(room);
for (auto& a_collider : colliders_) {
if (a_collider->Intersect(b)) {
return true;
}
}
return false;
}
ColliderComponent* Entity::TestCollisionAndGetCollider(Room* room, ColliderComponent* b)
{
if (b->owner->IsDead(room)) {
return nullptr;
}
OnPreCollision(room);
b->owner->OnPreCollision(room);
for (auto& a_collider : colliders_) {
if (a_collider->Intersect(b)) {
return a_collider;
}
}
return nullptr;
}
bool Entity::TestCollisionEx(Room* room, const a8::Vec2& aabb_pos, AabbCollider& aabb_box)
{
OnPreCollision(room);
if (aabb_box.owner) {
aabb_box.owner->OnPreCollision(room);
}
for (auto& a_collider : colliders_) {
if (a_collider->IntersectEx(aabb_pos, &aabb_box)) {
return true;
}
}
return false;
}
void Entity::ClearColliders()
{
for (auto& itr : colliders_) {
ColliderComponent* collider = itr;
DestoryCollider(collider);
}
colliders_.clear();
}
void Entity::BroadcastFullState(Room* room)
{
std::set<GridCell*> tmp_grids;
room->grid_service->GetAllCells(room, grid_id_, tmp_grids);
room->grid_service->TraverseAllLayerHumanList
(
room->GetRoomIdx(),
tmp_grids,
[this] (Human* hum, bool& stop)
{
hum->AddToNewObjects(this);
});
}
void Entity::BroadcastDeleteState(Room* room)
{
#if 0
room->TraverseHumanList
(
a8::XParams(),
[this] (Human* hum, a8::XParams& param) -> bool
{
hum->RemoveObjects(this);
return true;
});
#else
std::set<GridCell*> tmp_grids;
room->grid_service->GetAllCells(room, grid_id_, tmp_grids);
room->grid_service->TraverseAllLayerHumanList
(
room->GetRoomIdx(),
tmp_grids,
[this] (Human* hum, bool& stop)
{
hum->RemoveObjects(this);
});
#endif
}
void Entity::RemoveFromAroundPlayers(Room* room)
{
#if 1
room->TraverseHumanList
(
a8::XParams(),
[this] (Human* hum, a8::XParams& param) -> bool
{
hum->RemovePartObjects(this);
return true;
});
#else
std::set<GridCell*> tmp_grids;
room->grid_service->GetAllCells(room, grid_id_, tmp_grids);
room->grid_service->TraverseAllLayerHumanList
(
room->GetRoomIdx(),
tmp_grids,
[this] (Human* hum, bool& stop)
{
hum->RemovePartObjects(this);
});
#endif
}
void Entity::AddEntityCollider(ColliderComponent* collider)
{
colliders_.push_back(collider);
}
bool Entity::IsClientCached(Human* hum)
{
ObjectSyncFlags* sync_flags = hum->GetObjectSyncFlags(GetUniId());
if (sync_flags) {
int flags = sync_flags->flags;
if (IsDead(hum->room)) {
if (a8::HasBitFlag(flags, kOsfIsDead)) {
return sync_flags->last_sync_frameno > 0;
} else {
return false;
}
} else {
if (!a8::HasBitFlag(flags, kOsfIsDead)) {
return sync_flags->last_sync_frameno > 0;
} else {
return false;
}
}
}
return false;
}
bool Entity::CanClientCache(Human* hum)
{
ObjectSyncFlags* sync_flags = hum->GetObjectSyncFlags(GetUniId());
return sync_flags != nullptr;
}
void Entity::AddClientCache(Human* hum)
{
ObjectSyncFlags* sync_flags = hum->GetObjectSyncFlags(GetUniId());
if (sync_flags) {
int flags = sync_flags->flags;
if (IsDead(hum->room)) {
a8::SetBitFlag(flags, kOsfIsDead);
} else {
a8::UnSetBitFlag(flags, kOsfIsDead);
}
sync_flags->flags = flags;
sync_flags->last_sync_frameno = hum->room->GetFrameNo();
}
}
EntityWeakPtr Entity::AllocEntityWeakPtr()
{
EntityWeakPtr ptr;
ptr.Attach(this);
return ptr;
}
EntityWeakPtr& Entity::GetEntityWeakPtrRef()
{
if (!entity_weak_ptr_.Get()) {
entity_weak_ptr_.Attach(this);
}
return entity_weak_ptr_;
}