diff --git a/CMakeLists.txt b/CMakeLists.txt index 27643a43..8f381be3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,7 @@ add_definitions(-DBUILDING_CHAKRASHIM=1) add_definitions(-DHTTP_PARSER_STRICT=0) add_definitions(-DNGHTTP2_STATICLIB) add_definitions(-DHAVE_INSPECTOR=1) +add_definitions(-DALT_SERVER_API) file(GLOB_RECURSE PROJECT_SOURCE_FILES "src/*.h" "src/*.hpp" "src/*.cpp") diff --git a/README.md b/README.md index d9ae29c6..36d01f20 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,27 @@ # altv-js-module JS module for alt:V Multiplayer. Powered by NodeJS & v8 + +## Troubleshooting +**Problem**: I want to build a native Node.js addon with +[node-gyp](https://github.com/nodejs/node-gyp) but the alt:V server can not load +it and responds with following error: +``` +./altv-server: symbol lookup error: /usr/share/addon/binding.node: undefined symbol: node_module_register +``` +**Solution**: Add a C++ file to your project with following content and include +it the ```sources``` in your ```binding.gyp``` file. +```cpp +#include +#include + +extern "C" NODE_EXTERN void node_module_register(void* mod) { + auto base_ptr = dlopen("libnode.so.72", RTLD_NOW | RTLD_GLOBAL); + if (base_ptr == nullptr) { + return; + } + auto register_func = reinterpret_cast(dlsym(base_ptr, "node_module_register")); + if (register_func == nullptr) { + return; + } + register_func(mod); +} diff --git a/src/CNodeResourceImpl.h b/src/CNodeResourceImpl.h index 98846052..b2dcb780 100644 --- a/src/CNodeResourceImpl.h +++ b/src/CNodeResourceImpl.h @@ -8,6 +8,8 @@ #include "helpers/V8Entity.h" #include "helpers/V8Helpers.h" +#include "node.h" + class CNodeScriptRuntime; class CNodeResourceImpl : public V8ResourceImpl diff --git a/src/CNodeScriptRuntime.cpp b/src/CNodeScriptRuntime.cpp index 8d431595..0938c3d3 100644 --- a/src/CNodeScriptRuntime.cpp +++ b/src/CNodeScriptRuntime.cpp @@ -64,13 +64,9 @@ void CNodeScriptRuntime::OnDispose() } while (uv_loop_alive(uv_default_loop())); }*/ - platform->DrainTasks(isolate); - platform->CancelPendingDelayedTasks(isolate); - platform->UnregisterIsolate(isolate); - - isolate->Dispose(); + v8::V8::Dispose(); + v8::V8::ShutdownPlatform(); - platform.release(); //node::FreePlatform(platform.release()); } diff --git a/src/bindings/Blip.cpp b/src/bindings/Blip.cpp index ad7ad5dd..dbd3cb7b 100644 --- a/src/bindings/Blip.cpp +++ b/src/bindings/Blip.cpp @@ -29,11 +29,12 @@ static void PointConstructor(const v8::FunctionCallbackInfo& info) V8Helpers::Throw(isolate, "Failed to create Blip"); } -static V8Class v8Blip("Blip", "WorldObject", nullptr, [](v8::Local tpl) { +extern V8Class v8WorldObject; +extern V8Class v8Blip("Blip", v8WorldObject, nullptr, [](v8::Local tpl) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); }); -static V8Class v8PointBlip("PointBlip", "Blip", PointConstructor, [](v8::Local tpl) { +extern V8Class v8PointBlip("PointBlip", v8Blip, PointConstructor, [](v8::Local tpl) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); }); diff --git a/src/bindings/Checkpoint.cpp b/src/bindings/Checkpoint.cpp index 69f93cfc..46543faf 100644 --- a/src/bindings/Checkpoint.cpp +++ b/src/bindings/Checkpoint.cpp @@ -37,6 +37,7 @@ static void Constructor(const v8::FunctionCallbackInfo& info) V8Helpers::Throw(isolate, "Failed to create Checkpoint"); } -static V8Class v8Checkpoint("Checkpoint", "Colshape", Constructor, [](v8::Local tpl) { +extern V8Class v8Colshape; +extern V8Class v8Checkpoint("Checkpoint", v8Colshape, Constructor, [](v8::Local tpl) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); }); diff --git a/src/bindings/ColShape.cpp b/src/bindings/ColShape.cpp index be09b757..2506ab87 100755 --- a/src/bindings/ColShape.cpp +++ b/src/bindings/ColShape.cpp @@ -71,7 +71,8 @@ static void PlayersOnlySetter(v8::Local name, v8::Local v _this->SetPlayersOnly(playersOnly); } -static V8Class v8Colshape("Colshape", "WorldObject", nullptr, [](v8::Local tpl) { +extern V8Class v8WorldObject; +extern V8Class v8Colshape("Colshape", v8WorldObject, nullptr, [](v8::Local tpl) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); V8::SetAccessor(isolate, tpl, "colshapeType", ColshapeTypeGetter); @@ -80,7 +81,7 @@ static V8Class v8Colshape("Colshape", "WorldObject", nullptr, [](v8::Local& info) +extern V8Class v8ColshapeCylinder("ColshapeCylinder", v8Colshape, [](const v8::FunctionCallbackInfo& info) { v8::Isolate* isolate = info.GetIsolate(); @@ -105,7 +106,7 @@ static V8Class v8ColshapeCylinder("ColshapeCylinder", "Colshape", [](const v8::F V8Helpers::Throw(isolate, "Failed to create ColshapeCylinder"); }, [](v8::Local tpl) {}); -static V8Class v8ColshapeSphere("ColshapeSphere", "Colshape", [](const v8::FunctionCallbackInfo& info) +extern V8Class v8ColshapeSphere("ColshapeSphere", v8Colshape, [](const v8::FunctionCallbackInfo& info) { v8::Isolate* isolate = info.GetIsolate(); @@ -128,7 +129,7 @@ static V8Class v8ColshapeSphere("ColshapeSphere", "Colshape", [](const v8::Funct V8Helpers::Throw(isolate, "Failed to create ColshapeSphere"); }, [](v8::Local tpl) {}); -static V8Class v8ColshapeCircle("ColshapeCircle", "Colshape", [](const v8::FunctionCallbackInfo& info) +extern V8Class v8ColshapeCircle("ColshapeCircle", v8Colshape, [](const v8::FunctionCallbackInfo& info) { v8::Isolate* isolate = info.GetIsolate(); @@ -150,7 +151,7 @@ static V8Class v8ColshapeCircle("ColshapeCircle", "Colshape", [](const v8::Funct V8Helpers::Throw(isolate, "Failed to create ColshapeCircle"); }, [](v8::Local tpl) {}); -static V8Class v8ColshapeCuboid("ColshapeCuboid", "Colshape", [](const v8::FunctionCallbackInfo& info) +extern V8Class v8ColshapeCuboid("ColshapeCuboid", v8Colshape, [](const v8::FunctionCallbackInfo& info) { v8::Isolate* isolate = info.GetIsolate(); @@ -175,7 +176,7 @@ static V8Class v8ColshapeCuboid("ColshapeCuboid", "Colshape", [](const v8::Funct V8Helpers::Throw(isolate, "Failed to create ColshapeCuboid"); }, [](v8::Local tpl) {}); -static V8Class v8ColshapeRectangle("ColshapeRectangle", "Colshape", [](const v8::FunctionCallbackInfo& info) +extern V8Class v8ColshapeRectangle("ColshapeRectangle", v8Colshape, [](const v8::FunctionCallbackInfo& info) { v8::Isolate* isolate = info.GetIsolate(); diff --git a/src/bindings/Main.cpp b/src/bindings/Main.cpp index 14fa5ab0..9c95a6da 100644 --- a/src/bindings/Main.cpp +++ b/src/bindings/Main.cpp @@ -242,26 +242,45 @@ static void ResourceLoaded(const v8::FunctionCallbackInfo& info) } } -static V8Module v8Alt("alt", +extern V8Class v8Vector3, + v8RGBA, + v8File, + v8BaseObject, + v8WorldObject, + v8Entity, + v8Player, + v8Vehicle, + v8Blip, + v8PointBlip, + v8Checkpoint, + v8VoiceChannel, + v8Colshape, + v8ColshapeCylinder, + v8ColshapeSphere, + v8ColshapeCircle, + v8ColshapeCuboid, + v8ColshapeRectangle; + +extern V8Module v8Alt("alt", { - "Vector3", - "RGBA", - "File", - "BaseObject", - "WorldObject", - "Entity", - "Player", - "Vehicle", - "Blip", - "PointBlip", - "Checkpoint", - "VoiceChannel", - "Colshape", - "ColshapeCylinder", - "ColshapeSphere", - "ColshapeCircle", - "ColshapeCuboid", - "ColshapeRectangle" + v8Vector3, + v8RGBA, + v8File, + v8BaseObject, + v8WorldObject, + v8Entity, + v8Player, + v8Vehicle, + v8Blip, + v8PointBlip, + v8Checkpoint, + v8VoiceChannel, + v8Colshape, + v8ColshapeCylinder, + v8ColshapeSphere, + v8ColshapeCircle, + v8ColshapeCuboid, + v8ColshapeRectangle }, [](v8::Local ctx, v8::Local exports) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); @@ -292,7 +311,6 @@ static V8Module v8Alt("alt", alt::StringView rootDir = alt::ICore::Instance().GetRootDirectory(); exports->Set(isolate->GetEnteredContext(), v8::String::NewFromUtf8(isolate, "rootDir"), v8::String::NewFromUtf8(isolate, rootDir.CStr())); - alt::IResource* resource = V8ResourceImpl::GetResource(ctx); - V8_CHECK(resource, "invalid resource"); - exports->Set(isolate->GetEnteredContext(), v8::String::NewFromUtf8(isolate, "resourceName"), v8::String::NewFromUtf8(isolate, resource->GetName().CStr())); + exports->Set(isolate->GetEnteredContext(), v8::String::NewFromUtf8(isolate, "defaultDimension"), v8::Integer::New(isolate, alt::DEFAULT_DIMENSION)); + exports->Set(isolate->GetEnteredContext(), v8::String::NewFromUtf8(isolate, "globalDimension"), v8::Integer::New(isolate, alt::GLOBAL_DIMENSION)); }); diff --git a/src/bindings/Player.cpp b/src/bindings/Player.cpp index 694d90d9..e1b83666 100644 --- a/src/bindings/Player.cpp +++ b/src/bindings/Player.cpp @@ -478,6 +478,21 @@ static void RemoveAllWeapons(const v8::FunctionCallbackInfo& info) player->RemoveAllWeapons(); } +static void ClearBloodDamage(const v8::FunctionCallbackInfo& info) +{ + v8::Isolate* isolate = info.GetIsolate(); + + V8ResourceImpl* resource = V8ResourceImpl::Get(isolate->GetEnteredContext()); + V8_CHECK(resource, "invalid resource"); + + V8Entity* _this = V8Entity::Get(info.This()); + V8_CHECK(_this, "entity is invalid"); + + Ref player = _this->GetHandle().As(); + + player->ClearBloodDamage(); +} + static void AddWeaponComponent(const v8::FunctionCallbackInfo& info) { v8::Isolate* isolate = info.GetIsolate(); @@ -589,7 +604,8 @@ static void StaticGetByID(const v8::FunctionCallbackInfo& info) } } -static V8Class v8Player("Player", "Entity", nullptr, [](v8::Local tpl) { +extern V8Class v8Entity; +extern V8Class v8Player("Player", v8Entity, nullptr, [](v8::Local tpl) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::Local proto = tpl->PrototypeTemplate(); @@ -626,6 +642,7 @@ static V8Class v8Player("Player", "Entity", nullptr, [](v8::LocalSet(v8::String::NewFromUtf8(isolate, "setDateTime"), v8::FunctionTemplate::New(isolate, &SetDateTime)); proto->Set(v8::String::NewFromUtf8(isolate, "setWeather"), v8::FunctionTemplate::New(isolate, &SetWeather)); + proto->Set(v8::String::NewFromUtf8(isolate, "clearBloodDamage"), v8::FunctionTemplate::New(isolate, &ClearBloodDamage)); proto->Set(v8::String::NewFromUtf8(isolate, "giveWeapon"), v8::FunctionTemplate::New(isolate, &GiveWeapon)); proto->Set(v8::String::NewFromUtf8(isolate, "removeWeapon"), v8::FunctionTemplate::New(isolate, &RemoveWeapon)); proto->Set(v8::String::NewFromUtf8(isolate, "removeAllWeapons"), v8::FunctionTemplate::New(isolate, &RemoveAllWeapons)); diff --git a/src/bindings/Vehicle.cpp b/src/bindings/Vehicle.cpp index 033897d1..3d8b732e 100644 --- a/src/bindings/Vehicle.cpp +++ b/src/bindings/Vehicle.cpp @@ -20,6 +20,20 @@ static void DriverGetter(v8::Local name, const v8::PropertyCallbackI V8_RETURN_BASE_OBJECT(_this->GetDriver()); } +static void GetAttached(const v8::FunctionCallbackInfo& info) +{ + V8_GET_ISOLATE_CONTEXT_RESOURCE(); + V8_GET_THIS_BASE_OBJECT(_this, IVehicle); + V8_RETURN_BASE_OBJECT(_this->GetAttached()); +} + +static void GetAttachedTo(const v8::FunctionCallbackInfo& info) +{ + V8_GET_ISOLATE_CONTEXT_RESOURCE(); + V8_GET_THIS_BASE_OBJECT(_this, IVehicle); + V8_RETURN_BASE_OBJECT(_this->GetAttachedTo()); +} + static void DestroyedGetter(v8::Local name, const v8::PropertyCallbackInfo& info) { V8_GET_ISOLATE_CONTEXT(); @@ -101,7 +115,8 @@ static void StaticGetByID(const v8::FunctionCallbackInfo& info) } } -static V8Class v8Vehicle("Vehicle", "Entity", Constructor, [](v8::Local tpl) { +extern V8Class v8Entity; +extern V8Class v8Vehicle("Vehicle", v8Entity, Constructor, [](v8::Local tpl) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::Local proto = tpl->PrototypeTemplate(); @@ -215,6 +230,7 @@ static V8Class v8Vehicle("Vehicle", "Entity", Constructor, [](v8::LocalSet(v8::String::NewFromUtf8(isolate, "setArmoredWindowShootCount"), v8::FunctionTemplate::New(isolate, &SetArmoredWindowShootCount)); proto->Set(v8::String::NewFromUtf8(isolate, "getDamageStatusBase64"), v8::FunctionTemplate::New(isolate, &GetDamageStatus)); proto->Set(v8::String::NewFromUtf8(isolate, "setDamageStatusBase64"), v8::FunctionTemplate::New(isolate, &SetDamageStatus)); + proto->Set(v8::String::NewFromUtf8(isolate, "repair"), v8::FunctionTemplate::New(isolate, &SetFixed)); //Script getters/setters proto->SetAccessor(v8::String::NewFromUtf8(isolate, "manualEngineControl"), &ManualEngineControlGetter, &ManualEngineControlSetter); @@ -222,4 +238,8 @@ static V8Class v8Vehicle("Vehicle", "Entity", Constructor, [](v8::LocalSet(v8::String::NewFromUtf8(isolate, "getScriptDataBase64"), v8::FunctionTemplate::New(isolate, &GetScriptData)); proto->Set(v8::String::NewFromUtf8(isolate, "setScriptDataBase64"), v8::FunctionTemplate::New(isolate, &SetScriptData)); + + + proto->Set(v8::String::NewFromUtf8(isolate, "getAttached"), v8::FunctionTemplate::New(isolate, &GetAttached)); + proto->Set(v8::String::NewFromUtf8(isolate, "getAttachedTo"), v8::FunctionTemplate::New(isolate, &GetAttachedTo)); }); diff --git a/src/bindings/VoiceChannel.cpp b/src/bindings/VoiceChannel.cpp index 91ecf617..11ef5077 100644 --- a/src/bindings/VoiceChannel.cpp +++ b/src/bindings/VoiceChannel.cpp @@ -147,7 +147,8 @@ static void Constructor(const v8::FunctionCallbackInfo& info) "Failed to create VoiceChannel, make sure voice chat is enabled"); } -static V8Class v8VoiceChannel("VoiceChannel", "BaseObject", Constructor, [](v8::Local tpl) { +extern V8Class v8BaseObject; +extern V8Class v8VoiceChannel("VoiceChannel", v8BaseObject, Constructor, [](v8::Local tpl) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); V8::SetMethod(isolate, tpl, "addPlayer", &AddPlayer); diff --git a/src/bindings/vehicle/Damage.h b/src/bindings/vehicle/Damage.h index f3e48a0c..59070fb6 100644 --- a/src/bindings/vehicle/Damage.h +++ b/src/bindings/vehicle/Damage.h @@ -324,6 +324,18 @@ namespace V8::Vehicle vehicle->LoadDamageDataFromBase64(*damageStatus); } + void SetFixed(const v8::FunctionCallbackInfo& info) + { + v8::Isolate* isolate = info.GetIsolate(); + + V8Entity* _this = V8Entity::Get(info.This()); + V8_CHECK(_this, "entity is invalid"); + + Ref vehicle = _this->GetHandle().As(); + + vehicle->SetFixed(); + } + void GetDamageStatus(const v8::FunctionCallbackInfo& info) { v8::Isolate* isolate = info.GetIsolate(); diff --git a/src/cpp-sdk b/src/cpp-sdk index 6addd980..3e8d71e7 160000 --- a/src/cpp-sdk +++ b/src/cpp-sdk @@ -1 +1 @@ -Subproject commit 6addd980bdea3fb0aa3d3dfef1f400172cd3c708 +Subproject commit 3e8d71e76b760e8c97684090fda65782e212eeed diff --git a/src/events/Player.cpp b/src/events/Player.cpp index 7713b928..17307b76 100644 --- a/src/events/Player.cpp +++ b/src/events/Player.cpp @@ -8,6 +8,7 @@ #include "cpp-sdk/events/CPlayerDamageEvent.h" #include "cpp-sdk/events/CPlayerDeathEvent.h" #include "cpp-sdk/events/CPlayerEnterVehicleEvent.h" +#include "cpp-sdk/events/CPlayerEnteringVehicleEvent.h" #include "cpp-sdk/events/CPlayerLeaveVehicleEvent.h" #include "cpp-sdk/events/CPlayerChangeVehicleSeatEvent.h" #include "cpp-sdk/events/CPlayerWeaponChangeEvent.h" @@ -74,6 +75,18 @@ V8::LocalEventHandler playerEnterVehicle( } ); +V8::LocalEventHandler playerEnteringVehicle( + EventType::PLAYER_ENTERING_VEHICLE, + "playerEnteringVehicle", // TODO: don't change names, it's okay + [](V8ResourceImpl* resource, const CEvent* e, std::vector>& args) { + auto ev = static_cast(e); + + args.push_back(resource->GetBaseObjectOrNull(ev->GetPlayer())); + args.push_back(resource->GetBaseObjectOrNull(ev->GetTarget())); + args.push_back(v8::Integer::New(resource->GetIsolate(), ev->GetSeat())); + } +); + V8::LocalEventHandler playerLeaveVehicle( EventType::PLAYER_LEAVE_VEHICLE, "playerLeftVehicle", // TODO: change name for consistency diff --git a/src/events/Vehicle.cpp b/src/events/Vehicle.cpp index dcf54837..75878ea0 100644 --- a/src/events/Vehicle.cpp +++ b/src/events/Vehicle.cpp @@ -3,6 +3,10 @@ #include "helpers/V8ResourceImpl.h" #include "helpers/V8Helpers.h" +#include "cpp-sdk/events/CVehicleAttachEvent.h" +#include "cpp-sdk/events/CVehicleDetachEvent.h" +#include "cpp-sdk/events/CNetOwnerChangeEvent.h" + using alt::CEvent; using EventType = CEvent::Type; @@ -13,4 +17,38 @@ V8::LocalEventHandler vehicleDestroy( auto ev = static_cast(e); args.push_back(resource->GetBaseObjectOrNull(ev->GetTarget())); } +); + +V8::LocalEventHandler vehicleAttach( + EventType::VEHICLE_ATTACH, + "vehicleAttach", + [](V8ResourceImpl* resource, const CEvent* e, std::vector>& args) { + auto ev = static_cast(e); + + args.push_back(resource->GetBaseObjectOrNull(ev->GetTarget())); + args.push_back(resource->GetBaseObjectOrNull(ev->GetAttached())); + } +); + +V8::LocalEventHandler vehicleDetach( + EventType::VEHICLE_DETACH, + "vehicleDetach", + [](V8ResourceImpl* resource, const CEvent* e, std::vector>& args) { + auto ev = static_cast(e); + + args.push_back(resource->GetBaseObjectOrNull(ev->GetTarget())); + args.push_back(resource->GetBaseObjectOrNull(ev->GetDetached())); + } +); + +V8::LocalEventHandler netOwnerChange( + EventType::NETOWNER_CHANGE, + "netOwnerChange", + [](V8ResourceImpl* resource, const CEvent* e, std::vector>& args) { + auto ev = static_cast(e); + + args.push_back(resource->GetBaseObjectOrNull(ev->GetTarget())); + args.push_back(resource->GetBaseObjectOrNull(ev->GetNewOwner())); + args.push_back(resource->GetBaseObjectOrNull(ev->GetOldOwner())); + } ); \ No newline at end of file diff --git a/src/helpers b/src/helpers index c26a3dd9..28feb50f 160000 --- a/src/helpers +++ b/src/helpers @@ -1 +1 @@ -Subproject commit c26a3dd97c3f007c5db24c2a10982be59e5a0a66 +Subproject commit 28feb50ff84b943900a50622805ac4d429a7ab96 diff --git a/src/node-module.cpp b/src/node-module.cpp index fee46364..11e2fede 100644 --- a/src/node-module.cpp +++ b/src/node-module.cpp @@ -24,12 +24,13 @@ //v8::V8::Dispose(); }*/ +extern V8Module v8Alt; static void Initialize(v8::Local exports) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::HandleScope handle_scope(isolate); - V8Module::All().at("alt")->Register(isolate, isolate->GetEnteredContext(), exports); + v8Alt.Register(isolate, isolate->GetEnteredContext(), exports); } NODE_MODULE_LINKED(alt, Initialize) diff --git a/src/stdafx.h b/src/stdafx.h index 51fb968d..ed2828fb 100644 --- a/src/stdafx.h +++ b/src/stdafx.h @@ -18,7 +18,7 @@ #include #include "cpp-sdk/SDK.h" -#include "Log.h" +#include "helpers/Log.h" #include "node.h" #include "node_platform.h" #include "node_internals.h"