Remove "controllable" and other stuff

This commit is contained in:
tovjemam 2026-01-15 01:34:48 +01:00
parent 1831befb85
commit 899b0f990c
21 changed files with 280 additions and 190 deletions

View File

@ -97,8 +97,6 @@ set(CLIENT_ONLY_SOURCES
)
set(SERVER_ONLY_SOURCES
"src/game/controllable.cpp"
"src/game/controllable.hpp"
"src/game/entity.hpp"
"src/game/entity.cpp"
"src/game/game.hpp"

View File

@ -38,7 +38,24 @@ void App::Frame()
}
// detect inputs originating in this frame
game::PlayerInputFlags new_input = input_ & ~prev_input_;
//game::PlayerInputFlags new_input = input_ & ~prev_input_;
// detect input changes
for (size_t i = 0; i < game::IN__COUNT; ++i)
{
auto in_old = prev_input_ & (1 << i);
auto in_new = input_ & (1 << i);
if (in_old > in_new) // released
{
SendInput(static_cast<game::PlayerInputType>(i), false);
}
else if (in_new > in_old) // pressed
{
SendInput(static_cast<game::PlayerInputType>(i), true);
}
}
prev_input_ = input_;
if (session_)
@ -81,14 +98,14 @@ void App::Frame()
renderer_.DrawList(dlist_, params);
if (time_ - last_send_time_ > 0.040f)
{
auto msg = BeginMsg(net::MSG_IN);
msg.Write(input_);
// if (time_ - last_send_time_ > 0.040f)
// {
// auto msg = BeginMsg(net::MSG_IN);
// msg.Write(input_);
last_send_time_ = time_;
// last_send_time_ = time_;
}
// }
}
void App::Connected()
@ -153,9 +170,13 @@ void App::AddChatMessagePrefix(const std::string& prefix, const std::string& tex
App::~App() {}
void App::Send(std::vector<char> data)
void App::SendInput(game::PlayerInputType type, bool enable)
{
auto msg = BeginMsg(net::MSG_IN);
uint8_t val = type;
if (enable)
val |= 128;
msg.Write(val);
}
void App::InitChat()

View File

@ -47,7 +47,7 @@ public:
~App();
private:
void Send(std::vector<char> data);
void SendInput(game::PlayerInputType type, bool enable);
void InitChat();
void UpdateChat();

View File

@ -314,41 +314,40 @@ static void Frame()
const uint8_t* kbd_state = SDL_GetKeyboardState(nullptr);
if (kbd_state[SDL_GetScancodeFromKey(SDLK_w)])
input |= game::IN_FORWARD;
input |= (1 << game::IN_FORWARD);
if (kbd_state[SDL_GetScancodeFromKey(SDLK_s)])
input |= game::IN_BACKWARD;
input |= (1 << game::IN_BACKWARD);
if (kbd_state[SDL_GetScancodeFromKey(SDLK_a)])
input |= game::IN_LEFT;
input |= (1 << game::IN_LEFT);
if (kbd_state[SDL_GetScancodeFromKey(SDLK_d)])
input |= game::IN_RIGHT;
input |= (1 << game::IN_RIGHT);
if (kbd_state[SDL_GetScancodeFromKey(SDLK_SPACE)])
input |= game::IN_JUMP;
input |= (1 << game::IN_JUMP);
if (kbd_state[SDL_GetScancodeFromKey(SDLK_LCTRL)])
input |= game::IN_CROUCH;
input |= (1 << game::IN_CROUCH);
if (kbd_state[SDL_GetScancodeFromKey(SDLK_e)])
input |= game::IN_USE;
input |= (1 << game::IN_USE);
if (kbd_state[SDL_GetScancodeFromKey(SDLK_F3)])
input |= game::IN_DEBUG1;
input |= (1 << game::IN_DEBUG1);
if (kbd_state[SDL_GetScancodeFromKey(SDLK_F4)])
input |= game::IN_DEBUG2;
input |= (1 << game::IN_DEBUG2);
if (kbd_state[SDL_GetScancodeFromKey(SDLK_F5)])
input |= game::IN_DEBUG3;
input |= (1 << game::IN_DEBUG3);
int mouse_state = SDL_GetMouseState(nullptr, nullptr);
if (mouse_state & SDL_BUTTON(SDL_BUTTON_LEFT))
input |= game::IN_ATTACK;
s_app->SetInput(input);
s_app->Frame();

View File

@ -1,9 +0,0 @@
#include "controllable.hpp"
#include "player.hpp"
game::Controllable::~Controllable()
{
if (controller_)
controller_->Control(nullptr);
}

View File

@ -1,30 +0,0 @@
#pragma once
#include "utils/defs.hpp"
namespace game
{
class Entity;
class Player;
class Controllable
{
public:
Controllable() = default;
DELETE_COPY_MOVE(Controllable)
virtual Entity& GetEntity() = 0;
Player* GetController() { return controller_; }
const Player* GetController() const { return controller_; }
~Controllable();
private:
Player* controller_ = nullptr;
friend class Player;
};
}

View File

@ -16,10 +16,15 @@ void game::Game::Update()
void game::Game::PlayerJoined(Player& player)
{
player.SetWorld(default_world_.get());
player.SetWorld(default_world_);
}
void game::Game::PlayerLeft(Player& player)
{
}
bool game::Game::PlayerInput(Player& player, PlayerInputType type, bool enabled)
{
return false; // not handled here
}

View File

@ -18,6 +18,8 @@ public:
void PlayerJoined(Player& player);
void PlayerLeft(Player& player);
bool PlayerInput(Player& player, PlayerInputType type, bool enabled);
private:
std::shared_ptr<World> default_world_;

View File

@ -1,15 +1,75 @@
#include "openworld.hpp"
#include "vehicle.hpp"
#include "player.hpp"
#include "vehicle.hpp"
game::OpenWorld::OpenWorld() : World("openworld") {}
void game::OpenWorld::PlayerJoined(Player& player)
{
SpawnVehicle(player);
}
void game::OpenWorld::PlayerInput(Player& player, PlayerInputType type, bool enabled)
{
auto vehicle = player_vehicles_.at(&player);
// player.SendChat("input zmenen: " + std::to_string(static_cast<int>(type)) + "=" + (enabled ? "1" : "0"));
switch (type)
{
case IN_FORWARD:
vehicle->SetInput(VIN_FORWARD, enabled);
break;
case IN_BACKWARD:
vehicle->SetInput(VIN_BACKWARD, enabled);
break;
case IN_LEFT:
vehicle->SetInput(VIN_LEFT, enabled);
break;
case IN_RIGHT:
vehicle->SetInput(VIN_RIGHT, enabled);
break;
case IN_DEBUG1:
if (enabled)
vehicle->SetPosition({ 100.0f, 100.0f, 5.0f });
break;
case IN_DEBUG2:
if (enabled)
SpawnVehicle(player);
break;
default:
break;
}
}
void game::OpenWorld::PlayerLeft(Player& player)
{
RemoveVehicle(player);
}
void game::OpenWorld::RemoveVehicle(Player& player)
{
auto it = player_vehicles_.find(&player);
if (it != player_vehicles_.end())
{
it->second->Remove();
player_vehicles_.erase(it);
}
}
void game::OpenWorld::SpawnVehicle(Player& player)
{
RemoveVehicle(player);
// spawn him car
// random model
const char* vehicles[] = { "pickup", "passat" };
const char* vehicles[] = {"pickup", "passat"};
auto vehicle_name = vehicles[rand() % (sizeof(vehicles) / sizeof(vehicles[0]))];
// ranodm color
@ -22,20 +82,11 @@ void game::OpenWorld::PlayerJoined(Player& player)
}
auto& vehicle = Spawn<Vehicle>(vehicle_name, color);
player.Control(&vehicle);
player_vehicles_[&player] = vehicle.GetEntNum();
}
void game::OpenWorld::PlayerLeft(Player& player)
{
auto it = player_vehicles_.find(&player);
Entity* ent = GetEntity(it->second);
if (ent)
ent->Remove();
player_vehicles_.erase(it);
vehicle.SetPosition({ 100.0f, 100.0f, 5.0f });
player.SetCamera(vehicle.GetEntNum());
player_vehicles_[&player] = &vehicle;
player.SendChat("dostals " + std::string(vehicle_name));
}

View File

@ -1,6 +1,7 @@
#pragma once
#include "world.hpp"
#include "vehicle.hpp"
namespace game
{
@ -11,10 +12,15 @@ public:
OpenWorld();
virtual void PlayerJoined(Player& player) override;
virtual void PlayerInput(Player& player, PlayerInputType type, bool enabled) override;
virtual void PlayerLeft(Player& player) override;
private:
std::map<Player*, net::EntNum> player_vehicles_;
void SpawnVehicle(Player& player);
void RemoveVehicle(Player& player);
private:
std::map<Player*, Vehicle*> player_vehicles_;
};

View File

@ -22,10 +22,10 @@ bool game::Player::ProcessMsg(net::MessageType type, net::InMessage& msg)
void game::Player::Update()
{
if (world_ != known_world_)
if (world_.get() != known_world_)
{
SendWorldMsg();
known_world_ = world_;
known_world_ = world_.get();
known_ents_.clear();
}
@ -33,36 +33,31 @@ void game::Player::Update()
SyncEntities();
}
void game::Player::SetWorld(World* world)
void game::Player::SetWorld(std::shared_ptr<World> world)
{
if (world == world_)
return;
Control(nullptr);
if (world_)
world_->PlayerLeft(*this);
world_ = world;
world_ = std::move(world);
if (world_)
world_->PlayerJoined(*this);
}
void game::Player::Control(Controllable* ctl)
void game::Player::SetCamera(net::EntNum entnum)
{
if (ctl == ctl_)
return;
auto msg = BeginMsg(net::MSG_CAM);
msg.Write(entnum);
}
if (ctl_)
ctl_->controller_ = nullptr; // clear old
ctl_ = ctl;
if (ctl_)
ctl_->controller_ = this;
SendControl();
void game::Player::SendChat(const std::string text)
{
auto msg = BeginMsg(net::MSG_CHAT);
net::ChatMessage chatm = text;
msg.Write(chatm);
}
game::Player::~Player()
@ -78,13 +73,6 @@ void game::Player::SendWorldMsg()
msg.Write(net::MapName(world_->GetMapName()));
}
void game::Player::SendControl()
{
auto msg = BeginMsg(net::MSG_CONTROL);
net::EntNum entnum = ctl_ ? ctl_->GetEntity().GetEntNum() : 0;
msg.Write(entnum);
}
void game::Player::SyncEntities()
{
const auto& ents = world_->GetEntities();
@ -161,8 +149,31 @@ void game::Player::SendDestroyEntity(net::EntNum entnum)
bool game::Player::ProcessInputMsg(net::InMessage& msg)
{
if (!msg.Read(in_))
uint8_t val;
if (!msg.Read(val))
return false;
bool enabled = false;
if (val & 128)
{
enabled = true;
val &= ~128;
}
Input(static_cast<PlayerInputType>(val), enabled);
return true;
}
void game::Player::Input(PlayerInputType type, bool enabled)
{
if (enabled)
in_ |= (1 << type);
else
in_ &= ~(1 << type);
if (!game_.PlayerInput(*this, type, enabled))
{
if (world_)
world_->PlayerInput(*this, type, enabled);
}
}

View File

@ -8,7 +8,6 @@
#include "player_input.hpp"
#include "game.hpp"
#include "controllable.hpp"
namespace game
{
@ -17,13 +16,6 @@ class World;
class Entity;
class Vehicle;
enum PlayerState
{
PS_NONE,
PS_CHARACTER,
PS_VEHICLE,
};
class Player : public net::MsgProducer
{
public:
@ -33,8 +25,10 @@ public:
bool ProcessMsg(net::MessageType type, net::InMessage& msg);
void Update();
void SetWorld(World* world);
void Control(Controllable* ctl);
void SetWorld(std::shared_ptr<World> world);
void SetCamera(net::EntNum entnum);
void SendChat(const std::string text);
PlayerInputFlags GetInput() const { return in_; }
@ -42,7 +36,6 @@ public:
private:
void SendWorldMsg();
void SendControl();
// entities sync
void SyncEntities();
@ -54,19 +47,18 @@ private:
// msg handlers
bool ProcessInputMsg(net::InMessage& msg);
// events
void Input(PlayerInputType type, bool enabled);
private:
Game& game_;
std::string name_;
World* world_ = nullptr;
std::shared_ptr<World> world_ = nullptr;
World* known_world_ = nullptr;
std::set<net::EntNum> known_ents_;
PlayerInputFlags in_ = 0;
PlayerState state_ = PS_NONE;
Controllable* ctl_ = nullptr;
};
}

View File

@ -6,18 +6,22 @@ namespace game
{
using PlayerInputFlags = uint16_t;
enum PlayerInputFlag : PlayerInputFlags
enum PlayerInputType : uint8_t
{
IN_FORWARD = 1 << 0,
IN_BACKWARD = 1 << 1,
IN_LEFT = 1 << 2,
IN_RIGHT = 1 << 3,
IN_JUMP = 1 << 4,
IN_CROUCH = 1 << 5,
IN_USE = 1 << 6,
IN_ATTACK = 1 << 7,
IN_DEBUG1 = 1 << 8,
IN_DEBUG2 = 1 << 9,
IN_DEBUG3 = 1 << 10,
IN_FORWARD,
IN_BACKWARD,
IN_LEFT,
IN_RIGHT,
IN_JUMP,
IN_CROUCH,
IN_USE,
IN_ATTACK,
IN_DEBUG1,
IN_DEBUG2,
IN_DEBUG3,
IN_DEBUG4,
IN_DEBUG5,
IN__COUNT,
};
}

View File

@ -109,6 +109,22 @@ void game::Vehicle::SendInitData(Player& player, net::OutMessage& msg) const
net::ModelName name(model_name_);
msg.Write(name);
net::WriteRGB(msg, color_); // primary color
WriteState(msg);
}
void game::Vehicle::SetInput(VehicleInputType type, bool enable)
{
if (enable)
in_ |= (1 << type);
else
in_ &= ~(1 << type);
}
void game::Vehicle::SetPosition(const glm::vec3& pos)
{
auto t = body_->getWorldTransform();
t.setOrigin(btVector3(pos.x, pos.y, pos.z));
body_->setWorldTransform(t);
}
game::Vehicle::~Vehicle()
@ -130,16 +146,6 @@ void game::Vehicle::ProcessInput()
float engineForce = 0;
float breakingForce = 0;
// process input
PlayerInputFlags in = GetController() ? GetController()->GetInput() : 0;
if (in & IN_DEBUG1)
{
auto t = body_->getWorldTransform();
t.setOrigin(btVector3(100, 100, 5));
body_->setWorldTransform(t);
}
float speed = vehicle_->getCurrentSpeedKmHour();
float maxsc = .5f;
@ -151,14 +157,19 @@ void game::Vehicle::ProcessInput()
float t_delta = 1.0f / 25.0f;
if (in & IN_FORWARD)
const bool in_forward = in_ & (1 << VIN_FORWARD);
const bool in_backward = in_ & (1 << VIN_BACKWARD);
const bool in_left = in_ & (1 << VIN_LEFT);
const bool in_right = in_ & (1 << VIN_RIGHT);
if (in_forward)
{
if (speed < -1)
breakingForce = maxBreakingForce;
else
engineForce = maxEngineForce;
}
if (in & IN_BACKWARD)
if (in_backward)
{
if (speed > 1)
breakingForce = maxBreakingForce;
@ -167,19 +178,19 @@ void game::Vehicle::ProcessInput()
}
// idle breaking
if (!(in & IN_FORWARD) && !(in & IN_BACKWARD))
if (!in_forward && !in_backward)
{
breakingForce = maxBreakingForce * 0.05f;
}
if (in & IN_LEFT)
if (in_left)
{
if (steering_ < steeringClamp)
steering_ += steeringIncrement * t_delta;
}
else
{
if (in & IN_RIGHT)
if (in_right)
{
if (steering_ > -steeringClamp)
steering_ -= steeringIncrement * t_delta;
@ -229,9 +240,8 @@ void game::Vehicle::UpdateWheels()
}
}
void game::Vehicle::SendUpdateMsg()
void game::Vehicle::WriteState(net::OutMessage& msg) const
{
auto msg = BeginEntMsg(net::EMSG_UPDATE);
msg.Write(flags_);
net::WriteTransform(msg, root_.local);
@ -245,24 +255,10 @@ void game::Vehicle::SendUpdateMsg()
msg.Write<net::WheelZOffsetQ>(wheel.z_offset);
msg.Write<net::RotationSpeedQ>(wheel.speed);
}
// TEMP wheels
// TODO: REMOVE
// for (size_t i =0; i < vehicle_->getNumWheels(); ++i)
// {
// vehicle_->updateWheelTransform(i, true);
// btTransform tr = vehicle_->getWheelTransformWS(i);
// Transform trans;
// trans.SetBtTransform(tr);
// net::WriteTransform(msg, trans);
// // static glm::vec3 min_angles(1000.0f);
// // static glm::vec3 max_angles(-1000.0f);
// // min_angles = glm::min(min_angles, angles);
// // max_angles= glm::max(max_angles, angles);
// // std::cout << angles.x << " " << angles.y << " " << angles.z << " | " <<std::endl;
// }
}
void game::Vehicle::SendUpdateMsg()
{
auto msg = BeginEntMsg(net::EMSG_UPDATE);
WriteState(msg);
}

View File

@ -5,7 +5,6 @@
#include "assets/vehiclemdl.hpp"
#include "collision/motionstate.hpp"
#include "controllable.hpp"
#include "entity.hpp"
#include "world.hpp"
#include "vehicleflags.hpp"
@ -22,7 +21,18 @@ struct VehicleWheelState
float z_offset = 0.0f; // [m] against model definition
};
class Vehicle : public Entity, public Controllable
using VehicleInputFlags = uint8_t;
enum VehicleInputType
{
VIN_FORWARD,
VIN_BACKWARD,
VIN_LEFT,
VIN_RIGHT,
VIN_HANDBRAKE,
};
class Vehicle : public Entity
{
public:
using Super = Entity;
@ -32,14 +42,16 @@ public:
virtual void Update() override;
virtual void SendInitData(Player& player, net::OutMessage& msg) const override;
// Controllable
Entity& GetEntity() override { return *this; };
void SetInput(VehicleInputType type, bool enable);
void SetPosition(const glm::vec3& pos);
virtual ~Vehicle();
private:
void ProcessInput();
void UpdateWheels();
void WriteState(net::OutMessage& msg) const;
void SendUpdateMsg();
private:
@ -58,6 +70,8 @@ private:
std::array<VehicleWheelState, MAX_WHEELS> wheels_;
VehicleFlags flags_;
VehicleInputFlags in_ = 0;
};
} // namespace game

View File

@ -6,6 +6,7 @@
#include "collision/dynamicsworld.hpp"
#include "entity.hpp"
#include "net/defs.hpp"
#include "player_input.hpp"
namespace game
{
@ -33,6 +34,7 @@ public:
// events
virtual void PlayerJoined(Player& player) {}
virtual void PlayerInput(Player& player, PlayerInputType type, bool enabled) {}
virtual void PlayerLeft(Player& player) {}
Entity* GetEntity(net::EntNum entnum);

View File

@ -30,8 +30,11 @@ bool game::view::ClientSession::ProcessSingleMessage(net::MessageType type, net:
case net::MSG_CHWORLD:
return ProcessWorldMsg(msg);
case net::MSG_CONTROL:
return ProcessControlMsg(msg);
case net::MSG_CAM:
return ProcessCameraMsg(msg);
case net::MSG_CHAT:
return ProcessChatMsg(msg);
default:
// try pass the msg to world
@ -66,9 +69,9 @@ glm::mat4 game::view::ClientSession::GetViewMatrix() const
{
glm::vec3 center(0, 0, 3);
if (world_ && ctl_)
if (world_ && follow_ent_)
{
auto ent = world_->GetEntity(ctl_);
auto ent = world_->GetEntity(follow_ent_);
if (ent)
center += ent->GetRoot().local.position;
}
@ -103,10 +106,20 @@ bool game::view::ClientSession::ProcessWorldMsg(net::InMessage& msg)
return true;
}
bool game::view::ClientSession::ProcessControlMsg(net::InMessage& msg)
bool game::view::ClientSession::ProcessCameraMsg(net::InMessage& msg)
{
if (!msg.Read(ctl_))
if (!msg.Read(follow_ent_))
return false;
return true;
}
bool game::view::ClientSession::ProcessChatMsg(net::InMessage& msg)
{
net::ChatMessage chatm;
if (!msg.Read(chatm))
return false;
app_.AddChatMessagePrefix("Server", chatm);
return true;
}

View File

@ -34,7 +34,8 @@ public:
private:
// msg handlers
bool ProcessWorldMsg(net::InMessage& msg);
bool ProcessControlMsg(net::InMessage& msg);
bool ProcessCameraMsg(net::InMessage& msg);
bool ProcessChatMsg(net::InMessage& msg);
private:
App& app_;
@ -42,7 +43,7 @@ private:
std::unique_ptr<WorldView> world_;
float yaw_ = 0.0f, pitch_ = 0.0f;
net::EntNum ctl_ = 0;
net::EntNum follow_ent_ = 0;
};

View File

@ -31,7 +31,11 @@ std::unique_ptr<game::view::VehicleView> game::view::VehicleView::InitFromMsg(Wo
auto model = assets::CacheManager::GetVehicleModel("data/" + std::string(modelname) + ".veh");
return std::make_unique<VehicleView>(world, std::move(model), color);
auto vehicle = std::make_unique<VehicleView>(world, std::move(model), color);
vehicle->ReadState(msg);
vehicle->root_trans_[0] = vehicle->root_trans_[1];
return vehicle;
}
bool game::view::VehicleView::ProcessMsg(net::EntMsgType type, net::InMessage& msg)
@ -125,7 +129,7 @@ void game::view::VehicleView::Draw(gfx::DrawList& dlist)
}
}
bool game::view::VehicleView::ProcessUpdateMsg(net::InMessage& msg)
bool game::view::VehicleView::ReadState(net::InMessage& msg)
{
root_trans_[0] = root_.local;
auto& root_trans = root_trans_[1];
@ -151,5 +155,9 @@ bool game::view::VehicleView::ProcessUpdateMsg(net::InMessage& msg)
wheel.steering = i < 2 ? steering : 0.0f;
}
return true;
return true;}
bool game::view::VehicleView::ProcessUpdateMsg(net::InMessage& msg)
{
return ReadState(msg);
}

View File

@ -31,6 +31,7 @@ public:
virtual void Draw(gfx::DrawList& dlist) override;
private:
bool ReadState(net::InMessage& msg);
bool ProcessUpdateMsg(net::InMessage& msg);
private:

View File

@ -20,6 +20,10 @@ enum MessageType : uint8_t
// IN <PlayerInputFlags> <ViewYawQ> <ViewPitchQ>
MSG_IN,
/*~~~~~~~~ Session ~~~~~~~~*/
// CHAT <ChatMessage>
MSG_CHAT,
/*~~~~~~~~ World ~~~~~~~~*/
// CHWORLD <MapName>
MSG_CHWORLD,
@ -32,8 +36,8 @@ enum MessageType : uint8_t
// ENTDESTROY <EntNum>
MSG_ENTDESTROY,
// CONTROL <EntNum>
MSG_CONTROL,
// CAM <EntNum>
MSG_CAM,
/*~~~~~~~~~~~~~~~~*/
MSG_COUNT,
@ -42,6 +46,7 @@ enum MessageType : uint8_t
using PlayerName = FixedStr<24>;
using MapName = FixedStr<32>;
using ModelName = FixedStr<64>;
using ChatMessage = FixedStr<1024>;
// pi approx fraction
constexpr long long PI_N = 245850922;