From 680c08781b80a959d88e5b922ac0a0124839cde6 Mon Sep 17 00:00:00 2001 From: Timo Date: Thu, 31 Aug 2023 19:03:37 +0200 Subject: [PATCH] refactor: split up altv package into multiple subpackages (#17) * refactor: split root package into smaller subpackages (WIP) * fix(factory): player entity & factory * chore(entity): disable base object tests * refactor(entity): shorter BaseObjectType enums * refactor: seperate io, import, export & permission * fix(event): rename package events to event * fix(mvalue): use current resource global var instead of resource name setter * chore(readme): useful build information * docs: contribution & troubleshooting guide * refactor: remove connectionInfo interface * feat(cmd): gencapi cli * docs: update c-api build explanation * chore: delete runtime/tools/pkg-capi.js (superseeded by cmd/gencapi) * fix(cmd): gencapi snake case * ci: publish go module on release & generate capi for go test * ci: only run in prs or on tracked branches * fix(scripts): windows capi build * ci: fix windows capi generate * ci: fix capi generate * ci: fix go test matrix * fix: some deep source code errors * ci: attempt to fix capi gen permissions * ci: attempt to fix permissions --- .github/workflows/build-c-api.yml | 106 - .github/workflows/build-deploy-module.yml | 139 - .github/workflows/publish-module.yml | 77 + .github/workflows/test-api.yml | 23 +- .github/workflows/test-module.yml | 3 + CONTRIBUTING.md | 51 + README.md | 28 +- TROUBLESHOOTING.md | 43 + altio/file.go | 41 + log.go => altlog/log.go | 18 +- base_object.go | 245 -- cgo.go | 9 + cmd/gencapi/body.tmpl | 27 + cmd/gencapi/casing.go | 17 + cmd/gencapi/gen.go | 53 + cmd/gencapi/head.tmpl | 36 + cmd/gencapi/main.go | 140 + cmd/gencapi/method.go | 154 + cmd/gencapi/typedef.go | 28 + connection_info.go | 46 +- entity.go | 54 +- entity/base_object.go | 176 + .../base_object_test.go | 16 +- entity/entity.go | 9 + entity/player.go | 49 + entity/type.go | 30 + entity/vehicle.go | 33 + entity/world_object.go | 9 + {events => event}/client_script.go | 26 +- {events => event}/connection_queue.go | 6 +- {events => event}/console_command.go | 2 +- {events => event}/ctx.go | 16 +- {events => event}/emit.go | 12 +- {events => event}/errors.go | 2 +- {events => event}/events.go | 2 +- {events => event}/player_connect.go | 12 +- {events => event}/player_damage.go | 17 +- {events => event}/register.go | 12 +- {events => event}/resource_error.go | 2 +- {events => event}/resource_stop.go | 2 +- {events => event}/server_script.go | 18 +- {events => event}/server_started.go | 2 +- export/export.go | 38 + exports.go | 57 - factories.go | 102 - factory/factories.go | 124 + .../factories_test.go | 16 +- file.go | 38 - imprt/import.go | 33 + internal/c-api/CMakeLists.txt | 8 - internal/c-api/lib/capi.h | 2980 ++++++++++++----- internal/c-api/lib/linux/libcapi.a | Bin 249114 -> 249042 bytes mvalue/func.go | 11 +- perm.go | 28 - perm/perm.go | 19 + player.go | 60 - init.go => resource/init.go | 16 +- resource.go => resource/resource.go | 81 +- runtime/tools/pkg-capi.js | 272 -- scripts/build-capi.bat | 2 + scripts/build-capi.sh | 2 + test/base_object.go | 101 - test/entity.go | 5 - test/player.go | 57 - test/world_object.go | 5 - vehicle.go | 45 - world_object.go | 9 - 67 files changed, 3515 insertions(+), 2385 deletions(-) delete mode 100644 .github/workflows/build-c-api.yml delete mode 100644 .github/workflows/build-deploy-module.yml create mode 100644 .github/workflows/publish-module.yml create mode 100644 CONTRIBUTING.md create mode 100644 TROUBLESHOOTING.md create mode 100644 altio/file.go rename log.go => altlog/log.go (70%) delete mode 100644 base_object.go create mode 100644 cgo.go create mode 100644 cmd/gencapi/body.tmpl create mode 100644 cmd/gencapi/casing.go create mode 100644 cmd/gencapi/gen.go create mode 100644 cmd/gencapi/head.tmpl create mode 100644 cmd/gencapi/main.go create mode 100644 cmd/gencapi/method.go create mode 100644 cmd/gencapi/typedef.go create mode 100644 entity/base_object.go rename base_object_test.go => entity/base_object_test.go (87%) create mode 100644 entity/entity.go create mode 100644 entity/player.go create mode 100644 entity/type.go create mode 100644 entity/vehicle.go create mode 100644 entity/world_object.go rename {events => event}/client_script.go (72%) rename {events => event}/connection_queue.go (95%) rename {events => event}/console_command.go (98%) rename {events => event}/ctx.go (78%) rename {events => event}/emit.go (85%) rename {events => event}/errors.go (92%) rename {events => event}/events.go (99%) rename {events => event}/player_connect.go (75%) rename {events => event}/player_damage.go (67%) rename {events => event}/register.go (73%) rename {events => event}/resource_error.go (98%) rename {events => event}/resource_stop.go (98%) rename {events => event}/server_script.go (81%) rename {events => event}/server_started.go (98%) create mode 100644 export/export.go delete mode 100644 exports.go delete mode 100644 factories.go create mode 100644 factory/factories.go rename factories_test.go => factory/factories_test.go (66%) delete mode 100644 file.go create mode 100644 imprt/import.go delete mode 100644 perm.go create mode 100644 perm/perm.go delete mode 100644 player.go rename init.go => resource/init.go (71%) rename resource.go => resource/resource.go (59%) delete mode 100644 runtime/tools/pkg-capi.js delete mode 100644 test/base_object.go delete mode 100644 test/entity.go delete mode 100644 test/player.go delete mode 100644 test/world_object.go delete mode 100644 vehicle.go delete mode 100644 world_object.go diff --git a/.github/workflows/build-c-api.yml b/.github/workflows/build-c-api.yml deleted file mode 100644 index 985041d..0000000 --- a/.github/workflows/build-c-api.yml +++ /dev/null @@ -1,106 +0,0 @@ -name: Build c-api -on: - push: - paths: - - "c-api/*" - - "runtime/src/capi/*" - - workflow_dispatch: - -concurrency: - group: ${{ github.ref }} - cancel-in-progress: true - -jobs: - build: - strategy: - matrix: - os: [ubuntu-20.04, windows-2019] - name: Build ${{ matrix.os }} - runs-on: ${{ matrix.os }} - #env: - # working-directory: ./c-api - steps: - - name: Checkout repository - uses: actions/checkout@v2 - with: - persist-credentials: false - fetch-depth: 0 - - - name: Build windows - if: matrix.os == 'windows-2019' - working-directory: ./c-api - run: | - ./build.bat - copy build/out/capi.h lib/capi.h - - - name: Build linux - if: matrix.os == 'ubuntu-20.04' - working-directory: ./c-api - run: | - ./build.sh - cp build/out/capi.h lib/capi.h - - - name: Extract branch name - shell: bash - run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})" - id: extract_branch - - - name: Upload windows artifacts - if: matrix.os == 'windows-2019' - uses: actions/upload-artifact@v2 - with: - name: go-module-capi-windows - path: ./c-api/lib/win32/ - - - name: Upload ubuntu artifacts - if: matrix.os == 'ubuntu-20.04' - uses: actions/upload-artifact@v2 - with: - name: go-module-capi-linux - path: | - ./c-api/lib/ - !./c-api/lib/win32/ - - commit: - name: Commit & Push libs - runs-on: ubuntu-20.04 - needs: [build-windows-2019, build-ubuntu-20.04] - steps: - - name: Checkout repository - uses: actions/checkout@v2 - with: - persist-credentials: false - fetch-depth: 0 - - - name: Download windows artifacts - uses: actions/download-artifact@v2 - with: - name: go-module-capi-windows - path: c-api/lib/win32/ - - - name: Download linux artifacts - uses: actions/download-artifact@v2 - with: - name: go-module-capi-linux - path: c-api/lib/ - - - name: Commit & Push static libs - uses: actions-js/push@v1.3 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - message: "chore: update c-api libs" - branch: ${{ steps.extract_branch.outputs.branch }} - - delete-artifacts: - name: Delete artifacts - runs-on: ubuntu-18.04 - needs: [ create-release ] - if: ${{ always() }} - steps: - - name: Delete artifacts - uses: geekyeggo/delete-artifact@v1 - with: - name: | - go-module-capi-windows - go-module-capi-linux \ No newline at end of file diff --git a/.github/workflows/build-deploy-module.yml b/.github/workflows/build-deploy-module.yml deleted file mode 100644 index 41e498a..0000000 --- a/.github/workflows/build-deploy-module.yml +++ /dev/null @@ -1,139 +0,0 @@ -name: Build & Deploy Go Module -on: - push: - branches-ignore: - - '**' - tags: - - 'v*.*.*-dev.*' - - 'v*.*.*-rc.*' - - 'v*.*.*' - -jobs: - build: - strategy: - matrix: - os: [ubuntu-20.04, windows-2019] - name: Build ${{ matrix.os }} - runs-on: ${{ matrix.os }} - steps: - - name: Checkout repository - uses: actions/checkout@v2 - with: - submodules: recursive - - #- name: Create LFS file list - # run: git lfs ls-files -l | cut -d' ' -f1 | sort > .lfs-assets-id -# - #- name: Restore LFS cache - # uses: actions/cache@v2 - # id: lfs-cache - # with: - # path: .git/lfs - # key: ${{ runner.os }}-lfs-${{ hashFiles('.lfs-assets-id') }}-v1 -# - #- name: Git LFS Pull - # run: git lfs pull - - - name: Extract version - id: version - shell: bash - run: | - TAG=${GITHUB_REF/refs\/tags\//} - echo ::set-output name=TAG::${TAG} - echo ::set-output name=VERSION::${TAG#v} - - - name: Build - if: matrix.os == 'windows-2019' - shell: cmd - run: | - mkdir build - pushd build - cmake -G"Visual Studio 16" -A x64 -DGO_MODULE_VERSION=%VERSION% .. - cmake --build . --config Release - popd - mkdir dist\go-module - copy bin\Release\go-module.dll dist\go-module - env: - VERSION: ${{ steps.version.outputs.VERSION }} - working-directory: ./runtime - - - name: Build - if: matrix.os == 'ubuntu-20.04' - run: | - sudo add-apt-repository ppa:ubuntu-toolchain-r/test - sudo apt-get update - sudo apt-get install gcc-8 g++-8 - mkdir build && cd build - cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=g++-8 -DGO_MODULE_VERSION=%VERSION% .. - cmake --build . --config Release - cd .. - mkdir -p dist/go-module - cp ./bin/libgo-module.so dist/go-module - env: - VERSION: ${{ steps.version.outputs.VERSION }} - working-directory: ./runtime - - - name: Upload artifacts - uses: actions/upload-artifact@v2 - with: - name: go-module-${{ matrix.os }} - path: ./runtime/dist/ - - create-release: - name: Create GitHub Release - runs-on: ubuntu-latest - needs: [build] - steps: - - name: Download windows artifacts - uses: actions/download-artifact@v2 - with: - name: go-module-windows-2019 - path: dist-windows - - - name: Download linux artifacts - uses: actions/download-artifact@v2 - with: - name: go-module-ubuntu-20.04 - path: dist-linux - - - name: Create Release - id: create_release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag_name: ${{ github.ref }} - release_name: Release ${{ steps.version.outputs.TAG }} - - - name: Upload windows artifacts - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./dist-windows/go-module/go-module.dll - asset_name: go-module.dll - asset_content_type: application/x-msdownload - - - name: Upload linux artifacts - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./dist-linux/go-module/libgo-module.so - asset_name: libgo-module.so - asset_content_type: application/octet-stream - - delete-artifacts: - name: Delete artifacts - runs-on: ubuntu-18.04 - needs: [ create-release ] - if: ${{ always() }} - steps: - - name: Delete artifacts - uses: geekyeggo/delete-artifact@v1 - with: - name: | - go-module-ubuntu-20.04 - go-module-windows-2019 \ No newline at end of file diff --git a/.github/workflows/publish-module.yml b/.github/workflows/publish-module.yml new file mode 100644 index 0000000..4e8c85c --- /dev/null +++ b/.github/workflows/publish-module.yml @@ -0,0 +1,77 @@ +name: Publish Go Module +on: + release: + types: [created] + +jobs: + build: + strategy: + matrix: + os: [ubuntu-20.04, windows-2019] + name: Build ${{ matrix.os }} + runs-on: ${{ matrix.os }} + steps: + - name: Checkout repository + uses: actions/checkout@v2 + with: + submodules: recursive + + - name: Get release + id: get_release + uses: bruceadams/get-release@v1.3.2 + env: + GITHUB_TOKEN: ${{ github.token }} + + - name: Extract version + id: version + shell: bash + run: | + TAG=${GITHUB_REF/refs\/tags\//} + echo ::set-output name=TAG::${TAG} + echo ::set-output name=VERSION::${TAG#v} + + - name: Build module for windows + if: matrix.os == 'windows-2019' + shell: cmd + run: | + mkdir build + pushd build + cmake -G"Visual Studio 16" -A x64 -DGO_MODULE_VERSION=%VERSION% .. + cmake --build . --config Release + popd + env: + VERSION: ${{ steps.version.outputs.VERSION }} + working-directory: ./runtime + + - name: Build module for linux + if: matrix.os == 'ubuntu-20.04' + run: | + sudo add-apt-repository ppa:ubuntu-toolchain-r/test + sudo apt-get update + sudo apt-get install gcc-8 g++-8 + mkdir build && cd build + cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=g++-8 -DGO_MODULE_VERSION=%VERSION% .. + cmake --build . --config Release + env: + VERSION: ${{ steps.version.outputs.VERSION }} + working-directory: ./runtime + + - name: Upload windows artifacts + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.get_release.outputs.upload_url }} + asset_path: ./runtime/bin/Release/go-module.dll + asset_name: go-module.dll + asset_content_type: application/x-msdownload + + - name: Upload linux artifacts + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.get_release.outputs.upload_url }} + asset_path: ./runtime/bin/libgo-module.so + asset_name: libgo-module.so + asset_content_type: application/octet-stream \ No newline at end of file diff --git a/.github/workflows/test-api.yml b/.github/workflows/test-api.yml index e32cf53..f4984d6 100644 --- a/.github/workflows/test-api.yml +++ b/.github/workflows/test-api.yml @@ -3,17 +3,16 @@ on: push: paths: - "*.go" - - "internal/**" - - "events/**" - - "mvalue/**" + - "**/*.go" - "go.mod" - "go.sum" + branches: + - main + - dev pull_request: paths: - "*.go" - - "internal/**" - - "events/**" - - "mvalue/**" + - "**/*.go" - "go.mod" - "go.sum" @@ -22,6 +21,11 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest] + include: + - os: windows-latest + script_name: .\scripts\build-capi.bat + - os: ubuntu-latest + script_name: ./scripts/build-capi.sh name: Test ${{ matrix.os }} runs-on: ${{ matrix.os }} steps: @@ -35,13 +39,16 @@ jobs: with: go-version: '1.21.0' + - name: Generate C-API + run: ${{ matrix.script_name }} + - name: Test altv run: go test working-directory: . - - name: Test altv/events + - name: Test altv/event run: go test - working-directory: ./events + working-directory: ./event - name: Test altv/mvalue run: go test diff --git a/.github/workflows/test-module.yml b/.github/workflows/test-module.yml index d845328..8e996fd 100644 --- a/.github/workflows/test-module.yml +++ b/.github/workflows/test-module.yml @@ -3,6 +3,9 @@ on: push: paths: - "runtime/**" + branches: + - main + - dev pull_request: paths: - "runtime/**" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..d037265 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,51 @@ +# Contributing + +## Architecture + +The go-module is split into three parts: the [runtime](/runtime), the [c-api](/internal/c-api) and the [go-api](/). + +| Part | Language | Description | +| ------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------- | +| Runtime | C++ | The runtime is the core of the module. It is responsible for initializing the go-module ScriptRuntime and loading the resource library. | +| C-API | C | The c-api is the interface between the runtime and the go-api. It is responsible for all go <-> runtime calls | +| Go-API | Go | The go-api is api you are using to build your custom gamemode. It utilizes the c-api to call alt:V functions exported by the runtime | + +The C-API is currently generated by a custom [nodejs script](/runtime/tools/pkg-capi.js).
+**DO NOT** edit the c-api files manually, as they will be overwritten on the next build. + +## Build from source + +### Build the module +For instructions on how to build the go-module, take a look at the [Runtime Readme](/runtime/README.md). + +### Build the c-api +Building the c-api constists of two parts: +- Generation of the c-api header & source file +- Actual build of the c-api using cmake + +To build the **c-api** clone the repository:
+`git clone --recurse-submodules https://github.com/timo972/altv-go.git` + +and run the following command:
+`make capi` + +This will execute
+` +go run cmd/gencapi/*.go -cout=./internal/c-api/build/out/capi.c -hout=./internal/c-api/build/out/capi.h -hout=./internal/c-api/lib/capi.h ./runtime/src/capi +`
+to generate the c-api header & source file and start the cmake build afterwards. + +### Checking the build +To check if the build was successful, you can run the following command:
+``go test -v``
+This will run all tests in the root go package and errors in case the capi is not built correctly or incompatible with the go api. + +## Using your local build + +To use your local version of the altv-go package, you need to add the following line to the go.mod file **of your resource**: + +``` +replace github.com/timo972/altv-go => ../relative/path/to/your/altv-go +``` + +This tells go to use the local version of the package instead of the one hosted on github. diff --git a/README.md b/README.md index 940e384..86d78bd 100644 --- a/README.md +++ b/README.md @@ -14,9 +14,9 @@

- Get started + Troubleshooting   •   - Docs + Contributing   •   alt:V   •   @@ -28,12 +28,13 @@
-> Go package for alt:V Multiplayer. Runtime can be found [here](runtime). +> Go package for alt:V Multiplayer. Runtime can be found [here](runtime). - -> ⚠️ Notice: updated occasionally, not actively maintained + +> ⚠️ Notice: updated occasionally, not actively maintained > ⛔ Module is currently in development and not ready for production use - expect heavy api changes and bugs. > ✨ Contributions of any kind are always welcome! @@ -53,20 +54,20 @@ package main import "C" import ( "github.com/timo972/altv-go" - // this package is a required import. if you are not using the events package, import it like this - // _ "github.com/timo972/altv-go/events" + // this package is a required import. if you are not using the event package, import it like this + // _ "github.com/timo972/altv-go/event" // if you are not importing it, the module will log errors calling the ServerStarted and ResourceStopEvent - "github.com/timo972/altv-go/events" + "github.com/timo972/altv-go/event" ) func init() { // You may want to initialize something here. - // However the alt:V api is limited due to the reason + // However the alt:V api is limited due to the reason // that the package did not load the go-module's c-api yet! // As of now you can only use the event features here. // e.g. - events.On.ServerStarted(func () { + event.On.ServerStarted(func () { altv.LogInfo("Server Started") }) } @@ -91,7 +92,7 @@ func OnStop() { For more examples take a look at the [altv-go-examples]() repository. -## Building +## Building your Resource #### Windows @@ -105,5 +106,8 @@ go build -o my-resource.dll -buildmode=c-shared go build -o my-resource.so -buildmode=c-shared ``` +Something went wrong? A build error? See the [Troubleshooting Guide](/TROUBLESHOOTING.md). + ## Help -If you need help to get started, have a look at the [docs](https://altv-go.tbeck.dev) or contact me on Discord: `Timo9#4468` + +If you need help to get started contact me on Discord: `Timo9#4468` diff --git a/TROUBLESHOOTING.md b/TROUBLESHOOTING.md new file mode 100644 index 0000000..25ac407 --- /dev/null +++ b/TROUBLESHOOTING.md @@ -0,0 +1,43 @@ +# Troubleshooting + +## Common Build Errors + +### [...]\altv-go\base_object.go:3:11: fatal error: capi.h: No such file or directory + +This error occurs when the c-api is not built or the header file is not in the correct location. +See the [Contribution Guide](/CONTRIBUTING.md#build-the-c-api) for instructions on how to build the c-api & copy the capi.h. + +### [...]/x86_64-w64-mingw32/bin/ld.exe: cannot find -ldl: No such file or directory \ collect2.exe: error: ld returned 1 exit status +> This error only occurs on windows + +You are missing the libdl.a library. This library is required to build the module on windows.
+If you are using mingw-w64 you can install the package `mingw-w64-dlfcn` which contains the libdl.a library. + +### -buildmode=c-shared requires exactly one main package +You are probably running the `go build` command in the wrong directory.
+Make sure you are in the directory of your resource. + +## Common Runtime Errors + +### [Error] Failed to open main file +Make sure your `resource.toml` looks something like this: +```toml +type = 'go' +main = 'my-resource.dll' +``` +**DO NOT** set `main` path to a **.go** file. It must be a shared library - a **.dll** or **.so** file.
+You should have built your resource with the `go build -o [resource-name].so -buildmode=c-shared` command previously.
+Set the path to that `[resource-name].so` output file as the `main` path in your `resource.toml` file.
+ +### [Error] Couldnt call OnStop +This error occurs when the module is unable to call the `OnStop` function of your resource.
+Make sure you have exported the `OnStop` function in your resource.
+```go +// import "C" is required at the top of your file to enable the //export directive +import "C" + +//export OnStop +func OnStop() { + // do something +} +``` \ No newline at end of file diff --git a/altio/file.go b/altio/file.go new file mode 100644 index 0000000..7da310e --- /dev/null +++ b/altio/file.go @@ -0,0 +1,41 @@ +package altio + +// #cgo CFLAGS: -I../internal/c-api/lib +// #cgo linux LDFLAGS: -L../internal/c-api/lib/linux -lcapi -ldl -g +// #cgo windows LDFLAGS: -L../internal/c-api/lib/win32 -lcapi -ldl -g +// #cgo CXXFLAGS: -std=c++14 +// #include +// #include "capi.h" +import "C" +import ( + "io" + "strings" + "unsafe" +) + +// FileExists checks if the file at the given path exists. +func Exists(path string) bool { + cStr := C.CString(path) + defer C.free(unsafe.Pointer(cStr)) + + return int(C.core_file_exists(cStr)) == 1 +} + +// ReadAll reads the file at the given path and returns its content as a string. +func ReadAll(path string) (string, error) { + cStr := C.CString(path) + defer C.free(unsafe.Pointer(cStr)) + + cContent := C.core_read_file(cStr) + return C.GoString(cContent), nil +} + +// Read reads the file at the given path and returns an io.Reader. +func Read(path string) (io.Reader, error) { + data, err := ReadAll(path) + if err != nil { + return nil, err + } + + return strings.NewReader(data), nil +} diff --git a/log.go b/altlog/log.go similarity index 70% rename from log.go rename to altlog/log.go index 1770718..389a395 100644 --- a/log.go +++ b/altlog/log.go @@ -1,9 +1,11 @@ -package altv +package altlog -/* -#include -#include "capi.h" -*/ +// #cgo CFLAGS: -I../internal/c-api/lib +// #cgo linux LDFLAGS: -L../internal/c-api/lib/linux -lcapi -ldl -g +// #cgo windows LDFLAGS: -L../internal/c-api/lib/win32 -lcapi -ldl -g +// #cgo CXXFLAGS: -std=c++14 +// #include +// #include "capi.h" import "C" import ( "io" @@ -25,14 +27,14 @@ func (l *altLog) Write(p []byte) (n int, err error) { var Console io.Writer = &altLog{} // LogWarning logs a warning message to the console. -func LogWarning(msgs ...string) { +func Warnln(msgs ...string) { cstr := C.CString(strings.Join(msgs, " ")) defer C.free(unsafe.Pointer(cstr)) C.core_log_warning(cstr) } // LogError logs an error message to the console. -func LogError(msgs ...string) { +func Errorln(msgs ...string) { cstr := C.CString(strings.Join(msgs, " ")) defer C.free(unsafe.Pointer(cstr)) C.core_log_error(cstr) @@ -41,7 +43,7 @@ func LogError(msgs ...string) { // Log logs a message to the console. // You can use color codes in the message. // https://docs.altv.mp/articles/logging.html -func Log(msgs ...string) { +func Println(msgs ...string) { cstr := C.CString(strings.Join(msgs, " ")) defer C.free(unsafe.Pointer(cstr)) C.core_log_colored(cstr) diff --git a/base_object.go b/base_object.go deleted file mode 100644 index f600208..0000000 --- a/base_object.go +++ /dev/null @@ -1,245 +0,0 @@ -package altv - -// #include "capi.h" -// #include -import "C" -import ( - "context" - "errors" - "fmt" - "unsafe" - - "github.com/goccy/go-json" - "github.com/timo972/altv-go/internal/cutil" - "github.com/timo972/altv-go/mvalue" -) - -var ErrInvalidBaseObject = errors.New("base object is invalid") - -type BaseObjectType = uint8 - -const ( - BaseTypePlayer BaseObjectType = iota - BaseTypeVehicle - BaseTypePed - BaseTypeNetworkObject - BaseTypeBlip - BaseTypeWebView - BaseTypeVoiceChannel - BaseTypeColShape - BaseTypeCheckpoint - BaseTypeWebSocketClient - BaseTypeHttpClient - BaseTypeAudio - BaseTypeRMLElement - BaseTypeRMLDocument - BaseTypeLocalPlayer - BaseTypeObject - BaseTypeVirtualEntity - BaseTypeVirtualEntityGroup - BaseTypeMarker - BaseTypeTextLabel - BaseTypeLocalPed - BaseTypeLocalVehicle - BaseTypeAudioFilter - BaseTypeSize -) - -type BaseObject interface { - json.Marshaler - // json.Unmarshaler - ID() uint32 - Type() BaseObjectType - Ptr() unsafe.Pointer - Valid() bool - Destroy() - Context() context.Context - SetMetaData(key string, value interface{}) error - MetaData(key string, value interface{}) error - CancelCtx(error) -} - -type baseObject struct { - id uint32 - ptr unsafe.Pointer - typ BaseObjectType - ctx context.Context - cancelFunc context.CancelCauseFunc -} - -type BaseObjectData[T BaseObject] struct { - json.Marshaler - json.Unmarshaler - ID uint32 - Type BaseObjectType - ptr unsafe.Pointer - Model uint32 -} - -type baseObjectData struct { - mvalue.SpecialType - ID uint32 `json:"id"` - Type BaseObjectType `json:"type"` - Ptr string `json:"ptr"` - Model uint32 `json:"model,omitempty"` -} - -func (b *BaseObjectData[T]) MarshalJSON() ([]byte, error) { - return json.Marshal(baseObjectData{ID: b.ID, Type: b.Type, Ptr: "", Model: b.Model, SpecialType: mvalue.SpecialType{Type: mvalue.TypeBaseObject}}) -} - -func (b *BaseObjectData[T]) UnmarshalJSON(data []byte) error { - var obj baseObjectData - var err error - if err = json.Unmarshal(data, &obj); err != nil { - return err - } - - if b.ptr, err = mvalue.ParsePointer(obj.Ptr); err != nil { - return err - } - b.ID = obj.ID - b.Type = obj.Type - b.Model = obj.Model - return nil -} - -func (b *BaseObjectData[T]) Obj() (T, error) { - return GetBaseObject[T](b.Type, b.ptr, b.ID, b.Model) -} - -func (b *baseObject) MarshalJSON() ([]byte, error) { - return json.Marshal(baseObjectData{ID: b.id, Type: b.typ}) -} - -func (b *baseObject) ID() uint32 { - return b.id -} - -func (b *baseObject) Type() BaseObjectType { - return b.typ -} - -func (b *baseObject) Ptr() unsafe.Pointer { - return b.ptr -} - -func (b *baseObject) Valid() bool { - if b.ctx == nil { - return false - } - - // TODO: check if base object still exists - // probably check where pointer is pointing to - if err := b.ctx.Err(); err != nil { - return false - } - return true -} - -func (b *baseObject) Destroy() { - if b.typ == BaseTypePlayer { - C.player_destroy(b.ptr) - } else if b.typ == BaseTypeVoiceChannel { - C.voice_channel_destroy(b.ptr) - } else if b.typ == BaseTypeCheckpoint { - C.checkpoint_destroy(b.ptr) - } else if b.typ == BaseTypeColShape { - C.col_shape_destroy(b.ptr) - } else if b.typ == BaseTypeVehicle { - C.vehicle_destroy(b.ptr) - } else if b.typ == BaseTypeBlip { - C.blip_destroy(b.ptr) - } -} - -func (b *baseObject) Context() context.Context { - return b.ctx -} - -func (b *baseObject) CancelCtx(err error) { - b.cancelFunc(err) -} - -func (b *baseObject) SetMetaData(key string, v any) error { - data, free, err := marshal(v) - if err != nil { - return err - } - defer free() - - cKey := C.CString(key) - defer C.free(unsafe.Pointer(cKey)) - if b.typ == BaseTypePlayer { - C.player_set_meta_data(b.ptr, cKey, data) - } else if b.typ == BaseTypeVehicle { - C.vehicle_set_meta_data(b.ptr, cKey, data) - } - - return nil -} - -func (b *baseObject) MetaData(key string, v any) error { - var carr C.struct_array - ckey := C.CString(key) - defer C.free(unsafe.Pointer(ckey)) - if b.typ == BaseTypePlayer { - carr = C.player_get_meta_data(b.ptr, ckey) - } else if b.typ == BaseTypeVehicle { - carr = C.vehicle_get_meta_data(b.ptr, ckey) - } - - return unmarshal(carr, v) -} - -func newBaseObject(typ BaseObjectType, ptr unsafe.Pointer, id uint32) baseObject { - ctx, cancel := context.WithCancelCause(context.Background()) - return baseObject{ - ptr: ptr, - id: id, - typ: typ, - ctx: ctx, - cancelFunc: cancel, - } -} - -//export altCreateBaseObject -func altCreateBaseObject(entity C.struct_entity) { - fmt.Printf("altCreateBaseObject\n") - id := uint32(entity.id) - typ := BaseObjectType(entity.typ) - ptr := unsafe.Pointer(entity.ptr) - model := uint32(entity.model) - - if _, err := GetBaseObject[BaseObject](typ, ptr, id, model); err != nil { - LogError(fmt.Sprintf("altCreateBaseObject: %s", err.Error())) - } -} - -//export altRemoveBaseObject -func altRemoveBaseObject(entity C.struct_entity) { - fmt.Printf("altRemoveBaseObject\n") - id := uint32(entity.id) - typ := BaseObjectType(entity.typ) - ptr := unsafe.Pointer(entity.ptr) - model := uint32(entity.model) - - obj, err := GetBaseObject[BaseObject](typ, ptr, id, model) - if err != nil { - LogError(fmt.Sprintf("altRemoveBaseObject: %s", err.Error())) - return - } - - obj.CancelCtx(ErrInvalidBaseObject) - baseObjectCache.Delete(id) -} - -func newBaseObjectArray[T BaseObject](arr C.struct_array) []T { - return cutil.NewArrayFunc[C.struct_entity, T](unsafe.Pointer(arr.array), int(arr.size), func(item C.struct_entity) T { - v, err := getBaseObject[T](item) - if err != nil { - LogError(fmt.Sprintf("[Go] newBaseObjectArray: %s", err.Error())) - } - return v - }) -} diff --git a/cgo.go b/cgo.go new file mode 100644 index 0000000..e1dff7f --- /dev/null +++ b/cgo.go @@ -0,0 +1,9 @@ +package altv + +// #cgo CFLAGS: -I./internal/c-api/lib +// #cgo linux LDFLAGS: -L./internal/c-api/lib/linux -lcapi -ldl -g +// #cgo windows LDFLAGS: -L./internal/c-api/lib/win32 -lcapi -ldl -g +// #cgo CXXFLAGS: -std=c++14 +// #include +// #include "capi.h" +import "C" diff --git a/cmd/gencapi/body.tmpl b/cmd/gencapi/body.tmpl new file mode 100644 index 0000000..d1ec372 --- /dev/null +++ b/cmd/gencapi/body.tmpl @@ -0,0 +1,27 @@ +#include "capi.h" + +Module module; + +{{ range .Methods }} +{{ .CInit }} +{{ end }} + +{{ range .Methods }} +{{ .CBody }} +{{ end }} + +int load_module(const char *path) +{ + module = LOAD_LIB(path); + + if (module == NULL) + { + return 0; + } + + {{ range .Methods }} + {{ .CLoad }} + {{ end }} + + return 1; +} diff --git a/cmd/gencapi/casing.go b/cmd/gencapi/casing.go new file mode 100644 index 0000000..56ea814 --- /dev/null +++ b/cmd/gencapi/casing.go @@ -0,0 +1,17 @@ +package main + +import ( + "regexp" + "strings" +) + +// thanks stack overflow + +var matchFirstCap = regexp.MustCompile("(.)([A-Z][a-z]+)") +var matchAllCap = regexp.MustCompile("([a-z0-9])([A-Z])") + +func ToSnakeCase(str string) string { + snake := matchFirstCap.ReplaceAllString(str, "${1}_${2}") + snake = matchAllCap.ReplaceAllString(snake, "${1}_${2}") + return strings.ToLower(snake) +} diff --git a/cmd/gencapi/gen.go b/cmd/gencapi/gen.go new file mode 100644 index 0000000..f6e9464 --- /dev/null +++ b/cmd/gencapi/gen.go @@ -0,0 +1,53 @@ +package main + +import ( + "embed" + "io" + "log" + "text/template" +) + +//go:embed *.tmpl +var tmplfs embed.FS + +type templateData struct { + Methods []*method + Structs []typedef +} + +func tmplData(structs []typedef, capi map[string][]*method) *templateData { + data := &templateData{ + Methods: make([]*method, 0), + Structs: structs, + } + + for _, file := range capi { + data.Methods = append(data.Methods, file...) + } + + return data +} + +func genCHead(dst io.Writer, structs []typedef, capi map[string][]*method) error { + tmpl, err := template.New("head.tmpl").ParseFS(tmplfs, "head.tmpl") + if err != nil { + return err + } + + data := tmplData(structs, capi) + log.Printf("writing %d typedefs and %d methods to header", len(data.Structs), len(data.Methods)) + + return tmpl.Execute(dst, data) +} + +func genCBody(dst io.Writer, capi map[string][]*method) error { + tmpl, err := template.New("body.tmpl").ParseFS(tmplfs, "body.tmpl") + if err != nil { + return err + } + + data := tmplData(nil, capi) + log.Printf("writing %d methods to body", len(data.Methods)) + + return tmpl.Execute(dst, data) +} diff --git a/cmd/gencapi/head.tmpl b/cmd/gencapi/head.tmpl new file mode 100644 index 0000000..517ba65 --- /dev/null +++ b/cmd/gencapi/head.tmpl @@ -0,0 +1,36 @@ +#ifndef CAPI_MODULE +#define CAPI_MODULE + +#ifndef __linux__ +#include + +#define SEPARATOR "\\" +#define LOAD_LIB(path) LoadLibrary(path) +#define GET_FUNC(module, name, type) (type) GetProcAddress(module, name); + +typedef HINSTANCE Module; +#else +#include +#include + +#define SEPARATOR "/" +#define LOAD_LIB(name) dlopen(name, RTLD_NOW); +#define GET_FUNC(module, name, type) (type) dlsym(module, name); + +typedef void *Module; +#endif + +int load_module(const char *path); + +{{ range .Structs }} +{{ .String }} +{{ end }} + +{{ range .Methods }} +{{ .CTypedef }} +{{ end }} + +{{ range .Methods }} +{{ .CHead }} +{{ end }} +#endif \ No newline at end of file diff --git a/cmd/gencapi/main.go b/cmd/gencapi/main.go new file mode 100644 index 0000000..e8e1ce9 --- /dev/null +++ b/cmd/gencapi/main.go @@ -0,0 +1,140 @@ +package main + +import ( + "flag" + "fmt" + "io" + "log" + "os" + "path" + "strings" +) + +type stringArrayFlag []string + +func (strs *stringArrayFlag) String() string { + return strings.Join(*strs, ";") +} + +func (strs *stringArrayFlag) Set(v string) error { + *strs = append(*strs, v) + return nil +} + +func ensureFileDirs(targets []string) error { + for _, target := range targets { + if err := os.MkdirAll(path.Dir(target), 0755); err != nil { + return fmt.Errorf("error ensuring %s outpout folder: %w", target, err) + } + } + return nil +} + +func createDst(dsts []string) (io.Writer, func(), error) { + writers := make([]io.Writer, len(dsts)) + + for i, dst := range dsts { + f, err := os.OpenFile(dst, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644) + if err != nil { + return nil, nil, fmt.Errorf("error opening %s: %w", dst, err) + } + + writers[i] = f + } + + return io.MultiWriter(writers...), func() { + for _, w := range writers { + if f, ok := w.(*os.File); ok { + f.Close() + } + } + }, nil +} + +func main() { + log.Printf("running gencapi") + + // flag.StringVar(&runtimeStructsPath, "structs", runtimeStructsPath, "struct definitions file path") + + var coutPaths stringArrayFlag = []string{} + var houtPaths stringArrayFlag = []string{} + flag.Var(&coutPaths, "cout", "c body output file path") + flag.Var(&houtPaths, "hout", "c header output file path") + + flag.Parse() + + runtimeCAPIPath := flag.Arg(0) + var runtimeStructsPath = path.Join(path.Dir(runtimeCAPIPath), "Main.h") + + if len(coutPaths)+len(houtPaths) == 0 { + coutPaths = append(coutPaths, "capi.c") + houtPaths = append(houtPaths, "capi.h") + } + + log.Printf("runtime CAPI path: %s", runtimeCAPIPath) + log.Printf("runtime structs path: %s", runtimeStructsPath) + log.Printf("capi header paths: %s", houtPaths) + log.Printf("capi body paths: %s", coutPaths) + + if _, err := os.Stat(runtimeCAPIPath); os.IsNotExist(err) { + log.Fatalf("runtime CAPI folder does not exist: %s", runtimeCAPIPath) + } else if err != nil { + log.Fatalf("error checking runtime CAPI folder: %s", err) + } + + if err := ensureFileDirs(coutPaths); err != nil { + log.Fatal(err) + } + + if err := ensureFileDirs(houtPaths); err != nil { + log.Fatal(err) + } + + log.Printf("generating CAPI files from %s and struct defs from %s", runtimeCAPIPath, runtimeStructsPath) + + runtimeStructs, err := os.Open(runtimeStructsPath) + if err != nil { + runtimeStructs.Close() + log.Fatalf("error opening runtime structs file: %s", err) + } + + runtimeCAPI := os.DirFS(runtimeCAPIPath) + capi, err := parseCAPIDir(runtimeCAPI) + if err != nil { + log.Fatalf("error parsing runtime CAPI folder: %s", err) + } + + log.Printf("parsed %d CAPI files", len(capi)) + + typedefs, err := parseTypedefs(runtimeStructs) + runtimeStructs.Close() + if err != nil { + log.Fatalf("error parsing runtime structs file: %s", err) + } + + log.Printf("parsed %d typedefs", len(typedefs)) + + log.Printf("capi header destinations: %v", houtPaths) + hout, closeH, err := createDst(houtPaths) + if err != nil { + log.Fatalf("error creating hout: %v", err) + } + + if err = genCHead(hout, typedefs, capi); err != nil { + closeH() + log.Fatalf("error generating capi head: %v", err) + } + closeH() + + log.Printf("capi body destinations: %v", coutPaths) + cout, closeC, err := createDst(coutPaths) + if err != nil { + log.Fatalf("error creating cout: %v", err) + } + + if err = genCBody(cout, capi); err != nil { + closeC() + log.Fatalf("error generating capi body: %v", err) + } + closeC() +} diff --git a/cmd/gencapi/method.go b/cmd/gencapi/method.go new file mode 100644 index 0000000..841a4c6 --- /dev/null +++ b/cmd/gencapi/method.go @@ -0,0 +1,154 @@ +package main + +import ( + "fmt" + "io" + "io/fs" + "log" + "regexp" + "strings" +) + +type method struct { + returnType string + className string + classMethod string + args []string +} + +func (m *method) Returns() bool { + return m.returnType != "void" +} + +func (m *method) Name() string { + return fmt.Sprintf("%s_%s", m.className, m.classMethod) +} + +func (m *method) CName() string { + return ToSnakeCase(m.className + m.classMethod) +} + +func (m *method) CArgs() string { + if len(m.args) == 0 { + return "" + } + + return strings.Join(m.args, ", ") +} + +func (m *method) CArgNames() string { + vnames := make([]string, len(m.args)) + for i, arg := range m.args { + vname := arg[strings.LastIndex(arg, " ")+1:] + if vname[0] == '*' { + vname = vname[1:] + } + vnames[i] = vname + } + + return strings.Join(vnames, ",") +} + +// capi.h +// method.CTypedef() +// method.CHead() + +// capi.c +// method.CInit() +// method.CLoad() - inside load_module function +// method.CBody() + +func (m *method) CTypedef() string { + return fmt.Sprintf("typedef %s (*capi_%s)(%s);", m.returnType, m.CName(), m.CArgs()) +} + +func (m *method) CHead() string { + return fmt.Sprintf("%s %s(%s);", m.returnType, m.CName(), m.CArgs()) +} + +func (m *method) CInit() string { + return fmt.Sprintf("capi_%s g_call_%s;", m.CName(), m.CName()) +} + +func (m *method) CLoad() string { + return fmt.Sprintf("g_call_%s = GET_FUNC(module, %q, capi_%s);", m.CName(), m.Name(), m.CName()) +} + +func (m *method) CBody() string { + var tmpl string + if m.Returns() { + tmpl = "%s %s(%s)\n{\nreturn g_call_%s(%s);\n}" + } else { + tmpl = "%s %s(%s)\n{\ng_call_%s(%s);\n}" + } + + return fmt.Sprintf(tmpl, m.returnType, m.CName(), m.CArgs(), m.CName(), m.CArgNames()) +} + +func parseMethodArgs(argstr string) []string { + argstr = strings.Trim(argstr, " ") + if argstr == "" { + return make([]string, 0) + } + return strings.Split(argstr, ",") +} + +func parseMethods(src io.Reader) ([]*method, error) { + data, err := io.ReadAll(src) + if err != nil { + return nil, err + } + + r := regexp.MustCompile(`(?m)EXPORT\s([a-zA-Z0-9\s\*]{1,}[\s\*]{1,1})([A-Z]{1,1}[a-zA-Z]+)_([a-zA-Z0-9]+)\(([a-zA-Z0-9\s\*\,]{0,})\);`) + + matches := r.FindAllSubmatch(data, -1) + + methods := make([]*method, len(matches)) + for i, match := range matches { + methods[i] = &method{ + returnType: strings.Trim(string(match[1]), " "), + className: string(match[2]), + classMethod: string(match[3]), + args: parseMethodArgs(string(match[4])), + } + } + + return methods, nil +} + +func parseCAPIDir(runtimeCAPI fs.FS) (map[string][]*method, error) { + capiMethods := make(map[string][]*method) + if err := fs.WalkDir(runtimeCAPI, ".", func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + + if d.IsDir() { + return nil + } + + // only process headers + if !strings.HasSuffix(path, ".h") { + return nil + } + + h, err := runtimeCAPI.Open(path) + if err != nil { + return fmt.Errorf("error opening %s: %w", path, err) + } + + methods, err := parseMethods(h) + if err != nil { + return err + } + + log.Printf("%s: %d methods", path, len(methods)) + capiMethods[path] = methods + + return nil + }); err != nil { + return nil, fmt.Errorf("error walking runtime CAPI folder: %s", err) + } + + return capiMethods, nil +} diff --git a/cmd/gencapi/typedef.go b/cmd/gencapi/typedef.go new file mode 100644 index 0000000..b0e1c13 --- /dev/null +++ b/cmd/gencapi/typedef.go @@ -0,0 +1,28 @@ +package main + +import ( + "io" + "regexp" +) + +type typedef string + +func (t typedef) String() string { + return string(t) +} + +func parseTypedefs(src io.Reader) ([]typedef, error) { + data, err := io.ReadAll(src) + if err != nil { + return nil, err + } + + r := regexp.MustCompile(`(?m)typedef\s[a-z]+\s[a-zA-Z0-9\s]+{[^}]+}[\s]{0,1}[a-zA-Z0-9]+;`) + matches := r.FindAllSubmatch(data, -1) + typedefs := make([]typedef, len(matches)) + for i, match := range matches { + typedefs[i] = typedef(match[0]) + } + + return typedefs, nil +} diff --git a/connection_info.go b/connection_info.go index ec3cb53..22a5292 100644 --- a/connection_info.go +++ b/connection_info.go @@ -11,7 +11,7 @@ import ( "github.com/timo972/altv-go/internal/lib" ) -type ConnectionInfo interface { +/*type ConnectionInfo interface { // ID returns the id of the connecting player ID() uint32 // Name returns the name of the connecting player @@ -49,9 +49,9 @@ type ConnectionInfo interface { Decline(reason string) // Accepted returns if the connection was accepted Accepted() bool -} +}*/ -type connInfo struct { +type ConnectionInfo struct { ptr unsafe.Pointer id uint32 name string @@ -71,8 +71,8 @@ type connInfo struct { } // NewConnectionInfo ! INTERNAL ONLY ! -func NewConnectionInfo(ptr unsafe.Pointer, id uint32, name string, socialID uint64, socialName string, hwidHash uint64, hwidExHash uint64, authToken string, debug bool, branch string, build uint32, cdnUrl string, passwordHash uint64, ip string, discordUserId int64, cloudAuthHash string) ConnectionInfo { - return &connInfo{ +func NewConnectionInfo(ptr unsafe.Pointer, id uint32, name string, socialID uint64, socialName string, hwidHash uint64, hwidExHash uint64, authToken string, debug bool, branch string, build uint32, cdnUrl string, passwordHash uint64, ip string, discordUserId int64, cloudAuthHash string) *ConnectionInfo { + return &ConnectionInfo{ ptr: ptr, id: id, name: name, @@ -92,76 +92,76 @@ func NewConnectionInfo(ptr unsafe.Pointer, id uint32, name string, socialID uint } } -func (c *connInfo) ID() uint32 { +func (c *ConnectionInfo) ID() uint32 { return c.id } -func (c *connInfo) Name() string { +func (c *ConnectionInfo) Name() string { return c.name } -func (c *connInfo) SocialID() uint64 { +func (c *ConnectionInfo) SocialID() uint64 { return c.socialID } -func (c *connInfo) SocialName() string { +func (c *ConnectionInfo) SocialName() string { return c.socialName } -func (c *connInfo) HwIdHash() uint64 { +func (c *ConnectionInfo) HwIdHash() uint64 { return c.hwidHash } -func (c *connInfo) HwIdExHash() uint64 { +func (c *ConnectionInfo) HwIdExHash() uint64 { return c.hwidExHash } -func (c *connInfo) AuthToken() string { +func (c *ConnectionInfo) AuthToken() string { return c.authToken } -func (c *connInfo) Debug() bool { +func (c *ConnectionInfo) Debug() bool { return c.isDebug } -func (c *connInfo) Branch() string { +func (c *ConnectionInfo) Branch() string { return c.branch } -func (c *connInfo) Build() uint32 { +func (c *ConnectionInfo) Build() uint32 { return c.build } -func (c *connInfo) CDNUrl() string { +func (c *ConnectionInfo) CDNUrl() string { return c.cdnUrl } -func (c *connInfo) PasswordHash() uint64 { +func (c *ConnectionInfo) PasswordHash() uint64 { return c.passwordHash } -func (c *connInfo) IP() string { +func (c *ConnectionInfo) IP() string { return c.ip } -func (c *connInfo) DiscordUserID() int64 { +func (c *ConnectionInfo) DiscordUserID() int64 { return c.discordUserID } -func (c *connInfo) CloudAuthHash() string { +func (c *ConnectionInfo) CloudAuthHash() string { return c.cloudAuthHash } -func (c *connInfo) Accept(sendNames bool) { +func (c *ConnectionInfo) Accept(sendNames bool) { C.connection_accept(c.ptr, C.uchar(lib.Bool2int(sendNames))) } -func (c *connInfo) Decline(reason string) { +func (c *ConnectionInfo) Decline(reason string) { r := C.CString(reason) defer C.free(unsafe.Pointer(r)) C.connection_decline(c.ptr, r) } -func (c *connInfo) Accepted() bool { +func (c *ConnectionInfo) Accepted() bool { return int(C.connection_is_accepted(c.ptr)) == 1 } diff --git a/entity.go b/entity.go index 6889979..ca3e622 100644 --- a/entity.go +++ b/entity.go @@ -1,9 +1,55 @@ package altv -type Entity interface { - WorldObject +// #include "capi.h" +import "C" +import ( + "fmt" + "unsafe" + + "github.com/timo972/altv-go/altlog" + "github.com/timo972/altv-go/entity" + "github.com/timo972/altv-go/factory" + "github.com/timo972/altv-go/internal/cutil" +) + +func getEntityData(e C.struct_entity) (typ entity.BaseObjectType, ptr unsafe.Pointer, id uint32, model uint32) { + ptr = unsafe.Pointer(e.ptr) + id = uint32(e.id) + typ = entity.BaseObjectType(e.typ) + model = uint32(e.model) + + return +} + +func newBaseObjectArray[T entity.BaseObject](arr C.struct_array) []T { + return cutil.NewArrayFunc[C.struct_entity, T](unsafe.Pointer(arr.array), int(arr.size), func(item C.struct_entity) T { + v, err := factory.GetBaseObject[T](getEntityData(item)) + if err != nil { + altlog.Errorln(fmt.Sprintf("[Go] newBaseObjectArray: %s", err.Error())) + } + return v + }) +} + +func Players() []entity.Player { + arr := C.core_get_players() + return newBaseObjectArray[entity.Player](arr) } -type entity struct { - worldObject +func PlayerByID(id uint32) (entity.Player, error) { + p := C.core_get_base_object_by_id(C.uchar(entity.TypePlayer), C.uint(id)) + return factory.GetBaseObject[entity.Player](getEntityData(p)) +} + +func VehicleByID(id uint32) (entity.Vehicle, error) { + e := C.core_get_base_object_by_id(C.uchar(entity.TypePlayer), C.uint(id)) + return factory.GetBaseObject[entity.Vehicle](getEntityData(e)) +} + +func CreateVehicle(model uint32, pos Vector3, rot Vector3) (entity.Vehicle, error) { + // TODO: validate model beforehand. best solution: data/vehmodels.bin + + e := C.core_create_vehicle(C.ulong(model), C.float(pos.X), C.float(pos.Y), C.float(pos.Z), C.float(rot.X), C.float(rot.Y), C.float(rot.Z)) + + return factory.GetBaseObject[entity.Vehicle](getEntityData(e)) } diff --git a/entity/base_object.go b/entity/base_object.go new file mode 100644 index 0000000..ee5525e --- /dev/null +++ b/entity/base_object.go @@ -0,0 +1,176 @@ +package entity + +// #cgo CFLAGS: -I../internal/c-api/lib +// #cgo linux LDFLAGS: -L../internal/c-api/lib/linux -lcapi -ldl -g +// #cgo windows LDFLAGS: -L../internal/c-api/lib/win32 -lcapi -ldl -g +// #cgo CXXFLAGS: -std=c++14 +// #include +// #include "capi.h" +import "C" +import ( + "context" + "errors" + "unsafe" + + "github.com/goccy/go-json" +) + +var ErrInvalidBaseObject = errors.New("base object is invalid") + +type BaseObject interface { + json.Marshaler + // json.Unmarshaler + ID() uint32 + Type() BaseObjectType + Ptr() unsafe.Pointer + Valid() bool + Destroy() + Context() context.Context + SetMetaData(key string, value interface{}) error + MetaData(key string, value interface{}) error + CancelCtx(error) +} + +type AltBaseObject struct { + id uint32 + ptr unsafe.Pointer + typ BaseObjectType + ctx context.Context + cancelFunc context.CancelCauseFunc +} + +/*type BaseObjectData[T BaseObject] struct { + json.Marshaler + json.Unmarshaler + ID uint32 + Type BaseObjectType + Ptr unsafe.Pointer + Model uint32 +} + +type altBaseObjectData struct { + mvalue.SpecialType + ID uint32 `json:"id"` + Type BaseObjectType `json:"type"` + Ptr string `json:"ptr"` + Model uint32 `json:"model,omitempty"` +} + +func (b *BaseObjectData[T]) MarshalJSON() ([]byte, error) { + return json.Marshal(AltBaseObjectData{ID: b.ID, Type: b.Type, Ptr: "", Model: b.Model, SpecialType: mvalue.SpecialType{Type: mvalue.TypeBaseObject}}) +} + +func (b *BaseObjectData[T]) UnmarshalJSON(data []byte) error { + var obj AltBaseObjectData + var err error + if err = json.Unmarshal(data, &obj); err != nil { + return err + } + + if b.Ptr, err = mvalue.ParsePointer(obj.Ptr); err != nil { + return err + } + b.ID = obj.ID + b.Type = obj.Type + b.Model = obj.Model + return nil +} + +func (b *BaseObjectData[T]) Obj() (T, error) { + return nil, nil // factory.GetBaseObject[T](b.Type, b.Ptr, b.ID, b.Model) +}*/ + +func (b *AltBaseObject) MarshalJSON() ([]byte, error) { + return []byte("{}"), nil // json.Marshal(AltBaseObjectData{ID: b.id, Type: b.typ}) +} + +func (b *AltBaseObject) ID() uint32 { + return b.id +} + +func (b *AltBaseObject) Type() BaseObjectType { + return b.typ +} + +func (b *AltBaseObject) Ptr() unsafe.Pointer { + return b.ptr +} + +func (b *AltBaseObject) Valid() bool { + if b.ctx == nil { + return false + } + + // TODO: check if base object still exists + // probably check where pointer is pointing to + if err := b.ctx.Err(); err != nil { + return false + } + return true +} + +func (b *AltBaseObject) Destroy() { + if b.typ == TypePlayer { + C.player_destroy(b.ptr) + } else if b.typ == TypeVoiceChannel { + C.voice_channel_destroy(b.ptr) + } else if b.typ == TypeCheckpoint { + C.checkpoint_destroy(b.ptr) + } else if b.typ == TypeColShape { + C.col_shape_destroy(b.ptr) + } else if b.typ == TypeVehicle { + C.vehicle_destroy(b.ptr) + } else if b.typ == TypeBlip { + C.blip_destroy(b.ptr) + } +} + +func (b *AltBaseObject) Context() context.Context { + return b.ctx +} + +func (b *AltBaseObject) CancelCtx(err error) { + b.cancelFunc(err) +} + +func (b *AltBaseObject) SetMetaData(key string, v any) error { + /*data, free, err := marshal(v) + if err != nil { + return err + } + defer free() + + cKey := C.CString(key) + defer C.free(unsafe.Pointer(cKey)) + if b.typ == BaseTypePlayer { + C.player_set_meta_data(b.ptr, cKey, data) + } else if b.typ == BaseTypeVehicle { + C.vehicle_set_meta_data(b.ptr, cKey, data) + }*/ + + return nil +} + +func (b *AltBaseObject) MetaData(key string, v any) error { + /*var carr C.struct_array + ckey := C.CString(key) + defer C.free(unsafe.Pointer(ckey)) + if b.typ == BaseTypePlayer { + carr = C.player_get_meta_data(b.ptr, ckey) + } else if b.typ == BaseTypeVehicle { + carr = C.vehicle_get_meta_data(b.ptr, ckey) + }*/ + + return nil // unmarshal(carr, v) +} + +func newBaseObject(typ BaseObjectType, ptr unsafe.Pointer, id uint32) AltBaseObject { + ctx, cancel := context.WithCancelCause(context.Background()) + return AltBaseObject{ + ptr: ptr, + id: id, + typ: typ, + ctx: ctx, + cancelFunc: cancel, + } +} diff --git a/base_object_test.go b/entity/base_object_test.go similarity index 87% rename from base_object_test.go rename to entity/base_object_test.go index 662685e..fa80703 100644 --- a/base_object_test.go +++ b/entity/base_object_test.go @@ -1,12 +1,6 @@ -package altv +package entity -import ( - "testing" - - "github.com/timo972/altv-go/mvalue" -) - -func TestBaseObjectMarshal(t *testing.T) { +/*func TestBaseObjectMarshal(t *testing.T) { testCases := []struct { id uint32 typ BaseObjectType @@ -29,9 +23,9 @@ func TestBaseObjectMarshal(t *testing.T) { t.Errorf("mvalue.Marshal(%+v) = %s; want %s", obj, string(result), testCase.output) } } -} +}*/ -func TestBaseObjectUnmarshal(t *testing.T) { +/*func TestBaseObjectUnmarshal(t *testing.T) { testCases := []struct { id uint32 typ BaseObjectType @@ -70,4 +64,4 @@ func TestBaseObjectUnmarshal(t *testing.T) { continue } } -} +}*/ diff --git a/entity/entity.go b/entity/entity.go new file mode 100644 index 0000000..d104373 --- /dev/null +++ b/entity/entity.go @@ -0,0 +1,9 @@ +package entity + +type Entity interface { + WorldObject +} + +type AltEntity struct { + AltWorldObject +} diff --git a/entity/player.go b/entity/player.go new file mode 100644 index 0000000..67a3866 --- /dev/null +++ b/entity/player.go @@ -0,0 +1,49 @@ +package entity + +// #include "capi.h" +import "C" +import ( + "unsafe" +) + +type Player interface { + Entity + DiscordUserID() int64 + SocialID() uint64 + Health() uint16 + Spawn(x float64, y float64, z float64, delayMs uint) +} + +type AltPlayer struct { + AltEntity +} + +func NewPlayer(ptr unsafe.Pointer, id uint32) Player { + return &AltPlayer{ + AltEntity{ + AltWorldObject{ + AltBaseObject: newBaseObject(TypePlayer, ptr, id), + }, + }, + } +} + +/*func EmptyPlayer() Player { + return &player{} +}*/ + +func (p *AltPlayer) SocialID() uint64 { + return uint64(C.player_get_social_id(p.ptr)) +} + +func (p *AltPlayer) DiscordUserID() int64 { + return int64(C.player_get_discord_id(p.ptr)) +} + +func (p *AltPlayer) Health() uint16 { + return uint16(C.player_get_health(p.ptr)) +} + +func (p *AltPlayer) Spawn(x float64, y float64, z float64, delayMs uint) { + C.player_spawn(p.ptr, C.float(x), C.float(y), C.float(z), C.ulong(delayMs)) +} diff --git a/entity/type.go b/entity/type.go new file mode 100644 index 0000000..eace73b --- /dev/null +++ b/entity/type.go @@ -0,0 +1,30 @@ +package entity + +type BaseObjectType = uint8 + +const ( + TypePlayer BaseObjectType = iota + TypeVehicle + TypePed + TypeNetworkObject + TypeBlip + TypeWebView + TypeVoiceChannel + TypeColShape + TypeCheckpoint + TypeWebSocketClient + TypeHttpClient + TypeAudio + TypeRMLElement + TypeRMLDocument + TypeLocalPlayer + TypeObject + TypeVirtualEntity + TypeVirtualEntityGroup + TypeMarker + TypeTextLabel + TypeLocalPed + TypeLocalVehicle + TypeAudioFilter + TypeSize +) diff --git a/entity/vehicle.go b/entity/vehicle.go new file mode 100644 index 0000000..20daa1e --- /dev/null +++ b/entity/vehicle.go @@ -0,0 +1,33 @@ +package entity + +// #include "capi.h" +import "C" +import ( + "unsafe" +) + +type Vehicle interface { + Entity +} + +type AltVehicle struct { + AltEntity + model uint32 +} + +func NewVehicle(ptr unsafe.Pointer, id uint32, model uint32) Vehicle { + v := &AltVehicle{ + AltEntity{ + AltWorldObject{ + AltBaseObject: newBaseObject(TypeVehicle, ptr, id), + }, + }, + model, + } + + return v +} + +func (v *AltVehicle) Model() uint32 { + return v.model +} diff --git a/entity/world_object.go b/entity/world_object.go new file mode 100644 index 0000000..ca61da1 --- /dev/null +++ b/entity/world_object.go @@ -0,0 +1,9 @@ +package entity + +type WorldObject interface { + BaseObject +} + +type AltWorldObject struct { + AltBaseObject +} diff --git a/events/client_script.go b/event/client_script.go similarity index 72% rename from events/client_script.go rename to event/client_script.go index 70ef323..b20e029 100644 --- a/events/client_script.go +++ b/event/client_script.go @@ -1,10 +1,12 @@ -package events +package event import ( "fmt" "unsafe" - "github.com/timo972/altv-go" + "github.com/timo972/altv-go/altlog" + "github.com/timo972/altv-go/entity" + "github.com/timo972/altv-go/factory" "golang.org/x/exp/slices" ) @@ -15,11 +17,11 @@ type ClientEventListener func(ctx *ClientCtx) func numClientEventListeners(eventName string) int { count := 0 - if events, ok := on.clientScriptEvents[eventName]; ok { - count += len(events) + if event, ok := on.clientScriptEvents[eventName]; ok { + count += len(event) } - if events, ok := once.clientScriptEvents[eventName]; ok { - count += len(events) + if event, ok := once.clientScriptEvents[eventName]; ok { + count += len(event) } return count @@ -74,23 +76,23 @@ func altClientScriptEvent(e C.struct_entity, cName *C.char, arr C.struct_array) ctx.defaults() var err error - ctx.p, err = altv.GetBaseObject[altv.Player](altv.BaseObjectType(e.typ), unsafe.Pointer(e.ptr), uint32(e.id), 0) + ctx.p, err = factory.GetBaseObject[entity.Player](entity.BaseObjectType(e.typ), unsafe.Pointer(e.ptr), uint32(e.id), 0) if err != nil { - altv.LogError(fmt.Sprintf("[Go] ClientScriptEvent: %v", err)) + altlog.Errorln(fmt.Sprintf("[Go] ClientScriptEvent: %v", err)) return } ctx.copyArgs(arr) - if events, ok := once.clientScriptEvents[evt]; ok { - for _, event := range events { + if event, ok := once.clientScriptEvents[evt]; ok { + for _, event := range event { event(ctx) } once.clientScriptEvents[evt] = make([]ClientEventListener, 0) } - if events, ok := on.clientScriptEvents[evt]; ok { - for _, event := range events { + if event, ok := on.clientScriptEvents[evt]; ok { + for _, event := range event { event(ctx) } } diff --git a/events/connection_queue.go b/event/connection_queue.go similarity index 95% rename from events/connection_queue.go rename to event/connection_queue.go index d4014ff..017d96c 100644 --- a/events/connection_queue.go +++ b/event/connection_queue.go @@ -1,4 +1,4 @@ -package events +package event import ( "unsafe" @@ -10,8 +10,8 @@ import ( // #include "capi.h" import "C" -type connectionQueueAddListener func(connectionInfo altv.ConnectionInfo) -type connectionQueueRemoveListener func(connectionInfo altv.ConnectionInfo) +type connectionQueueAddListener func(connectionInfo *altv.ConnectionInfo) +type connectionQueueRemoveListener func(connectionInfo *altv.ConnectionInfo) func checkConnectionQueueAdd() { lisCount := len(on.connectionQueueAddEvents) + len(once.connectionQueueAddEvents) diff --git a/events/console_command.go b/event/console_command.go similarity index 98% rename from events/console_command.go rename to event/console_command.go index 1599433..d4378e7 100644 --- a/events/console_command.go +++ b/event/console_command.go @@ -1,4 +1,4 @@ -package events +package event // #include "capi.h" import "C" diff --git a/events/ctx.go b/event/ctx.go similarity index 78% rename from events/ctx.go rename to event/ctx.go index a039478..d906ead 100644 --- a/events/ctx.go +++ b/event/ctx.go @@ -1,4 +1,4 @@ -package events +package event import ( "context" @@ -6,7 +6,7 @@ import ( "sync" "github.com/goccy/go-reflect" - "github.com/timo972/altv-go" + "github.com/timo972/altv-go/entity" "github.com/timo972/altv-go/mvalue" ) @@ -30,7 +30,7 @@ type Ctx struct { type ClientCtx struct { Ctx - p altv.Player + p entity.Player } func (c *Ctx) reset() { @@ -47,12 +47,12 @@ func (c *Ctx) copyArgs(cargs C.struct_array) { size := int(cargs.size) c.bufs = make([][]byte, size) c.cache = make([]interface{}, size) - log.Printf("events::ctx::copyArgs -> array size %d", size) + log.Printf("event::ctx::copyArgs -> array size %d", size) cbufs := (*[1 << 28]C.struct_array)(cargs.array)[:size:size] for i := 0; i < size; i++ { c.bufs[i] = C.GoBytes(cbufs[i].array, C.int(cbufs[i].size)) - log.Printf("events::ctx::copyArgs -> array[%d]: %+v = %s size %d === %d", i, c.bufs[i], c.bufs[i], len(c.bufs[i]), cbufs[i].size) + log.Printf("event::ctx::copyArgs -> array[%d]: %+v = %s size %d === %d", i, c.bufs[i], c.bufs[i], len(c.bufs[i]), cbufs[i].size) } } @@ -67,7 +67,7 @@ func (c *Ctx) Value(i int, v interface{}) error { } if c.cache[i] != nil { - log.Printf("events::ctx::Value (cached) -> %d: %v", i, c.cache[i]) + log.Printf("event::ctx::Value (cached) -> %d: %v", i, c.cache[i]) reflect.ValueNoEscapeOf(v).Set(reflect.ValueNoEscapeOf(c.cache[i])) return nil } @@ -78,7 +78,7 @@ func (c *Ctx) Value(i int, v interface{}) error { } c.cache[i] = v - log.Printf("events::ctx::Value -> %d: %v", i, v) + log.Printf("event::ctx::Value -> %d: %v", i, v) return nil } @@ -94,6 +94,6 @@ func (c *ClientCtx) reset() { } // Player returns the player that triggered the event -func (c *ClientCtx) Player() altv.Player { +func (c *ClientCtx) Player() entity.Player { return c.p } diff --git a/events/emit.go b/event/emit.go similarity index 85% rename from events/emit.go rename to event/emit.go index b656903..2744ed0 100644 --- a/events/emit.go +++ b/event/emit.go @@ -1,9 +1,9 @@ -package events +package event import ( "unsafe" - "github.com/timo972/altv-go" + "github.com/timo972/altv-go/entity" "github.com/timo972/altv-go/internal/cutil" "github.com/timo972/altv-go/mvalue" ) @@ -41,9 +41,9 @@ func marshalArgs(args []any) (C.struct_array, func(), error) { return cargs, free, nil } -func newPlayerCArray(p []altv.Player) (C.struct_array, cutil.FreeArrayFunc) { +func newPlayerCArray(p []entity.Player) (C.struct_array, cutil.FreeArrayFunc) { // 8 is sizeof void ptr on 64bit - ptr, size, free := cutil.NewCArrayFunc[altv.Player, unsafe.Pointer](p, 8, func(item altv.Player) unsafe.Pointer { + ptr, size, free := cutil.NewCArrayFunc[entity.Player, unsafe.Pointer](p, 8, func(item entity.Player) unsafe.Pointer { return item.Ptr() }) @@ -78,7 +78,7 @@ func Emit(eventName string, args ...any) error { return nil } -func EmitClient(p altv.Player, evt string, args ...any) error { +func EmitClient(p entity.Player, evt string, args ...any) error { cevt := C.CString(evt) defer C.free(unsafe.Pointer(cevt)) @@ -92,7 +92,7 @@ func EmitClient(p altv.Player, evt string, args ...any) error { return nil } -func EmitClients(p []altv.Player, evt string, args ...any) error { +func EmitClients(p []entity.Player, evt string, args ...any) error { cclients, freeClients := newPlayerCArray(p) defer freeClients() diff --git a/events/errors.go b/event/errors.go similarity index 92% rename from events/errors.go rename to event/errors.go index 1902997..5a5d8a4 100644 --- a/events/errors.go +++ b/event/errors.go @@ -1,4 +1,4 @@ -package events +package event import "errors" diff --git a/events/events.go b/event/events.go similarity index 99% rename from events/events.go rename to event/events.go index 4cdc20b..58f5d55 100644 --- a/events/events.go +++ b/event/events.go @@ -1,4 +1,4 @@ -package events +package event // #cgo CFLAGS: -I../internal/c-api/lib // #cgo linux LDFLAGS: -L../internal/c-api/lib/linux -lcapi -ldl -g diff --git a/events/player_connect.go b/event/player_connect.go similarity index 75% rename from events/player_connect.go rename to event/player_connect.go index ddf0b26..4fe3b77 100644 --- a/events/player_connect.go +++ b/event/player_connect.go @@ -1,4 +1,4 @@ -package events +package event // #include "capi.h" import "C" @@ -6,11 +6,13 @@ import ( "fmt" "unsafe" - "github.com/timo972/altv-go" + "github.com/timo972/altv-go/altlog" + "github.com/timo972/altv-go/entity" + "github.com/timo972/altv-go/factory" "golang.org/x/exp/slices" ) -type playerConnectListener func(p altv.Player) +type playerConnectListener func(p entity.Player) func (e *subscriber) PlayerConnect(listener playerConnectListener) int { e.playerConnectEvents = append(e.playerConnectEvents, listener) @@ -38,9 +40,9 @@ func checkPlayerConnect() { //export altPlayerConnectEvent func altPlayerConnectEvent(e C.struct_entity) { - p, err := altv.GetBaseObject[altv.Player](altv.BaseObjectType(e.typ), unsafe.Pointer(e.ptr), uint32(e.id), 0) + p, err := factory.GetBaseObject[entity.Player](entity.BaseObjectType(e.typ), unsafe.Pointer(e.ptr), uint32(e.id), 0) if err != nil { - altv.LogError(fmt.Sprintf("[Go] PlayerConnect: %v", err)) + altlog.Errorln(fmt.Sprintf("[Go] PlayerConnect: %v", err)) return } diff --git a/events/player_damage.go b/event/player_damage.go similarity index 67% rename from events/player_damage.go rename to event/player_damage.go index e06d512..ddbd6ff 100644 --- a/events/player_damage.go +++ b/event/player_damage.go @@ -1,17 +1,20 @@ -package events +package event import ( "C" - "github.com/timo972/altv-go" "golang.org/x/exp/slices" ) import ( "fmt" "unsafe" + + "github.com/timo972/altv-go/altlog" + "github.com/timo972/altv-go/entity" + "github.com/timo972/altv-go/factory" ) -type playerDamageListener = func(p altv.Player, attacker altv.Entity, healthDamage uint16, armourDamage uint16, weapon uint32) +type playerDamageListener = func(p entity.Player, attacker entity.Entity, healthDamage uint16, armourDamage uint16, weapon uint32) func checkPlayerDamageEvent() { lisCount := len(on.playerDamageEvents) + len(once.playerDamageEvents) @@ -38,14 +41,14 @@ func (unsub *unsubscriber) PlayerDamage(id int) error { //export altPlayerDamageEvent func altPlayerDamageEvent(cp C.struct_entity, ce C.struct_entity, healthDmg C.ushort, armourDmg C.ushort, weap C.ulong) { - p, err := altv.GetBaseObject[altv.Player](altv.BaseObjectType(cp.typ), unsafe.Pointer(cp.ptr), uint32(cp.id), 0) + p, err := factory.GetBaseObject[entity.Player](entity.BaseObjectType(cp.typ), unsafe.Pointer(cp.ptr), uint32(cp.id), 0) if err != nil { - altv.LogError(fmt.Sprintf("[Go] PlayerDamage: %v", err)) + altlog.Errorln(fmt.Sprintf("[Go] PlayerDamage: %v", err)) return } - e, err := altv.GetBaseObject[altv.Entity](altv.BaseObjectType(ce.typ), unsafe.Pointer(ce.ptr), uint32(ce.id), uint32(ce.model)) + e, err := factory.GetBaseObject[entity.Entity](entity.BaseObjectType(ce.typ), unsafe.Pointer(ce.ptr), uint32(ce.id), uint32(ce.model)) if err != nil { - altv.LogError(fmt.Sprintf("[Go] PlayerDamage: %v", err)) + altlog.Errorln(fmt.Sprintf("[Go] PlayerDamage: %v", err)) return } diff --git a/events/register.go b/event/register.go similarity index 73% rename from events/register.go rename to event/register.go index 8564ea5..7b927e0 100644 --- a/events/register.go +++ b/event/register.go @@ -1,4 +1,4 @@ -package events +package event // #include "capi.h" // #include @@ -6,30 +6,30 @@ import "C" import ( "unsafe" - "github.com/timo972/altv-go" + "github.com/timo972/altv-go/resource" ) var queue = map[uint16]struct{}{} func registerOnEvent(event uint16) { - if !altv.Ready() { + if !resource.Ready() { queue[event] = struct{}{} return } - cresource := C.CString(altv.CurrentResource.Name()) + cresource := C.CString(resource.Current.Name()) defer C.free(unsafe.Pointer(cresource)) C.runtime_register_alt_event(cresource, C.ushort(event)) } func unregisterOnEvent(event uint16) { - if !altv.Ready() { + if !resource.Ready() { delete(queue, event) return } - cresource := C.CString(altv.CurrentResource.Name()) + cresource := C.CString(resource.Current.Name()) defer C.free(unsafe.Pointer(cresource)) C.runtime_unregister_alt_event(cresource, C.ushort(event)) diff --git a/events/resource_error.go b/event/resource_error.go similarity index 98% rename from events/resource_error.go rename to event/resource_error.go index 3becebb..fbadb69 100644 --- a/events/resource_error.go +++ b/event/resource_error.go @@ -1,4 +1,4 @@ -package events +package event // #include "capi.h" import "C" diff --git a/events/resource_stop.go b/event/resource_stop.go similarity index 98% rename from events/resource_stop.go rename to event/resource_stop.go index fe3c60a..fefdeb4 100644 --- a/events/resource_stop.go +++ b/event/resource_stop.go @@ -1,4 +1,4 @@ -package events +package event // #include "capi.h" import "C" diff --git a/events/server_script.go b/event/server_script.go similarity index 81% rename from events/server_script.go rename to event/server_script.go index 661e6c9..1a02497 100644 --- a/events/server_script.go +++ b/event/server_script.go @@ -1,4 +1,4 @@ -package events +package event import ( "golang.org/x/exp/slices" @@ -11,11 +11,11 @@ type ServerEventListener func(ctx *Ctx) func numServerEventListeners(eventName string) int { count := 0 - if events, ok := on.serverScriptEvents[eventName]; ok { - count += len(events) + if event, ok := on.serverScriptEvents[eventName]; ok { + count += len(event) } - if events, ok := once.serverScriptEvents[eventName]; ok { - count += len(events) + if event, ok := once.serverScriptEvents[eventName]; ok { + count += len(event) } return count @@ -71,15 +71,15 @@ func altServerScriptEvent(cName *C.char, arr C.struct_array) { ctx.copyArgs(arr) - if events, ok := once.serverScriptEvents[evt]; ok { - for _, event := range events { + if event, ok := once.serverScriptEvents[evt]; ok { + for _, event := range event { event(ctx) } once.serverScriptEvents[evt] = make([]ServerEventListener, 0) } - if events, ok := on.serverScriptEvents[evt]; ok { - for _, event := range events { + if event, ok := on.serverScriptEvents[evt]; ok { + for _, event := range event { event(ctx) } } diff --git a/events/server_started.go b/event/server_started.go similarity index 98% rename from events/server_started.go rename to event/server_started.go index 3494af5..efe214b 100644 --- a/events/server_started.go +++ b/event/server_started.go @@ -1,4 +1,4 @@ -package events +package event import ( "fmt" diff --git a/export/export.go b/export/export.go new file mode 100644 index 0000000..7074f5d --- /dev/null +++ b/export/export.go @@ -0,0 +1,38 @@ +package export + +import ( + "errors" +) + +// #cgo CFLAGS: -I../internal/c-api/lib +// #cgo linux LDFLAGS: -L../internal/c-api/lib/linux -lcapi -ldl -g +// #cgo windows LDFLAGS: -L../internal/c-api/lib/win32 -lcapi -ldl -g +// #cgo CXXFLAGS: -std=c++14 +// #include +// #include "capi.h" +import "C" + +var ErrFailedToRegister = errors.New("failed to register export") + +// Export exports a value which can be imported by other resources, no matter which language. See mvalue serialization for more information about supported values. +func New(name string, value any) error { + /*carr, free, err := marshal(value) + if err != nil { + return err + } + defer free() + + crname := C.CString(resource.Current.Name()) + defer C.free(unsafe.Pointer(crname)) + + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + + ok := C.runtime_register_alt_export(crname, cname, carr) + + if int(ok) != 1 { + return ErrFailedToRegister + }*/ + + return nil +} diff --git a/exports.go b/exports.go deleted file mode 100644 index 0fdba34..0000000 --- a/exports.go +++ /dev/null @@ -1,57 +0,0 @@ -package altv - -import ( - "errors" - "unsafe" - - "github.com/timo972/altv-go/mvalue" -) - -/* -#include -#include "capi.h" -*/ -import "C" - -var ErrFailedToRegisterExport = errors.New("failed to register export") - -func resourceImport(resourceName string, name string, out any) error { - crname := C.CString(resourceName) - defer C.free(unsafe.Pointer(crname)) - - cname := C.CString(name) - defer C.free(unsafe.Pointer(cname)) - - carr := C.runtime_get_alt_export(crname, cname) - data := C.GoBytes(carr.array, C.int(carr.size)) - - return mvalue.Unmarshal(data, out) -} - -// Export exports a value which can be imported by other resources, no matter which language. See mvalue serialization for more information about supported values. -func Export(name string, value any) error { - carr, free, err := marshal(value) - if err != nil { - return err - } - defer free() - - crname := C.CString(CurrentResource.Name()) - defer C.free(unsafe.Pointer(crname)) - - cname := C.CString(name) - defer C.free(unsafe.Pointer(cname)) - - ok := C.runtime_register_alt_export(crname, cname, carr) - - if int(ok) != 1 { - return ErrFailedToRegisterExport - } - - return nil -} - -// Import imports a value exported by another resource, no matter which language. See mvalue serialization for more information about supported values. -func Import(resourceName string, name string, out any) error { - return resourceImport(resourceName, name, out) -} diff --git a/factories.go b/factories.go deleted file mode 100644 index a86dc85..0000000 --- a/factories.go +++ /dev/null @@ -1,102 +0,0 @@ -package altv - -// #include "capi.h" -import "C" -import ( - "errors" - "fmt" - "sync" - "unsafe" -) - -var baseObjectCache = sync.Map{} -var factories = sync.Map{} -var ErrNoFactory = errors.New("no factory found") -var ErrInvalidFactory = errors.New("invalid factory") - -func getEntityData(e C.struct_entity) (typ BaseObjectType, ptr unsafe.Pointer, id uint32, model uint32) { - ptr = unsafe.Pointer(e.ptr) - id = uint32(e.id) - typ = BaseObjectType(e.typ) - model = uint32(e.model) - - return -} - -func getOrCreateBaseObject[Type BaseObject](typ BaseObjectType, ptr unsafe.Pointer, id uint32, model uint32) (object Type, err error) { - b, ok := baseObjectCache.Load(id) - if !ok { - f, ok := factories.Load(typ) - if !ok { - return object, ErrNoFactory - } - - if typ == BaseTypeVehicle { - factory, ok := f.(VehicleFactory) - if !ok { - return object, ErrInvalidFactory - } - - object = factory(ptr, id, model).(Type) - baseObjectCache.Store(id, object) - return object, nil - } - - - if typ == BaseTypePlayer { - factory, ok := f.(BaseFactory[Player]) - if !ok { - return object, ErrInvalidFactory - } - - object = factory(ptr, id).(Type) - baseObjectCache.Store(id, object) - return object, nil - } - - factory, ok := f.(BaseFactory[Type]) - if !ok { - fmt.Printf("factory is not BaseFactory[Type]: %T != %T\n", factory, f) - return object, ErrInvalidFactory - } - - object = factory(ptr, id) - baseObjectCache.Store(id, object) - return object, nil - } - - fmt.Printf("loaded baseObject typ %v id %v from cache\n", typ, id) - - return b.(Type), nil -} - -type BaseFactory[Type BaseObject] func(ptr unsafe.Pointer, id uint32) Type -type VehicleFactory func(ptr unsafe.Pointer, id uint32, model uint32) Vehicle - -// SetPlayerFactory sets the factory used by the package to create player struct instances -func SetPlayerFactory(factory BaseFactory[Player]) { - factories.Store(BaseTypePlayer, factory) - fmt.Println("Player Factory loaded", BaseTypePlayer, factory) -} - -func SetVehicleFactory(factory VehicleFactory) { - factories.Store(BaseTypeVehicle, factory) - fmt.Println("Vehicle Factory loaded", BaseTypeVehicle, factory) -} - -func init() { - SetPlayerFactory(NewPlayer) - SetVehicleFactory(NewVehicle) -} - -// getBaseObject ! internal only ! -func getBaseObject[Type BaseObject](p C.struct_entity) (Type, error) { - typ, ptr, id, model := getEntityData(p) - - return getOrCreateBaseObject[Type](typ, ptr, id, model) -} - -// GetBaseObject ! internal only ! -func GetBaseObject[Type BaseObject](typ BaseObjectType, ptr unsafe.Pointer, id uint32, model uint32) (Type, error) { - return getOrCreateBaseObject[Type](typ, ptr, id, model) -} diff --git a/factory/factories.go b/factory/factories.go new file mode 100644 index 0000000..c7b2e38 --- /dev/null +++ b/factory/factories.go @@ -0,0 +1,124 @@ +package factory + +// #cgo CFLAGS: -I../internal/c-api/lib +// #cgo linux LDFLAGS: -L../internal/c-api/lib/linux -lcapi -ldl -g +// #cgo windows LDFLAGS: -L../internal/c-api/lib/win32 -lcapi -ldl -g +// #cgo CXXFLAGS: -std=c++14 +// #include +// #include "capi.h" +import "C" +import ( + "errors" + "fmt" + "sync" + "unsafe" + + "github.com/timo972/altv-go/altlog" + "github.com/timo972/altv-go/entity" +) + +var baseObjectCache = sync.Map{} +var factories = sync.Map{} +var ErrNoFactory = errors.New("no factory found") +var ErrInvalidFactory = errors.New("invalid factory") + +func getOrCreateBaseObject[Type entity.BaseObject](typ entity.BaseObjectType, ptr unsafe.Pointer, id uint32, model uint32) (object Type, err error) { + b, ok := baseObjectCache.Load(id) + if !ok { + f, ok := factories.Load(typ) + if !ok { + return object, ErrNoFactory + } + + if typ == entity.TypeVehicle { + factory, ok := f.(VehicleFactory) + if !ok { + return object, ErrInvalidFactory + } + + object = factory(ptr, id, model).(Type) + baseObjectCache.Store(id, object) + return object, nil + } + + if typ == entity.TypePlayer { + factory, ok := f.(BaseFactory[entity.Player]) + if !ok { + return object, ErrInvalidFactory + } + + object = factory(ptr, id).(Type) + baseObjectCache.Store(id, object) + return object, nil + } + + factory, ok := f.(BaseFactory[Type]) + if !ok { + fmt.Printf("factory is not BaseFactory[Type]: %T != %T\n", factory, f) + return object, ErrInvalidFactory + } + + object = factory(ptr, id) + baseObjectCache.Store(id, object) + return object, nil + } + + fmt.Printf("loaded baseObject typ %v id %v from cache\n", typ, id) + + return b.(Type), nil +} + +type BaseFactory[Type entity.BaseObject] func(ptr unsafe.Pointer, id uint32) Type +type VehicleFactory func(ptr unsafe.Pointer, id uint32, model uint32) entity.Vehicle + +// SetPlayerFactory sets the factory used by the package to create player struct instances +func SetPlayerFactory(factory BaseFactory[entity.Player]) { + factories.Store(entity.TypePlayer, factory) + fmt.Println("Player Factory loaded", entity.TypePlayer, factory) +} + +func SetVehicleFactory(factory VehicleFactory) { + factories.Store(entity.TypeVehicle, factory) + fmt.Println("Vehicle Factory loaded", entity.TypeVehicle, factory) +} + +func init() { + SetPlayerFactory(entity.NewPlayer) + SetVehicleFactory(entity.NewVehicle) +} + +// GetBaseObject ! internal only ! +func GetBaseObject[Type entity.BaseObject](typ entity.BaseObjectType, ptr unsafe.Pointer, id uint32, model uint32) (Type, error) { + return getOrCreateBaseObject[Type](typ, ptr, id, model) +} + +//export altCreateBaseObject +func altCreateBaseObject(e C.struct_entity) { + fmt.Printf("altCreateBaseObject\n") + id := uint32(e.id) + typ := entity.BaseObjectType(e.typ) + ptr := unsafe.Pointer(e.ptr) + model := uint32(e.model) + + if _, err := GetBaseObject[entity.BaseObject](typ, ptr, id, model); err != nil { + altlog.Errorln(fmt.Sprintf("altCreateBaseObject: %s", err.Error())) + } +} + +//export altRemoveBaseObject +func altRemoveBaseObject(e C.struct_entity) { + fmt.Printf("altRemoveBaseObject\n") + id := uint32(e.id) + typ := entity.BaseObjectType(e.typ) + ptr := unsafe.Pointer(e.ptr) + model := uint32(e.model) + + obj, err := GetBaseObject[entity.BaseObject](typ, ptr, id, model) + if err != nil { + altlog.Errorln(fmt.Sprintf("altRemoveBaseObject: %s", err.Error())) + return + } + + obj.CancelCtx(entity.ErrInvalidBaseObject) + baseObjectCache.Delete(id) +} diff --git a/factories_test.go b/factory/factories_test.go similarity index 66% rename from factories_test.go rename to factory/factories_test.go index 5150a4d..5cc052e 100644 --- a/factories_test.go +++ b/factory/factories_test.go @@ -1,18 +1,20 @@ -package altv +package factory import ( "testing" "unsafe" + + "github.com/timo972/altv-go/entity" ) type testPlayer struct { - Player + entity.Player username string } -func testPlayerFactory(ptr unsafe.Pointer, id uint32) Player { +func testPlayerFactory(ptr unsafe.Pointer, id uint32) entity.Player { return &testPlayer{ - Player: NewPlayer(ptr, id), + Player: entity.NewPlayer(ptr, id), } } @@ -27,12 +29,12 @@ func TestPlayerFactory(t *testing.T) { } type testVehicle struct { - Vehicle + entity.Vehicle } -func testVehicleFactory(ptr unsafe.Pointer, id uint32, model uint32) Vehicle { +func testVehicleFactory(ptr unsafe.Pointer, id uint32, model uint32) entity.Vehicle { return &testVehicle{ - Vehicle: NewVehicle(ptr, id, model), + Vehicle: entity.NewVehicle(ptr, id, model), } } diff --git a/file.go b/file.go deleted file mode 100644 index 968442b..0000000 --- a/file.go +++ /dev/null @@ -1,38 +0,0 @@ -package altv - -import ( - "io" - "strings" - "unsafe" -) - -// #include -// #include "capi.h" -import "C" - -// FileExists checks if the file at the given path exists. -func FileExists(path string) bool { - cStr := C.CString(path) - defer C.free(unsafe.Pointer(cStr)) - - return int(C.core_file_exists(cStr)) == 1 -} - -// FileReadAll reads the file at the given path and returns its content as a string. -func FileReadAll(path string) (string, error) { - cStr := C.CString(path) - defer C.free(unsafe.Pointer(cStr)) - - cContent := C.core_read_file(cStr) - return C.GoString(cContent), nil -} - -// FileRead reads the file at the given path and returns an io.Reader. -func FileRead(path string) (io.Reader, error) { - data, err := FileReadAll(path) - if err != nil { - return nil, err - } - - return strings.NewReader(data), nil -} diff --git a/imprt/import.go b/imprt/import.go new file mode 100644 index 0000000..5cb3f7e --- /dev/null +++ b/imprt/import.go @@ -0,0 +1,33 @@ +package imprt + +import ( + "unsafe" + + "github.com/timo972/altv-go/mvalue" +) + +// #cgo CFLAGS: -I../internal/c-api/lib +// #cgo linux LDFLAGS: -L../internal/c-api/lib/linux -lcapi -ldl -g +// #cgo windows LDFLAGS: -L../internal/c-api/lib/win32 -lcapi -ldl -g +// #cgo CXXFLAGS: -std=c++14 +// #include +// #include "capi.h" +import "C" + +func resourceImport(resourceName string, name string, out any) error { + crname := C.CString(resourceName) + defer C.free(unsafe.Pointer(crname)) + + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + + carr := C.runtime_get_alt_export(crname, cname) + data := C.GoBytes(carr.array, C.int(carr.size)) + + return mvalue.Unmarshal(data, out) +} + +// New imports a value exported by another resource, no matter which language. See mvalue serialization for more information about supported values. +func New(resourceName string, name string, out any) error { + return resourceImport(resourceName, name, out) +} diff --git a/internal/c-api/CMakeLists.txt b/internal/c-api/CMakeLists.txt index 02f3612..1d953f9 100644 --- a/internal/c-api/CMakeLists.txt +++ b/internal/c-api/CMakeLists.txt @@ -11,14 +11,6 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/lib/linux") endif() MESSAGE(STATUS "Compiling altv-go-capi:" ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}) -# Generate c-api header & source files -add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/out/capi.h ${CMAKE_CURRENT_BINARY_DIR}/out/capi.c - COMMAND node ../../../runtime/tools/pkg-capi.js -) -# Copy header to lib directory -# FIXME: -#configure_file(${CMAKE_CURRENT_BINARY_DIR}/out/capi.h ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/../capi.h COPYONLY) - # Aggiungere l'origine all'eseguibile di questo progetto. add_library (capi STATIC "./out/capi.c" "./out/capi.h") diff --git a/internal/c-api/lib/capi.h b/internal/c-api/lib/capi.h index e527f8e..2c9d204 100644 --- a/internal/c-api/lib/capi.h +++ b/internal/c-api/lib/capi.h @@ -1,4 +1,3 @@ - #ifndef CAPI_MODULE #define CAPI_MODULE @@ -173,1241 +172,2384 @@ typedef struct boneInfo { const char* name; } BoneInfo; -// /home/timo/dev/os/altv/altv-go/runtime/src/capi/BaseObject.h Module.h - -// /home/timo/dev/os/altv/altv-go/runtime/src/capi/BaseObject.h Module.h -// /home/timo/dev/os/altv/altv-go/runtime/src/capi/Blip.h Module.h typedef int (*capi_blip_get_type)(void *c); -typedef int (*capi_blip_has_meta_data)(void *base, const char *key); -typedef Array (*capi_blip_get_meta_data)(void *base, const char *key); -typedef void (*capi_blip_set_meta_data)(void *base, const char *key, Array data); -typedef void (*capi_blip_delete_meta_data)(void *base, const char *key); + +typedef int (*capi_blip_has_meta_data)(void *base, const char *key); + +typedef Array (*capi_blip_get_meta_data)(void *base, const char *key); + +typedef void (*capi_blip_set_meta_data)(void *base, const char *key, Array data); + +typedef void (*capi_blip_delete_meta_data)(void *base, const char *key); + typedef void (*capi_blip_destroy)(void *b); -typedef int (*capi_blip_is_valid)(const char *resourceName, void *p); + +typedef int (*capi_blip_is_valid)(const char *resourceName, void *p); + typedef Position (*capi_blip_get_position)(void *p); -typedef void (*capi_blip_set_position)(void *p, float x, float y, float z); + +typedef void (*capi_blip_set_position)(void *p, float x, float y, float z); + typedef long (*capi_blip_get_dimension)(void *p); -typedef void (*capi_blip_set_dimension)(void *p, long dimension); + +typedef void (*capi_blip_set_dimension)(void *p, long dimension); + typedef int (*capi_blip_is_global)(void *b); + typedef Array (*capi_blip_get_targets)(void *b); + typedef int (*capi_blip_is_attached)(void *b); + typedef Entity (*capi_blip_attached_to)(void *b); -typedef void (*capi_blip_attach_to)(void *b, Entity e); + +typedef void (*capi_blip_attach_to)(void *b, Entity e); + typedef unsigned char (*capi_blip_get_blip_type)(void *b); -typedef Vector2 (*capi_blip_get_scale_x_y)(void *b); -typedef void (*capi_blip_set_scale_x_y)(void *b, Vector2 scale); + +typedef Vector2 (*capi_blip_get_scale_xy)(void *b); + +typedef void (*capi_blip_set_scale_xy)(void *b, Vector2 scale); + typedef int (*capi_blip_get_display)(void *b); -typedef void (*capi_blip_set_display)(void *b, int display); + +typedef void (*capi_blip_set_display)(void *b, int display); + typedef int (*capi_blip_get_sprite)(void *b); + typedef int (*capi_blip_get_color)(void *b); + typedef RGBA (*capi_blip_get_secondary_color)(void *b); + typedef int (*capi_blip_get_alpha)(void *b); + typedef int (*capi_blip_get_flash_timer)(void *b); + typedef int (*capi_blip_get_flash_interval)(void *b); + typedef int (*capi_blip_get_as_friendly)(void *b); + typedef int (*capi_blip_get_route)(void *b); + typedef int (*capi_blip_get_bright)(void *b); + typedef int (*capi_blip_get_number)(void *b); + typedef int (*capi_blip_get_show_cone)(void *b); + typedef int (*capi_blip_get_flashes)(void *b); + typedef int (*capi_blip_get_flashes_alternate)(void *b); + typedef int (*capi_blip_get_as_short_range)(void *b); + typedef int (*capi_blip_get_priority)(void *b); + typedef float (*capi_blip_get_rotation)(void *b); + typedef const char * (*capi_blip_get_gxt_name)(void *b); + typedef const char * (*capi_blip_get_name)(void *b); + typedef RGBA (*capi_blip_get_route_color)(void *b); + typedef int (*capi_blip_get_pulse)(void *b); + typedef int (*capi_blip_get_as_mission_creator)(void *b); + typedef int (*capi_blip_get_tick_visible)(void *b); + typedef int (*capi_blip_get_heading_indicator_visible)(void *b); + typedef int (*capi_blip_get_outline_indicator_visible)(void *b); + typedef int (*capi_blip_get_friend_indicator_visible)(void *b); + typedef int (*capi_blip_get_crew_indicator_visible)(void *b); + typedef int (*capi_blip_get_category)(void *b); + typedef int (*capi_blip_get_as_high_detail)(void *b); + typedef int (*capi_blip_get_shrinked)(void *b); -typedef void (*capi_blip_set_sprite)(void *b, int sprite); -typedef void (*capi_blip_set_color)(void *b, int color); -typedef void (*capi_blip_set_route)(void *b, int state); -typedef void (*capi_blip_set_route_color)(void *b, RGBA color); -typedef void (*capi_blip_set_secondary_color)(void *b, RGBA color); -typedef void (*capi_blip_set_alpha)(void *b, int alpha); -typedef void (*capi_blip_set_flash_timer)(void *b, int timer); -typedef void (*capi_blip_set_flash_interval)(void *b, int interval); -typedef void (*capi_blip_set_as_friendly)(void *b, int friendly); -typedef void (*capi_blip_set_bright)(void *b, int bright); -typedef void (*capi_blip_set_number)(void *b, int number); -typedef void (*capi_blip_set_show_cone)(void *b, int state); -typedef void (*capi_blip_set_flashes)(void *b, int state); -typedef void (*capi_blip_set_flashes_alternate)(void *b, int state); -typedef void (*capi_blip_set_as_short_range)(void *b, int state); -typedef void (*capi_blip_set_priority)(void *b, int state); -typedef void (*capi_blip_set_rotation)(void *b, float rot); -typedef void (*capi_blip_set_gxt_name)(void *b, const char *name); -typedef void (*capi_blip_set_name)(void *b, const char *name); -typedef void (*capi_blip_set_pulse)(void *b, int val); -typedef void (*capi_blip_set_as_mission_creator)(void *b, int val); -typedef void (*capi_blip_set_tick_visible)(void *b, int val); -typedef void (*capi_blip_set_heading_indicator_visible)(void *b, int val); -typedef void (*capi_blip_set_outline_indicator_visible)(void *b, int val); -typedef void (*capi_blip_set_friend_indicator_visible)(void *b, int val); -typedef void (*capi_blip_set_crew_indicator_visible)(void *b, int val); -typedef void (*capi_blip_set_category)(void *b, int val); -typedef void (*capi_blip_set_as_high_detail)(void *b, int val); -typedef void (*capi_blip_set_shrinked)(void *b, int val); -typedef void (*capi_blip_fade)(void *b, unsigned int opacity, unsigned int duration); - - -// /home/timo/dev/os/altv/altv-go/runtime/src/capi/Blip.h Module.h -int blip_get_type(void *c); -int blip_has_meta_data(void *base, const char *key); -Array blip_get_meta_data(void *base, const char *key); -void blip_set_meta_data(void *base, const char *key, Array data); -void blip_delete_meta_data(void *base, const char *key); -void blip_destroy(void *b); -int blip_is_valid(const char *resourceName, void *p); -Position blip_get_position(void *p); -void blip_set_position(void *p, float x, float y, float z); -long blip_get_dimension(void *p); -void blip_set_dimension(void *p, long dimension); -int blip_is_global(void *b); -Array blip_get_targets(void *b); -int blip_is_attached(void *b); -Entity blip_attached_to(void *b); -void blip_attach_to(void *b, Entity e); -unsigned char blip_get_blip_type(void *b); -Vector2 blip_get_scale_x_y(void *b); -void blip_set_scale_x_y(void *b, Vector2 scale); -int blip_get_display(void *b); -void blip_set_display(void *b, int display); -int blip_get_sprite(void *b); -int blip_get_color(void *b); -RGBA blip_get_secondary_color(void *b); -int blip_get_alpha(void *b); -int blip_get_flash_timer(void *b); -int blip_get_flash_interval(void *b); -int blip_get_as_friendly(void *b); -int blip_get_route(void *b); -int blip_get_bright(void *b); -int blip_get_number(void *b); -int blip_get_show_cone(void *b); -int blip_get_flashes(void *b); -int blip_get_flashes_alternate(void *b); -int blip_get_as_short_range(void *b); -int blip_get_priority(void *b); -float blip_get_rotation(void *b); -const char * blip_get_gxt_name(void *b); -const char * blip_get_name(void *b); -RGBA blip_get_route_color(void *b); -int blip_get_pulse(void *b); -int blip_get_as_mission_creator(void *b); -int blip_get_tick_visible(void *b); -int blip_get_heading_indicator_visible(void *b); -int blip_get_outline_indicator_visible(void *b); -int blip_get_friend_indicator_visible(void *b); -int blip_get_crew_indicator_visible(void *b); -int blip_get_category(void *b); -int blip_get_as_high_detail(void *b); -int blip_get_shrinked(void *b); -void blip_set_sprite(void *b, int sprite); -void blip_set_color(void *b, int color); -void blip_set_route(void *b, int state); -void blip_set_route_color(void *b, RGBA color); -void blip_set_secondary_color(void *b, RGBA color); -void blip_set_alpha(void *b, int alpha); -void blip_set_flash_timer(void *b, int timer); -void blip_set_flash_interval(void *b, int interval); -void blip_set_as_friendly(void *b, int friendly); -void blip_set_bright(void *b, int bright); -void blip_set_number(void *b, int number); -void blip_set_show_cone(void *b, int state); -void blip_set_flashes(void *b, int state); -void blip_set_flashes_alternate(void *b, int state); -void blip_set_as_short_range(void *b, int state); -void blip_set_priority(void *b, int state); -void blip_set_rotation(void *b, float rot); -void blip_set_gxt_name(void *b, const char *name); -void blip_set_name(void *b, const char *name); -void blip_set_pulse(void *b, int val); -void blip_set_as_mission_creator(void *b, int val); -void blip_set_tick_visible(void *b, int val); -void blip_set_heading_indicator_visible(void *b, int val); -void blip_set_outline_indicator_visible(void *b, int val); -void blip_set_friend_indicator_visible(void *b, int val); -void blip_set_crew_indicator_visible(void *b, int val); -void blip_set_category(void *b, int val); -void blip_set_as_high_detail(void *b, int val); -void blip_set_shrinked(void *b, int val); -void blip_fade(void *b, unsigned int opacity, unsigned int duration); - -// /home/timo/dev/os/altv/altv-go/runtime/src/capi/Checkpoint.h Module.h -typedef int (*capi_checkpoint_get_type)(void *c); -typedef int (*capi_checkpoint_has_meta_data)(void* base, const char *key); -typedef Array (*capi_checkpoint_get_meta_data)(void* base, const char *key); -typedef void (*capi_checkpoint_set_meta_data)(void *base, const char *key, Array data); -typedef void (*capi_checkpoint_delete_meta_data)(void *base, const char *key); -typedef void (*capi_checkpoint_destroy)(void *b); -typedef int (*capi_checkpoint_is_valid)(const char* resourceName, void *p); -typedef Position (*capi_checkpoint_get_position)(void *p); -typedef void (*capi_checkpoint_set_position)(void* p, float x, float y, float z); -typedef long (*capi_checkpoint_get_dimension)(void* p); -typedef void (*capi_checkpoint_set_dimension)(void* p, long dimension); -typedef int (*capi_checkpoint_get_col_shape_type)(void *c); -typedef int (*capi_checkpoint_is_entity_in)(void *c, Entity e); -typedef int (*capi_checkpoint_is_point_in)(void *c, float x, float y, float z); -typedef void (*capi_checkpoint_set_players_only)(void *c, int state); -typedef int (*capi_checkpoint_is_players_only)(void *c); -typedef unsigned char (*capi_checkpoint_is_entity_id_in)(void *c, unsigned short id); -typedef unsigned char (*capi_checkpoint_get_checkpoint_type)(void *c); -typedef float (*capi_checkpoint_get_height)(void *c); -typedef float (*capi_checkpoint_get_radius)(void *c); -typedef RGBA (*capi_checkpoint_get_color)(void *c); -typedef Position (*capi_checkpoint_get_next_position)(void *c); -typedef void (*capi_checkpoint_set_checkpoint_type)(void *c, unsigned char type); -typedef void (*capi_checkpoint_set_height)(void *c, float height); -typedef void (*capi_checkpoint_set_radius)(void *c, float radius); -typedef void (*capi_checkpoint_set_color)(void *c, unsigned char r, unsigned char g, unsigned char b, unsigned char a); -typedef void (*capi_checkpoint_set_next_position)(void *c, float x, float y, float z); +typedef void (*capi_blip_set_sprite)(void *b, int sprite); -// /home/timo/dev/os/altv/altv-go/runtime/src/capi/Checkpoint.h Module.h -int checkpoint_get_type(void *c); -int checkpoint_has_meta_data(void* base, const char *key); -Array checkpoint_get_meta_data(void* base, const char *key); -void checkpoint_set_meta_data(void *base, const char *key, Array data); -void checkpoint_delete_meta_data(void *base, const char *key); -void checkpoint_destroy(void *b); -int checkpoint_is_valid(const char* resourceName, void *p); -Position checkpoint_get_position(void *p); -void checkpoint_set_position(void* p, float x, float y, float z); -long checkpoint_get_dimension(void* p); -void checkpoint_set_dimension(void* p, long dimension); -int checkpoint_get_col_shape_type(void *c); -int checkpoint_is_entity_in(void *c, Entity e); -int checkpoint_is_point_in(void *c, float x, float y, float z); -void checkpoint_set_players_only(void *c, int state); -int checkpoint_is_players_only(void *c); -unsigned char checkpoint_is_entity_id_in(void *c, unsigned short id); -unsigned char checkpoint_get_checkpoint_type(void *c); -float checkpoint_get_height(void *c); -float checkpoint_get_radius(void *c); -RGBA checkpoint_get_color(void *c); -Position checkpoint_get_next_position(void *c); -void checkpoint_set_checkpoint_type(void *c, unsigned char type); -void checkpoint_set_height(void *c, float height); -void checkpoint_set_radius(void *c, float radius); -void checkpoint_set_color(void *c, unsigned char r, unsigned char g, unsigned char b, unsigned char a); -void checkpoint_set_next_position(void *c, float x, float y, float z); +typedef void (*capi_blip_set_color)(void *b, int color); -// /home/timo/dev/os/altv/altv-go/runtime/src/capi/ColShape.h Module.h -typedef int (*capi_col_shape_get_type)(void *c); -typedef int (*capi_col_shape_has_meta_data)(void* base, const char *key); -typedef Array (*capi_col_shape_get_meta_data)(void* base, const char *key); -typedef void (*capi_col_shape_set_meta_data)(void *base, const char *key, Array data); -typedef void (*capi_col_shape_delete_meta_data)(void *base, const char *key); -typedef void (*capi_col_shape_destroy)(void *b); -typedef int (*capi_col_shape_is_valid)(const char* resourceName, void *p); -typedef Position (*capi_col_shape_get_position)(void *p); -typedef void (*capi_col_shape_set_position)(void* p, float x, float y, float z); -typedef long (*capi_col_shape_get_dimension)(void* p); -typedef void (*capi_col_shape_set_dimension)(void* p, long dimension); -typedef int (*capi_col_shape_get_col_shape_type)(void *c); -typedef int (*capi_col_shape_is_entity_in)(void *c, Entity e); -typedef int (*capi_col_shape_is_point_in)(void *c, float x, float y, float z); -typedef void (*capi_col_shape_set_players_only)(void *c, int state); -typedef int (*capi_col_shape_is_players_only)(void *c); -typedef unsigned char (*capi_col_shape_is_entity_id_in)(void *c, unsigned short id); +typedef void (*capi_blip_set_route)(void *b, int state); +typedef void (*capi_blip_set_route_color)(void *b, RGBA color); -// /home/timo/dev/os/altv/altv-go/runtime/src/capi/ColShape.h Module.h -int col_shape_get_type(void *c); -int col_shape_has_meta_data(void* base, const char *key); -Array col_shape_get_meta_data(void* base, const char *key); -void col_shape_set_meta_data(void *base, const char *key, Array data); -void col_shape_delete_meta_data(void *base, const char *key); -void col_shape_destroy(void *b); -int col_shape_is_valid(const char* resourceName, void *p); -Position col_shape_get_position(void *p); -void col_shape_set_position(void* p, float x, float y, float z); -long col_shape_get_dimension(void* p); -void col_shape_set_dimension(void* p, long dimension); -int col_shape_get_col_shape_type(void *c); -int col_shape_is_entity_in(void *c, Entity e); -int col_shape_is_point_in(void *c, float x, float y, float z); -void col_shape_set_players_only(void *c, int state); -int col_shape_is_players_only(void *c); -unsigned char col_shape_is_entity_id_in(void *c, unsigned short id); +typedef void (*capi_blip_set_secondary_color)(void *b, RGBA color); + +typedef void (*capi_blip_set_alpha)(void *b, int alpha); + +typedef void (*capi_blip_set_flash_timer)(void *b, int timer); + +typedef void (*capi_blip_set_flash_interval)(void *b, int interval); + +typedef void (*capi_blip_set_as_friendly)(void *b, int friendly); + +typedef void (*capi_blip_set_bright)(void *b, int bright); + +typedef void (*capi_blip_set_number)(void *b, int number); + +typedef void (*capi_blip_set_show_cone)(void *b, int state); + +typedef void (*capi_blip_set_flashes)(void *b, int state); + +typedef void (*capi_blip_set_flashes_alternate)(void *b, int state); + +typedef void (*capi_blip_set_as_short_range)(void *b, int state); + +typedef void (*capi_blip_set_priority)(void *b, int state); + +typedef void (*capi_blip_set_rotation)(void *b, float rot); + +typedef void (*capi_blip_set_gxt_name)(void *b, const char *name); + +typedef void (*capi_blip_set_name)(void *b, const char *name); + +typedef void (*capi_blip_set_pulse)(void *b, int val); + +typedef void (*capi_blip_set_as_mission_creator)(void *b, int val); + +typedef void (*capi_blip_set_tick_visible)(void *b, int val); + +typedef void (*capi_blip_set_heading_indicator_visible)(void *b, int val); + +typedef void (*capi_blip_set_outline_indicator_visible)(void *b, int val); + +typedef void (*capi_blip_set_friend_indicator_visible)(void *b, int val); + +typedef void (*capi_blip_set_crew_indicator_visible)(void *b, int val); + +typedef void (*capi_blip_set_category)(void *b, int val); + +typedef void (*capi_blip_set_as_high_detail)(void *b, int val); + +typedef void (*capi_blip_set_shrinked)(void *b, int val); + +typedef void (*capi_blip_fade)(void *b, unsigned int opacity, unsigned int duration); -// /home/timo/dev/os/altv/altv-go/runtime/src/capi/Core.h Module.h typedef void (*capi_core_log_info)(const char *message); + typedef void (*capi_core_log_debug)(const char *message); + typedef void (*capi_core_log_warning)(const char *message); + typedef void (*capi_core_log_error)(const char *message); + typedef void (*capi_core_log_colored)(const char *message); -typedef Entity (*capi_core_create_vehicle)(unsigned long model, float posX, float posY, float posZ, - float rotX, float rotY, float rotZ); -typedef Entity (*capi_core_create_checkpoint)(unsigned char type, float x, float y, float z, float radius, float height, unsigned char r, - unsigned char g, unsigned char b, unsigned char a, unsigned long streamingDistance); -typedef Entity (*capi_core_create_voice_channel)(int spacial, float maxDistance); + +typedef Entity (*capi_core_create_vehicle)(unsigned long model, float posX, float posY, float posZ, + float rotX, float rotY, float rotZ); + +typedef Entity + (*capi_core_create_checkpoint)(unsigned char type, float x, float y, float z, float radius, float height, unsigned char r, + unsigned char g, unsigned char b, unsigned char a, unsigned long streamingDistance); + +typedef Entity (*capi_core_create_voice_channel)(int spacial, float maxDistance); + typedef const char * (*capi_core_get_version)(); + typedef const char * (*capi_core_get_branch)(); + typedef int (*capi_core_is_debug)(); + typedef unsigned long (*capi_core_hash)(const char *str); + typedef int (*capi_core_file_exists)(const char *path); + typedef const char * (*capi_core_read_file)(const char *path); -typedef Entity (*capi_core_get_entity_by_i_d)(unsigned short id); -typedef Entity (*capi_core_get_base_object_by_i_d)(unsigned char type, unsigned int id); + +typedef Entity (*capi_core_get_entity_by_id)(unsigned short id); + +typedef Entity (*capi_core_get_base_object_by_id)(unsigned char type, unsigned int id); + typedef Array (*capi_core_get_entities)(); + typedef Array (*capi_core_get_players)(); + typedef Array (*capi_core_get_vehicles)(); + typedef Array (*capi_core_get_blips)(); + typedef Array (*capi_core_get_col_shapes)(); + typedef Array (*capi_core_get_checkpoints)(); + typedef Array (*capi_core_get_virtual_entities)(); + typedef Array (*capi_core_get_virtual_entity_groups)(); + typedef Array (*capi_core_get_markers)(); + typedef Array (*capi_core_get_peds)(); + typedef int (*capi_core_has_meta_data)(const char *key); + typedef Array (*capi_core_get_meta_data)(const char *key); -typedef void (*capi_core_set_meta_data)(const char *key, Array data); + +typedef void (*capi_core_set_meta_data)(const char *key, Array data); + typedef void (*capi_core_delete_meta_data)(const char *key); + typedef int (*capi_core_has_synced_meta_data)(const char *key); + typedef Array (*capi_core_get_synced_meta_data)(const char *key); + typedef Array (*capi_core_get_required_permissions)(); + typedef Array (*capi_core_get_optional_permissions)(); + typedef void (*capi_core_destroy_base_object)(void *h); + typedef const char * (*capi_core_get_root_directory)(); + typedef int (*capi_core_start_resource)(const char *name); + typedef void (*capi_core_stop_resource)(const char *name); + typedef void (*capi_core_restart_resource)(const char *name); -typedef void (*capi_core_set_synced_meta_data)(const char *key, Array data); + +typedef void (*capi_core_set_synced_meta_data)(const char *key, Array data); + typedef void (*capi_core_delete_synced_meta_data)(const char *key); + typedef Array (*capi_core_get_players_by_name)(const char *name); + typedef unsigned int (*capi_core_get_net_time)(); + typedef void (*capi_core_set_password)(const char *password); -typedef const char * (*capi_core_get_s_d_k_hash)(); -typedef Entity (*capi_core_create_col_shape_cylinder)(float posX, float posY, float posZ, float radius, float height); -typedef Entity (*capi_core_create_col_shape_cube)(float posX1, float posY1, float posZ1, float posX2, float posY2, float posZ2); -typedef Entity (*capi_core_create_col_shape_rectangle)(float x1, float y1, float x2, float y2, float z); -typedef Entity (*capi_core_create_col_shape_circle)(float posX, float posY, float posZ, float radius); -typedef Entity (*capi_core_create_col_shape_sphere)(float posX, float posY, float posZ, float radius); -typedef void (*capi_core_trigger_local_event)(const char *ev, Array args); -typedef void (*capi_core_trigger_local_event_raw)(const char* ev, char* bytes, unsigned long long size); -typedef void (*capi_core_trigger_client_event)(void *p, const char *ev, Array args); -typedef void (*capi_core_trigger_client_event_for)(Array clients, const char *ev, Array args); -typedef void (*capi_core_trigger_client_event_for_all)(const char *ev, Array args); -typedef Entity (*capi_core_create_point_blip_position)(float x, float y, float z, unsigned short global); -typedef Entity (*capi_core_create_point_blip_entity)(Entity entity, unsigned short global); -typedef Entity (*capi_core_create_area_blip)(float x, float y, float z, float width, float height, unsigned short global); -typedef Entity (*capi_core_create_radius_blip)(float x, float y, float z, float radius, unsigned short global); -typedef Entity (*capi_core_create_col_shape_polygon)(float minZ, float maxZ, Array points); + +typedef const char * (*capi_core_get_sdk_hash)(); + +typedef Entity (*capi_core_create_col_shape_cylinder)(float posX, float posY, float posZ, float radius, float height); + +typedef Entity (*capi_core_create_col_shape_cube)(float posX1, float posY1, float posZ1, float posX2, float posY2, float posZ2); + +typedef Entity (*capi_core_create_col_shape_rectangle)(float x1, float y1, float x2, float y2, float z); + +typedef Entity (*capi_core_create_col_shape_circle)(float posX, float posY, float posZ, float radius); + +typedef Entity (*capi_core_create_col_shape_sphere)(float posX, float posY, float posZ, float radius); + +typedef void (*capi_core_trigger_local_event)(const char *ev, Array args); + +typedef void (*capi_core_trigger_local_event_raw)(const char* ev, char* bytes, unsigned long long size); + +typedef void (*capi_core_trigger_client_event)(void *p, const char *ev, Array args); + +typedef void (*capi_core_trigger_client_event_for)(Array clients, const char *ev, Array args); + +typedef void (*capi_core_trigger_client_event_for_all)(const char *ev, Array args); + +typedef Entity (*capi_core_create_point_blip_position)(float x, float y, float z, unsigned short global); + +typedef Entity (*capi_core_create_point_blip_entity)(Entity entity, unsigned short global); + +typedef Entity (*capi_core_create_area_blip)(float x, float y, float z, float width, float height, unsigned short global); + +typedef Entity (*capi_core_create_radius_blip)(float x, float y, float z, float radius, unsigned short global); + +typedef Entity (*capi_core_create_col_shape_polygon)(float minZ, float maxZ, Array points); + typedef Array (*capi_core_get_all_resources)(); -typedef const char * (*capi_core_string_to_s_h_a256)(const char *str); + +typedef const char * (*capi_core_string_to_sha256)(const char *str); + typedef void (*capi_core_stop_server)(); + typedef VehicleModelInfo (*capi_core_get_vehicle_model_by_hash)(unsigned int hash); + typedef PedModelInfo (*capi_core_get_ped_model_by_hash)(unsigned int hash); + typedef Array (*capi_core_get_server_config)(); + typedef unsigned long long (*capi_core_hash_server_password)(const char *password); + typedef void* (*capi_core_get_resource_by_name)(const char *resourceName); +typedef unsigned char (*capi_resource_is_started)(void *r); -// /home/timo/dev/os/altv/altv-go/runtime/src/capi/Core.h Module.h -void core_log_info(const char *message); -void core_log_debug(const char *message); -void core_log_warning(const char *message); -void core_log_error(const char *message); -void core_log_colored(const char *message); -Entity core_create_vehicle(unsigned long model, float posX, float posY, float posZ, - float rotX, float rotY, float rotZ); -Entity core_create_checkpoint(unsigned char type, float x, float y, float z, float radius, float height, unsigned char r, - unsigned char g, unsigned char b, unsigned char a, unsigned long streamingDistance); -Entity core_create_voice_channel(int spacial, float maxDistance); -const char * core_get_version(); -const char * core_get_branch(); -int core_is_debug(); -unsigned long core_hash(const char *str); -int core_file_exists(const char *path); -const char * core_read_file(const char *path); -Entity core_get_entity_by_i_d(unsigned short id); -Entity core_get_base_object_by_i_d(unsigned char type, unsigned int id); -Array core_get_entities(); -Array core_get_players(); -Array core_get_vehicles(); -Array core_get_blips(); -Array core_get_col_shapes(); -Array core_get_checkpoints(); -Array core_get_virtual_entities(); -Array core_get_virtual_entity_groups(); -Array core_get_markers(); -Array core_get_peds(); -int core_has_meta_data(const char *key); -Array core_get_meta_data(const char *key); -void core_set_meta_data(const char *key, Array data); -void core_delete_meta_data(const char *key); -int core_has_synced_meta_data(const char *key); -Array core_get_synced_meta_data(const char *key); -Array core_get_required_permissions(); -Array core_get_optional_permissions(); -void core_destroy_base_object(void *h); -const char * core_get_root_directory(); -int core_start_resource(const char *name); -void core_stop_resource(const char *name); -void core_restart_resource(const char *name); -void core_set_synced_meta_data(const char *key, Array data); -void core_delete_synced_meta_data(const char *key); -Array core_get_players_by_name(const char *name); -unsigned int core_get_net_time(); -void core_set_password(const char *password); -const char * core_get_s_d_k_hash(); -Entity core_create_col_shape_cylinder(float posX, float posY, float posZ, float radius, float height); -Entity core_create_col_shape_cube(float posX1, float posY1, float posZ1, float posX2, float posY2, float posZ2); -Entity core_create_col_shape_rectangle(float x1, float y1, float x2, float y2, float z); -Entity core_create_col_shape_circle(float posX, float posY, float posZ, float radius); -Entity core_create_col_shape_sphere(float posX, float posY, float posZ, float radius); -void core_trigger_local_event(const char *ev, Array args); -void core_trigger_local_event_raw(const char* ev, char* bytes, unsigned long long size); -void core_trigger_client_event(void *p, const char *ev, Array args); -void core_trigger_client_event_for(Array clients, const char *ev, Array args); -void core_trigger_client_event_for_all(const char *ev, Array args); -Entity core_create_point_blip_position(float x, float y, float z, unsigned short global); -Entity core_create_point_blip_entity(Entity entity, unsigned short global); -Entity core_create_area_blip(float x, float y, float z, float width, float height, unsigned short global); -Entity core_create_radius_blip(float x, float y, float z, float radius, unsigned short global); -Entity core_create_col_shape_polygon(float minZ, float maxZ, Array points); -Array core_get_all_resources(); -const char * core_string_to_s_h_a256(const char *str); -void core_stop_server(); -VehicleModelInfo core_get_vehicle_model_by_hash(unsigned int hash); -PedModelInfo core_get_ped_model_by_hash(unsigned int hash); -Array core_get_server_config(); -unsigned long long core_hash_server_password(const char *password); -void* core_get_resource_by_name(const char *resourceName); +typedef const char * (*capi_resource_get_type)(void *r); + +typedef const char * (*capi_resource_get_name)(void* r); + +typedef const char * (*capi_resource_get_main)(void *r); + +typedef Array (*capi_resource_get_config)(void *r); + +typedef Array (*capi_resource_get_exports)(void *r); + +typedef Array (*capi_resource_get_dependencies)(void *r); + +typedef Array (*capi_resource_get_dependants)(void *r); + +typedef Array (*capi_resource_get_required_permissions)(void *r); + +typedef Array (*capi_resource_get_optional_permissions)(void *r); + +typedef const char * (*capi_resource_get_path)(void *r); + +typedef int (*capi_col_shape_get_type)(void *c); + +typedef int (*capi_col_shape_has_meta_data)(void* base, const char *key); + +typedef Array (*capi_col_shape_get_meta_data)(void* base, const char *key); + +typedef void (*capi_col_shape_set_meta_data)(void *base, const char *key, Array data); + +typedef void (*capi_col_shape_delete_meta_data)(void *base, const char *key); + +typedef void (*capi_col_shape_destroy)(void *b); + +typedef int (*capi_col_shape_is_valid)(const char* resourceName, void *p); + +typedef Position (*capi_col_shape_get_position)(void *p); + +typedef void (*capi_col_shape_set_position)(void* p, float x, float y, float z); + +typedef long (*capi_col_shape_get_dimension)(void* p); + +typedef void (*capi_col_shape_set_dimension)(void* p, long dimension); + +typedef int (*capi_col_shape_get_col_shape_type)(void *c); + +typedef int (*capi_col_shape_is_entity_in)(void *c, Entity e); + +typedef int (*capi_col_shape_is_point_in)(void *c, float x, float y, float z); + +typedef void (*capi_col_shape_set_players_only)(void *c, int state); + +typedef int (*capi_col_shape_is_players_only)(void *c); + +typedef unsigned char (*capi_col_shape_is_entity_id_in)(void *c, unsigned short id); -// /home/timo/dev/os/altv/altv-go/runtime/src/capi/Player.h Module.h typedef const char * (*capi_player_get_name)(void *p); -typedef int (*capi_player_has_meta_data)(void *base, const char *key); -typedef Array (*capi_player_get_meta_data)(void *base, const char *key); -typedef void (*capi_player_set_meta_data)(void *base, const char *key, Array data); -typedef void (*capi_player_delete_meta_data)(void *base, const char *key); -typedef int (*capi_player_has_synced_meta_data)(void *base, const char *key); -typedef Array (*capi_player_get_synced_meta_data)(void *base, const char *key); -typedef void (*capi_player_set_synced_meta_data)(void *base, const char *key, Array data); -typedef void (*capi_player_delete_synced_meta_data)(void *base, const char *key); -typedef int (*capi_player_has_stream_synced_meta_data)(void *base, const char *key); -typedef Array (*capi_player_get_stream_synced_meta_data)(void *base, const char *key); -typedef void (*capi_player_set_stream_synced_meta_data)(void *base, const char *key, Array data); -typedef void (*capi_player_delete_stream_synced_meta_data)(void *base, const char *key); + +typedef int (*capi_player_has_meta_data)(void *base, const char *key); + +typedef Array (*capi_player_get_meta_data)(void *base, const char *key); + +typedef void (*capi_player_set_meta_data)(void *base, const char *key, Array data); + +typedef void (*capi_player_delete_meta_data)(void *base, const char *key); + +typedef int (*capi_player_has_synced_meta_data)(void *base, const char *key); + +typedef Array (*capi_player_get_synced_meta_data)(void *base, const char *key); + +typedef void (*capi_player_set_synced_meta_data)(void *base, const char *key, Array data); + +typedef void (*capi_player_delete_synced_meta_data)(void *base, const char *key); + +typedef int (*capi_player_has_stream_synced_meta_data)(void *base, const char *key); + +typedef Array (*capi_player_get_stream_synced_meta_data)(void *base, const char *key); + +typedef void (*capi_player_set_stream_synced_meta_data)(void *base, const char *key, Array data); + +typedef void (*capi_player_delete_stream_synced_meta_data)(void *base, const char *key); + typedef Position (*capi_player_get_position)(void *p); -typedef void (*capi_player_set_position)(void *p, float x, float y, float z); + +typedef void (*capi_player_set_position)(void *p, float x, float y, float z); + typedef Rotation (*capi_player_get_rotation)(void *p); -typedef void (*capi_player_set_rotation)(void *p, float roll, float pitch, float yaw); + +typedef void (*capi_player_set_rotation)(void *p, float roll, float pitch, float yaw); + typedef long (*capi_player_get_dimension)(void *p); -typedef void (*capi_player_set_dimension)(void *p, long dimension); -typedef void (*capi_player_spawn)(void *p, float x, float y, float z, unsigned long delay); + +typedef void (*capi_player_set_dimension)(void *p, long dimension); + +typedef void (*capi_player_spawn)(void *p, float x, float y, float z, unsigned long delay); + typedef void (*capi_player_despawn)(void *p); -typedef void (*capi_player_set_model)(void *p, unsigned long model); + +typedef void (*capi_player_set_model)(void *p, unsigned long model); + typedef unsigned long (*capi_player_get_model)(void *p); + typedef unsigned int (*capi_player_get_health)(void *p); -typedef void (*capi_player_set_health)(void *p, unsigned int health); -typedef int (*capi_player_has_weapon_component)(void *p, unsigned long weapon, unsigned long component); + +typedef void (*capi_player_set_health)(void *p, unsigned int health); + +typedef int (*capi_player_has_weapon_component)(void *p, unsigned long weapon, unsigned long component); + typedef Array (*capi_player_get_current_weapon_components)(void *p); -typedef unsigned int (*capi_player_get_weapon_tint_index)(void *p, unsigned long weapon); + +typedef unsigned int (*capi_player_get_weapon_tint_index)(void *p, unsigned long weapon); + typedef unsigned int (*capi_player_get_current_weapon_tint_index)(void *p); + typedef unsigned long (*capi_player_get_current_weapon)(void *p); + typedef int (*capi_player_is_dead)(void *p); + typedef int (*capi_player_is_jumping)(void *p); + typedef int (*capi_player_is_in_ragdoll)(void *p); + typedef int (*capi_player_is_aiming)(void *p); + typedef int (*capi_player_is_shooting)(void *p); + typedef int (*capi_player_is_reloading)(void *p); + typedef unsigned int (*capi_player_get_armour)(void *p); -typedef void (*capi_player_set_armour)(void *p, unsigned int armour); + +typedef void (*capi_player_set_armour)(void *p, unsigned int armour); + typedef float (*capi_player_get_move_speed)(void *p); + typedef Position (*capi_player_get_aim_pos)(void *p); + typedef Rotation (*capi_player_get_head_rotation)(void *p); + typedef int (*capi_player_is_in_vehicle)(void *p); + typedef Entity (*capi_player_get_vehicle)(void *p); + typedef unsigned int (*capi_player_get_seat)(void *p); + typedef Entity (*capi_player_get_entity_aiming_at)(void *p); + typedef Position (*capi_player_get_entity_aim_offset)(void *p); + typedef int (*capi_player_is_flashlight_active)(void *p); + typedef int (*capi_player_is_connected)(void *p); + typedef unsigned long (*capi_player_get_ping)(void *p); -typedef const char * (*capi_player_get_i_p)(void *p); -typedef unsigned long long (*capi_player_get_social_i_d)(void *p); + +typedef const char * (*capi_player_get_ip)(void *p); + +typedef unsigned long long (*capi_player_get_social_id)(void *p); + typedef unsigned long long (*capi_player_get_hwid_hash)(void *p); + typedef unsigned long long (*capi_player_get_hwid_ex_hash)(void *p); + typedef const char * (*capi_player_get_auth_token)(void *p); -typedef void (*capi_player_set_max_armour)(void *p, unsigned int armour); -typedef void (*capi_player_set_current_weapon)(void *p, unsigned long weapon); -typedef void (*capi_player_set_weapon_tint_index)(void *p, unsigned long weapon, unsigned int tintIndex); -typedef void (*capi_player_add_weapon_component)(void *p, unsigned long weapon, unsigned long component); -typedef void (*capi_player_remove_weapon_component)(void *p, unsigned long weapon, unsigned long component); + +typedef void (*capi_player_set_max_armour)(void *p, unsigned int armour); + +typedef void (*capi_player_set_current_weapon)(void *p, unsigned long weapon); + +typedef void (*capi_player_set_weapon_tint_index)(void *p, unsigned long weapon, unsigned int tintIndex); + +typedef void (*capi_player_add_weapon_component)(void *p, unsigned long weapon, unsigned long component); + +typedef void (*capi_player_remove_weapon_component)(void *p, unsigned long weapon, unsigned long component); + typedef void (*capi_player_clear_blood_damage)(void *p); -typedef void (*capi_player_set_max_health)(void *p, unsigned int health); -typedef void (*capi_player_give_weapon)(void *p, unsigned long weapon, long ammo, int selectWeapon); -typedef void (*capi_player_remove_weapon)(void *p, unsigned long weapon); -typedef void (*capi_player_remove_all_weapons)(void *p, unsigned short removeAmmo); -typedef void (*capi_player_set_date_time)(void *p, int day, int month, int year, int hour, int minute, int second); -typedef void (*capi_player_set_weather)(void *p, unsigned long weather); -typedef void (*capi_player_kick)(void *p, const char *reason); -typedef Cloth (*capi_player_get_clothes)(void *p, unsigned int component); -typedef DlcCloth (*capi_player_get_dlc_clothes)(void *p, unsigned int component); -typedef Prop (*capi_player_get_props)(void *p, unsigned int component); -typedef DlcProp (*capi_player_get_dlc_props)(void *p, unsigned int component); -typedef void (*capi_player_set_clothes)(void *p, unsigned int component, unsigned int drawable, unsigned int texture, unsigned int palette); -typedef void (*capi_player_set_dlc_clothes)(void *p, unsigned int component, unsigned int drawable, unsigned int texture, unsigned int palette, + +typedef void (*capi_player_set_max_health)(void *p, unsigned int health); + +typedef void (*capi_player_give_weapon)(void *p, unsigned long weapon, long ammo, int selectWeapon); + +typedef void (*capi_player_remove_weapon)(void *p, unsigned long weapon); + +typedef void (*capi_player_remove_all_weapons)(void *p, unsigned short removeAmmo); + +typedef void (*capi_player_set_date_time)(void *p, int day, int month, int year, int hour, int minute, int second); + +typedef void (*capi_player_set_weather)(void *p, unsigned long weather); + +typedef void (*capi_player_kick)(void *p, const char *reason); + +typedef Cloth (*capi_player_get_clothes)(void *p, unsigned int component); + +typedef DlcCloth (*capi_player_get_dlc_clothes)(void *p, unsigned int component); + +typedef Prop (*capi_player_get_props)(void *p, unsigned int component); + +typedef DlcProp (*capi_player_get_dlc_props)(void *p, unsigned int component); + +typedef void + (*capi_player_set_clothes)(void *p, unsigned int component, unsigned int drawable, unsigned int texture, unsigned int palette); + +typedef void + (*capi_player_set_dlc_clothes)(void *p, unsigned int component, unsigned int drawable, unsigned int texture, unsigned int palette, unsigned long dlc); -typedef void (*capi_player_set_props)(void *p, unsigned int component, unsigned int drawable, unsigned int texture); -typedef void (*capi_player_set_dlc_props)(void *p, unsigned int component, unsigned int drawable, unsigned int texture, unsigned long dlc); -typedef void (*capi_player_clear_props)(void *p, unsigned int component); -typedef int (*capi_player_is_entity_in_streaming_range)(void *p, unsigned short entityId); + +typedef void (*capi_player_set_props)(void *p, unsigned int component, unsigned int drawable, unsigned int texture); + +typedef void + (*capi_player_set_dlc_props)(void *p, unsigned int component, unsigned int drawable, unsigned int texture, unsigned long dlc); + +typedef void (*capi_player_clear_props)(void *p, unsigned int component); + +typedef int (*capi_player_is_entity_in_streaming_range)(void *p, unsigned short entityId); + typedef unsigned int (*capi_player_get_max_health)(void *p); + typedef unsigned int (*capi_player_get_max_armour)(void *p); + typedef void (*capi_player_detach)(void *p); -typedef void (*capi_player_attach_to_entity)(void *p, Entity e, int otherBoneIndex, int myBoneIndex, Position position, Rotation rotation, - int collision, int noFixedRotation); -typedef void (*capi_player_set_visible)(void *p, int toggle); + +typedef void + (*capi_player_attach_to_entity)(void *p, Entity e, int otherBoneIndex, int myBoneIndex, Position position, Rotation rotation, + int collision, int noFixedRotation); + +typedef void (*capi_player_set_visible)(void *p, int toggle); + typedef int (*capi_player_get_visible)(void *p); -typedef unsigned long (*capi_player_get_i_d)(void *p); + +typedef unsigned long (*capi_player_get_id)(void *p); + typedef Entity (*capi_player_get_network_owner)(void *p); -typedef void (*capi_player_set_network_owner)(void *p, void *owner, int disableMigration); + +typedef void (*capi_player_set_network_owner)(void *p, void *owner, int disableMigration); + typedef void (*capi_player_destroy)(void *p); -typedef int (*capi_player_is_valid)(const char* resourceName, void *p); + +typedef int (*capi_player_is_valid)(const char* resourceName, void *p); + typedef int (*capi_player_get_streamed)(void *p); -typedef void (*capi_player_set_streamed)(void *p, int toggle); + +typedef void (*capi_player_set_streamed)(void *p, int toggle); + typedef int (*capi_player_get_invincible)(void *p); -typedef void (*capi_player_set_invincible)(void *p, int toggle); -typedef void (*capi_player_set_into_vehicle)(void *p, void *v, unsigned char seat); + +typedef void (*capi_player_set_invincible)(void *p, int toggle); + +typedef void (*capi_player_set_into_vehicle)(void *p, void *v, unsigned char seat); + typedef int (*capi_player_is_frozen)(void *p); -typedef void (*capi_player_set_frozen)(void *p, int state); + +typedef void (*capi_player_set_frozen)(void *p, int state); + typedef int (*capi_player_has_collision)(void *p); -typedef void (*capi_player_set_collision)(void *p, int state); -typedef void (*capi_player_play_ambient_speech)(void *p, const char *speechName, const char *speechParam, unsigned int speechDictHash); -typedef int (*capi_player_set_head_overlay)(void *p, unsigned char overlayID, unsigned char index, float opacity); -typedef int (*capi_player_remove_head_overlay)(void *p, unsigned char overlayID); -typedef int (*capi_player_set_head_overlay_color)(void *p, unsigned char overlayID, unsigned char colorType, unsigned char colorIndex, + +typedef void (*capi_player_set_collision)(void *p, int state); + +typedef void + (*capi_player_play_ambient_speech)(void *p, const char *speechName, const char *speechParam, unsigned int speechDictHash); + +typedef int (*capi_player_set_head_overlay)(void *p, unsigned char overlayID, unsigned char index, float opacity); + +typedef int (*capi_player_remove_head_overlay)(void *p, unsigned char overlayID); + +typedef int + (*capi_player_set_head_overlay_color)(void *p, unsigned char overlayID, unsigned char colorType, unsigned char colorIndex, unsigned char secondColorIndex); -typedef HeadOverlay (*capi_player_get_head_overlay)(void *p, unsigned char overlayID); -typedef int (*capi_player_set_face_feature)(void *p, unsigned char index, float scale); -typedef float (*capi_player_get_face_feature_scale)(void *p, unsigned char index); -typedef int (*capi_player_remove_face_feature)(void *p, unsigned char index); -typedef int (*capi_player_set_head_blend_palette_color)(void *p, unsigned char id, unsigned char red, unsigned char green, unsigned char blue); -typedef RGBA (*capi_player_get_head_blend_palette_color)(void *p, unsigned char id); -typedef void (*capi_player_set_head_blend_data)(void *p, unsigned int shapeFirstID, unsigned int shapeSecondID, unsigned int shapeThirdID, - unsigned int skinFirstID, unsigned int skinSecondID, unsigned int skinThirdID, - float shapeMix, float skinMix, float thirdMix); + +typedef HeadOverlay (*capi_player_get_head_overlay)(void *p, unsigned char overlayID); + +typedef int (*capi_player_set_face_feature)(void *p, unsigned char index, float scale); + +typedef float (*capi_player_get_face_feature_scale)(void *p, unsigned char index); + +typedef int (*capi_player_remove_face_feature)(void *p, unsigned char index); + +typedef int + (*capi_player_set_head_blend_palette_color)(void *p, unsigned char id, unsigned char red, unsigned char green, unsigned char blue); + +typedef RGBA (*capi_player_get_head_blend_palette_color)(void *p, unsigned char id); + +typedef void + (*capi_player_set_head_blend_data)(void *p, unsigned int shapeFirstID, unsigned int shapeSecondID, unsigned int shapeThirdID, + unsigned int skinFirstID, unsigned int skinSecondID, unsigned int skinThirdID, + float shapeMix, float skinMix, float thirdMix); + typedef HeadBlendData (*capi_player_get_head_blend_data)(void *p); -typedef int (*capi_player_set_eye_color)(void *p, short eyeColor); + +typedef int (*capi_player_set_eye_color)(void *p, short eyeColor); + typedef short (*capi_player_get_eye_color)(void *p); -typedef void (*capi_player_set_hair_color)(void *p, unsigned char hairColor); + +typedef void (*capi_player_set_hair_color)(void *p, unsigned char hairColor); + typedef unsigned char (*capi_player_get_hair_color)(void *p); -typedef void (*capi_player_set_hair_highlight_color)(void *p, unsigned char hairHighlightColor); + +typedef void (*capi_player_set_hair_highlight_color)(void *p, unsigned char hairHighlightColor); + typedef unsigned char (*capi_player_get_hair_highlight_color)(void *p); + typedef Array (*capi_player_get_weapons)(void *p); -typedef int (*capi_player_has_local_meta_data)(void *p, const char *key); -typedef void (*capi_player_set_local_meta_data)(void *p, const char *key, Array data); -typedef Array (*capi_player_get_local_meta_data)(void *p, const char *key); -typedef void (*capi_player_delete_local_meta_data)(void *p, const char *key); + +typedef int (*capi_player_has_local_meta_data)(void *p, const char *key); + +typedef void (*capi_player_set_local_meta_data)(void *p, const char *key, Array data); + +typedef Array (*capi_player_get_local_meta_data)(void *p, const char *key); + +typedef void (*capi_player_delete_local_meta_data)(void *p, const char *key); + typedef unsigned int (*capi_player_get_current_animation_dict)(void *p); + typedef unsigned int (*capi_player_get_current_animation_name)(void *p); + typedef unsigned char (*capi_player_is_spawned)(void *p); + typedef float (*capi_player_get_forward_speed)(void *p); + typedef float (*capi_player_get_strafe_speed)(void *p); + typedef long long (*capi_player_get_discord_id)(void *p); + typedef unsigned int (*capi_player_get_interior_location)(void *p); + typedef unsigned int (*capi_player_get_last_damaged_body_part)(void *p); -typedef void (*capi_player_set_last_damaged_body_part)(void *p, unsigned int bodyPart); +typedef void (*capi_player_set_last_damaged_body_part)(void *p, unsigned int bodyPart); + +typedef int (*capi_runtime_register_alt_event)(const char *resourceName, unsigned short eventType); + +typedef int (*capi_runtime_unregister_alt_event)(const char *resourceName, unsigned short eventType); + +typedef int (*capi_runtime_register_alt_export)(const char *resourceName, const char *exportName, Array value); + +typedef Array (*capi_runtime_get_alt_export)(const char *targetResourceName, const char *exportName); + +typedef void * (*capi_runtime_create_m_value_function)(const char *resourceName, unsigned long long id); + +typedef Array (*capi_runtime_call_m_value_function)(void *ptr, Array args); + +typedef void (*capi_connection_accept)(void *handle, unsigned char sendNames); + +typedef void (*capi_connection_decline)(void *handle, const char *reason); + +typedef int (*capi_connection_is_accepted)(void *handle); + +typedef int (*capi_vehicle_has_meta_data)(void *base, const char *key); + +typedef Array (*capi_vehicle_get_meta_data)(void *base, const char *key); + +typedef void (*capi_vehicle_set_meta_data)(void *base, const char *key, Array data); + +typedef void (*capi_vehicle_delete_meta_data)(void *base, const char *key); + +typedef int (*capi_vehicle_has_synced_meta_data)(void *base, const char *key); + +typedef Array (*capi_vehicle_get_synced_meta_data)(void *base, const char *key); + +typedef void (*capi_vehicle_set_synced_meta_data)(void *base, const char *key, Array data); + +typedef void (*capi_vehicle_delete_synced_meta_data)(void *base, const char *key); + +typedef int (*capi_vehicle_has_stream_synced_meta_data)(void *base, const char *key); + +typedef Array (*capi_vehicle_get_stream_synced_meta_data)(void *base, const char *key); + +typedef void (*capi_vehicle_set_stream_synced_meta_data)(void *base, const char *key, Array data); + +typedef void (*capi_vehicle_delete_stream_synced_meta_data)(void *base, const char *key); + +typedef Position (*capi_vehicle_get_position)(void *v); + +typedef void (*capi_vehicle_set_position)(void *v, float x, float y, float z); + +typedef Rotation (*capi_vehicle_get_rotation)(void *v); + +typedef void (*capi_vehicle_set_rotation)(void *v, float roll, float pitch, float yaw); + +typedef long (*capi_vehicle_get_dimension)(void *v); + +typedef void (*capi_vehicle_set_dimension)(void *v, long dimension); + +typedef unsigned long (*capi_vehicle_get_id)(void *v); + +typedef unsigned long (*capi_vehicle_get_model)(void *v); + +typedef void (*capi_vehicle_detach)(void *v); + +typedef void + (*capi_vehicle_attach_to_entity)(void *v, Entity e, int otherBoneIndex, int myBoneIndex, Position position, Rotation rotation, + int collision, int noFixedRotation); + +typedef void (*capi_vehicle_set_visible)(void *v, int toggle); + +typedef int (*capi_vehicle_get_visible)(void *v); + +typedef Entity (*capi_vehicle_get_network_owner)(void *v); + +typedef void (*capi_vehicle_set_network_owner)(void *v, void *owner, int disableMigration); + +typedef Entity (*capi_vehicle_get_driver)(void *v); + +typedef int (*capi_vehicle_is_destroyed)(void *v); + +typedef unsigned long (*capi_vehicle_get_mod)(void *v, unsigned int category); + +typedef unsigned long (*capi_vehicle_get_mods_count)(void *v, unsigned int category); + +typedef unsigned long (*capi_vehicle_get_mod_kits_count)(void *v); + +typedef unsigned long (*capi_vehicle_get_mod_kit)(void *v); + +typedef int (*capi_vehicle_is_primary_color_rgb)(void *v); + +typedef unsigned long (*capi_vehicle_get_primary_color)(void *v); + +typedef RGBA (*capi_vehicle_get_primary_color_rgb)(void *v); + +typedef int (*capi_vehicle_is_secondary_color_rgb)(void *v); + +typedef unsigned long (*capi_vehicle_get_secondary_color)(void *v); + +typedef RGBA (*capi_vehicle_get_secondary_color_rgb)(void *v); + +typedef unsigned long (*capi_vehicle_get_pearl_color)(void *v); + +typedef unsigned long (*capi_vehicle_get_wheel_color)(void *v); + +typedef unsigned long (*capi_vehicle_get_interior_color)(void *v); + +typedef unsigned long (*capi_vehicle_get_dashboard_color)(void *v); + +typedef int (*capi_vehicle_is_tire_smoke_color_custom)(void *v); + +typedef RGBA (*capi_vehicle_get_tire_smoke_color)(void *v); + +typedef unsigned long (*capi_vehicle_get_wheel_type)(void *v); + +typedef unsigned long (*capi_vehicle_get_wheel_variation)(void *v); + +typedef unsigned long (*capi_vehicle_get_rear_wheel_variation)(void *v); + +typedef int (*capi_vehicle_get_custom_tires)(void *v); + +typedef unsigned long (*capi_vehicle_get_special_darkness)(void *v); + +typedef unsigned long (*capi_vehicle_get_numberplate_index)(void *v); + +typedef const char * (*capi_vehicle_get_numberplate_text)(void *v); + +typedef unsigned long (*capi_vehicle_get_window_tint)(void *v); + +typedef unsigned long (*capi_vehicle_get_dirt_level)(void *v); + +typedef int (*capi_vehicle_is_extra_on)(void *v, unsigned int extraID); + +typedef int (*capi_vehicle_is_neon_active)(void *v); + +typedef VehicleNeonState (*capi_vehicle_get_neon_active)(void *v); + +typedef RGBA (*capi_vehicle_get_neon_color)(void *v); + +typedef unsigned long (*capi_vehicle_get_livery)(void *v); + +typedef unsigned long (*capi_vehicle_get_roof_livery)(void *v); + +typedef const char * (*capi_vehicle_get_appearance_data_base64)(void *v); + +typedef int (*capi_vehicle_is_engine_on)(void *v); + +typedef int (*capi_vehicle_is_handbrake_active)(void *v); + +typedef unsigned long (*capi_vehicle_get_headlight_color)(void *v); + +typedef unsigned long (*capi_vehicle_get_radio_station_index)(void *v); + +typedef int (*capi_vehicle_is_siren_active)(void *v); + +typedef unsigned long (*capi_vehicle_get_lock_state)(void *v); + +typedef unsigned long (*capi_vehicle_get_door_state)(void *v, unsigned int doorId); + +typedef int (*capi_vehicle_is_window_opened)(void *v, unsigned int windowId); + +typedef int (*capi_vehicle_is_daylight_on)(void *v); + +typedef int (*capi_vehicle_is_nightlight_on)(void *v); + +typedef unsigned long (*capi_vehicle_get_roof_state)(void *v); + +typedef int (*capi_vehicle_is_flamethrower_active)(void *v); + +typedef float (*capi_vehicle_get_lights_multiplier)(void *v); + +typedef const char * (*capi_vehicle_get_game_state_base64)(void *v); + +typedef long (*capi_vehicle_get_engine_health)(void *v); + +typedef long (*capi_vehicle_get_petrol_tank_health)(void *v); + +typedef unsigned long (*capi_vehicle_get_wheels_count)(void *v); + +typedef int (*capi_vehicle_is_wheel_burst)(void *v, unsigned int wheelId); + +typedef int (*capi_vehicle_does_wheel_has_tire)(void *v, unsigned int wheelId); + +typedef int (*capi_vehicle_is_wheel_detached)(void *v, unsigned int wheelId); + +typedef int (*capi_vehicle_is_wheel_on_fire)(void *v, unsigned int wheelId); + +typedef float (*capi_vehicle_get_wheel_health)(void *v, unsigned int wheelId); + +typedef unsigned long (*capi_vehicle_get_repairs_count)(void *v); + +typedef unsigned long (*capi_vehicle_get_body_health)(void *v); + +typedef unsigned long (*capi_vehicle_get_body_additional_health)(void *v); + +typedef const char * (*capi_vehicle_get_health_data_base64)(void *v); + +typedef unsigned long (*capi_vehicle_get_part_damage_level)(void *v, unsigned int partId); + +typedef unsigned long (*capi_vehicle_get_part_bullet_holes)(void *v, unsigned int partId); + +typedef int (*capi_vehicle_is_light_damaged)(void *v, unsigned int lightId); + +typedef int (*capi_vehicle_is_window_damaged)(void *v, unsigned int windowId); + +typedef int (*capi_vehicle_is_special_light_damaged)(void *v, unsigned int specialLightId); + +typedef int (*capi_vehicle_has_armored_windows)(void *v); + +typedef float (*capi_vehicle_get_armored_window_health)(void *v, unsigned int windowId); + +typedef unsigned long (*capi_vehicle_get_armored_window_shoot_count)(void *v, unsigned int windowId); + +typedef unsigned long (*capi_vehicle_get_bumper_damage_level)(void *v, unsigned int bumperId); + +typedef const char * (*capi_vehicle_get_damage_data_base64)(void *v); + +typedef int (*capi_vehicle_is_manual_engine_control)(void *v); + +typedef const char * (*capi_vehicle_get_script_data_base64)(void *v); + +typedef void (*capi_vehicle_toggle_extra)(void *v, unsigned int extraID, int state); + +typedef void (*capi_vehicle_set_fixed)(void *v); + +typedef int (*capi_vehicle_set_mod)(void *v, unsigned int category, unsigned int id); + +typedef int (*capi_vehicle_set_mod_kit)(void *v, unsigned int id); + +typedef void (*capi_vehicle_set_primary_color)(void *v, unsigned int color); + +typedef void (*capi_vehicle_set_primary_color_rgb)(void *v, unsigned int r, unsigned int g, unsigned int b, unsigned int a); + +typedef void (*capi_vehicle_set_secondary_color)(void *v, unsigned int color); + +typedef void (*capi_vehicle_set_secondary_color_rgb)(void *v, unsigned int r, unsigned int g, unsigned int b, unsigned int a); + +typedef void (*capi_vehicle_set_pearl_color)(void *v, unsigned int color); + +typedef void (*capi_vehicle_set_wheel_color)(void *v, unsigned int color); + +typedef void (*capi_vehicle_set_interior_color)(void *v, unsigned int color); + +typedef void (*capi_vehicle_set_dashboard_color)(void *v, unsigned int color); + +typedef void (*capi_vehicle_set_tire_smoke_color)(void *v, unsigned int r, unsigned int g, unsigned int b, unsigned int a); + +typedef void (*capi_vehicle_set_wheels)(void *v, unsigned int type, unsigned int variation); + +typedef void (*capi_vehicle_set_rear_wheels)(void *v, unsigned int variation); + +typedef void (*capi_vehicle_set_custom_tires)(void *v, int state); + +typedef void (*capi_vehicle_set_special_darkness)(void *v, unsigned int value); + +typedef void (*capi_vehicle_set_numberplate_index)(void *v, unsigned int index); + +typedef void (*capi_vehicle_set_numberplate_text)(void *v, const char *text); + +typedef void (*capi_vehicle_set_window_tint)(void *v, unsigned int tint); + +typedef void (*capi_vehicle_set_dirt_level)(void *v, unsigned int level); + +typedef void (*capi_vehicle_set_neon_active)(void *v, int left, int right, int front, int back); + +typedef void (*capi_vehicle_set_neon_color)(void *v, unsigned int r, unsigned int g, unsigned int b, unsigned int a); + +typedef void (*capi_vehicle_set_livery)(void *v, unsigned int livery); + +typedef void (*capi_vehicle_set_roof_livery)(void *v, unsigned int roofLivery); + +typedef void (*capi_vehicle_load_appearance_data_from_base64)(void *v, const char *base64); + +typedef void (*capi_vehicle_set_engine_on)(void *v, int state); + +typedef void (*capi_vehicle_set_headlight_color)(void *v, unsigned int color); + +typedef void (*capi_vehicle_set_radio_station_index)(void *v, unsigned int stationIndex); + +typedef void (*capi_vehicle_set_siren_active)(void *v, int state); + +typedef void (*capi_vehicle_set_lock_state)(void *v, unsigned int state); + +typedef void (*capi_vehicle_set_door_state)(void *v, unsigned int doorId, unsigned int state); + +typedef void (*capi_vehicle_set_window_opened)(void *v, unsigned int windowId, int state); + +typedef void (*capi_vehicle_set_roof_state)(void *v, unsigned int state); + +typedef void (*capi_vehicle_set_lights_multiplier)(void *v, float multiplier); + +typedef void (*capi_vehicle_set_engine_health)(void *v, unsigned long health); + +typedef void (*capi_vehicle_set_petrol_tank_health)(void *v, unsigned long health); + +typedef void (*capi_vehicle_set_wheel_burst)(void *v, unsigned int wheelId, int state); + +typedef void (*capi_vehicle_set_wheel_has_tire)(void *v, unsigned int wheelId, int state); + +typedef void (*capi_vehicle_set_wheel_detached)(void *v, unsigned int wheelId, int state); + +typedef void (*capi_vehicle_set_wheel_on_fire)(void *v, unsigned int wheelId, int state); + +typedef void (*capi_vehicle_set_wheel_health)(void *v, unsigned int wheelId, float health); + +typedef void (*capi_vehicle_set_wheel_fixed)(void *v, unsigned int wheelId); + +typedef void (*capi_vehicle_set_body_health)(void *v, unsigned long health); + +typedef void (*capi_vehicle_set_body_additional_health)(void *v, unsigned long health); + +typedef void (*capi_vehicle_set_part_damage_level)(void *v, unsigned int partId, unsigned int damage); + +typedef void (*capi_vehicle_set_part_bullet_holes)(void *v, unsigned int partId, unsigned int shootsCount); + +typedef void (*capi_vehicle_set_light_damaged)(void *v, unsigned int lightId, int isDamaged); + +typedef void (*capi_vehicle_set_window_damaged)(void *v, unsigned int windowId, int isDamaged); + +typedef void (*capi_vehicle_set_special_light_damaged)(void *v, unsigned int specialLightId, int isDamaged); + +typedef void (*capi_vehicle_set_armored_window_health)(void *v, unsigned int windowId, float health); + +typedef void (*capi_vehicle_set_armored_window_shoot_count)(void *v, unsigned int windowId, unsigned int count); + +typedef void (*capi_vehicle_set_bumper_damage_level)(void *v, unsigned int bumperId, unsigned int damageLevel); + +typedef void (*capi_vehicle_set_manual_engine_control)(void *v, int state); + +typedef void (*capi_vehicle_load_damage_data_from_base64)(void *v, const char *base64); + +typedef void (*capi_vehicle_load_script_data_from_base64)(void *v, const char *base64); + +typedef void (*capi_vehicle_load_game_state_from_base64)(void *v, const char *base64); + +typedef void (*capi_vehicle_load_health_data_from_base64)(void *v, const char *base64); + +typedef Entity (*capi_vehicle_get_attached)(void *v); + +typedef Entity (*capi_vehicle_get_attached_to)(void *v); + +typedef void (*capi_vehicle_destroy)(void *v); + +typedef int (*capi_vehicle_is_valid)(const char *resourceName, void *p); + +typedef int (*capi_vehicle_get_streamed)(void *v); + +typedef void (*capi_vehicle_set_streamed)(void *v, int toggle); + +typedef int (*capi_vehicle_is_frozen)(void *v); + +typedef void (*capi_vehicle_set_frozen)(void *v, int state); + +typedef int (*capi_vehicle_has_collision)(void *v); + +typedef void (*capi_vehicle_set_collision)(void *v, int state); + +typedef int (*capi_vehicle_is_drift_mode)(void *v); + +typedef void (*capi_vehicle_set_drift_mode)(void *v, int state); + +typedef int (*capi_vehicle_is_train_mission_train)(void *v); + +typedef void (*capi_vehicle_set_train_mission_train)(void *v, int value); + +typedef char (*capi_vehicle_get_train_track_id)(void *v); + +typedef void (*capi_vehicle_set_train_track_id)(void *v, char trackId); + +typedef Entity (*capi_vehicle_get_train_engine_id)(void *v); + +typedef void (*capi_vehicle_set_train_engine_id)(void *v, void *e); + +typedef char (*capi_vehicle_get_train_config_index)(void *v); + +typedef void (*capi_vehicle_set_train_config_index)(void *v, char trainConfigIndex); + +typedef float (*capi_vehicle_get_train_distance_from_engine)(void *v); + +typedef void (*capi_vehicle_set_train_distance_from_engine)(void *v, float distanceFromEngine); + +typedef int (*capi_vehicle_is_train_engine)(void *v); + +typedef void (*capi_vehicle_set_train_is_engine)(void *v, int isEngine); + +typedef int (*capi_vehicle_is_train_caboose)(void *v); + +typedef void (*capi_vehicle_set_train_is_caboose)(void *v, int isCaboose); + +typedef int (*capi_vehicle_get_train_direction)(void *v); + +typedef void (*capi_vehicle_set_train_direction)(void *v, int direction); + +typedef int (*capi_vehicle_has_train_passenger_carriages)(void *v); + +typedef void (*capi_vehicle_set_train_has_passenger_carriages)(void *v, int hasPassengerCarriages); + +typedef int (*capi_vehicle_get_train_render_derailed)(void *v); + +typedef void (*capi_vehicle_set_train_render_derailed)(void *v, int renderDerailed); + +typedef int (*capi_vehicle_get_train_force_doors_open)(void *v); + +typedef void (*capi_vehicle_set_train_force_doors_open)(void *v, int forceDoorsOpen); + +typedef float (*capi_vehicle_get_train_cruise_speed)(void *v); + +typedef void (*capi_vehicle_set_train_cruise_speed)(void *v, float cruiseSpeed); + +typedef char (*capi_vehicle_get_train_carriage_config_index)(void *v); + +typedef void (*capi_vehicle_set_train_carriage_config_index)(void *v, char carriageConfigIndex); + +typedef Entity (*capi_vehicle_get_train_linked_to_backward_id)(void *v); + +typedef void (*capi_vehicle_set_train_linked_to_backward_id)(void *v, void *e); + +typedef Entity (*capi_vehicle_get_train_linked_to_forward_id)(void *v); + +typedef void (*capi_vehicle_set_train_linked_to_forward_id)(void *v, void *e); + +typedef void (*capi_vehicle_set_train_unk1)(void *v, int unk1); + +typedef int (*capi_vehicle_get_train_unk1)(void *v); + +typedef void (*capi_vehicle_set_train_unk2)(void *v, int unk2); + +typedef int (*capi_vehicle_get_train_unk2)(void *v); + +typedef void (*capi_vehicle_set_train_unk3)(void *v, int unk3); + +typedef int (*capi_vehicle_get_train_unk3)(void *v); + +typedef int (*capi_vehicle_is_boat_anchor_active)(void *v); + +typedef void (*capi_vehicle_set_boat_anchor_active)(void *v, int state); + +typedef int (*capi_vehicle_set_search_light)(void *v, int state, Entity e); + +typedef unsigned char (*capi_vehicle_get_light_state)(void *v); + +typedef void (*capi_vehicle_set_light_state)(void *v, unsigned char state); + +typedef unsigned char (*capi_vehicle_has_timed_explosion)(void *v); + +typedef Entity (*capi_vehicle_get_timed_explosion_culprit)(void *v); + +typedef unsigned int (*capi_vehicle_get_timed_explosion_time)(void *v); + +typedef void (*capi_vehicle_set_timed_explosion)(void *v, unsigned char state, void *culprit, unsigned int time); + +typedef unsigned char (*capi_vehicle_is_towing_disabled)(void *v); + +typedef void (*capi_vehicle_set_towing_disabled)(void *v, unsigned char state); + +typedef float (*capi_vehicle_get_rocket_refuel_speed)(void *v); + +typedef void (*capi_vehicle_set_rocket_refuel_speed)(void *v, float speed); + +typedef unsigned int (*capi_vehicle_get_counter_measure_count)(void *v); + +typedef void (*capi_vehicle_set_counter_measure_count)(void *v, unsigned int count); + +typedef float (*capi_vehicle_get_script_max_speed)(void *v); + +typedef void (*capi_vehicle_set_script_max_speed)(void *v, float speed); + +typedef int (*capi_vehicle_get_weapon_capacity)(void *v, unsigned char index); + +typedef void (*capi_vehicle_set_weapon_capacity)(void *v, unsigned char index, int capacity); + +typedef unsigned char (*capi_vehicle_get_hybrid_extra_active)(void *v); + +typedef void (*capi_vehicle_set_hybrid_extra_active)(void *v, unsigned char state); + +typedef unsigned char (*capi_vehicle_get_hybrid_extra_state)(void *v); + +typedef void (*capi_vehicle_set_hybrid_extra_state)(void *v, unsigned char state); + +typedef int (*capi_voice_channel_is_valid)(const char* resourceName, void *p); + +typedef int (*capi_voice_channel_get_type)(void *c); + +typedef int (*capi_voice_channel_has_meta_data)(void* base, const char *key); + +typedef Array (*capi_voice_channel_get_meta_data)(void* base, const char *key); + +typedef void (*capi_voice_channel_set_meta_data)(void *base, const char *key, Array data); + +typedef void (*capi_voice_channel_delete_meta_data)(void *base, const char *key); + +typedef void (*capi_voice_channel_destroy)(void *b); + +typedef int (*capi_voice_channel_is_spatial)(void *v); + +typedef float (*capi_voice_channel_get_max_distance)(void *v); + +typedef int (*capi_voice_channel_has_player)(void *v, void *p); + +typedef void (*capi_voice_channel_add_player)(void *v, void *p); + +typedef void (*capi_voice_channel_remove_player)(void *v, void *p); + +typedef int (*capi_voice_channel_is_player_muted)(void *v, void *p); + +typedef void (*capi_voice_channel_mute_player)(void *v, void *p); + +typedef void (*capi_voice_channel_unmute_player)(void *v, void *p); + +typedef unsigned long long (*capi_voice_channel_get_player_count)(void *v); + +typedef Array (*capi_voice_channel_get_players)(void *v); + +typedef int (*capi_checkpoint_get_type)(void *c); + +typedef int (*capi_checkpoint_has_meta_data)(void* base, const char *key); + +typedef Array (*capi_checkpoint_get_meta_data)(void* base, const char *key); + +typedef void (*capi_checkpoint_set_meta_data)(void *base, const char *key, Array data); + +typedef void (*capi_checkpoint_delete_meta_data)(void *base, const char *key); + +typedef void (*capi_checkpoint_destroy)(void *b); + +typedef int (*capi_checkpoint_is_valid)(const char* resourceName, void *p); + +typedef Position (*capi_checkpoint_get_position)(void *p); + +typedef void (*capi_checkpoint_set_position)(void* p, float x, float y, float z); + +typedef long (*capi_checkpoint_get_dimension)(void* p); + +typedef void (*capi_checkpoint_set_dimension)(void* p, long dimension); + +typedef int (*capi_checkpoint_get_col_shape_type)(void *c); + +typedef int (*capi_checkpoint_is_entity_in)(void *c, Entity e); + +typedef int (*capi_checkpoint_is_point_in)(void *c, float x, float y, float z); + +typedef void (*capi_checkpoint_set_players_only)(void *c, int state); + +typedef int (*capi_checkpoint_is_players_only)(void *c); + +typedef unsigned char (*capi_checkpoint_is_entity_id_in)(void *c, unsigned short id); + +typedef unsigned char (*capi_checkpoint_get_checkpoint_type)(void *c); + +typedef float (*capi_checkpoint_get_height)(void *c); + +typedef float (*capi_checkpoint_get_radius)(void *c); + +typedef RGBA (*capi_checkpoint_get_color)(void *c); + +typedef Position (*capi_checkpoint_get_next_position)(void *c); + +typedef void (*capi_checkpoint_set_checkpoint_type)(void *c, unsigned char type); + +typedef void (*capi_checkpoint_set_height)(void *c, float height); + +typedef void (*capi_checkpoint_set_radius)(void *c, float radius); + +typedef void (*capi_checkpoint_set_color)(void *c, unsigned char r, unsigned char g, unsigned char b, unsigned char a); + +typedef void (*capi_checkpoint_set_next_position)(void *c, float x, float y, float z); + + + +int blip_get_type(void *c); + +int blip_has_meta_data(void *base, const char *key); + +Array blip_get_meta_data(void *base, const char *key); + +void blip_set_meta_data(void *base, const char *key, Array data); + +void blip_delete_meta_data(void *base, const char *key); + +void blip_destroy(void *b); + +int blip_is_valid(const char *resourceName, void *p); + +Position blip_get_position(void *p); + +void blip_set_position(void *p, float x, float y, float z); + +long blip_get_dimension(void *p); + +void blip_set_dimension(void *p, long dimension); + +int blip_is_global(void *b); + +Array blip_get_targets(void *b); + +int blip_is_attached(void *b); + +Entity blip_attached_to(void *b); + +void blip_attach_to(void *b, Entity e); + +unsigned char blip_get_blip_type(void *b); + +Vector2 blip_get_scale_xy(void *b); + +void blip_set_scale_xy(void *b, Vector2 scale); + +int blip_get_display(void *b); + +void blip_set_display(void *b, int display); + +int blip_get_sprite(void *b); + +int blip_get_color(void *b); + +RGBA blip_get_secondary_color(void *b); + +int blip_get_alpha(void *b); + +int blip_get_flash_timer(void *b); + +int blip_get_flash_interval(void *b); + +int blip_get_as_friendly(void *b); + +int blip_get_route(void *b); + +int blip_get_bright(void *b); + +int blip_get_number(void *b); + +int blip_get_show_cone(void *b); + +int blip_get_flashes(void *b); + +int blip_get_flashes_alternate(void *b); + +int blip_get_as_short_range(void *b); + +int blip_get_priority(void *b); + +float blip_get_rotation(void *b); + +const char * blip_get_gxt_name(void *b); + +const char * blip_get_name(void *b); + +RGBA blip_get_route_color(void *b); + +int blip_get_pulse(void *b); + +int blip_get_as_mission_creator(void *b); + +int blip_get_tick_visible(void *b); + +int blip_get_heading_indicator_visible(void *b); + +int blip_get_outline_indicator_visible(void *b); + +int blip_get_friend_indicator_visible(void *b); + +int blip_get_crew_indicator_visible(void *b); + +int blip_get_category(void *b); + +int blip_get_as_high_detail(void *b); + +int blip_get_shrinked(void *b); + +void blip_set_sprite(void *b, int sprite); + +void blip_set_color(void *b, int color); + +void blip_set_route(void *b, int state); + +void blip_set_route_color(void *b, RGBA color); + +void blip_set_secondary_color(void *b, RGBA color); + +void blip_set_alpha(void *b, int alpha); + +void blip_set_flash_timer(void *b, int timer); + +void blip_set_flash_interval(void *b, int interval); + +void blip_set_as_friendly(void *b, int friendly); + +void blip_set_bright(void *b, int bright); + +void blip_set_number(void *b, int number); + +void blip_set_show_cone(void *b, int state); + +void blip_set_flashes(void *b, int state); + +void blip_set_flashes_alternate(void *b, int state); + +void blip_set_as_short_range(void *b, int state); + +void blip_set_priority(void *b, int state); + +void blip_set_rotation(void *b, float rot); + +void blip_set_gxt_name(void *b, const char *name); + +void blip_set_name(void *b, const char *name); + +void blip_set_pulse(void *b, int val); + +void blip_set_as_mission_creator(void *b, int val); + +void blip_set_tick_visible(void *b, int val); + +void blip_set_heading_indicator_visible(void *b, int val); + +void blip_set_outline_indicator_visible(void *b, int val); + +void blip_set_friend_indicator_visible(void *b, int val); + +void blip_set_crew_indicator_visible(void *b, int val); + +void blip_set_category(void *b, int val); + +void blip_set_as_high_detail(void *b, int val); + +void blip_set_shrinked(void *b, int val); + +void blip_fade(void *b, unsigned int opacity, unsigned int duration); + +void core_log_info(const char *message); + +void core_log_debug(const char *message); + +void core_log_warning(const char *message); + +void core_log_error(const char *message); + +void core_log_colored(const char *message); + +Entity core_create_vehicle(unsigned long model, float posX, float posY, float posZ, + float rotX, float rotY, float rotZ); + +Entity + core_create_checkpoint(unsigned char type, float x, float y, float z, float radius, float height, unsigned char r, + unsigned char g, unsigned char b, unsigned char a, unsigned long streamingDistance); + +Entity core_create_voice_channel(int spacial, float maxDistance); + +const char * core_get_version(); + +const char * core_get_branch(); + +int core_is_debug(); + +unsigned long core_hash(const char *str); + +int core_file_exists(const char *path); + +const char * core_read_file(const char *path); + +Entity core_get_entity_by_id(unsigned short id); + +Entity core_get_base_object_by_id(unsigned char type, unsigned int id); + +Array core_get_entities(); + +Array core_get_players(); + +Array core_get_vehicles(); + +Array core_get_blips(); + +Array core_get_col_shapes(); + +Array core_get_checkpoints(); + +Array core_get_virtual_entities(); + +Array core_get_virtual_entity_groups(); + +Array core_get_markers(); + +Array core_get_peds(); + +int core_has_meta_data(const char *key); + +Array core_get_meta_data(const char *key); + +void core_set_meta_data(const char *key, Array data); + +void core_delete_meta_data(const char *key); + +int core_has_synced_meta_data(const char *key); + +Array core_get_synced_meta_data(const char *key); + +Array core_get_required_permissions(); + +Array core_get_optional_permissions(); + +void core_destroy_base_object(void *h); + +const char * core_get_root_directory(); + +int core_start_resource(const char *name); + +void core_stop_resource(const char *name); + +void core_restart_resource(const char *name); + +void core_set_synced_meta_data(const char *key, Array data); + +void core_delete_synced_meta_data(const char *key); + +Array core_get_players_by_name(const char *name); + +unsigned int core_get_net_time(); + +void core_set_password(const char *password); + +const char * core_get_sdk_hash(); + +Entity core_create_col_shape_cylinder(float posX, float posY, float posZ, float radius, float height); + +Entity core_create_col_shape_cube(float posX1, float posY1, float posZ1, float posX2, float posY2, float posZ2); + +Entity core_create_col_shape_rectangle(float x1, float y1, float x2, float y2, float z); + +Entity core_create_col_shape_circle(float posX, float posY, float posZ, float radius); + +Entity core_create_col_shape_sphere(float posX, float posY, float posZ, float radius); + +void core_trigger_local_event(const char *ev, Array args); + +void core_trigger_local_event_raw(const char* ev, char* bytes, unsigned long long size); + +void core_trigger_client_event(void *p, const char *ev, Array args); + +void core_trigger_client_event_for(Array clients, const char *ev, Array args); + +void core_trigger_client_event_for_all(const char *ev, Array args); + +Entity core_create_point_blip_position(float x, float y, float z, unsigned short global); + +Entity core_create_point_blip_entity(Entity entity, unsigned short global); + +Entity core_create_area_blip(float x, float y, float z, float width, float height, unsigned short global); + +Entity core_create_radius_blip(float x, float y, float z, float radius, unsigned short global); + +Entity core_create_col_shape_polygon(float minZ, float maxZ, Array points); + +Array core_get_all_resources(); + +const char * core_string_to_sha256(const char *str); + +void core_stop_server(); + +VehicleModelInfo core_get_vehicle_model_by_hash(unsigned int hash); + +PedModelInfo core_get_ped_model_by_hash(unsigned int hash); + +Array core_get_server_config(); + +unsigned long long core_hash_server_password(const char *password); + +void* core_get_resource_by_name(const char *resourceName); + +unsigned char resource_is_started(void *r); + +const char * resource_get_type(void *r); + +const char * resource_get_name(void* r); + +const char * resource_get_main(void *r); + +Array resource_get_config(void *r); + +Array resource_get_exports(void *r); + +Array resource_get_dependencies(void *r); + +Array resource_get_dependants(void *r); + +Array resource_get_required_permissions(void *r); + +Array resource_get_optional_permissions(void *r); + +const char * resource_get_path(void *r); + +int col_shape_get_type(void *c); + +int col_shape_has_meta_data(void* base, const char *key); + +Array col_shape_get_meta_data(void* base, const char *key); + +void col_shape_set_meta_data(void *base, const char *key, Array data); + +void col_shape_delete_meta_data(void *base, const char *key); + +void col_shape_destroy(void *b); + +int col_shape_is_valid(const char* resourceName, void *p); + +Position col_shape_get_position(void *p); + +void col_shape_set_position(void* p, float x, float y, float z); + +long col_shape_get_dimension(void* p); + +void col_shape_set_dimension(void* p, long dimension); + +int col_shape_get_col_shape_type(void *c); + +int col_shape_is_entity_in(void *c, Entity e); + +int col_shape_is_point_in(void *c, float x, float y, float z); + +void col_shape_set_players_only(void *c, int state); + +int col_shape_is_players_only(void *c); + +unsigned char col_shape_is_entity_id_in(void *c, unsigned short id); + +const char * player_get_name(void *p); + +int player_has_meta_data(void *base, const char *key); + +Array player_get_meta_data(void *base, const char *key); + +void player_set_meta_data(void *base, const char *key, Array data); + +void player_delete_meta_data(void *base, const char *key); + +int player_has_synced_meta_data(void *base, const char *key); + +Array player_get_synced_meta_data(void *base, const char *key); + +void player_set_synced_meta_data(void *base, const char *key, Array data); + +void player_delete_synced_meta_data(void *base, const char *key); + +int player_has_stream_synced_meta_data(void *base, const char *key); + +Array player_get_stream_synced_meta_data(void *base, const char *key); + +void player_set_stream_synced_meta_data(void *base, const char *key, Array data); + +void player_delete_stream_synced_meta_data(void *base, const char *key); + +Position player_get_position(void *p); + +void player_set_position(void *p, float x, float y, float z); + +Rotation player_get_rotation(void *p); + +void player_set_rotation(void *p, float roll, float pitch, float yaw); + +long player_get_dimension(void *p); + +void player_set_dimension(void *p, long dimension); + +void player_spawn(void *p, float x, float y, float z, unsigned long delay); -// /home/timo/dev/os/altv/altv-go/runtime/src/capi/Player.h Module.h -const char * player_get_name(void *p); -int player_has_meta_data(void *base, const char *key); -Array player_get_meta_data(void *base, const char *key); -void player_set_meta_data(void *base, const char *key, Array data); -void player_delete_meta_data(void *base, const char *key); -int player_has_synced_meta_data(void *base, const char *key); -Array player_get_synced_meta_data(void *base, const char *key); -void player_set_synced_meta_data(void *base, const char *key, Array data); -void player_delete_synced_meta_data(void *base, const char *key); -int player_has_stream_synced_meta_data(void *base, const char *key); -Array player_get_stream_synced_meta_data(void *base, const char *key); -void player_set_stream_synced_meta_data(void *base, const char *key, Array data); -void player_delete_stream_synced_meta_data(void *base, const char *key); -Position player_get_position(void *p); -void player_set_position(void *p, float x, float y, float z); -Rotation player_get_rotation(void *p); -void player_set_rotation(void *p, float roll, float pitch, float yaw); -long player_get_dimension(void *p); -void player_set_dimension(void *p, long dimension); -void player_spawn(void *p, float x, float y, float z, unsigned long delay); void player_despawn(void *p); -void player_set_model(void *p, unsigned long model); + +void player_set_model(void *p, unsigned long model); + unsigned long player_get_model(void *p); + unsigned int player_get_health(void *p); -void player_set_health(void *p, unsigned int health); -int player_has_weapon_component(void *p, unsigned long weapon, unsigned long component); + +void player_set_health(void *p, unsigned int health); + +int player_has_weapon_component(void *p, unsigned long weapon, unsigned long component); + Array player_get_current_weapon_components(void *p); -unsigned int player_get_weapon_tint_index(void *p, unsigned long weapon); + +unsigned int player_get_weapon_tint_index(void *p, unsigned long weapon); + unsigned int player_get_current_weapon_tint_index(void *p); + unsigned long player_get_current_weapon(void *p); + int player_is_dead(void *p); + int player_is_jumping(void *p); + int player_is_in_ragdoll(void *p); + int player_is_aiming(void *p); + int player_is_shooting(void *p); + int player_is_reloading(void *p); + unsigned int player_get_armour(void *p); -void player_set_armour(void *p, unsigned int armour); + +void player_set_armour(void *p, unsigned int armour); + float player_get_move_speed(void *p); + Position player_get_aim_pos(void *p); + Rotation player_get_head_rotation(void *p); + int player_is_in_vehicle(void *p); + Entity player_get_vehicle(void *p); + unsigned int player_get_seat(void *p); + Entity player_get_entity_aiming_at(void *p); + Position player_get_entity_aim_offset(void *p); + int player_is_flashlight_active(void *p); + int player_is_connected(void *p); + unsigned long player_get_ping(void *p); -const char * player_get_i_p(void *p); -unsigned long long player_get_social_i_d(void *p); + +const char * player_get_ip(void *p); + +unsigned long long player_get_social_id(void *p); + unsigned long long player_get_hwid_hash(void *p); + unsigned long long player_get_hwid_ex_hash(void *p); + const char * player_get_auth_token(void *p); -void player_set_max_armour(void *p, unsigned int armour); -void player_set_current_weapon(void *p, unsigned long weapon); -void player_set_weapon_tint_index(void *p, unsigned long weapon, unsigned int tintIndex); -void player_add_weapon_component(void *p, unsigned long weapon, unsigned long component); -void player_remove_weapon_component(void *p, unsigned long weapon, unsigned long component); + +void player_set_max_armour(void *p, unsigned int armour); + +void player_set_current_weapon(void *p, unsigned long weapon); + +void player_set_weapon_tint_index(void *p, unsigned long weapon, unsigned int tintIndex); + +void player_add_weapon_component(void *p, unsigned long weapon, unsigned long component); + +void player_remove_weapon_component(void *p, unsigned long weapon, unsigned long component); + void player_clear_blood_damage(void *p); -void player_set_max_health(void *p, unsigned int health); -void player_give_weapon(void *p, unsigned long weapon, long ammo, int selectWeapon); -void player_remove_weapon(void *p, unsigned long weapon); -void player_remove_all_weapons(void *p, unsigned short removeAmmo); -void player_set_date_time(void *p, int day, int month, int year, int hour, int minute, int second); -void player_set_weather(void *p, unsigned long weather); -void player_kick(void *p, const char *reason); -Cloth player_get_clothes(void *p, unsigned int component); -DlcCloth player_get_dlc_clothes(void *p, unsigned int component); -Prop player_get_props(void *p, unsigned int component); -DlcProp player_get_dlc_props(void *p, unsigned int component); -void player_set_clothes(void *p, unsigned int component, unsigned int drawable, unsigned int texture, unsigned int palette); -void player_set_dlc_clothes(void *p, unsigned int component, unsigned int drawable, unsigned int texture, unsigned int palette, + +void player_set_max_health(void *p, unsigned int health); + +void player_give_weapon(void *p, unsigned long weapon, long ammo, int selectWeapon); + +void player_remove_weapon(void *p, unsigned long weapon); + +void player_remove_all_weapons(void *p, unsigned short removeAmmo); + +void player_set_date_time(void *p, int day, int month, int year, int hour, int minute, int second); + +void player_set_weather(void *p, unsigned long weather); + +void player_kick(void *p, const char *reason); + +Cloth player_get_clothes(void *p, unsigned int component); + +DlcCloth player_get_dlc_clothes(void *p, unsigned int component); + +Prop player_get_props(void *p, unsigned int component); + +DlcProp player_get_dlc_props(void *p, unsigned int component); + +void + player_set_clothes(void *p, unsigned int component, unsigned int drawable, unsigned int texture, unsigned int palette); + +void + player_set_dlc_clothes(void *p, unsigned int component, unsigned int drawable, unsigned int texture, unsigned int palette, unsigned long dlc); -void player_set_props(void *p, unsigned int component, unsigned int drawable, unsigned int texture); -void player_set_dlc_props(void *p, unsigned int component, unsigned int drawable, unsigned int texture, unsigned long dlc); -void player_clear_props(void *p, unsigned int component); -int player_is_entity_in_streaming_range(void *p, unsigned short entityId); + +void player_set_props(void *p, unsigned int component, unsigned int drawable, unsigned int texture); + +void + player_set_dlc_props(void *p, unsigned int component, unsigned int drawable, unsigned int texture, unsigned long dlc); + +void player_clear_props(void *p, unsigned int component); + +int player_is_entity_in_streaming_range(void *p, unsigned short entityId); + unsigned int player_get_max_health(void *p); + unsigned int player_get_max_armour(void *p); + void player_detach(void *p); -void player_attach_to_entity(void *p, Entity e, int otherBoneIndex, int myBoneIndex, Position position, Rotation rotation, - int collision, int noFixedRotation); -void player_set_visible(void *p, int toggle); + +void + player_attach_to_entity(void *p, Entity e, int otherBoneIndex, int myBoneIndex, Position position, Rotation rotation, + int collision, int noFixedRotation); + +void player_set_visible(void *p, int toggle); + int player_get_visible(void *p); -unsigned long player_get_i_d(void *p); + +unsigned long player_get_id(void *p); + Entity player_get_network_owner(void *p); -void player_set_network_owner(void *p, void *owner, int disableMigration); + +void player_set_network_owner(void *p, void *owner, int disableMigration); + void player_destroy(void *p); -int player_is_valid(const char* resourceName, void *p); + +int player_is_valid(const char* resourceName, void *p); + int player_get_streamed(void *p); -void player_set_streamed(void *p, int toggle); + +void player_set_streamed(void *p, int toggle); + int player_get_invincible(void *p); -void player_set_invincible(void *p, int toggle); -void player_set_into_vehicle(void *p, void *v, unsigned char seat); + +void player_set_invincible(void *p, int toggle); + +void player_set_into_vehicle(void *p, void *v, unsigned char seat); + int player_is_frozen(void *p); -void player_set_frozen(void *p, int state); + +void player_set_frozen(void *p, int state); + int player_has_collision(void *p); -void player_set_collision(void *p, int state); -void player_play_ambient_speech(void *p, const char *speechName, const char *speechParam, unsigned int speechDictHash); -int player_set_head_overlay(void *p, unsigned char overlayID, unsigned char index, float opacity); -int player_remove_head_overlay(void *p, unsigned char overlayID); -int player_set_head_overlay_color(void *p, unsigned char overlayID, unsigned char colorType, unsigned char colorIndex, + +void player_set_collision(void *p, int state); + +void + player_play_ambient_speech(void *p, const char *speechName, const char *speechParam, unsigned int speechDictHash); + +int player_set_head_overlay(void *p, unsigned char overlayID, unsigned char index, float opacity); + +int player_remove_head_overlay(void *p, unsigned char overlayID); + +int + player_set_head_overlay_color(void *p, unsigned char overlayID, unsigned char colorType, unsigned char colorIndex, unsigned char secondColorIndex); -HeadOverlay player_get_head_overlay(void *p, unsigned char overlayID); -int player_set_face_feature(void *p, unsigned char index, float scale); -float player_get_face_feature_scale(void *p, unsigned char index); -int player_remove_face_feature(void *p, unsigned char index); -int player_set_head_blend_palette_color(void *p, unsigned char id, unsigned char red, unsigned char green, unsigned char blue); -RGBA player_get_head_blend_palette_color(void *p, unsigned char id); -void player_set_head_blend_data(void *p, unsigned int shapeFirstID, unsigned int shapeSecondID, unsigned int shapeThirdID, - unsigned int skinFirstID, unsigned int skinSecondID, unsigned int skinThirdID, - float shapeMix, float skinMix, float thirdMix); + +HeadOverlay player_get_head_overlay(void *p, unsigned char overlayID); + +int player_set_face_feature(void *p, unsigned char index, float scale); + +float player_get_face_feature_scale(void *p, unsigned char index); + +int player_remove_face_feature(void *p, unsigned char index); + +int + player_set_head_blend_palette_color(void *p, unsigned char id, unsigned char red, unsigned char green, unsigned char blue); + +RGBA player_get_head_blend_palette_color(void *p, unsigned char id); + +void + player_set_head_blend_data(void *p, unsigned int shapeFirstID, unsigned int shapeSecondID, unsigned int shapeThirdID, + unsigned int skinFirstID, unsigned int skinSecondID, unsigned int skinThirdID, + float shapeMix, float skinMix, float thirdMix); + HeadBlendData player_get_head_blend_data(void *p); -int player_set_eye_color(void *p, short eyeColor); + +int player_set_eye_color(void *p, short eyeColor); + short player_get_eye_color(void *p); -void player_set_hair_color(void *p, unsigned char hairColor); + +void player_set_hair_color(void *p, unsigned char hairColor); + unsigned char player_get_hair_color(void *p); -void player_set_hair_highlight_color(void *p, unsigned char hairHighlightColor); + +void player_set_hair_highlight_color(void *p, unsigned char hairHighlightColor); + unsigned char player_get_hair_highlight_color(void *p); + Array player_get_weapons(void *p); -int player_has_local_meta_data(void *p, const char *key); -void player_set_local_meta_data(void *p, const char *key, Array data); -Array player_get_local_meta_data(void *p, const char *key); -void player_delete_local_meta_data(void *p, const char *key); + +int player_has_local_meta_data(void *p, const char *key); + +void player_set_local_meta_data(void *p, const char *key, Array data); + +Array player_get_local_meta_data(void *p, const char *key); + +void player_delete_local_meta_data(void *p, const char *key); + unsigned int player_get_current_animation_dict(void *p); + unsigned int player_get_current_animation_name(void *p); + unsigned char player_is_spawned(void *p); + float player_get_forward_speed(void *p); + float player_get_strafe_speed(void *p); + long long player_get_discord_id(void *p); + unsigned int player_get_interior_location(void *p); + unsigned int player_get_last_damaged_body_part(void *p); -void player_set_last_damaged_body_part(void *p, unsigned int bodyPart); -// /home/timo/dev/os/altv/altv-go/runtime/src/capi/Resource.h Module.h -typedef unsigned char (*capi_resource_is_started)(void *r); -typedef const char * (*capi_resource_get_type)(void *r); -typedef const char * (*capi_resource_get_name)(void* r); -typedef const char * (*capi_resource_get_main)(void *r); -typedef Array (*capi_resource_get_config)(void *r); -typedef Array (*capi_resource_get_exports)(void *r); -typedef Array (*capi_resource_get_dependencies)(void *r); -typedef Array (*capi_resource_get_dependants)(void *r); -typedef Array (*capi_resource_get_required_permissions)(void *r); -typedef Array (*capi_resource_get_optional_permissions)(void *r); -typedef const char * (*capi_resource_get_path)(void *r); +void player_set_last_damaged_body_part(void *p, unsigned int bodyPart); +int runtime_register_alt_event(const char *resourceName, unsigned short eventType); -// /home/timo/dev/os/altv/altv-go/runtime/src/capi/Resource.h Module.h -unsigned char resource_is_started(void *r); -const char * resource_get_type(void *r); -const char * resource_get_name(void* r); -const char * resource_get_main(void *r); -Array resource_get_config(void *r); -Array resource_get_exports(void *r); -Array resource_get_dependencies(void *r); -Array resource_get_dependants(void *r); -Array resource_get_required_permissions(void *r); -Array resource_get_optional_permissions(void *r); -const char * resource_get_path(void *r); +int runtime_unregister_alt_event(const char *resourceName, unsigned short eventType); -// /home/timo/dev/os/altv/altv-go/runtime/src/capi/Runtime.h Module.h -typedef int (*capi_runtime_register_alt_event)(const char *resourceName, unsigned short eventType); -typedef int (*capi_runtime_unregister_alt_event)(const char *resourceName, unsigned short eventType); -typedef int (*capi_runtime_register_alt_export)(const char *resourceName, const char *exportName, Array value); -typedef Array (*capi_runtime_get_alt_export)(const char *targetResourceName, const char *exportName); -typedef void * (*capi_runtime_create_m_value_function)(const char *resourceName, unsigned long long id); -typedef Array (*capi_runtime_call_m_value_function)(void *ptr, Array args); -typedef void (*capi_connection_accept)(void *handle, unsigned char sendNames); -typedef void (*capi_connection_decline)(void *handle, const char *reason); -typedef int (*capi_connection_is_accepted)(void *handle); +int runtime_register_alt_export(const char *resourceName, const char *exportName, Array value); + +Array runtime_get_alt_export(const char *targetResourceName, const char *exportName); +void * runtime_create_m_value_function(const char *resourceName, unsigned long long id); + +Array runtime_call_m_value_function(void *ptr, Array args); + +void connection_accept(void *handle, unsigned char sendNames); + +void connection_decline(void *handle, const char *reason); -// /home/timo/dev/os/altv/altv-go/runtime/src/capi/Runtime.h Module.h -int runtime_register_alt_event(const char *resourceName, unsigned short eventType); -int runtime_unregister_alt_event(const char *resourceName, unsigned short eventType); -int runtime_register_alt_export(const char *resourceName, const char *exportName, Array value); -Array runtime_get_alt_export(const char *targetResourceName, const char *exportName); -void * runtime_create_m_value_function(const char *resourceName, unsigned long long id); -Array runtime_call_m_value_function(void *ptr, Array args); -void connection_accept(void *handle, unsigned char sendNames); -void connection_decline(void *handle, const char *reason); int connection_is_accepted(void *handle); -// /home/timo/dev/os/altv/altv-go/runtime/src/capi/Vehicle.h Module.h -typedef int (*capi_vehicle_has_meta_data)(void *base, const char *key); -typedef Array (*capi_vehicle_get_meta_data)(void *base, const char *key); -typedef void (*capi_vehicle_set_meta_data)(void *base, const char *key, Array data); -typedef void (*capi_vehicle_delete_meta_data)(void *base, const char *key); -typedef int (*capi_vehicle_has_synced_meta_data)(void *base, const char *key); -typedef Array (*capi_vehicle_get_synced_meta_data)(void *base, const char *key); -typedef void (*capi_vehicle_set_synced_meta_data)(void *base, const char *key, Array data); -typedef void (*capi_vehicle_delete_synced_meta_data)(void *base, const char *key); -typedef int (*capi_vehicle_has_stream_synced_meta_data)(void *base, const char *key); -typedef Array (*capi_vehicle_get_stream_synced_meta_data)(void *base, const char *key); -typedef void (*capi_vehicle_set_stream_synced_meta_data)(void *base, const char *key, Array data); -typedef void (*capi_vehicle_delete_stream_synced_meta_data)(void *base, const char *key); -typedef Position (*capi_vehicle_get_position)(void *v); -typedef void (*capi_vehicle_set_position)(void *v, float x, float y, float z); -typedef Rotation (*capi_vehicle_get_rotation)(void *v); -typedef void (*capi_vehicle_set_rotation)(void *v, float roll, float pitch, float yaw); -typedef long (*capi_vehicle_get_dimension)(void *v); -typedef void (*capi_vehicle_set_dimension)(void *v, long dimension); -typedef unsigned long (*capi_vehicle_get_i_d)(void *v); -typedef unsigned long (*capi_vehicle_get_model)(void *v); -typedef void (*capi_vehicle_detach)(void *v); -typedef void (*capi_vehicle_attach_to_entity)(void *v, Entity e, int otherBoneIndex, int myBoneIndex, Position position, Rotation rotation, - int collision, int noFixedRotation); -typedef void (*capi_vehicle_set_visible)(void *v, int toggle); -typedef int (*capi_vehicle_get_visible)(void *v); -typedef Entity (*capi_vehicle_get_network_owner)(void *v); -typedef void (*capi_vehicle_set_network_owner)(void *v, void *owner, int disableMigration); -typedef Entity (*capi_vehicle_get_driver)(void *v); -typedef int (*capi_vehicle_is_destroyed)(void *v); -typedef unsigned long (*capi_vehicle_get_mod)(void *v, unsigned int category); -typedef unsigned long (*capi_vehicle_get_mods_count)(void *v, unsigned int category); -typedef unsigned long (*capi_vehicle_get_mod_kits_count)(void *v); -typedef unsigned long (*capi_vehicle_get_mod_kit)(void *v); -typedef int (*capi_vehicle_is_primary_color_r_g_b)(void *v); -typedef unsigned long (*capi_vehicle_get_primary_color)(void *v); -typedef RGBA (*capi_vehicle_get_primary_color_r_g_b)(void *v); -typedef int (*capi_vehicle_is_secondary_color_r_g_b)(void *v); -typedef unsigned long (*capi_vehicle_get_secondary_color)(void *v); -typedef RGBA (*capi_vehicle_get_secondary_color_r_g_b)(void *v); -typedef unsigned long (*capi_vehicle_get_pearl_color)(void *v); -typedef unsigned long (*capi_vehicle_get_wheel_color)(void *v); -typedef unsigned long (*capi_vehicle_get_interior_color)(void *v); -typedef unsigned long (*capi_vehicle_get_dashboard_color)(void *v); -typedef int (*capi_vehicle_is_tire_smoke_color_custom)(void *v); -typedef RGBA (*capi_vehicle_get_tire_smoke_color)(void *v); -typedef unsigned long (*capi_vehicle_get_wheel_type)(void *v); -typedef unsigned long (*capi_vehicle_get_wheel_variation)(void *v); -typedef unsigned long (*capi_vehicle_get_rear_wheel_variation)(void *v); -typedef int (*capi_vehicle_get_custom_tires)(void *v); -typedef unsigned long (*capi_vehicle_get_special_darkness)(void *v); -typedef unsigned long (*capi_vehicle_get_numberplate_index)(void *v); -typedef const char * (*capi_vehicle_get_numberplate_text)(void *v); -typedef unsigned long (*capi_vehicle_get_window_tint)(void *v); -typedef unsigned long (*capi_vehicle_get_dirt_level)(void *v); -typedef int (*capi_vehicle_is_extra_on)(void *v, unsigned int extraID); -typedef int (*capi_vehicle_is_neon_active)(void *v); -typedef VehicleNeonState (*capi_vehicle_get_neon_active)(void *v); -typedef RGBA (*capi_vehicle_get_neon_color)(void *v); -typedef unsigned long (*capi_vehicle_get_livery)(void *v); -typedef unsigned long (*capi_vehicle_get_roof_livery)(void *v); -typedef const char * (*capi_vehicle_get_appearance_data_base64)(void *v); -typedef int (*capi_vehicle_is_engine_on)(void *v); -typedef int (*capi_vehicle_is_handbrake_active)(void *v); -typedef unsigned long (*capi_vehicle_get_headlight_color)(void *v); -typedef unsigned long (*capi_vehicle_get_radio_station_index)(void *v); -typedef int (*capi_vehicle_is_siren_active)(void *v); -typedef unsigned long (*capi_vehicle_get_lock_state)(void *v); -typedef unsigned long (*capi_vehicle_get_door_state)(void *v, unsigned int doorId); -typedef int (*capi_vehicle_is_window_opened)(void *v, unsigned int windowId); -typedef int (*capi_vehicle_is_daylight_on)(void *v); -typedef int (*capi_vehicle_is_nightlight_on)(void *v); -typedef unsigned long (*capi_vehicle_get_roof_state)(void *v); -typedef int (*capi_vehicle_is_flamethrower_active)(void *v); -typedef float (*capi_vehicle_get_lights_multiplier)(void *v); -typedef const char * (*capi_vehicle_get_game_state_base64)(void *v); -typedef long (*capi_vehicle_get_engine_health)(void *v); -typedef long (*capi_vehicle_get_petrol_tank_health)(void *v); -typedef unsigned long (*capi_vehicle_get_wheels_count)(void *v); -typedef int (*capi_vehicle_is_wheel_burst)(void *v, unsigned int wheelId); -typedef int (*capi_vehicle_does_wheel_has_tire)(void *v, unsigned int wheelId); -typedef int (*capi_vehicle_is_wheel_detached)(void *v, unsigned int wheelId); -typedef int (*capi_vehicle_is_wheel_on_fire)(void *v, unsigned int wheelId); -typedef float (*capi_vehicle_get_wheel_health)(void *v, unsigned int wheelId); -typedef unsigned long (*capi_vehicle_get_repairs_count)(void *v); -typedef unsigned long (*capi_vehicle_get_body_health)(void *v); -typedef unsigned long (*capi_vehicle_get_body_additional_health)(void *v); -typedef const char * (*capi_vehicle_get_health_data_base64)(void *v); -typedef unsigned long (*capi_vehicle_get_part_damage_level)(void *v, unsigned int partId); -typedef unsigned long (*capi_vehicle_get_part_bullet_holes)(void *v, unsigned int partId); -typedef int (*capi_vehicle_is_light_damaged)(void *v, unsigned int lightId); -typedef int (*capi_vehicle_is_window_damaged)(void *v, unsigned int windowId); -typedef int (*capi_vehicle_is_special_light_damaged)(void *v, unsigned int specialLightId); -typedef int (*capi_vehicle_has_armored_windows)(void *v); -typedef float (*capi_vehicle_get_armored_window_health)(void *v, unsigned int windowId); -typedef unsigned long (*capi_vehicle_get_armored_window_shoot_count)(void *v, unsigned int windowId); -typedef unsigned long (*capi_vehicle_get_bumper_damage_level)(void *v, unsigned int bumperId); -typedef const char * (*capi_vehicle_get_damage_data_base64)(void *v); -typedef int (*capi_vehicle_is_manual_engine_control)(void *v); -typedef const char * (*capi_vehicle_get_script_data_base64)(void *v); -typedef void (*capi_vehicle_toggle_extra)(void *v, unsigned int extraID, int state); -typedef void (*capi_vehicle_set_fixed)(void *v); -typedef int (*capi_vehicle_set_mod)(void *v, unsigned int category, unsigned int id); -typedef int (*capi_vehicle_set_mod_kit)(void *v, unsigned int id); -typedef void (*capi_vehicle_set_primary_color)(void *v, unsigned int color); -typedef void (*capi_vehicle_set_primary_color_r_g_b)(void *v, unsigned int r, unsigned int g, unsigned int b, unsigned int a); -typedef void (*capi_vehicle_set_secondary_color)(void *v, unsigned int color); -typedef void (*capi_vehicle_set_secondary_color_r_g_b)(void *v, unsigned int r, unsigned int g, unsigned int b, unsigned int a); -typedef void (*capi_vehicle_set_pearl_color)(void *v, unsigned int color); -typedef void (*capi_vehicle_set_wheel_color)(void *v, unsigned int color); -typedef void (*capi_vehicle_set_interior_color)(void *v, unsigned int color); -typedef void (*capi_vehicle_set_dashboard_color)(void *v, unsigned int color); -typedef void (*capi_vehicle_set_tire_smoke_color)(void *v, unsigned int r, unsigned int g, unsigned int b, unsigned int a); -typedef void (*capi_vehicle_set_wheels)(void *v, unsigned int type, unsigned int variation); -typedef void (*capi_vehicle_set_rear_wheels)(void *v, unsigned int variation); -typedef void (*capi_vehicle_set_custom_tires)(void *v, int state); -typedef void (*capi_vehicle_set_special_darkness)(void *v, unsigned int value); -typedef void (*capi_vehicle_set_numberplate_index)(void *v, unsigned int index); -typedef void (*capi_vehicle_set_numberplate_text)(void *v, const char *text); -typedef void (*capi_vehicle_set_window_tint)(void *v, unsigned int tint); -typedef void (*capi_vehicle_set_dirt_level)(void *v, unsigned int level); -typedef void (*capi_vehicle_set_neon_active)(void *v, int left, int right, int front, int back); -typedef void (*capi_vehicle_set_neon_color)(void *v, unsigned int r, unsigned int g, unsigned int b, unsigned int a); -typedef void (*capi_vehicle_set_livery)(void *v, unsigned int livery); -typedef void (*capi_vehicle_set_roof_livery)(void *v, unsigned int roofLivery); -typedef void (*capi_vehicle_load_appearance_data_from_base64)(void *v, const char *base64); -typedef void (*capi_vehicle_set_engine_on)(void *v, int state); -typedef void (*capi_vehicle_set_headlight_color)(void *v, unsigned int color); -typedef void (*capi_vehicle_set_radio_station_index)(void *v, unsigned int stationIndex); -typedef void (*capi_vehicle_set_siren_active)(void *v, int state); -typedef void (*capi_vehicle_set_lock_state)(void *v, unsigned int state); -typedef void (*capi_vehicle_set_door_state)(void *v, unsigned int doorId, unsigned int state); -typedef void (*capi_vehicle_set_window_opened)(void *v, unsigned int windowId, int state); -typedef void (*capi_vehicle_set_roof_state)(void *v, unsigned int state); -typedef void (*capi_vehicle_set_lights_multiplier)(void *v, float multiplier); -typedef void (*capi_vehicle_set_engine_health)(void *v, unsigned long health); -typedef void (*capi_vehicle_set_petrol_tank_health)(void *v, unsigned long health); -typedef void (*capi_vehicle_set_wheel_burst)(void *v, unsigned int wheelId, int state); -typedef void (*capi_vehicle_set_wheel_has_tire)(void *v, unsigned int wheelId, int state); -typedef void (*capi_vehicle_set_wheel_detached)(void *v, unsigned int wheelId, int state); -typedef void (*capi_vehicle_set_wheel_on_fire)(void *v, unsigned int wheelId, int state); -typedef void (*capi_vehicle_set_wheel_health)(void *v, unsigned int wheelId, float health); -typedef void (*capi_vehicle_set_wheel_fixed)(void *v, unsigned int wheelId); -typedef void (*capi_vehicle_set_body_health)(void *v, unsigned long health); -typedef void (*capi_vehicle_set_body_additional_health)(void *v, unsigned long health); -typedef void (*capi_vehicle_set_part_damage_level)(void *v, unsigned int partId, unsigned int damage); -typedef void (*capi_vehicle_set_part_bullet_holes)(void *v, unsigned int partId, unsigned int shootsCount); -typedef void (*capi_vehicle_set_light_damaged)(void *v, unsigned int lightId, int isDamaged); -typedef void (*capi_vehicle_set_window_damaged)(void *v, unsigned int windowId, int isDamaged); -typedef void (*capi_vehicle_set_special_light_damaged)(void *v, unsigned int specialLightId, int isDamaged); -typedef void (*capi_vehicle_set_armored_window_health)(void *v, unsigned int windowId, float health); -typedef void (*capi_vehicle_set_armored_window_shoot_count)(void *v, unsigned int windowId, unsigned int count); -typedef void (*capi_vehicle_set_bumper_damage_level)(void *v, unsigned int bumperId, unsigned int damageLevel); -typedef void (*capi_vehicle_set_manual_engine_control)(void *v, int state); -typedef void (*capi_vehicle_load_damage_data_from_base64)(void *v, const char *base64); -typedef void (*capi_vehicle_load_script_data_from_base64)(void *v, const char *base64); -typedef void (*capi_vehicle_load_game_state_from_base64)(void *v, const char *base64); -typedef void (*capi_vehicle_load_health_data_from_base64)(void *v, const char *base64); -typedef Entity (*capi_vehicle_get_attached)(void *v); -typedef Entity (*capi_vehicle_get_attached_to)(void *v); -typedef void (*capi_vehicle_destroy)(void *v); -typedef int (*capi_vehicle_is_valid)(const char *resourceName, void *p); -typedef int (*capi_vehicle_get_streamed)(void *v); -typedef void (*capi_vehicle_set_streamed)(void *v, int toggle); -typedef int (*capi_vehicle_is_frozen)(void *v); -typedef void (*capi_vehicle_set_frozen)(void *v, int state); -typedef int (*capi_vehicle_has_collision)(void *v); -typedef void (*capi_vehicle_set_collision)(void *v, int state); -typedef int (*capi_vehicle_is_drift_mode)(void *v); -typedef void (*capi_vehicle_set_drift_mode)(void *v, int state); -typedef int (*capi_vehicle_is_train_mission_train)(void *v); -typedef void (*capi_vehicle_set_train_mission_train)(void *v, int value); -typedef char (*capi_vehicle_get_train_track_id)(void *v); -typedef void (*capi_vehicle_set_train_track_id)(void *v, char trackId); -typedef Entity (*capi_vehicle_get_train_engine_id)(void *v); -typedef void (*capi_vehicle_set_train_engine_id)(void *v, void *e); -typedef char (*capi_vehicle_get_train_config_index)(void *v); -typedef void (*capi_vehicle_set_train_config_index)(void *v, char trainConfigIndex); -typedef float (*capi_vehicle_get_train_distance_from_engine)(void *v); -typedef void (*capi_vehicle_set_train_distance_from_engine)(void *v, float distanceFromEngine); -typedef int (*capi_vehicle_is_train_engine)(void *v); -typedef void (*capi_vehicle_set_train_is_engine)(void *v, int isEngine); -typedef int (*capi_vehicle_is_train_caboose)(void *v); -typedef void (*capi_vehicle_set_train_is_caboose)(void *v, int isCaboose); -typedef int (*capi_vehicle_get_train_direction)(void *v); -typedef void (*capi_vehicle_set_train_direction)(void *v, int direction); -typedef int (*capi_vehicle_has_train_passenger_carriages)(void *v); -typedef void (*capi_vehicle_set_train_has_passenger_carriages)(void *v, int hasPassengerCarriages); -typedef int (*capi_vehicle_get_train_render_derailed)(void *v); -typedef void (*capi_vehicle_set_train_render_derailed)(void *v, int renderDerailed); -typedef int (*capi_vehicle_get_train_force_doors_open)(void *v); -typedef void (*capi_vehicle_set_train_force_doors_open)(void *v, int forceDoorsOpen); -typedef float (*capi_vehicle_get_train_cruise_speed)(void *v); -typedef void (*capi_vehicle_set_train_cruise_speed)(void *v, float cruiseSpeed); -typedef char (*capi_vehicle_get_train_carriage_config_index)(void *v); -typedef void (*capi_vehicle_set_train_carriage_config_index)(void *v, char carriageConfigIndex); -typedef Entity (*capi_vehicle_get_train_linked_to_backward_id)(void *v); -typedef void (*capi_vehicle_set_train_linked_to_backward_id)(void *v, void *e); -typedef Entity (*capi_vehicle_get_train_linked_to_forward_id)(void *v); -typedef void (*capi_vehicle_set_train_linked_to_forward_id)(void *v, void *e); -typedef void (*capi_vehicle_set_train_unk1)(void *v, int unk1); -typedef int (*capi_vehicle_get_train_unk1)(void *v); -typedef void (*capi_vehicle_set_train_unk2)(void *v, int unk2); -typedef int (*capi_vehicle_get_train_unk2)(void *v); -typedef void (*capi_vehicle_set_train_unk3)(void *v, int unk3); -typedef int (*capi_vehicle_get_train_unk3)(void *v); -typedef int (*capi_vehicle_is_boat_anchor_active)(void *v); -typedef void (*capi_vehicle_set_boat_anchor_active)(void *v, int state); -typedef int (*capi_vehicle_set_search_light)(void *v, int state, Entity e); -typedef unsigned char (*capi_vehicle_get_light_state)(void *v); -typedef void (*capi_vehicle_set_light_state)(void *v, unsigned char state); -typedef unsigned char (*capi_vehicle_has_timed_explosion)(void *v); -typedef Entity (*capi_vehicle_get_timed_explosion_culprit)(void *v); -typedef unsigned int (*capi_vehicle_get_timed_explosion_time)(void *v); -typedef void (*capi_vehicle_set_timed_explosion)(void *v, unsigned char state, void *culprit, unsigned int time); -typedef unsigned char (*capi_vehicle_is_towing_disabled)(void *v); -typedef void (*capi_vehicle_set_towing_disabled)(void *v, unsigned char state); -typedef float (*capi_vehicle_get_rocket_refuel_speed)(void *v); -typedef void (*capi_vehicle_set_rocket_refuel_speed)(void *v, float speed); -typedef unsigned int (*capi_vehicle_get_counter_measure_count)(void *v); -typedef void (*capi_vehicle_set_counter_measure_count)(void *v, unsigned int count); -typedef float (*capi_vehicle_get_script_max_speed)(void *v); -typedef void (*capi_vehicle_set_script_max_speed)(void *v, float speed); -typedef int (*capi_vehicle_get_weapon_capacity)(void *v, unsigned char index); -typedef void (*capi_vehicle_set_weapon_capacity)(void *v, unsigned char index, int capacity); -typedef unsigned char (*capi_vehicle_get_hybrid_extra_active)(void *v); -typedef void (*capi_vehicle_set_hybrid_extra_active)(void *v, unsigned char state); -typedef unsigned char (*capi_vehicle_get_hybrid_extra_state)(void *v); -typedef void (*capi_vehicle_set_hybrid_extra_state)(void *v, unsigned char state); - - -// /home/timo/dev/os/altv/altv-go/runtime/src/capi/Vehicle.h Module.h -int vehicle_has_meta_data(void *base, const char *key); -Array vehicle_get_meta_data(void *base, const char *key); -void vehicle_set_meta_data(void *base, const char *key, Array data); -void vehicle_delete_meta_data(void *base, const char *key); -int vehicle_has_synced_meta_data(void *base, const char *key); -Array vehicle_get_synced_meta_data(void *base, const char *key); -void vehicle_set_synced_meta_data(void *base, const char *key, Array data); -void vehicle_delete_synced_meta_data(void *base, const char *key); -int vehicle_has_stream_synced_meta_data(void *base, const char *key); -Array vehicle_get_stream_synced_meta_data(void *base, const char *key); -void vehicle_set_stream_synced_meta_data(void *base, const char *key, Array data); -void vehicle_delete_stream_synced_meta_data(void *base, const char *key); +int vehicle_has_meta_data(void *base, const char *key); + +Array vehicle_get_meta_data(void *base, const char *key); + +void vehicle_set_meta_data(void *base, const char *key, Array data); + +void vehicle_delete_meta_data(void *base, const char *key); + +int vehicle_has_synced_meta_data(void *base, const char *key); + +Array vehicle_get_synced_meta_data(void *base, const char *key); + +void vehicle_set_synced_meta_data(void *base, const char *key, Array data); + +void vehicle_delete_synced_meta_data(void *base, const char *key); + +int vehicle_has_stream_synced_meta_data(void *base, const char *key); + +Array vehicle_get_stream_synced_meta_data(void *base, const char *key); + +void vehicle_set_stream_synced_meta_data(void *base, const char *key, Array data); + +void vehicle_delete_stream_synced_meta_data(void *base, const char *key); + Position vehicle_get_position(void *v); -void vehicle_set_position(void *v, float x, float y, float z); + +void vehicle_set_position(void *v, float x, float y, float z); + Rotation vehicle_get_rotation(void *v); -void vehicle_set_rotation(void *v, float roll, float pitch, float yaw); + +void vehicle_set_rotation(void *v, float roll, float pitch, float yaw); + long vehicle_get_dimension(void *v); -void vehicle_set_dimension(void *v, long dimension); -unsigned long vehicle_get_i_d(void *v); + +void vehicle_set_dimension(void *v, long dimension); + +unsigned long vehicle_get_id(void *v); + unsigned long vehicle_get_model(void *v); + void vehicle_detach(void *v); -void vehicle_attach_to_entity(void *v, Entity e, int otherBoneIndex, int myBoneIndex, Position position, Rotation rotation, - int collision, int noFixedRotation); -void vehicle_set_visible(void *v, int toggle); + +void + vehicle_attach_to_entity(void *v, Entity e, int otherBoneIndex, int myBoneIndex, Position position, Rotation rotation, + int collision, int noFixedRotation); + +void vehicle_set_visible(void *v, int toggle); + int vehicle_get_visible(void *v); + Entity vehicle_get_network_owner(void *v); -void vehicle_set_network_owner(void *v, void *owner, int disableMigration); + +void vehicle_set_network_owner(void *v, void *owner, int disableMigration); + Entity vehicle_get_driver(void *v); + int vehicle_is_destroyed(void *v); -unsigned long vehicle_get_mod(void *v, unsigned int category); -unsigned long vehicle_get_mods_count(void *v, unsigned int category); + +unsigned long vehicle_get_mod(void *v, unsigned int category); + +unsigned long vehicle_get_mods_count(void *v, unsigned int category); + unsigned long vehicle_get_mod_kits_count(void *v); + unsigned long vehicle_get_mod_kit(void *v); -int vehicle_is_primary_color_r_g_b(void *v); + +int vehicle_is_primary_color_rgb(void *v); + unsigned long vehicle_get_primary_color(void *v); -RGBA vehicle_get_primary_color_r_g_b(void *v); -int vehicle_is_secondary_color_r_g_b(void *v); + +RGBA vehicle_get_primary_color_rgb(void *v); + +int vehicle_is_secondary_color_rgb(void *v); + unsigned long vehicle_get_secondary_color(void *v); -RGBA vehicle_get_secondary_color_r_g_b(void *v); + +RGBA vehicle_get_secondary_color_rgb(void *v); + unsigned long vehicle_get_pearl_color(void *v); + unsigned long vehicle_get_wheel_color(void *v); + unsigned long vehicle_get_interior_color(void *v); + unsigned long vehicle_get_dashboard_color(void *v); + int vehicle_is_tire_smoke_color_custom(void *v); + RGBA vehicle_get_tire_smoke_color(void *v); + unsigned long vehicle_get_wheel_type(void *v); + unsigned long vehicle_get_wheel_variation(void *v); + unsigned long vehicle_get_rear_wheel_variation(void *v); + int vehicle_get_custom_tires(void *v); + unsigned long vehicle_get_special_darkness(void *v); + unsigned long vehicle_get_numberplate_index(void *v); + const char * vehicle_get_numberplate_text(void *v); + unsigned long vehicle_get_window_tint(void *v); + unsigned long vehicle_get_dirt_level(void *v); -int vehicle_is_extra_on(void *v, unsigned int extraID); + +int vehicle_is_extra_on(void *v, unsigned int extraID); + int vehicle_is_neon_active(void *v); + VehicleNeonState vehicle_get_neon_active(void *v); + RGBA vehicle_get_neon_color(void *v); + unsigned long vehicle_get_livery(void *v); + unsigned long vehicle_get_roof_livery(void *v); + const char * vehicle_get_appearance_data_base64(void *v); + int vehicle_is_engine_on(void *v); + int vehicle_is_handbrake_active(void *v); + unsigned long vehicle_get_headlight_color(void *v); + unsigned long vehicle_get_radio_station_index(void *v); + int vehicle_is_siren_active(void *v); + unsigned long vehicle_get_lock_state(void *v); -unsigned long vehicle_get_door_state(void *v, unsigned int doorId); -int vehicle_is_window_opened(void *v, unsigned int windowId); + +unsigned long vehicle_get_door_state(void *v, unsigned int doorId); + +int vehicle_is_window_opened(void *v, unsigned int windowId); + int vehicle_is_daylight_on(void *v); + int vehicle_is_nightlight_on(void *v); + unsigned long vehicle_get_roof_state(void *v); + int vehicle_is_flamethrower_active(void *v); + float vehicle_get_lights_multiplier(void *v); + const char * vehicle_get_game_state_base64(void *v); + long vehicle_get_engine_health(void *v); + long vehicle_get_petrol_tank_health(void *v); + unsigned long vehicle_get_wheels_count(void *v); -int vehicle_is_wheel_burst(void *v, unsigned int wheelId); -int vehicle_does_wheel_has_tire(void *v, unsigned int wheelId); -int vehicle_is_wheel_detached(void *v, unsigned int wheelId); -int vehicle_is_wheel_on_fire(void *v, unsigned int wheelId); -float vehicle_get_wheel_health(void *v, unsigned int wheelId); + +int vehicle_is_wheel_burst(void *v, unsigned int wheelId); + +int vehicle_does_wheel_has_tire(void *v, unsigned int wheelId); + +int vehicle_is_wheel_detached(void *v, unsigned int wheelId); + +int vehicle_is_wheel_on_fire(void *v, unsigned int wheelId); + +float vehicle_get_wheel_health(void *v, unsigned int wheelId); + unsigned long vehicle_get_repairs_count(void *v); + unsigned long vehicle_get_body_health(void *v); + unsigned long vehicle_get_body_additional_health(void *v); + const char * vehicle_get_health_data_base64(void *v); -unsigned long vehicle_get_part_damage_level(void *v, unsigned int partId); -unsigned long vehicle_get_part_bullet_holes(void *v, unsigned int partId); -int vehicle_is_light_damaged(void *v, unsigned int lightId); -int vehicle_is_window_damaged(void *v, unsigned int windowId); -int vehicle_is_special_light_damaged(void *v, unsigned int specialLightId); + +unsigned long vehicle_get_part_damage_level(void *v, unsigned int partId); + +unsigned long vehicle_get_part_bullet_holes(void *v, unsigned int partId); + +int vehicle_is_light_damaged(void *v, unsigned int lightId); + +int vehicle_is_window_damaged(void *v, unsigned int windowId); + +int vehicle_is_special_light_damaged(void *v, unsigned int specialLightId); + int vehicle_has_armored_windows(void *v); -float vehicle_get_armored_window_health(void *v, unsigned int windowId); -unsigned long vehicle_get_armored_window_shoot_count(void *v, unsigned int windowId); -unsigned long vehicle_get_bumper_damage_level(void *v, unsigned int bumperId); + +float vehicle_get_armored_window_health(void *v, unsigned int windowId); + +unsigned long vehicle_get_armored_window_shoot_count(void *v, unsigned int windowId); + +unsigned long vehicle_get_bumper_damage_level(void *v, unsigned int bumperId); + const char * vehicle_get_damage_data_base64(void *v); + int vehicle_is_manual_engine_control(void *v); + const char * vehicle_get_script_data_base64(void *v); -void vehicle_toggle_extra(void *v, unsigned int extraID, int state); + +void vehicle_toggle_extra(void *v, unsigned int extraID, int state); + void vehicle_set_fixed(void *v); -int vehicle_set_mod(void *v, unsigned int category, unsigned int id); -int vehicle_set_mod_kit(void *v, unsigned int id); -void vehicle_set_primary_color(void *v, unsigned int color); -void vehicle_set_primary_color_r_g_b(void *v, unsigned int r, unsigned int g, unsigned int b, unsigned int a); -void vehicle_set_secondary_color(void *v, unsigned int color); -void vehicle_set_secondary_color_r_g_b(void *v, unsigned int r, unsigned int g, unsigned int b, unsigned int a); -void vehicle_set_pearl_color(void *v, unsigned int color); -void vehicle_set_wheel_color(void *v, unsigned int color); -void vehicle_set_interior_color(void *v, unsigned int color); -void vehicle_set_dashboard_color(void *v, unsigned int color); -void vehicle_set_tire_smoke_color(void *v, unsigned int r, unsigned int g, unsigned int b, unsigned int a); -void vehicle_set_wheels(void *v, unsigned int type, unsigned int variation); -void vehicle_set_rear_wheels(void *v, unsigned int variation); -void vehicle_set_custom_tires(void *v, int state); -void vehicle_set_special_darkness(void *v, unsigned int value); -void vehicle_set_numberplate_index(void *v, unsigned int index); -void vehicle_set_numberplate_text(void *v, const char *text); -void vehicle_set_window_tint(void *v, unsigned int tint); -void vehicle_set_dirt_level(void *v, unsigned int level); -void vehicle_set_neon_active(void *v, int left, int right, int front, int back); -void vehicle_set_neon_color(void *v, unsigned int r, unsigned int g, unsigned int b, unsigned int a); -void vehicle_set_livery(void *v, unsigned int livery); -void vehicle_set_roof_livery(void *v, unsigned int roofLivery); -void vehicle_load_appearance_data_from_base64(void *v, const char *base64); -void vehicle_set_engine_on(void *v, int state); -void vehicle_set_headlight_color(void *v, unsigned int color); -void vehicle_set_radio_station_index(void *v, unsigned int stationIndex); -void vehicle_set_siren_active(void *v, int state); -void vehicle_set_lock_state(void *v, unsigned int state); -void vehicle_set_door_state(void *v, unsigned int doorId, unsigned int state); -void vehicle_set_window_opened(void *v, unsigned int windowId, int state); -void vehicle_set_roof_state(void *v, unsigned int state); -void vehicle_set_lights_multiplier(void *v, float multiplier); -void vehicle_set_engine_health(void *v, unsigned long health); -void vehicle_set_petrol_tank_health(void *v, unsigned long health); -void vehicle_set_wheel_burst(void *v, unsigned int wheelId, int state); -void vehicle_set_wheel_has_tire(void *v, unsigned int wheelId, int state); -void vehicle_set_wheel_detached(void *v, unsigned int wheelId, int state); -void vehicle_set_wheel_on_fire(void *v, unsigned int wheelId, int state); -void vehicle_set_wheel_health(void *v, unsigned int wheelId, float health); -void vehicle_set_wheel_fixed(void *v, unsigned int wheelId); -void vehicle_set_body_health(void *v, unsigned long health); -void vehicle_set_body_additional_health(void *v, unsigned long health); -void vehicle_set_part_damage_level(void *v, unsigned int partId, unsigned int damage); -void vehicle_set_part_bullet_holes(void *v, unsigned int partId, unsigned int shootsCount); -void vehicle_set_light_damaged(void *v, unsigned int lightId, int isDamaged); -void vehicle_set_window_damaged(void *v, unsigned int windowId, int isDamaged); -void vehicle_set_special_light_damaged(void *v, unsigned int specialLightId, int isDamaged); -void vehicle_set_armored_window_health(void *v, unsigned int windowId, float health); -void vehicle_set_armored_window_shoot_count(void *v, unsigned int windowId, unsigned int count); -void vehicle_set_bumper_damage_level(void *v, unsigned int bumperId, unsigned int damageLevel); -void vehicle_set_manual_engine_control(void *v, int state); -void vehicle_load_damage_data_from_base64(void *v, const char *base64); -void vehicle_load_script_data_from_base64(void *v, const char *base64); -void vehicle_load_game_state_from_base64(void *v, const char *base64); -void vehicle_load_health_data_from_base64(void *v, const char *base64); + +int vehicle_set_mod(void *v, unsigned int category, unsigned int id); + +int vehicle_set_mod_kit(void *v, unsigned int id); + +void vehicle_set_primary_color(void *v, unsigned int color); + +void vehicle_set_primary_color_rgb(void *v, unsigned int r, unsigned int g, unsigned int b, unsigned int a); + +void vehicle_set_secondary_color(void *v, unsigned int color); + +void vehicle_set_secondary_color_rgb(void *v, unsigned int r, unsigned int g, unsigned int b, unsigned int a); + +void vehicle_set_pearl_color(void *v, unsigned int color); + +void vehicle_set_wheel_color(void *v, unsigned int color); + +void vehicle_set_interior_color(void *v, unsigned int color); + +void vehicle_set_dashboard_color(void *v, unsigned int color); + +void vehicle_set_tire_smoke_color(void *v, unsigned int r, unsigned int g, unsigned int b, unsigned int a); + +void vehicle_set_wheels(void *v, unsigned int type, unsigned int variation); + +void vehicle_set_rear_wheels(void *v, unsigned int variation); + +void vehicle_set_custom_tires(void *v, int state); + +void vehicle_set_special_darkness(void *v, unsigned int value); + +void vehicle_set_numberplate_index(void *v, unsigned int index); + +void vehicle_set_numberplate_text(void *v, const char *text); + +void vehicle_set_window_tint(void *v, unsigned int tint); + +void vehicle_set_dirt_level(void *v, unsigned int level); + +void vehicle_set_neon_active(void *v, int left, int right, int front, int back); + +void vehicle_set_neon_color(void *v, unsigned int r, unsigned int g, unsigned int b, unsigned int a); + +void vehicle_set_livery(void *v, unsigned int livery); + +void vehicle_set_roof_livery(void *v, unsigned int roofLivery); + +void vehicle_load_appearance_data_from_base64(void *v, const char *base64); + +void vehicle_set_engine_on(void *v, int state); + +void vehicle_set_headlight_color(void *v, unsigned int color); + +void vehicle_set_radio_station_index(void *v, unsigned int stationIndex); + +void vehicle_set_siren_active(void *v, int state); + +void vehicle_set_lock_state(void *v, unsigned int state); + +void vehicle_set_door_state(void *v, unsigned int doorId, unsigned int state); + +void vehicle_set_window_opened(void *v, unsigned int windowId, int state); + +void vehicle_set_roof_state(void *v, unsigned int state); + +void vehicle_set_lights_multiplier(void *v, float multiplier); + +void vehicle_set_engine_health(void *v, unsigned long health); + +void vehicle_set_petrol_tank_health(void *v, unsigned long health); + +void vehicle_set_wheel_burst(void *v, unsigned int wheelId, int state); + +void vehicle_set_wheel_has_tire(void *v, unsigned int wheelId, int state); + +void vehicle_set_wheel_detached(void *v, unsigned int wheelId, int state); + +void vehicle_set_wheel_on_fire(void *v, unsigned int wheelId, int state); + +void vehicle_set_wheel_health(void *v, unsigned int wheelId, float health); + +void vehicle_set_wheel_fixed(void *v, unsigned int wheelId); + +void vehicle_set_body_health(void *v, unsigned long health); + +void vehicle_set_body_additional_health(void *v, unsigned long health); + +void vehicle_set_part_damage_level(void *v, unsigned int partId, unsigned int damage); + +void vehicle_set_part_bullet_holes(void *v, unsigned int partId, unsigned int shootsCount); + +void vehicle_set_light_damaged(void *v, unsigned int lightId, int isDamaged); + +void vehicle_set_window_damaged(void *v, unsigned int windowId, int isDamaged); + +void vehicle_set_special_light_damaged(void *v, unsigned int specialLightId, int isDamaged); + +void vehicle_set_armored_window_health(void *v, unsigned int windowId, float health); + +void vehicle_set_armored_window_shoot_count(void *v, unsigned int windowId, unsigned int count); + +void vehicle_set_bumper_damage_level(void *v, unsigned int bumperId, unsigned int damageLevel); + +void vehicle_set_manual_engine_control(void *v, int state); + +void vehicle_load_damage_data_from_base64(void *v, const char *base64); + +void vehicle_load_script_data_from_base64(void *v, const char *base64); + +void vehicle_load_game_state_from_base64(void *v, const char *base64); + +void vehicle_load_health_data_from_base64(void *v, const char *base64); + Entity vehicle_get_attached(void *v); + Entity vehicle_get_attached_to(void *v); + void vehicle_destroy(void *v); -int vehicle_is_valid(const char *resourceName, void *p); + +int vehicle_is_valid(const char *resourceName, void *p); + int vehicle_get_streamed(void *v); -void vehicle_set_streamed(void *v, int toggle); + +void vehicle_set_streamed(void *v, int toggle); + int vehicle_is_frozen(void *v); -void vehicle_set_frozen(void *v, int state); + +void vehicle_set_frozen(void *v, int state); + int vehicle_has_collision(void *v); -void vehicle_set_collision(void *v, int state); + +void vehicle_set_collision(void *v, int state); + int vehicle_is_drift_mode(void *v); -void vehicle_set_drift_mode(void *v, int state); + +void vehicle_set_drift_mode(void *v, int state); + int vehicle_is_train_mission_train(void *v); -void vehicle_set_train_mission_train(void *v, int value); + +void vehicle_set_train_mission_train(void *v, int value); + char vehicle_get_train_track_id(void *v); -void vehicle_set_train_track_id(void *v, char trackId); + +void vehicle_set_train_track_id(void *v, char trackId); + Entity vehicle_get_train_engine_id(void *v); -void vehicle_set_train_engine_id(void *v, void *e); + +void vehicle_set_train_engine_id(void *v, void *e); + char vehicle_get_train_config_index(void *v); -void vehicle_set_train_config_index(void *v, char trainConfigIndex); + +void vehicle_set_train_config_index(void *v, char trainConfigIndex); + float vehicle_get_train_distance_from_engine(void *v); -void vehicle_set_train_distance_from_engine(void *v, float distanceFromEngine); + +void vehicle_set_train_distance_from_engine(void *v, float distanceFromEngine); + int vehicle_is_train_engine(void *v); -void vehicle_set_train_is_engine(void *v, int isEngine); + +void vehicle_set_train_is_engine(void *v, int isEngine); + int vehicle_is_train_caboose(void *v); -void vehicle_set_train_is_caboose(void *v, int isCaboose); + +void vehicle_set_train_is_caboose(void *v, int isCaboose); + int vehicle_get_train_direction(void *v); -void vehicle_set_train_direction(void *v, int direction); + +void vehicle_set_train_direction(void *v, int direction); + int vehicle_has_train_passenger_carriages(void *v); -void vehicle_set_train_has_passenger_carriages(void *v, int hasPassengerCarriages); + +void vehicle_set_train_has_passenger_carriages(void *v, int hasPassengerCarriages); + int vehicle_get_train_render_derailed(void *v); -void vehicle_set_train_render_derailed(void *v, int renderDerailed); + +void vehicle_set_train_render_derailed(void *v, int renderDerailed); + int vehicle_get_train_force_doors_open(void *v); -void vehicle_set_train_force_doors_open(void *v, int forceDoorsOpen); + +void vehicle_set_train_force_doors_open(void *v, int forceDoorsOpen); + float vehicle_get_train_cruise_speed(void *v); -void vehicle_set_train_cruise_speed(void *v, float cruiseSpeed); + +void vehicle_set_train_cruise_speed(void *v, float cruiseSpeed); + char vehicle_get_train_carriage_config_index(void *v); -void vehicle_set_train_carriage_config_index(void *v, char carriageConfigIndex); + +void vehicle_set_train_carriage_config_index(void *v, char carriageConfigIndex); + Entity vehicle_get_train_linked_to_backward_id(void *v); -void vehicle_set_train_linked_to_backward_id(void *v, void *e); + +void vehicle_set_train_linked_to_backward_id(void *v, void *e); + Entity vehicle_get_train_linked_to_forward_id(void *v); -void vehicle_set_train_linked_to_forward_id(void *v, void *e); -void vehicle_set_train_unk1(void *v, int unk1); + +void vehicle_set_train_linked_to_forward_id(void *v, void *e); + +void vehicle_set_train_unk1(void *v, int unk1); + int vehicle_get_train_unk1(void *v); -void vehicle_set_train_unk2(void *v, int unk2); + +void vehicle_set_train_unk2(void *v, int unk2); + int vehicle_get_train_unk2(void *v); -void vehicle_set_train_unk3(void *v, int unk3); + +void vehicle_set_train_unk3(void *v, int unk3); + int vehicle_get_train_unk3(void *v); + int vehicle_is_boat_anchor_active(void *v); -void vehicle_set_boat_anchor_active(void *v, int state); -int vehicle_set_search_light(void *v, int state, Entity e); + +void vehicle_set_boat_anchor_active(void *v, int state); + +int vehicle_set_search_light(void *v, int state, Entity e); + unsigned char vehicle_get_light_state(void *v); -void vehicle_set_light_state(void *v, unsigned char state); + +void vehicle_set_light_state(void *v, unsigned char state); + unsigned char vehicle_has_timed_explosion(void *v); + Entity vehicle_get_timed_explosion_culprit(void *v); + unsigned int vehicle_get_timed_explosion_time(void *v); -void vehicle_set_timed_explosion(void *v, unsigned char state, void *culprit, unsigned int time); + +void vehicle_set_timed_explosion(void *v, unsigned char state, void *culprit, unsigned int time); + unsigned char vehicle_is_towing_disabled(void *v); -void vehicle_set_towing_disabled(void *v, unsigned char state); + +void vehicle_set_towing_disabled(void *v, unsigned char state); + float vehicle_get_rocket_refuel_speed(void *v); -void vehicle_set_rocket_refuel_speed(void *v, float speed); + +void vehicle_set_rocket_refuel_speed(void *v, float speed); + unsigned int vehicle_get_counter_measure_count(void *v); -void vehicle_set_counter_measure_count(void *v, unsigned int count); + +void vehicle_set_counter_measure_count(void *v, unsigned int count); + float vehicle_get_script_max_speed(void *v); -void vehicle_set_script_max_speed(void *v, float speed); -int vehicle_get_weapon_capacity(void *v, unsigned char index); -void vehicle_set_weapon_capacity(void *v, unsigned char index, int capacity); + +void vehicle_set_script_max_speed(void *v, float speed); + +int vehicle_get_weapon_capacity(void *v, unsigned char index); + +void vehicle_set_weapon_capacity(void *v, unsigned char index, int capacity); + unsigned char vehicle_get_hybrid_extra_active(void *v); -void vehicle_set_hybrid_extra_active(void *v, unsigned char state); + +void vehicle_set_hybrid_extra_active(void *v, unsigned char state); + unsigned char vehicle_get_hybrid_extra_state(void *v); -void vehicle_set_hybrid_extra_state(void *v, unsigned char state); -// /home/timo/dev/os/altv/altv-go/runtime/src/capi/VoiceChannel.h Module.h -typedef int (*capi_voice_channel_is_valid)(const char* resourceName, void *p); -typedef int (*capi_voice_channel_get_type)(void *c); -typedef int (*capi_voice_channel_has_meta_data)(void* base, const char *key); -typedef Array (*capi_voice_channel_get_meta_data)(void* base, const char *key); -typedef void (*capi_voice_channel_set_meta_data)(void *base, const char *key, Array data); -typedef void (*capi_voice_channel_delete_meta_data)(void *base, const char *key); -typedef void (*capi_voice_channel_destroy)(void *b); -typedef int (*capi_voice_channel_is_spatial)(void *v); -typedef float (*capi_voice_channel_get_max_distance)(void *v); -typedef int (*capi_voice_channel_has_player)(void *v, void *p); -typedef void (*capi_voice_channel_add_player)(void *v, void *p); -typedef void (*capi_voice_channel_remove_player)(void *v, void *p); -typedef int (*capi_voice_channel_is_player_muted)(void *v, void *p); -typedef void (*capi_voice_channel_mute_player)(void *v, void *p); -typedef void (*capi_voice_channel_unmute_player)(void *v, void *p); -typedef unsigned long long (*capi_voice_channel_get_player_count)(void *v); -typedef Array (*capi_voice_channel_get_players)(void *v); +void vehicle_set_hybrid_extra_state(void *v, unsigned char state); +int voice_channel_is_valid(const char* resourceName, void *p); -// /home/timo/dev/os/altv/altv-go/runtime/src/capi/VoiceChannel.h Module.h -int voice_channel_is_valid(const char* resourceName, void *p); int voice_channel_get_type(void *c); -int voice_channel_has_meta_data(void* base, const char *key); -Array voice_channel_get_meta_data(void* base, const char *key); -void voice_channel_set_meta_data(void *base, const char *key, Array data); -void voice_channel_delete_meta_data(void *base, const char *key); + +int voice_channel_has_meta_data(void* base, const char *key); + +Array voice_channel_get_meta_data(void* base, const char *key); + +void voice_channel_set_meta_data(void *base, const char *key, Array data); + +void voice_channel_delete_meta_data(void *base, const char *key); + void voice_channel_destroy(void *b); + int voice_channel_is_spatial(void *v); + float voice_channel_get_max_distance(void *v); -int voice_channel_has_player(void *v, void *p); -void voice_channel_add_player(void *v, void *p); -void voice_channel_remove_player(void *v, void *p); -int voice_channel_is_player_muted(void *v, void *p); -void voice_channel_mute_player(void *v, void *p); -void voice_channel_unmute_player(void *v, void *p); + +int voice_channel_has_player(void *v, void *p); + +void voice_channel_add_player(void *v, void *p); + +void voice_channel_remove_player(void *v, void *p); + +int voice_channel_is_player_muted(void *v, void *p); + +void voice_channel_mute_player(void *v, void *p); + +void voice_channel_unmute_player(void *v, void *p); + unsigned long long voice_channel_get_player_count(void *v); + Array voice_channel_get_players(void *v); +int checkpoint_get_type(void *c); + +int checkpoint_has_meta_data(void* base, const char *key); + +Array checkpoint_get_meta_data(void* base, const char *key); + +void checkpoint_set_meta_data(void *base, const char *key, Array data); + +void checkpoint_delete_meta_data(void *base, const char *key); + +void checkpoint_destroy(void *b); + +int checkpoint_is_valid(const char* resourceName, void *p); + +Position checkpoint_get_position(void *p); + +void checkpoint_set_position(void* p, float x, float y, float z); + +long checkpoint_get_dimension(void* p); + +void checkpoint_set_dimension(void* p, long dimension); + +int checkpoint_get_col_shape_type(void *c); + +int checkpoint_is_entity_in(void *c, Entity e); + +int checkpoint_is_point_in(void *c, float x, float y, float z); + +void checkpoint_set_players_only(void *c, int state); + +int checkpoint_is_players_only(void *c); + +unsigned char checkpoint_is_entity_id_in(void *c, unsigned short id); + +unsigned char checkpoint_get_checkpoint_type(void *c); + +float checkpoint_get_height(void *c); + +float checkpoint_get_radius(void *c); + +RGBA checkpoint_get_color(void *c); + +Position checkpoint_get_next_position(void *c); + +void checkpoint_set_checkpoint_type(void *c, unsigned char type); + +void checkpoint_set_height(void *c, float height); + +void checkpoint_set_radius(void *c, float radius); + +void checkpoint_set_color(void *c, unsigned char r, unsigned char g, unsigned char b, unsigned char a); + +void checkpoint_set_next_position(void *c, float x, float y, float z); #endif \ No newline at end of file diff --git a/internal/c-api/lib/linux/libcapi.a b/internal/c-api/lib/linux/libcapi.a index 44aa40589c6c253b46e74ff7873f636e48382b6b..80ed347b38f6df3c34fed1395a4c14de8309bcef 100644 GIT binary patch literal 249042 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 PcWvpC_Gt5O_WA!G3?qN% literal 249114 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

C1vlbEi&!EN|V|u%8%sjD&j)B6;4ws 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 diff --git a/mvalue/func.go b/mvalue/func.go index 95adb56..de39491 100644 --- a/mvalue/func.go +++ b/mvalue/func.go @@ -4,6 +4,7 @@ import ( "unsafe" "github.com/goccy/go-json" + "github.com/timo972/altv-go/resource" ) type FuncCtx struct{} @@ -28,6 +29,11 @@ type importFuncData struct { var exported = make([]*exportFuncData, 0) func (f ExportFunc) MarshalJSON() ([]byte, error) { + resourceName = "" + if resource.Current != nil { + resourceName = resource.Current.Name() + } + data := &exportFuncData{ SpecialType: SpecialType{Type: TypeFunction}, ID: len(exported), @@ -52,8 +58,3 @@ func (f *ImportFunc) UnmarshalJSON(raw []byte) error { func CallFunc(f *ImportFunc, args ...any) any { return nil } - -// SetResourceName sets the resource name for the exported functions. Do not use this by yourself or you might break function exporting! -func SetResourceName(name string) { - resourceName = name -} diff --git a/perm.go b/perm.go deleted file mode 100644 index eb9a1e4..0000000 --- a/perm.go +++ /dev/null @@ -1,28 +0,0 @@ -package altv - -/* -#include -#include "capi.h" -*/ -import "C" -import ( - "unsafe" - - "github.com/timo972/altv-go/internal/cutil" -) - -type Permission = uint8 - -const ( - PermNone Permission = iota - PermScreenCapture - PermWebRTC - PermClipboardAccess - PermAll -) - -func newPermissionArray(arr C.struct_array) []Permission { - return cutil.NewArrayFunc[C.uchar, Permission](unsafe.Pointer(arr.array), int(arr.size), func(item C.uchar) Permission { - return Permission(item) - }) -} diff --git a/perm/perm.go b/perm/perm.go new file mode 100644 index 0000000..880ca65 --- /dev/null +++ b/perm/perm.go @@ -0,0 +1,19 @@ +package perm + +// #cgo CFLAGS: -I../internal/c-api/lib +// #cgo linux LDFLAGS: -L../internal/c-api/lib/linux -lcapi -ldl -g +// #cgo windows LDFLAGS: -L../internal/c-api/lib/win32 -lcapi -ldl -g +// #cgo CXXFLAGS: -std=c++14 +// #include +// #include "capi.h" +import "C" + +type Permission = uint8 + +const ( + PermNone Permission = iota + PermScreenCapture + PermWebRTC + PermClipboardAccess + PermAll +) diff --git a/player.go b/player.go deleted file mode 100644 index 49cf157..0000000 --- a/player.go +++ /dev/null @@ -1,60 +0,0 @@ -package altv - -// #include "capi.h" -import "C" -import ( - "unsafe" -) - -type Player interface { - Entity - DiscordUserID() int64 - SocialID() uint64 - Health() uint16 - Spawn(x float64, y float64, z float64, delayMs uint) -} - -type player struct { - entity -} - -func NewPlayer(ptr unsafe.Pointer, id uint32) Player { - p := &player{ - entity{ - worldObject{ - baseObject: newBaseObject(BaseTypePlayer, ptr, id), - }, - }, - } - - return p -} - -/*func EmptyPlayer() Player { - return &player{} -}*/ - -func Players() []Player { - arr := C.core_get_players() - return newBaseObjectArray[Player](arr) -} - -func PlayerByID(id uint32) (Player, error) { - return getBaseObject[Player](C.core_get_base_object_by_i_d(C.uchar(BaseTypePlayer), C.uint(id))) -} - -func (p *player) SocialID() uint64 { - return uint64(C.player_get_social_i_d(p.ptr)) -} - -func (p *player) DiscordUserID() int64 { - return int64(C.player_get_discord_id(p.ptr)) -} - -func (p *player) Health() uint16 { - return uint16(C.player_get_health(p.ptr)) -} - -func (p *player) Spawn(x float64, y float64, z float64, delayMs uint) { - C.player_spawn(p.ptr, C.float(x), C.float(y), C.float(z), C.ulong(delayMs)) -} diff --git a/init.go b/resource/init.go similarity index 71% rename from init.go rename to resource/init.go index 6ef8a25..0b419f1 100644 --- a/init.go +++ b/resource/init.go @@ -1,4 +1,4 @@ -package altv +package resource import ( "fmt" @@ -6,13 +6,8 @@ import ( "unsafe" "github.com/timo972/altv-go/internal/lib" - "github.com/timo972/altv-go/mvalue" ) -// #cgo CFLAGS: -I./internal/c-api/lib -// #cgo linux LDFLAGS: -L./internal/c-api/lib/linux -lcapi -ldl -g -// #cgo windows LDFLAGS: -L./internal/c-api/lib/win32 -lcapi -ldl -g -// #cgo CXXFLAGS: -std=c++14 // #include // #include "capi.h" import "C" @@ -45,10 +40,10 @@ func listenSignal() { func initGoResource(ptr unsafe.Pointer, name *C.char, path *C.char, ver *C.char) C.int { fmt.Println("resource initializing") - CurrentResource = &localResource{ + Current = &LocalResource{ name: C.GoString(name), path: C.GoString(path), - publicResource: publicResource{ + PublicResource: PublicResource{ ptr: ptr, }, } @@ -63,13 +58,12 @@ func initGoResource(ptr unsafe.Pointer, name *C.char, path *C.char, ver *C.char) status := C.load_module(mod) if int(status) == 0 { - log.Fatalf("couldn't locate %s library", lib.MODULE_NAME) + log.Printf("couldn't locate %s library", lib.MODULE_NAME) + return status } fmt.Println("resource initialized") - mvalue.SetResourceName(CurrentResource.Name()) - ready = true // go listenSignal() diff --git a/resource.go b/resource/resource.go similarity index 59% rename from resource.go rename to resource/resource.go index b89ca0e..003c656 100644 --- a/resource.go +++ b/resource/resource.go @@ -1,22 +1,31 @@ -package altv - -/* -#include -#include "capi.h" -*/ +package resource + +// #cgo CFLAGS: -I../internal/c-api/lib +// #cgo linux LDFLAGS: -L../internal/c-api/lib/linux -lcapi -ldl -g +// #cgo windows LDFLAGS: -L../internal/c-api/lib/win32 -lcapi -ldl -g +// #cgo CXXFLAGS: -std=c++14 +// #include +// #include "capi.h" import "C" import ( "unsafe" "github.com/timo972/altv-go/internal/cutil" + "github.com/timo972/altv-go/perm" ) -type publicResource struct { +func newPermissionArray(arr C.struct_array) []perm.Permission { + return cutil.NewArrayFunc[C.uchar, perm.Permission](unsafe.Pointer(arr.array), int(arr.size), func(item C.uchar) perm.Permission { + return perm.Permission(item) + }) +} + +type PublicResource struct { ptr unsafe.Pointer } -type localResource struct { - publicResource +type LocalResource struct { + PublicResource name string path string } @@ -37,109 +46,105 @@ type Resource interface { // Dependants returns resource names that depend on this resource. Dependants() []string // RequiredPermissions returns the required permissions the player has to grant for this resource. - RequiredPermissions() []Permission + RequiredPermissions() []perm.Permission // OptionalPermissions returns the optional permissions the player can grant for this resource. - OptionalPermissions() []Permission + OptionalPermissions() []perm.Permission // Path returns the resource path. Path() string // Config populates the given struct with the resource config. Config(out any) error // Import imports a value exported by another resource, no matter which language. See mvalue serialization for more information about supported values. - Import(name string, out any) error + // Import(name string, out any) error } // CurrentResource is the resource you are scripting in. -var CurrentResource Resource +var Current *LocalResource // ResourceByName returns a resource by it's name. -func ResourceByName(name string) Resource { +func ByName(name string) Resource { str := C.CString(name) defer C.free(unsafe.Pointer(str)) ptr := C.core_get_resource_by_name(str) - return &publicResource{ + return &PublicResource{ ptr: ptr, } } // AllResources returns all resources. -func AllResources() []Resource { +func All() []Resource { arr := C.core_get_all_resources() return cutil.NewArrayFunc[unsafe.Pointer, Resource](unsafe.Pointer(arr.array), int(arr.size), func(item unsafe.Pointer) Resource { - return &publicResource{ + return &PublicResource{ ptr: item, } }) } -func (r publicResource) IsStarted() bool { +func (r PublicResource) IsStarted() bool { return uint8(C.resource_is_started(r.ptr)) == 1 } -func (r localResource) IsStarted() bool { +func (r LocalResource) IsStarted() bool { return true } -func (r publicResource) Type() string { +func (r PublicResource) Type() string { return C.GoString(C.resource_get_type(r.ptr)) } -func (r localResource) Type() string { +func (r LocalResource) Type() string { return "go" } -func (r publicResource) Name() string { +func (r PublicResource) Name() string { return C.GoString(C.resource_get_name(r.ptr)) } -func (r localResource) Name() string { +func (r LocalResource) Name() string { return r.name } -func (r publicResource) Main() string { +func (r PublicResource) Main() string { return C.GoString(C.resource_get_main(r.ptr)) } -func (r publicResource) Exports(out any) error { - return nil -} - -func (r publicResource) Dependencies() []string { +func (r PublicResource) Dependencies() []string { cDeps := C.resource_get_dependencies(r.ptr) return cutil.NewStringArray(unsafe.Pointer(cDeps.array), int(cDeps.size)) } -func (r publicResource) Dependants() []string { +func (r PublicResource) Dependants() []string { cDeps := C.resource_get_dependants(r.ptr) return cutil.NewStringArray(unsafe.Pointer(cDeps.array), int(cDeps.size)) } -func (r publicResource) RequiredPermissions() []Permission { +func (r PublicResource) RequiredPermissions() []perm.Permission { data := C.resource_get_required_permissions(r.ptr) return newPermissionArray(data) } -func (r publicResource) OptionalPermissions() []Permission { +func (r PublicResource) OptionalPermissions() []perm.Permission { data := C.resource_get_optional_permissions(r.ptr) return newPermissionArray(data) } -func (r publicResource) Path() string { +func (r PublicResource) Path() string { return C.GoString(C.resource_get_path(r.ptr)) } -func (r localResource) Path() string { +func (r LocalResource) Path() string { return r.path } -func (r publicResource) Config(out any) error { +func (r PublicResource) Config(out any) error { return nil } -func (r publicResource) Import(name string, out any) error { - return resourceImport(r.Name(), name, out) -} +/*func (r PublicResource) Import(name string, out any) error { + return imprt.New(r.Name(), name, out) +}*/ diff --git a/runtime/tools/pkg-capi.js b/runtime/tools/pkg-capi.js deleted file mode 100644 index 7690dda..0000000 --- a/runtime/tools/pkg-capi.js +++ /dev/null @@ -1,272 +0,0 @@ -const fs = require("fs"); -const path = require("path"); -const { promisify } = require("util"); - -const readFile = promisify(fs.readFile); -const readDir = promisify(fs.readdir); -const writeFile = promisify(fs.writeFile); - -const definitionRegex = - /*/^[\/]{0,0}EXPORT\s([a-zA-Z0-9\s\*]{1,}[\s\*]{1,1})([A-Z]{1,1}[a-zA-Z]+)_([a-zA-Z0-9]+)\(([a-zA-Z0-9\s\*\,]{0,})\);/gm*/ /EXPORT\s([a-zA-Z0-9\s\*]{1,}[\s\*]{1,1})([A-Z]{1,1}[a-zA-Z]+)_([a-zA-Z0-9]+)\(([a-zA-Z0-9\s\*\,]{0,})\);/gm; -// match: whole line -// group 1: return type -// group 2: class name -// group 3: cpp-sdk func name -// group 4: arg as string, seperated by comma - -const typedefRegex = - /typedef\s[a-z]+\s[a-zA-Z0-9\s]+{[^}]+}[\s]{0,1}[a-zA-Z0-9]+;/gm; -// match whole struct typedef - -function camelCaseToSnakeCase(str) { - for (var i = 0; i < str.length; i++) { - const char = str.charAt(i); - - const isUpper = /[A-Z]/g.test(char); - - if (i === 0 && isUpper) - str = char.toLocaleLowerCase() + str.substring(1, str.length); - else if (isUpper) - str = - str.substring(0, i) + - "_" + - char.toLocaleLowerCase() + - str.substring(i + 1, str.length); - } - - return str; -} - -function generateCTypedef(returnValue, className, methodName, args) { - const fn = `capi_${camelCaseToSnakeCase(className + methodName)}`; - const typedef = `typedef ${returnValue} (*${fn})(${args});\n`; - - return [typedef, fn]; -} - -function generateCFuncDef(returnValue, className, methodName, args) { - const func = `${returnValue} ${camelCaseToSnakeCase( - className + methodName - )}(${args});\n`; - - return func; -} - -function generateCFuncInit(typedefName, pureName) { - const callName = `g_call_${pureName}`; - return [`${typedefName} ${callName};\n`, callName]; -} - -function generateCGetFunc(cFuncInitName, className, methodName, typedefName) { - return `${cFuncInitName} = GET_FUNC(module, "${className}_${methodName}", ${typedefName});\n`; -} - -function generateCFuncBody(returnType, pureName, argStr) { - const args = argStr.split(",").map((val) => { - const lastIdxOfSpace = val.lastIndexOf(" ") + 1; - // let type = val.substring(0, lastIdxOfSpace).trim(); - let name = val.substring(lastIdxOfSpace, val.length); - if (name.charAt(0) === "*") { - name = name.substring(1, name.length); - // type += " *"; - } - return name; - }); - - if (returnType === "void") - return ` -${returnType} ${pureName}(${argStr}) -{ - g_call_${pureName}(${args.join(", ")}); -}\n`; - else - return ` -${returnType} ${pureName}(${argStr}) -{ - return g_call_${pureName}(${args.join(", ")}); -}\n`; -} - -function loadModuleStuff(lines) { - return ` -int load_module(const char *path) -{ - module = LOAD_LIB(path); - - if (module == NULL) - { - return 0; - } - - ${lines.join("\n")} - - return 1; -} -`; -} - -function generateCApiPartial(definitionPath, definitionContent) { - return new Promise((resolve, reject) => { - let hContent = `// ${definitionPath} Module.h\n`; - let hFuncDefs = `// ${definitionPath} Module.h\n`; - let cContent = `// ${definitionPath} Module.c\n`; - let cLoadModuleFunc = `// ${definitionPath} int load_module(const char *path);\n`; - let cFuncBodys = `// ${definitionPath} Module.c\n`; - let match; - - while ((match = definitionRegex.exec(definitionContent)) !== null) { - if (match.index === definitionRegex.lastIndex) { - definitionRegex.lastIndex++; - } - - const returnType = match[1].trim(); - - const [typedef, name] = generateCTypedef( - returnType, - match[2], - match[3], - match[4] - ); - const func = generateCFuncDef(returnType, match[2], match[3], match[4]); - - const snakeName = name.substring(5, name.length); - - const [cInit, callName] = generateCFuncInit(name, snakeName); - const cFunc = generateCGetFunc(callName, match[2], match[3], name); - const cFuncBody = generateCFuncBody(returnType, snakeName, match[4]); - - if ( - typeof typedef !== "string" || - typeof func !== "string" || - typeof cInit !== "string" || - typeof cFunc !== "string" || - typeof cFuncBody !== "string" || - typeof callName !== "string" - ) { - reject(`invalid return of generateCTypedef, check script!`); - return; - } else hContent += typedef; - cContent += cInit; - hFuncDefs += func; - cLoadModuleFunc += cFunc; - cFuncBodys += cFuncBody; - } - - cContent += "\n\n"; - hContent += "\n\n"; - hContent += hFuncDefs; - cContent += "\n\n"; - cContent += cFuncBodys; - - resolve([hContent, cContent, cLoadModuleFunc]); - }); -} - -const files = [ - // we need the structs - path.join(__dirname, "../src/Main.h"), - // c-api definitions - path.join(__dirname, "../src/capi/") -]; - -const cBegin = ` -#include "capi.h" - -Module module; -`; - -const hBegin = ` -#ifndef CAPI_MODULE -#define CAPI_MODULE - -#ifndef __linux__ -#include - -#define SEPARATOR "\\\\" -#define LOAD_LIB(path) LoadLibrary(path) -#define GET_FUNC(module, name, type) (type) GetProcAddress(module, name); - -typedef HINSTANCE Module; -#else -#include -#include - -#define SEPARATOR "/" -#define LOAD_LIB(name) dlopen(name, RTLD_NOW); -#define GET_FUNC(module, name, type) (type) dlsym(module, name); - -typedef void *Module; -#endif - -int load_module(const char *path); -`; - -async function main() { - // check for necessary files - files.forEach((p) => { - if (!fs.existsSync(p)) { - throw new Error( - `Could not find file: '${p}' tool must be run in project root` - ); - } - }); - - // filter c-api definitions - const res = (await readDir(files[1])) - .filter((f) => f.endsWith(".h")) - .map((f) => path.join(files[1], f)); - if (res.length < 1) - throw new Error(`Could not find any c-api definitions ('${files[1]}')`); - - console.log(`reading ${res.length} file(s)...`); - - // read c-api definitions - const partials = await Promise.all( - res.map(async (fp) => { - const definitionContent = await readFile(fp, { - encoding: "utf8", - }); - - return generateCApiPartial(fp, definitionContent); - }) - ); - - console.log(`joining partials...`); - - // join c-api partials (header & source) - let h = partials.map((x) => x[0]).join("\n"); - const c = partials.map((x) => x[1]).join("\n"); - const d = partials.map((x) => x[2]); - - const getFuncsStr = loadModuleStuff(d); - - console.log(`including ${files[0]} typedefs...`); - const mainH = await readFile(files[0], { - encoding: "utf8", - }); - - let typedefs = ""; - let m; - while ((m = typedefRegex.exec(mainH)) !== null) { - if (m.index === typedefRegex.lastIndex) { - typedefRegex.lastIndex++; - } - - m.forEach((match) => { - typedefs += "\n" + match + "\n"; - }); - } - - console.log("writing package c-api..."); - - if (!fs.existsSync("./out")) fs.mkdirSync("./out"); - await writeFile( - `./out/capi.h`, - hBegin + "\n" + typedefs + "\n" + h + "\n" + "\n#endif" - ); - await writeFile(`./out/capi.c`, cBegin + "\n" + c + "\n\n" + getFuncsStr); - - console.log("done!"); -} - -main(); diff --git a/scripts/build-capi.bat b/scripts/build-capi.bat index f3ff860..dec05ed 100644 --- a/scripts/build-capi.bat +++ b/scripts/build-capi.bat @@ -1,5 +1,7 @@ @echo off +go run ./cmd/gencapi/... -cout=./internal/c-api/build/out/capi.c -hout=./internal/c-api/build/out/capi.h -hout=./internal/c-api/lib/capi.h ./runtime/src/capi + cd.\internal\c-api IF NOT EXIST build\ ( diff --git a/scripts/build-capi.sh b/scripts/build-capi.sh index c1ac2c9..f3a5cc9 100755 --- a/scripts/build-capi.sh +++ b/scripts/build-capi.sh @@ -1,5 +1,7 @@ #!/bin/bash +go run cmd/gencapi/*.go -cout=./internal/c-api/build/out/capi.c -hout=./internal/c-api/build/out/capi.h -hout=./internal/c-api/lib/capi.h ./runtime/src/capi + cd ./internal/c-api if [ ! -d build ]; then diff --git a/test/base_object.go b/test/base_object.go deleted file mode 100644 index b3cdb73..0000000 --- a/test/base_object.go +++ /dev/null @@ -1,101 +0,0 @@ -package test - -import ( - "context" - "encoding/json" - "errors" - "unsafe" - - "github.com/timo972/altv-go" - "github.com/timo972/altv-go/mvalue" -) - -// copied from altv-go/base_object.go -type baseObjectData struct { - mvalue.SpecialType - ID uint32 `json:"id"` - Type altv.BaseObjectType `json:"type"` - Ptr string `json:"ptr"` - Model uint32 `json:"model,omitempty"` -} - -type BaseObject struct { - ctx context.Context - cancelFunc context.CancelCauseFunc - ptr unsafe.Pointer - id uint32 - typ altv.BaseObjectType - meta map[string][]byte -} - -func (b *BaseObject) Type() altv.BaseObjectType { - return b.typ -} - -func (b *BaseObject) SetType(typ altv.BaseObjectType) *BaseObject { - b.typ = typ - return b -} - -func (b *BaseObject) ID() uint32 { - return b.id -} - -func (b *BaseObject) SetID(id uint32) *BaseObject { - b.id = id - return b -} - -func (b *BaseObject) Valid() bool { - return b.ctx.Err() == nil -} - -func (b *BaseObject) Ptr() unsafe.Pointer { - return b.ptr -} - -func (b *BaseObject) SetPtr(ptr unsafe.Pointer) *BaseObject { - b.ptr = ptr - return b -} - -func (b *BaseObject) Destroy() { - b.cancelFunc(errors.New("object destroyed")) -} - -func (b *BaseObject) Context() context.Context { - return b.ctx -} - -func (b *BaseObject) SetMetaData(key string, value interface{}) error { - data, err := mvalue.Marshal(value) - if err != nil { - return err - } - b.meta[key] = data - return nil -} - -func (b *BaseObject) MetaData(key string, value interface{}) error { - raw, ok := b.meta[key] - if !ok { - return errors.New("meta data not found") - } - return mvalue.Unmarshal(raw, value) -} - -func (b *BaseObject) MarshalJSON() ([]byte, error) { - return json.Marshal(baseObjectData{ID: b.id, Type: b.typ}) -} - -func (b *BaseObject) CancelCtx(err error) { - b.cancelFunc(err) -} - -func NewBaseObject(id uint32, typ altv.BaseObjectType) *BaseObject { - ctx, cancel := context.WithCancelCause(context.Background()) - return &BaseObject{ - ctx: ctx, - cancelFunc: cancel, - } -} diff --git a/test/entity.go b/test/entity.go deleted file mode 100644 index dcbc721..0000000 --- a/test/entity.go +++ /dev/null @@ -1,5 +0,0 @@ -package test - -type Entity struct { - WorldObject -} diff --git a/test/player.go b/test/player.go deleted file mode 100644 index 6c887a4..0000000 --- a/test/player.go +++ /dev/null @@ -1,57 +0,0 @@ -package test - -import "github.com/timo972/altv-go" - -type Player struct { - Entity - name string - socialID uint64 - discordUserID int64 - health uint16 -} - -func (p *Player) Name() string { - return p.name -} - -func (p *Player) SetName(name string) *Player { - p.name = name - return p -} - -func (p *Player) SocialID() uint64 { - return p.socialID -} - -func (p *Player) SetSocialID(id uint64) *Player { - p.socialID = id - return p -} - -func (p *Player) DiscordUserID() int64 { - return p.discordUserID -} - -func (p *Player) SetDiscordUserID(id int64) *Player { - p.discordUserID = id - return p -} - -func (p *Player) Health() uint16 { - return 100 -} - -func (p *Player) SetHealth(health uint16) *Player { - p.health = health - return p -} - -func NewPlayer(id uint32) *Player { - return &Player{ - Entity: Entity{ - WorldObject: WorldObject{ - BaseObject: *NewBaseObject(id, altv.BaseTypePlayer), - }, - }, - } -} diff --git a/test/world_object.go b/test/world_object.go deleted file mode 100644 index 0c84466..0000000 --- a/test/world_object.go +++ /dev/null @@ -1,5 +0,0 @@ -package test - -type WorldObject struct { - BaseObject -} diff --git a/vehicle.go b/vehicle.go deleted file mode 100644 index e0ceeb2..0000000 --- a/vehicle.go +++ /dev/null @@ -1,45 +0,0 @@ -package altv - -// #include "capi.h" -import "C" -import ( - "unsafe" -) - -type Vehicle interface { - Entity -} - -type vehicle struct { - entity - model uint32 -} - -func NewVehicle(ptr unsafe.Pointer, id uint32, model uint32) Vehicle { - v := &vehicle{ - entity{ - worldObject{ - baseObject: newBaseObject(BaseTypeVehicle, ptr, id), - }, - }, - model, - } - - return v -} - -func VehicleByID(id uint32) (Vehicle, error) { - return getBaseObject[Vehicle](C.core_get_base_object_by_i_d(C.uchar(BaseTypeVehicle), C.uint(id))) -} - -func CreateVehicle(model uint32, pos Vector3, rot Vector3) (Vehicle, error) { - // TODO: validate model beforehand. best solution: data/vehmodels.bin - - e := C.core_create_vehicle(C.ulong(model), C.float(pos.X), C.float(pos.Y), C.float(pos.Z), C.float(rot.X), C.float(rot.Y), C.float(rot.Z)) - - return getBaseObject[Vehicle](e) -} - -func (v *vehicle) Model() uint32 { - return v.model -} diff --git a/world_object.go b/world_object.go deleted file mode 100644 index 1e4d3f5..0000000 --- a/world_object.go +++ /dev/null @@ -1,9 +0,0 @@ -package altv - -type WorldObject interface { - BaseObject -} - -type worldObject struct { - baseObject -}