fekalnigtacko/src/gameview/simple_entity_view.cpp
2026-03-01 16:40:57 +01:00

110 lines
2.7 KiB
C++

#include "simple_entity_view.hpp"
#include "net/defs.hpp"
#include "assets/cache.hpp"
#include "worldview.hpp"
#include "net/utils.hpp"
game::view::SimpleEntityView::SimpleEntityView(WorldView& world, net::InMessage& msg) : Super(world, msg)
{
net::ModelName modelname;
if (!msg.Read(modelname))
throw EntityInitError();
if (modelname.len > 0)
{
model_ = assets::CacheManager::GetModel(std::string(modelname));
if (!model_)
throw EntityInitError();
}
if (!ReadState(&msg))
throw EntityInitError();
states_[0] = states_[1]; // lerp from the read state to avoid jump
root_.local = states_[0].trans;
radius_ = 20.0f;
}
bool game::view::SimpleEntityView::ProcessMsg(net::EntMsgType type, net::InMessage& msg)
{
switch (type)
{
default:
return Super::ProcessMsg(type, msg);
}
}
bool game::view::SimpleEntityView::ProcessUpdateMsg(net::InMessage* msg)
{
return ReadState(msg);
}
void game::view::SimpleEntityView::Update(const UpdateInfo& info)
{
Super::Update(info);
// interpolate states
float tps = 25.0f;
float t = (info.time - update_time_) * tps * 0.8f; // assume some jitter, interpolate for longer
t = glm::clamp(t, 0.0f, 2.0f);
root_.local = Transform::Lerp(states_[0].trans, states_[1].trans, t);
root_.UpdateMatrix();
}
void game::view::SimpleEntityView::Draw(const DrawArgs& args)
{
Super::Draw(args);
if (!model_)
return;
const auto& mesh = *model_->GetMesh();
for (const auto& surface : mesh.surfaces)
{
gfx::DrawSurfaceCmd cmd;
cmd.surface = &surface;
cmd.matrices = &root_.matrix;
args.dlist.AddSurface(cmd);
}
}
bool game::view::SimpleEntityView::ReadState(net::InMessage* msg)
{
update_time_ = world_.GetTime();
// init lerp start state
states_[0].trans = root_.local;
auto& new_state = states_[1];
if (msg)
{
// parse state delta
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))
return false;
net::DecodePosition(sync_.pos, new_state.trans.position);
}
// 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;
}