├── docs ├── articles │ ├── api-reference │ │ ├── api.md │ │ └── events.md │ ├── stylesheets │ │ └── extra.css │ ├── vehicle.md │ ├── colshapes.md │ ├── vectors.md │ ├── index.md │ ├── intro.md │ ├── tasks.md │ ├── additional-information.md │ └── events.md ├── alt │ ├── __init__.py │ └── events.py ├── README.md └── mkdocs.yml ├── stubs ├── .gitignore ├── setup.py ├── setup.cfg └── README.md ├── .editorconfig ├── src ├── bindings │ ├── bindings.hpp │ ├── bindings.cpp │ ├── log.cpp │ ├── intervals.cpp │ ├── events.cpp │ └── alt.cpp ├── main.hpp ├── main.cpp ├── events │ ├── events.cpp │ ├── events.hpp │ ├── vehicle.cpp │ ├── meta.cpp │ ├── Main.cpp │ └── player.cpp ├── utils.hpp ├── classes │ ├── base │ │ ├── worldobject.cpp │ │ ├── voicechannel.cpp │ │ ├── baseobject.cpp │ │ ├── checkpoint.cpp │ │ ├── colshape.cpp │ │ ├── entity.cpp │ │ ├── blip.cpp │ │ ├── player.cpp │ │ └── vehicle.cpp │ ├── types │ │ ├── rgba.cpp │ │ ├── resource.cpp │ │ ├── connectioninfo.cpp │ │ ├── enums.cpp │ │ ├── vehiclemodelinfo.cpp │ │ ├── vector2.hpp │ │ ├── resource.hpp │ │ ├── vector3.hpp │ │ ├── vector2.cpp │ │ ├── vector3.cpp │ │ └── enums.hpp │ └── classes.hpp ├── interval.hpp ├── PythonRuntime.hpp ├── interval.cpp ├── PythonResource.hpp ├── PythonRuntime.cpp ├── utils.cpp └── PythonResource.cpp ├── .gitmodules ├── .gitignore ├── README.md ├── cmake └── python.cmake ├── CMakeLists.txt ├── .clang-format └── .github └── workflows └── build.yml /docs/articles/api-reference/api.md: -------------------------------------------------------------------------------- 1 | ::: alt -------------------------------------------------------------------------------- /docs/articles/api-reference/events.md: -------------------------------------------------------------------------------- 1 | ::: alt.events -------------------------------------------------------------------------------- /docs/alt/__init__.py: -------------------------------------------------------------------------------- 1 | ../../stubs/alt-stubs/__init__.pyi -------------------------------------------------------------------------------- /stubs/.gitignore: -------------------------------------------------------------------------------- 1 | altv_stubs.egg-info/ 2 | build/ 3 | dist/ -------------------------------------------------------------------------------- /stubs/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | 4 | setup( 5 | name="altv-stubs", 6 | packages=["alt-stubs"], 7 | package_data={"alt-stubs": ["__init__.pyi"]}, 8 | ) 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 4 6 | end_of_line = crlf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | -------------------------------------------------------------------------------- /src/bindings/bindings.hpp: -------------------------------------------------------------------------------- 1 | #include "main.hpp" 2 | 3 | void RegisterLogFunctions(py::module_ m); 4 | void RegisterEventFunctions(py::module_ m); 5 | void RegisterMainFunctions(py::module_ m); 6 | void RegisterIntervalFunctions(py::module_ m); 7 | -------------------------------------------------------------------------------- /stubs/setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | name = alt-stubs 3 | version = 1.0.1 4 | license = MIT 5 | author = ZackaryH8 & Marvis 6 | url = https://github.com/ZackaryH8/altv-python-stubs 7 | description = Stubs for alt:V Python Module 8 | long_description = file: README.md 9 | long_description_content_type = text/markdown 10 | keywords = mypy, altv 11 | -------------------------------------------------------------------------------- /stubs/README.md: -------------------------------------------------------------------------------- 1 | # altv-python-stubs 2 | 3 | # What is this? 4 | This is a file to allow autocomplete for the alt:V Python Module. A manual approach was chosen for this because the autogenerated ones were not great. Based on [alt:V Types](https://github.com/altmp/altv-types). 5 | 6 | # Installation 7 | ``` 8 | $ pip install altv-stubs 9 | ``` 10 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "vendors/cpp-sdk"] 2 | path = vendors/cpp-sdk 3 | url = https://github.com/altmp/cpp-sdk 4 | [submodule "vendors/magic_enum"] 5 | path = vendors/magic_enum 6 | url = https://github.com/Neargye/magic_enum 7 | ignore = dirty 8 | [submodule "vendors/pybind11"] 9 | path = vendors/pybind11 10 | url = https://github.com/pybind/pybind11 11 | branch = stable 12 | -------------------------------------------------------------------------------- /src/main.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define ALT_SERVER_API 4 | 5 | #ifdef _WIN32 6 | static char SEPARATOR = '\\'; 7 | #else 8 | static char SEPARATOR = '/'; 9 | #endif 10 | 11 | // Standard C++ stuff 12 | #include 13 | #include 14 | #include 15 | 16 | // AltV SDK 17 | #include 18 | 19 | // Python API 20 | #include 21 | #include 22 | #include 23 | 24 | namespace py = pybind11;// NOLINT 25 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # altv-python-docs 2 | 3 | This is repository for official [alt:V Python Module](https://github.com/Marvisak/altv-python-module) docs 4 | 5 | ## Requirements 6 | 7 | - MkDocs 8 | - Material Theme 9 | - MkDocStrings and the Python Handler 10 | 11 | ## How to start 12 | 13 | ``` 14 | >>> mkdocs serve 15 | ``` 16 | 17 | ## Contributing 18 | If you feel like some feature is not documented, or you would like to add something, feel free to create a PR with your changes, any contribution is appreciated -------------------------------------------------------------------------------- /docs/articles/stylesheets/extra.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --md-primary-fg-color: #008736; 3 | --md-primary-fg-color--light: #F1F2F2; 4 | --md-primary-fg-color--dark: #1F1F1F; 5 | } 6 | 7 | :root, 8 | [data-md-color-scheme=default] { 9 | --md-primary-fg-color: #008736; 10 | --md-primary-fg-color--light: #F1F2F2; 11 | --md-primary-fg-color--dark: #1F1F1F; 12 | } 13 | 14 | 15 | div.doc-contents:not(.first) { 16 | padding-left: 25px; 17 | border-left: .05rem solid var(--md-default-fg-color--lightest); 18 | margin-bottom: 80px; 19 | } -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "main.hpp" 2 | #include "PythonRuntime.hpp" 3 | #include "version/version.h" 4 | 5 | EXPORT bool altMain(alt::ICore* core) 6 | { 7 | alt::ICore::SetInstance(core); 8 | 9 | try 10 | { 11 | auto runtime = new PythonRuntime(); 12 | core->RegisterScriptRuntime("py", runtime); 13 | } 14 | catch (std::exception& e) 15 | { 16 | core->LogError(e.what()); 17 | return false; 18 | } 19 | 20 | core->LogInfo("Python module successfully loaded"); 21 | return true; 22 | } 23 | 24 | EXPORT const char* GetSDKHash() 25 | { 26 | return ALT_SDK_VERSION; 27 | } 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | dist/ 3 | docs/site/ 4 | cmake-build*/ 5 | CMakeSettings.json 6 | .cache/ 7 | 8 | ### IDE ### 9 | .idea 10 | .vs 11 | .vscode 12 | 13 | ### C++ ### 14 | # Prerequisites 15 | *.d 16 | 17 | # Compiled Object files 18 | *.slo 19 | *.lo 20 | *.o 21 | *.obj 22 | 23 | # Precompiled Headers 24 | *.gch 25 | *.pch 26 | 27 | # Compiled Dynamic libraries 28 | *.so 29 | *.dylib 30 | *.dll 31 | 32 | # Fortran module files 33 | *.mod 34 | *.smod 35 | 36 | # Compiled Static libraries 37 | *.lai 38 | *.la 39 | *.a 40 | *.lib 41 | 42 | # Executables 43 | *.exe 44 | *.out 45 | *.app 46 | -------------------------------------------------------------------------------- /src/events/events.cpp: -------------------------------------------------------------------------------- 1 | #include "events.hpp" 2 | 3 | EventHandler::EventHandler(alt::CEvent::Type eventType) 4 | { 5 | all()[eventType] = this; 6 | } 7 | 8 | EventHandler::EventHandler(alt::CEvent::Type eventType, ArgsGetter argsGetter) 9 | : argsGetter(argsGetter) 10 | { 11 | all()[eventType] = this; 12 | } 13 | 14 | EventHandler* EventHandler::Get(const alt::CEvent* event) 15 | { 16 | return all()[event->GetType()]; 17 | } 18 | 19 | void EventHandler::GetEventArgs(const alt::CEvent* event, py::list& args) 20 | { 21 | if (argsGetter.has_value()) 22 | argsGetter.value()(event, args); 23 | } 24 | -------------------------------------------------------------------------------- /src/utils.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PythonRuntime.hpp" 4 | #include "main.hpp" 5 | 6 | namespace Utils 7 | { 8 | alt::MValue ValueToMValue(const py::object& arg); 9 | py::object MValueToValue(const alt::MValueConst& mValue); 10 | py::object ConfigNodeToValue(Config::Value::ValuePtr node); 11 | py::object GetBaseObject(const alt::Ref& baseObject); 12 | template 13 | py::list ArrayToPyList(const alt::Array& array) 14 | { 15 | py::list pyList; 16 | for (auto element : array) 17 | pyList.append(element); 18 | return pyList; 19 | } 20 | }// namespace Utils 21 | -------------------------------------------------------------------------------- /src/classes/base/worldobject.cpp: -------------------------------------------------------------------------------- 1 | #include "classes/classes.hpp" 2 | #include "classes/types/vector3.hpp" 3 | 4 | Vector3 GetPosition(alt::IWorldObject* _this) 5 | { 6 | return (Vector3)_this->GetPosition(); 7 | } 8 | 9 | void SetPosition(alt::IWorldObject* _this, Vector3 pos) 10 | { 11 | _this->SetPosition(pos.ToAlt()); 12 | } 13 | 14 | void RegisterWorldObjectClass(const py::module_& m) 15 | { 16 | auto pyClass = py::class_>(m, "WorldObject"); 17 | 18 | pyClass.def_property("pos", &GetPosition, &SetPosition); 19 | pyClass.def_property("dimension", &alt::IWorldObject::GetDimension, &alt::IWorldObject::SetDimension); 20 | } 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | Module Logo 3 |

alt:V Python Module

4 |

Adds alt:V serverside language support for Python

5 |

6 | 7 | ## [Docs](https://marvisak.github.io/altv-python-module/) 8 | 9 | ## How to install 10 | 1) Download the newest version from [Releases](https://github.com/Marvisak/altv-python-module/releases) 11 | 2) Open the zip file 12 | 3) Drag & Drop files from the zip into your server's modules folder 13 | 4) Open your server's server.cfg and add the module: 14 | ``` 15 | modules: [ python-module ] 16 | ``` 17 | 18 | # I really appreciate any contribution 19 | -------------------------------------------------------------------------------- /src/interval.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "main.hpp" 3 | 4 | class Interval 5 | { 6 | private: 7 | double milliseconds; 8 | py::function function; 9 | uint32_t nextTime; 10 | bool running = true; 11 | PyThreadState* interpreter; 12 | 13 | public: 14 | Interval(double milliseconds, py::function function, PyThreadState* interpreter); 15 | 16 | py::function GetFunc() 17 | { 18 | return function; 19 | } 20 | 21 | void SetRunning(bool start) 22 | { 23 | running = start; 24 | } 25 | 26 | bool IsRunning() const 27 | { 28 | return running; 29 | } 30 | 31 | void SetMilliseconds(double newMilliseconds) 32 | { 33 | milliseconds = newMilliseconds; 34 | } 35 | 36 | void TimeWarning(uint32_t time, const std::string& resourceName); 37 | 38 | bool Update(uint32_t time); 39 | }; 40 | -------------------------------------------------------------------------------- /src/PythonRuntime.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PythonResource.hpp" 4 | #include "events/events.hpp" 5 | #include "main.hpp" 6 | 7 | class PythonRuntime : public alt::IScriptRuntime 8 | { 9 | std::vector resources{}; 10 | PyThreadState* mainInterpreter; 11 | static PythonRuntime* instance; 12 | #ifdef __linux__ 13 | void* python; 14 | #endif 15 | public: 16 | PythonRuntime(); 17 | alt::IResource::Impl* CreateImpl(alt::IResource* resource) override; 18 | void DestroyImpl(alt::IResource::Impl* impl) override; 19 | void OnDispose() override; 20 | PythonResource* GetPythonResourceFromInterp(PyThreadState* state); 21 | 22 | PyThreadState* GetInterpreter() 23 | { 24 | return mainInterpreter; 25 | } 26 | 27 | static PythonRuntime* GetInstance() 28 | { 29 | return instance; 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /docs/articles/vehicle.md: -------------------------------------------------------------------------------- 1 | # Vehicle 2 | 3 | If you want to drive a vehicle you need to create it first. You can create them from serverside, and they will be completely synced. 4 | 5 | 6 | ```py 7 | import alt 8 | 9 | vehicle = alt.Vehicle("elegy", 10, 10, 10, 0, 0, 0) # Creates vehicle with the model elegy on 10,10,10 with 0,0,0 rotation 10 | vehicle2 = alt.Vehicle(alt.hash("panto"), alt.Vector3(40, 40, 40), alt.Vector3(20, 20, 20)) # Creates vehicle with model panto on 40,40,40 with 20,20,20 rotation 11 | ``` 12 | 13 | Vehicles have a lot of properties and methods you can use to edit them 14 | 15 | ```py 16 | vehicle.primary_color_rgb = alt.RGBA(255, 0, 0) # Makes the spawned vehicle red 17 | ``` 18 | 19 | You can see all the methods and properties you can use on vehicle in our stubs or inside the [API Reference](api-reference/api.md) 20 | 21 | -------------------------------------------------------------------------------- /src/bindings/bindings.cpp: -------------------------------------------------------------------------------- 1 | #include "bindings.hpp" 2 | #include "classes/classes.hpp" 3 | #include "main.hpp" 4 | 5 | PYBIND11_EMBEDDED_MODULE(alt, m) 6 | { 7 | m.doc() = "alt:V Python Module"; 8 | 9 | RegisterEnums(m); 10 | RegisterVector2Class(m); 11 | RegisterVector3Class(m); 12 | RegisterRGBAClass(m); 13 | RegisterConnectionInfoClass(m); 14 | RegisterVehicleModelInfoClass(m); 15 | RegisterResourceClass(m); 16 | 17 | RegisterBaseObjectClass(m); 18 | RegisterWorldObjectClass(m); 19 | RegisterEntityClass(m); 20 | RegisterVehicleClass(m); 21 | RegisterPlayerClass(m); 22 | RegisterColShapeClass(m); 23 | RegisterBlipClass(m); 24 | RegisterCheckpointClass(m); 25 | RegisterVoiceChannelClass(m); 26 | 27 | RegisterLogFunctions(m); 28 | RegisterEventFunctions(m); 29 | RegisterMainFunctions(m); 30 | RegisterIntervalFunctions(m); 31 | } 32 | -------------------------------------------------------------------------------- /src/events/events.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "main.hpp" 3 | 4 | class EventHandler 5 | { 6 | static std::unordered_map& all() 7 | { 8 | static std::unordered_map _all; 9 | return _all; 10 | } 11 | using ArgsGetter = std::function; 12 | std::optional argsGetter; 13 | 14 | public: 15 | EventHandler(alt::CEvent::Type eventType, ArgsGetter argsGetter); 16 | // TODO probably remove this 17 | explicit EventHandler(alt::CEvent::Type eventType);// This is kinda useless, currently it's only used to know that the event is registered, might be removed in the future, but I'll keep it here now 18 | void GetEventArgs(const alt::CEvent* event, py::list& args); 19 | 20 | static EventHandler* Get(const alt::CEvent* event); 21 | }; 22 | -------------------------------------------------------------------------------- /src/classes/types/rgba.cpp: -------------------------------------------------------------------------------- 1 | #include "classes/classes.hpp" 2 | 3 | std::string ToString(alt::RGBA _this) 4 | { 5 | return "RGBA(" + std::to_string(_this.r) + ", " + std::to_string(_this.g) + ", " + std::to_string(_this.b) + ", " + std::to_string(_this.a) + ")"; 6 | } 7 | 8 | py::list ToList(alt::RGBA _this) 9 | { 10 | py::list list; 11 | list.append(_this.r); 12 | list.append(_this.g); 13 | list.append(_this.b); 14 | list.append(_this.a); 15 | return list; 16 | } 17 | 18 | void RegisterRGBAClass(const py::module_& m) 19 | { 20 | auto pyClass = py::class_(m, "RGBA"); 21 | pyClass.def(py::init(), py::arg("r"), py::arg("g"), py::arg("b"), py::arg("a") = 255); 22 | pyClass.def_readwrite("r", &alt::RGBA::r); 23 | pyClass.def_readwrite("g", &alt::RGBA::g); 24 | pyClass.def_readwrite("b", &alt::RGBA::b); 25 | pyClass.def_readwrite("a", &alt::RGBA::a); 26 | pyClass.def("to_bgra", &alt::RGBA::toBGRA); 27 | pyClass.def("to_argb", &alt::RGBA::toARGB); 28 | pyClass.def("to_list", &ToList); 29 | pyClass.def("__str__", &ToString); 30 | } 31 | -------------------------------------------------------------------------------- /src/classes/classes.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "main.hpp" 3 | 4 | PYBIND11_DECLARE_HOLDER_TYPE(T, alt::Ref, true) 5 | 6 | namespace pybind11::detail 7 | { 8 | template 9 | struct holder_helper> { 10 | static const T* get(const alt::Ref& p) 11 | { 12 | return p.Get(); 13 | } 14 | }; 15 | }// namespace pybind11::detail 16 | 17 | void RegisterEnums(const py::module_& m); 18 | void RegisterRGBAClass(const py::module_& m); 19 | void RegisterConnectionInfoClass(const py::module_& m); 20 | void RegisterVehicleModelInfoClass(const py::module_& m); 21 | void RegisterVector2Class(const py::module_& m); 22 | void RegisterVector3Class(const py::module_& m); 23 | void RegisterBaseObjectClass(const py::module_& m); 24 | void RegisterWorldObjectClass(const py::module_& m); 25 | void RegisterEntityClass(const py::module_& m); 26 | void RegisterPlayerClass(const py::module_& m); 27 | void RegisterVehicleClass(const py::module_& m); 28 | void RegisterColShapeClass(const py::module_& m); 29 | void RegisterResourceClass(const py::module_& m); 30 | void RegisterBlipClass(const py::module_& m); 31 | void RegisterCheckpointClass(const py::module_& m); 32 | void RegisterVoiceChannelClass(const py::module_& m); 33 | -------------------------------------------------------------------------------- /src/classes/types/resource.cpp: -------------------------------------------------------------------------------- 1 | #include "resource.hpp" 2 | 3 | void RegisterResourceClass(const py::module_& m) 4 | { 5 | auto pyClass = py::class_(m, "Resource"); 6 | pyClass.def_property_readonly("is_started", &Resource::IsStarted); 7 | pyClass.def_property_readonly("type", &Resource::GetType); 8 | pyClass.def_property_readonly("name", &Resource::GetName); 9 | pyClass.def_property_readonly("main", &Resource::GetMain); 10 | pyClass.def_property_readonly("path", &Resource::GetPath); 11 | pyClass.def_property_readonly("config", &Resource::GetConfig); 12 | pyClass.def_property_readonly("exports", &Resource::GetExports); 13 | pyClass.def_property_readonly("dependencies", &Resource::GetDependencies); 14 | pyClass.def_property_readonly("dependants", &Resource::GetDependants); 15 | pyClass.def_property_readonly("required_permissions", &Resource::GetRequiredPermissions); 16 | pyClass.def_property_readonly("optional_permissions", &Resource::GetOptionalPermissions); 17 | 18 | pyClass.def_static("get_by_name", &Resource::GetByName, py::arg("resource_name")); 19 | pyClass.def_property_readonly_static("all", &Resource::GetAllResources); 20 | pyClass.def_property_readonly_static("current", &Resource::GetCurrent); 21 | } 22 | -------------------------------------------------------------------------------- /src/bindings/log.cpp: -------------------------------------------------------------------------------- 1 | #include "main.hpp" 2 | 3 | void Log(const py::args& args, const std::string& separator = " ") 4 | { 5 | std::string str; 6 | for (const py::handle& arg : args) 7 | { 8 | if (!str.empty()) 9 | str += separator; 10 | str += py::str(arg).cast(); 11 | } 12 | alt::ICore::Instance().LogColored(str); 13 | } 14 | 15 | void LogError(const py::args& args, const std::string& separator = " ") 16 | { 17 | std::string str; 18 | for (const py::handle& arg : args) 19 | { 20 | if (!str.empty()) 21 | str += separator; 22 | str += py::str(arg).cast(); 23 | } 24 | alt::ICore::Instance().LogError(str); 25 | } 26 | 27 | void LogWarning(const py::args& args, const std::string& separator = " ") 28 | { 29 | std::string str; 30 | for (const py::handle& arg : args) 31 | { 32 | if (!str.empty()) 33 | str += separator; 34 | str += py::str(arg).cast(); 35 | } 36 | alt::ICore::Instance().LogWarning(str); 37 | } 38 | 39 | void RegisterLogFunctions(py::module_ m) 40 | { 41 | m.def("log", &Log, py::arg("sep") = " ", "Logs text to the console"); 42 | m.def("log_error", &LogError, py::arg("sep") = " ", "Logs error to the console"); 43 | m.def("log_warning", &LogWarning, py::arg("sep") = " ", "Logs warning to the console"); 44 | } 45 | -------------------------------------------------------------------------------- /src/interval.cpp: -------------------------------------------------------------------------------- 1 | #include "interval.hpp" 2 | #include "PythonRuntime.hpp" 3 | 4 | Interval::Interval(double milliseconds, py::function function, PyThreadState* interpreter) 5 | : milliseconds(milliseconds), function(std::move(function)), interpreter(interpreter) 6 | { 7 | nextTime = alt::ICore::Instance().GetNetTime() + (long)milliseconds; 8 | } 9 | 10 | void Interval::TimeWarning(uint32_t time, const std::string& resourceName) 11 | { 12 | auto inspect = py::module_::import("inspect"); 13 | auto path = inspect.attr("getfile")(function).cast(); 14 | std::string str = std::string("Interval at ").append(resourceName).append(":").append(path.substr(path.find_last_of("/\\") + 1)).append(" at function ").append(function.attr("__name__").cast()).append(" was too long ").append(std::to_string(alt::ICore::Instance().GetNetTime() - time)).append("ms"); 15 | alt::ICore::Instance().LogWarning(str); 16 | } 17 | 18 | bool Interval::Update(uint32_t time) 19 | { 20 | if (time >= nextTime && running) 21 | { 22 | try 23 | { 24 | PyThreadState_Swap(interpreter); 25 | function(); 26 | PyThreadState_Swap(PythonRuntime::GetInstance()->GetInterpreter()); 27 | } 28 | catch (py::error_already_set& e) 29 | { 30 | e.discard_as_unraisable(function.attr("__name__")); 31 | } 32 | nextTime = time + (long)milliseconds; 33 | return true; 34 | } 35 | return false; 36 | } 37 | -------------------------------------------------------------------------------- /src/events/vehicle.cpp: -------------------------------------------------------------------------------- 1 | #include "events.hpp" 2 | #include "utils.hpp" 3 | 4 | EventHandler vehicleDestroy(alt::CEvent::Type::VEHICLE_DESTROY, [](const alt::CEvent* ev, py::list& args) { 5 | auto event = dynamic_cast(ev); 6 | args.append(event->GetTarget().Get()); 7 | }); 8 | 9 | EventHandler vehicleDamage(alt::CEvent::Type::VEHICLE_DAMAGE, [](const alt::CEvent* ev, py::list& args) { 10 | auto event = dynamic_cast(ev); 11 | args.append(event->GetTarget().Get()); 12 | args.append(Utils::GetBaseObject(event->GetDamager())); 13 | args.append(event->GetBodyHealthDamage()); 14 | args.append(event->GetBodyAdditionalHealthDamage()); 15 | args.append(event->GetEngineHealthDamage()); 16 | args.append(event->GetPetrolTankHealthDamage()); 17 | args.append(event->GetDamagedWith()); 18 | }); 19 | 20 | EventHandler vehicleAttach(alt::CEvent::Type::VEHICLE_ATTACH, [](const alt::CEvent* ev, py::list& args) { 21 | auto event = dynamic_cast(ev); 22 | args.append(event->GetTarget().Get()); 23 | args.append(event->GetAttached().Get()); 24 | }); 25 | 26 | EventHandler vehicleDetach(alt::CEvent::Type::VEHICLE_DETACH, [](const alt::CEvent* ev, py::list& args) { 27 | auto event = dynamic_cast(ev); 28 | args.append(event->GetTarget().Get()); 29 | args.append(event->GetDetached().Get()); 30 | }); 31 | -------------------------------------------------------------------------------- /src/classes/types/connectioninfo.cpp: -------------------------------------------------------------------------------- 1 | #include "classes/classes.hpp" 2 | 3 | void RegisterConnectionInfoClass(const py::module_& m) 4 | { 5 | auto pyClass = py::class_>(m, "ConnectionInfo"); 6 | pyClass.def_property_readonly("name", &alt::IConnectionInfo::GetName); 7 | pyClass.def_property_readonly("social_id", &alt::IConnectionInfo::GetSocialId); 8 | pyClass.def_property_readonly("hwid_hash", &alt::IConnectionInfo::GetHwIdHash); 9 | pyClass.def_property_readonly("hwid_ex_hash", &alt::IConnectionInfo::GetHwIdExHash); 10 | pyClass.def_property_readonly("auth_token", &alt::IConnectionInfo::GetAuthToken); 11 | pyClass.def_property_readonly("is_debug", &alt::IConnectionInfo::GetIsDebug); 12 | pyClass.def_property_readonly("branch", &alt::IConnectionInfo::GetBranch); 13 | pyClass.def_property_readonly("build", &alt::IConnectionInfo::GetBuild); 14 | pyClass.def_property_readonly("cdn_url", &alt::IConnectionInfo::GetCdnUrl); 15 | pyClass.def_property_readonly("password_hash", &alt::IConnectionInfo::GetPasswordHash); 16 | pyClass.def_property_readonly("ip", &alt::IConnectionInfo::GetIp); 17 | pyClass.def_property_readonly("discord_user_id", &alt::IConnectionInfo::GetDiscordUserID); 18 | pyClass.def_property_readonly("accepted", &alt::IConnectionInfo::IsAccepted); 19 | 20 | pyClass.def("accept", &alt::IConnectionInfo::Accept); 21 | pyClass.def("decline", &alt::IConnectionInfo::Decline, py::arg("reason")); 22 | } 23 | -------------------------------------------------------------------------------- /src/classes/base/voicechannel.cpp: -------------------------------------------------------------------------------- 1 | #include "classes/classes.hpp" 2 | 3 | void RegisterVoiceChannelClass(const py::module_& m) 4 | { 5 | auto pyClass = py::class_>(m, "VoiceChannel"); 6 | 7 | pyClass.def(py::init<>([](bool spatial, float maxDistance) { 8 | auto voiceChannel = alt::ICore::Instance().CreateVoiceChannel(spatial, maxDistance); 9 | if (voiceChannel) 10 | return voiceChannel.Get(); 11 | throw std::runtime_error("Failed to create VoiceChannel, make sure voice chat is enabled"); 12 | }), 13 | py::arg("spatial"), py::arg("max_distance")); 14 | 15 | pyClass.def_property_readonly("player_count", &alt::IVoiceChannel::GetPlayerCount); 16 | pyClass.def_property_readonly("players", &alt::IVoiceChannel::GetPlayers); 17 | pyClass.def_property_readonly("max_distance", &alt::IVoiceChannel::GetMaxDistance); 18 | pyClass.def_property_readonly("spatial", &alt::IVoiceChannel::IsSpatial); 19 | 20 | pyClass.def("add_player", &alt::IVoiceChannel::AddPlayer, py::arg("player")); 21 | pyClass.def("has_player", &alt::IVoiceChannel::HasPlayer, py::arg("player")); 22 | pyClass.def("is_player_muted", &alt::IVoiceChannel::IsPlayerMuted, py::arg("player")); 23 | pyClass.def("mute_player", &alt::IVoiceChannel::MutePlayer, py::arg("player")); 24 | pyClass.def("remove_player", &alt::IVoiceChannel::RemovePlayer); 25 | pyClass.def("unmute_player", &alt::IVoiceChannel::UnmutePlayer); 26 | } 27 | -------------------------------------------------------------------------------- /src/classes/types/enums.cpp: -------------------------------------------------------------------------------- 1 | #include "enums.hpp" 2 | #include "classes/classes.hpp" 3 | #include "magic_enum.hpp" 4 | 5 | template 6 | void export_enum(const py::module_& m, const char* enumName) 7 | { 8 | py::enum_ enum_type(m, enumName); 9 | for (const auto& [value, name] : magic_enum::enum_entries()) 10 | { 11 | enum_type.value(name.data(), value); 12 | } 13 | } 14 | 15 | void RegisterEnums(const py::module_& m) 16 | { 17 | export_enum(m, "BaseObjectType"); 18 | export_enum(m, "WeatherType"); 19 | export_enum(m, "WeaponTint"); 20 | export_enum(m, "VehicleModType"); 21 | export_enum(m, "WindowTint"); 22 | export_enum(m, "RadioStation"); 23 | export_enum(m, "VehicleLockState"); 24 | export_enum(m, "VehicleDoorState"); 25 | export_enum(m, "VehicleDoor"); 26 | export_enum(m, "VehiclePart"); 27 | export_enum(m, "VehiclePartDamage"); 28 | export_enum(m, "VehicleBumper"); 29 | export_enum(m, "VehicleBumperDamage"); 30 | export_enum(m, "NumberPlateStyle"); 31 | export_enum(m, "Event"); 32 | export_enum(m, "ExplosionType"); 33 | export_enum(m, "BodyPart"); 34 | export_enum(m, "VehicleType"); 35 | export_enum(m, "ColShapeType"); 36 | export_enum(m, "BlipColor"); 37 | export_enum(m, "BlipSprite"); 38 | export_enum(m, "CheckpointType"); 39 | export_enum(m, "ConnectDeniedReason"); 40 | } 41 | -------------------------------------------------------------------------------- /cmake/python.cmake: -------------------------------------------------------------------------------- 1 | include(ProcessorCount) 2 | 3 | function(DownloadPython py_version) 4 | set(_download_link https://www.python.org/ftp/python/${py_version}/Python-${py_version}.tgz) 5 | get_filename_component(_filename ${_download_link} NAME) 6 | set(_path ${CMAKE_CURRENT_BINARY_DIR}/${_filename}) 7 | if (NOT EXISTS ${_path}) 8 | message("Downloading ${_download_link}") 9 | file(DOWNLOAD ${_download_link} ${_path}) 10 | execute_process(COMMAND ${CMAKE_COMMAND} -E tar xfz ${_path} 11 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 12 | RESULT_VARIABLE rv) 13 | if (NOT rv EQUAL 0) 14 | message(FATAL_ERROR "extraction failed") 15 | endif() 16 | endif() 17 | endfunction() 18 | 19 | function(CompilePython py_version) 20 | set(_filename Python-${py_version}) 21 | set(_path ${CMAKE_CURRENT_BINARY_DIR}/${_filename}) 22 | if (UNIX) 23 | if (NOT EXISTS ${_path}/pyconfig.h) 24 | message("Configuring Python") 25 | execute_process(COMMAND ./configure --enable-optimizations --enable-shared 26 | WORKING_DIRECTORY ${_path} OUTPUT_QUIET) 27 | 28 | ProcessorCount(cores) 29 | message("Compiling Python") 30 | execute_process(COMMAND make -j${cores} 31 | WORKING_DIRECTORY ${_path} OUTPUT_QUIET) 32 | endif() 33 | 34 | else() 35 | if (NOT EXISTS ${_path}/PCbuild/amd64) 36 | message("Compiling Python") 37 | execute_process(COMMAND PCBuild\\build.bat -p x64 38 | WORKING_DIRECTORY ${_path} OUTPUT_QUIET) 39 | endif() 40 | endif() 41 | endfunction() -------------------------------------------------------------------------------- /src/classes/types/vehiclemodelinfo.cpp: -------------------------------------------------------------------------------- 1 | #include "classes/classes.hpp" 2 | #include "enums.hpp" 3 | 4 | VehicleType GetType(const alt::VehicleModelInfo& modelInfo) 5 | { 6 | return (VehicleType)modelInfo.modelType; 7 | } 8 | 9 | py::list GetAvailableModKits(const alt::VehicleModelInfo& modelInfo) 10 | { 11 | py::list list; 12 | for (auto modkit : modelInfo.modkits) 13 | list.append(modkit != 0xFFFF); 14 | return list; 15 | } 16 | 17 | void RegisterVehicleModelInfoClass(const py::module_& m) 18 | { 19 | auto pyClass = py::class_(m, "VehicleModelInfo"); 20 | pyClass.def_readonly("title", &alt::VehicleModelInfo::title); 21 | pyClass.def_readonly("wheels_count", &alt::VehicleModelInfo::wheelsCount); 22 | pyClass.def_readonly("has_armored_windows", &alt::VehicleModelInfo::hasArmoredWindows); 23 | pyClass.def_readonly("primary_color", &alt::VehicleModelInfo::primaryColor); 24 | pyClass.def_readonly("secondary_color", &alt::VehicleModelInfo::secondaryColor); 25 | pyClass.def_readonly("pearl_color", &alt::VehicleModelInfo::pearlColor); 26 | pyClass.def_readonly("wheels_color", &alt::VehicleModelInfo::wheelsColor); 27 | pyClass.def_readonly("interior_color", &alt::VehicleModelInfo::interiorColor); 28 | pyClass.def_readonly("dashboard_color", &alt::VehicleModelInfo::dashboardColor); 29 | pyClass.def_readonly("has_auto_attach_trailer", &alt::VehicleModelInfo::hasAutoAttachTrailer); 30 | 31 | pyClass.def_property_readonly("type", &GetType); 32 | pyClass.def_property_readonly("available_modkits", &GetAvailableModKits); 33 | 34 | pyClass.def("has_extra", &alt::VehicleModelInfo::DoesExtraExist, py::arg("extra_id")); 35 | pyClass.def("has_default_extra", &alt::VehicleModelInfo::DoesExtraDefault, py::arg("extra_id")); 36 | } 37 | -------------------------------------------------------------------------------- /docs/mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: alt:V Python Module 2 | 3 | theme: 4 | name: material 5 | palette: 6 | - media: "(prefers-color-scheme: light)" 7 | scheme: default 8 | toggle: 9 | icon: material/toggle-switch-off-outline 10 | name: Switch to dark mode 11 | - media: "(prefers-color-scheme: dark)" 12 | scheme: slate 13 | toggle: 14 | icon: material/toggle-switch 15 | name: Switch to light mode 16 | icon: 17 | repo: fontawesome/brands/github-alt 18 | 19 | docs_dir: articles 20 | repo_name: Marvisak/altv-python-module 21 | repo_url: https://github.com/Marvisak/altv-python-module 22 | edit_uri: edit/dev/docs/articles 23 | 24 | extra_css: 25 | - stylesheets/extra.css 26 | 27 | plugins: 28 | - mkdocstrings: 29 | handlers: 30 | python: 31 | import: 32 | - https://docs.python.org/3/objects.inv 33 | - https://mkdocstrings.github.io/objects.inv 34 | - https://mkdocstrings.github.io/griffe/objects.inv 35 | rendering: 36 | show_if_no_docstring: True 37 | show_source: False 38 | show_signature_annotations: True 39 | merge_init_into_class: True 40 | members_order: source 41 | 42 | markdown_extensions: 43 | - md_in_html 44 | - admonition 45 | - pymdownx.details 46 | - pymdownx.superfences 47 | - pymdownx.inlinehilite 48 | 49 | 50 | nav: 51 | - Home: "index.md" 52 | - Intro: "intro.md" 53 | - Events: "events.md" 54 | - Tasks and Timers: "tasks.md" 55 | - Vectors: "vectors.md" 56 | - Vehicle: "vehicle.md" 57 | - ColShapes: "colshapes.md" 58 | - Additional Information: "additional-information.md" 59 | - API Reference: 60 | Events: "api-reference/events.md" 61 | API: "api-reference/api.md" 62 | -------------------------------------------------------------------------------- /docs/articles/colshapes.md: -------------------------------------------------------------------------------- 1 | # ColShapes 2 | 3 | ColShapes are collision zones which can detect entities entering them/leaving them 4 | 5 | There are 6 types of colShapes: 6 | - Circle 7 | - Cylinder 8 | - Sphere 9 | - Cube 10 | - Rectangle 11 | - Polygon 12 | - Checkpoint 13 | 14 | All of them work differently, we are going to take a look at Circle and later at Checkpoint 15 | 16 | ```py 17 | import alt 18 | 19 | test_colshape = alt.ColShape.circle(0, 0, 20) 20 | 21 | @alt.event(alt.Event.ColShape) 22 | def colshape_event(colshape: alt.ColShape, entity: alt.Entity, state: bool) -> None: 23 | if colshape != test_colshape: # If it isn't our ColShape we can return 24 | return 25 | 26 | if isinstance(entity, alt.Player): 27 | if state: # Entered colshape 28 | alt.log(f"Player {entity.name} just entered colshape.") 29 | else: 30 | alt.log(f"Player {entity.name} just leaved colshape.") 31 | ``` 32 | 33 | This code will output text when player enters and leaves colshape. 34 | 35 | ## Checkpoints 36 | 37 | Checkpoints are little different from ColShapes. The biggest change is that the player can see the ColShape. 38 | 39 | ```py 40 | import alt 41 | 42 | checkpoint = alt.Checkpoint(alt.CheckpointType.Ring, 0, 0, 70, 2, 2, 255, 0, 0, 255) 43 | 44 | @alt.event(alt.Event.ColShape) 45 | def colshape_event(colshape: alt.ColShape, entity: alt.Entity, state: bool) -> None: 46 | if colshape != checkpoint: # If it isn't our Checkpoint we can return 47 | return 48 | 49 | if isinstance(entity, alt.Player): 50 | if state: # Entered checkpoint 51 | alt.log(f"Player {entity.name} just entered checkpoint.") 52 | else: 53 | alt.log(f"Player {entity.name} just leaved checkpoint.") 54 | ``` 55 | 56 | 57 | -------------------------------------------------------------------------------- /docs/articles/vectors.md: -------------------------------------------------------------------------------- 1 | # Vectors 2 | 3 | In order to progress forward we need to learn about vectors 4 | 5 | We have 2 types of vectors, Vector3 and Vector2 6 | 7 | ## Vector3 8 | 9 | This is the vector you are probably going to use the most 10 | 11 | You can create Vector3 like this: `alt.Vector3(0, 0, 0)` and replacing the 0 with your required number 12 | 13 | You can perform most mathematical operations on vectors 14 | 15 | ```py 16 | import alt 17 | 18 | vector = alt.Vector3(10, 10, 10) 19 | vector2 = alt.Vector3(20, 20, 20) 20 | 21 | alt.log(vector + vector2) 22 | alt.log(vector - vector2) 23 | alt.log(vector * vector2) 24 | alt.log(vector / vector2) 25 | ``` 26 | 27 | This code outputs: 28 | 29 | ``` 30 | Vector3(30.000000, 30.000000, 30.000000) 31 | Vector3(-10.000000, -10.000000, -10.000000) 32 | Vector3(200.000000, 200.000000, 200.000000) 33 | Vector3(0.500000, 0.500000, 0.500000) 34 | ``` 35 | 36 | ## Vector2 37 | 38 | Vector2 is almost identical to Vector3, but you only get 2 numbers 39 | 40 | You can create Vector2 like this `alt.Vector2(0, 0)` 41 | 42 | You can also perform most mathematical operations 43 | 44 | ```py 45 | import alt 46 | 47 | vector = alt.Vector2(10, 10) 48 | vector2 = alt.Vector2(20, 20) 49 | 50 | alt.log(vector + vector2) 51 | alt.log(vector - vector2) 52 | alt.log(vector * vector2) 53 | alt.log(vector / vector2) 54 | ``` 55 | 56 | This code outputs: 57 | 58 | ``` 59 | Vector2(30.000000, 30.000000) 60 | Vector2(-10.000000, -10.000000) 61 | Vector2(200.000000, 200.000000) 62 | Vector2(0.500000, 0.500000) 63 | ``` 64 | 65 | --- 66 | 67 | Now you should know basic information about Vectors 68 | 69 | Vectors have much more functions which you can find in API reference, this should be just a quick explanation of how do they work 70 | 71 | Next we are going to learn about vehicles 72 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1) 2 | 3 | include(vendors/cpp-sdk/CMakeLists.txt) 4 | include(cmake/python.cmake) 5 | 6 | project(python-module) 7 | set(PROJECT_MODULE_NAME python-module) 8 | 9 | set(PYTHON_VERSION 3.11.0) 10 | 11 | message("Downloading and Compiling Python, this might take a while") 12 | DownloadPython(${PYTHON_VERSION}) 13 | CompilePython(${PYTHON_VERSION}) 14 | 15 | set(CMAKE_CXX_STANDARD 17) 16 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 17 | set(CMAKE_CXX_VISIBILITY_PRESET hidden) 18 | set(CMAKE_SHARED_LIBRARY_PREFIX "") 19 | 20 | add_definitions(-DMODULE_NAME="${PROJECT_MODULE_NAME}") 21 | add_definitions(-D_CRT_SECURE_NO_WARNINGS) 22 | 23 | 24 | file(GLOB_RECURSE PROJECT_SOURCE_FILES "./src/*.h" "./src/*.hpp" "./src/*.cpp") 25 | include_directories( 26 | "${PROJECT_SOURCE_DIR}/src" 27 | "${PROJECT_SOURCE_DIR}/vendors/cpp-sdk" 28 | "${PROJECT_SOURCE_DIR}/vendors/magic_enum/include" 29 | "${CMAKE_CURRENT_BINARY_DIR}/Python-${PYTHON_VERSION}/Include" 30 | "${PROJECT_SOURCE_DIR}/vendors/pybind11/include" 31 | ) 32 | 33 | if (UNIX) 34 | include_directories("${CMAKE_CURRENT_BINARY_DIR}/Python-${PYTHON_VERSION}") 35 | endif(UNIX) 36 | 37 | if (WIN32) 38 | include_directories("${CMAKE_CURRENT_BINARY_DIR}/Python-${PYTHON_VERSION}/PC") 39 | set(CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE, x64) 40 | endif(WIN32) 41 | 42 | add_library( 43 | ${PROJECT_MODULE_NAME} SHARED 44 | ${PROJECT_SOURCE_FILES} 45 | ) 46 | 47 | add_dependencies(${PROJECT_MODULE_NAME} alt-sdk) 48 | 49 | if (WIN32) 50 | target_link_libraries(${PROJECT_MODULE_NAME} ${CMAKE_CURRENT_BINARY_DIR}/Python-${PYTHON_VERSION}/PCbuild/amd64/python311.lib) 51 | endif(WIN32) 52 | 53 | if (UNIX) 54 | target_link_libraries(${PROJECT_MODULE_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/Python-${PYTHON_VERSION}/libpython3.11.so) 55 | endif(UNIX) 56 | -------------------------------------------------------------------------------- /src/classes/base/baseobject.cpp: -------------------------------------------------------------------------------- 1 | #include "classes/classes.hpp" 2 | #include "classes/types/enums.hpp" 3 | #include "utils.hpp" 4 | 5 | uint64_t GetRefCount(alt::IBaseObject* _this) 6 | { 7 | if (alt::ICore::Instance().IsDebug()) 8 | return _this->GetRefCount(); 9 | throw std::runtime_error("ref_count is only available in debug mode"); 10 | } 11 | 12 | BaseObjectType GetBaseObjectType(alt::IBaseObject* _this) 13 | { 14 | return (BaseObjectType)_this->GetType(); 15 | } 16 | 17 | bool GetValid(alt::IBaseObject* _this) 18 | { 19 | PyThreadState* interp = PyThreadState_Get(); 20 | PythonResource* resource = PythonRuntime::GetInstance()->GetPythonResourceFromInterp(interp); 21 | return resource->IsObjectValid(_this); 22 | } 23 | 24 | py::object GetMeta(alt::IBaseObject* _this, const std::string& key) 25 | { 26 | return Utils::MValueToValue(_this->GetMetaData(key)); 27 | } 28 | 29 | void SetMeta(alt::IBaseObject* _this, const std::string& key, const py::object& value) 30 | { 31 | _this->SetMetaData(key, Utils::ValueToMValue(value)); 32 | } 33 | 34 | void Destroy(alt::IBaseObject* _this) 35 | { 36 | alt::ICore::Instance().DestroyBaseObject(_this); 37 | } 38 | 39 | void RegisterBaseObjectClass(const py::module_& m) 40 | { 41 | auto pyClass = py::class_>(m, "BaseObject"); 42 | 43 | pyClass.def_property_readonly("ref_count", &GetRefCount); 44 | pyClass.def_property_readonly("valid", &GetValid); 45 | pyClass.def_property_readonly("type", &GetBaseObjectType); 46 | 47 | // Meta 48 | pyClass.def("delete_meta", &alt::IBaseObject::DeleteMetaData, py::arg("key")); 49 | pyClass.def("has_meta", &alt::IBaseObject::HasMetaData, py::arg("key")); 50 | pyClass.def("set_meta", &SetMeta, py::arg("key"), py::arg("value")); 51 | pyClass.def("get_meta", &GetMeta, py::arg("key")); 52 | 53 | pyClass.def("destroy", &Destroy); 54 | } 55 | -------------------------------------------------------------------------------- /src/classes/base/checkpoint.cpp: -------------------------------------------------------------------------------- 1 | #include "classes/classes.hpp" 2 | #include "classes/types/enums.hpp" 3 | #include "classes/types/vector3.hpp" 4 | 5 | alt::ICheckpoint* CreateCheckpoint(uint8_t type, alt::Position pos, float radius, float height, alt::RGBA color) 6 | { 7 | auto checkpoint = alt::ICore::Instance().CreateCheckpoint(type, pos, radius, height, color); 8 | if (checkpoint) 9 | return checkpoint.Get(); 10 | throw std::runtime_error("Failed to create Checkpoint"); 11 | } 12 | 13 | CheckpointType GetCheckpointType(alt::ICheckpoint* _this) 14 | { 15 | return (CheckpointType)_this->GetCheckpointType(); 16 | } 17 | 18 | void RegisterCheckpointClass(const py::module_& m) 19 | { 20 | auto pyClass = py::class_, alt::IColShape>(m, "Checkpoint"); 21 | 22 | pyClass.def(py::init<>([](uint8_t type, double x, double y, double z, float radius, float height, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { 23 | return CreateCheckpoint(type, alt::Position(x, y, z), radius, height, alt::RGBA(r, g, b, a)); 24 | }), 25 | py::arg("type"), py::arg("x"), py::arg("y"), py::arg("z"), py::arg("radius"), py::arg("height"), py::arg("r"), py::arg("g"), py::arg("b"), py::arg("a")); 26 | 27 | pyClass.def(py::init<>([](uint8_t type, Vector3 pos, float radius, float height, alt::RGBA color) { 28 | return CreateCheckpoint(type, pos.ToAlt(), radius, height, color); 29 | }), 30 | py::arg("type"), py::arg("pos"), py::arg("radius"), py::arg("height"), py::arg("color")); 31 | 32 | // TODO Once setters start working change them to normal properties 33 | pyClass.def_property_readonly("checkpoint_type", &GetCheckpointType); 34 | pyClass.def_property_readonly("height", &alt::ICheckpoint::GetHeight); 35 | pyClass.def_property_readonly("radius", &alt::ICheckpoint::GetRadius); 36 | pyClass.def_property_readonly("color", &alt::ICheckpoint::GetColor); 37 | } 38 | -------------------------------------------------------------------------------- /src/events/meta.cpp: -------------------------------------------------------------------------------- 1 | #include "events.hpp" 2 | #include "utils.hpp" 3 | 4 | EventHandler syncedMetaChange(alt::CEvent::Type::SYNCED_META_CHANGE, [](const alt::CEvent* ev, py::list& args) { 5 | auto event = dynamic_cast(ev); 6 | args.append(Utils::GetBaseObject(event->GetTarget().Get())); 7 | args.append(event->GetKey()); 8 | args.append(Utils::MValueToValue(event->GetVal())); 9 | args.append(Utils::MValueToValue(event->GetOldVal())); 10 | }); 11 | 12 | EventHandler streamSyncedMetaChange(alt::CEvent::Type::STREAM_SYNCED_META_CHANGE, [](const alt::CEvent* ev, py::list& args) { 13 | auto event = dynamic_cast(ev); 14 | args.append(Utils::GetBaseObject(event->GetTarget().Get())); 15 | args.append(event->GetKey()); 16 | args.append(Utils::MValueToValue(event->GetVal())); 17 | args.append(Utils::MValueToValue(event->GetOldVal())); 18 | }); 19 | 20 | EventHandler globalMetaChange(alt::CEvent::Type::GLOBAL_META_CHANGE, [](const alt::CEvent* ev, py::list& args) { 21 | auto event = dynamic_cast(ev); 22 | args.append(event->GetKey()); 23 | args.append(Utils::MValueToValue(event->GetVal())); 24 | args.append(Utils::MValueToValue(event->GetOldVal())); 25 | }); 26 | 27 | EventHandler globalSyncedMetaChange(alt::CEvent::Type::GLOBAL_SYNCED_META_CHANGE, [](const alt::CEvent* ev, py::list& args) { 28 | auto event = dynamic_cast(ev); 29 | args.append(event->GetKey()); 30 | args.append(Utils::MValueToValue(event->GetVal())); 31 | args.append(Utils::MValueToValue(event->GetOldVal())); 32 | }); 33 | 34 | EventHandler localMetaChange(alt::CEvent::Type::LOCAL_SYNCED_META_CHANGE, [](const alt::CEvent* ev, py::list& args) { 35 | auto event = dynamic_cast(ev); 36 | args.append(event->GetTarget().Get()); 37 | args.append(event->GetKey()); 38 | args.append(Utils::MValueToValue(event->GetVal())); 39 | args.append(Utils::MValueToValue(event->GetOldVal())); 40 | }); 41 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | # Generated from CLion C/C++ Code Style settings 2 | BasedOnStyle: LLVM 3 | AccessModifierOffset: -3 4 | AlignAfterOpenBracket: Align 5 | AlignConsecutiveAssignments: None 6 | AlignOperands: DontAlign 7 | AllowAllArgumentsOnNextLine: false 8 | AllowAllConstructorInitializersOnNextLine: false 9 | AllowAllParametersOfDeclarationOnNextLine: false 10 | AllowShortBlocksOnASingleLine: Always 11 | AllowShortCaseLabelsOnASingleLine: false 12 | AllowShortFunctionsOnASingleLine: None 13 | AllowShortIfStatementsOnASingleLine: Always 14 | AllowShortLambdasOnASingleLine: All 15 | AllowShortLoopsOnASingleLine: true 16 | AlwaysBreakAfterReturnType: None 17 | AlwaysBreakTemplateDeclarations: Yes 18 | BreakBeforeBraces: Custom 19 | BraceWrapping: 20 | AfterCaseLabel: false 21 | AfterClass: true 22 | AfterControlStatement: Always 23 | AfterEnum: true 24 | AfterFunction: true 25 | AfterNamespace: true 26 | AfterUnion: true 27 | BeforeCatch: true 28 | BeforeElse: true 29 | IndentBraces: false 30 | SplitEmptyFunction: true 31 | SplitEmptyRecord: true 32 | BreakBeforeBinaryOperators: NonAssignment 33 | BreakBeforeTernaryOperators: true 34 | BreakConstructorInitializers: BeforeColon 35 | BreakInheritanceList: BeforeColon 36 | ColumnLimit: 0 37 | CompactNamespaces: false 38 | ContinuationIndentWidth: 4 39 | IndentCaseLabels: false 40 | IndentPPDirectives: None 41 | IndentWidth: 4 42 | KeepEmptyLinesAtTheStartOfBlocks: true 43 | MaxEmptyLinesToKeep: 1 44 | NamespaceIndentation: All 45 | ObjCSpaceAfterProperty: false 46 | ObjCSpaceBeforeProtocolList: false 47 | PointerAlignment: Left 48 | ReflowComments: false 49 | SpaceAfterCStyleCast: false 50 | SpaceAfterLogicalNot: false 51 | SpaceAfterTemplateKeyword: false 52 | SpaceBeforeAssignmentOperators: true 53 | SpaceBeforeCpp11BracedList: false 54 | SpaceBeforeCtorInitializerColon: true 55 | SpaceBeforeInheritanceColon: true 56 | SpaceBeforeParens: ControlStatements 57 | SpaceBeforeRangeBasedForLoopColon: true 58 | SpaceInEmptyParentheses: false 59 | SpacesBeforeTrailingComments: 0 60 | SpacesInAngles: false 61 | SpacesInCStyleCastParentheses: false 62 | SpacesInContainerLiterals: false 63 | SpacesInParentheses: false 64 | SpacesInSquareBrackets: false 65 | TabWidth: 4 66 | UseTab: ForContinuationAndIndentation 67 | -------------------------------------------------------------------------------- /src/PythonResource.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "interval.hpp" 4 | #include "main.hpp" 5 | 6 | class PythonRuntime; 7 | class PythonResource : public alt::IResource::Impl 8 | { 9 | PythonRuntime* runtime; 10 | alt::IResource* resource; 11 | PyThreadState* interpreter; 12 | 13 | std::map> localEvents; 14 | std::map> localCustomEvents; 15 | std::map> remoteEvents; 16 | 17 | int intervalId = 0; 18 | std::vector tasks; 19 | std::map timers; 20 | 21 | std::unordered_map> objects; 22 | 23 | public: 24 | PythonResource(PythonRuntime* runtime, alt::IResource* resource) 25 | : runtime(runtime), resource(resource) 26 | { 27 | } 28 | 29 | bool Start() override; 30 | 31 | bool Stop() override; 32 | 33 | bool OnEvent(const alt::CEvent* ev) override; 34 | 35 | bool IsObjectValid(const alt::Ref& object); 36 | 37 | void OnTick() override; 38 | 39 | void OnCreateBaseObject(alt::Ref object) override; 40 | 41 | void OnRemoveBaseObject(alt::Ref object) override; 42 | 43 | int AddTimer(double milliseconds, const py::function& func); 44 | 45 | void ClearTimer(int timerId); 46 | 47 | void AddTask(double milliseconds, const py::function& func); 48 | 49 | Interval* GetInterval(const py::function& func); 50 | 51 | void AddScriptEvent(const alt::CEvent::Type& type, const py::function& eventFunc); 52 | 53 | void AddServerEvent(const std::string& eventName, const py::function& eventFunc); 54 | 55 | void AddClientEvent(const std::string& eventName, const py::function& eventFunc); 56 | 57 | void HandleCustomEvent(const alt::CEvent* event); 58 | 59 | alt::IResource* GetResource() 60 | { 61 | return resource; 62 | } 63 | 64 | PyThreadState* GetInterpreter() 65 | { 66 | return interpreter; 67 | } 68 | 69 | class PythonFunction : public alt::IMValueFunction::Impl 70 | { 71 | private: 72 | py::function func; 73 | 74 | public: 75 | explicit PythonFunction(py::function func) 76 | : func(std::move(func)){}; 77 | 78 | alt::MValue Call(alt::MValueArgs args) const override; 79 | }; 80 | 81 | bool MakeClient(alt::IResource::CreationInfo* info, alt::Array files) override; 82 | }; 83 | -------------------------------------------------------------------------------- /src/classes/types/vector2.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "main.hpp" 3 | 4 | class Vector2 5 | { 6 | double GetAngle(const Vector2& other, const bool& degrees) const; 7 | 8 | public: 9 | double x, y; 10 | 11 | Vector2(double x, double y) 12 | : x(x), y(y) 13 | { 14 | } 15 | explicit Vector2(alt::Position position) 16 | : x{position[0]}, y{position[1]} 17 | { 18 | } 19 | explicit Vector2(alt::Rotation rotation) 20 | : x{rotation[0]}, y{rotation[1]} 21 | { 22 | } 23 | explicit Vector2(alt::Vector2f vector) 24 | : x{vector[0]}, y{vector[1]} 25 | { 26 | } 27 | explicit Vector2(const py::list& vectorList) 28 | : x{vectorList[0].cast()}, y{vectorList[1].cast()} 29 | { 30 | } 31 | 32 | py::dict ToDict(); 33 | py::list ToList(); 34 | 35 | alt::Position ToAlt() const; 36 | std::string ToString() const; 37 | 38 | Vector2 ToDegrees() const; 39 | Vector2 ToRadians() const; 40 | 41 | double Length() const; 42 | double Distance(Vector2& other) const; 43 | double DistanceSquared(Vector2& other) const; 44 | bool IsInRange(const Vector2& other, double range) const; 45 | Vector2 Lerp(Vector2 other, double ratio) const; 46 | 47 | Vector2 operator+(const Vector2& other) const; 48 | Vector2 operator+(double num) const; 49 | Vector2 operator+(const py::list& vectorList) const; 50 | 51 | Vector2 operator-(const Vector2& other) const; 52 | Vector2 operator-(double num) const; 53 | Vector2 operator-(const py::list& vectorList) const; 54 | Vector2 operator-() const; 55 | 56 | Vector2 operator/(const Vector2& other) const; 57 | Vector2 operator/(double num) const; 58 | Vector2 operator/(const py::list& vectorList) const; 59 | 60 | Vector2 operator*(const Vector2& other) const; 61 | Vector2 operator*(double num) const; 62 | Vector2 operator*(const py::list& vectorList) const; 63 | 64 | bool operator==(const Vector2& other) const; 65 | 66 | double Dot(const Vector2& other) const; 67 | double Dot(double num) const; 68 | double Dot(const py::list& vectorList) const; 69 | 70 | Vector2 Normalize() const; 71 | 72 | static Vector2 Zero(const py::object& _this); 73 | static Vector2 One(const py::object& _this); 74 | static Vector2 Up(const py::object& _this); 75 | static Vector2 Down(const py::object& _this); 76 | static Vector2 Left(const py::object& _this); 77 | static Vector2 Right(const py::object& _this); 78 | 79 | static Vector2 PositiveInfinity(const py::object& _this); 80 | static Vector2 NegativeInfinity(const py::object& _this); 81 | 82 | double AngleTo(const Vector2& other); 83 | double AngleToDegrees(const Vector2& other); 84 | }; 85 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build & Deploy 2 | on: 3 | workflow_dispatch: 4 | push: 5 | tags: 6 | - "dev/*.*-dev*" 7 | - "rc/*.*-rc*" 8 | - "release/*.*" 9 | 10 | jobs: 11 | create-release: 12 | name: Create GitHub Release 13 | runs-on: ubuntu-latest 14 | outputs: 15 | upload_url: ${{ steps.create_release.outputs.upload_url }} 16 | steps: 17 | - name: Create Release 18 | id: create_release 19 | uses: actions/create-release@v1 20 | env: 21 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 22 | with: 23 | tag_name: ${{ github.ref }} 24 | release_name: Release ${{ github.ref }} 25 | draft: false 26 | 27 | build-windows: 28 | name: Build Windows server module 29 | runs-on: windows-2019 30 | needs: [create-release] 31 | steps: 32 | - name: Checkout repo 33 | uses: actions/checkout@v2 34 | with: 35 | submodules: recursive 36 | lfs: true 37 | 38 | - name: Build 39 | shell: cmd 40 | run: build.bat 41 | 42 | - name: Zip artifacts 43 | run: | 44 | cd dist 45 | tar -acf ..\python-module-windows.zip * 46 | 47 | - name: Upload artifacts to release 48 | uses: actions/upload-release-asset@v1 49 | env: 50 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 51 | with: 52 | upload_url: ${{ needs.create-release.outputs.upload_url }} 53 | asset_path: python-module-windows.zip 54 | asset_name: python-module-windows.zip 55 | asset_content_type: application/octet-stream 56 | 57 | build-linux: 58 | name: Build Linux server module 59 | runs-on: ubuntu-20.04 60 | needs: [create-release] 61 | steps: 62 | - name: Checkout repo 63 | uses: actions/checkout@v2 64 | with: 65 | submodules: recursive 66 | lfs: true 67 | 68 | - name: Build 69 | run: | 70 | sudo chmod +x build.sh 71 | ./build.sh 72 | - name: Zip artifacts 73 | run: | 74 | cd dist 75 | zip -r ../python-module-linux . 76 | - name: Upload artifacts to release 77 | uses: actions/upload-release-asset@v1 78 | env: 79 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 80 | with: 81 | upload_url: ${{ needs.create-release.outputs.upload_url }} 82 | asset_path: python-module-linux.zip 83 | asset_name: python-module-linux.zip 84 | asset_content_type: application/octet-stream 85 | -------------------------------------------------------------------------------- /src/classes/types/resource.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "classes/classes.hpp" 4 | #include "utils.hpp" 5 | 6 | class Resource 7 | { 8 | private: 9 | alt::IResource* resource; 10 | 11 | public: 12 | Resource(alt::IResource* resource) 13 | : resource(resource) 14 | { 15 | } 16 | 17 | bool IsStarted() 18 | { 19 | return resource->IsStarted(); 20 | } 21 | 22 | std::string GetType() 23 | { 24 | return resource->GetType(); 25 | } 26 | 27 | std::string GetName() 28 | { 29 | return resource->GetName(); 30 | } 31 | 32 | std::string GetMain() 33 | { 34 | return resource->GetMain(); 35 | } 36 | 37 | std::string GetPath() 38 | { 39 | return resource->GetPath(); 40 | } 41 | 42 | py::dict GetConfig() 43 | { 44 | Config::Value::ValuePtr config = resource->GetConfig(); 45 | return Utils::ConfigNodeToValue(config); 46 | } 47 | 48 | py::dict GetExports() 49 | { 50 | return Utils::MValueToValue(resource->GetExports()); 51 | } 52 | 53 | py::list GetDependencies() 54 | { 55 | return Utils::ArrayToPyList(resource->GetDependencies()); 56 | } 57 | 58 | py::list GetDependants() 59 | { 60 | return Utils::ArrayToPyList(resource->GetDependants()); 61 | } 62 | 63 | py::list GetRequiredPermissions() 64 | { 65 | py::list list; 66 | auto permissions = resource->GetRequiredPermissions(); 67 | for (auto permission : permissions) 68 | list.append((int)permission); 69 | return list; 70 | } 71 | 72 | py::list GetOptionalPermissions() 73 | { 74 | py::list list; 75 | auto permissions = resource->GetOptionalPermissions(); 76 | for (auto permission : permissions) 77 | list.append((int)permission); 78 | return list; 79 | } 80 | 81 | static py::object GetByName(const std::string& resourceName) 82 | { 83 | auto resource = alt::ICore::Instance().GetResource(resourceName); 84 | if (resource != nullptr) 85 | return py::cast(Resource(resource)); 86 | return py::none(); 87 | } 88 | 89 | static py::list GetAllResources(const py::object& type) 90 | { 91 | py::list list; 92 | auto resources = alt::ICore::Instance().GetAllResources(); 93 | for (auto resource : resources) 94 | list.append(Resource(resource)); 95 | return list; 96 | } 97 | 98 | static Resource GetCurrent(const py::object& type) 99 | { 100 | PyThreadState* interp = PyThreadState_Get(); 101 | PythonResource* resource = PythonRuntime::GetInstance()->GetPythonResourceFromInterp(interp); 102 | return {resource->GetResource()}; 103 | } 104 | }; 105 | -------------------------------------------------------------------------------- /src/bindings/intervals.cpp: -------------------------------------------------------------------------------- 1 | #include "PythonRuntime.hpp" 2 | #include "bindings.hpp" 3 | #include "main.hpp" 4 | 5 | void CreateAttrsForTaskFunction(PythonResource* resource, const py::function& func) 6 | { 7 | Interval* task = resource->GetInterval(func); 8 | func.attr("stop") = py::cpp_function([task, func] { 9 | task->SetRunning(false); 10 | }); 11 | 12 | func.attr("start") = py::cpp_function([task, func] { 13 | task->SetRunning(true); 14 | }); 15 | 16 | func.attr("is_running") = py::cpp_function([task, func] { 17 | return task->IsRunning(); 18 | }); 19 | 20 | func.attr("change_interval") = py::cpp_function([task, func](double milliseconds = 0, double seconds = 0, double minutes = 0, double hours = 0) { 21 | if (seconds > 0) milliseconds += seconds * 1000; 22 | if (minutes > 0) milliseconds += minutes * 60 * 1000; 23 | if (hours > 0) milliseconds += hours * 60 * 60 * 1000; 24 | task->SetMilliseconds(milliseconds); 25 | }, 26 | py::arg("milliseconds") = 0, py::arg("seconds") = 0, py::arg("minutes") = 0, py::arg("hours") = 0); 27 | } 28 | 29 | py::cpp_function Task(double milliseconds = 0, double seconds = 0, double minutes = 0, double hours = 0) 30 | { 31 | if (seconds > 0) milliseconds += seconds * 1000; 32 | if (minutes > 0) milliseconds += minutes * 60 * 1000; 33 | if (hours > 0) milliseconds += hours * 60 * 60 * 1000; 34 | return [milliseconds](const py::function& func) { 35 | PyThreadState* interp = PyThreadState_Get(); 36 | PythonResource* resource = PythonRuntime::GetInstance()->GetPythonResourceFromInterp(interp); 37 | resource->AddTask(milliseconds, func); 38 | CreateAttrsForTaskFunction(resource, func); 39 | return func; 40 | }; 41 | } 42 | 43 | int Timer(const py::function& func, double milliseconds) 44 | { 45 | PyThreadState* interp = PyThreadState_Get(); 46 | PythonResource* resource = PythonRuntime::GetInstance()->GetPythonResourceFromInterp(interp); 47 | return resource->AddTimer(milliseconds, func); 48 | } 49 | 50 | void ClearTimer(int timerId) 51 | { 52 | PyThreadState* interp = PyThreadState_Get(); 53 | PythonResource* resource = PythonRuntime::GetInstance()->GetPythonResourceFromInterp(interp); 54 | resource->ClearTimer(timerId); 55 | } 56 | 57 | void RegisterIntervalFunctions(py::module_ m) 58 | { 59 | m.def("task", &Task, py::kw_only(), py::arg("milliseconds") = 0, py::arg("seconds") = 0, py::arg("minutes") = 0, py::arg("hours") = 0, "Decorator for creating task"); 60 | m.def("timer", &Timer, py::arg("func"), py::arg("milliseconds"), "Creates timer and returns it's id"); 61 | m.def("clear_timer", &ClearTimer, py::arg("timer_id"), "Clears the timer by it's id"); 62 | } 63 | -------------------------------------------------------------------------------- /src/PythonRuntime.cpp: -------------------------------------------------------------------------------- 1 | #include "PythonRuntime.hpp" 2 | #ifdef __linux__ 3 | #include 4 | #endif 5 | 6 | PythonRuntime* PythonRuntime::instance = nullptr; 7 | 8 | PythonRuntime::PythonRuntime() 9 | { 10 | #ifdef __linux__ 11 | // Without this, python doesn't recognize the shared lib, should be linux only issue 12 | std::string so = std::string("libpython") + std::to_string(PY_MAJOR_VERSION) + "." + std::to_string(PY_MINOR_VERSION) + ".so.1.0"; 13 | python = dlopen(so.c_str(), RTLD_NOW | RTLD_NOLOAD | RTLD_GLOBAL); 14 | #endif 15 | // For compatibility reasons disable site packages, if user wants to use 3rd party modules they should create venv 16 | Py_IsolatedFlag = 1; 17 | 18 | #ifdef _WIN32 19 | std::string pathSeparator = ";"; 20 | #else 21 | std::string pathSeparator = ":"; 22 | #endif 23 | std::string basePath = alt::ICore::Instance().GetRootDirectory() + SEPARATOR + "modules" + SEPARATOR + "python-module" + SEPARATOR + "python"; 24 | std::string path = basePath + pathSeparator + (basePath + SEPARATOR + "libs.zip"); 25 | 26 | // Venv should get recognized automatically, but if it doesn't, here is a config option for it 27 | alt::config::Node venv = alt::ICore::Instance().GetServerConfig()["python-venv"]; 28 | if (venv) 29 | path.append(pathSeparator + alt::ICore::Instance().GetRootDirectory() + SEPARATOR + venv.ToString()); 30 | 31 | Py_SetPath(std::wstring(path.begin(), path.end()).c_str()); 32 | py::initialize_interpreter(false); 33 | py::module_::import("alt"); 34 | mainInterpreter = PyThreadState_Get(); 35 | instance = this; 36 | } 37 | 38 | PythonResource* PythonRuntime::GetPythonResourceFromInterp(PyThreadState* interp) 39 | { 40 | for (PythonResource* resource : resources) 41 | if (resource->GetInterpreter() == interp) 42 | return resource; 43 | if (interp->interp == PyInterpreterState_Main()) 44 | alt::ICore::Instance().LogError("Main Interpreter Passed"); 45 | return nullptr; 46 | } 47 | 48 | alt::IResource::Impl* PythonRuntime::CreateImpl(alt::IResource* impl) 49 | { 50 | auto* resource = new PythonResource(this, impl); 51 | resources.push_back(resource); 52 | return resource; 53 | } 54 | 55 | void PythonRuntime::DestroyImpl(alt::IResource::Impl* impl) 56 | { 57 | auto* resource = dynamic_cast(impl); 58 | for (int i{}; i < resources.size(); i++) 59 | { 60 | if (resources[i]->GetResource()->GetName() == resource->GetResource()->GetName()) 61 | { 62 | resources.erase(resources.begin() + i); 63 | break; 64 | } 65 | } 66 | delete resource; 67 | } 68 | 69 | void PythonRuntime::OnDispose() 70 | { 71 | PyThreadState_Swap(mainInterpreter); 72 | py::finalize_interpreter(); 73 | #ifdef __linux__ 74 | dlclose(python); 75 | #endif 76 | } 77 | -------------------------------------------------------------------------------- /src/classes/types/vector3.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "main.hpp" 3 | 4 | class Vector3 5 | { 6 | double GetAngle(const Vector3& other, const bool& boolean) const; 7 | 8 | public: 9 | double x, y, z; 10 | 11 | Vector3(double x, double y, double z) 12 | : x(x), y(y), z(z) 13 | { 14 | } 15 | explicit Vector3(alt::Position position) 16 | : x{position[0]}, y{position[1]}, z{position[2]} 17 | { 18 | } 19 | explicit Vector3(alt::Rotation rotation) 20 | : x{rotation[0]}, y{rotation[1]}, z{rotation[2]} 21 | { 22 | } 23 | explicit Vector3(alt::Vector3f vector) 24 | : x{vector[0]}, y{vector[1]}, z{vector[2]} 25 | { 26 | } 27 | explicit Vector3(const py::list& vectorList) 28 | : x{vectorList[0].cast()}, y{vectorList[1].cast()}, z{vectorList[2].cast()} 29 | { 30 | } 31 | 32 | py::dict ToDict(); 33 | py::list ToList(); 34 | 35 | alt::Position ToAlt() const; 36 | std::string ToString() const; 37 | 38 | Vector3 ToDegrees() const; 39 | Vector3 ToRadians() const; 40 | 41 | double Length() const; 42 | double Distance(Vector3& other) const; 43 | double DistanceSquared(Vector3& other) const; 44 | bool IsInRange(const Vector3& other, double range) const; 45 | Vector3 Lerp(Vector3 other, double ratio) const; 46 | 47 | Vector3 operator+(const Vector3& other) const; 48 | Vector3 operator+(double num) const; 49 | Vector3 operator+(const py::list& vectorList) const; 50 | 51 | Vector3 operator-(const Vector3& other) const; 52 | Vector3 operator-(double num) const; 53 | Vector3 operator-(const py::list& vectorList) const; 54 | Vector3 operator-() const; 55 | 56 | Vector3 operator/(const Vector3& other) const; 57 | Vector3 operator/(double num) const; 58 | Vector3 operator/(const py::list& vectorList) const; 59 | 60 | Vector3 operator*(const Vector3& other) const; 61 | Vector3 operator*(double num) const; 62 | Vector3 operator*(const py::list& vectorList) const; 63 | 64 | bool operator==(const Vector3& other) const; 65 | 66 | Vector3 Cross(const Vector3& other) const; 67 | Vector3 Cross(double num) const; 68 | Vector3 Cross(const py::list& vectorList) const; 69 | 70 | double Dot(const Vector3& other) const; 71 | double Dot(double num) const; 72 | double Dot(const py::list& vectorList) const; 73 | 74 | Vector3 Normalize() const; 75 | 76 | static Vector3 Zero(const py::object& _this); 77 | static Vector3 One(const py::object& _this); 78 | static Vector3 Up(const py::object& _this); 79 | static Vector3 Down(const py::object& _this); 80 | static Vector3 Left(const py::object& _this); 81 | static Vector3 Right(const py::object& _this); 82 | static Vector3 Back(const py::object& _this); 83 | static Vector3 Forward(const py::object& _this); 84 | 85 | static Vector3 PositiveInfinity(const py::object& _this); 86 | static Vector3 NegativeInfinity(const py::object& _this); 87 | 88 | double AngleTo(const Vector3& other); 89 | double AngleToDegrees(const Vector3& other); 90 | }; 91 | -------------------------------------------------------------------------------- /docs/articles/index.md: -------------------------------------------------------------------------------- 1 | # alt:V Python Module 2 | 3 |
4 | ![Logo](https://user-images.githubusercontent.com/40175773/162998616-a79410f7-5053-431d-afe8-c68b11a48c32.png) 5 |
alt:V Python Module, fast and simple Python alt:V implementation
6 |
7 | --- 8 | alt:V Python Module adds server-side language support for Python 9 | 10 | By installing Python Module you will be able to fully use alt:V server-side API from your Python code 11 | 12 | This documentation only explains the Python module itself and assumes you are familiar with alt:V and how to use it. 13 | 14 | --- 15 | 16 | ## Let's create your first alt:V Python resource 17 | 18 | ### Requirements 19 | 20 | - Already working alt:V server 21 | - Basic Python knowledge 22 | - Basic knowledge of command prompts 23 | - An IDE or any other code editor 24 | 25 | ### Installation 26 | 27 | Installation of the Python Module is really easy 28 | 29 | - [Download](https://github.com/Marvisak/altv-python-module/releases/latest) the latest version of the module for your desired platform 30 | - Create `modules/python-module` folder in your alt:V server folder 31 | - Move all the files from the zip file you downloaded into the folder you created 32 | - Add into your `server.cfg` modules column "python-module" 33 | 34 | ```yaml 35 | modules: ['python-module'] 36 | ``` 37 | 38 | Now start the server, if you see this message in the console 39 | 40 | ``` 41 | Python module successfully loaded 42 | ``` 43 | 44 | Then Python module was installed successfully, and you are good to go 45 | 46 | ### Creating a resource 47 | 48 | Creating a resource is identical to creating JavaScript resource 49 | 50 | Let's start by creating required files of our resource 51 | 52 | For this tutorial we are going to call our resource `python` 53 | 54 | ``` 55 | resources/python 56 | 57 | resources/python/resource.cfg 58 | 59 | resources/python/main.py 60 | ``` 61 | 62 | ??? note 63 | Python is currently only supported on server-side, so in this documentation we are only going to create server files, your gamemode will probably have some client files in order to function 64 | 65 | There will be few places where we will need to have some client code, in that case we are going to use JavaScript 66 | 67 | ```yaml title="resource.cfg" 68 | type: py 69 | main: main.py 70 | ``` 71 | 72 | ```py title="main.py" 73 | import alt 74 | 75 | alt.log("My First Python Resource Started!") 76 | ``` 77 | 78 | Now only thing left to do is add the resource into your `server.cfg` 79 | 80 | ```yaml 81 | resources: ['python'] 82 | ``` 83 | 84 | And now when you start your server you should see this message in the console 85 | 86 | ``` 87 | My First Python Resource Started! 88 | ``` 89 | 90 | Congratulations, you have just created your first alt:V Python Resource 91 | 92 | ## What's next 93 | 94 | In the next few articles you are going to learn how the Python module works and how can you use it 95 | 96 | After you read through this documentation you should have solid understanding of how the module works and how to use it. 97 | -------------------------------------------------------------------------------- /docs/articles/intro.md: -------------------------------------------------------------------------------- 1 | # Intro 2 | 3 | Let's start by breaking down the code we wrote previously 4 | 5 | ```py 6 | import alt 7 | 8 | alt.log("My First Python Resource Started!") 9 | ``` 10 | 11 | This is a very simple code, but it's great for explaining how does the module work 12 | 13 | ## Import alt module 14 | 15 | ```py hl_lines="1" 16 | import alt 17 | 18 | alt.log("My First Python Resource Started!") 19 | ``` 20 | 21 | The alt module is your way to communicate with alt:V API 22 | 23 | It is embedded right into the module, so you don't have to install anything. 24 | 25 | If you don't need alt:V API in your file you don't have to import it, but most of the thing module does are only usable through this import, so without it, you are going to write plain Python. 26 | 27 | Your IDE won't show you any typehints for the alt module, if you want to have them, you can find info about them and much more at [Additional Information](additional-information.md) article 28 | 29 | ## Log into the console 30 | 31 | ```py hl_lines="3" 32 | import alt 33 | 34 | alt.log("My First Python Resource Started!") 35 | ``` 36 | 37 | This line calls the log function 38 | 39 | The log function behaves exactly like print function, it even has `sep` parameter which changes the way arguments passed to it are separated 40 | 41 | The difference between this function and normal `#!python print()` is that this function uses alt:V API so the output looks different 42 | 43 | ```py 44 | print("My First Python Resource Started!") 45 | ``` 46 | 47 | Outputs simply: `My First Python Resource Started!` 48 | 49 | While our original code outputs: `[XX:XX:XX] My First Python Resource Started!` 50 | 51 | ??? note 52 | In the rest of articles when we will use this function, the timestamp is going to be removed 53 | 54 | --- 55 | 56 | We have 3 kinds of log functions 57 | 58 | - `alt.log()` 59 | - `alt.log_error()` 60 | - `alt.log_warning()` 61 | 62 | Each of these functions works exactly the same, only the output looks differently. 63 | 64 | --- 65 | 66 | You can pass any amount of arguments you want, all of them are going to be parsed to string and separated by space. 67 | 68 | ```py 69 | import alt 70 | 71 | alt.log("Hello", 50, [20, 30, 50]) 72 | ``` 73 | 74 | This code outputs: `Hello 50 [20, 30, 50]` 75 | 76 | If you want to edit the separator of the arguments you pass in, you should use the `sep` argument. 77 | 78 | ```py 79 | import alt 80 | 81 | alt.log("Hello", 50, [], sep=",") 82 | ``` 83 | 84 | This code outputs: `Hello,50,[20, 30, 50]` 85 | 86 | --- 87 | 88 | You can also color the text you are outputting if you are using the `alt.log()` function 89 | 90 | ```py 91 | import alt 92 | 93 | alt.log("~r~This ~g~is ~b~colorful") 94 | ``` 95 | 96 | This code outputs: This is colorful 97 | 98 | --- 99 | 100 | Now you should have basic understanding of how alt module works 101 | 102 | You should also know everything about how log functions work and how can you use them in your code 103 | 104 | In the next article we are going to learn about events and how to use them -------------------------------------------------------------------------------- /src/bindings/events.cpp: -------------------------------------------------------------------------------- 1 | #include "classes/types/enums.hpp" 2 | #include "main.hpp" 3 | #include "utils.hpp" 4 | 5 | py::cpp_function ScriptEvent(Event event) 6 | { 7 | return [event](const py::function& func) { 8 | PyThreadState* interp = PyThreadState_Get(); 9 | PythonResource* resource = PythonRuntime::GetInstance()->GetPythonResourceFromInterp(interp); 10 | auto ev = static_cast(event); 11 | 12 | if (!alt::ICore::Instance().IsEventEnabled(ev)) 13 | alt::ICore::Instance().ToggleEvent(ev, true); 14 | 15 | auto castEvent = static_cast(event); 16 | resource->AddScriptEvent(castEvent, func); 17 | }; 18 | } 19 | 20 | py::cpp_function ServerEvent(const std::string& eventName) 21 | { 22 | return [eventName](const py::function& func) { 23 | PyThreadState* interp = PyThreadState_Get(); 24 | PythonResource* resource = PythonRuntime::GetInstance()->GetPythonResourceFromInterp(interp); 25 | resource->AddServerEvent(eventName, func); 26 | }; 27 | } 28 | 29 | py::cpp_function ClientEvent(const std::string& eventName) 30 | { 31 | return [eventName](const py::function& func) { 32 | PyThreadState* interp = PyThreadState_Get(); 33 | PythonResource* resource = PythonRuntime::GetInstance()->GetPythonResourceFromInterp(interp); 34 | resource->AddClientEvent(eventName, func); 35 | }; 36 | } 37 | 38 | void Emit(const std::string& eventName, const py::args& args) 39 | { 40 | alt::MValueArgs eventArgs; 41 | for (const py::handle& arg : *args) 42 | eventArgs.Push(Utils::ValueToMValue(arg.cast())); 43 | 44 | alt::ICore::Instance().TriggerLocalEvent(eventName, eventArgs); 45 | } 46 | 47 | void EmitClient(alt::IPlayer* player, const std::string& eventName, const py::args& args) 48 | { 49 | alt::MValueArgs eventArgs; 50 | for (const py::handle& arg : *args) 51 | eventArgs.Push(Utils::ValueToMValue(arg.cast())); 52 | alt::ICore::Instance().TriggerClientEvent(player, eventName, eventArgs); 53 | } 54 | 55 | void EmitClient(const std::vector& players, const std::string& eventName, const py::args& args) 56 | { 57 | alt::MValueArgs eventArgs; 58 | for (const py::handle& arg : *args) 59 | eventArgs.Push(Utils::ValueToMValue(arg.cast())); 60 | for (alt::IPlayer* player : players) 61 | alt::ICore::Instance().TriggerClientEvent(player, eventName, eventArgs); 62 | } 63 | 64 | void EmitAllClients(const std::string& eventName, const py::args& args) 65 | { 66 | alt::MValueArgs eventArgs; 67 | for (const py::handle& arg : *args) 68 | eventArgs.Push(Utils::ValueToMValue(arg.cast())); 69 | alt::ICore::Instance().TriggerClientEventForAll(eventName, eventArgs); 70 | } 71 | 72 | void RegisterEventFunctions(py::module_ m) 73 | { 74 | m.def("script_event", &ScriptEvent, py::arg("event"), "Decorator for registering event listener"); 75 | m.def("server_event", &ServerEvent, py::arg("event"), "Decorator for registering custom event listener"); 76 | m.def("client_event", &ClientEvent, py::arg("event"), "Decorator for registering client event listener"); 77 | m.def("emit", &Emit, py::arg("event_name"), "Emits event"); 78 | m.def("emit_client", py::overload_cast(&EmitClient), py::arg("player"), py::arg("event_name"), "Emits client event"); 79 | m.def("emit_client", py::overload_cast&, const std::string&, const py::args&>(&EmitClient), py::arg("players"), py::arg("event_name"), "Emits client event to all clients in the list"); 80 | m.def("emit_all_clients", &EmitAllClients, py::arg("event_name"), "Emits event to all clients"); 81 | } 82 | -------------------------------------------------------------------------------- /docs/articles/tasks.md: -------------------------------------------------------------------------------- 1 | # Tasks and Timers 2 | 3 | Sometimes you want to call functions in loop or after certain amount of time 4 | 5 | You can't use tools provided by Python because they will freeze your whole code execution 6 | 7 | Thankfully Python module provides you with tools which can help you solve this problem 8 | 9 | ## Tasks 10 | 11 | Tasks or as some call it intervals call your code every X milliseconds 12 | 13 | ```py 14 | import alt 15 | 16 | @alt.task(seconds=1) 17 | def task() -> None: 18 | alt.log("I am called every second!") 19 | ``` 20 | 21 | After you run this code you should see something like this: 22 | ``` 23 | [XX:XX:01] I am called every second! 24 | [XX:XX:02] I am called every second! 25 | [XX:XX:03] I am called every second! 26 | [XX:XX:04] I am called every second! 27 | ``` 28 | 29 | As you can see tasks are very similar to events, we are also using decorator 30 | 31 | The decorator `alt.task()` has 4 keyword arguments: `milliseconds`, `seconds`, `minutes`, `hours`, all of them are floats 32 | 33 | All the arguments you enter will get converted into milliseconds 34 | 35 | If you don't enter any arguments the function will get executed every server tick 36 | 37 | You can also combine the arguments to create something like this 38 | 39 | ```py 40 | import alt 41 | 42 | @alt.task(minutes=1, seconds=30) 43 | def task() -> None: 44 | alt.log("I am called every minute and a half!") 45 | ``` 46 | 47 | Which outputs this: 48 | ``` 49 | [XX:01:30] I am called every minute and a half! 50 | [XX:03:00] I am called every minute and a half! 51 | [XX:04:30] I am called every minute and a half! 52 | [XX:06:00] I am called every minute and a half! 53 | ``` 54 | 55 | The function you used the decorator on will then get 4 new functions 56 | 57 | - `func.stop()` Stops the task from executing 58 | - `func.start()` Starts the task if it was stopped previously 59 | - `func.is_running()` Returns `True` if the interval is running, otherwise `False` 60 | - `func.set_interval()` Changes the interval, takes the exact same arguments as the `alt.task()` decorator 61 | 62 | So you can create something like this: 63 | 64 | ```py 65 | import alt 66 | 67 | @alt.task() 68 | def task() -> None: 69 | alt.log("I am called only once!") 70 | task.stop() 71 | ``` 72 | 73 | Which outputs: 74 | ``` 75 | I am called only once! 76 | ``` 77 | 78 | ??? note 79 | You should never do something like this, if you need a code which should execute only once, use timers which are explained below 80 | 81 | 82 | ## Timers 83 | 84 | Timers call your code after X milliseconds, the difference between tasks and timers is that timers call your function only once 85 | 86 | ```py 87 | import alt 88 | 89 | def timer() -> None: 90 | alt.log("I am called after one second!") 91 | 92 | timer_id = alt.timer(timer, 1000) 93 | ``` 94 | 95 | Which outputs: 96 | ``` 97 | [XX:XX:01] I am called after one second! 98 | ``` 99 | 100 | The `alt.timer()` function takes 2 arguments, the first one is the function you want to add to the timer, and the second one is the amount of milliseconds after which the function should get called 101 | 102 | If you need the timer to stop so that the function doesn't execute, you can use the `alt.clear_timer()` function 103 | 104 | The function takes the number you got from the `alt.timer()` as an argument. 105 | 106 | ```py 107 | import alt 108 | 109 | def timer() -> None: 110 | alt.log("I am never called :(") 111 | 112 | timer_id = alt.timer(timer, 1000) 113 | 114 | alt.clear_timer(timer_id) 115 | ``` 116 | 117 | --- 118 | 119 | Now you should know everything about Tasks and Timers 120 | 121 | Next we are going to learn about vectors 122 | -------------------------------------------------------------------------------- /docs/articles/additional-information.md: -------------------------------------------------------------------------------- 1 | # Additional Information 2 | 3 | This article will be about some additional information you might need 4 | 5 | ## Installing 3rd party packages | Using venv 6 | 7 | You'll probably want to use some 3rd party package in your code. 8 | 9 | For compatibility reasons python module doesn't allow you to use your global environment, so you need to create virtual environment 10 | 11 | There are 2 ways how to use it with the module 12 | 13 | ### The easy way 14 | 15 | The easy way is the way you would normally create virtual environment 16 | 17 | There are many ways how to achieve this but for the sake of this tutorial I am going to use the standard python way 18 | 19 | ``` 20 | $ python -m venv env 21 | ``` 22 | 23 | Execute this command in your server root folder, and it should create an environment in a folder called env. 24 | 25 | Now just enter it, this example is for windows 26 | 27 | ``` 28 | $ env\Scripts\activate 29 | ``` 30 | 31 | Now just start the server, and it should load the virtual environment into the path 32 | 33 | If it doesn't which will probably happen if you are using Windows, use the second way 34 | 35 | ### The annoying way 36 | 37 | I am going to expect that you have created your virtual environment in the previous step 38 | 39 | Here you will need to find your site-packages folder 40 | 41 | On Windows this is: `env\Lib\site-packages` 42 | 43 | Now open your `server.cfg` and enter this field: 44 | ``` 45 | python-venv: env\Lib\site-packages 46 | ``` 47 | Of course replace the path with your own one, this path has to be relative to the server root folder. 48 | 49 | Now start your server, and you can now import any third party packages you install into the virtual environment 50 | 51 | ### Problems 52 | 53 | There might be a bit of a problem, as the module should always be running the newest version of Python, it's APIs might not be compatible with the APIs of the Python you have installed on your system. 54 | 55 | This might create a problem with packages written in C as effectively you are installing packages for a wrong version of Python, so if you find any problems. The only way how to fix them is probably installing the newest version of Python on your system. 56 | 57 | If any package doesn't work even with the newest version of Python create issue on GitHub. 58 | 59 | ## Autocompletion and stubs 60 | 61 | If you want autocompletion for your code, you need to download our stubs 62 | 63 | You can either install it into your global environment (not recommended) or into your virtual environment you created in the previous step (recommended) 64 | 65 | ``` 66 | $ pip install altv-stubs 67 | ``` 68 | 69 | This should install stubs of the module and your IDE should automatically detect that the stubs were installed and add autocompletion 70 | 71 | ## Async 72 | 73 | Currently, there is no implementation of Python async in the module, meaning that any code which requires the `await` keyword won't work 74 | 75 | I (the module developer) am not experienced enough with asynchronous Python to be able to implement it 76 | 77 | If you have the necessary knowledge on how to use Python async and can help implement it, contact me on discord `Marvis#5422` 78 | 79 | ## MyPy 80 | 81 | This is just a little recommendation from me. 82 | 83 | You've probably heard of TypeScript, the static JavaScript, what if I told you there is something similar like that for Python 84 | 85 | It's called MyPy and because unlike JavaScript Python already has typehints and other required stuff for static code it's a CLI application instead of whole other language 86 | 87 | You can find all the information about MyPy [on their website](https://mypy.readthedocs.io/en/stable/) 88 | 89 | You will need the stubs installed in order for MyPy to check your code 90 | 91 | All the code in this documentation should be compatible with MyPy 92 | -------------------------------------------------------------------------------- /src/classes/base/colshape.cpp: -------------------------------------------------------------------------------- 1 | #include "classes/classes.hpp" 2 | #include "classes/types/enums.hpp" 3 | #include "classes/types/vector2.hpp" 4 | #include "classes/types/vector3.hpp" 5 | 6 | ColShapeType GetColShapeType(alt::IColShape* _this) 7 | { 8 | return (ColShapeType)_this->GetColshapeType(); 9 | } 10 | 11 | bool IsPointIn(alt::IColShape* _this, Vector3 pos) 12 | { 13 | return _this->IsPointIn(pos.ToAlt()); 14 | } 15 | 16 | void RegisterColShapeClass(const py::module_& m) 17 | { 18 | auto pyClass = py::class_>(m, "ColShape", py::multiple_inheritance()); 19 | 20 | pyClass.def_static( 21 | "circle", [](double x, double y, float radius) { 22 | return alt::ICore::Instance().CreateColShapeCircle({x, y, 0}, radius); 23 | }, 24 | py::arg("x"), py::arg("y"), py::arg("radius")); 25 | 26 | pyClass.def_static( 27 | "circle", [](Vector2 pos, float radius) { 28 | return alt::ICore::Instance().CreateColShapeCircle(pos.ToAlt(), radius); 29 | }, 30 | py::arg("pos"), py::arg("radius")); 31 | 32 | pyClass.def_static( 33 | "cylinder", [](double x, double y, double z, float radius, float height) { 34 | return alt::ICore::Instance().CreateColShapeCylinder({x, y, z}, radius, height); 35 | }, 36 | py::arg("x"), py::arg("y"), py::arg("z"), py::arg("radius"), py::arg("height")); 37 | 38 | pyClass.def_static( 39 | "cylinder", [](Vector3 pos, float radius, float height) { 40 | return alt::ICore::Instance().CreateColShapeCylinder(pos.ToAlt(), radius, height); 41 | }, 42 | py::arg("pos"), py::arg("radius"), py::arg("height")); 43 | 44 | pyClass.def_static( 45 | "sphere", [](double x, double y, double z, float radius) { 46 | return alt::ICore::Instance().CreateColShapeSphere({x, y, z}, radius); 47 | }, 48 | py::arg("x"), py::arg("y"), py::arg("z"), py::arg("radius")); 49 | 50 | pyClass.def_static( 51 | "sphere", [](Vector3 pos, float radius) { 52 | return alt::ICore::Instance().CreateColShapeSphere(pos.ToAlt(), radius); 53 | }, 54 | py::arg("pos"), py::arg("radius")); 55 | 56 | pyClass.def_static( 57 | "cube", [](double x1, double y1, double z1, double x2, double y2, double z2) { 58 | return alt::ICore::Instance().CreateColShapeCube({x1, y1, z1}, {x2, y2, z2}); 59 | }, 60 | py::arg("x1"), py::arg("y1"), py::arg("z1"), py::arg("x2"), py::arg("y2"), py::arg("z2")); 61 | 62 | pyClass.def_static( 63 | "cube", [](Vector3 pos1, Vector3 pos2) { 64 | return alt::ICore::Instance().CreateColShapeCube(pos1.ToAlt(), pos2.ToAlt()); 65 | }, 66 | py::arg("pos1"), py::arg("pos2")); 67 | 68 | pyClass.def_static( 69 | "rectangle", [](float x1, float y1, float x2, float y2) { 70 | return alt::ICore::Instance().CreateColShapeRectangle(x1, y1, x2, y2, 0); 71 | }, 72 | py::arg("x1"), py::arg("y1"), py::arg("x2"), py::arg("y2")); 73 | 74 | pyClass.def_static( 75 | "rectangle", [](Vector2 pos1, Vector2 pos2) { 76 | return alt::ICore::Instance().CreateColShapeRectangle((float)pos1.x, (float)pos1.y, (float)pos2.x, (float)pos2.y, 0); 77 | }, 78 | py::arg("pos1"), py::arg("pos2")); 79 | 80 | pyClass.def_static( 81 | "polygon", [](float minZ, float maxZ, const std::vector& points) { 82 | std::vector parsed_points; 83 | for (auto point : points) 84 | parsed_points.emplace_back(point.ToAlt()); 85 | return alt::ICore::Instance().CreateColShapePolygon(minZ, maxZ, parsed_points); 86 | }, 87 | py::arg("min_z"), py::arg("max_z"), py::arg("points")); 88 | 89 | pyClass.def_property_readonly("colshape_type", &GetColShapeType); 90 | pyClass.def_property("players_only", &alt::IColShape::IsPlayersOnly, &alt::IColShape::SetPlayersOnly); 91 | 92 | pyClass.def("is_entity_in", &alt::IColShape::IsEntityIn, py::arg("entity")); 93 | pyClass.def("is_entity_in", &alt::IColShape::IsEntityIdIn, py::arg("entity_id")); 94 | pyClass.def("is_point_in", &IsPointIn, py::arg("pos")); 95 | } 96 | -------------------------------------------------------------------------------- /src/events/Main.cpp: -------------------------------------------------------------------------------- 1 | #include "classes/types/enums.hpp" 2 | #include "classes/types/vector3.hpp" 3 | #include "events.hpp" 4 | #include "utils.hpp" 5 | 6 | EventHandler resourceStart(alt::CEvent::Type::RESOURCE_START, [](const alt::CEvent* ev, py::list& args) { 7 | auto event = dynamic_cast(ev); 8 | args.append(event->GetResource()->GetName()); 9 | }); 10 | 11 | EventHandler resourceStop(alt::CEvent::Type::RESOURCE_STOP, [](const alt::CEvent* ev, py::list& args) { 12 | auto event = dynamic_cast(ev); 13 | args.append(event->GetResource()->GetName()); 14 | }); 15 | 16 | EventHandler resourceError(alt::CEvent::Type::RESOURCE_ERROR, [](const alt::CEvent* ev, py::list& args) { 17 | auto event = dynamic_cast(ev); 18 | args.append(event->GetResource()->GetName()); 19 | }); 20 | 21 | EventHandler fire(alt::CEvent::Type::FIRE_EVENT, [](const alt::CEvent* ev, py::list& args) { 22 | auto event = dynamic_cast(ev); 23 | args.append(event->GetSource().Get()); 24 | py::list fireInfos; 25 | for (alt::CFireEvent::FireInfo fireInfo : event->GetFires()) 26 | { 27 | py::dict fireInfoDict; 28 | fireInfoDict["pos"] = Vector3(fireInfo.position); 29 | fireInfoDict["weapon"] = fireInfo.weaponHash; 30 | fireInfos.append(fireInfoDict); 31 | } 32 | args.append(fireInfos); 33 | }); 34 | 35 | EventHandler explosion(alt::CEvent::Type::EXPLOSION_EVENT, [](const alt::CEvent* ev, py::list& args) { 36 | auto event = dynamic_cast(ev); 37 | args.append(event->GetSource().Get()); 38 | args.append(static_cast(event->GetExplosionType())); 39 | args.append(Vector3(event->GetPosition())); 40 | args.append(event->GetExplosionFX()); 41 | args.append(Utils::GetBaseObject(event->GetTarget())); 42 | }); 43 | 44 | EventHandler startProjectile(alt::CEvent::Type::START_PROJECTILE_EVENT, [](const alt::CEvent* ev, py::list& args) { 45 | auto event = dynamic_cast(ev); 46 | args.append(event->GetSource().Get()); 47 | args.append(Vector3(event->GetStartPosition())); 48 | args.append(Vector3(event->GetDirection())); 49 | args.append(event->GetAmmoHash()); 50 | args.append(event->GetWeaponHash()); 51 | }); 52 | 53 | EventHandler weaponDamage(alt::CEvent::Type::WEAPON_DAMAGE_EVENT, [](const alt::CEvent* ev, py::list& args) { 54 | auto event = dynamic_cast(ev); 55 | args.append(event->GetSource().Get()); 56 | args.append(Utils::GetBaseObject(event->GetTarget())); 57 | args.append(event->GetWeaponHash()); 58 | args.append(event->GetDamageValue()); 59 | args.append(Vector3(event->GetShotOffset())); 60 | args.append(static_cast(event->GetBodyPart())); 61 | }); 62 | 63 | EventHandler netOwnerChange(alt::CEvent::Type::NETOWNER_CHANGE, [](const alt::CEvent* ev, py::list& args) { 64 | auto event = dynamic_cast(ev); 65 | args.append(Utils::GetBaseObject(event->GetTarget())); 66 | args.append(event->GetNewOwner().Get()); 67 | args.append(event->GetOldOwner().Get()); 68 | }); 69 | 70 | EventHandler removeEntity(alt::CEvent::Type::REMOVE_ENTITY_EVENT, [](const alt::CEvent* ev, py::list& args) { 71 | auto event = dynamic_cast(ev); 72 | args.append(Utils::GetBaseObject(event->GetEntity())); 73 | }); 74 | 75 | EventHandler consoleCommand(alt::CEvent::Type::CONSOLE_COMMAND_EVENT, [](const alt::CEvent* ev, py::list& args) { 76 | auto event = dynamic_cast(ev); 77 | args.append(event->GetName()); 78 | py::list commandArgs; 79 | for (const auto& arg : event->GetArgs()) 80 | commandArgs.append(arg); 81 | args.append(commandArgs); 82 | }); 83 | 84 | EventHandler colShapeEvent(alt::CEvent::Type::COLSHAPE_EVENT, [](const alt::CEvent* ev, py::list& args) { 85 | auto event = dynamic_cast(ev); 86 | args.append(Utils::GetBaseObject(event->GetTarget().Get())); 87 | args.append(Utils::GetBaseObject(event->GetEntity().Get())); 88 | args.append(event->GetState()); 89 | }); 90 | 91 | EventHandler serverStarted(alt::CEvent::Type::SERVER_STARTED); 92 | -------------------------------------------------------------------------------- /docs/alt/events.py: -------------------------------------------------------------------------------- 1 | from . import * 2 | 3 | 4 | def ServerStarted() -> None: 5 | ... 6 | 7 | 8 | def PlayerConnect(player: Player) -> None: 9 | ... 10 | 11 | 12 | def PlayerBeforeConnect(connection_info: ConnectionInfo) -> str | bool | None: 13 | ... 14 | 15 | 16 | def PlayerDisconnect(player: Player, reason: str) -> None: 17 | ... 18 | 19 | 20 | def ConnectionQueueAdd(connection_info: ConnectionInfo) -> None: 21 | ... 22 | 23 | 24 | def ConnectionQueueRemove(connection_info: ConnectionInfo) -> None: 25 | ... 26 | 27 | 28 | def ResourceStart(resource_name: str) -> None: 29 | ... 30 | 31 | 32 | def ResourceStop(resource_name: str) -> None: 33 | ... 34 | 35 | 36 | def ResourceError(resource_name: str) -> None: 37 | ... 38 | 39 | 40 | def SyncedMetaChange(entity: Entity, key: str, value: str, old_value: str) -> None: 41 | ... 42 | 43 | 44 | def StreamSyncedMetaChange( 45 | entity: Entity, key: str, value: str, old_value: str 46 | ) -> None: 47 | ... 48 | 49 | 50 | def GlobalMetaChange(key: str, value: str, old_value: str) -> None: 51 | ... 52 | 53 | 54 | def GlobalSyncedMetaChange(key: str, value: str, old_value: str) -> None: 55 | ... 56 | 57 | 58 | def LocalMetaChange(player: Player, key: str, value: str, old_value: str) -> None: 59 | ... 60 | 61 | 62 | def PlayerDamage( 63 | victim: Player, 64 | attacker: Entity, 65 | health_damage: int, 66 | armour_damage: int, 67 | weapon_hash: int, 68 | ) -> None: 69 | ... 70 | 71 | 72 | def PlayerDeath(victim: Player, killer: Entity, weapon_hash: int) -> None: 73 | ... 74 | 75 | 76 | def Fire(player: Player, fires: FireInfo) -> bool | None: 77 | ... 78 | 79 | 80 | def Explosion( 81 | source: Player, type: ExplosionType, pos: Vector3, fx: int, target: Entity 82 | ) -> bool | None: 83 | ... 84 | 85 | 86 | def StartProjectile( 87 | player: Player, pos: Vector3, dir: Vector3, ammo_hash: int, weapon_hash: int 88 | ) -> bool | None: 89 | ... 90 | 91 | 92 | def WeaponDamage( 93 | source: Player, 94 | target: Entity, 95 | weapon_hash: int, 96 | damage: int, 97 | offset: Vector3, 98 | body_part: BodyPart, 99 | ) -> bool | None: 100 | ... 101 | 102 | 103 | def VehicleDestroy(vehicle: Vehicle) -> None: 104 | ... 105 | 106 | 107 | def VehicleDamage( 108 | vehicle: Vehicle, 109 | attacker: Entity, 110 | body_health_damage: int, 111 | additional_body_health_damage: int, 112 | engine_health_damage: int, 113 | petrol_tank_damage: int, 114 | weapon: int, 115 | ) -> None: 116 | ... 117 | 118 | 119 | def ColShape(colshape: ColShape, entity: Entity, state: bool) -> None: 120 | ... 121 | 122 | 123 | def PlayerEnterVehicle(player: Player, vehicle: Vehicle, seat: int) -> None: 124 | ... 125 | 126 | 127 | def PlayerEnteringVehicle(player: Player, vehicle: Vehicle, seat: int) -> None: 128 | ... 129 | 130 | 131 | def PlayerLeftVehicle(player: Player, vehicle: Vehicle, seat: int) -> None: 132 | ... 133 | 134 | 135 | def PlayerChangeVehicleSeat( 136 | player: Player, vehicle: Vehicle, old_seat: int, seat: int 137 | ) -> None: 138 | ... 139 | 140 | 141 | def PlayerWeaponChange(player: Player, old_weapon: int, weapon: int) -> bool | None: 142 | ... 143 | 144 | 145 | def PlayerRequestControl(player: Player, target: Entity) -> bool | None: 146 | ... 147 | 148 | 149 | def VehicleAttach(vehicle: Vehicle, attached_vehicle: Vehicle) -> None: 150 | ... 151 | 152 | 153 | def VehicleDetach(vehicle: Vehicle, detached_vehicle: Vehicle) -> None: 154 | ... 155 | 156 | 157 | def NetOwnerChange(entity: Entity, owner: Player, old_owner: Player) -> None: 158 | ... 159 | 160 | 161 | def RemoveEntity(object: Entity) -> None: 162 | ... 163 | 164 | 165 | def ConsoleCommand(name: str, args: List[str]) -> None: 166 | ... 167 | 168 | 169 | def PlayerAnimationChange( 170 | player: Player, 171 | old_anim_dict: int, 172 | new_anim_dict: int, 173 | old_anim_name: int, 174 | new_anim_name: int, 175 | ) -> None: 176 | ... 177 | 178 | 179 | def PlayerInteriorChange(player: Player, new_interior: int, old_interior: int) -> None: 180 | ... 181 | 182 | 183 | def PlayerConnectDenied( 184 | player: Player, 185 | name: str, 186 | ip: str, 187 | password_hash: int, 188 | is_debug: bool, 189 | branch: str, 190 | version: int, 191 | cdn_url: str, 192 | discord_id: int, 193 | ) -> None: 194 | ... 195 | -------------------------------------------------------------------------------- /src/classes/base/entity.cpp: -------------------------------------------------------------------------------- 1 | #include "classes/classes.hpp" 2 | #include "classes/types/vector3.hpp" 3 | #include "utils.hpp" 4 | 5 | py::list GetAllEntities(const py::object& type) 6 | { 7 | py::list list; 8 | auto array = alt::ICore::Instance().GetEntities(); 9 | for (const auto& entity : array) 10 | list.append(Utils::GetBaseObject(entity)); 11 | return list; 12 | } 13 | 14 | py::object GetEntityById(uint16_t id) 15 | { 16 | return Utils::GetBaseObject(alt::ICore::Instance().GetEntityByID(id)); 17 | } 18 | 19 | Vector3 GetRotation(alt::IEntity* _this) 20 | { 21 | return (Vector3)_this->GetRotation(); 22 | } 23 | 24 | void SetRotation(alt::IEntity* _this, Vector3 rot) 25 | { 26 | _this->SetRotation(rot.ToAlt()); 27 | } 28 | 29 | void AttachToEntity(alt::IEntity* _this, alt::IEntity* entity, int16_t entityBoneId, int16_t ownBoneId, Vector3 pos, Vector3 rot, bool enableCollisions, bool noFixedRotation) 30 | { 31 | _this->AttachToEntity(entity, entityBoneId, ownBoneId, pos.ToAlt(), rot.ToAlt(), enableCollisions, noFixedRotation); 32 | } 33 | 34 | py::object GetSyncedMeta(alt::IEntity* _this, const std::string& key) 35 | { 36 | return Utils::MValueToValue(_this->GetSyncedMetaData(key)); 37 | } 38 | 39 | py::object GetStreamSyncedMeta(alt::IEntity* _this, const std::string& key) 40 | { 41 | return Utils::MValueToValue(_this->GetStreamSyncedMetaData(key)); 42 | } 43 | 44 | void SetSyncedMeta(alt::IEntity* _this, const std::string& key, const py::object& value) 45 | { 46 | _this->SetSyncedMetaData(key, Utils::ValueToMValue(value)); 47 | } 48 | 49 | void SetStreamSyncedMeta(alt::IEntity* _this, const std::string& key, const py::object& value) 50 | { 51 | _this->SetStreamSyncedMetaData(key, Utils::ValueToMValue(value)); 52 | } 53 | 54 | void ResetNetOwner(alt::IEntity* _this, bool disable_migration) 55 | { 56 | _this->SetNetworkOwner(nullptr, disable_migration); 57 | } 58 | 59 | void SetModel(alt::IPlayer* _this, const py::object& object) 60 | { 61 | if (py::isinstance(object)) 62 | _this->SetModel(alt::ICore::Instance().Hash(object.cast())); 63 | else if (py::isinstance(object)) 64 | _this->SetModel(object.cast()); 65 | else 66 | throw py::value_error("int or str expected"); 67 | } 68 | 69 | void RegisterEntityClass(const py::module_& m) 70 | { 71 | auto pyClass = py::class_>(m, "Entity"); 72 | 73 | // Static 74 | pyClass.def_property_readonly_static("all", &GetAllEntities); 75 | pyClass.def_static("get_by_id", &GetEntityById, py::arg("id")); 76 | 77 | // Entity Data 78 | pyClass.def_property_readonly("id", &alt::IEntity::GetID); 79 | pyClass.def_property("rot", &GetRotation, &SetRotation); 80 | pyClass.def_property("streamed", &alt::IEntity::GetStreamed, &alt::IEntity::SetStreamed); 81 | pyClass.def_property("visible", &alt::IEntity::GetVisible, &alt::IEntity::SetVisible); 82 | pyClass.def_property("collision", &alt::IEntity::HasCollision, &alt::IEntity::SetCollision); 83 | pyClass.def_property("frozen", &alt::IEntity::IsFrozen, &alt::IEntity::SetFrozen); 84 | 85 | // Model 86 | pyClass.def_property("model", &alt::IEntity::GetModel, &SetModel); 87 | 88 | // NetOwner 89 | pyClass.def_property_readonly("net_owner", &alt::IEntity::GetNetworkOwner); 90 | pyClass.def("set_net_owner", &alt::IEntity::SetNetworkOwner, py::arg("player"), py::arg("disable_migration") = false); 91 | pyClass.def("reset_net_owner", &ResetNetOwner, py::arg("disable_migration") = false); 92 | 93 | // Attach 94 | pyClass.def("attach_to", &AttachToEntity, py::arg("entity"), py::arg("entity_bone_id"), py::arg("own_bone_id"), py::arg("pos"), py::arg("rot"), py::arg("enable_collisions"), py::arg("no_fixed_rotation")); 95 | pyClass.def("detach", &alt::IEntity::Detach); 96 | 97 | // Synced MetaData 98 | pyClass.def("get_synced_meta", &GetSyncedMeta, py::arg("key")); 99 | pyClass.def("has_synced_meta", &alt::IEntity::HasSyncedMetaData, py::arg("key")); 100 | pyClass.def("set_synced_meta", &SetSyncedMeta, py::arg("key"), py::arg("value")); 101 | pyClass.def("delete_synced_meta", &alt::IEntity::DeleteSyncedMetaData, py::arg("key")); 102 | 103 | // Stream Synced MetaData 104 | pyClass.def("get_stream_synced_meta", &GetStreamSyncedMeta, py::arg("key")); 105 | pyClass.def("has_stream_synced_meta", &alt::IEntity::HasStreamSyncedMetaData, py::arg("key")); 106 | pyClass.def("set_stream_synced_meta", &SetStreamSyncedMeta, py::arg("key"), py::arg("value")); 107 | pyClass.def("delete_stream_synced_meta", &alt::IEntity::DeleteStreamSyncedMetaData, py::arg("key")); 108 | } 109 | -------------------------------------------------------------------------------- /src/events/player.cpp: -------------------------------------------------------------------------------- 1 | #include "events.hpp" 2 | #include "utils.hpp" 3 | #include "../classes/types/enums.hpp" 4 | 5 | EventHandler playerConnect(alt::CEvent::Type::PLAYER_CONNECT, [](const alt::CEvent* ev, py::list& args) { 6 | auto event = dynamic_cast(ev); 7 | args.append(event->GetTarget().Get()); 8 | }); 9 | 10 | EventHandler playerBeforeConnect(alt::CEvent::Type::PLAYER_BEFORE_CONNECT, [](const alt::CEvent* ev, py::list& args) { 11 | auto event = dynamic_cast(ev); 12 | args.append(event->GetConnectionInfo().Get()); 13 | }); 14 | 15 | EventHandler playerDisconnect(alt::CEvent::Type::PLAYER_DISCONNECT, [](const alt::CEvent* ev, py::list& args) { 16 | auto event = dynamic_cast(ev); 17 | args.append(event->GetTarget().Get()); 18 | args.append(event->GetReason()); 19 | }); 20 | 21 | EventHandler connectionQueueAdd(alt::CEvent::Type::CONNECTION_QUEUE_ADD, [](const alt::CEvent* ev, py::list& args) { 22 | auto event = dynamic_cast(ev); 23 | args.append(event->GetConnectionInfo().Get()); 24 | }); 25 | 26 | EventHandler connectionQueueRemove(alt::CEvent::Type::CONNECTION_QUEUE_REMOVE, [](const alt::CEvent* ev, py::list& args) { 27 | auto event = dynamic_cast(ev); 28 | args.append(event->GetConnectionInfo().Get()); 29 | }); 30 | 31 | EventHandler playerDamage(alt::CEvent::Type::PLAYER_DAMAGE, [](const alt::CEvent* ev, py::list& args) { 32 | auto event = dynamic_cast(ev); 33 | args.append(event->GetTarget().Get()); 34 | args.append(Utils::GetBaseObject(event->GetAttacker())); 35 | args.append(event->GetHealthDamage()); 36 | args.append(event->GetArmourDamage()); 37 | args.append(event->GetWeapon()); 38 | }); 39 | 40 | EventHandler playerDeath(alt::CEvent::Type::PLAYER_DEATH, [](const alt::CEvent* ev, py::list& args) { 41 | auto event = dynamic_cast(ev); 42 | args.append(event->GetTarget().Get()); 43 | args.append(Utils::GetBaseObject(event->GetKiller())); 44 | args.append(event->GetWeapon()); 45 | }); 46 | 47 | EventHandler playerEnterVehicle(alt::CEvent::Type::PLAYER_ENTER_VEHICLE, [](const alt::CEvent* ev, py::list& args) { 48 | auto event = dynamic_cast(ev); 49 | args.append(event->GetPlayer().Get()); 50 | args.append(event->GetTarget().Get()); 51 | args.append(event->GetSeat()); 52 | }); 53 | 54 | EventHandler playerEnteringVehicle(alt::CEvent::Type::PLAYER_ENTERING_VEHICLE, [](const alt::CEvent* ev, py::list& args) { 55 | auto event = dynamic_cast(ev); 56 | args.append(event->GetPlayer().Get()); 57 | args.append(event->GetTarget().Get()); 58 | args.append(event->GetSeat()); 59 | }); 60 | 61 | EventHandler playerLeftVehicle(alt::CEvent::Type::PLAYER_LEAVE_VEHICLE, [](const alt::CEvent* ev, py::list& args) { 62 | auto event = dynamic_cast(ev); 63 | args.append(event->GetPlayer().Get()); 64 | args.append(event->GetTarget().Get()); 65 | args.append(event->GetSeat()); 66 | }); 67 | 68 | EventHandler playerChangeVehicleSeat(alt::CEvent::Type::PLAYER_CHANGE_VEHICLE_SEAT, [](const alt::CEvent* ev, py::list& args) { 69 | auto event = dynamic_cast(ev); 70 | args.append(event->GetPlayer().Get()); 71 | args.append(event->GetTarget().Get()); 72 | args.append(event->GetOldSeat()); 73 | args.append(event->GetNewSeat()); 74 | }); 75 | 76 | EventHandler playerWeaponChange(alt::CEvent::Type::PLAYER_WEAPON_CHANGE, [](const alt::CEvent* ev, py::list& args) { 77 | auto event = dynamic_cast(ev); 78 | args.append(event->GetTarget().Get()); 79 | args.append(event->GetOldWeapon()); 80 | args.append(event->GetNewWeapon()); 81 | }); 82 | 83 | EventHandler playerRequestControl(alt::CEvent::Type::PLAYER_REQUEST_CONTROL, [](const alt::CEvent* ev, py::list& args) { 84 | auto event = dynamic_cast(ev); 85 | args.append(event->GetPlayer().Get()); 86 | args.append(Utils::GetBaseObject(event->GetTarget().Get())); 87 | }); 88 | 89 | EventHandler playerAnimationChange(alt::CEvent::Type::PLAYER_CHANGE_ANIMATION_EVENT, [](const alt::CEvent* ev, py::list& args) { 90 | auto event = dynamic_cast(ev); 91 | args.append(event->GetTarget().Get()); 92 | args.append(event->GetOldAnimationDict()); 93 | args.append(event->GetNewAnimationDict()); 94 | args.append(event->GetOldAnimationName()); 95 | args.append(event->GetNewAnimationName()); 96 | }); 97 | 98 | 99 | EventHandler playerInteriorChange(alt::CEvent::Type::PLAYER_CHANGE_INTERIOR_EVENT, [](const alt::CEvent* ev, py::list& args) { 100 | auto event = dynamic_cast(ev); 101 | args.append(event->GetTarget().Get()); 102 | args.append(event->GetNewInteriorLocation()); 103 | args.append(event->GetOldInteriorLocation()); 104 | }); 105 | 106 | EventHandler playerConnectDenied(alt::CEvent::Type::PLAYER_CONNECT_DENIED, [](const alt::CEvent* ev, py::list& args) { 107 | auto event = dynamic_cast(ev); 108 | args.append(ConnectDeniedReason(event->GetReason())); 109 | args.append(event->GetName()); 110 | args.append(event->GetIp()); 111 | args.append(event->GetPasswordHash()); 112 | args.append(event->IsDebug()); 113 | args.append(event->GetBranch()); 114 | args.append(event->GetMajorVersion()); 115 | args.append(event->GetCdnUrl()); 116 | args.append(event->GetDiscordId()); 117 | }); -------------------------------------------------------------------------------- /src/bindings/alt.cpp: -------------------------------------------------------------------------------- 1 | #include "main.hpp" 2 | #include "utils.hpp" 3 | #include "version/version.h" 4 | 5 | uint32_t Hash(const std::string& str) 6 | { 7 | return alt::ICore::Instance().Hash(str); 8 | } 9 | 10 | uint32_t GetNetTime() 11 | { 12 | return alt::ICore::Instance().GetNetTime(); 13 | } 14 | 15 | py::dict GetServerConfig() 16 | { 17 | Config::Value::ValuePtr config = alt::ICore::Instance().GetServerConfig(); 18 | return Utils::ConfigNodeToValue(config); 19 | } 20 | 21 | alt::VehicleModelInfo GetVehicleModelInfoByHash(uint32_t vehicleHash) 22 | { 23 | return alt::ICore::Instance().GetVehicleModelByHash(vehicleHash); 24 | } 25 | 26 | py::dict GetPedModelInfoByHash(uint32_t pedHash) { 27 | py::dict dict; 28 | alt::PedModelInfo pedModelInfo = alt::ICore::Instance().GetPedModelByHash(pedHash); 29 | dict["hash"] = pedModelInfo.hash; 30 | dict["name"] = pedModelInfo.name; 31 | py::list pedBones; 32 | for (const auto& pedBone : pedModelInfo.bones) { 33 | py::dict pyPedBone; 34 | pyPedBone["id"] = pedBone.id; 35 | pyPedBone["index"] = pedBone.index; 36 | pyPedBone["name"] = pedBone.name; 37 | pedBones.append(pyPedBone); 38 | } 39 | dict["bones"] = pedBones; 40 | return dict; 41 | } 42 | 43 | uint64_t HashServerPassword(const std::string& password) 44 | { 45 | return alt::ICore::Instance().HashServerPassword(password); 46 | } 47 | 48 | void RestartResource(const std::string& resourceName) 49 | { 50 | alt::ICore::Instance().RestartResource(resourceName); 51 | } 52 | 53 | void StartResource(const std::string& resourceName) 54 | { 55 | alt::ICore::Instance().StartResource(resourceName); 56 | } 57 | 58 | void StopResource(const std::string& resourceName) 59 | { 60 | alt::ICore::Instance().StopResource(resourceName); 61 | } 62 | 63 | void SetPassword(const std::string& password) 64 | { 65 | return alt::ICore::Instance().SetPassword(password); 66 | } 67 | 68 | void StopServer() 69 | { 70 | alt::ICore::Instance().StopServer(); 71 | } 72 | 73 | std::string StringToSHA256(const std::string& str) 74 | { 75 | return alt::ICore::Instance().StringToSHA256(str); 76 | } 77 | 78 | void Export(const std::string& name, const py::object& object) 79 | { 80 | PyThreadState* interp = PyThreadState_Get(); 81 | PythonResource* resource = PythonRuntime::GetInstance()->GetPythonResourceFromInterp(interp); 82 | auto exports = resource->GetResource()->GetExports(); 83 | exports->Set(name, Utils::ValueToMValue(object)); 84 | } 85 | 86 | py::object GetMeta(const std::string& key) 87 | { 88 | return Utils::MValueToValue(alt::ICore::Instance().GetMetaData(key)); 89 | } 90 | 91 | void SetMeta(const std::string& key, const py::object& value) 92 | { 93 | alt::ICore::Instance().SetMetaData(key, Utils::ValueToMValue(value)); 94 | } 95 | 96 | bool HasMeta(const std::string& key) 97 | { 98 | return alt::ICore::Instance().HasMetaData(key); 99 | } 100 | 101 | void DeleteMeta(const std::string& key) 102 | { 103 | return alt::ICore::Instance().DeleteMetaData(key); 104 | } 105 | 106 | py::object GetSyncedMeta(const std::string& key) 107 | { 108 | return Utils::MValueToValue(alt::ICore::Instance().GetSyncedMetaData(key)); 109 | } 110 | 111 | void SetSyncedMeta(const std::string& key, const py::object& value) 112 | { 113 | alt::ICore::Instance().SetSyncedMetaData(key, Utils::ValueToMValue(value)); 114 | } 115 | 116 | bool HasSyncedMeta(const std::string& key) 117 | { 118 | return alt::ICore::Instance().HasSyncedMetaData(key); 119 | } 120 | 121 | void DeleteSyncedMeta(const std::string& key) 122 | { 123 | alt::ICore::Instance().DeleteSyncedMetaData(key); 124 | } 125 | 126 | void SetWorldProfiler(bool state) 127 | { 128 | alt::ICore::Instance().SetWorldProfiler(state); 129 | } 130 | 131 | void RegisterMainFunctions(py::module_ m) 132 | { 133 | m.attr("branch") = alt::ICore::Instance().GetBranch(); 134 | m.attr("debug") = alt::ICore::Instance().IsDebug(); 135 | m.attr("default_dimension") = alt::DEFAULT_DIMENSION; 136 | m.attr("global_dimension") = alt::GLOBAL_DIMENSION; 137 | m.attr("root_dir") = alt::ICore::Instance().GetRootDirectory(); 138 | m.attr("sdk_version") = ALT_SDK_VERSION; 139 | m.attr("version") = alt::ICore::Instance().GetVersion(); 140 | 141 | m.def("hash", &Hash, py::arg("value")); 142 | m.def("get_net_time", &GetNetTime); 143 | m.def("get_server_config", &GetServerConfig); 144 | m.def("get_vehicle_model_info_by_hash", &GetVehicleModelInfoByHash, py::arg("vehicle_hash")); 145 | m.def("get_ped_model_info_by_hash", &GetPedModelInfoByHash, py::arg("ped_hash")); 146 | m.def("hash_server_password", &HashServerPassword, py::arg("password")); 147 | m.def("set_password", &SetPassword, py::arg("password")); 148 | m.def("stop_server", &StopServer); 149 | m.def("string_to_sha256", &StringToSHA256, py::arg("value")); 150 | m.def("export", &Export, py::arg("name"), py::arg("object")); 151 | m.def("set_world_profiler", &SetWorldProfiler, py::arg("state")); 152 | 153 | m.def("restart_resource", &RestartResource, py::arg("resource_name")); 154 | m.def("start_resource", &StartResource, py::arg("resource_name")); 155 | m.def("stop_resource", &StopResource, py::arg("resource_name")); 156 | 157 | m.def("get_meta", &GetMeta, py::arg("key")); 158 | m.def("set_meta", &SetMeta, py::arg("key"), py::arg("value")); 159 | m.def("has_meta", &HasMeta, py::arg("key")); 160 | m.def("delete_meta", &DeleteMeta, py::arg("key")); 161 | 162 | m.def("get_synced_meta", &GetSyncedMeta, py::arg("key")); 163 | m.def("set_synced_meta", &SetSyncedMeta, py::arg("key"), py::arg("value")); 164 | m.def("has_synced_meta", &HasSyncedMeta, py::arg("key")); 165 | m.def("delete_synced_meta", &DeleteSyncedMeta, py::arg("key")); 166 | } 167 | -------------------------------------------------------------------------------- /src/classes/base/blip.cpp: -------------------------------------------------------------------------------- 1 | #include "classes/classes.hpp" 2 | #include "classes/types/enums.hpp" 3 | #include "classes/types/vector2.hpp" 4 | #include "classes/types/vector3.hpp" 5 | #include "utils.hpp" 6 | 7 | BlipColor GetBlipColor(alt::IBlip* _this) 8 | { 9 | return (BlipColor)_this->GetColor(); 10 | } 11 | 12 | float GetBlipScale(alt::IBlip* _this) 13 | { 14 | return _this->GetScaleXY()[0]; 15 | } 16 | 17 | void SetBlipScale(alt::IBlip* _this, float scale) 18 | { 19 | _this->SetScaleXY({scale, scale}); 20 | } 21 | 22 | Vector2 GetSize(alt::IBlip* _this) 23 | { 24 | return (Vector2)_this->GetScaleXY(); 25 | } 26 | 27 | void SetSize(alt::IBlip* _this, Vector2 size) 28 | { 29 | _this->SetScaleXY(size.ToAlt()); 30 | } 31 | 32 | BlipSprite GetBlipSprite(alt::IBlip* _this) 33 | { 34 | return (BlipSprite)_this->GetSprite(); 35 | } 36 | 37 | py::list GetAllBlips(const py::object& type) 38 | { 39 | return Utils::ArrayToPyList>(alt::ICore::Instance().GetBlips()); 40 | } 41 | 42 | void RegisterBlipClass(const py::module_& m) 43 | { 44 | auto pyClass = py::class_>(m, "Blip"); 45 | 46 | pyClass.def_static( 47 | "area", [](double x, double y, double z, float width, float height) { 48 | auto blip = alt::ICore::Instance().CreateBlip(nullptr, alt::IBlip::BlipType::AREA, {x, y, z}); 49 | blip->SetScaleXY({width, height}); 50 | return blip; 51 | }, 52 | py::arg("x"), py::arg("y"), py::arg("z"), py::arg("width"), py::arg("height")); 53 | 54 | pyClass.def_static( 55 | "area", [](Vector3 pos, float width, float height) { 56 | auto blip = alt::ICore::Instance().CreateBlip(nullptr, alt::IBlip::BlipType::AREA, pos.ToAlt()); 57 | blip->SetScaleXY({width, height}); 58 | return blip; 59 | }, 60 | py::arg("pos"), py::arg("width"), py::arg("height")); 61 | 62 | pyClass.def_static( 63 | "point", [](double x, double y, double z) { 64 | return alt::ICore::Instance().CreateBlip(nullptr, alt::IBlip::BlipType::DESTINATION, {x, y, z}); 65 | }, 66 | py::arg("x"), py::arg("y"), py::arg("z")); 67 | 68 | pyClass.def_static( 69 | "point", [](Vector3 pos) { 70 | return alt::ICore::Instance().CreateBlip(nullptr, alt::IBlip::BlipType::DESTINATION, pos.ToAlt()); 71 | }, 72 | py::arg("pos")); 73 | 74 | pyClass.def_static( 75 | "point", [](alt::IEntity* entity) { 76 | return alt::ICore::Instance().CreateBlip(nullptr, alt::IBlip::BlipType::DESTINATION, entity); 77 | }, 78 | py::arg("entity")); 79 | 80 | pyClass.def_static( 81 | "radius", [](double x, double y, double z, float radius) { 82 | auto blip = alt::ICore::Instance().CreateBlip(nullptr, alt::IBlip::BlipType::RADIUS, {x, y, z}); 83 | blip->SetScaleXY({radius, radius}); 84 | return blip; 85 | }, 86 | py::arg("x"), py::arg("y"), py::arg("z"), py::arg("radius")); 87 | 88 | pyClass.def_static( 89 | "radius", [](Vector3 pos, float radius) { 90 | auto blip = alt::ICore::Instance().CreateBlip(nullptr, alt::IBlip::BlipType::RADIUS, pos.ToAlt()); 91 | blip->SetScaleXY({radius, radius}); 92 | return blip; 93 | }, 94 | py::arg("pos"), py::arg("radius")); 95 | 96 | pyClass.def_property_readonly_static("all", &GetAllBlips); 97 | 98 | pyClass.def("fade", &alt::IBlip::Fade, py::arg("opacity"), py::arg("duration")); 99 | 100 | pyClass.def_property("alpha", &alt::IBlip::GetAlpha, &alt::IBlip::SetAlpha); 101 | pyClass.def_property("as_mission_creator", &alt::IBlip::GetAsMissionCreator, &alt::IBlip::SetAsMissionCreator); 102 | pyClass.def_property("attached_to", &alt::IBlip::AttachedTo, &alt::IBlip::AttachTo); 103 | pyClass.def_property("bright", &alt::IBlip::GetBright, &alt::IBlip::SetBright); 104 | pyClass.def_property("category", &alt::IBlip::GetCategory, &alt::IBlip::SetCategory); 105 | pyClass.def_property("color", &GetBlipColor, &alt::IBlip::SetColor); 106 | pyClass.def_property("crew_indicator_visible", &alt::IBlip::GetCrewIndicatorVisible, &alt::IBlip::SetCrewIndicatorVisible); 107 | pyClass.def_property("display", &alt::IBlip::GetDisplay, &alt::IBlip::SetDisplay); 108 | pyClass.def_property("flash_interval", &alt::IBlip::GetFlashInterval, &alt::IBlip::SetFlashInterval); 109 | pyClass.def_property("flash_timer", &alt::IBlip::GetFlashTimer, &alt::IBlip::SetFlashTimer); 110 | pyClass.def_property("flashes", &alt::IBlip::GetFlashes, &alt::IBlip::SetFlashes); 111 | pyClass.def_property("flashes_alternate", &alt::IBlip::GetFlashesAlternate, &alt::IBlip::SetFlashesAlternate); 112 | pyClass.def_property("friend_indicator_visible", &alt::IBlip::GetFriendIndicatorVisible, &alt::IBlip::SetFriendIndicatorVisible); 113 | pyClass.def_property("gxt_name", &alt::IBlip::GetGxtName, &alt::IBlip::SetGxtName); 114 | pyClass.def_property("heading", &alt::IBlip::GetRotation, &alt::IBlip::SetRotation); 115 | pyClass.def_property("heading_indicator_visible", &alt::IBlip::GetHeadingIndicatorVisible, &alt::IBlip::SetHeadingIndicatorVisible); 116 | pyClass.def_property("high_detail", &alt::IBlip::GetAsHighDetail, &alt::IBlip::SetAsHighDetail); 117 | pyClass.def_property("name", &alt::IBlip::GetName, &alt::IBlip::SetName); 118 | pyClass.def_property("number", &alt::IBlip::GetNumber, &alt::IBlip::SetNumber); 119 | pyClass.def_property("outline_indicator_visible", &alt::IBlip::GetOutlineIndicatorVisible, &alt::IBlip::SetOutlineIndicatorVisible); 120 | pyClass.def_property("priority", &alt::IBlip::GetPriority, &alt::IBlip::SetPriority); 121 | pyClass.def_property("pulse", &alt::IBlip::GetPulse, &alt::IBlip::SetPulse); 122 | pyClass.def_property("route", &alt::IBlip::GetRoute, &alt::IBlip::SetRoute); 123 | pyClass.def_property("route_color", &alt::IBlip::GetRouteColor, &alt::IBlip::SetRouteColor); 124 | pyClass.def_property("scale", &GetBlipScale, &SetBlipScale); 125 | pyClass.def_property("secondary_color", &alt::IBlip::GetSecondaryColor, &alt::IBlip::SetSecondaryColor); 126 | pyClass.def_property("short_range", &alt::IBlip::GetAsShortRange, &alt::IBlip::SetAsShortRange); 127 | pyClass.def_property("show_cone", &alt::IBlip::GetShowCone, &alt::IBlip::SetShowCone); 128 | pyClass.def_property("shrinked", &alt::IBlip::GetShrinked, &alt::IBlip::SetShrinked); 129 | pyClass.def_property("size", &GetSize, &SetSize); 130 | pyClass.def_property("sprite", &GetBlipSprite, &alt::IBlip::SetSprite); 131 | pyClass.def_property("tick_visible", &alt::IBlip::GetTickVisible, &alt::IBlip::SetTickVisible); 132 | } 133 | -------------------------------------------------------------------------------- /src/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "utils.hpp" 2 | #include "classes/types/vector2.hpp" 3 | #include "classes/types/vector3.hpp" 4 | 5 | alt::MValue Utils::ValueToMValue(const py::object& arg) 6 | { 7 | if (py::isinstance(arg)) 8 | return alt::ICore::Instance().CreateMValueString(py::str(arg).cast()); 9 | else if (py::isinstance(arg)) 10 | return alt::ICore::Instance().CreateMValueBool(py::bool_(arg).cast()); 11 | else if (py::isinstance(arg)) 12 | return alt::ICore::Instance().CreateMValueInt(py::int_(arg).cast()); 13 | else if (py::isinstance(arg)) 14 | return alt::ICore::Instance().CreateMValueNil(); 15 | else if (py::isinstance(arg)) 16 | return alt::ICore::Instance().CreateMValueDouble(py::float_(arg).cast()); 17 | else if (py::isinstance(arg) || py::isinstance(arg)) 18 | { 19 | auto tempList = alt::ICore::Instance().CreateMValueList(); 20 | for (auto element : arg) 21 | tempList->Push(ValueToMValue(element.cast())); 22 | return tempList; 23 | } 24 | else if (py::isinstance(arg)) 25 | { 26 | auto tempDict = alt::ICore::Instance().CreateMValueDict(); 27 | auto dict = arg.cast(); 28 | for (auto item : dict) 29 | tempDict->Set(item.first.cast(), ValueToMValue(item.second.cast())); 30 | return tempDict; 31 | } 32 | else if (py::isinstance(arg)) 33 | { 34 | auto func = arg.cast(); 35 | return alt::ICore::Instance().CreateMValueFunction(new PythonResource::PythonFunction(func)); 36 | } 37 | else if (py::isinstance(arg)) 38 | return alt::ICore::Instance().CreateMValueString(arg.cast().cast()); 39 | else if (py::isinstance(arg)) 40 | { 41 | auto byteArray = arg.cast(); 42 | return alt::ICore::Instance().CreateMValueByteArray(reinterpret_cast(byteArray.cast().c_str()), byteArray.size()); 43 | } 44 | else if (py::isinstance(arg)) 45 | return alt::ICore::Instance().CreateMValueVector3(arg.cast().ToAlt()); 46 | else if (py::isinstance(arg)) 47 | return alt::ICore::Instance().CreateMValueVector2(arg.cast().ToAlt()); 48 | else if (py::isinstance(arg)) 49 | return alt::ICore::Instance().CreateMValueRGBA(arg.cast()); 50 | else if (py::isinstance(arg)) 51 | return alt::ICore::Instance().CreateMValueBaseObject(arg.cast()); 52 | else 53 | return alt::ICore::Instance().CreateMValueNone(); 54 | } 55 | 56 | py::object Utils::MValueToValue(const alt::MValueConst& mValue) 57 | { 58 | switch (mValue->GetType()) 59 | { 60 | case alt::IMValue::Type::NIL: 61 | case alt::IMValue::Type::NONE: 62 | return py::none(); 63 | case alt::IMValue::Type::BOOL: 64 | return py::bool_(mValue.As()->Value()); 65 | case alt::IMValue::Type::INT: 66 | return py::int_(static_cast(mValue.As()->Value())); 67 | case alt::IMValue::Type::UINT: 68 | return py::int_(static_cast(mValue.As()->Value())); 69 | case alt::IMValue::Type::DOUBLE: 70 | return py::float_(mValue.As()->Value()); 71 | case alt::IMValue::Type::STRING: 72 | return py::str(mValue.As()->Value()); 73 | case alt::IMValue::Type::LIST: { 74 | auto mList = mValue.As(); 75 | py::list pyList; 76 | for (uint64_t i = 0; i < mList->GetSize(); i++) 77 | pyList.append(MValueToValue(mList->Get(i))); 78 | return pyList; 79 | } 80 | 81 | case alt::IMValue::Type::DICT: { 82 | auto mDict = mValue.As(); 83 | py::dict pyDict; 84 | for (auto item = mDict->Begin(); item; item = mDict->Next()) 85 | { 86 | auto dictVal = MValueToValue(item->GetValue().Get()); 87 | pyDict[item->GetKey().c_str()] = dictVal; 88 | } 89 | return pyDict; 90 | } 91 | 92 | case alt::IMValue::Type::VECTOR3: { 93 | Vector3 mVector3 = Vector3(mValue.As()->Value()); 94 | return py::cast(mVector3); 95 | } 96 | 97 | case alt::IMValue::Type::VECTOR2: { 98 | Vector2 mVector2 = Vector2(mValue.As()->Value()); 99 | return py::cast(mVector2); 100 | } 101 | 102 | case alt::IMValue::Type::BASE_OBJECT: { 103 | auto mBaseObject = mValue.As()->Value(); 104 | return Utils::GetBaseObject(mBaseObject); 105 | } 106 | case alt::IMValue::Type::FUNCTION: { 107 | auto mFunc = mValue.As(); 108 | py::cpp_function pyFunc = [mFunc](const py::args& args) { 109 | alt::MValueArgs funcArgs; 110 | for (auto arg : args) 111 | funcArgs.Push(Utils::ValueToMValue(arg.cast())); 112 | auto returnValue = mFunc->Call(funcArgs); 113 | return MValueToValue(returnValue); 114 | }; 115 | return pyFunc; 116 | } 117 | case alt::IMValue::Type::RGBA: { 118 | auto mRGBA = mValue.As().Get()->Value(); 119 | return py::cast(mRGBA); 120 | } 121 | case alt::IMValue::Type::BYTE_ARRAY: { 122 | auto mByteArray = mValue.As(); 123 | return py::bytearray(reinterpret_cast(mByteArray->GetData()), (Py_ssize_t)mByteArray->GetSize()); 124 | } 125 | default: 126 | return py::none(); 127 | } 128 | } 129 | 130 | py::object Utils::ConfigNodeToValue(Config::Value::ValuePtr node) 131 | { 132 | switch (node->GetType()) 133 | { 134 | case Config::Value::Type::NONE: 135 | return py::none(); 136 | case Config::Value::Type::BOOL: 137 | return py::bool_(node->AsBool()); 138 | case Config::Value::Type::NUMBER: 139 | return py::float_(node->AsNumber()); 140 | case Config::Value::Type::STRING: 141 | return py::str(node->AsString()); 142 | case Config::Value::Type::LIST: { 143 | Config::Value::List list = node->AsList(); 144 | py::list pyList; 145 | for (auto val : list) 146 | pyList.append(ConfigNodeToValue(val)); 147 | return pyList; 148 | } 149 | case Config::Value::Type::DICT: { 150 | Config::Value::Dict dict = node->AsDict(); 151 | py::dict pyDict; 152 | for (auto& pair : dict) 153 | pyDict[pair.first.c_str()] = ConfigNodeToValue(pair.second); 154 | return pyDict; 155 | } 156 | default: 157 | return py::none(); 158 | } 159 | } 160 | 161 | py::object Utils::GetBaseObject(const alt::Ref& baseObject) 162 | { 163 | if (!baseObject) return py::none(); 164 | switch (baseObject->GetType()) 165 | { 166 | case alt::IBaseObject::Type::PLAYER: 167 | return py::cast(dynamic_cast(baseObject.Get())); 168 | case alt::IBaseObject::Type::VEHICLE: 169 | return py::cast(dynamic_cast(baseObject.Get())); 170 | case alt::IBaseObject::Type::BLIP: 171 | return py::cast(dynamic_cast(baseObject.Get())); 172 | case alt::IBaseObject::Type::COLSHAPE: 173 | return py::cast(dynamic_cast(baseObject.Get())); 174 | case alt::IBaseObject::Type::CHECKPOINT: 175 | return py::cast(dynamic_cast(baseObject.Get())); 176 | case alt::IBaseObject::Type::VOICE_CHANNEL: 177 | return py::cast(dynamic_cast(baseObject.Get())); 178 | default: 179 | return py::none(); 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /src/PythonResource.cpp: -------------------------------------------------------------------------------- 1 | #include "PythonResource.hpp" 2 | #include "utils.hpp" 3 | 4 | bool PythonResource::Start() 5 | { 6 | PyThreadState_Swap(runtime->GetInterpreter()); 7 | interpreter = Py_NewInterpreter(); 8 | 9 | std::string path = resource->GetPath(); 10 | std::string main = resource->GetMain(); 11 | std::string fullPath = path + SEPARATOR + main; 12 | 13 | // Makes importing local files possible 14 | py::module_ sys = py::module_::import("sys"); 15 | py::list pyPath = sys.attr("path"); 16 | pyPath.append(fullPath.substr(0, fullPath.find_last_of("\\/"))); 17 | 18 | py::dict modules = sys.attr("modules"); 19 | py::object imp = py::module_::import("importlib.util"); 20 | for (const auto& depName : resource->GetDependencies()) 21 | { 22 | alt::IResource* dep = alt::ICore::Instance().GetResource(depName); 23 | 24 | py::object spec = imp.attr("spec_from_loader")(depName, py::none()); 25 | py::object module = imp.attr("module_from_spec")(spec); 26 | 27 | py::dict exports = Utils::MValueToValue(dep->GetExports()); 28 | for (auto exp : exports) 29 | module.attr(exp.first) = exp.second; 30 | modules[depName.c_str()] = module; 31 | } 32 | 33 | FILE* fp = fopen(fullPath.c_str(), "r"); 34 | if (!fp) 35 | { 36 | alt::ICore::Instance().LogError("Main file not found"); 37 | return false; 38 | } 39 | bool crashed = PyRun_SimpleFile(fp, fullPath.c_str()); 40 | fclose(fp); 41 | 42 | PyThreadState_Swap(runtime->GetInterpreter()); 43 | return !crashed; 44 | } 45 | bool PythonResource::Stop() 46 | { 47 | localEvents.clear(); 48 | localCustomEvents.clear(); 49 | remoteEvents.clear(); 50 | objects.clear(); 51 | 52 | for (const auto& task : tasks) delete task; 53 | for (const auto& timer : timers) delete timer.second; 54 | tasks.clear(); 55 | timers.clear(); 56 | PyThreadState_Swap(interpreter); 57 | Py_EndInterpreter(interpreter); 58 | PyThreadState_Swap(runtime->GetInterpreter()); 59 | return true; 60 | } 61 | 62 | bool PythonResource::OnEvent(const alt::CEvent* event) 63 | { 64 | auto eventType = event->GetType(); 65 | if (eventType == alt::CEvent::Type::SERVER_SCRIPT_EVENT || eventType == alt::CEvent::Type::CLIENT_SCRIPT_EVENT) 66 | HandleCustomEvent(event); 67 | else 68 | { 69 | auto eventHandler = EventHandler::Get(event); 70 | if (eventHandler) 71 | { 72 | auto callbacks = localEvents[eventType]; 73 | if (callbacks.empty()) return true; 74 | py::list eventArgs; 75 | eventHandler->GetEventArgs(event, eventArgs); 76 | for (const auto& callback : callbacks) 77 | { 78 | try 79 | { 80 | PyThreadState_Swap(interpreter); 81 | py::object returnValue = callback(*eventArgs); 82 | PyThreadState_Swap(runtime->GetInterpreter()); 83 | if (py::isinstance(returnValue) && !returnValue.cast()) 84 | event->Cancel(); 85 | else if (py::isinstance(returnValue) && eventType == alt::CEvent::Type::PLAYER_BEFORE_CONNECT) 86 | reinterpret_cast(const_cast(event))->Cancel(returnValue.cast()); 87 | } 88 | catch (py::error_already_set& e) 89 | { 90 | e.discard_as_unraisable(callback.attr("__name__")); 91 | } 92 | } 93 | } 94 | } 95 | return true; 96 | } 97 | 98 | void PythonResource::OnTick() 99 | { 100 | for (auto task : tasks) 101 | { 102 | uint32_t time = alt::ICore::Instance().GetNetTime(); 103 | if (task->Update(time) && (alt::ICore::Instance().GetNetTime() - time) > 10) 104 | task->TimeWarning(time, resource->GetName()); 105 | } 106 | for (auto it = timers.cbegin(); it != timers.cend();) 107 | { 108 | uint32_t time = alt::ICore::Instance().GetNetTime(); 109 | if (it->second->Update(time)) 110 | { 111 | if ((alt::ICore::Instance().GetNetTime() - time) > 10) 112 | it->second->TimeWarning(time, resource->GetName()); 113 | delete it->second; 114 | it = timers.erase(it); 115 | } 116 | else 117 | it = std::next(it); 118 | } 119 | } 120 | 121 | void PythonResource::HandleCustomEvent(const alt::CEvent* ev) 122 | { 123 | py::list eventArgs; 124 | std::vector callbacks; 125 | if (ev->GetType() == alt::CEvent::Type::SERVER_SCRIPT_EVENT) 126 | { 127 | auto event = dynamic_cast(ev); 128 | std::string name = event->GetName(); 129 | callbacks = localCustomEvents[name]; 130 | if (callbacks.empty()) return; 131 | for (const auto& arg : event->GetArgs()) 132 | { 133 | auto value = Utils::MValueToValue(arg); 134 | eventArgs.append(value); 135 | } 136 | } 137 | else 138 | { 139 | auto event = dynamic_cast(ev); 140 | std::string name = event->GetName(); 141 | callbacks = remoteEvents[name]; 142 | if (callbacks.empty()) return; 143 | eventArgs.append(event->GetTarget().Get()); 144 | for (const auto& arg : event->GetArgs()) 145 | { 146 | auto value = Utils::MValueToValue(arg); 147 | eventArgs.append(value); 148 | } 149 | } 150 | for (const auto& callback : callbacks) 151 | { 152 | try 153 | { 154 | PyThreadState_Swap(interpreter); 155 | callback(*eventArgs); 156 | PyThreadState_Swap(runtime->GetInterpreter()); 157 | } 158 | catch (py::error_already_set& e) 159 | { 160 | e.discard_as_unraisable(callback.attr("__name__")); 161 | } 162 | } 163 | } 164 | 165 | void PythonResource::OnCreateBaseObject(alt::Ref object) 166 | { 167 | object->AddRef(); 168 | objects.insert({object->GetType(), object}); 169 | } 170 | 171 | void PythonResource::OnRemoveBaseObject(alt::Ref object) 172 | { 173 | auto range = objects.equal_range(object->GetType()); 174 | for (auto it = range.first; it != range.second; it++) 175 | if (it->second == object) 176 | { 177 | objects.erase(it); 178 | break; 179 | } 180 | } 181 | 182 | bool PythonResource::IsObjectValid(const alt::Ref& object) 183 | { 184 | auto range = objects.equal_range(object->GetType()); 185 | for (auto it = range.first; it != range.second; it++) 186 | if (it->second == object) return true; 187 | return false; 188 | } 189 | 190 | int PythonResource::AddTimer(double milliseconds, const py::function& func) 191 | { 192 | auto task = new Interval(milliseconds, func, interpreter); 193 | intervalId++; 194 | timers[intervalId] = task; 195 | return intervalId; 196 | } 197 | 198 | void PythonResource::ClearTimer(int timerId) 199 | { 200 | auto interval = timers[timerId]; 201 | timers.erase(timerId); 202 | delete interval; 203 | } 204 | 205 | void PythonResource::AddTask(double milliseconds, const py::function& func) 206 | { 207 | auto task = new Interval(milliseconds, func, interpreter); 208 | tasks.push_back(task); 209 | } 210 | 211 | Interval* PythonResource::GetInterval(const py::function& func) 212 | { 213 | for (int i{}; i < tasks.size(); i++) 214 | if (tasks[i]->GetFunc().is(func)) 215 | return tasks[i]; 216 | return nullptr; 217 | } 218 | 219 | void PythonResource::AddScriptEvent(const alt::CEvent::Type& type, const py::function& eventFunc) 220 | { 221 | localEvents[type].push_back(eventFunc); 222 | } 223 | 224 | void PythonResource::AddServerEvent(const std::string& eventName, const py::function& eventFunc) 225 | { 226 | localCustomEvents[eventName].push_back(eventFunc); 227 | } 228 | 229 | void PythonResource::AddClientEvent(const std::string& eventName, const py::function& eventFunc) 230 | { 231 | remoteEvents[eventName].push_back(eventFunc); 232 | } 233 | 234 | alt::MValue PythonResource::PythonFunction::Call(alt::MValueArgs args) const 235 | { 236 | py::list funcArgs; 237 | for (const auto& arg : args) 238 | funcArgs.append(Utils::MValueToValue(arg)); 239 | auto returnValue = func(*funcArgs); 240 | return Utils::ValueToMValue(returnValue); 241 | } 242 | 243 | bool PythonResource::MakeClient(alt::IResource::CreationInfo* info, alt::Array files) 244 | { 245 | info->type = "js"; 246 | return true; 247 | } 248 | -------------------------------------------------------------------------------- /docs/articles/events.md: -------------------------------------------------------------------------------- 1 | # Events 2 | 3 | Sometimes you want to execute code when something happens 4 | 5 | This is why events exist, let's take a look at how they work 6 | 7 | ## Event's with no arguments 8 | 9 | Let's start with events without any arguments as they are easier to understand, currently there is only one so let's take a look at it. 10 | 11 | ```py 12 | import alt 13 | 14 | @alt.event(alt.Event.ServerStarted) 15 | def server_started() -> None: 16 | alt.log("Server Started!") 17 | ``` 18 | 19 | This code outputs `Server Started!` when the event is triggered, in this case the ServerStarted event which triggers when the server is started 20 | 21 | Let's go through this code line by line 22 | 23 | --- 24 | 25 | ### Decorator 26 | ```py hl_lines="3" 27 | import alt 28 | 29 | @alt.event(alt.Event.ServerStarted) 30 | def server_started() -> None: 31 | alt.log("Server Started!") 32 | ``` 33 | 34 | This decorator `alt.event()` decorator, is placed above a function which should get executed once the specified event is triggered 35 | 36 | The first and only argument you pass to this function is an event you want to subscribe to. This has to be `alt.Event` enum, otherwise exception will be raised 37 | 38 | --- 39 | 40 | ### Function 41 | ```py hl_lines="4 5" 42 | import alt 43 | 44 | @alt.event(alt.Event.ServerStarted) 45 | def server_started() -> None: 46 | alt.log("Server Started!") 47 | ``` 48 | 49 | This is the function you want to call once the event is triggered, the name can be anything you want 50 | 51 | Because we are creating event with no arguments, there shouldn't be any arguments for this function 52 | 53 | The body of the function can of course be anything you want, most of the time it's going to do something with the arguments passed to it 54 | 55 | ## Events with arguments 56 | 57 | Most of the time you want to get some info from events, this is possible through arguments 58 | 59 | ```py 60 | import alt 61 | 62 | @alt.event(alt.Event.PlayerConnect) 63 | def player_connect(player: alt.Player) -> None: 64 | alt.log(f"Player joined: {player.name}") 65 | player.model = "mp_m_freemode_01" 66 | player.spawn(0, 0, 0) 67 | ``` 68 | 69 | The only difference between these events and events without arguments, is that the function you create needs to have arguments 70 | 71 | This is a PlayerConnect event which gets executed when player joins, our first argument is the player which connected 72 | 73 | In this event we are logging into the console that player joined, spawning the player and setting its model 74 | 75 | ## Custom events 76 | 77 | Sometimes you want to trigger events yourself, like for example when you want 2 resources communicate with each other or client to communicate with server 78 | 79 | The communication can go as follows: 80 | 81 | - Client -> Server 82 | - Server -> Client 83 | - Server -> Server 84 | 85 | ### Client -> Server 86 | 87 | ```js title="client.js" 88 | import alt from "alt-client"; 89 | 90 | alt.emitServer("clientEvent", "This is message from client"); 91 | ``` 92 | 93 | ```py title="server.py" 94 | import alt 95 | 96 | @alt.client_event("clientEvent") 97 | def client_event(player: alt.Player, msg: str) -> None: 98 | alt.log(f"Player {player.name} sent {msg}") 99 | ``` 100 | 101 | Client events work almost identically to normal events, you only need to replace the decorator `alt.event()` with `alt.client_event()` and instead of `alt.Event` enum, pass name of the event as string 102 | 103 | When you receive event from client, you will get the player object as the first argument, this is the player which triggered the event 104 | 105 | Rest of the arguments are the ones sent with the event, in this example it is the string `This is message from client` 106 | 107 | ### Server -> Client 108 | 109 | ```js title="client.js" 110 | import alt from "alt-client"; 111 | 112 | alt.onServer("serverEvent", (msg) => { 113 | alt.log(msg); 114 | }); 115 | ``` 116 | 117 | ```py title="server.py" 118 | import alt 119 | 120 | @alt.event(alt.Event.PlayerConnect) 121 | def player_connect(player: alt.Player) -> None: 122 | # These 2 do the same thing 123 | player.emit("serverEvent", "This is a server event") 124 | alt.emit_client(player, "serverEvent", "This is a server event") 125 | 126 | # You can also pass list instead of single player 127 | alt.emit_client([player], "serverEvent", "This is a server event") 128 | 129 | # This will emit an event to all players 130 | alt.emit_all_clients("serverEvent", "This is a server event") 131 | ``` 132 | 133 | When we want to emit event from server to specific player, we need to have the player object 134 | 135 | All the ways to emit a client event are showed in this code 136 | 137 | The first two emit event to single player only, they both work completely the same way 138 | 139 | The third one works the same way as the second one, apart from that you can pass list instead of single player, this can be useful when you need to emit event to multiple players 140 | 141 | And the fourth and last one is the simplest, by calling the function you emit event to players 142 | 143 | ### Server -> Server 144 | 145 | ```py 146 | import alt 147 | 148 | @alt.custom_event("customEvent") 149 | def custom_event(msg: str) -> None: 150 | alt.log(f"Message received {msg}") 151 | 152 | alt.emit("customEvent", "This is a message from server") 153 | ``` 154 | 155 | Subscribing to events from server works the same way as with client events, only difference is that you use `alt.custom_event()` decorator 156 | 157 | Emitting the event is also very similar to emitting client event, you just call `alt.emit()` function and pass the event name and the arguments 158 | 159 | ### Note about custom event arguments 160 | 161 | Important thing to keep in mind, is that you can't pass everything as an event argument, the structures you sent have to be cross-language, so any custom object you might try to send as an argument won't work 162 | 163 | Here is the list of types which you can send: `str`, `int`, `float`, `bool`, `NoneType`, `list`, `dict`, `function`, `bytes`, `bytearray`, `alt.Vector2`, `alt.Vector3`, `alt.RGBA`, `alt.BaseObject` 164 | 165 | Functions can be only sent on the server, trying to send function to client or vice versa will fail 166 | 167 | Keep in mind that if you send function, the return value and arguments of the function must be sendable in an event 168 | 169 | ## Cancelling Events 170 | 171 | There are some events which you are able to cancel 172 | 173 | Most of them are triggered by player doing something, and by cancelling them you disable it syncing to other players 174 | 175 | ```py 176 | import alt 177 | 178 | @alt.event(alt.Event.Explosion) 179 | def explosion(player: alt.Player, *args) -> bool: 180 | alt.log(f"{player.name} caused an explosion") 181 | return False 182 | ``` 183 | 184 | This is the explosion event, which gets triggered once explosion is created 185 | 186 | We can cancel events by returning `False`, you can cancel any event this way, but not every event will be changed once you cancel them 187 | 188 | Also, here you can see that we used `*args` as an argument, this makes it so that you don't need to specify every single argument if you don't need them 189 | 190 | 191 | The only event which works differently is `alt.Event.PlayerBeforeConnect` 192 | 193 | In this event you can return `False` as with other events, but also a string, this will do the same thing as returning `False` but will also show a message 194 | 195 | ```py 196 | import alt 197 | 198 | banned_players = [ 199 | "very_bad_player" 200 | ] 201 | 202 | @alt.event(alt.Event.PlayerBeforeConnect) 203 | def player_before_connect(connection_info: alt.ConnectionInfo) -> str | None: 204 | if connection_info.name in banned_players: 205 | return "You are banned" 206 | ``` 207 | 208 | --- 209 | 210 | You can see all of the available events inside [API Reference](api-reference/events.md) 211 | 212 | Now you should know what events are and how to use them 213 | 214 | In the next article we are going to learn about Tasks and Timers 215 | -------------------------------------------------------------------------------- /src/classes/types/vector2.cpp: -------------------------------------------------------------------------------- 1 | #include "vector2.hpp" 2 | #include "classes/classes.hpp" 3 | 4 | double Vector2::GetAngle(const Vector2& other, const bool& degrees) const 5 | { 6 | double xy = x * other.x + y * other.y; 7 | double posALength = sqrt(std::pow(x, 2) + std::pow(y, 2)); 8 | double posBLength = sqrt(std::pow(other.x, 2) + std::pow(other.y, 2)); 9 | 10 | if (posALength == 0 || posBLength == 0) 11 | { 12 | return -1; 13 | } 14 | 15 | double cos = xy / (posALength * posBLength); 16 | 17 | if (degrees) 18 | return std::acos(cos); 19 | else 20 | return std::acos(cos) * (180 / alt::PI); 21 | } 22 | 23 | py::dict Vector2::ToDict() 24 | { 25 | py::dict dict; 26 | dict["x"] = x; 27 | dict["y"] = y; 28 | return dict; 29 | } 30 | 31 | py::list Vector2::ToList() 32 | { 33 | py::list list; 34 | list.append(x); 35 | list.append(y); 36 | return list; 37 | } 38 | 39 | alt::Position Vector2::ToAlt() const 40 | { 41 | return {x, y, 0}; 42 | } 43 | 44 | std::string Vector2::ToString() const 45 | { 46 | return "Vector2(" + std::to_string(x) + ", " + std::to_string(y) + ")"; 47 | } 48 | 49 | Vector2 Vector2::ToDegrees() const 50 | { 51 | return {x * (180 / alt::PI), y * (180 / alt::PI)}; 52 | } 53 | 54 | Vector2 Vector2::ToRadians() const 55 | { 56 | return {x * (alt::PI / 180), y * (alt::PI / 180)}; 57 | } 58 | 59 | double Vector2::Length() const 60 | { 61 | return sqrt(x * x + y * y); 62 | } 63 | 64 | double Vector2::Distance(Vector2& other) const 65 | { 66 | return sqrt(DistanceSquared(other)); 67 | } 68 | 69 | double Vector2::DistanceSquared(Vector2& other) const 70 | { 71 | return std::pow(x - other.x, 2) + std::pow(y - other.y, 2); 72 | } 73 | 74 | Vector2 Vector2::Lerp(Vector2 other, double ratio) const 75 | { 76 | double x1 = x + (other.x - x) * ratio; 77 | double y1 = y + (other.y - y) * ratio; 78 | return {x1, y1}; 79 | } 80 | 81 | bool Vector2::IsInRange(const Vector2& other, double range) const 82 | { 83 | double dx = abs(x - other.x); 84 | double dy = abs(y - other.y); 85 | 86 | return dx <= range && dy <= range && dx * dx + dy * dy <= range * range; 87 | } 88 | 89 | Vector2 Vector2::operator+(const Vector2& other) const 90 | { 91 | return {x + other.x, y + other.y}; 92 | } 93 | 94 | Vector2 Vector2::operator+(double num) const 95 | { 96 | return {x + num, y + num}; 97 | } 98 | 99 | Vector2 Vector2::operator+(const py::list& vectorList) const 100 | { 101 | return {x + vectorList[0].cast(), y + vectorList[1].cast()}; 102 | } 103 | 104 | Vector2 Vector2::operator-(const Vector2& other) const 105 | { 106 | return {x - other.x, y - other.y}; 107 | } 108 | 109 | Vector2 Vector2::operator-(double num) const 110 | { 111 | return {x - num, y - num}; 112 | } 113 | 114 | Vector2 Vector2::operator-(const py::list& vectorList) const 115 | { 116 | return {x - vectorList[0].cast(), y - vectorList[1].cast()}; 117 | } 118 | 119 | Vector2 Vector2::operator-() const 120 | { 121 | return {-x, -y}; 122 | } 123 | 124 | Vector2 Vector2::operator/(const Vector2& other) const 125 | { 126 | return {x / other.x, y / other.y}; 127 | } 128 | 129 | Vector2 Vector2::operator/(double num) const 130 | { 131 | return {x / num, y / num}; 132 | } 133 | 134 | Vector2 Vector2::operator/(const py::list& vectorList) const 135 | { 136 | return {x / vectorList[0].cast(), y / vectorList[1].cast()}; 137 | } 138 | 139 | Vector2 Vector2::operator*(const Vector2& other) const 140 | { 141 | return {x * other.x, y * other.y}; 142 | } 143 | 144 | Vector2 Vector2::operator*(double num) const 145 | { 146 | return {x * num, y * num}; 147 | } 148 | 149 | Vector2 Vector2::operator*(const py::list& vectorList) const 150 | { 151 | return {x * vectorList[0].cast(), y * vectorList[1].cast()}; 152 | } 153 | 154 | bool Vector2::operator==(const Vector2& other) const 155 | { 156 | return x == other.x && y == other.y; 157 | } 158 | 159 | double Vector2::Dot(const Vector2& other) const 160 | { 161 | return x * other.x + y * other.y; 162 | } 163 | 164 | double Vector2::Dot(double num) const 165 | { 166 | return x * num + y * num; 167 | } 168 | 169 | double Vector2::Dot(const py::list& vectorList) const 170 | { 171 | return x * vectorList[0].cast() + y * vectorList[1].cast(); 172 | } 173 | 174 | Vector2 Vector2::Normalize() const 175 | { 176 | double length = sqrt(x * x + y * y); 177 | return {x / length, y / length}; 178 | } 179 | 180 | Vector2 Vector2::Zero(const py::object& _this) 181 | { 182 | return {0, 0}; 183 | } 184 | 185 | Vector2 Vector2::One(const py::object& _this) 186 | { 187 | return {1, 1}; 188 | } 189 | 190 | Vector2 Vector2::Up(const py::object& _this) 191 | { 192 | return {0, 1}; 193 | } 194 | 195 | Vector2 Vector2::Down(const py::object& _this) 196 | { 197 | return {0, -1}; 198 | } 199 | 200 | Vector2 Vector2::Left(const py::object& _this) 201 | { 202 | return {-1, 0}; 203 | } 204 | 205 | Vector2 Vector2::Right(const py::object& _this) 206 | { 207 | return {1, 0}; 208 | } 209 | 210 | Vector2 Vector2::PositiveInfinity(const py::object& _this) 211 | { 212 | return {std::numeric_limits::infinity(), std::numeric_limits::infinity()}; 213 | } 214 | 215 | Vector2 Vector2::NegativeInfinity(const py::object& _this) 216 | { 217 | return {-std::numeric_limits::infinity(), -std::numeric_limits::infinity()}; 218 | } 219 | 220 | double Vector2::AngleTo(const Vector2& other) 221 | { 222 | return GetAngle(other, false); 223 | } 224 | 225 | double Vector2::AngleToDegrees(const Vector2& other) 226 | { 227 | return GetAngle(other, true); 228 | } 229 | 230 | void RegisterVector2Class(const py::module_& m) 231 | { 232 | auto pyClass = py::class_(m, "Vector2"); 233 | pyClass.def(py::init([](double _x, double _y) { return Vector2(_x, _y); }), py::arg("x"), py::arg("y")); 234 | pyClass.def(py::init([](const py::list& vectorList) { return Vector2(vectorList); }), py::arg("vector_list")); 235 | 236 | pyClass.def_readwrite("x", &Vector2::x); 237 | pyClass.def_readwrite("y", &Vector2::y); 238 | pyClass.def("__str__", &Vector2::ToString); 239 | 240 | pyClass.def("to_dict", &Vector2::ToDict); 241 | pyClass.def("to_list", &Vector2::ToList); 242 | pyClass.def("length", &Vector2::Length); 243 | pyClass.def("distance", &Vector2::Distance, py::arg("vector")); 244 | pyClass.def("distance_squared", &Vector2::DistanceSquared, py::arg("vector")); 245 | pyClass.def("lerp", &Vector2::Lerp, py::arg("vector"), py::arg("ratio")); 246 | 247 | pyClass.def("to_degrees", &Vector2::ToDegrees); 248 | pyClass.def("to_radians", &Vector2::ToRadians); 249 | pyClass.def("is_in_range", &Vector2::IsInRange, py::arg("vector"), py::arg("range")); 250 | 251 | pyClass.def(py::self + py::self); 252 | pyClass.def(py::self + double()); 253 | pyClass.def(py::self + py::list()); 254 | 255 | pyClass.def(py::self - py::self); 256 | pyClass.def(py::self - double()); 257 | pyClass.def(py::self - py::list()); 258 | pyClass.def(-py::self); 259 | 260 | pyClass.def(py::self * py::self); 261 | pyClass.def(py::self * double()); 262 | pyClass.def(py::self * py::list()); 263 | 264 | pyClass.def(py::self / py::self); 265 | pyClass.def(py::self / double()); 266 | pyClass.def(py::self / py::list()); 267 | 268 | pyClass.def(py::self == py::self); 269 | 270 | pyClass.def("dot", py::overload_cast(&Vector2::Dot, py::const_), py::arg("vector")); 271 | pyClass.def("dot", py::overload_cast(&Vector2::Dot, py::const_), py::arg("vector_list")); 272 | pyClass.def("dot", py::overload_cast(&Vector2::Dot, py::const_), py::arg("num")); 273 | 274 | pyClass.def_property_readonly_static("zero", &Vector2::Zero); 275 | pyClass.def_property_readonly_static("one", &Vector2::One); 276 | pyClass.def_property_readonly_static("up", &Vector2::Up); 277 | pyClass.def_property_readonly_static("down", &Vector2::Down); 278 | pyClass.def_property_readonly_static("left", &Vector2::Left); 279 | pyClass.def_property_readonly_static("right", &Vector2::Right); 280 | pyClass.def_property_readonly_static("positive_infinity", &Vector2::PositiveInfinity); 281 | pyClass.def_property_readonly_static("negative_infinity", &Vector2::NegativeInfinity); 282 | 283 | pyClass.def("normalize", &Vector2::Normalize); 284 | pyClass.def("angle_to", &Vector2::AngleTo, py::arg("vector")); 285 | pyClass.def("angle_to_degrees", &Vector2::AngleToDegrees, py::arg("vector")); 286 | } 287 | -------------------------------------------------------------------------------- /src/classes/types/vector3.cpp: -------------------------------------------------------------------------------- 1 | #include "vector3.hpp" 2 | #include "classes/classes.hpp" 3 | 4 | double Vector3::GetAngle(const Vector3& other, const bool& degrees) const 5 | { 6 | double xy = x * other.x + y * other.y; 7 | double posALength = sqrt(std::pow(x, 2) + std::pow(y, 2)); 8 | double posBLength = sqrt(std::pow(other.x, 2) + std::pow(other.y, 2)); 9 | 10 | if (posALength == 0 || posBLength == 0) 11 | { 12 | return -1; 13 | } 14 | 15 | double cos = xy / (posALength * posBLength); 16 | 17 | if (degrees) 18 | return std::acos(cos); 19 | else 20 | return std::acos(cos) * (180 / alt::PI); 21 | } 22 | 23 | py::dict Vector3::ToDict() 24 | { 25 | py::dict dict; 26 | dict["x"] = x; 27 | dict["y"] = y; 28 | dict["z"] = z; 29 | return dict; 30 | } 31 | 32 | py::list Vector3::ToList() 33 | { 34 | py::list list; 35 | list.append(x); 36 | list.append(y); 37 | list.append(z); 38 | return list; 39 | } 40 | 41 | alt::Position Vector3::ToAlt() const 42 | { 43 | return alt::Position{x, y, z}; 44 | } 45 | 46 | std::string Vector3::ToString() const 47 | { 48 | return "Vector3(" + std::to_string(x) + ", " + std::to_string(y) + ", " + std::to_string(z) + ")"; 49 | } 50 | 51 | Vector3 Vector3::ToDegrees() const 52 | { 53 | return {x * (180 / alt::PI), y * (180 / alt::PI), z * (180 / alt::PI)}; 54 | } 55 | 56 | Vector3 Vector3::ToRadians() const 57 | { 58 | return {x * (alt::PI / 180), y * (alt::PI / 180), z * (alt::PI / 180)}; 59 | } 60 | 61 | double Vector3::Length() const 62 | { 63 | return sqrt(x * x + y * y + z * z); 64 | } 65 | 66 | double Vector3::Distance(Vector3& other) const 67 | { 68 | return sqrt(DistanceSquared(other)); 69 | } 70 | 71 | double Vector3::DistanceSquared(Vector3& other) const 72 | { 73 | return std::pow(x - other.x, 2) + std::pow(y - other.y, 2) + std::pow(z - other.z, 2); 74 | } 75 | 76 | bool Vector3::IsInRange(const Vector3& other, double range) const 77 | { 78 | double dx = abs(x - other.x); 79 | double dy = abs(y - other.y); 80 | double dz = abs(z - other.z); 81 | 82 | return dx <= range && dy <= range && dz <= range && dx * dx + dy * dy + dz * dz <= range * range; 83 | } 84 | 85 | Vector3 Vector3::Lerp(Vector3 other, double ratio) const 86 | { 87 | double x1 = x + (other.x - x) * ratio; 88 | double y1 = y + (other.y - y) * ratio; 89 | double z1 = z + (other.z - z) * ratio; 90 | return {x1, y1, z1}; 91 | } 92 | 93 | Vector3 Vector3::operator+(const Vector3& other) const 94 | { 95 | return {x + other.x, y + other.y, z + other.z}; 96 | } 97 | 98 | Vector3 Vector3::operator+(double num) const 99 | { 100 | return {x + num, y + num, z + num}; 101 | } 102 | 103 | Vector3 Vector3::operator+(const py::list& vectorList) const 104 | { 105 | return {x + vectorList[0].cast(), y + vectorList[1].cast(), z + vectorList[2].cast()}; 106 | } 107 | 108 | Vector3 Vector3::operator-(const Vector3& other) const 109 | { 110 | return {x - other.x, y - other.y, z - other.z}; 111 | } 112 | 113 | Vector3 Vector3::operator-(double num) const 114 | { 115 | return {x - num, y - num, z - num}; 116 | } 117 | 118 | Vector3 Vector3::operator-(const py::list& vectorList) const 119 | { 120 | return {x - vectorList[0].cast(), y - vectorList[1].cast(), z - vectorList[2].cast()}; 121 | } 122 | 123 | Vector3 Vector3::operator-() const 124 | { 125 | return {-x, -y, -z}; 126 | } 127 | 128 | Vector3 Vector3::operator/(const Vector3& other) const 129 | { 130 | return {x / other.x, y / other.y, z / other.z}; 131 | } 132 | 133 | Vector3 Vector3::operator/(double num) const 134 | { 135 | return {x / num, y / num, z / num}; 136 | } 137 | 138 | Vector3 Vector3::operator/(const py::list& vectorList) const 139 | { 140 | return {x / vectorList[0].cast(), y / vectorList[1].cast(), z / vectorList[2].cast()}; 141 | } 142 | 143 | Vector3 Vector3::operator*(const Vector3& other) const 144 | { 145 | return {x * other.x, y * other.y, z * other.z}; 146 | } 147 | 148 | Vector3 Vector3::operator*(double num) const 149 | { 150 | return {x * num, y * num, z * num}; 151 | } 152 | 153 | Vector3 Vector3::operator*(const py::list& vectorList) const 154 | { 155 | return {x * vectorList[0].cast(), y * vectorList[1].cast(), z * vectorList[2].cast()}; 156 | } 157 | 158 | bool Vector3::operator==(const Vector3& other) const 159 | { 160 | return x == other.x && y == other.y && z == other.z; 161 | } 162 | 163 | Vector3 Vector3::Cross(const Vector3& other) const 164 | { 165 | return {y * other.z - z * other.y, z * other.x - x * other.z, x * other.y - y * other.x}; 166 | } 167 | 168 | Vector3 Vector3::Cross(double num) const 169 | { 170 | return {y * num - z * num, z * num - x * num, x * num - y * num}; 171 | } 172 | 173 | Vector3 Vector3::Cross(const py::list& vectorList) const 174 | { 175 | auto _x = vectorList[0].cast(); 176 | auto _y = vectorList[1].cast(); 177 | auto _z = vectorList[2].cast(); 178 | 179 | return {y * _z - z * _y, z * _x - x * _z, x * _y - y * _x}; 180 | } 181 | 182 | double Vector3::Dot(const Vector3& other) const 183 | { 184 | return x * other.x + y * other.y + z * other.z; 185 | } 186 | 187 | double Vector3::Dot(double num) const 188 | { 189 | return x * num + y * num + z * num; 190 | } 191 | 192 | double Vector3::Dot(const py::list& vectorList) const 193 | { 194 | return x * vectorList[0].cast() + y * vectorList[1].cast() + z * vectorList[2].cast(); 195 | } 196 | 197 | Vector3 Vector3::Normalize() const 198 | { 199 | double length = sqrt(x * x + y * y + z * z); 200 | return {x / length, y / length, z / length}; 201 | } 202 | 203 | Vector3 Vector3::Zero(const py::object& _this) 204 | { 205 | return {0, 0, 0}; 206 | } 207 | 208 | Vector3 Vector3::One(const py::object& _this) 209 | { 210 | return {1, 1, 1}; 211 | } 212 | 213 | Vector3 Vector3::Up(const py::object& _this) 214 | { 215 | return {0, 1, 0}; 216 | } 217 | 218 | Vector3 Vector3::Down(const py::object& _this) 219 | { 220 | return {0, -1, 0}; 221 | } 222 | 223 | Vector3 Vector3::Left(const py::object& _this) 224 | { 225 | return {-1, 0, 0}; 226 | } 227 | 228 | Vector3 Vector3::Right(const py::object& _this) 229 | { 230 | return {1, 0, 0}; 231 | } 232 | 233 | Vector3 Vector3::Back(const py::object& _this) 234 | { 235 | return {0, 0, -1}; 236 | } 237 | 238 | Vector3 Vector3::Forward(const py::object& _this) 239 | { 240 | return {0, 0, 1}; 241 | } 242 | 243 | Vector3 Vector3::PositiveInfinity(const py::object& _this) 244 | { 245 | return {std::numeric_limits::infinity(), std::numeric_limits::infinity(), 246 | std::numeric_limits::infinity()}; 247 | } 248 | 249 | Vector3 Vector3::NegativeInfinity(const py::object& _this) 250 | { 251 | return {-std::numeric_limits::infinity(), -std::numeric_limits::infinity(), 252 | -std::numeric_limits::infinity()}; 253 | } 254 | 255 | double Vector3::AngleTo(const Vector3& other) 256 | { 257 | return GetAngle(other, false); 258 | } 259 | 260 | double Vector3::AngleToDegrees(const Vector3& other) 261 | { 262 | return GetAngle(other, true); 263 | } 264 | 265 | void RegisterVector3Class(const py::module_& m) 266 | { 267 | auto pyClass = py::class_(m, "Vector3"); 268 | pyClass.def(py::init([](double _x, double _y, double _z) { return Vector3(_x, _y, _z); }), py::arg("x"), py::arg("y"), py::arg("z")); 269 | pyClass.def(py::init([](const py::list& vectorList) { return Vector3(vectorList); }), py::arg("vector_list")); 270 | 271 | pyClass.def_readwrite("x", &Vector3::x); 272 | pyClass.def_readwrite("y", &Vector3::y); 273 | pyClass.def_readwrite("z", &Vector3::z); 274 | pyClass.def("__str__", &Vector3::ToString); 275 | 276 | pyClass.def("to_dict", &Vector3::ToDict); 277 | pyClass.def("to_list", &Vector3::ToList); 278 | pyClass.def("length", &Vector3::Length); 279 | pyClass.def("distance", &Vector3::Distance, py::arg("vector")); 280 | pyClass.def("distance_squared", &Vector3::DistanceSquared, py::arg("vector")); 281 | 282 | pyClass.def("to_degrees", &Vector3::ToDegrees); 283 | pyClass.def("to_radians", &Vector3::ToRadians); 284 | pyClass.def("is_in_range", &Vector3::IsInRange, py::arg("vector"), py::arg("range")); 285 | pyClass.def("lerp", &Vector3::Lerp, py::arg("vector"), py::arg("ratio")); 286 | 287 | pyClass.def(py::self + py::self); 288 | pyClass.def(py::self + double()); 289 | pyClass.def(py::self + py::list()); 290 | 291 | pyClass.def(py::self - py::self); 292 | pyClass.def(py::self - double()); 293 | pyClass.def(py::self - py::list()); 294 | pyClass.def(-py::self); 295 | 296 | pyClass.def(py::self * py::self); 297 | pyClass.def(py::self * double()); 298 | pyClass.def(py::self * py::list()); 299 | 300 | pyClass.def(py::self / py::list()); 301 | pyClass.def(py::self / double()); 302 | pyClass.def(py::self / py::self); 303 | 304 | pyClass.def(py::self == py::self); 305 | 306 | pyClass.def("cross", py::overload_cast(&Vector3::Cross, py::const_), py::arg("vector")); 307 | pyClass.def("cross", py::overload_cast(&Vector3::Cross, py::const_), py::arg("num")); 308 | pyClass.def("cross", py::overload_cast(&Vector3::Cross, py::const_), py::arg("vector_list")); 309 | 310 | pyClass.def("dot", py::overload_cast(&Vector3::Dot, py::const_), py::arg("vector")); 311 | pyClass.def("dot", py::overload_cast(&Vector3::Dot, py::const_), py::arg("num")); 312 | pyClass.def("dot", py::overload_cast(&Vector3::Dot, py::const_), py::arg("vector_list")); 313 | 314 | pyClass.def_property_readonly_static("zero", &Vector3::Zero); 315 | pyClass.def_property_readonly_static("one", &Vector3::One); 316 | pyClass.def_property_readonly_static("up", &Vector3::Up); 317 | pyClass.def_property_readonly_static("down", &Vector3::Down); 318 | pyClass.def_property_readonly_static("left", &Vector3::Left); 319 | pyClass.def_property_readonly_static("right", &Vector3::Right); 320 | pyClass.def_property_readonly_static("back", &Vector3::Back); 321 | pyClass.def_property_readonly_static("forward", &Vector3::Forward); 322 | pyClass.def_property_readonly_static("positive_infinity", &Vector3::PositiveInfinity); 323 | pyClass.def_property_readonly_static("negative_infinity", &Vector3::NegativeInfinity); 324 | 325 | pyClass.def("normalize", &Vector3::Normalize); 326 | pyClass.def("angle_to", &Vector3::AngleTo, py::arg("vector")); 327 | pyClass.def("angle_to_degrees", &Vector3::AngleToDegrees, py::arg("vector")); 328 | } 329 | -------------------------------------------------------------------------------- /src/classes/base/player.cpp: -------------------------------------------------------------------------------- 1 | #include "classes/classes.hpp" 2 | #include "classes/types/enums.hpp" 3 | #include "classes/types/vector3.hpp" 4 | #include "utils.hpp" 5 | 6 | py::list GetAllPlayers(const py::object& type) 7 | { 8 | return Utils::ArrayToPyList>(alt::ICore::Instance().GetPlayers()); 9 | } 10 | 11 | alt::IPlayer* GetPlayerById(uint16_t id) 12 | { 13 | auto entity = alt::ICore::Instance().GetEntityByID(id); 14 | if (entity && entity->GetType() == alt::IBaseObject::Type::PLAYER) 15 | return dynamic_cast(entity.Get()); 16 | return nullptr; 17 | } 18 | 19 | void Spawn(alt::IPlayer* _this, float x, float y, float z, uint32_t delay = 0) 20 | { 21 | alt::Position altPos{x, y, z}; 22 | _this->Spawn(altPos, delay); 23 | } 24 | 25 | void Spawn(alt::IPlayer* _this, Vector3 pos, uint32_t delay = 0) 26 | { 27 | _this->Spawn(pos.ToAlt(), delay); 28 | } 29 | 30 | py::list GetCurrentWeaponComponents(alt::IPlayer* _this) 31 | { 32 | return Utils::ArrayToPyList(_this->GetCurrentWeaponComponents()); 33 | } 34 | 35 | py::list GetWeapons(alt::IPlayer* _this) 36 | { 37 | py::list list; 38 | alt::Array weapons = _this->GetWeapons(); 39 | for (const alt::Weapon& weapon : weapons) 40 | { 41 | py::dict dict; 42 | dict["hash"] = weapon.hash; 43 | dict["tint_index"] = weapon.tintIndex; 44 | dict["components"] = weapon.components; 45 | list.append(dict); 46 | } 47 | return list; 48 | } 49 | 50 | void SetDlcClothes(alt::IPlayer* _this, uint32_t dlc, uint8_t component, uint16_t drawable, uint8_t texture, uint8_t palette = 2) 51 | { 52 | if (drawable < 128) 53 | _this->SetDlcClothes(component, drawable, texture, palette, dlc); 54 | else 55 | throw py::value_error("Drawable can't be higher than 127"); 56 | } 57 | 58 | bool SetDlcProps(alt::IPlayer* _this, uint32_t dlc, uint8_t component, uint8_t drawable, uint8_t texture) 59 | { 60 | return _this->SetDlcProps(component, drawable, texture, dlc); 61 | } 62 | 63 | Vector3 GetAimPos(alt::IPlayer* _this) 64 | { 65 | return (Vector3)_this->GetAimPos(); 66 | } 67 | 68 | Vector3 GetHeadRot(alt::IPlayer* _this) 69 | { 70 | return (Vector3)_this->GetHeadRotation(); 71 | } 72 | 73 | py::object GetEntityAimingAt(alt::IPlayer* _this) 74 | { 75 | return Utils::GetBaseObject(_this->GetEntityAimingAt()); 76 | } 77 | 78 | WeaponTint GetCurrentWeaponTintIndex(alt::IPlayer* _this) 79 | { 80 | return (WeaponTint)_this->GetCurrentWeaponTintIndex(); 81 | } 82 | 83 | Vector3 GetEntityAimOffset(alt::IPlayer* _this) 84 | { 85 | return (Vector3)_this->GetEntityAimOffset(); 86 | } 87 | 88 | py::dict GetClothes(alt::IPlayer* _this, uint8_t component) 89 | { 90 | alt::Cloth cloth = _this->GetClothes(component); 91 | py::dict dict; 92 | dict["drawable"] = cloth.drawableId; 93 | dict["texture"] = cloth.textureId; 94 | dict["palette"] = cloth.paletteId; 95 | return dict; 96 | } 97 | 98 | py::dict GetDlcClothes(alt::IPlayer* _this, uint8_t component) 99 | { 100 | alt::DlcCloth dlcCloth = _this->GetDlcClothes(component); 101 | py::dict dict; 102 | dict["dlc"] = dlcCloth.dlc; 103 | dict["drawable"] = dlcCloth.drawableId; 104 | dict["texture"] = dlcCloth.textureId; 105 | dict["palette"] = dlcCloth.paletteId; 106 | return dict; 107 | } 108 | 109 | py::dict GetDlcProp(alt::IPlayer* _this, uint8_t component) 110 | { 111 | alt::DlcProp dlcProp = _this->GetDlcProps(component); 112 | py::dict dict; 113 | dict["dlc"] = dlcProp.dlc; 114 | dict["drawable"] = dlcProp.drawableId; 115 | dict["texture"] = dlcProp.textureId; 116 | return dict; 117 | } 118 | 119 | py::dict GetHeadBlendData(alt::IPlayer* _this) 120 | { 121 | alt::HeadBlendData headBlendData = _this->GetHeadBlendData(); 122 | py::dict dict; 123 | dict["shape_first_id"] = headBlendData.shapeFirstID; 124 | dict["shape_second_id"] = headBlendData.shapeSecondID; 125 | dict["shape_third_id"] = headBlendData.shapeThirdID; 126 | dict["skin_first_id"] = headBlendData.skinFirstID; 127 | dict["skin_second_id"] = headBlendData.skinSecondID; 128 | dict["skin_third_id"] = headBlendData.skinThirdID; 129 | dict["shape_mix"] = headBlendData.shapeMix; 130 | dict["skin_mix"] = headBlendData.skinMix; 131 | dict["third_mix"] = headBlendData.thirdMix; 132 | return dict; 133 | } 134 | 135 | py::dict GetHeadOverlay(alt::IPlayer* _this, uint8_t overlayId) 136 | { 137 | alt::HeadOverlay headOverlay = _this->GetHeadOverlay(overlayId); 138 | py::dict dict; 139 | dict["index"] = headOverlay.index; 140 | dict["opacity"] = headOverlay.opacity; 141 | dict["color_type"] = headOverlay.colorType; 142 | dict["color_index"] = headOverlay.colorIndex; 143 | dict["second_color_index"] = headOverlay.secondColorIndex; 144 | return dict; 145 | } 146 | 147 | py::dict GetProps(alt::IPlayer* _this, uint8_t component) 148 | { 149 | alt::Prop prop = _this->GetProps(component); 150 | py::dict dict; 151 | dict["drawable"] = prop.drawableId; 152 | dict["texture"] = prop.textureId; 153 | return dict; 154 | } 155 | 156 | py::object GetLocalMeta(alt::IPlayer* _this, const std::string& key) 157 | { 158 | return Utils::MValueToValue(_this->GetLocalMetaData(key)); 159 | } 160 | 161 | void SetLocalMeta(alt::IPlayer* _this, const std::string& key, const py::object& value) 162 | { 163 | _this->SetLocalMetaData(key, Utils::ValueToMValue(value)); 164 | } 165 | 166 | void Emit(alt::IPlayer* _this, const std::string& eventName, const py::args& args) 167 | { 168 | alt::MValueArgs eventArgs; 169 | for (const py::handle& arg : *args) 170 | eventArgs.Push(Utils::ValueToMValue(arg.cast())); 171 | alt::ICore::Instance().TriggerClientEvent(_this, eventName, eventArgs); 172 | } 173 | 174 | BodyPart GetLastDamagedBodyPart(alt::IPlayer* _this) { 175 | return (BodyPart)_this->GetLastDamagedBodyPart(); 176 | } 177 | 178 | void RegisterPlayerClass(const py::module_& m) 179 | { 180 | auto pyClass = py::class_>(m, "Player", py::multiple_inheritance()); 181 | 182 | // Static 183 | pyClass.def_property_readonly_static("all", &GetAllPlayers); 184 | pyClass.def_static("get_by_id", &GetPlayerById, py::arg("id")); 185 | 186 | // Events 187 | pyClass.def("emit", &Emit, py::arg("event_name")); 188 | 189 | // Player Data 190 | pyClass.def_property_readonly("name", &alt::IPlayer::GetName); 191 | pyClass.def_property_readonly("ip", &alt::IPlayer::GetIP); 192 | pyClass.def_property_readonly("connected", &alt::IPlayer::IsConnected); 193 | pyClass.def_property_readonly("ping", &alt::IPlayer::GetPing); 194 | pyClass.def_property_readonly("social_id", &alt::IPlayer::GetSocialID); 195 | pyClass.def_property_readonly("hwid_hash", &alt::IPlayer::GetHwidHash); 196 | pyClass.def_property_readonly("hwid_ex_hash", &alt::IPlayer::GetHwidExHash); 197 | pyClass.def_property_readonly("auth_token", &alt::IPlayer::GetAuthToken); 198 | pyClass.def_property_readonly("discord_id", &alt::IPlayer::GetDiscordId); 199 | pyClass.def("kick", &alt::IPlayer::Kick, py::arg("reason") = "Kicked"); 200 | 201 | // Game Data 202 | pyClass.def_property_readonly("move_speed", &alt::IPlayer::GetMoveSpeed); 203 | pyClass.def_property_readonly("strafe_speed", &alt::IPlayer::GetStrafeSpeed); 204 | pyClass.def_property_readonly("forward_speed", &alt::IPlayer::GetForwardSpeed); 205 | pyClass.def_property_readonly("aim_pos", &GetAimPos); 206 | pyClass.def_property_readonly("head_rot", &GetHeadRot); 207 | pyClass.def_property_readonly("entity_aiming_at", &GetEntityAimingAt); 208 | pyClass.def_property_readonly("entity_aim_offset", &GetEntityAimOffset); 209 | pyClass.def_property_readonly("interior_location", &alt::IPlayer::GetInteriorLocation); 210 | pyClass.def_property("invincible", &alt::IPlayer::GetInvincible, &alt::IPlayer::SetInvincible); 211 | pyClass.def_property("last_damaged_body_part", &GetLastDamagedBodyPart, &alt::IPlayer::SetLastDamagedBodyPart); 212 | pyClass.def("play_ambient_speech", &alt::IPlayer::PlayAmbientSpeech, py::arg("speech_name"), py::arg("speech_param"), py::arg("speech_dict_hash")); 213 | 214 | // Weather & Time 215 | pyClass.def("set_date_time", &alt::IPlayer::SetDateTime, py::arg("day"), py::arg("month"), py::arg("year"), py::arg("hour"), py::arg("minute"), py::arg("second")); 216 | pyClass.def("set_weather", &alt::IPlayer::SetWeather); 217 | 218 | // Vehicles 219 | pyClass.def_property_readonly("in_vehicle", &alt::IPlayer::IsInVehicle); 220 | pyClass.def_property_readonly("vehicle", &alt::IPlayer::GetVehicle); 221 | pyClass.def_property_readonly("seat", &alt::IPlayer::GetSeat); 222 | pyClass.def("set_into_vehicle", &alt::IPlayer::SetIntoVehicle, py::arg("vehicle"), py::arg("seat")); 223 | 224 | // Health 225 | pyClass.def_property("health", &alt::IPlayer::GetHealth, &alt::IPlayer::SetHealth); 226 | pyClass.def_property("max_health", &alt::IPlayer::GetMaxHealth, &alt::IPlayer::SetMaxHealth); 227 | pyClass.def("clear_blood_damage", &alt::IPlayer::ClearBloodDamage); 228 | 229 | // Armour 230 | pyClass.def_property("armour", &alt::IPlayer::GetArmour, &alt::IPlayer::SetArmour); 231 | pyClass.def_property("max_armour", &alt::IPlayer::GetMaxArmour, &alt::IPlayer::SetMaxArmour); 232 | 233 | // Weapons 234 | pyClass.def_property("current_weapon", &alt::IPlayer::GetCurrentWeapon, &alt::IPlayer::SetCurrentWeapon); 235 | pyClass.def("give_weapon", &alt::IPlayer::GiveWeapon, py::arg("weapon_hash"), py::arg("ammo"), py::arg("equip_now")); 236 | pyClass.def("remove_weapon", &alt::IPlayer::RemoveWeapon, py::arg("weapon_hash")); 237 | pyClass.def("remove_all_weapons", &alt::IPlayer::RemoveAllWeapons); 238 | pyClass.def("set_weapon_tint_index", &alt::IPlayer::SetWeaponTintIndex, py::arg("weapon_hash"), py::arg("tint_index")); 239 | pyClass.def_property_readonly("current_weapon_tint_index", &GetCurrentWeaponTintIndex); 240 | pyClass.def_property_readonly("current_weapon_components", &GetCurrentWeaponComponents); 241 | pyClass.def("add_weapon_component", &alt::IPlayer::AddWeaponComponent, py::arg("weapon_hash"), py::arg("component")); 242 | pyClass.def("remove_weapon_component", &alt::IPlayer::RemoveWeaponComponent, py::arg("weapon_hash"), py::arg("component")); 243 | pyClass.def_property_readonly("weapons", &GetWeapons); 244 | 245 | // Current Status 246 | pyClass.def_property_readonly("dead", &alt::IPlayer::IsDead); 247 | pyClass.def_property_readonly("jumping", &alt::IPlayer::IsJumping); 248 | pyClass.def_property_readonly("in_ragdoll", &alt::IPlayer::IsInRagdoll); 249 | pyClass.def_property_readonly("aiming", &alt::IPlayer::IsAiming); 250 | pyClass.def_property_readonly("shooting", &alt::IPlayer::IsShooting); 251 | pyClass.def_property_readonly("reloading", &alt::IPlayer::IsReloading); 252 | pyClass.def_property_readonly("super_jump", &alt::IPlayer::IsSuperJumpEnabled); 253 | pyClass.def_property_readonly("crouching", &alt::IPlayer::IsCrouching); 254 | pyClass.def_property_readonly("stealthy", &alt::IPlayer::IsStealthy); 255 | pyClass.def_property_readonly("flashlight_active", &alt::IPlayer::IsFlashlightActive); 256 | 257 | // Face Features 258 | pyClass.def("set_head_overlay", &alt::IPlayer::SetHeadOverlay, py::arg("overlay_id"), py::arg("index"), py::arg("opacity")); 259 | pyClass.def("remove_head_overlay", &alt::IPlayer::RemoveHeadOverlay, py::arg("overlay_id")); 260 | pyClass.def("set_head_overlay_color", &alt::IPlayer::SetHeadOverlayColor, py::arg("overlay_id"), py::arg("color_type"), py::arg("color_index"), py::arg("second_color_index")); 261 | pyClass.def("get_head_overlay", &GetHeadOverlay, py::arg("overlay_id")); 262 | pyClass.def("set_face_feature", &alt::IPlayer::SetFaceFeature, py::arg("index"), py::arg("scale")); 263 | pyClass.def("get_face_feature_scale", &alt::IPlayer::GetFaceFeatureScale, py::arg("index")); 264 | pyClass.def("remove_face_feature", &alt::IPlayer::RemoveFaceFeature, py::arg("index")); 265 | pyClass.def("set_head_blend_palette_color", &alt::IPlayer::SetHeadBlendPaletteColor, py::arg("id"), py::arg("red"), py::arg("green"), py::arg("blue")); 266 | pyClass.def("get_head_blend_palette_color", &alt::IPlayer::GetHeadBlendPaletteColor, py::arg("id")); 267 | pyClass.def("set_head_blend_data", &alt::IPlayer::SetHeadBlendData, py::arg("shape_first_id"), py::arg("shape_second_id"), py::arg("shape_third_id"), py::arg("skin_first_id"), py::arg("skin_second_id"), py::arg("skin_third_id"), py::arg("shape_mix"), py::arg("skin_mix"), py::arg("third_mix")); 268 | pyClass.def_property_readonly("head_blend_data", &GetHeadBlendData); 269 | pyClass.def("get_eye_color", &alt::IPlayer::GetEyeColor); 270 | pyClass.def("set_eye_color", &alt::IPlayer::SetEyeColor, py::arg("eye_color")); 271 | pyClass.def_property("hair_color", &alt::IPlayer::GetHairColor, &alt::IPlayer::SetHairColor); 272 | pyClass.def_property("hair_highlight_color", &alt::IPlayer::GetHairHighlightColor, &alt::IPlayer::SetHairHighlightColor); 273 | 274 | // Clothing & Props 275 | pyClass.def("get_clothes", &GetClothes, py::arg("component")); 276 | pyClass.def("set_clothes", &alt::IPlayer::SetClothes, py::arg("component"), py::arg("drawable"), py::arg("texture"), py::arg("palette") = 0); 277 | pyClass.def("get_dlc_clothes", &GetDlcClothes, py::arg("component")); 278 | pyClass.def("set_dlc_clothes", &SetDlcClothes, py::arg("dlc"), py::arg("component"), py::arg("drawable"), py::arg("texture"), py::arg("palette") = 2); 279 | pyClass.def("get_prop", &GetProps, py::arg("component")); 280 | pyClass.def("set_prop", &alt::IPlayer::SetProps, py::arg("component"), py::arg("drawable"), py::arg("texture")); 281 | pyClass.def("get_dlc_prop", &GetDlcProp, py::arg("component")); 282 | pyClass.def("set_dlc_prop", &SetDlcProps, py::arg("dlc"), py::arg("component"), py::arg("drawable"), py::arg("texture")); 283 | pyClass.def("clear_prop", &alt::IPlayer::ClearProps); 284 | 285 | // Streaming Range 286 | pyClass.def("is_entity_in_streaming_range", py::overload_cast>(&alt::IPlayer::IsEntityInStreamingRange), py::arg("entity")); 287 | pyClass.def("is_entity_in_streaming_range", py::overload_cast(&alt::IPlayer::IsEntityInStreamingRange), py::arg("id")); 288 | 289 | // Spawn 290 | pyClass.def_property_readonly("spawned", &alt::IPlayer::IsSpawned); 291 | pyClass.def("spawn", py::overload_cast(&Spawn), py::arg("pos"), py::arg("delay") = 0); 292 | pyClass.def("spawn", py::overload_cast(&Spawn), py::arg("x"), py::arg("y"), py::arg("z"), py::arg("delay") = 0); 293 | pyClass.def("despawn", &alt::IPlayer::Despawn); 294 | 295 | // Animations 296 | pyClass.def_property_readonly("current_animation_dict", &alt::IPlayer::GetCurrentAnimationDict); 297 | pyClass.def_property_readonly("current_animation_name", &alt::IPlayer::GetCurrentAnimationName); 298 | 299 | // Local MetaData 300 | pyClass.def("get_local_meta", &GetLocalMeta, py::arg("key")); 301 | pyClass.def("has_local_meta", &alt::IPlayer::HasLocalMetaData, py::arg("key")); 302 | pyClass.def("set_local_meta", &SetLocalMeta, py::arg("key"), py::arg("value")); 303 | pyClass.def("delete_local_meta", &alt::IPlayer::DeleteLocalMetaData, py::arg("key")); 304 | } 305 | -------------------------------------------------------------------------------- /src/classes/base/vehicle.cpp: -------------------------------------------------------------------------------- 1 | #include "classes/classes.hpp" 2 | #include "classes/types/enums.hpp" 3 | #include "classes/types/vector3.hpp" 4 | #include "utils.hpp" 5 | 6 | py::list GetAllVehicles(const py::object& type) 7 | { 8 | return Utils::ArrayToPyList>(alt::ICore::Instance().GetVehicles()); 9 | } 10 | 11 | alt::IVehicle* GetVehicleById(uint16_t id) 12 | { 13 | auto entity = alt::ICore::Instance().GetEntityByID(id); 14 | if (entity && entity->GetType() == alt::IBaseObject::Type::VEHICLE) 15 | return dynamic_cast(entity.Get()); 16 | return nullptr; 17 | } 18 | 19 | alt::IVehicle* CreateVehicle(uint32_t hash, alt::Position pos, alt::Rotation rot) 20 | { 21 | auto vehicle = alt::ICore::Instance().CreateVehicle(hash, pos, rot); 22 | if (vehicle) 23 | return vehicle.Get(); 24 | throw std::runtime_error("Failed to create vehicle"); 25 | } 26 | 27 | WindowTint GetWindowTint(alt::IVehicle* _this) 28 | { 29 | return (WindowTint)_this->GetWindowTint(); 30 | } 31 | 32 | py::dict GetNeonActive(alt::IVehicle* _this) 33 | { 34 | py::dict dict; 35 | bool left, right, front, back; 36 | _this->GetNeonActive(&left, &right, &front, &back); 37 | dict["left"] = left; 38 | dict["right"] = right; 39 | dict["front"] = front; 40 | dict["back"] = back; 41 | return dict; 42 | } 43 | 44 | void SetNeonActive(alt::IVehicle* _this, const py::dict& neon) 45 | { 46 | _this->SetNeonActive(neon["left"].cast(), neon["right"].cast(), neon["front"].cast(), neon["back"].cast()); 47 | } 48 | 49 | RadioStation GetRadioStationIndex(alt::IVehicle* _this) 50 | { 51 | return (RadioStation)_this->GetRadioStationIndex(); 52 | } 53 | 54 | VehicleLockState GetLockState(alt::IVehicle* _this) 55 | { 56 | return (VehicleLockState)_this->GetLockState(); 57 | } 58 | 59 | VehicleDoorState GetDoorState(alt::IVehicle* _this, uint8_t doorId) 60 | { 61 | return (VehicleDoorState)_this->GetDoorState(doorId); 62 | } 63 | 64 | VehiclePartDamage GetPartDamageLevel(alt::IVehicle* _this, uint8_t partId) 65 | { 66 | return (VehiclePartDamage)_this->GetPartDamageLevel(partId); 67 | } 68 | 69 | VehicleBumper GetBumperDamageLevel(alt::IVehicle* _this, uint8_t bumperId) 70 | { 71 | return (VehicleBumper)_this->GetBumperDamageLevel(bumperId); 72 | } 73 | 74 | void SetSearchLightTo(alt::IVehicle* _this, alt::IEntity* entity, bool state) 75 | { 76 | _this->SetSearchLight(state, entity); 77 | } 78 | 79 | NumberPlateStyle GetNumberplateIndex(alt::IVehicle* _this) 80 | { 81 | return (NumberPlateStyle)_this->GetNumberplateIndex(); 82 | } 83 | 84 | Vector3 GetVelocity(alt::IVehicle* _this) 85 | { 86 | return (Vector3)_this->GetVelocity(); 87 | } 88 | 89 | void RegisterVehicleClass(const py::module_& m) 90 | { 91 | auto pyClass = py::class_>(m, "Vehicle"); 92 | pyClass.def(py::init<>([](const std::string& model, float x, float y, float z, float rx, float ry, float rz) { 93 | auto hash = alt::ICore::Instance().Hash(model); 94 | return CreateVehicle(hash, alt::Position(x, y, z), alt::Rotation(rx, ry, rz)); 95 | }), 96 | py::arg("model"), py::arg("x"), py::arg("y"), py::arg("z"), py::arg("rx"), py::arg("ry"), py::arg("rz")); 97 | pyClass.def(py::init<>([](uint32_t hash, float x, float y, float z, float rx, float ry, float rz) { 98 | return CreateVehicle(hash, alt::Position(x, y, z), alt::Rotation(rx, ry, rz)); 99 | }), 100 | py::arg("model"), py::arg("x"), py::arg("y"), py::arg("z"), py::arg("rx"), py::arg("ry"), py::arg("rz")); 101 | pyClass.def(py::init<>([](const std::string& model, Vector3 pos, Vector3 rot) { 102 | auto hash = alt::ICore::Instance().Hash(model); 103 | return CreateVehicle(hash, pos.ToAlt(), rot.ToAlt()); 104 | }), 105 | py::arg("model"), py::arg("pos"), py::arg("rot")); 106 | pyClass.def(py::init<>([](uint32_t hash, Vector3 pos, Vector3 rot) { 107 | return CreateVehicle(hash, pos.ToAlt(), rot.ToAlt()); 108 | }), 109 | py::arg("model"), py::arg("pos"), py::arg("rot")); 110 | 111 | pyClass.def_property_readonly_static("all", &GetAllVehicles); 112 | pyClass.def_static("get_by_id", &GetVehicleById, py::arg("id")); 113 | 114 | pyClass.def("get_mod", &alt::IVehicle::GetMod, py::arg("mod_type")); 115 | pyClass.def("set_mod", &alt::IVehicle::SetMod, py::arg("mod_type"), py::arg("mod_id")); 116 | pyClass.def("get_mods_count", &alt::IVehicle::GetModsCount, py::arg("mod_type")); 117 | pyClass.def("get_extra", &alt::IVehicle::IsExtraOn, py::arg("extra_id")); 118 | pyClass.def("set_extra", &alt::IVehicle::ToggleExtra, py::arg("extra_id"), py::arg("state")); 119 | pyClass.def("get_door_state", &GetDoorState, py::arg("door_id")); 120 | pyClass.def("set_door_state", &alt::IVehicle::SetDoorState, py::arg("door_id"), py::arg("state")); 121 | pyClass.def("is_window_opened", &alt::IVehicle::IsWindowOpened, py::arg("window_id")); 122 | pyClass.def("set_window_opened", &alt::IVehicle::SetWindowOpened, py::arg("window_id"), py::arg("state")); 123 | pyClass.def("is_wheel_burst", &alt::IVehicle::IsWheelBurst, py::arg("wheel_id")); 124 | pyClass.def("does_wheel_has_tire", &alt::IVehicle::DoesWheelHasTire, py::arg("wheel_id")); 125 | pyClass.def("is_wheel_detached", &alt::IVehicle::IsWheelDetached, py::arg("wheel_id")); 126 | pyClass.def("is_wheel_on_fire", &alt::IVehicle::IsWheelOnFire, py::arg("wheel_id")); 127 | pyClass.def("get_wheel_health", &alt::IVehicle::GetWheelHealth, py::arg("wheel_id")); 128 | pyClass.def("set_wheel_health", &alt::IVehicle::SetWheelHealth, py::arg("wheel_id"), py::arg("health")); 129 | pyClass.def("get_part_damage_level", &GetPartDamageLevel, py::arg("part_id")); 130 | pyClass.def("get_part_bullet_holes", &alt::IVehicle::GetPartBulletHoles, py::arg("part_id")); 131 | pyClass.def("is_light_damaged", &alt::IVehicle::IsLightDamaged, py::arg("light_id")); 132 | pyClass.def("is_window_damaged", &alt::IVehicle::IsWindowDamaged, py::arg("window_id")); 133 | pyClass.def("is_special_light_damaged", &alt::IVehicle::IsSpecialLightDamaged, py::arg("special_light_id")); 134 | pyClass.def("get_armored_window_health", &alt::IVehicle::GetArmoredWindowHealth, py::arg("window_id")); 135 | pyClass.def("get_armored_window_shoot_count", &alt::IVehicle::GetArmoredWindowShootCount, py::arg("window_id")); 136 | pyClass.def("get_bumper_damage_level", &GetBumperDamageLevel, py::arg("bumper_id")); 137 | pyClass.def("repair", &alt::IVehicle::SetFixed); 138 | pyClass.def("set_wheels", &alt::IVehicle::SetWheels, py::arg("wheel_type"), py::arg("wheel_id")); 139 | pyClass.def("set_rear_wheels", &alt::IVehicle::SetRearWheels, py::arg("wheel_id")); 140 | pyClass.def("set_wheel_burst", &alt::IVehicle::SetWheelBurst, py::arg("wheel_id"), py::arg("state")); 141 | pyClass.def("set_wheel_has_tire", &alt::IVehicle::SetWheelHasTire, py::arg("wheel_id"), py::arg("state")); 142 | pyClass.def("set_wheel_detached", &alt::IVehicle::SetWheelDetached, py::arg("wheel_id"), py::arg("state")); 143 | pyClass.def("set_wheel_on_fire", &alt::IVehicle::SetWheelOnFire, py::arg("wheel_id"), py::arg("state")); 144 | pyClass.def("set_wheel_fixed", &alt::IVehicle::SetWheelFixed, py::arg("wheel_id")); 145 | pyClass.def("set_part_damage_level", &alt::IVehicle::SetPartDamageLevel, py::arg("part_id"), py::arg("level")); 146 | pyClass.def("set_part_bullet_holes", &alt::IVehicle::SetPartBulletHoles, py::arg("part_id"), py::arg("count")); 147 | pyClass.def("set_light_damaged", &alt::IVehicle::SetLightDamaged, py::arg("light_id"), py::arg("is_damaged")); 148 | pyClass.def("set_window_damaged", &alt::IVehicle::SetWindowDamaged, py::arg("window_id"), py::arg("is_damaged")); 149 | pyClass.def("set_special_light_damaged", &alt::IVehicle::SetSpecialLightDamaged, py::arg("special_light_id"), py::arg("is_damaged")); 150 | pyClass.def("set_armored_window_health", &alt::IVehicle::SetArmoredWindowHealth, py::arg("window_id"), py::arg("health")); 151 | pyClass.def("set_armored_window_shoot_count", &alt::IVehicle::SetArmoredWindowShootCount, py::arg("window_id"), py::arg("count")); 152 | pyClass.def("set_bumper_damage_level", &alt::IVehicle::SetBumperDamageLevel, py::arg("bumper_id"), py::arg("level")); 153 | pyClass.def("set_search_light_to", &SetSearchLightTo, py::arg("entity"), py::arg("state")); 154 | pyClass.def("set_timed_explosion", &alt::IVehicle::SetTimedExplosion, py::arg("state"), py::arg("culprit"), py::arg("time")); 155 | pyClass.def("get_weapon_capacity", &alt::IVehicle::GetWeaponCapacity, py::arg("weapon_index")); 156 | pyClass.def("set_weapon_capacity", &alt::IVehicle::SetWeaponCapacity, py::arg("weapon_index"), py::arg("capacity")); 157 | 158 | pyClass.def_property("modkit", &alt::IVehicle::GetModKit, &alt::IVehicle::SetModKit); 159 | pyClass.def_property("primary_color", &alt::IVehicle::GetPrimaryColor, &alt::IVehicle::SetPrimaryColor); 160 | pyClass.def_property("primary_color_rgb", &alt::IVehicle::GetPrimaryColorRGB, &alt::IVehicle::SetPrimaryColorRGB); 161 | pyClass.def_property("secondary_color", &alt::IVehicle::GetSecondaryColor, &alt::IVehicle::SetSecondaryColor); 162 | pyClass.def_property("secondary_color_rgb", &alt::IVehicle::GetSecondaryColorRGB, &alt::IVehicle::SetSecondaryColorRGB); 163 | pyClass.def_property("pearl_color", &alt::IVehicle::GetPearlColor, &alt::IVehicle::SetPearlColor); 164 | pyClass.def_property("wheel_color", &alt::IVehicle::GetWheelColor, &alt::IVehicle::SetWheelColor); 165 | pyClass.def_property("interior_color", &alt::IVehicle::GetInteriorColor, &alt::IVehicle::SetInteriorColor); 166 | pyClass.def_property("dashboard_color", &alt::IVehicle::GetDashboardColor, &alt::IVehicle::SetDashboardColor); 167 | pyClass.def_property("tire_smoke_color", &alt::IVehicle::GetTireSmokeColor, &alt::IVehicle::SetTireSmokeColor); 168 | pyClass.def_property("custom_tires", &alt::IVehicle::GetCustomTires, &alt::IVehicle::SetCustomTires); 169 | pyClass.def_property("darkness", &alt::IVehicle::GetSpecialDarkness, &alt::IVehicle::SetSpecialDarkness); 170 | pyClass.def_property("number_plate_index", &GetNumberplateIndex, &alt::IVehicle::SetNumberplateIndex); 171 | pyClass.def_property("number_plate_text", &alt::IVehicle::GetNumberplateText, &alt::IVehicle::SetNumberplateText); 172 | pyClass.def_property("window_tint", &GetWindowTint, &alt::IVehicle::SetWindowTint); 173 | pyClass.def_property("dirt_level", &alt::IVehicle::GetDirtLevel, &alt::IVehicle::SetDirtLevel); 174 | pyClass.def_property("neon", &GetNeonActive, &SetNeonActive); 175 | pyClass.def_property("neon_color", &alt::IVehicle::GetNeonColor, &alt::IVehicle::SetNeonColor); 176 | pyClass.def_property("livery", &alt::IVehicle::GetLivery, &alt::IVehicle::SetLivery); 177 | pyClass.def_property("roof_livery", &alt::IVehicle::GetRoofLivery, &alt::IVehicle::SetRoofLivery); 178 | pyClass.def_property("game_state_base64", &alt::IVehicle::GetGameStateBase64, &alt::IVehicle::LoadGameStateFromBase64); 179 | pyClass.def_property("appearance_data_base64", &alt::IVehicle::GetAppearanceDataBase64, &alt::IVehicle::LoadAppearanceDataFromBase64); 180 | pyClass.def_property("health_data_base64", &alt::IVehicle::GetHealthDataBase64, &alt::IVehicle::LoadHealthDataFromBase64); 181 | pyClass.def_property("damage_data_base64", &alt::IVehicle::GetDamageDataBase64, &alt::IVehicle::LoadDamageDataFromBase64); 182 | pyClass.def_property("script_data_base64", &alt::IVehicle::GetScriptDataBase64, &alt::IVehicle::LoadScriptDataFromBase64); 183 | pyClass.def_property("engine_on", &alt::IVehicle::IsEngineOn, &alt::IVehicle::SetEngineOn); 184 | pyClass.def_property("headlight_color", &alt::IVehicle::GetHeadlightColor, &alt::IVehicle::SetHeadlightColor); 185 | pyClass.def_property("active_radio_station", &GetRadioStationIndex, &alt::IVehicle::SetRadioStationIndex); 186 | pyClass.def_property("siren_active", &alt::IVehicle::IsSirenActive, &alt::IVehicle::SetSirenActive); 187 | pyClass.def_property("lock_state", &GetLockState, &alt::IVehicle::SetLockState); 188 | pyClass.def_property("roof_state", &alt::IVehicle::GetRoofState, &alt::IVehicle::SetRoofState); 189 | pyClass.def_property("lights_multiplier", &alt::IVehicle::GetLightsMultiplier, &alt::IVehicle::SetLightsMultiplier); 190 | pyClass.def_property("engine_health", &alt::IVehicle::GetEngineHealth, &alt::IVehicle::SetEngineHealth); 191 | pyClass.def_property("petrol_tank_health", &alt::IVehicle::GetPetrolTankHealth, &alt::IVehicle::SetPetrolTankHealth); 192 | pyClass.def_property("body_health", &alt::IVehicle::GetBodyHealth, &alt::IVehicle::SetBodyHealth); 193 | pyClass.def_property("body_additional_health", &alt::IVehicle::GetBodyAdditionalHealth, &alt::IVehicle::SetBodyAdditionalHealth); 194 | pyClass.def_property("manual_engine_control", &alt::IVehicle::IsManualEngineControl, &alt::IVehicle::SetManualEngineControl); 195 | pyClass.def_property("drift_mode_enabled", &alt::IVehicle::IsDriftMode, &alt::IVehicle::SetDriftMode); 196 | pyClass.def_property("is_mission_train", &alt::IVehicle::IsTrainMissionTrain, &alt::IVehicle::SetTrainMissionTrain); 197 | pyClass.def_property("is_train_engine", &alt::IVehicle::IsTrainEngine, &alt::IVehicle::SetTrainIsEngine); 198 | pyClass.def_property("train_track_id", &alt::IVehicle::GetTrainTrackId, &alt::IVehicle::SetTrainTrackId); 199 | pyClass.def_property("train_engine_id", &alt::IVehicle::GetTrainEngineId, &alt::IVehicle::SetTrainEngineId); 200 | pyClass.def_property("train_config_index", &alt::IVehicle::GetTrainConfigIndex, &alt::IVehicle::SetTrainConfigIndex); 201 | pyClass.def_property("train_distance_from_engine", &alt::IVehicle::GetTrainDistanceFromEngine, &alt::IVehicle::SetTrainDistanceFromEngine); 202 | pyClass.def_property("is_train_caboose", &alt::IVehicle::IsTrainCaboose, &alt::IVehicle::SetTrainIsCaboose); 203 | pyClass.def_property("train_direction", &alt::IVehicle::GetTrainDirection, &alt::IVehicle::SetTrainDirection); 204 | pyClass.def_property("train_passenger_carriages", &alt::IVehicle::HasTrainPassengerCarriages, &alt::IVehicle::SetTrainHasPassengerCarriages); 205 | pyClass.def_property("train_render_derailed", &alt::IVehicle::GetTrainRenderDerailed, &alt::IVehicle::SetTrainRenderDerailed); 206 | pyClass.def_property("train_force_doors_open", &alt::IVehicle::GetTrainForceDoorsOpen, &alt::IVehicle::SetTrainForceDoorsOpen); 207 | pyClass.def_property("train_cruise_speed", &alt::IVehicle::GetTrainCruiseSpeed, &alt::IVehicle::SetTrainCruiseSpeed); 208 | pyClass.def_property("train_carriage_config_index", &alt::IVehicle::GetTrainCarriageConfigIndex, &alt::IVehicle::SetTrainCarriageConfigIndex); 209 | pyClass.def_property("train_linked_to_backward_id", &alt::IVehicle::GetTrainLinkedToBackwardId, &alt::IVehicle::SetTrainLinkedToBackwardId); 210 | pyClass.def_property("train_linked_to_forward_id", &alt::IVehicle::GetTrainLinkedToForwardId, &alt::IVehicle::SetTrainLinkedToForwardId); 211 | pyClass.def_property("train_unk1", &alt::IVehicle::GetTrainUnk1, &alt::IVehicle::SetTrainUnk1); 212 | pyClass.def_property("train_unk2", &alt::IVehicle::GetTrainUnk2, &alt::IVehicle::SetTrainUnk2); 213 | pyClass.def_property("train_unk3", &alt::IVehicle::GetTrainUnk3, &alt::IVehicle::SetTrainUnk3); 214 | pyClass.def_property("boat_anchor_active", &alt::IVehicle::IsBoatAnchorActive, &alt::IVehicle::SetBoatAnchorActive); 215 | pyClass.def_property("light_state", &alt::IVehicle::GetLightState, &alt::IVehicle::SetLightState); 216 | pyClass.def_property("is_towing_disabled", &alt::IVehicle::IsTowingDisabled, &alt::IVehicle::SetDisableTowing); 217 | pyClass.def_property("rocket_refuel_speed", &alt::IVehicle::GetRocketRefuelSpeed, &alt::IVehicle::SetRocketRefuelSpeed); 218 | pyClass.def_property("bomb_count", &alt::IVehicle::GetBombCount, &alt::IVehicle::SetBombCount); 219 | pyClass.def_property("counter_measure_count", &alt::IVehicle::GetCounterMeasureCount, &alt::IVehicle::SetCounterMeasureCount); 220 | pyClass.def_property("script_max_speed", &alt::IVehicle::GetScriptMaxSpeed, &alt::IVehicle::SetScriptMaxSpeed); 221 | pyClass.def_property("weapons_disabled", &alt::IVehicle::GetWeaponsDisabled, &alt::IVehicle::SetWeaponsDisabled); 222 | pyClass.def_property("hybrid_extra_active", &alt::IVehicle::GetHybridExtraActive, &alt::IVehicle::SetHybridExtraActive); 223 | pyClass.def_property("hybrid_extra_state", &alt::IVehicle::GetHybridExtraState, &alt::IVehicle::SetHybridExtraState); 224 | pyClass.def_property("damage_modifier", &alt::IVehicle::GetDamageModifier, &alt::IVehicle::SetDamageModifier); 225 | pyClass.def_property("damage_multiplier", &alt::IVehicle::GetDamageMultiplier, &alt::IVehicle::SetDamageMultiplier); 226 | 227 | pyClass.def_property_readonly("driver", &alt::IVehicle::GetDriver); 228 | pyClass.def_property_readonly("destroyed", &alt::IVehicle::IsDestroyed); 229 | pyClass.def_property_readonly("modkits_count", &alt::IVehicle::GetModKitsCount); 230 | pyClass.def_property_readonly("is_primary_color_rgb", &alt::IVehicle::IsPrimaryColorRGB); 231 | pyClass.def_property_readonly("is_secondary_color_rgb", &alt::IVehicle::IsSecondaryColorRGB); 232 | pyClass.def_property_readonly("is_tire_smoke_color_custom", &alt::IVehicle::IsTireSmokeColorCustom); 233 | pyClass.def_property_readonly("wheel_type", &alt::IVehicle::GetWheelType); 234 | pyClass.def_property_readonly("front_wheels", &alt::IVehicle::GetWheelVariation); 235 | pyClass.def_property_readonly("rear_wheels", &alt::IVehicle::GetRearWheelVariation); 236 | pyClass.def_property_readonly("neon_active", &alt::IVehicle::IsNeonActive); 237 | pyClass.def_property_readonly("handbrake_active", &alt::IVehicle::IsHandbrakeActive); 238 | pyClass.def_property_readonly("daylight_on", &alt::IVehicle::IsDaylightOn); 239 | pyClass.def_property_readonly("nightlight_on", &alt::IVehicle::IsNightlightOn); 240 | pyClass.def_property_readonly("flamethrower_active", &alt::IVehicle::IsFlamethrowerActive); 241 | pyClass.def_property_readonly("wheels_count", &alt::IVehicle::GetWheelsCount); 242 | pyClass.def_property_readonly("repairs_count", &alt::IVehicle::GetRepairsCount); 243 | pyClass.def_property_readonly("has_armored_windows", &alt::IVehicle::HasArmoredWindows); 244 | pyClass.def_property_readonly("velocity", &GetVelocity); 245 | pyClass.def_property_readonly("attached", &alt::IVehicle::GetAttached); 246 | pyClass.def_property_readonly("attached_to", &alt::IVehicle::GetAttachedTo); 247 | pyClass.def_property_readonly("has_timed_explosion", &alt::IVehicle::HasTimedExplosion); 248 | pyClass.def_property_readonly("timed_explosion_culprit", &alt::IVehicle::GetTimedExplosionCulprit); 249 | pyClass.def_property_readonly("timed_explosion_time", &alt::IVehicle::GetTimedExplosionTime); 250 | } 251 | -------------------------------------------------------------------------------- /src/classes/types/enums.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | enum class WeatherType : uint32_t 6 | { 7 | ExtraSunny, 8 | Clear, 9 | Clouds, 10 | Smog, 11 | Foggy, 12 | Overcast, 13 | Rain, 14 | Thunder, 15 | Clearing, 16 | Neutral, 17 | Snow, 18 | Blizzard, 19 | Snowlight, 20 | Xmas, 21 | Halloween, 22 | }; 23 | 24 | enum class WeaponTint : uint32_t 25 | { 26 | Normal, 27 | Green, 28 | Gold, 29 | Pink, 30 | Army, 31 | LSPD, 32 | Orange, 33 | Platinum 34 | }; 35 | 36 | enum class VehicleModType : uint8_t 37 | { 38 | Spoiler, 39 | FrontBumper, 40 | RearBumper, 41 | SideSkirt, 42 | Exhaust, 43 | Frame, 44 | Grille, 45 | Hood, 46 | Fender, 47 | RightFender, 48 | Roof, 49 | Engine, 50 | Brakes, 51 | Transmission, 52 | Horn, 53 | Suspension, 54 | Armor, 55 | Unk1, 56 | Turbo, 57 | Unk2, 58 | TireSmoke, 59 | Unk3, 60 | XenonLights, 61 | FrontWheels, 62 | BackWheels, 63 | Plateholder, 64 | VanityPlates, 65 | TrimDesign, 66 | Ornaments, 67 | Dashboard, 68 | Dial, 69 | DoorSpeaker, 70 | Seats, 71 | SteeringWheel, 72 | ColumnShifterLeavers, 73 | Plaques, 74 | Speakers, 75 | Trunk, 76 | Hydraulics, 77 | EngineBlock, 78 | AirFilter, 79 | Struts, 80 | ArchCover, 81 | Aerials, 82 | Trim, 83 | Tank, 84 | Windows, 85 | Unk4, 86 | Livery, 87 | }; 88 | 89 | enum class WindowTint : uint8_t 90 | { 91 | DarkSmoke, 92 | Green, 93 | LightSmoke, 94 | Limo, 95 | Clear, 96 | PureBlack, 97 | Stock 98 | }; 99 | 100 | enum class RadioStation : uint32_t 101 | { 102 | Nothing, 103 | RadioOff, 104 | MediaPlayer, 105 | TheMusicLocker, 106 | MotoMami, 107 | BlueArk, 108 | WorldWideFM, 109 | FlyLoFM, 110 | TheLowdown, 111 | TheLab, 112 | RadioMirrorPark, 113 | KultFM, 114 | Space, 115 | VinewoodBoulevardRadio, 116 | Blonded, 117 | LosSantosUndergroundRadio, 118 | iFruitRadio, 119 | LosSantosRockRadio, 120 | NonStopPopFM, 121 | RadioLosSantos, 122 | ChannelX, 123 | WestCoastTalkRadio, 124 | RebelRadio, 125 | SoulwaxFM, 126 | EastLosFM, 127 | WestCoastClassics 128 | }; 129 | 130 | enum class VehicleLockState : uint8_t 131 | { 132 | Nothing, 133 | Unlocked, 134 | Locked, 135 | LockoutPlayerOnly, 136 | LockPlayerInside, 137 | InitiallyLocked, 138 | ForceDoorsShut, 139 | LockedCanBeDamaged, 140 | }; 141 | 142 | enum class VehicleDoor : uint8_t 143 | { 144 | DriverFront, 145 | PassengerFront, 146 | DriverRear, 147 | PassengerRear, 148 | Hood, 149 | Trunk, 150 | }; 151 | 152 | enum class VehicleDoorState : uint8_t 153 | { 154 | Closed, 155 | OpenedLevel1, 156 | OpenedLevel2, 157 | OpenedLevel3, 158 | OpenedLevel4, 159 | OpenedLevel5, 160 | OpenedLevel6, 161 | OpenedLevel7, 162 | Unknown = 255, 163 | }; 164 | 165 | enum class VehiclePart : uint8_t 166 | { 167 | FrontLeft, 168 | FrontRight, 169 | MiddleLeft, 170 | MiddleRight, 171 | RearLeft, 172 | RearRight, 173 | }; 174 | 175 | enum class VehiclePartDamage : uint8_t 176 | { 177 | NotDamaged, 178 | DamagedLevel1, 179 | DamagedLevel2, 180 | DamagedLevel3, 181 | }; 182 | 183 | enum class VehicleBumper : uint8_t 184 | { 185 | Front, 186 | Rear, 187 | }; 188 | 189 | enum class VehicleBumperDamage : uint8_t 190 | { 191 | NotDamaged, 192 | Damaged, 193 | Nothing, 194 | }; 195 | 196 | enum class NumberPlateStyle : uint32_t 197 | { 198 | BlueWhite, 199 | BlueWhite2, 200 | BlueWhite3, 201 | Yankton, 202 | YellowBlack, 203 | YellowBlue 204 | }; 205 | 206 | enum class Event : uint16_t 207 | { 208 | ServerStarted = 1, 209 | 210 | PlayerConnect, 211 | PlayerBeforeConnect, 212 | PlayerDisconnect, 213 | PlayerConnectDenied, 214 | 215 | ConnectionQueueAdd, 216 | ConnectionQueueRemove, 217 | 218 | ResourceStart, 219 | ResourceStop, 220 | ResourceError, 221 | 222 | SyncedMetaChange = 13, 223 | StreamSyncedMetaChange, 224 | GlobalMetaChange, 225 | GlobalSyncedMetaChange, 226 | LocalMetaChange, 227 | 228 | PlayerDamage, 229 | PlayerDeath, 230 | Fire, 231 | Explosion, 232 | StartProjectile, 233 | WeaponDamage, 234 | VehicleDestroy, 235 | VehicleDamage, 236 | 237 | ColShape = 27, 238 | 239 | PlayerEnterVehicle, 240 | PlayerEnteringVehicle, 241 | PlayerLeftVehicle, 242 | PlayerChangeVehicleSeat, 243 | PlayerWeaponChange, 244 | PlayerRequestControl, 245 | 246 | VehicleAttach, 247 | VehicleDetach, 248 | NetOwnerChange, 249 | 250 | RemoveEntity, 251 | 252 | ConsoleCommand = 41, 253 | 254 | PlayerAnimationChange, 255 | PlayerInteriorChange 256 | }; 257 | 258 | enum class ExplosionType : int8_t 259 | { 260 | Grenade, 261 | GrenadeLauncher, 262 | StickyBomb, 263 | Molotov, 264 | Rocket, 265 | TankShell, 266 | HiOctane, 267 | Car, 268 | Plane, 269 | PetrolPump, 270 | Bike, 271 | DirSteam, 272 | DirFlame, 273 | DirWaterHydrant, 274 | DirGasCanister, 275 | Boat, 276 | ShipDestroy, 277 | Truck, 278 | Bullet, 279 | SmokeGrenadeLauncher, 280 | SmokeGrenade, 281 | BzGas, 282 | Flare, 283 | GasCanister, 284 | Extinguisher, 285 | ProgrammableAr, 286 | Train, 287 | Barrel, 288 | Propane, 289 | Blimp, 290 | DirFlameExplode, 291 | Tanker, 292 | PlaneRocket, 293 | VehicleBullet, 294 | GasTank, 295 | Firework, 296 | Snowball, 297 | ProxMine, 298 | ValkyrieCannon, 299 | Unknown = -1, 300 | }; 301 | 302 | enum class BodyPart : int8_t 303 | { 304 | Pelvis, 305 | LeftHip, 306 | LeftLeg, 307 | LeftFoot, 308 | RightHip, 309 | RightLeg, 310 | RightFoot, 311 | LowerTorso, 312 | UpperTorso, 313 | Chest, 314 | UnderNeck, 315 | LeftShoulder, 316 | LeftUpperArm, 317 | LeftElbrow, 318 | LeftWrist, 319 | RightShoulder, 320 | RightUpperArm, 321 | RightElbrow, 322 | RightWrist, 323 | Neck, 324 | Head, 325 | Unknown = -1, 326 | }; 327 | 328 | enum class VehicleType : uint8_t 329 | { 330 | Invalid, 331 | Ped, 332 | Automobile, 333 | Plane, 334 | Trailer, 335 | QuadBike, 336 | SubmarineCar, 337 | AmphibiousAutomobile, 338 | AmphibiousQuadBike, 339 | Heli, 340 | Blimp, 341 | AutoGyro, 342 | Bike, 343 | BMX, 344 | Boat, 345 | Train, 346 | Submarine, 347 | Object 348 | }; 349 | 350 | enum class ColShapeType : uint8_t 351 | { 352 | Sphere, 353 | Cylinder, 354 | Circle, 355 | Cuboid, 356 | Rect, 357 | CheckpointCylinder, 358 | Polygon 359 | }; 360 | 361 | enum class BaseObjectType : uint8_t 362 | { 363 | Player, 364 | Vehicle, 365 | Blip, 366 | WebView, 367 | VoiceChannel, 368 | ColShape, 369 | Checkpoint, 370 | WebSocketClient, 371 | HttpClient, 372 | Audio, 373 | RmlElement, 374 | RmlDocument, 375 | LocalPlayer 376 | }; 377 | 378 | enum class BlipColor : int 379 | { 380 | White, 381 | Red, 382 | Green, 383 | Blue, 384 | Yellow = 5, 385 | LightRed, 386 | Violet, 387 | Pink, 388 | LightOrange, 389 | LightBrown, 390 | LightGreen, 391 | LightBlue, 392 | LightPurple, 393 | DarkPurple, 394 | Cyan, 395 | LightYellow, 396 | Organe, 397 | DarkPink = 19, 398 | GraniteGreen, 399 | DarkBrown, 400 | LightGray, 401 | LightPink, 402 | LemonGreen, 403 | ForestGreen, 404 | ElectricBlue, 405 | BrightPurple, 406 | DarkYellow, 407 | DarkCyan = 30, 408 | Beige = 36, 409 | DarkGray = 40, 410 | PinkRed, 411 | Gold = 46, 412 | Orange, 413 | BrilliantRose, 414 | MediumPurple = 50, 415 | Salmon, 416 | DarkGreen, 417 | BlizzardBlue, 418 | OracleBlue, 419 | Silver, 420 | EastBay = 58, 421 | YellowOrange = 60, 422 | MulberryPink, 423 | AltoGray, 424 | JellyBeanBlue, 425 | DarkOrange, 426 | Mamba, 427 | Default, 428 | TransparentBlack = 72, 429 | DeepRed = 76, 430 | TransparentRed = 79, 431 | TransparentBlue = 80, 432 | Purple = 83, 433 | }; 434 | 435 | enum class BlipSprite : int 436 | { 437 | Higher, 438 | Lower, 439 | PolicePed, 440 | WantedRadius, 441 | Area, 442 | Centre, 443 | North, 444 | Waypoint, 445 | Radius, 446 | RadiusOutline, 447 | WeaponHigher, 448 | WeaponLower, 449 | HigherAI, 450 | LowerAI, 451 | PoliceHeliSpin, 452 | PolicePlaneMove, 453 | MPCrew = 27, 454 | MPFriendlies, 455 | CableCar = 36, 456 | Activities, 457 | Raceflag, 458 | Safehouse = 40, 459 | Police, 460 | PoliceChase, 461 | PoliceHeli, 462 | BombA, 463 | Snitch = 47, 464 | PlanningLocations, 465 | CriminalCarsteal = 50, 466 | CriminalDrugs, 467 | CriminalHoldups, 468 | CriminalPlayer = 54, 469 | CopPatrol = 56, 470 | CopPlayer, 471 | CriminalWanted, 472 | Heist, 473 | PoliceStation, 474 | Hospital, 475 | AssassinsMark, 476 | Elevator, 477 | Helicopter, 478 | RandomCharacter = 66, 479 | SecurityVan, 480 | TowTruck, 481 | IllegalParking = 70, 482 | Barber, 483 | CarModShop, 484 | ClothesStore, 485 | Tattoo = 75, 486 | ArmenianFamily, 487 | LesterFamily, 488 | MichaelFamily, 489 | TrevorFamily, 490 | JewelryHeist, 491 | DragRaceFinish = 82, 492 | Rampage = 84, 493 | VinewoodTours, 494 | LamarFamily, 495 | FranklinFamily = 88, 496 | ChineseStrand, 497 | FlightSchool, 498 | EyeSky, 499 | AirHockey, 500 | Bar, 501 | BaseJump, 502 | Basketball, 503 | BiolabHeist = 96, 504 | CabaretClub = 99, 505 | CarWash, 506 | ComedyClub = 102, 507 | Darts, 508 | DocksHeist, 509 | FbiHeist, 510 | FbiOfficersStrand, 511 | FinaleBankHeist, 512 | FinancierStrand, 513 | Golf, 514 | GunShop, 515 | InternetCafe, 516 | MichaelFamilyExile, 517 | NiceHouseHeist, 518 | RandomFemale, 519 | RandomMale, 520 | RuralBankHeist = 118, 521 | ShootingRange, 522 | SolomonStrand, 523 | StripClub, 524 | Tennis, 525 | TrevorFamilyExile, 526 | MichaelTrevorFamily, 527 | Triathlon = 126, 528 | OffRoadRacing, 529 | GangCops, 530 | GangMexicans, 531 | GangBikers, 532 | SnitchRed = 133, 533 | CriminalCuffKeys, 534 | Cinema, 535 | MusicVenue, 536 | PoliceStationBlue, 537 | Airport, 538 | CriminalSavedVehicle, 539 | WeedStash, 540 | Hunting, 541 | Pool, 542 | ObjectiveBlue, 543 | ObjectiveGreen, 544 | ObjectiveRed, 545 | ObjectiveYellow, 546 | ArmsDealing, 547 | MPFriend, 548 | CelebrityTheft, 549 | WeaponAssaultRifle, 550 | WeaponBat, 551 | WeaponGrenade, 552 | WeaponHealth, 553 | WeaponKnife, 554 | WeaponMolotov, 555 | WeaponPistol, 556 | WeaponRocket, 557 | WeaponShotgun, 558 | WeaponSmg, 559 | WeaponSniper, 560 | MPNoise, 561 | PointOfInterest, 562 | Passive, 563 | UsingMenu, 564 | GangCopsPartner = 171, 565 | WeaponMinigun = 173, 566 | WeaponArmour = 175, 567 | PropertyTakeover, 568 | GangMexicansHighlight, 569 | GangBikersHighlight, 570 | TriathlonCycling, 571 | TriathlonSwimming, 572 | PropertyTakeoverBikers, 573 | PropertyTakeoverCops, 574 | PropertyTakeoverVagos, 575 | Camera, 576 | CentreRed, 577 | HandcuffKeysBikers, 578 | HandcuffKeysVagos, 579 | HandcuffsClosedBikers, 580 | HandcuffsClosedVagos, 581 | CameraBadger = 192, 582 | CameraFacade, 583 | CameraIfruit, 584 | Yoga = 197, 585 | Taxi, 586 | Shrink = 205, 587 | Epsilon, 588 | FinancierStrandGrey, 589 | TrevorFamilyGrey, 590 | TrevorFamilyRed, 591 | FranklinFamilyGrey, 592 | FranklinFamilyBlue, 593 | FranklinA, 594 | FranklinB, 595 | FranklinC, 596 | GangVehicle = 225, 597 | GangVehicleBikers, 598 | GangVehicleCops, 599 | GangVehicleVagos, 600 | Guncar, 601 | DrivingBikers, 602 | DrivingCops, 603 | DrivingVagos, 604 | GangCopsHighlight, 605 | ShieldBikers, 606 | ShieldCops = 235, 607 | ShieldVagos, 608 | CustodyBikers, 609 | CustodyVagos, 610 | ArmsDealingAir = 251, 611 | PlayerStateArrested, 612 | PlayerStateCustody, 613 | PlayerStateDriving, 614 | PlayerStateKeyholder, 615 | PlayerStatePartner, 616 | Ztype = 262, 617 | Stinger, 618 | Packer, 619 | Monroe, 620 | Fairground, 621 | Property, 622 | GangHighlight, 623 | Altruist, 624 | AI, 625 | OnMission, 626 | CashPickup, 627 | Chop, 628 | Dead, 629 | TerritoryLocked, 630 | CashLost, 631 | CashVagos, 632 | CashCops, 633 | Hooker, 634 | Friend, 635 | Mission2to4, 636 | Mission2to8, 637 | Mission2to12, 638 | Mission2to16, 639 | CustodyDropOff, 640 | OnMissionCops, 641 | OnMissionLost, 642 | OnMissionVagos, 643 | CriminalCarStealCops, 644 | CriminalCarStealBikers, 645 | CriminalCarStealVagos, 646 | BandStrand, 647 | SimeonFamily, 648 | Mission1, 649 | Mission2, 650 | FriendDarts, 651 | FriendComedyClub, 652 | FriendCinema, 653 | FriendTennis, 654 | FriendStripClub, 655 | FriendLiveMusic, 656 | FriendGolf, 657 | BountyHit, 658 | UgcMission, 659 | Horde, 660 | CrateDrop, 661 | PlaneDrop, 662 | Sub, 663 | Race, 664 | Deathmatch, 665 | ArmWrestling, 666 | Mission1to2, 667 | ShootingRangeGunShop, 668 | RaceAir, 669 | RaceLand, 670 | RaceSea, 671 | Tow, 672 | Garbage, 673 | Drill, 674 | Spikes, 675 | Firetruck, 676 | Minigun2, 677 | Bugstar, 678 | Submarine, 679 | Chinook, 680 | GetawayCar, 681 | MissionBikers1, 682 | MissionBikers1to2, 683 | MissionBikers2, 684 | MissionBikers2to4, 685 | MissionBikers2to8, 686 | MissionBikers2to12, 687 | MissionBikers2to16, 688 | MissionCops1, 689 | MissionCops1to2, 690 | MissionCops2, 691 | MissionCops2to4, 692 | MissionCops2to8, 693 | MissionCops2to12, 694 | MissionCops2to16, 695 | MissionVagos1, 696 | MissionVagos1to2, 697 | MissionVagos2, 698 | MissionVagos2to4, 699 | MissionVagos2to8, 700 | MissionVagos2to12, 701 | MissionVagos2to16, 702 | GangBike, 703 | GasGrenade, 704 | PropertyForSale, 705 | GangAttackPackage, 706 | MartinMadrazzo, 707 | EnemyHeliSpin, 708 | Boost, 709 | Devin, 710 | Dock, 711 | Garage, 712 | GolfFlag, 713 | Hangar, 714 | Helipad, 715 | JerryCan, 716 | Mask, 717 | HeistPrep, 718 | Incapacitated, 719 | SpawnPointPickup, 720 | Boilersuit, 721 | Completed, 722 | Rockets, 723 | GarageForSale, 724 | HelipadForSale, 725 | DockForSale, 726 | HangarForSale, 727 | Placeholder6, 728 | Business, 729 | BusinessForSale, 730 | RaceBike, 731 | Parachute, 732 | TeamDeathmatch, 733 | RaceFoot, 734 | VehicleDeathmatch, 735 | Barry, 736 | Dom, 737 | Maryann, 738 | Cletus, 739 | Josh, 740 | Minute, 741 | Omega, 742 | Tonya, 743 | Paparazzo, 744 | Aim, 745 | CrateDropBackground, 746 | GreenAndNetPlayer1, 747 | GreenAndNetPlayer2, 748 | GreenAndNetPlayer3, 749 | GreenAndFriendly, 750 | NetPlayer1AndNetPlayer2, 751 | NetPlayer1AndNetPlayer3, 752 | Creator, 753 | CreatorDirection, 754 | Abigail, 755 | Blimp, 756 | Repair, 757 | Testosterone, 758 | Dinghy, 759 | Fanatic, 760 | InfoIcon = 407, 761 | CaptureTheFlag, 762 | LastTeamStanding, 763 | Boat, 764 | CaptureTheFlagBase, 765 | CaptureTheFlagOutline = 413, 766 | CaptureTheFlagBaseNoBag, 767 | WeaponJerrycan, 768 | Rp, 769 | LevelInside, 770 | BountyHitInside, 771 | CaptureTheUSAFlag, 772 | CaptureTheUSAFlagOutline, 773 | Tank, 774 | PlayerHeli, 775 | PlayerPlane, 776 | PlayerJet, 777 | CentreStroke, 778 | PlayerGunCar, 779 | PlayerBoat, 780 | MPHeist, 781 | Temp1, 782 | Temp2, 783 | Temp3, 784 | Temp4, 785 | Temp5, 786 | Temp6, 787 | RaceStunt, 788 | HotProperty, 789 | UrbanWarfareVersus, 790 | KingOfTheCastle, 791 | PlayerKing, 792 | DeadDrop, 793 | PennedIn, 794 | Beast, 795 | EdgePointer, 796 | EdgeCrossTheLine, 797 | MPLamar, 798 | Bennys, 799 | CornerNumber1, 800 | CornerNumber2, 801 | CornerNumber3, 802 | CornerNumber4, 803 | CornerNumber5, 804 | CornerNumber6, 805 | CornerNumber7, 806 | CornerNumber8, 807 | Yacht, 808 | FindersKeepers, 809 | AssaultPackage, 810 | HuntTheBoss, 811 | Sightseer, 812 | TurretedLimo, 813 | BellyOfTheBeast, 814 | YachtLocation, 815 | PickupBeast, 816 | PickupZoned, 817 | PickupRandom, 818 | PickupSlowTime, 819 | PickupSwap, 820 | PickupThermal, 821 | PickupWeed, 822 | WeaponRailgun, 823 | Seashark, 824 | PickupHidden, 825 | Warehouse, 826 | WarehouseForSale, 827 | Office, 828 | OfficeForSale, 829 | Truck, 830 | Contraband, 831 | Trailer, 832 | VIP, 833 | Cargobob, 834 | AreaOutline, 835 | PickupAccelerator, 836 | PickupGhost, 837 | PickupDetonator, 838 | PickupBomb, 839 | PickupArmoured, 840 | Stunt, 841 | WeaponLives, 842 | StuntPremium, 843 | Adversary, 844 | BikerClubhouse, 845 | BikerCagedIn, 846 | BikerTurfWar, 847 | BikerJoust, 848 | ProductionWeed, 849 | ProductionCrack, 850 | ProductionFakeId, 851 | ProductionMeth, 852 | ProductionMoney, 853 | Package, 854 | Capture1, 855 | Capture2, 856 | Capture3, 857 | Capture4, 858 | Capture5, 859 | Capture6, 860 | Capture7, 861 | Capture8, 862 | Capture9, 863 | Capture10, 864 | Quad, 865 | Bus, 866 | DrugsPackage, 867 | PickupJump, 868 | Adversary4, 869 | Adversary8, 870 | Adversary10, 871 | Adversary12, 872 | Adversary16, 873 | Laptop, 874 | PickupDeadline, 875 | SportsCar, 876 | WarehouseVehicle, 877 | RegPapers, 878 | PoliceStationDropoff, 879 | Junkyard, 880 | ExVech1, 881 | ExVech2, 882 | ExVech3, 883 | ExVech4, 884 | ExVech5, 885 | ExVech6, 886 | ExVech7, 887 | TargetA, 888 | TargetB, 889 | TargetC, 890 | TargetD, 891 | TargetE, 892 | TargetF, 893 | TargetG, 894 | TargetH, 895 | Juggernaut, 896 | PickupRepair, 897 | SteeringWheel, 898 | Trophy, 899 | PickupRocketBoost, 900 | PickupHomingRocket, 901 | PickupMachinegun, 902 | PickupParachute, 903 | PickupTime5, 904 | PickupTime10, 905 | PickupTime15, 906 | PickupTime20, 907 | PickupTime30, 908 | Supplies, 909 | PropertyBunker, 910 | GrWvm1, 911 | GrWvm2, 912 | GrWvm3, 913 | GrWvm4, 914 | GrWvm5, 915 | GrWvm6, 916 | GrCovertOps, 917 | AdversaryBunker, 918 | GrMocUpgrade, 919 | GrWUpgrade, 920 | SmCargo, 921 | SmHangar, 922 | TfCheckpoint, 923 | RaceTf, 924 | SmWp1, 925 | SmWp2, 926 | SmWp3, 927 | SmWp4, 928 | SmWp5, 929 | SmWp6, 930 | SmWp7, 931 | SmWp8, 932 | SmWp9, 933 | SmWp10, 934 | SmWp11, 935 | SmWp12, 936 | SmWp13, 937 | SmWp14, 938 | NhpBag, 939 | NhpChest, 940 | NhpOrbit, 941 | NhpVeh1, 942 | NhpBase, 943 | NhpOverlay, 944 | NhpTurret, 945 | NhpMgFirewall, 946 | NhpMgNode, 947 | NhpWp1, 948 | NhpWp2, 949 | NhpWp3, 950 | NhpWp4, 951 | NhpWp5, 952 | NhpWp6, 953 | NhpWp7, 954 | NhpWp8, 955 | NhpWp9, 956 | NhpCCTV, 957 | NhpStarterpack, 958 | NhpTurretConsole, 959 | NhpMgMirRotate, 960 | NhpMgMirStatic, 961 | NhpMgProxy, 962 | AcsrRaceTarget, 963 | AcsrRaceHotring, 964 | AcsrWp1, 965 | AcsrWp2, 966 | BatClubProperty, 967 | BatCargo, 968 | BatTruck, 969 | BatHackJewel, 970 | BatHackGold, 971 | BatKeypad, 972 | BatHackTarget, 973 | PickupDtbHealth, 974 | PickupDtbBlastIncrease, 975 | PickupDtbBlastDecrease, 976 | PickupDtbBombIncrease, 977 | PickupDtbBombDecrease, 978 | BatRivalClub, 979 | BatDrone, 980 | BatCashReg, 981 | CCTV, 982 | BatAssassinate, 983 | BatPbus, 984 | BatWp1, 985 | BatWp2, 986 | BatWp3, 987 | BatWp4, 988 | BatWp5, 989 | BatWp6, 990 | Blimp2, 991 | Oppressor2, 992 | BatWp7, 993 | ArenaSeries, 994 | ArenaPremium, 995 | ArenaWorkshop, 996 | RaceWars, 997 | ArenaTurret, 998 | ArenaRCCar, 999 | ArenaRCWorkshop, 1000 | ArenaTrapFire, 1001 | ArenaTrapFlip, 1002 | ArenaTrapSea, 1003 | ArenaTrapTurn, 1004 | ArenaTrapPit, 1005 | ArenaTrapMine, 1006 | ArenaTrapBomb, 1007 | ArenaTrapWall, 1008 | ArenaTrapBrd, 1009 | ArenaTrapSbrd, 1010 | ArenaBruiser, 1011 | ArenaBrutus, 1012 | ArenaCerberus, 1013 | ArenaDeathbike, 1014 | ArenaDominator, 1015 | ArenaImpaler, 1016 | ArenaImperator, 1017 | ArenaIssi, 1018 | ArenaSasquatch, 1019 | ArenaScarab, 1020 | ArenaSlamvan, 1021 | ArenaZr, 1022 | }; 1023 | 1024 | enum class CheckpointType : uint8_t 1025 | { 1026 | CylinderSingleArrow, 1027 | CylinderDoubleArrow, 1028 | CylinderTripleArrow, 1029 | CylinderCycleArrow, 1030 | CylinderCheckerboard, 1031 | CylinderWrench, 1032 | CylinderSingleArrow2, 1033 | CylinderDoubleArrow2, 1034 | CylinderTripleArrow2, 1035 | CylinderCycleArrow2, 1036 | CylinderCheckerboard2, 1037 | CylinderWrench2, 1038 | RingSingleArrow, 1039 | RingDoubleArrow, 1040 | RingTripleArrow, 1041 | RingCycleArrow, 1042 | RingCheckerboard, 1043 | SingleArrow, 1044 | DoubleArrow, 1045 | TripleArrow, 1046 | CycleArrow, 1047 | Checkerboard, 1048 | CylinderSingleArrow3, 1049 | CylinderDoubleArrow3, 1050 | CylinderTripleArrow3, 1051 | CylinderCycleArrow3, 1052 | CylinderCheckerboard3, 1053 | CylinderSingleArrow4, 1054 | CylinderDoubleArrow4, 1055 | CylinderTripleArrow4, 1056 | CylinderCycleArrow4, 1057 | CylinderCheckerboard4, 1058 | CylinderSingleArrow5, 1059 | CylinderDoubleArrow5, 1060 | CylinderTripleArrow5, 1061 | CylinderCycleArrow5, 1062 | CylinderCheckerboard5, 1063 | RingPlaneUp, 1064 | RingPlaneLeft, 1065 | RingPlaneRight, 1066 | RingPlaneDown, 1067 | Empty, 1068 | Ring, 1069 | Empty2, 1070 | Cylinder, 1071 | Cylinder1, 1072 | Cylinder2, 1073 | Cylinder3, 1074 | Cylinder4, 1075 | Cylinder5, 1076 | Empty3, 1077 | Empty4, 1078 | Empty5, 1079 | Empty6, 1080 | RingDollar, 1081 | RingWolf, 1082 | RingQuestionMark, 1083 | RingPlane, 1084 | RingChopper, 1085 | RingBoat, 1086 | RingCar, 1087 | RingBike, 1088 | RingBicycle, 1089 | RingTruck, 1090 | RingParachute, 1091 | RingJetpack, 1092 | RingWhirl, 1093 | }; 1094 | 1095 | enum class ConnectDeniedReason : uint8_t { 1096 | WrongVersion, 1097 | WrongBranch, 1098 | DebugNotAllowed, 1099 | WrongPassword, 1100 | WrongCdnUrl 1101 | }; 1102 | --------------------------------------------------------------------------------