diff --git a/server/src/CNodeResourceImpl.cpp b/server/src/CNodeResourceImpl.cpp index 0c70c51a..ca6944d1 100644 --- a/server/src/CNodeResourceImpl.cpp +++ b/server/src/CNodeResourceImpl.cpp @@ -140,6 +140,8 @@ void CNodeResourceImpl::OnEvent(const alt::CEvent* e) v8::Context::Scope scope(GetContext()); // env->PushAsyncCallbackScope(); + HandleVehiclePassengerSeatEvents(e); + V8Helpers::EventHandler* handler = V8Helpers::EventHandler::Get(e); if(!handler) return; @@ -186,6 +188,69 @@ void CNodeResourceImpl::OnEvent(const alt::CEvent* e) return; } +void CNodeResourceImpl::HandleVehiclePassengerSeatEvents(const alt::CEvent* ev) +{ + auto evType = ev->GetType(); + + if (evType == alt::CEvent::Type::PLAYER_ENTER_VEHICLE) + { + auto event = static_cast(ev); + auto vehicle = event->GetTarget(); + auto player = event->GetPlayer(); + auto seat = event->GetSeat(); + + if (!vehiclePassengers.contains(vehicle)) + vehiclePassengers[vehicle] = {}; + + vehiclePassengers[vehicle][seat] = player; + } + else if (evType == alt::CEvent::Type::PLAYER_LEAVE_VEHICLE) + { + auto event = static_cast(ev); + auto vehicle = event->GetTarget(); + auto player = event->GetPlayer(); + + if (vehiclePassengers.contains(vehicle)) + { + for ( auto it = vehiclePassengers[vehicle].begin(); it != vehiclePassengers[vehicle].end(); ) + { + if (it->second == player) + it = vehiclePassengers[vehicle].erase(it); + else + ++it; + } + + if (vehiclePassengers[vehicle].empty()) + vehiclePassengers.erase(vehicle); + } + } + else if (evType == alt::CEvent::Type::PLAYER_CHANGE_VEHICLE_SEAT) + { + auto event = static_cast(ev); + auto vehicle = event->GetTarget(); + + if (!vehiclePassengers.contains(vehicle)) + vehiclePassengers[vehicle] = {}; + + vehiclePassengers[vehicle].erase(event->GetOldSeat()); + vehiclePassengers[vehicle][event->GetNewSeat()] = event->GetPlayer(); + } + else if (evType == alt::CEvent::Type::REMOVE_BASE_OBJECT_EVENT) + { + auto event = static_cast(ev); + +#undef GetObject + auto entity = event->GetObject(); + + if (entity->GetType() == alt::IBaseObject::Type::VEHICLE) + { + auto vehicle = entity->As(); + if (vehiclePassengers.contains(vehicle)) + vehiclePassengers.erase(vehicle); + } + } +} + void CNodeResourceImpl::OnTick() { v8::Locker locker(isolate); diff --git a/server/src/CNodeResourceImpl.h b/server/src/CNodeResourceImpl.h index d17242f4..3581c63a 100644 --- a/server/src/CNodeResourceImpl.h +++ b/server/src/CNodeResourceImpl.h @@ -25,6 +25,7 @@ class CNodeResourceImpl : public V8ResourceImpl bool Stop() override; void OnEvent(const alt::CEvent* ev) override; + void HandleVehiclePassengerSeatEvents(const alt::CEvent* ev); void OnTick() override; bool MakeClient(alt::IResource::CreationInfo* info, std::vector) override; diff --git a/server/src/bindings/Vehicle.cpp b/server/src/bindings/Vehicle.cpp index dd841a35..48f79231 100644 --- a/server/src/bindings/Vehicle.cpp +++ b/server/src/bindings/Vehicle.cpp @@ -229,6 +229,27 @@ static void RoofClosedGetter(v8::Local name, const v8::PropertyCallb V8_RETURN_BOOLEAN(_this->GetRoofState() == 1); } +static void GetPassengers(v8::Local, const v8::PropertyCallbackInfo& info) +{ + V8_GET_ISOLATE_CONTEXT_RESOURCE(); + V8_GET_THIS_BASE_OBJECT(_this, IVehicle); + + auto obj = v8::Object::New(isolate); + auto passengers = V8ResourceImpl::vehiclePassengers[_this]; + + if (!passengers.empty()) + { + for (auto& [seat, player] : passengers) + { + auto entity = resource->GetBaseObjectOrNull(player); + if (!entity->IsNull()) + obj->Set(ctx, seat, entity); + } + } + + V8_RETURN(obj); +} + extern V8Class v8Entity; extern V8Class v8Vehicle("Vehicle", v8Entity, @@ -244,6 +265,7 @@ extern V8Class v8Vehicle("Vehicle", // Common getter/setters V8Helpers::SetAccessor(isolate, tpl, "destroyed"); V8Helpers::SetAccessor(isolate, tpl, "driver"); + V8Helpers::SetAccessor(isolate, tpl, "passengers", &GetPassengers); V8Helpers::SetAccessor(isolate, tpl, "velocity"); V8Helpers::SetAccessor(isolate, tpl, "quaternion"); diff --git a/shared/IRuntimeEventHandler.h b/shared/IRuntimeEventHandler.h index e18cc9e2..0d8002d8 100644 --- a/shared/IRuntimeEventHandler.h +++ b/shared/IRuntimeEventHandler.h @@ -15,6 +15,10 @@ class IRuntimeEventHandler // All events the module uses, which need to be enabled and never disabled static constexpr std::array internalEvents = { EventType::CONNECTION_COMPLETE, EventType::DISCONNECT_EVENT, EventType::GAME_ENTITY_CREATE, EventType::GAME_ENTITY_DESTROY, EventType::RESOURCE_STOP +#ifdef ALT_SERVER_API + // required for vehicle seat stuff + , EventType::PLAYER_ENTER_VEHICLE, EventType::PLAYER_LEAVE_VEHICLE, EventType::PLAYER_CHANGE_VEHICLE_SEAT, EventType::REMOVE_BASE_OBJECT_EVENT +#endif }; // Keeps track of the event handlers registered for all events diff --git a/shared/V8ResourceImpl.h b/shared/V8ResourceImpl.h index a382e9f4..8e7d69d3 100644 --- a/shared/V8ResourceImpl.h +++ b/shared/V8ResourceImpl.h @@ -313,6 +313,10 @@ class V8ResourceImpl : public alt::IResource::Impl return static_cast(ctx->GetAlignedPointerFromEmbedderData(1)); } +#ifdef ALT_SERVER_API + static inline std::unordered_map> vehiclePassengers{}; +#endif + protected: v8::Isolate* isolate; alt::IResource* resource;