Optimize entity updates
This commit is contained in:
parent
02e779fc70
commit
84a8d269de
@ -220,16 +220,15 @@ void game::Character::UpdateSyncState()
|
|||||||
|
|
||||||
void game::Character::SendUpdateMsg()
|
void game::Character::SendUpdateMsg()
|
||||||
{
|
{
|
||||||
auto msg = BeginEntMsg(net::EMSG_UPDATE);
|
auto msg = BeginUpdateMsg();
|
||||||
auto fields_pos = msg.Reserve<CharacterSyncFieldFlags>();
|
auto fields_pos = msg.Reserve<CharacterSyncFieldFlags>();
|
||||||
auto fields = WriteState(msg, sync_[1 - sync_current_]);
|
auto fields = WriteState(msg, sync_[1 - sync_current_]);
|
||||||
|
|
||||||
// TODO: allow this
|
if (fields == 0)
|
||||||
// if (fields == 0)
|
{
|
||||||
// {
|
DiscardUpdateMsg();
|
||||||
// DiscardMsg();
|
return;
|
||||||
// return;
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
msg.WriteAt(fields_pos, fields);
|
msg.WriteAt(fields_pos, fields);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,6 +40,12 @@ bool game::Entity::TryUpdate()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void game::Entity::FinalizeFrame()
|
||||||
|
{
|
||||||
|
ResetMsg();
|
||||||
|
DiscardUpdateMsg();
|
||||||
|
}
|
||||||
|
|
||||||
void game::Entity::SetNametag(const std::string& nametag)
|
void game::Entity::SetNametag(const std::string& nametag)
|
||||||
{
|
{
|
||||||
nametag_ = nametag;
|
nametag_ = nametag;
|
||||||
@ -89,3 +95,14 @@ net::OutMessage game::Entity::BeginEntMsg(net::EntMsgType type)
|
|||||||
msg.Write(type);
|
msg.Write(type);
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
net::OutMessage game::Entity::BeginUpdateMsg()
|
||||||
|
{
|
||||||
|
update_msg_buf_.clear(); // make sure
|
||||||
|
return net::OutMessage(update_msg_buf_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void game::Entity::DiscardUpdateMsg()
|
||||||
|
{
|
||||||
|
update_msg_buf_.clear();
|
||||||
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <span>
|
||||||
|
|
||||||
#include "net/msg_producer.hpp"
|
#include "net/msg_producer.hpp"
|
||||||
#include "transform_node.hpp"
|
#include "transform_node.hpp"
|
||||||
@ -28,6 +29,10 @@ public:
|
|||||||
virtual void Update();
|
virtual void Update();
|
||||||
bool TryUpdate(); // if not already updated
|
bool TryUpdate(); // if not already updated
|
||||||
int64_t GetUpdateTime() const { return upd_time_; }
|
int64_t GetUpdateTime() const { return upd_time_; }
|
||||||
|
|
||||||
|
std::span<const char> GetUpdateMsg() const { return update_msg_buf_; }
|
||||||
|
|
||||||
|
void FinalizeFrame();
|
||||||
|
|
||||||
void SetNametag(const std::string& nametag);
|
void SetNametag(const std::string& nametag);
|
||||||
|
|
||||||
@ -55,6 +60,8 @@ private:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
net::OutMessage BeginEntMsg(net::EntMsgType type);
|
net::OutMessage BeginEntMsg(net::EntMsgType type);
|
||||||
|
net::OutMessage BeginUpdateMsg();
|
||||||
|
void DiscardUpdateMsg();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
World& world_;
|
World& world_;
|
||||||
@ -70,6 +77,9 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
int64_t upd_time_ = -1;
|
int64_t upd_time_ = -1;
|
||||||
|
|
||||||
|
std::vector<char> update_msg_buf_;
|
||||||
|
|
||||||
std::string nametag_;
|
std::string nametag_;
|
||||||
net::EntNum parentnum_ = 0;
|
net::EntNum parentnum_ = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -106,6 +106,10 @@ void game::Player::SyncEntities()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// list of entities to send update and messages of
|
||||||
|
static std::vector<const Entity*> upd_ents;
|
||||||
|
upd_ents.clear();
|
||||||
|
|
||||||
const auto& ents = world_->GetEntities();
|
const auto& ents = world_->GetEntities();
|
||||||
|
|
||||||
auto ent_it = ents.begin();
|
auto ent_it = ents.begin();
|
||||||
@ -116,36 +120,73 @@ void game::Player::SyncEntities()
|
|||||||
const net::EntNum entnum = (ent_it != ents.end() ? ent_it->first : std::numeric_limits<net::EntNum>::max());
|
const net::EntNum entnum = (ent_it != ents.end() ? ent_it->first : std::numeric_limits<net::EntNum>::max());
|
||||||
const net::EntNum knownum = (know_it != known_ents_.end() ? *know_it : std::numeric_limits<net::EntNum>::max());
|
const net::EntNum knownum = (know_it != known_ents_.end() ? *know_it : std::numeric_limits<net::EntNum>::max());
|
||||||
|
|
||||||
if (entnum == knownum) // ----- entity exists and is currently known -----
|
if (entnum == knownum) // entity exists and is currently known
|
||||||
{
|
{
|
||||||
const Entity& e = *ent_it->second;
|
const Entity& e = *ent_it->second;
|
||||||
if (ShouldSeeEntity(e)) // still visible?
|
if (ShouldSeeEntity(e)) // still visible?
|
||||||
{
|
{
|
||||||
SendUpdateEntity(e); // 2) update
|
upd_ents.push_back(&e);
|
||||||
++ent_it;
|
++ent_it;
|
||||||
++know_it;
|
++know_it;
|
||||||
}
|
}
|
||||||
else // vanished for player
|
else // not longed visible for player
|
||||||
{
|
{
|
||||||
SendDestroyEntity(knownum); // 3) destroy
|
SendDestroyEntity(knownum);
|
||||||
know_it = known_ents_.erase(know_it); // remove from known
|
know_it = known_ents_.erase(know_it);
|
||||||
++ent_it;
|
++ent_it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (entnum < knownum) // ----- entity exists, player does NOT know it -----
|
else if (entnum < knownum) // entity exists, player does NOT know it
|
||||||
{
|
{
|
||||||
const Entity& e = *ent_it->second;
|
const Entity& e = *ent_it->second;
|
||||||
if (ShouldSeeEntity(e)) // 1) become visible
|
if (ShouldSeeEntity(e))
|
||||||
{
|
{
|
||||||
SendInitEntity(e);
|
SendInitEntity(e);
|
||||||
known_ents_.insert(entnum); // add to known
|
known_ents_.insert(entnum);
|
||||||
} // else: stays invisible, nothing to do
|
}
|
||||||
++ent_it;
|
++ent_it;
|
||||||
}
|
}
|
||||||
else // ----- player knows it, but it no longer exists -----
|
else // player knows it, but it no longer exists
|
||||||
{
|
{
|
||||||
SendDestroyEntity(knownum); // 3) destroy
|
SendDestroyEntity(knownum);
|
||||||
know_it = known_ents_.erase(know_it); // remove from known
|
know_it = known_ents_.erase(know_it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// write update payload
|
||||||
|
{
|
||||||
|
auto msg = BeginMsg(net::MSG_UPDATEENTS);
|
||||||
|
size_t count_pos = msg.Reserve<net::EntCount>();
|
||||||
|
|
||||||
|
net::EntCount count = 0;
|
||||||
|
net::EntNum lastnum = 0;
|
||||||
|
|
||||||
|
for (auto ent : upd_ents)
|
||||||
|
{
|
||||||
|
auto ent_upd = ent->GetUpdateMsg();
|
||||||
|
if (!ent_upd.empty())
|
||||||
|
{
|
||||||
|
auto numdiff = ent->GetEntNum() - lastnum;
|
||||||
|
|
||||||
|
msg.WriteVarInt(numdiff);
|
||||||
|
msg.Write(ent_upd);
|
||||||
|
|
||||||
|
++count;
|
||||||
|
lastnum = ent->GetEntNum();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
msg.WriteAt(count_pos, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// write other entity msgs
|
||||||
|
for (auto ent : upd_ents)
|
||||||
|
{
|
||||||
|
auto ent_msg = ent->GetMsg();
|
||||||
|
if (!ent_msg.empty())
|
||||||
|
{
|
||||||
|
auto msg = BeginMsg();
|
||||||
|
msg.Write(ent_msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -171,13 +212,6 @@ void game::Player::SendInitEntity(const Entity& entity)
|
|||||||
entity.SendInitData(*this, msg);
|
entity.SendInitData(*this, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void game::Player::SendUpdateEntity(const Entity& entity)
|
|
||||||
{
|
|
||||||
MSGDEBUG(std::cout << "seding update ent " << entity.GetEntNum() << std::endl;)
|
|
||||||
auto msg = BeginMsg(); // no CMD here, these are already included in entity message payload!
|
|
||||||
msg.Write(entity.GetMsg());
|
|
||||||
}
|
|
||||||
|
|
||||||
void game::Player::SendDestroyEntity(net::EntNum entnum)
|
void game::Player::SendDestroyEntity(net::EntNum entnum)
|
||||||
{
|
{
|
||||||
MSGDEBUG(std::cout << "seding ENTDESTROY " << entnum << std::endl;)
|
MSGDEBUG(std::cout << "seding ENTDESTROY " << entnum << std::endl;)
|
||||||
|
|||||||
@ -45,7 +45,6 @@ private:
|
|||||||
void SyncEntities();
|
void SyncEntities();
|
||||||
bool ShouldSeeEntity(const Entity& entity) const;
|
bool ShouldSeeEntity(const Entity& entity) const;
|
||||||
void SendInitEntity(const Entity& entity);
|
void SendInitEntity(const Entity& entity);
|
||||||
void SendUpdateEntity(const Entity& entity);
|
|
||||||
void SendDestroyEntity(net::EntNum entnum);
|
void SendDestroyEntity(net::EntNum entnum);
|
||||||
|
|
||||||
// msg handlers
|
// msg handlers
|
||||||
|
|||||||
@ -71,11 +71,18 @@ game::SimpleEntitySyncFieldFlags game::SimpleEntity::WriteState(net::OutMessage&
|
|||||||
|
|
||||||
void game::SimpleEntity::SendUpdateMsg()
|
void game::SimpleEntity::SendUpdateMsg()
|
||||||
{
|
{
|
||||||
auto msg = BeginEntMsg(net::EMSG_UPDATE);
|
auto msg = BeginUpdateMsg();
|
||||||
|
|
||||||
// write state against previous
|
// write state against previous
|
||||||
const SimpleEntitySyncState& prev = sync_[1 - sync_current_];
|
const SimpleEntitySyncState& prev = sync_[1 - sync_current_];
|
||||||
size_t fields_pos = msg.Reserve<SimpleEntitySyncFieldFlags>();
|
size_t fields_pos = msg.Reserve<SimpleEntitySyncFieldFlags>();
|
||||||
auto fields = WriteState(msg, prev);
|
auto fields = WriteState(msg, prev);
|
||||||
|
|
||||||
|
if (fields == 0)
|
||||||
|
{
|
||||||
|
DiscardUpdateMsg();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
msg.WriteAt(fields_pos, fields);
|
msg.WriteAt(fields_pos, fields);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -456,16 +456,15 @@ game::VehicleSyncFieldFlags game::Vehicle::WriteState(net::OutMessage& msg, cons
|
|||||||
|
|
||||||
void game::Vehicle::SendUpdateMsg()
|
void game::Vehicle::SendUpdateMsg()
|
||||||
{
|
{
|
||||||
auto msg = BeginEntMsg(net::EMSG_UPDATE);
|
auto msg = BeginUpdateMsg();
|
||||||
auto fields_pos = msg.Reserve<VehicleSyncFieldFlags>();
|
auto fields_pos = msg.Reserve<VehicleSyncFieldFlags>();
|
||||||
auto fields = WriteState(msg, sync_[1 - sync_current_]);
|
auto fields = WriteState(msg, sync_[1 - sync_current_]);
|
||||||
|
|
||||||
// TODO: allow this
|
if (fields == 0)
|
||||||
// if (fields == 0)
|
{
|
||||||
// {
|
DiscardUpdateMsg();
|
||||||
// DiscardMsg();
|
return;
|
||||||
// return;
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
msg.WriteAt(fields_pos, fields);
|
msg.WriteAt(fields_pos, fields);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -73,7 +73,7 @@ void game::World::FinishFrame()
|
|||||||
// reset ent msgs
|
// reset ent msgs
|
||||||
for (auto& [entnum, ent] : ents_)
|
for (auto& [entnum, ent] : ents_)
|
||||||
{
|
{
|
||||||
ent->ResetMsg();
|
ent->FinalizeFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,11 +30,10 @@ game::view::CharacterView::CharacterView(WorldView& world, net::InMessage& msg)
|
|||||||
UpdateSurfaceMask();
|
UpdateSurfaceMask();
|
||||||
|
|
||||||
// read initial state
|
// read initial state
|
||||||
if (!ReadState(msg))
|
if (!ReadState(&msg))
|
||||||
throw EntityInitError();
|
throw EntityInitError();
|
||||||
|
|
||||||
states_[0] = states_[1]; // lerp from the read state to avoid jump
|
OnAttach();
|
||||||
|
|
||||||
|
|
||||||
radius_ = 2.0f;
|
radius_ = 2.0f;
|
||||||
}
|
}
|
||||||
@ -43,18 +42,16 @@ bool game::view::CharacterView::ProcessMsg(net::EntMsgType type, net::InMessage&
|
|||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case net::EMSG_UPDATE:
|
|
||||||
return ProcessUpdateMsg(msg);
|
|
||||||
|
|
||||||
case net::EMSG_ATTACH:
|
|
||||||
skip_lerps_ = 1;
|
|
||||||
return Super::ProcessMsg(type, msg);
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return Super::ProcessMsg(type, msg);
|
return Super::ProcessMsg(type, msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool game::view::CharacterView::ProcessUpdateMsg(net::InMessage* msg)
|
||||||
|
{
|
||||||
|
return ReadState(msg);
|
||||||
|
}
|
||||||
|
|
||||||
void game::view::CharacterView::Update(const UpdateInfo& info)
|
void game::view::CharacterView::Update(const UpdateInfo& info)
|
||||||
{
|
{
|
||||||
Super::Update(info);
|
Super::Update(info);
|
||||||
@ -66,7 +63,12 @@ void game::view::CharacterView::Update(const UpdateInfo& info)
|
|||||||
|
|
||||||
root_.local = Transform::Lerp(states_[0].trans, states_[1].trans, t);
|
root_.local = Transform::Lerp(states_[0].trans, states_[1].trans, t);
|
||||||
animstate_.loco_blend = glm::mix(states_[0].loco_blend, states_[1].loco_blend, t);
|
animstate_.loco_blend = glm::mix(states_[0].loco_blend, states_[1].loco_blend, t);
|
||||||
animstate_.loco_phase = glm::mod(glm::mix(states_[0].loco_phase, states_[1].loco_phase, t), 1.0f);
|
|
||||||
|
float loco_phase0 = states_[0].loco_phase;
|
||||||
|
float loco_phase1 = states_[1].loco_phase;
|
||||||
|
if (loco_phase0 > loco_phase1)
|
||||||
|
loco_phase0 -= 1.0f;
|
||||||
|
animstate_.loco_phase = glm::mod(glm::mix(loco_phase0, loco_phase1, t), 1.0f);
|
||||||
|
|
||||||
animstate_.ApplyToSkeleton(sk_);
|
animstate_.ApplyToSkeleton(sk_);
|
||||||
|
|
||||||
@ -137,7 +139,17 @@ void game::view::CharacterView::Draw(const DrawArgs& args)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool game::view::CharacterView::ReadState(net::InMessage& msg)
|
void game::view::CharacterView::OnAttach()
|
||||||
|
{
|
||||||
|
states_[0] = states_[1]; // lerp from the read state to avoid jump
|
||||||
|
|
||||||
|
// init view state
|
||||||
|
root_.local = states_[0].trans;
|
||||||
|
animstate_.loco_blend = states_[0].loco_blend;
|
||||||
|
animstate_.loco_phase = states_[0].loco_phase;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool game::view::CharacterView::ReadState(net::InMessage* msg)
|
||||||
{
|
{
|
||||||
update_time_ = world_.GetTime();
|
update_time_ = world_.GetTime();
|
||||||
|
|
||||||
@ -148,66 +160,55 @@ bool game::view::CharacterView::ReadState(net::InMessage& msg)
|
|||||||
|
|
||||||
auto& new_state = states_[1];
|
auto& new_state = states_[1];
|
||||||
|
|
||||||
// parse state delta
|
if (msg)
|
||||||
CharacterSyncFieldFlags fields;
|
|
||||||
if (!msg.Read(fields))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// transform
|
|
||||||
if (fields & CSF_TRANSFORM)
|
|
||||||
{
|
{
|
||||||
if (!net::ReadDelta(msg, sync_.pos.x) || !net::ReadDelta(msg, sync_.pos.y) ||
|
// parse state delta
|
||||||
!net::ReadDelta(msg, sync_.pos.z) || !net::ReadDelta(msg, sync_.yaw))
|
CharacterSyncFieldFlags fields;
|
||||||
|
if (!msg->Read(fields))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
net::DecodePosition(sync_.pos, new_state.trans.position);
|
// transform
|
||||||
new_state.trans.rotation = glm::rotate(glm::quat(1.0f, 0.0f, 0.0f, 0.0f),
|
if (fields & CSF_TRANSFORM)
|
||||||
sync_.yaw.Decode() + glm::pi<float>() * 0.5f, glm::vec3(0, 0, 1));
|
{
|
||||||
}
|
if (!net::ReadDelta(*msg, sync_.pos.x) || !net::ReadDelta(*msg, sync_.pos.y) ||
|
||||||
|
!net::ReadDelta(*msg, sync_.pos.z) || !net::ReadDelta(*msg, sync_.yaw))
|
||||||
|
return false;
|
||||||
|
|
||||||
if (fields & CSF_IDLE_ANIM)
|
net::DecodePosition(sync_.pos, new_state.trans.position);
|
||||||
{
|
new_state.trans.rotation = glm::rotate(glm::quat(1.0f, 0.0f, 0.0f, 0.0f),
|
||||||
if (!msg.Read(sync_.idle_anim))
|
sync_.yaw.Decode() + glm::pi<float>() * 0.5f, glm::vec3(0, 0, 1));
|
||||||
return false;
|
}
|
||||||
|
|
||||||
animstate_.idle_anim_idx = sync_.idle_anim;
|
if (fields & CSF_IDLE_ANIM)
|
||||||
}
|
{
|
||||||
|
if (!msg->Read(sync_.idle_anim))
|
||||||
|
return false;
|
||||||
|
|
||||||
if (fields & CSF_LOCO_ANIMS)
|
animstate_.idle_anim_idx = sync_.idle_anim;
|
||||||
{
|
}
|
||||||
if (!msg.Read(sync_.walk_anim) || !msg.Read(sync_.run_anim))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
animstate_.walk_anim_idx = sync_.walk_anim;
|
if (fields & CSF_LOCO_ANIMS)
|
||||||
animstate_.run_anim_idx = sync_.run_anim;
|
{
|
||||||
}
|
if (!msg->Read(sync_.walk_anim) || !msg->Read(sync_.run_anim))
|
||||||
|
return false;
|
||||||
|
|
||||||
if (fields & CSF_LOCO_VALS)
|
animstate_.walk_anim_idx = sync_.walk_anim;
|
||||||
{
|
animstate_.run_anim_idx = sync_.run_anim;
|
||||||
if (!net::ReadDelta(msg, sync_.loco_blend) || !net::ReadDelta(msg, sync_.loco_phase))
|
}
|
||||||
return false;
|
|
||||||
|
|
||||||
new_state.loco_blend = sync_.loco_blend.Decode();
|
if (fields & CSF_LOCO_VALS)
|
||||||
new_state.loco_phase = sync_.loco_phase.Decode();
|
{
|
||||||
|
if (!net::ReadDelta(*msg, sync_.loco_blend) || !net::ReadDelta(*msg, sync_.loco_phase))
|
||||||
|
return false;
|
||||||
|
|
||||||
if (new_state.loco_phase < states_[0].loco_phase)
|
new_state.loco_blend = sync_.loco_blend.Decode();
|
||||||
states_[0].loco_phase -= 1.0f;
|
new_state.loco_phase = sync_.loco_phase.Decode();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skip_lerps_ > 0)
|
|
||||||
{
|
|
||||||
states_[0] = states_[1];
|
|
||||||
skip_lerps_--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool game::view::CharacterView::ProcessUpdateMsg(net::InMessage& msg)
|
|
||||||
{
|
|
||||||
return ReadState(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
game::view::CharacterView::SurfaceMask game::view::CharacterView::GetSurfaceMask(const std::string& name)
|
game::view::CharacterView::SurfaceMask game::view::CharacterView::GetSurfaceMask(const std::string& name)
|
||||||
{
|
{
|
||||||
const auto& surface_names = basemodel_->GetMesh()->surface_names;
|
const auto& surface_names = basemodel_->GetMesh()->surface_names;
|
||||||
|
|||||||
@ -34,12 +34,15 @@ public:
|
|||||||
DELETE_COPY_MOVE(CharacterView)
|
DELETE_COPY_MOVE(CharacterView)
|
||||||
|
|
||||||
virtual bool ProcessMsg(net::EntMsgType type, net::InMessage& msg) override;
|
virtual bool ProcessMsg(net::EntMsgType type, net::InMessage& msg) override;
|
||||||
|
virtual bool ProcessUpdateMsg(net::InMessage* msg) override;
|
||||||
virtual void Update(const UpdateInfo& info) override;
|
virtual void Update(const UpdateInfo& info) override;
|
||||||
virtual void Draw(const DrawArgs& args) override;
|
virtual void Draw(const DrawArgs& args) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void OnAttach() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool ReadState(net::InMessage& msg);
|
bool ReadState(net::InMessage* msg);
|
||||||
bool ProcessUpdateMsg(net::InMessage& msg);
|
|
||||||
|
|
||||||
SurfaceMask GetSurfaceMask(const std::string& name);
|
SurfaceMask GetSurfaceMask(const std::string& name);
|
||||||
void UpdateSurfaceMask();
|
void UpdateSurfaceMask();
|
||||||
@ -63,7 +66,6 @@ private:
|
|||||||
CharacterSyncState sync_;
|
CharacterSyncState sync_;
|
||||||
CharacterViewState states_[2];
|
CharacterViewState states_[2];
|
||||||
float update_time_ = 0.0f;
|
float update_time_ = 0.0f;
|
||||||
size_t skip_lerps_ = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,6 +30,11 @@ bool game::view::EntityView::ProcessMsg(net::EntMsgType type, net::InMessage& ms
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool game::view::EntityView::ProcessUpdateMsg(net::InMessage* msg)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool game::view::EntityView::TryUpdate(const UpdateInfo& info)
|
bool game::view::EntityView::TryUpdate(const UpdateInfo& info)
|
||||||
{
|
{
|
||||||
float time = world_.GetTime();
|
float time = world_.GetTime();
|
||||||
@ -81,7 +86,12 @@ bool game::view::EntityView::ReadNametag(net::InMessage& msg)
|
|||||||
|
|
||||||
bool game::view::EntityView::ReadAttach(net::InMessage& msg)
|
bool game::view::EntityView::ReadAttach(net::InMessage& msg)
|
||||||
{
|
{
|
||||||
return msg.Read(parentnum_);
|
if (!msg.Read(parentnum_))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
OnAttach();
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool game::view::EntityView::ProcessPlaySoundMsg(net::InMessage& msg)
|
bool game::view::EntityView::ProcessPlaySoundMsg(net::InMessage& msg)
|
||||||
|
|||||||
@ -36,6 +36,7 @@ public:
|
|||||||
DELETE_COPY_MOVE(EntityView)
|
DELETE_COPY_MOVE(EntityView)
|
||||||
|
|
||||||
virtual bool ProcessMsg(net::EntMsgType type, net::InMessage& msg);
|
virtual bool ProcessMsg(net::EntMsgType type, net::InMessage& msg);
|
||||||
|
virtual bool ProcessUpdateMsg(net::InMessage* msg);
|
||||||
|
|
||||||
bool TryUpdate(const UpdateInfo& info); // if not updated already
|
bool TryUpdate(const UpdateInfo& info); // if not updated already
|
||||||
virtual void Update(const UpdateInfo& info);
|
virtual void Update(const UpdateInfo& info);
|
||||||
@ -47,6 +48,9 @@ public:
|
|||||||
|
|
||||||
virtual ~EntityView() = default;
|
virtual ~EntityView() = default;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void OnAttach() {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool ReadNametag(net::InMessage& msg);
|
bool ReadNametag(net::InMessage& msg);
|
||||||
bool ReadAttach(net::InMessage& msg);
|
bool ReadAttach(net::InMessage& msg);
|
||||||
|
|||||||
@ -17,10 +17,11 @@ game::view::SimpleEntityView::SimpleEntityView(WorldView& world, net::InMessage&
|
|||||||
throw EntityInitError();
|
throw EntityInitError();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ReadState(msg))
|
if (!ReadState(&msg))
|
||||||
throw EntityInitError();
|
throw EntityInitError();
|
||||||
|
|
||||||
states_[0] = states_[1]; // lerp from the read state to avoid jump
|
states_[0] = states_[1]; // lerp from the read state to avoid jump
|
||||||
|
root_.local = states_[0].trans;
|
||||||
|
|
||||||
radius_ = 20.0f;
|
radius_ = 20.0f;
|
||||||
}
|
}
|
||||||
@ -29,14 +30,16 @@ bool game::view::SimpleEntityView::ProcessMsg(net::EntMsgType type, net::InMessa
|
|||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case net::EMSG_UPDATE:
|
|
||||||
return ProcessUpdateMsg(msg);
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return Super::ProcessMsg(type, msg);
|
return Super::ProcessMsg(type, msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool game::view::SimpleEntityView::ProcessUpdateMsg(net::InMessage* msg)
|
||||||
|
{
|
||||||
|
return ReadState(msg);
|
||||||
|
}
|
||||||
|
|
||||||
void game::view::SimpleEntityView::Update(const UpdateInfo& info)
|
void game::view::SimpleEntityView::Update(const UpdateInfo& info)
|
||||||
{
|
{
|
||||||
Super::Update(info);
|
Super::Update(info);
|
||||||
@ -67,7 +70,7 @@ void game::view::SimpleEntityView::Draw(const DrawArgs& args)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool game::view::SimpleEntityView::ReadState(net::InMessage& msg)
|
bool game::view::SimpleEntityView::ReadState(net::InMessage* msg)
|
||||||
{
|
{
|
||||||
update_time_ = world_.GetTime();
|
update_time_ = world_.GetTime();
|
||||||
|
|
||||||
@ -76,33 +79,31 @@ bool game::view::SimpleEntityView::ReadState(net::InMessage& msg)
|
|||||||
|
|
||||||
auto& new_state = states_[1];
|
auto& new_state = states_[1];
|
||||||
|
|
||||||
// parse state delta
|
if (msg)
|
||||||
SimpleEntitySyncFieldFlags fields;
|
|
||||||
if (!msg.Read(fields))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// pos
|
|
||||||
if (fields & SESF_POSITION)
|
|
||||||
{
|
{
|
||||||
if (!net::ReadDelta(msg, sync_.pos.x) || !net::ReadDelta(msg, sync_.pos.y) || !net::ReadDelta(msg, sync_.pos.z))
|
// parse state delta
|
||||||
|
SimpleEntitySyncFieldFlags fields;
|
||||||
|
if (!msg->Read(fields))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
net::DecodePosition(sync_.pos, new_state.trans.position);
|
// pos
|
||||||
}
|
if (fields & SESF_POSITION)
|
||||||
|
{
|
||||||
|
if (!net::ReadDelta(*msg, sync_.pos.x) || !net::ReadDelta(*msg, sync_.pos.y) || !net::ReadDelta(*msg, sync_.pos.z))
|
||||||
|
return false;
|
||||||
|
|
||||||
// rot
|
net::DecodePosition(sync_.pos, new_state.trans.position);
|
||||||
if (fields & SESF_ROTATION)
|
}
|
||||||
{
|
|
||||||
if (!net::ReadDelta(msg, sync_.rot.x) || !net::ReadDelta(msg, sync_.rot.y) || !net::ReadDelta(msg, sync_.rot.z))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
net::DecodeRotation(sync_.rot, new_state.trans.rotation);
|
// rot
|
||||||
|
if (fields & SESF_ROTATION)
|
||||||
|
{
|
||||||
|
if (!net::ReadDelta(*msg, sync_.rot.x) || !net::ReadDelta(*msg, sync_.rot.y) || !net::ReadDelta(*msg, sync_.rot.z))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
net::DecodeRotation(sync_.rot, new_state.trans.rotation);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool game::view::SimpleEntityView::ProcessUpdateMsg(net::InMessage& msg)
|
|
||||||
{
|
|
||||||
return ReadState(msg);
|
|
||||||
}
|
|
||||||
|
|||||||
@ -20,13 +20,12 @@ public:
|
|||||||
SimpleEntityView(WorldView& world, net::InMessage& msg);
|
SimpleEntityView(WorldView& world, net::InMessage& msg);
|
||||||
|
|
||||||
virtual bool ProcessMsg(net::EntMsgType type, net::InMessage& msg) override;
|
virtual bool ProcessMsg(net::EntMsgType type, net::InMessage& msg) override;
|
||||||
|
virtual bool ProcessUpdateMsg(net::InMessage* msg) override;
|
||||||
virtual void Update(const UpdateInfo& info) override;
|
virtual void Update(const UpdateInfo& info) override;
|
||||||
virtual void Draw(const DrawArgs& args) override;
|
virtual void Draw(const DrawArgs& args) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool ReadState(net::InMessage& msg);
|
bool ReadState(net::InMessage* msg);
|
||||||
|
|
||||||
bool ProcessUpdateMsg(net::InMessage& msg);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<const assets::Model> model_;
|
std::shared_ptr<const assets::Model> model_;
|
||||||
|
|||||||
@ -27,18 +27,14 @@ game::view::VehicleView::VehicleView(WorldView& world, net::InMessage& msg)
|
|||||||
|
|
||||||
color_ = glm::vec4(color, 1.0f);
|
color_ = glm::vec4(color, 1.0f);
|
||||||
|
|
||||||
if (!ReadState(msg))
|
if (!ReadState(&msg))
|
||||||
throw EntityInitError();
|
throw EntityInitError();
|
||||||
|
|
||||||
// init the other transform to identical
|
// init the other transform to identical
|
||||||
root_trans_[0] = root_trans_[1];
|
root_trans_[0] = root_trans_[1];
|
||||||
|
root_.local = root_trans_[0];
|
||||||
snd_accel_ = assets::CacheManager::GetSound("data/auto.snd");
|
|
||||||
|
|
||||||
// sync state
|
|
||||||
net::DecodePosition(sync_.pos, root_.local.position);
|
|
||||||
net::DecodeRotation(sync_.rot, root_.local.rotation);
|
|
||||||
|
|
||||||
|
snd_accel_ = assets::CacheManager::GetSound("data/auto.snd");
|
||||||
|
|
||||||
radius_ = 3.0f;
|
radius_ = 3.0f;
|
||||||
}
|
}
|
||||||
@ -47,14 +43,16 @@ bool game::view::VehicleView::ProcessMsg(net::EntMsgType type, net::InMessage& m
|
|||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case net::EMSG_UPDATE:
|
|
||||||
return ProcessUpdateMsg(msg);
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return Super::ProcessMsg(type, msg);
|
return Super::ProcessMsg(type, msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool game::view::VehicleView::ProcessUpdateMsg(net::InMessage* msg)
|
||||||
|
{
|
||||||
|
return ReadState(msg);
|
||||||
|
}
|
||||||
|
|
||||||
void game::view::VehicleView::Update(const UpdateInfo& info)
|
void game::view::VehicleView::Update(const UpdateInfo& info)
|
||||||
{
|
{
|
||||||
Super::Update(info);
|
Super::Update(info);
|
||||||
@ -145,81 +143,78 @@ void game::view::VehicleView::Draw(const DrawArgs& args)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool game::view::VehicleView::ReadState(net::InMessage& msg)
|
bool game::view::VehicleView::ReadState(net::InMessage* msg)
|
||||||
{
|
{
|
||||||
root_trans_[0] = root_.local;
|
root_trans_[0] = root_.local;
|
||||||
auto& root_trans = root_trans_[1];
|
auto& root_trans = root_trans_[1];
|
||||||
update_time_ = world_.GetTime();
|
update_time_ = world_.GetTime();
|
||||||
|
|
||||||
// parse state delta
|
if (msg)
|
||||||
VehicleSyncFieldFlags fields;
|
|
||||||
if (!msg.Read(fields))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// flags
|
|
||||||
if (fields & VSF_FLAGS)
|
|
||||||
{
|
{
|
||||||
if (!msg.Read(flags_))
|
// parse state delta
|
||||||
return false;
|
VehicleSyncFieldFlags fields;
|
||||||
}
|
if (!msg->Read(fields))
|
||||||
|
|
||||||
// pos
|
|
||||||
if (fields & VSF_POSITION)
|
|
||||||
{
|
|
||||||
if (!net::ReadDelta(msg, sync_.pos.x) ||
|
|
||||||
!net::ReadDelta(msg, sync_.pos.y) ||
|
|
||||||
!net::ReadDelta(msg, sync_.pos.z))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
net::DecodePosition(sync_.pos, root_trans.position);
|
// flags
|
||||||
}
|
if (fields & VSF_FLAGS)
|
||||||
|
|
||||||
// rot
|
|
||||||
if (fields & VSF_ROTATION)
|
|
||||||
{
|
|
||||||
if (!net::ReadDelta(msg, sync_.rot.x) ||
|
|
||||||
!net::ReadDelta(msg, sync_.rot.y) ||
|
|
||||||
!net::ReadDelta(msg, sync_.rot.z))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
net::DecodeRotation(sync_.rot, root_trans.rotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
// steering
|
|
||||||
if (fields & VSF_STEERING)
|
|
||||||
{
|
|
||||||
if (!net::ReadDelta(msg, sync_.steering))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
float steering = sync_.steering.Decode();
|
|
||||||
|
|
||||||
// wheels
|
|
||||||
if (fields & VSF_WHEELS)
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < wheels_.size(); ++i)
|
|
||||||
{
|
{
|
||||||
if (!net::ReadDelta(msg, sync_.wheels[i].z_offset) ||
|
if (!msg->Read(flags_))
|
||||||
!net::ReadDelta(msg, sync_.wheels[i].speed))
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pos
|
||||||
|
if (fields & VSF_POSITION)
|
||||||
|
{
|
||||||
|
if (!net::ReadDelta(*msg, sync_.pos.x) ||
|
||||||
|
!net::ReadDelta(*msg, sync_.pos.y) ||
|
||||||
|
!net::ReadDelta(*msg, sync_.pos.z))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
net::DecodePosition(sync_.pos, root_trans.position);
|
||||||
|
}
|
||||||
|
|
||||||
|
// rot
|
||||||
|
if (fields & VSF_ROTATION)
|
||||||
|
{
|
||||||
|
if (!net::ReadDelta(*msg, sync_.rot.x) ||
|
||||||
|
!net::ReadDelta(*msg, sync_.rot.y) ||
|
||||||
|
!net::ReadDelta(*msg, sync_.rot.z))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
net::DecodeRotation(sync_.rot, root_trans.rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
// steering
|
||||||
|
if (fields & VSF_STEERING)
|
||||||
|
{
|
||||||
|
if (!net::ReadDelta(*msg, sync_.steering))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
float steering = sync_.steering.Decode();
|
||||||
|
|
||||||
|
// wheels
|
||||||
|
if (fields & VSF_WHEELS)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < wheels_.size(); ++i)
|
||||||
|
{
|
||||||
|
if (!net::ReadDelta(*msg, sync_.wheels[i].z_offset) ||
|
||||||
|
!net::ReadDelta(*msg, sync_.wheels[i].speed))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& wheels = model_->GetWheels();
|
||||||
|
for (size_t i = 0; i < wheels_.size(); ++i)
|
||||||
|
{
|
||||||
|
auto& wheel = wheels_[i];
|
||||||
|
wheel.z_offset = sync_.wheels[i].z_offset.Decode();
|
||||||
|
wheel.speed = sync_.wheels[i].speed.Decode();
|
||||||
|
|
||||||
|
wheel.steering = i < 2 ? steering : 0.0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& wheels = model_->GetWheels();
|
|
||||||
for (size_t i = 0; i < wheels_.size(); ++i)
|
|
||||||
{
|
|
||||||
auto& wheel = wheels_[i];
|
|
||||||
wheel.z_offset = sync_.wheels[i].z_offset.Decode();
|
|
||||||
wheel.speed = sync_.wheels[i].speed.Decode();
|
|
||||||
|
|
||||||
wheel.steering = i < 2 ? steering : 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool game::view::VehicleView::ProcessUpdateMsg(net::InMessage& msg)
|
|
||||||
{
|
|
||||||
return ReadState(msg);
|
|
||||||
}
|
|
||||||
|
|||||||
@ -27,12 +27,12 @@ public:
|
|||||||
DELETE_COPY_MOVE(VehicleView)
|
DELETE_COPY_MOVE(VehicleView)
|
||||||
|
|
||||||
virtual bool ProcessMsg(net::EntMsgType type, net::InMessage& msg) override;
|
virtual bool ProcessMsg(net::EntMsgType type, net::InMessage& msg) override;
|
||||||
|
virtual bool ProcessUpdateMsg(net::InMessage* msg) override;
|
||||||
virtual void Update(const UpdateInfo& info) override;
|
virtual void Update(const UpdateInfo& info) override;
|
||||||
virtual void Draw(const DrawArgs& args) override;
|
virtual void Draw(const DrawArgs& args) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool ReadState(net::InMessage& msg);
|
bool ReadState(net::InMessage* msg);
|
||||||
bool ProcessUpdateMsg(net::InMessage& msg);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<const assets::VehicleModel> model_;
|
std::shared_ptr<const assets::VehicleModel> model_;
|
||||||
|
|||||||
@ -31,8 +31,9 @@ game::view::WorldView::WorldView(ClientSession& session, net::InMessage& msg) :
|
|||||||
// cache common snds and stuff
|
// cache common snds and stuff
|
||||||
Cache(assets::CacheManager::GetSound("data/breaksign.snd"));
|
Cache(assets::CacheManager::GetSound("data/breaksign.snd"));
|
||||||
Cache(assets::CacheManager::GetSound("data/breakpatnik.snd"));
|
Cache(assets::CacheManager::GetSound("data/breakpatnik.snd"));
|
||||||
|
Cache(assets::CacheManager::GetSound("data/breakwood.snd"));
|
||||||
|
Cache(assets::CacheManager::GetSound("data/cardoor.snd"));
|
||||||
Cache(assets::CacheManager::GetSound("data/crash.snd"));
|
Cache(assets::CacheManager::GetSound("data/crash.snd"));
|
||||||
Cache(assets::CacheManager::GetSound("data/breakwindow.snd"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool game::view::WorldView::ProcessMsg(net::MessageType type, net::InMessage& msg)
|
bool game::view::WorldView::ProcessMsg(net::MessageType type, net::InMessage& msg)
|
||||||
@ -44,6 +45,9 @@ bool game::view::WorldView::ProcessMsg(net::MessageType type, net::InMessage& ms
|
|||||||
|
|
||||||
case net::MSG_ENTMSG:
|
case net::MSG_ENTMSG:
|
||||||
return ProcessEntMsgMsg(msg);
|
return ProcessEntMsgMsg(msg);
|
||||||
|
|
||||||
|
case net::MSG_UPDATEENTS:
|
||||||
|
return ProcessUpdateEntsMsg(msg);
|
||||||
|
|
||||||
case net::MSG_ENTDESTROY:
|
case net::MSG_ENTDESTROY:
|
||||||
return ProcessEntDestroyMsg(msg);
|
return ProcessEntDestroyMsg(msg);
|
||||||
@ -172,6 +176,49 @@ bool game::view::WorldView::ProcessEntMsgMsg(net::InMessage& msg)
|
|||||||
return ent_it->second->ProcessMsg(type, msg);
|
return ent_it->second->ProcessMsg(type, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool game::view::WorldView::ProcessUpdateEntsMsg(net::InMessage& msg)
|
||||||
|
{
|
||||||
|
net::EntCount count;
|
||||||
|
if (!msg.Read(count))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
net::EntNum current = 0;
|
||||||
|
auto it = ents_.begin();
|
||||||
|
|
||||||
|
for (net::EntNum i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
int64_t diff;
|
||||||
|
if (!msg.ReadVarInt(diff))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
current += static_cast<net::EntNum>(diff);
|
||||||
|
|
||||||
|
while (it->first < current)
|
||||||
|
{
|
||||||
|
it->second->ProcessUpdateMsg(nullptr); // blank update
|
||||||
|
++it;
|
||||||
|
if (it == ents_.end())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it->first != current)
|
||||||
|
{
|
||||||
|
return false; // exact num wasnt found and it overrun
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!it->second->ProcessUpdateMsg(&msg))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// process remaining
|
||||||
|
for (; it != ents_.end(); ++it)
|
||||||
|
{
|
||||||
|
it->second->ProcessUpdateMsg(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool game::view::WorldView::ProcessEntDestroyMsg(net::InMessage& msg)
|
bool game::view::WorldView::ProcessEntDestroyMsg(net::InMessage& msg)
|
||||||
{
|
{
|
||||||
net::EntNum entnum;
|
net::EntNum entnum;
|
||||||
|
|||||||
@ -36,6 +36,7 @@ private:
|
|||||||
// msg handlers
|
// msg handlers
|
||||||
bool ProcessEntSpawnMsg(net::InMessage& msg);
|
bool ProcessEntSpawnMsg(net::InMessage& msg);
|
||||||
bool ProcessEntMsgMsg(net::InMessage& msg);
|
bool ProcessEntMsgMsg(net::InMessage& msg);
|
||||||
|
bool ProcessUpdateEntsMsg(net::InMessage& msg);
|
||||||
bool ProcessEntDestroyMsg(net::InMessage& msg);
|
bool ProcessEntDestroyMsg(net::InMessage& msg);
|
||||||
|
|
||||||
bool ProcessObjDestroyOrRespawnMsg(net::InMessage& msg, bool enable);
|
bool ProcessObjDestroyOrRespawnMsg(net::InMessage& msg, bool enable);
|
||||||
|
|||||||
@ -39,6 +39,8 @@ enum MessageType : uint8_t
|
|||||||
MSG_ENTSPAWN,
|
MSG_ENTSPAWN,
|
||||||
// ENTMSG <EntNum> data...
|
// ENTMSG <EntNum> data...
|
||||||
MSG_ENTMSG,
|
MSG_ENTMSG,
|
||||||
|
// UPDATEENTS <EntCount> ...
|
||||||
|
MSG_UPDATEENTS,
|
||||||
// ENTDESTROY <EntNum>
|
// ENTDESTROY <EntNum>
|
||||||
MSG_ENTDESTROY,
|
MSG_ENTDESTROY,
|
||||||
|
|
||||||
@ -67,6 +69,7 @@ using ViewPitchQ = Quantized<uint16_t, -PI_N, PI_N, PI_D>;
|
|||||||
|
|
||||||
// entities
|
// entities
|
||||||
using EntNum = uint16_t;
|
using EntNum = uint16_t;
|
||||||
|
using EntCount = EntNum;
|
||||||
|
|
||||||
enum EntType : uint8_t
|
enum EntType : uint8_t
|
||||||
{
|
{
|
||||||
@ -85,7 +88,7 @@ enum EntMsgType : uint8_t
|
|||||||
|
|
||||||
EMSG_NAMETAG,
|
EMSG_NAMETAG,
|
||||||
EMSG_ATTACH,
|
EMSG_ATTACH,
|
||||||
EMSG_UPDATE,
|
// EMSG_UPDATE, // deprecated
|
||||||
EMSG_PLAYSOUND,
|
EMSG_PLAYSOUND,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user