Compare commits
No commits in common. "7832c1b40cadea41155dd8dc8b4255aa57576a64" and "d0b30ed56ba7b35a4809ec857bdf993365d7d8d3" have entirely different histories.
7832c1b40c
...
d0b30ed56b
@ -130,8 +130,6 @@ set(SERVER_ONLY_SOURCES
|
||||
"src/game/destroyed_object.cpp"
|
||||
"src/game/drivable_vehicle.hpp"
|
||||
"src/game/drivable_vehicle.cpp"
|
||||
"src/game/enterable_world.hpp"
|
||||
"src/game/enterable_world.cpp"
|
||||
"src/game/entity.hpp"
|
||||
"src/game/entity.cpp"
|
||||
"src/game/game.hpp"
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 110 KiB |
@ -95,7 +95,7 @@ int assets::MapLoader::GetPercent() const
|
||||
return 10;
|
||||
|
||||
case ML_LOAD_MODELS:
|
||||
return 60 + (model_names_.size() > 0 ? (models_.size() * 30 / model_names_.size()) : 30);
|
||||
return 60 + models_.size() * 30 / model_names_.size();
|
||||
|
||||
case ML_STRUCTS:
|
||||
return 90;
|
||||
|
||||
@ -4,10 +4,10 @@
|
||||
#include "utils/math.hpp"
|
||||
#include "world.hpp"
|
||||
|
||||
game::Character::Character(World& world, const CharacterTuning& tuning)
|
||||
: Super(world, net::ET_CHARACTER), tuning_(tuning), bt_shape_(tuning_.shape.radius, tuning_.shape.height)
|
||||
game::Character::Character(World& world, const CharacterInfo& info)
|
||||
: Super(world, net::ET_CHARACTER), shape_(info.shape), bt_shape_(shape_.radius, shape_.height)
|
||||
{
|
||||
z_offset_ = tuning_.shape.height * 0.5f + tuning_.shape.radius - 0.05f;
|
||||
z_offset_ = shape_.height * 0.5f + shape_.radius - 0.05f;
|
||||
|
||||
sk_ = SkeletonInstance(assets::CacheManager::GetSkeleton("data/human.sk"), &root_);
|
||||
animstate_.idle_anim_idx = GetAnim("idle");
|
||||
@ -53,8 +53,8 @@ void game::Character::SendInitData(Player& player, net::OutMessage& msg) const
|
||||
Super::SendInitData(player, msg);
|
||||
|
||||
// write clothes
|
||||
msg.Write<net::NumClothes>(tuning_.clothes.size());
|
||||
for (const auto& clothes : tuning_.clothes)
|
||||
msg.Write<net::NumClothes>(clothes_.size());
|
||||
for (const auto& clothes : clothes_)
|
||||
{
|
||||
msg.Write(net::ClothesName(clothes.name));
|
||||
net::WriteRGB(msg, clothes.color);
|
||||
@ -120,6 +120,11 @@ void game::Character::SetPosition(const glm::vec3& position)
|
||||
SyncControllerTransform();
|
||||
}
|
||||
|
||||
void game::Character::AddClothes(std::string name, const glm::vec3& color)
|
||||
{
|
||||
clothes_.emplace_back(std::move(name), color);
|
||||
}
|
||||
|
||||
void game::Character::SetMainAnim(const std::string& anim_name)
|
||||
{
|
||||
animstate_.idle_anim_idx = GetAnim(anim_name);
|
||||
|
||||
@ -6,7 +6,6 @@
|
||||
#include "character_anim_state.hpp"
|
||||
#include "character_sync.hpp"
|
||||
#include "entity.hpp"
|
||||
#include "character_tuning.hpp"
|
||||
|
||||
namespace game
|
||||
{
|
||||
@ -23,6 +22,25 @@ enum CharacterInputType
|
||||
CIN_SPRINT,
|
||||
};
|
||||
|
||||
struct CapsuleShape
|
||||
{
|
||||
float radius;
|
||||
float height;
|
||||
|
||||
CapsuleShape(float radius, float height) : radius(radius), height(height) {}
|
||||
};
|
||||
|
||||
struct CharacterInfo
|
||||
{
|
||||
CapsuleShape shape = CapsuleShape(0.3f, 0.75f);
|
||||
};
|
||||
|
||||
struct CharacterClothes
|
||||
{
|
||||
std::string name;
|
||||
glm::vec3 color;
|
||||
};
|
||||
|
||||
class CharacterPhysicsController
|
||||
{
|
||||
public:
|
||||
@ -47,13 +65,11 @@ class Character : public Entity
|
||||
public:
|
||||
using Super = Entity;
|
||||
|
||||
Character(World& world, const CharacterTuning& tuning);
|
||||
Character(World& world, const CharacterInfo& info);
|
||||
|
||||
virtual void Update() override;
|
||||
virtual void SendInitData(Player& player, net::OutMessage& msg) const override;
|
||||
|
||||
const CharacterTuning& GetTuning() const { return tuning_; }
|
||||
|
||||
void EnablePhysics(bool enable);
|
||||
|
||||
void SetInput(CharacterInputType type, bool enable);
|
||||
@ -64,6 +80,8 @@ public:
|
||||
|
||||
void SetPosition(const glm::vec3& position);
|
||||
|
||||
void AddClothes(std::string name, const glm::vec3& color);
|
||||
|
||||
void SetMainAnim(const std::string& anim_name);
|
||||
|
||||
~Character() override = default;
|
||||
@ -82,7 +100,7 @@ private:
|
||||
assets::AnimIdx GetAnim(const std::string& name) const;
|
||||
|
||||
private:
|
||||
CharacterTuning tuning_;
|
||||
CapsuleShape shape_;
|
||||
|
||||
// glm::vec3 position_ = glm::vec3(0.0f);
|
||||
// glm::vec3 velocity_ = glm::vec3(0.0f);
|
||||
@ -103,6 +121,8 @@ private:
|
||||
|
||||
CharacterSyncState sync_[2];
|
||||
size_t sync_current_ = 0;
|
||||
|
||||
std::vector<CharacterClothes> clothes_;
|
||||
};
|
||||
|
||||
} // namespace game
|
||||
@ -1,30 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace game
|
||||
{
|
||||
|
||||
struct CharacterShape
|
||||
{
|
||||
float radius;
|
||||
float height;
|
||||
|
||||
CharacterShape(float radius, float height) : radius(radius), height(height) {}
|
||||
};
|
||||
|
||||
struct CharacterConfigClothes
|
||||
{
|
||||
std::string name;
|
||||
uint32_t color = 0xFFFFFF;
|
||||
};
|
||||
|
||||
struct CharacterTuning
|
||||
{
|
||||
CharacterShape shape = CharacterShape(0.3f, 0.75f);
|
||||
std::vector<CharacterConfigClothes> clothes;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
#include "controllable_character.hpp"
|
||||
#include "drivable_vehicle.hpp"
|
||||
|
||||
game::ControllableCharacter::ControllableCharacter(World& world, const CharacterTuning& tuning) : Character(world, tuning) {}
|
||||
game::ControllableCharacter::ControllableCharacter(World& world) : Character(world, CharacterInfo{}) {}
|
||||
|
||||
void game::ControllableCharacter::SetVehicle(DrivableVehicle* vehicle, uint32_t seat)
|
||||
{
|
||||
|
||||
@ -12,7 +12,7 @@ class ControllableCharacter : public Character
|
||||
public:
|
||||
using Super = Character;
|
||||
|
||||
ControllableCharacter(World& world, const CharacterTuning& tuning);
|
||||
ControllableCharacter(World& world);
|
||||
|
||||
void SetVehicle(DrivableVehicle* vehicle, uint32_t seat);
|
||||
|
||||
|
||||
@ -22,9 +22,6 @@ public:
|
||||
|
||||
bool SetPassenger(uint32_t seat_idx, ControllableCharacter* character);
|
||||
|
||||
size_t GetNumSeats() const { return seats_.size(); }
|
||||
ControllableCharacter* GetPassenger(size_t idx) const { return seats_[idx].occupant; }
|
||||
|
||||
~DrivableVehicle() override;
|
||||
|
||||
private:
|
||||
|
||||
@ -1,131 +0,0 @@
|
||||
#include "enterable_world.hpp"
|
||||
|
||||
#include "player_character.hpp"
|
||||
#include "drivable_vehicle.hpp"
|
||||
|
||||
game::EnterableWorld::EnterableWorld(std::string mapname) : World(std::move(mapname)) {}
|
||||
|
||||
game::PlayerCharacter& game::EnterableWorld::InsertPlayer(Player& player, const CharacterTuning& tuning, const glm::vec3& pos, float yaw)
|
||||
{
|
||||
return CreatePlayerCharacter(player, tuning, pos, yaw);
|
||||
}
|
||||
|
||||
void game::EnterableWorld::PlayerInput(Player& player, PlayerInputType type, bool enabled)
|
||||
{
|
||||
auto it = player_characters_.find(&player);
|
||||
if (it == player_characters_.end())
|
||||
return;
|
||||
|
||||
auto character = it->second;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
// case IN_DEBUG1:
|
||||
// if (enabled)
|
||||
// {
|
||||
// if (character->GetVehicle())
|
||||
// character->GetVehicle()->SetPosition({100.0f, 100.0f, 5.0f});
|
||||
// else
|
||||
// character->SetPosition({100.0f, 100.0f, 5.0f});
|
||||
// }
|
||||
// break;
|
||||
|
||||
default:
|
||||
character->ProcessInput(type, enabled);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void game::EnterableWorld::PlayerViewAnglesChanged(Player& player, float yaw, float pitch)
|
||||
{
|
||||
auto it = player_characters_.find(&player);
|
||||
if (it == player_characters_.end())
|
||||
return;
|
||||
|
||||
auto character = it->second;
|
||||
|
||||
character->SetForwardYaw(yaw);
|
||||
}
|
||||
|
||||
void game::EnterableWorld::RemovePlayer(Player& player)
|
||||
{
|
||||
RemovePlayerCharacter(player);
|
||||
}
|
||||
|
||||
game::PlayerCharacter& game::EnterableWorld::MovePlayerToWorld(Player& player, EnterableWorld& new_world, const glm::vec3& pos, float yaw)
|
||||
{
|
||||
auto old_character = player_characters_.at(&player);
|
||||
auto& tuning = old_character->GetTuning();
|
||||
RemovePlayer(player);
|
||||
|
||||
player.SetWorld(&new_world);
|
||||
auto& new_character = new_world.InsertPlayer(player, tuning, pos, yaw);
|
||||
|
||||
return new_character;
|
||||
}
|
||||
|
||||
void game::EnterableWorld::MoveVehicleToWorld(DrivableVehicle& vehicle, EnterableWorld& new_world, const glm::vec3& pos,
|
||||
float yaw)
|
||||
{
|
||||
if (&vehicle.GetWorld() != this)
|
||||
throw std::runtime_error("Attempt to move vehicle from other world");
|
||||
|
||||
auto& tuning = vehicle.GetTuning();
|
||||
auto& new_vehicle = new_world.Spawn<DrivableVehicle>(tuning);
|
||||
new_vehicle.SetPosition(pos);
|
||||
// TODO: yaw
|
||||
|
||||
// move passengers
|
||||
size_t num_seats = vehicle.GetNumSeats();
|
||||
for (size_t i = 0; i < num_seats; ++i)
|
||||
{
|
||||
auto passenger = vehicle.GetPassenger(i);
|
||||
if (!passenger)
|
||||
continue; // empty seat
|
||||
|
||||
auto player_passenger = dynamic_cast<PlayerCharacter*>(passenger);
|
||||
if (!player_passenger)
|
||||
continue; // not player but npc, will be ejected automatically upon vehicle deletion
|
||||
|
||||
auto player = player_passenger->GetPlayer();
|
||||
if (!player)
|
||||
continue; // moved already or sth
|
||||
|
||||
auto& new_character = MovePlayerToWorld(*player, new_world, glm::vec3(0.0f), 0.0f);
|
||||
new_character.SetVehicle(&new_vehicle, i);
|
||||
}
|
||||
|
||||
vehicle.Remove();
|
||||
}
|
||||
|
||||
game::PlayerCharacter* game::EnterableWorld::GetPlayerCharacter(Player& player)
|
||||
{
|
||||
auto it = player_characters_.find(&player);
|
||||
if (it == player_characters_.end())
|
||||
return nullptr;
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
game::PlayerCharacter& game::EnterableWorld::CreatePlayerCharacter(Player& player, const CharacterTuning& tuning, const glm::vec3& position, float yaw)
|
||||
{
|
||||
RemovePlayerCharacter(player);
|
||||
|
||||
auto& character = Spawn<PlayerCharacter>(player, tuning);
|
||||
character.SetPosition(position);
|
||||
character.SetYaw(yaw);
|
||||
|
||||
player_characters_[&player] = &character;
|
||||
return character;
|
||||
}
|
||||
|
||||
void game::EnterableWorld::RemovePlayerCharacter(Player& player)
|
||||
{
|
||||
auto character = GetPlayerCharacter(player);
|
||||
if (character)
|
||||
{
|
||||
character->DetachFromPlayer();
|
||||
character->Remove();
|
||||
}
|
||||
}
|
||||
@ -1,41 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "world.hpp"
|
||||
|
||||
namespace game
|
||||
{
|
||||
|
||||
class Player;
|
||||
class PlayerCharacter;
|
||||
class CharacterTuning;
|
||||
class DrivableVehicle;
|
||||
|
||||
class EnterableWorld : public World
|
||||
{
|
||||
public:
|
||||
EnterableWorld(std::string mapname);
|
||||
|
||||
// events
|
||||
virtual PlayerCharacter& InsertPlayer(Player& player, const CharacterTuning& tuning, const glm::vec3& pos, float yaw);
|
||||
virtual void PlayerInput(Player& player, PlayerInputType type, bool enabled);
|
||||
virtual void PlayerViewAnglesChanged(Player& player, float yaw, float pitch);
|
||||
virtual void RemovePlayer(Player& player);
|
||||
|
||||
// moves
|
||||
PlayerCharacter& MovePlayerToWorld(Player& player, EnterableWorld& new_world, const glm::vec3& pos, float yaw);
|
||||
void MoveVehicleToWorld(DrivableVehicle& vehicle, EnterableWorld& new_world, const glm::vec3& pos, float yaw);
|
||||
|
||||
PlayerCharacter* GetPlayerCharacter(Player& player);
|
||||
|
||||
private:
|
||||
PlayerCharacter& CreatePlayerCharacter(Player& player, const CharacterTuning& tuning, const glm::vec3& position, float yaw);
|
||||
void RemovePlayerCharacter(Player& player);
|
||||
|
||||
private:
|
||||
std::map<Player*, PlayerCharacter*> player_characters_;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
@ -24,8 +24,6 @@ public:
|
||||
net::EntNum GetEntNum() const { return entnum_; }
|
||||
net::EntType GetViewType() const { return viewtype_; }
|
||||
|
||||
World& GetWorld() const { return world_; }
|
||||
|
||||
virtual void SendInitData(Player& player, net::OutMessage& msg) const;
|
||||
|
||||
virtual void Update();
|
||||
|
||||
@ -1,147 +1,47 @@
|
||||
#include "game.hpp"
|
||||
|
||||
#include "openworld.hpp"
|
||||
#include "player.hpp"
|
||||
#include "player_character.hpp"
|
||||
|
||||
static constexpr glm::vec3 openworld_spawn(100.0f, 100.0f, 1.0f);
|
||||
static constexpr glm::vec3 test_spawn(0.0f, 0.0f, 1.0f);
|
||||
|
||||
static uint32_t GetRandomColor24()
|
||||
{
|
||||
uint8_t r, g, b;
|
||||
r = rand() % 256;
|
||||
g = rand() % 256;
|
||||
b = rand() % 256;
|
||||
return (b << 16) | (g << 8) | r;
|
||||
}
|
||||
#include "openworld.hpp"
|
||||
|
||||
game::Game::Game()
|
||||
{
|
||||
openworld_ = std::make_shared<OpenWorld>();
|
||||
all_worlds_.push_back(openworld_.get());
|
||||
default_world_ = std::make_shared<OpenWorld>();
|
||||
|
||||
testworld_ = std::make_shared<EnterableWorld>("testarena");
|
||||
all_worlds_.push_back(testworld_.get());
|
||||
}
|
||||
|
||||
void game::Game::Update()
|
||||
{
|
||||
for (auto world : all_worlds_)
|
||||
{
|
||||
world->Update(40);
|
||||
}
|
||||
default_world_->Update(40);
|
||||
}
|
||||
|
||||
void game::Game::FinishFrame()
|
||||
{
|
||||
for (auto world : all_worlds_)
|
||||
{
|
||||
world->FinishFrame();
|
||||
}
|
||||
default_world_->FinishFrame();
|
||||
}
|
||||
|
||||
void game::Game::PlayerJoined(Player& player)
|
||||
{
|
||||
player.SetWorld(default_world_);
|
||||
|
||||
players_.insert(&player);
|
||||
BroadcastChat(player.GetName() + "^r se připoojil jupí jupí jupííí");
|
||||
|
||||
players_.insert({&player, PlayerGameInfo(player)});
|
||||
auto& player_info = players_.at(&player);
|
||||
player_info.world = openworld_.get();
|
||||
player.SetWorld(openworld_.get());
|
||||
|
||||
CharacterTuning tuning{};
|
||||
tuning.clothes.push_back({"tshirt", GetRandomColor24()});
|
||||
tuning.clothes.push_back({"shorts", GetRandomColor24()});
|
||||
|
||||
openworld_->InsertPlayer(player, tuning, openworld_spawn, 0.0f);
|
||||
}
|
||||
|
||||
void game::Game::PlayerViewAnglesChanged(Player& player, float yaw, float pitch)
|
||||
{
|
||||
auto world = FindPlayerWorld(player);
|
||||
if (world)
|
||||
world->PlayerViewAnglesChanged(player, yaw, pitch);
|
||||
}
|
||||
|
||||
void game::Game::PlayerInput(Player& player, PlayerInputType type, bool enabled)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case IN_DEBUG2: {
|
||||
if (!enabled)
|
||||
return;
|
||||
|
||||
auto& player_info = players_.at(&player);
|
||||
|
||||
if (player_info.world == openworld_.get())
|
||||
{
|
||||
MovePlayerToWorld(player_info, testworld_.get(), test_spawn, 0.0f, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
MovePlayerToWorld(player_info, openworld_.get(), openworld_spawn, 0.0f, true);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
auto world = FindPlayerWorld(player);
|
||||
if (world)
|
||||
world->PlayerInput(player, type, enabled);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void game::Game::PlayerLeft(Player& player)
|
||||
{
|
||||
auto world = FindPlayerWorld(player);
|
||||
if (world)
|
||||
world->RemovePlayer(player);
|
||||
|
||||
players_.erase(&player);
|
||||
|
||||
BroadcastChat(player.GetName() + "^r se vodpojil zmrd");
|
||||
}
|
||||
|
||||
bool game::Game::PlayerInput(Player& player, PlayerInputType type, bool enabled)
|
||||
{
|
||||
return false; // not handled here
|
||||
}
|
||||
|
||||
void game::Game::BroadcastChat(const std::string& text)
|
||||
{
|
||||
for (auto& [player, info] : players_)
|
||||
for (auto player : players_)
|
||||
{
|
||||
player->SendChat(text);
|
||||
}
|
||||
}
|
||||
|
||||
void game::Game::MovePlayerToWorld(PlayerGameInfo& player_info, EnterableWorld* new_world, const glm::vec3& pos,
|
||||
float yaw, bool with_vehicle)
|
||||
{
|
||||
auto& player = player_info.player;
|
||||
auto& world = *player_info.world;
|
||||
|
||||
DrivableVehicle* vehicle = nullptr;
|
||||
|
||||
if (with_vehicle)
|
||||
{
|
||||
auto character = world.GetPlayerCharacter(player);
|
||||
vehicle = character->GetVehicle();
|
||||
}
|
||||
|
||||
if (vehicle)
|
||||
world.MoveVehicleToWorld(*vehicle, *new_world, pos, yaw);
|
||||
else
|
||||
world.MovePlayerToWorld(player, *new_world, pos, yaw);
|
||||
|
||||
player_info.world = new_world;
|
||||
}
|
||||
|
||||
game::EnterableWorld* game::Game::FindPlayerWorld(Player& player) const
|
||||
{
|
||||
auto it = players_.find(&player);
|
||||
if (it == players_.end())
|
||||
return nullptr;
|
||||
|
||||
return it->second.world;
|
||||
}
|
||||
|
||||
@ -1,23 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include "enterable_world.hpp"
|
||||
#include "openworld.hpp"
|
||||
#include "world.hpp"
|
||||
|
||||
namespace game
|
||||
{
|
||||
|
||||
class Player;
|
||||
|
||||
struct PlayerGameInfo
|
||||
{
|
||||
Player& player;
|
||||
EnterableWorld* world = nullptr;
|
||||
|
||||
PlayerGameInfo(Player& player) : player(player) {}
|
||||
};
|
||||
|
||||
class Game
|
||||
{
|
||||
public:
|
||||
@ -27,23 +19,15 @@ public:
|
||||
void FinishFrame();
|
||||
|
||||
void PlayerJoined(Player& player);
|
||||
void PlayerViewAnglesChanged(Player& player, float yaw, float pitch);
|
||||
void PlayerInput(Player& player, PlayerInputType type, bool enabled);
|
||||
void PlayerLeft(Player& player);
|
||||
bool PlayerInput(Player& player, PlayerInputType type, bool enabled);
|
||||
|
||||
private:
|
||||
void BroadcastChat(const std::string& text);
|
||||
|
||||
void MovePlayerToWorld(PlayerGameInfo& player_info, EnterableWorld* new_world, const glm::vec3& pos, float yaw, bool with_vehicle = false);
|
||||
|
||||
EnterableWorld* FindPlayerWorld(Player& player) const;
|
||||
|
||||
private:
|
||||
std::shared_ptr<OpenWorld> openworld_;
|
||||
std::shared_ptr<EnterableWorld> testworld_;
|
||||
|
||||
std::vector<World*> all_worlds_; // for common update etc.
|
||||
std::map<Player*, PlayerGameInfo> players_;
|
||||
std::shared_ptr<World> default_world_;
|
||||
std::set<Player*> players_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
#include <array>
|
||||
#include <iostream>
|
||||
|
||||
game::NpcCharacter::NpcCharacter(World& world, const CharacterTuning& tuning) : Super(world, tuning) {
|
||||
game::NpcCharacter::NpcCharacter(World& world) : Super(world) {
|
||||
VehicleChanged();
|
||||
}
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ class NpcCharacter : public ControllableCharacter
|
||||
public:
|
||||
using Super = ControllableCharacter;
|
||||
|
||||
NpcCharacter(World& world, const CharacterTuning& tuning);
|
||||
NpcCharacter(World& world);
|
||||
|
||||
virtual void VehicleChanged() override;
|
||||
|
||||
|
||||
@ -45,8 +45,10 @@ static uint32_t GetRandomColor24()
|
||||
return (b << 16) | (g << 8) | r;
|
||||
}
|
||||
|
||||
game::OpenWorld::OpenWorld() : EnterableWorld("openworld")
|
||||
game::OpenWorld::OpenWorld() : World("openworld")
|
||||
{
|
||||
srand(time(NULL));
|
||||
|
||||
// spawn bots
|
||||
for (size_t i = 0; i < 100; ++i)
|
||||
{
|
||||
@ -79,6 +81,97 @@ game::OpenWorld::OpenWorld() : EnterableWorld("openworld")
|
||||
|
||||
}
|
||||
|
||||
void game::OpenWorld::Update(int64_t delta_time)
|
||||
{
|
||||
World::Update(delta_time);
|
||||
|
||||
}
|
||||
|
||||
void game::OpenWorld::PlayerJoined(Player& player)
|
||||
{
|
||||
CreatePlayerCharacter(player);
|
||||
}
|
||||
|
||||
void game::OpenWorld::PlayerInput(Player& player, PlayerInputType type, bool enabled)
|
||||
{
|
||||
auto character = player_characters_.at(&player);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case IN_DEBUG1:
|
||||
if (enabled)
|
||||
{
|
||||
if (character->GetVehicle())
|
||||
character->GetVehicle()->SetPosition({100.0f, 100.0f, 5.0f});
|
||||
else
|
||||
character->SetPosition({100.0f, 100.0f, 5.0f});
|
||||
}
|
||||
break;
|
||||
|
||||
case IN_DEBUG2:
|
||||
if (enabled)
|
||||
CreatePlayerCharacter(player);
|
||||
break;
|
||||
|
||||
default:
|
||||
character->ProcessInput(type, enabled);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void game::OpenWorld::PlayerViewAnglesChanged(Player& player, float yaw, float pitch)
|
||||
{
|
||||
auto character = player_characters_.at(&player);
|
||||
character->SetForwardYaw(yaw);
|
||||
}
|
||||
|
||||
void game::OpenWorld::PlayerLeft(Player& player)
|
||||
{
|
||||
RemovePlayerCharacter(player);
|
||||
}
|
||||
|
||||
void game::OpenWorld::DestructibleDestroyed(net::ObjNum num, std::unique_ptr<MapObjectCollision> col)
|
||||
{
|
||||
auto& destroyed_obj = Spawn<DestroyedObject>(std::move(col));
|
||||
|
||||
Schedule(120000, [this, num] {
|
||||
RespawnObj(num);
|
||||
});
|
||||
}
|
||||
|
||||
template <class T, typename... TArgs>
|
||||
static T& SpawnRandomCharacter(game::OpenWorld& world, TArgs&&... args)
|
||||
{
|
||||
auto& character = world.Spawn<T>(std::forward<TArgs>(args)...);
|
||||
|
||||
// add clothes
|
||||
character.AddClothes("tshirt", GetRandomColor());
|
||||
character.AddClothes("shorts", GetRandomColor());
|
||||
|
||||
return character;
|
||||
}
|
||||
|
||||
void game::OpenWorld::CreatePlayerCharacter(Player& player)
|
||||
{
|
||||
RemovePlayerCharacter(player);
|
||||
|
||||
auto& character = SpawnRandomCharacter<PlayerCharacter>(*this, player);
|
||||
// character.SetNametag("player (" + std::to_string(character.GetEntNum()) + ")");
|
||||
character.SetPosition({100.0f, 100.0f, 5.0f});
|
||||
|
||||
player_characters_[&player] = &character;
|
||||
}
|
||||
|
||||
void game::OpenWorld::RemovePlayerCharacter(Player& player)
|
||||
{
|
||||
auto it = player_characters_.find(&player);
|
||||
if (it != player_characters_.end())
|
||||
{
|
||||
it->second->Remove();
|
||||
player_characters_.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
game::DrivableVehicle& game::OpenWorld::SpawnRandomVehicle()
|
||||
{
|
||||
game::VehicleTuning tuning;
|
||||
@ -105,10 +198,6 @@ void game::OpenWorld::SpawnBot()
|
||||
auto& vehicle = SpawnRandomVehicle();
|
||||
vehicle.SetPosition(roads->nodes[start_node].position + glm::vec3{0.0f, 0.0f, 5.0f});
|
||||
|
||||
CharacterTuning npc_tuning;
|
||||
npc_tuning.clothes.push_back({ "tshirt", GetRandomColor24() });
|
||||
npc_tuning.clothes.push_back({ "shorts", GetRandomColor24() });
|
||||
|
||||
auto& driver = Spawn<NpcCharacter>(npc_tuning);
|
||||
auto& driver = SpawnRandomCharacter<NpcCharacter>(*this);
|
||||
driver.SetVehicle(&vehicle, 0);
|
||||
}
|
||||
|
||||
@ -1,21 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include "enterable_world.hpp"
|
||||
#include "npc_character.hpp"
|
||||
#include "world.hpp"
|
||||
#include "vehicle.hpp"
|
||||
#include "character.hpp"
|
||||
#include "usable.hpp"
|
||||
#include "drivable_vehicle.hpp"
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace game
|
||||
{
|
||||
|
||||
class OpenWorld : public EnterableWorld
|
||||
class PlayerCharacter;
|
||||
class NpcCharacter;
|
||||
|
||||
class OpenWorld : public World
|
||||
{
|
||||
public:
|
||||
OpenWorld();
|
||||
|
||||
private:
|
||||
virtual void Update(int64_t delta_time) override;
|
||||
|
||||
virtual void PlayerJoined(Player& player) override;
|
||||
virtual void PlayerInput(Player& player, PlayerInputType type, bool enabled) override;
|
||||
virtual void PlayerViewAnglesChanged(Player& player, float yaw, float pitch) override;
|
||||
virtual void PlayerLeft(Player& player) override;
|
||||
|
||||
virtual void DestructibleDestroyed(net::ObjNum num, std::unique_ptr<MapObjectCollision> col) override;
|
||||
|
||||
private:
|
||||
void CreatePlayerCharacter(Player& player);
|
||||
void RemovePlayerCharacter(Player& player);
|
||||
|
||||
game::DrivableVehicle& SpawnRandomVehicle();
|
||||
void SpawnBot();
|
||||
|
||||
private:
|
||||
std::map<Player*, PlayerCharacter*> player_characters_;
|
||||
std::vector<NpcCharacter*> npcs_;
|
||||
};
|
||||
|
||||
|
||||
@ -6,7 +6,6 @@
|
||||
#include <glm/gtx/norm.hpp>
|
||||
|
||||
#include "world.hpp"
|
||||
#include "game.hpp"
|
||||
|
||||
game::Player::Player(Game& game, std::string name) : game_(game), name_(std::move(name))
|
||||
{
|
||||
@ -30,13 +29,11 @@ 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();
|
||||
|
||||
return; // send updates next frame
|
||||
}
|
||||
|
||||
if (world_)
|
||||
@ -46,12 +43,18 @@ void game::Player::Update()
|
||||
}
|
||||
}
|
||||
|
||||
void game::Player::SetWorld(World* world)
|
||||
void game::Player::SetWorld(std::shared_ptr<World> world)
|
||||
{
|
||||
if (world == world_)
|
||||
return;
|
||||
|
||||
world_ = world;
|
||||
if (world_)
|
||||
world_->PlayerLeft(*this);
|
||||
|
||||
world_ = std::move(world);
|
||||
|
||||
if (world_)
|
||||
world_->PlayerJoined(*this);
|
||||
}
|
||||
|
||||
void game::Player::SetCamera(net::EntNum entnum)
|
||||
@ -71,6 +74,7 @@ void game::Player::SendChat(const std::string& text)
|
||||
|
||||
game::Player::~Player()
|
||||
{
|
||||
SetWorld(nullptr);
|
||||
game_.PlayerLeft(*this);
|
||||
}
|
||||
|
||||
@ -243,7 +247,9 @@ bool game::Player::ProcessViewAnglesMsg(net::InMessage& msg)
|
||||
view_yaw_ = yaw_q.Decode();
|
||||
view_pitch_ = pitch_q.Decode();
|
||||
|
||||
game_.PlayerViewAnglesChanged(*this, view_yaw_, view_pitch_);
|
||||
if (world_)
|
||||
world_->PlayerViewAnglesChanged(*this, view_yaw_, view_pitch_);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -254,6 +260,10 @@ void game::Player::Input(PlayerInputType type, bool enabled)
|
||||
else
|
||||
in_ &= ~(1 << type);
|
||||
|
||||
game_.PlayerInput(*this, type, enabled);
|
||||
if (!game_.PlayerInput(*this, type, enabled))
|
||||
{
|
||||
if (world_)
|
||||
world_->PlayerInput(*this, type, enabled);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,23 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <set>
|
||||
#include <memory>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "net/defs.hpp"
|
||||
#include "net/inmessage.hpp"
|
||||
#include "net/msg_producer.hpp"
|
||||
#include "utils/defs.hpp"
|
||||
|
||||
#include "player_input.hpp"
|
||||
#include "game.hpp"
|
||||
|
||||
namespace game
|
||||
{
|
||||
|
||||
class Game;
|
||||
class World;
|
||||
class Entity;
|
||||
class Vehicle;
|
||||
|
||||
class Player : public net::MsgProducer
|
||||
{
|
||||
@ -28,7 +25,7 @@ public:
|
||||
bool ProcessMsg(net::MessageType type, net::InMessage& msg);
|
||||
void Update();
|
||||
|
||||
void SetWorld(World* world);
|
||||
void SetWorld(std::shared_ptr<World> world);
|
||||
|
||||
void SetCamera(net::EntNum entnum);
|
||||
void SendChat(const std::string& text);
|
||||
@ -63,7 +60,7 @@ 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_;
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#include "player_character.hpp"
|
||||
#include "world.hpp"
|
||||
#include "openworld.hpp"
|
||||
|
||||
game::PlayerCharacter::PlayerCharacter(World& world, Player& player, const CharacterTuning& tuning) : Super(world, tuning), player_(&player)
|
||||
game::PlayerCharacter::PlayerCharacter(World& world, Player& player) : Super(world), player_(player)
|
||||
{
|
||||
EnablePhysics(true);
|
||||
VehicleChanged();
|
||||
@ -18,16 +18,13 @@ void game::PlayerCharacter::Update()
|
||||
|
||||
void game::PlayerCharacter::VehicleChanged()
|
||||
{
|
||||
if (!player_)
|
||||
return;
|
||||
|
||||
if (vehicle_)
|
||||
{
|
||||
player_->SetCamera(vehicle_->GetEntNum());
|
||||
player_.SetCamera(vehicle_->GetEntNum());
|
||||
}
|
||||
else
|
||||
{
|
||||
player_->SetCamera(GetEntNum());
|
||||
player_.SetCamera(GetEntNum());
|
||||
}
|
||||
|
||||
UpdateInputs();
|
||||
@ -62,14 +59,9 @@ void game::PlayerCharacter::ProcessInput(PlayerInputType type, bool enabled)
|
||||
}
|
||||
}
|
||||
|
||||
void game::PlayerCharacter::DetachFromPlayer()
|
||||
{
|
||||
player_ = nullptr;
|
||||
}
|
||||
|
||||
void game::PlayerCharacter::UpdateInputs()
|
||||
{
|
||||
auto in = player_ ? player_->GetInput() : 0;
|
||||
auto in = player_.GetInput();
|
||||
CharacterInputFlags c_in = 0;
|
||||
VehicleInputFlags v_in = 0;
|
||||
|
||||
|
||||
@ -2,17 +2,18 @@
|
||||
|
||||
#include "drivable_vehicle.hpp"
|
||||
#include "player.hpp"
|
||||
#include "world.hpp"
|
||||
|
||||
namespace game
|
||||
{
|
||||
|
||||
class OpenWorld;
|
||||
|
||||
class PlayerCharacter : public ControllableCharacter
|
||||
{
|
||||
public:
|
||||
using Super = ControllableCharacter;
|
||||
|
||||
PlayerCharacter(World& world, Player& player, const CharacterTuning& tuning);
|
||||
PlayerCharacter(World& world, Player& player);
|
||||
|
||||
virtual void Update() override;
|
||||
|
||||
@ -20,16 +21,12 @@ public:
|
||||
|
||||
void ProcessInput(PlayerInputType type, bool enabled);
|
||||
|
||||
void DetachFromPlayer();
|
||||
|
||||
Player* GetPlayer() const { return player_; }
|
||||
|
||||
private:
|
||||
void UpdateInputs();
|
||||
void UpdateUseTarget();
|
||||
|
||||
private:
|
||||
Player* player_;
|
||||
Player& player_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -58,7 +58,6 @@ public:
|
||||
|
||||
const std::string& GetModelName() const { return tuning_.model; }
|
||||
const std::shared_ptr<const assets::VehicleModel>& GetModel() const { return model_; }
|
||||
const VehicleTuning& GetTuning() const { return tuning_; }
|
||||
|
||||
virtual ~Vehicle();
|
||||
|
||||
|
||||
@ -6,7 +6,6 @@
|
||||
#include "assets/cache.hpp"
|
||||
#include "utils/allocnum.hpp"
|
||||
#include "collision/object_info.hpp"
|
||||
#include "destroyed_object.hpp"
|
||||
|
||||
game::World::World(std::string mapname) : Scheduler(time_ms_), map_(*this, std::move(mapname))
|
||||
{
|
||||
@ -79,15 +78,6 @@ void game::World::FinishFrame()
|
||||
|
||||
}
|
||||
|
||||
void game::World::DestructibleDestroyed(net::ObjNum num, std::unique_ptr<MapObjectCollision> col)
|
||||
{
|
||||
auto& destroyed_obj = Spawn<DestroyedObject>(std::move(col));
|
||||
|
||||
Schedule(120000, [this, num] {
|
||||
RespawnObj(num);
|
||||
});
|
||||
}
|
||||
|
||||
game::Entity* game::World::GetEntity(net::EntNum entnum)
|
||||
{
|
||||
auto it = ents_.find(entnum);
|
||||
|
||||
@ -37,7 +37,13 @@ public:
|
||||
virtual void Update(int64_t delta_time);
|
||||
void FinishFrame();
|
||||
|
||||
virtual void DestructibleDestroyed(net::ObjNum num, std::unique_ptr<MapObjectCollision> col);
|
||||
// events
|
||||
virtual void PlayerJoined(Player& player) {}
|
||||
virtual void PlayerInput(Player& player, PlayerInputType type, bool enabled) {}
|
||||
virtual void PlayerViewAnglesChanged(Player& player, float yaw, float pitch) {}
|
||||
virtual void PlayerLeft(Player& player) {}
|
||||
|
||||
virtual void DestructibleDestroyed(net::ObjNum num, std::unique_ptr<MapObjectCollision> col) {}
|
||||
|
||||
Entity* GetEntity(net::EntNum entnum);
|
||||
|
||||
|
||||
@ -9,14 +9,12 @@
|
||||
#include "draw_args.hpp"
|
||||
|
||||
game::view::WorldView::WorldView(ClientSession& session, net::InMessage& msg) :
|
||||
session_(session), audiomaster_(session_.GetAudioMaster())
|
||||
session_(session), audiomaster_(session_.GetAudioMaster()), map_("openworld")
|
||||
{
|
||||
net::MapName mapname;
|
||||
if (!msg.Read(mapname))
|
||||
throw EntityInitError();
|
||||
|
||||
map_ = std::make_unique<MapInstanceView>(std::string(mapname));
|
||||
|
||||
// init destroyed objs
|
||||
net::ObjCount objcount;
|
||||
if (!msg.Read(objcount))
|
||||
@ -28,7 +26,7 @@ game::view::WorldView::WorldView(ClientSession& session, net::InMessage& msg) :
|
||||
if (!msg.Read(objnum))
|
||||
throw EntityInitError();
|
||||
|
||||
map_->EnableObj(objnum, false);
|
||||
map_.EnableObj(objnum, false);
|
||||
}
|
||||
|
||||
// cache common snds and stuff
|
||||
@ -71,8 +69,8 @@ void game::view::WorldView::Update(const UpdateInfo& info)
|
||||
{
|
||||
time_ = info.time;
|
||||
|
||||
if (!map_->IsLoaded())
|
||||
map_->LoadNext();
|
||||
if (!map_.IsLoaded())
|
||||
map_.LoadNext();
|
||||
|
||||
for (const auto& [entnum, ent] : ents_)
|
||||
{
|
||||
@ -82,7 +80,7 @@ void game::view::WorldView::Update(const UpdateInfo& info)
|
||||
|
||||
void game::view::WorldView::Draw(const DrawArgs& args) const
|
||||
{
|
||||
if (!map_->IsLoaded())
|
||||
if (!map_.IsLoaded())
|
||||
{
|
||||
DrawLoadingScreen(args);
|
||||
return;
|
||||
@ -90,7 +88,7 @@ void game::view::WorldView::Draw(const DrawArgs& args) const
|
||||
|
||||
args.env.clear_color = glm::vec3(0.5f, 0.7f, 1.0f);
|
||||
|
||||
map_->Draw(args);
|
||||
map_.Draw(args);
|
||||
|
||||
for (const auto& [entnum, ent] : ents_)
|
||||
{
|
||||
@ -139,7 +137,7 @@ void game::view::WorldView::DrawLoadingScreen(const DrawArgs& args) const
|
||||
glm::vec2 size(400.0f, 15.0f);
|
||||
glm::vec2 pos(margin, args.screen_size.y - margin - size.y);
|
||||
|
||||
int loaded_percent = map_->GetLoadingPercent();
|
||||
int loaded_percent = map_.GetLoadingPercent();
|
||||
float loaded = static_cast<float>(loaded_percent) * 0.01f;
|
||||
|
||||
args.gui.DrawRect(pos, pos + size, 0x77FFFFFF);
|
||||
@ -269,7 +267,7 @@ bool game::view::WorldView::ProcessObjDestroyOrRespawnMsg(net::InMessage& msg, b
|
||||
if (!msg.Read(objnum))
|
||||
return false;
|
||||
|
||||
map_->EnableObj(objnum, enable);
|
||||
map_.EnableObj(objnum, enable);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -48,7 +48,7 @@ private:
|
||||
private:
|
||||
ClientSession& session_;
|
||||
|
||||
std::unique_ptr<MapInstanceView> map_;
|
||||
MapInstanceView map_;
|
||||
std::map<net::EntNum, std::unique_ptr<EntityView>> ents_;
|
||||
|
||||
float time_ = 0.0f;
|
||||
|
||||
@ -17,8 +17,6 @@ void sv::Server::Run()
|
||||
{
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
srand(time(NULL));
|
||||
|
||||
auto t_start = std::chrono::steady_clock::now();
|
||||
auto t_next = t_start;
|
||||
auto t_prev = t_start;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user