Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 4 additions & 24 deletions code/client/src/core/modules/human.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,10 +204,10 @@ namespace MafiaMP::Core::Modules {

// Ensure we hook up remote human events for special cases
auto streamable = e.get_mut<Framework::World::Modules::Base::Streamable>();
streamable->modEvents.disconnectProc = [](flecs::entity e) {
streamable->disconnectProc = [](flecs::entity e) {
Remove(e);
};
streamable->modEvents.updateTransformProc = [](flecs::entity e) {
streamable->updateTransformProc = [](flecs::entity e) {
UpdateTransform(e);
};

Expand Down Expand Up @@ -274,16 +274,7 @@ namespace MafiaMP::Core::Modules {
e.add<Framework::World::Modules::Base::Frame>();

auto es = e.get_mut<Framework::World::Modules::Base::Streamable>();
es->modEvents.updateProc = [](Framework::Networking::NetworkPeer *peer, uint64_t guid, flecs::entity e) {
const auto updateData = e.get<Shared::Modules::HumanSync::UpdateData>();

Shared::Messages::Human::HumanUpdate humanUpdate {};
humanUpdate.SetServerID(Framework::World::ClientEngine::GetServerID(e));
humanUpdate.SetData(*updateData);
peer->Send(humanUpdate, guid);
return true;
};
es->modEvents.updateTransformProc = [](flecs::entity e) {
es->updateTransformProc = [](flecs::entity e) {
UpdateTransform(e);
};
}
Expand Down Expand Up @@ -417,18 +408,7 @@ namespace MafiaMP::Core::Modules {
humanData->carPassenger.enterForced = true;
}

// set up client updates (NPC streaming)
// TODO disabled for now, we don't really need to stream NPCs atm
#if 0
const auto es = e.get_mut<Framework::World::Modules::Base::Streamable>();
es->modEvents.clientUpdateProc = [&](Framework::Networking::NetworkPeer *peer, uint64_t guid, flecs::entity e) {
Shared::Messages::Human::HumanClientUpdate humanUpdate;
humanUpdate.FromParameters(e.id());
// set up sync data
peer->Send(humanUpdate, guid);
return true;
};
#endif
// NPC streaming not implemented - when needed, use StreamedTo relation observers
});
net->RegisterMessage<Shared::Messages::Human::HumanDespawn>(Shared::Messages::ModMessages::MOD_HUMAN_DESPAWN, [app](SLNet::RakNetGUID guid, Shared::Messages::Human::HumanDespawn *msg) {
const auto e = app->GetWorldEngine()->GetEntityByServerID(msg->GetServerID());
Expand Down
16 changes: 2 additions & 14 deletions code/client/src/core/modules/vehicle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,10 @@ namespace MafiaMP::Core::Modules {

// Ensure we hook up vehicle events for special cases
auto streamable = e.get_mut<Framework::World::Modules::Base::Streamable>();
streamable->modEvents.disconnectProc = [](flecs::entity e) {
streamable->disconnectProc = [](flecs::entity e) {
Remove(e);
};
streamable->modEvents.updateTransformProc = [](flecs::entity e) {
streamable->updateTransformProc = [](flecs::entity e) {
UpdateTransform(e);
};

Expand Down Expand Up @@ -145,18 +145,6 @@ namespace MafiaMP::Core::Modules {
auto trackingData = ent.get_mut<Core::Modules::Vehicle::Tracking>();
trackingData->car = car;

auto streamable = ent.get_mut<Framework::World::Modules::Base::Streamable>();
streamable->modEvents.updateProc = [](Framework::Networking::NetworkPeer *peer, uint64_t guid, flecs::entity e) {
const auto updateData = e.get<Shared::Modules::VehicleSync::UpdateData>();
const auto serverID = e.get<Framework::World::Modules::Base::ServerID>();

Shared::Messages::Vehicle::VehicleUpdate vehicleUpdate {};
vehicleUpdate.SetServerID(serverID->id);
vehicleUpdate.SetData(*updateData);
peer->Send(vehicleUpdate, guid);
return true;
};

Update(ent);
}
};
Expand Down
3 changes: 3 additions & 0 deletions code/server/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ set(MAFIAMP_SERVER_FILES
add_executable(MafiaMPServer ${MAFIAMP_SERVER_FILES})
target_include_directories(MafiaMPServer PRIVATE src)
target_link_libraries(MafiaMPServer Framework FrameworkServer)

# Reuse FrameworkServer's PCH (includes sol, flecs, and Framework's headers)
target_precompile_headers(MafiaMPServer REUSE_FROM FrameworkServer)
137 changes: 96 additions & 41 deletions code/server/src/core/modules/human.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "human.h"

#include "utils/time.h"
#include "world/modules/base.hpp"

#include "shared/messages/human/human_despawn.h"
Expand Down Expand Up @@ -47,50 +48,104 @@ namespace MafiaMP::Core::Modules {
}
};

auto es = e.get_mut<Framework::World::Modules::Base::Streamable>();

es->modEvents.spawnProc = [net](Framework::Networking::NetworkPeer *peer, uint64_t guid, flecs::entity e) {
const auto frame = e.get<Framework::World::Modules::Base::Frame>();
const auto s = e.get<Framework::World::Modules::Base::Streamer>();
Shared::Messages::Human::HumanSpawn humanSpawn;
humanSpawn.FromParameters(frame->modelHash, s->nickname, s->playerIndex);
humanSpawn.SetServerID(e.id());

const auto trackingMetadata = e.get<Shared::Modules::HumanSync::UpdateData>();
humanSpawn.SetCarPassenger(trackingMetadata->carPassenger.carId, trackingMetadata->carPassenger.seatId);

net->Send(humanSpawn, guid);
// todo other stuff
return true;
};

es->modEvents.despawnProc = [net](Framework::Networking::NetworkPeer *peer, uint64_t guid, flecs::entity e) {
Shared::Messages::Human::HumanDespawn humanDespawn;
humanDespawn.SetServerID(e.id());
net->Send(humanDespawn, guid);
return true;
};

es->modEvents.selfUpdateProc = [net](Framework::Networking::NetworkPeer *peer, uint64_t guid, flecs::entity e) {
Shared::Messages::Human::HumanSelfUpdate humanSelfUpdate;
humanSelfUpdate.SetServerID(e.id());
net->Send(humanSelfUpdate, guid);
return true;
};

es->modEvents.updateProc = [net](Framework::Networking::NetworkPeer *peer, uint64_t guid, flecs::entity e) {
const auto trackingMetadata = e.get<Shared::Modules::HumanSync::UpdateData>();
// const auto frame = e.get<Framework::World::Modules::Base::Frame>();

Shared::Messages::Human::HumanUpdate humanUpdate {};
humanUpdate.SetServerID(e.id());
humanUpdate.SetData(*trackingMetadata);
net->Send(humanUpdate, guid);
return true;
};
// Message sending is handled by observers set up in SetupMessages
}

void Human::SetupMessages(std::shared_ptr<Framework::World::ServerEngine> srv, Framework::Networking::NetworkServer *net) {
auto world = srv->GetWorld();

// Observer: Send HumanSpawn when StreamedTo relation is added to Human entities
world->observer()
.with<Framework::World::Modules::Base::StreamedTo>(flecs::Wildcard)
.with<Shared::Modules::HumanSync::UpdateData>()
.event(flecs::OnAdd)
.each([net](flecs::iter& it, size_t row) {
auto e = it.entity(row);
auto streamerEntity = it.pair(0).second();
if (!streamerEntity.is_valid() || !streamerEntity.is_alive())
return;

auto streamer = streamerEntity.get<Framework::World::Modules::Base::Streamer>();
if (!streamer)
return;

const auto frame = e.get<Framework::World::Modules::Base::Frame>();
Shared::Messages::Human::HumanSpawn humanSpawn;
humanSpawn.FromParameters(frame ? frame->modelHash : 0, streamer->nickname, streamer->playerIndex);
humanSpawn.SetServerID(e.id());

const auto trackingMetadata = e.get<Shared::Modules::HumanSync::UpdateData>();
if (trackingMetadata) {
humanSpawn.SetCarPassenger(trackingMetadata->carPassenger.carId, trackingMetadata->carPassenger.seatId);
}

net->Send(humanSpawn, streamer->guid);
});

// Observer: Send HumanDespawn when StreamedTo relation is removed from Human entities
world->observer()
.with<Framework::World::Modules::Base::StreamedTo>(flecs::Wildcard)
.with<Shared::Modules::HumanSync::UpdateData>()
.event(flecs::OnRemove)
.each([net](flecs::iter& it, size_t row) {
auto e = it.entity(row);
auto streamerEntity = it.pair(0).second();
if (!streamerEntity.is_valid() || !streamerEntity.is_alive())
return;

auto streamer = streamerEntity.get<Framework::World::Modules::Base::Streamer>();
if (!streamer)
return;

Shared::Messages::Human::HumanDespawn humanDespawn;
humanDespawn.SetServerID(e.id());
net->Send(humanDespawn, streamer->guid);
});

// System: Send periodic HumanUpdate/HumanSelfUpdate for streamed Human entities
world->system<Shared::Modules::HumanSync::UpdateData, Framework::World::Modules::Base::Streamable>("HumanStreamUpdates")
.kind(flecs::PostUpdate)
.each([net](flecs::entity e, Shared::Modules::HumanSync::UpdateData& updateData, Framework::World::Modules::Base::Streamable& streamable) {
// Skip entities not being streamed or marked as no-update
if (e.has<Framework::World::Modules::Base::NoTickUpdates>())
return;

// Iterate over all streamers this entity is streamed to
e.each<Framework::World::Modules::Base::StreamedTo>([&](flecs::entity streamerEntity) {
if (!streamerEntity.is_valid() || !streamerEntity.is_alive())
return;

auto streamer = streamerEntity.get<Framework::World::Modules::Base::Streamer>();
if (!streamer)
return;

// Check timing via the StreamedTo relation data
auto streamData = e.get_mut<Framework::World::Modules::Base::StreamedTo>(streamerEntity);
if (!streamData)
return;

double currentTime = static_cast<double>(Framework::Utils::Time::GetTime());
if (currentTime - streamData->lastUpdate < streamable.updateInterval)
return;

streamData->lastUpdate = currentTime;

// Send appropriate message based on ownership
if (streamer->guid != streamable.owner) {
// Non-owner gets regular update
Shared::Messages::Human::HumanUpdate humanUpdate {};
humanUpdate.SetServerID(e.id());
humanUpdate.SetData(updateData);
net->Send(humanUpdate, streamer->guid);
} else {
// Owner gets self update
Shared::Messages::Human::HumanSelfUpdate humanSelfUpdate;
humanSelfUpdate.SetServerID(e.id());
net->Send(humanSelfUpdate, streamer->guid);
}
});
});

net->RegisterMessage<Shared::Messages::Human::HumanUpdate>(Shared::Messages::ModMessages::MOD_HUMAN_UPDATE, [srv](SLNet::RakNetGUID guid, Shared::Messages::Human::HumanUpdate *msg) {
const auto e = srv->WrapEntity(msg->GetServerID());
if (!e.is_alive()) {
Expand Down
126 changes: 86 additions & 40 deletions code/server/src/core/modules/vehicle.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
#include "vehicle.h"

#include "networking/network_peer.h"
#include "world/modules/base.hpp"

#include "utils/time.h"
#include "world/modules/base.hpp"

#include "shared/game_rpc/vehicle/vehicle_player_enter.h"
Expand Down Expand Up @@ -70,49 +69,96 @@ namespace MafiaMP::Core::Modules {
return false;
};

es->modEvents.spawnProc = [net](Framework::Networking::NetworkPeer *peer, uint64_t guid, flecs::entity e) {
const auto frame = e.get<Framework::World::Modules::Base::Frame>();
auto trackingMetadata = e.get_mut<Shared::Modules::VehicleSync::UpdateData>();
Shared::Messages::Vehicle::VehicleSpawn vehicleSpawn;
vehicleSpawn.FromParameters(frame->modelName.c_str(), *trackingMetadata);
vehicleSpawn.SetServerID(e.id());
net->Send(vehicleSpawn, guid);
// todo other stuff
return true;
};

es->modEvents.despawnProc = [net](Framework::Networking::NetworkPeer *peer, uint64_t guid, flecs::entity e) {
Shared::Messages::Vehicle::VehicleDespawn vehicleDespawn;
vehicleDespawn.SetServerID(e.id());
net->Send(vehicleDespawn, guid);
return true;
};

es->modEvents.updateProc = [net](Framework::Networking::NetworkPeer *peer, uint64_t guid, flecs::entity e) {
auto trackingMetadata = e.get_mut<Shared::Modules::VehicleSync::UpdateData>();

Shared::Messages::Vehicle::VehicleUpdate vehicleUpdate {};
vehicleUpdate.SetServerID(e.id());
vehicleUpdate.SetData(*trackingMetadata);
net->Send(vehicleUpdate, guid);
return true;
};

// TODO: deprecate in favor of RPCs
/*es->modEvents.ownerUpdateProc = [net](Framework::Networking::NetworkPeer *peer, uint64_t guid, flecs::entity e) {
auto trackingMetadata = e.get_mut<Shared::Modules::VehicleSync::UpdateData>();

Shared::Messages::Vehicle::VehicleOwnerUpdate vehicleUpdate {};
vehicleUpdate.SetServerID(e.id());
vehicleUpdate.SetData(*trackingMetadata);
net->Send(vehicleUpdate, guid);
return true;
};*/
// Message sending is handled by observers set up in SetupMessages

return e;
}

void Vehicle::SetupMessages(std::shared_ptr<Framework::World::ServerEngine> srv, Framework::Networking::NetworkServer *net) {
auto world = srv->GetWorld();

// Observer: Send VehicleSpawn when StreamedTo relation is added to Vehicle entities
world->observer()
.with<Framework::World::Modules::Base::StreamedTo>(flecs::Wildcard)
.with<Shared::Modules::VehicleSync::UpdateData>()
.event(flecs::OnAdd)
.each([net](flecs::iter& it, size_t row) {
auto e = it.entity(row);
auto streamerEntity = it.pair(0).second();
if (!streamerEntity.is_valid() || !streamerEntity.is_alive())
return;

auto streamer = streamerEntity.get<Framework::World::Modules::Base::Streamer>();
if (!streamer)
return;

const auto frame = e.get<Framework::World::Modules::Base::Frame>();
auto trackingMetadata = e.get<Shared::Modules::VehicleSync::UpdateData>();
if (!frame || !trackingMetadata)
return;

Shared::Messages::Vehicle::VehicleSpawn vehicleSpawn;
vehicleSpawn.FromParameters(frame->modelName.c_str(), *trackingMetadata);
vehicleSpawn.SetServerID(e.id());
net->Send(vehicleSpawn, streamer->guid);
});

// Observer: Send VehicleDespawn when StreamedTo relation is removed from Vehicle entities
world->observer()
.with<Framework::World::Modules::Base::StreamedTo>(flecs::Wildcard)
.with<Shared::Modules::VehicleSync::UpdateData>()
.event(flecs::OnRemove)
.each([net](flecs::iter& it, size_t row) {
auto e = it.entity(row);
auto streamerEntity = it.pair(0).second();
if (!streamerEntity.is_valid() || !streamerEntity.is_alive())
return;

auto streamer = streamerEntity.get<Framework::World::Modules::Base::Streamer>();
if (!streamer)
return;

Shared::Messages::Vehicle::VehicleDespawn vehicleDespawn;
vehicleDespawn.SetServerID(e.id());
net->Send(vehicleDespawn, streamer->guid);
});

// System: Send periodic VehicleUpdate for streamed Vehicle entities
world->system<Shared::Modules::VehicleSync::UpdateData, Framework::World::Modules::Base::Streamable>("VehicleStreamUpdates")
.kind(flecs::PostUpdate)
.each([net](flecs::entity e, Shared::Modules::VehicleSync::UpdateData& updateData, Framework::World::Modules::Base::Streamable& streamable) {
// Skip entities marked as no-update
if (e.has<Framework::World::Modules::Base::NoTickUpdates>())
return;

// Iterate over all streamers this entity is streamed to
e.each<Framework::World::Modules::Base::StreamedTo>([&](flecs::entity streamerEntity) {
if (!streamerEntity.is_valid() || !streamerEntity.is_alive())
return;

auto streamer = streamerEntity.get<Framework::World::Modules::Base::Streamer>();
if (!streamer)
return;

// Check timing via the StreamedTo relation data
auto streamData = e.get_mut<Framework::World::Modules::Base::StreamedTo>(streamerEntity);
if (!streamData)
return;

double currentTime = static_cast<double>(Framework::Utils::Time::GetTime());
if (currentTime - streamData->lastUpdate < streamable.updateInterval)
return;

streamData->lastUpdate = currentTime;

// Send update (vehicles don't distinguish owner/non-owner updates currently)
Shared::Messages::Vehicle::VehicleUpdate vehicleUpdate {};
vehicleUpdate.SetServerID(e.id());
vehicleUpdate.SetData(updateData);
net->Send(vehicleUpdate, streamer->guid);
});
});

net->RegisterMessage<Shared::Messages::Vehicle::VehicleUpdate>(Shared::Messages::ModMessages::MOD_VEHICLE_UPDATE, [srv](SLNet::RakNetGUID guid, Shared::Messages::Vehicle::VehicleUpdate *msg) {
const auto e = srv->WrapEntity(msg->GetServerID());
if (!e.is_alive()) {
Expand Down