pma-locals 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client/main.ts +33 -0
- package/client/ped-handler.ts +151 -0
- package/client/tsconfig.json +29 -0
- package/definitions/Citizen.d.ts +205 -0
- package/definitions/index.d.ts +4 -0
- package/definitions/json.d.ts +4 -0
- package/definitions/redm.d.ts +23571 -0
- package/dist/client.js +2903 -0
- package/dist/server.js +0 -0
- package/package.json +25 -0
- package/scripts/dev.js +60 -0
- package/server/main.ts +0 -0
- package/server/tsconfig.json +25 -0
- package/shared/config.ts +11 -0
- package/shared/tsconfig.json +34 -0
- package/tsconfig.json +38 -0
- package/types/index.ts +11 -0
package/client/main.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Delay, Vector3 } from "@nativewrappers/redm";
|
|
2
|
+
import { cleanupPeds, processSpawning } from "./ped-handler";
|
|
3
|
+
|
|
4
|
+
// Example: Register peds with their spawn coordinates
|
|
5
|
+
// registerPed(
|
|
6
|
+
// 0x12345678, // model hash
|
|
7
|
+
// new Vector3(-297.74, 791.1, 118.4), // spawn coords
|
|
8
|
+
// 180.0, // heading
|
|
9
|
+
// 50.0, // spawn distance
|
|
10
|
+
// { dict: "amb_wander@world_human_smoke@male@male_a@idle_a", anim: "idle_a" }, // optional animation
|
|
11
|
+
// undefined // optional prop data
|
|
12
|
+
// );
|
|
13
|
+
|
|
14
|
+
setTick(async () => {
|
|
15
|
+
const playerPed = PlayerPedId();
|
|
16
|
+
if (!playerPed) {
|
|
17
|
+
await Delay(500);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const coords = GetEntityCoords(playerPed, true, true);
|
|
22
|
+
const playerPos = new Vector3(coords[0], coords[1], coords[2]);
|
|
23
|
+
|
|
24
|
+
await processSpawning(playerPos);
|
|
25
|
+
|
|
26
|
+
await Delay(500);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
on("onResourceStop", (resourceName: string) => {
|
|
30
|
+
if (resourceName !== GetCurrentResourceName()) return;
|
|
31
|
+
console.log(`Restarting ${resourceName}`);
|
|
32
|
+
cleanupPeds();
|
|
33
|
+
});
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { Animation, Props } from "$types/index";
|
|
2
|
+
import {
|
|
3
|
+
AnimationFlags,
|
|
4
|
+
createPed,
|
|
5
|
+
createProp,
|
|
6
|
+
IkControlFlags,
|
|
7
|
+
Model,
|
|
8
|
+
Prop,
|
|
9
|
+
Vector3,
|
|
10
|
+
} from "@nativewrappers/redm";
|
|
11
|
+
|
|
12
|
+
export interface PedConfig {
|
|
13
|
+
modelName: number;
|
|
14
|
+
coords: Vector3;
|
|
15
|
+
heading: number;
|
|
16
|
+
spawnDistance: number;
|
|
17
|
+
animation?: Animation;
|
|
18
|
+
propData?: Props;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface ActivePedData {
|
|
22
|
+
ped: any;
|
|
23
|
+
config: PedConfig;
|
|
24
|
+
prop: Prop | null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Module-level state
|
|
28
|
+
const pedConfigs: PedConfig[] = [];
|
|
29
|
+
const activePeds: Map<string, ActivePedData> = new Map();
|
|
30
|
+
|
|
31
|
+
export function registerPed(
|
|
32
|
+
modelName: number,
|
|
33
|
+
coords: Vector3,
|
|
34
|
+
heading: number,
|
|
35
|
+
spawnDistance: number = 100.0,
|
|
36
|
+
animation?: Animation,
|
|
37
|
+
propData?: Props
|
|
38
|
+
) {
|
|
39
|
+
pedConfigs.push({
|
|
40
|
+
modelName,
|
|
41
|
+
coords,
|
|
42
|
+
heading,
|
|
43
|
+
spawnDistance,
|
|
44
|
+
animation,
|
|
45
|
+
propData,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function getConfigKey(config: PedConfig): string {
|
|
50
|
+
return `${config.coords.x}_${config.coords.y}_${config.coords.z}`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function isPlayerNearCoords(playerPos: Vector3, targetPos: Vector3, distance: number): boolean {
|
|
54
|
+
const dx = playerPos.x - targetPos.x;
|
|
55
|
+
const dy = playerPos.y - targetPos.y;
|
|
56
|
+
const dz = playerPos.z - targetPos.z;
|
|
57
|
+
return Math.sqrt(dx * dx + dy * dy + dz * dz) <= distance;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export async function processSpawning(playerPos: Vector3) {
|
|
61
|
+
for (const config of pedConfigs) {
|
|
62
|
+
const key = getConfigKey(config);
|
|
63
|
+
const isNear = isPlayerNearCoords(playerPos, config.coords, config.spawnDistance);
|
|
64
|
+
const isSpawned = activePeds.has(key);
|
|
65
|
+
|
|
66
|
+
if (isNear && !isSpawned) {
|
|
67
|
+
// Player is within range and ped is not spawned -> spawn it
|
|
68
|
+
await spawnPed(config, key);
|
|
69
|
+
} else if (!isNear && isSpawned) {
|
|
70
|
+
// Player is outside range and ped is spawned -> delete it
|
|
71
|
+
despawnPed(key);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async function spawnPed(config: PedConfig, key: string) {
|
|
77
|
+
const ped = await createPed(new Model(config.modelName), config.coords, 0.0, false, true);
|
|
78
|
+
if (!ped) return;
|
|
79
|
+
SetRandomOutfitVariation(ped.Handle, true);
|
|
80
|
+
if (config.heading) {
|
|
81
|
+
ped.Heading = config.heading;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (config.animation) {
|
|
85
|
+
await ped.Tasks.playAnimation(
|
|
86
|
+
config.animation.dict,
|
|
87
|
+
config.animation.anim,
|
|
88
|
+
8.0,
|
|
89
|
+
8.0,
|
|
90
|
+
-1,
|
|
91
|
+
1,
|
|
92
|
+
AnimationFlags.Looping,
|
|
93
|
+
IkControlFlags.UpperBody
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
let prop: Prop | null = null;
|
|
98
|
+
if (config.propData) {
|
|
99
|
+
prop = await createProp(new Model(config.propData.model), ped.Position, 0, true, true);
|
|
100
|
+
if (prop) {
|
|
101
|
+
AttachEntityToEntity(
|
|
102
|
+
prop.Handle,
|
|
103
|
+
ped.Handle,
|
|
104
|
+
config.propData.boneId,
|
|
105
|
+
config.propData.offset[0],
|
|
106
|
+
config.propData.offset[1],
|
|
107
|
+
config.propData.offset[2],
|
|
108
|
+
config.propData.rotation[0],
|
|
109
|
+
config.propData.rotation[1],
|
|
110
|
+
config.propData.rotation[2],
|
|
111
|
+
true,
|
|
112
|
+
false,
|
|
113
|
+
false,
|
|
114
|
+
true,
|
|
115
|
+
1,
|
|
116
|
+
true
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
activePeds.set(key, { ped, config, prop });
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function despawnPed(key: string) {
|
|
125
|
+
const activePed = activePeds.get(key);
|
|
126
|
+
if (!activePed) return;
|
|
127
|
+
|
|
128
|
+
if (activePed.prop) {
|
|
129
|
+
activePed.prop.delete();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (activePed.ped) {
|
|
133
|
+
activePed.ped.delete();
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
activePeds.delete(key);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function cleanupPeds() {
|
|
140
|
+
for (const [key, activePed] of activePeds) {
|
|
141
|
+
if (activePed.prop) {
|
|
142
|
+
activePed.prop.delete();
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (activePed.ped) {
|
|
146
|
+
activePed.ped.delete();
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
activePeds.delete(key);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"baseUrl": ".",
|
|
5
|
+
"composite": true,
|
|
6
|
+
"types": [
|
|
7
|
+
"@types/node",
|
|
8
|
+
"@citizenfx/client",
|
|
9
|
+
"@nativewrappers/redm",
|
|
10
|
+
"../definitions/index.ts"
|
|
11
|
+
],
|
|
12
|
+
"paths": {
|
|
13
|
+
"$types/*": [
|
|
14
|
+
"../types/*",
|
|
15
|
+
"../definitions/index.ts"
|
|
16
|
+
],
|
|
17
|
+
"$shared/*": [
|
|
18
|
+
"../shared/*"
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
"resolveJsonModule": true,
|
|
22
|
+
"esModuleInterop": true
|
|
23
|
+
},
|
|
24
|
+
"include": [
|
|
25
|
+
"./",
|
|
26
|
+
"../types/*",
|
|
27
|
+
"../shared/*",
|
|
28
|
+
]
|
|
29
|
+
}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
|
|
3
|
+
interface IntPtrInitialized {}
|
|
4
|
+
interface FloatPtrInitialized {}
|
|
5
|
+
interface IntPtr {}
|
|
6
|
+
interface FloatPtr {}
|
|
7
|
+
interface VectorPtr {}
|
|
8
|
+
interface ReturnResultAnyway {}
|
|
9
|
+
interface ResultAsInteger {}
|
|
10
|
+
interface ResultAsFloat {}
|
|
11
|
+
interface ResultAsString {}
|
|
12
|
+
interface ResultAsVector {}
|
|
13
|
+
interface ResultAsLong {}
|
|
14
|
+
interface ResultAsObject {}
|
|
15
|
+
|
|
16
|
+
type InputArgument =
|
|
17
|
+
| string
|
|
18
|
+
| number
|
|
19
|
+
| IntPtrInitialized
|
|
20
|
+
| FloatPtrInitialized
|
|
21
|
+
| IntPtr
|
|
22
|
+
| FloatPtr
|
|
23
|
+
| VectorPtr
|
|
24
|
+
| ReturnResultAnyway
|
|
25
|
+
| ResultAsInteger
|
|
26
|
+
| ResultAsFloat
|
|
27
|
+
| ResultAsString
|
|
28
|
+
| ResultAsVector
|
|
29
|
+
| ResultAsLong
|
|
30
|
+
| ResultAsObject;
|
|
31
|
+
|
|
32
|
+
interface StateBagInterface {
|
|
33
|
+
[key: string]: any;
|
|
34
|
+
set(key: string, value: any, replicated: boolean): void;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
interface EntityInterface {
|
|
38
|
+
state: StateBagInterface;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
interface CitizenInterface {
|
|
42
|
+
trace(...args: string[]): void;
|
|
43
|
+
setTickFunction(callback: Function): void;
|
|
44
|
+
setEventFunction(callback: Function): void;
|
|
45
|
+
|
|
46
|
+
setCallRefFunction(callback: Function): void;
|
|
47
|
+
setDeleteRefFunction(callback: Function): void;
|
|
48
|
+
setDuplicateRefFunction(callback: Function): void;
|
|
49
|
+
canonicalizeRef(ref: number): string;
|
|
50
|
+
invokeFunctionReference(ref: string, args: Uint8Array): Uint8Array;
|
|
51
|
+
|
|
52
|
+
getTickCount(): number;
|
|
53
|
+
invokeNative<T = void>(hash: string, ...args: InputArgument[]): T;
|
|
54
|
+
invokeNativeByHash<T = void>(
|
|
55
|
+
hash1: number,
|
|
56
|
+
hash2: number,
|
|
57
|
+
...args: InputArgument[]
|
|
58
|
+
): T;
|
|
59
|
+
startProfiling(name?: string): void;
|
|
60
|
+
stopProfiling(name?: string): {};
|
|
61
|
+
|
|
62
|
+
pointerValueIntInitialized(): IntPtrInitialized;
|
|
63
|
+
pointerValueFloatInitialized(): FloatPtrInitialized;
|
|
64
|
+
pointerValueInt(): IntPtr;
|
|
65
|
+
pointerValueFloat(): FloatPtr;
|
|
66
|
+
pointerValueVector(): VectorPtr;
|
|
67
|
+
returnResultAnyway(): ReturnResultAnyway;
|
|
68
|
+
resultAsInteger(): ResultAsInteger;
|
|
69
|
+
resultAsFloat(): ResultAsFloat;
|
|
70
|
+
resultAsString(): ResultAsString;
|
|
71
|
+
resultAsVector(): ResultAsVector;
|
|
72
|
+
resultAsLong(): ResultAsLong;
|
|
73
|
+
resultAsObject(): ResultAsObject;
|
|
74
|
+
|
|
75
|
+
makeRefFunction(refFunction: Function): string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
interface CitizenTimer {
|
|
79
|
+
ref(): CitizenTimer;
|
|
80
|
+
unref(): CitizenTimer;
|
|
81
|
+
hasRef(): boolean;
|
|
82
|
+
refresh(): CitizenTimer;
|
|
83
|
+
[Symbol.toPrimitive](): number;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
type CitizenImmediate = Omit<CitizenTimer, "refresh">;
|
|
87
|
+
|
|
88
|
+
declare let Citizen: CitizenInterface;
|
|
89
|
+
|
|
90
|
+
declare function addRawEventListener(
|
|
91
|
+
eventName: string,
|
|
92
|
+
callback: Function,
|
|
93
|
+
): void;
|
|
94
|
+
|
|
95
|
+
declare function addEventListener(
|
|
96
|
+
eventName: string,
|
|
97
|
+
callback: Function,
|
|
98
|
+
netSafe?: boolean,
|
|
99
|
+
): void;
|
|
100
|
+
declare function on(eventName: string, callback: Function): void;
|
|
101
|
+
declare function AddEventHandler(eventName: string, callback: Function): void;
|
|
102
|
+
|
|
103
|
+
declare function addNetEventListener(
|
|
104
|
+
eventName: string,
|
|
105
|
+
callback: Function,
|
|
106
|
+
): void;
|
|
107
|
+
declare function onNet(eventName: string, callback: Function): void;
|
|
108
|
+
|
|
109
|
+
declare function emit(eventName: string, ...args: any[]): void;
|
|
110
|
+
declare function TriggerEvent(eventName: string, ...args: any[]): void;
|
|
111
|
+
|
|
112
|
+
declare function emitNet(eventName: string, ...args: any[]): void;
|
|
113
|
+
declare function TriggerServerEvent(eventName: string, ...args: any[]): void;
|
|
114
|
+
declare function TriggerLatentServerEvent(
|
|
115
|
+
eventName: string,
|
|
116
|
+
bps: number,
|
|
117
|
+
...args: any[]
|
|
118
|
+
): void;
|
|
119
|
+
|
|
120
|
+
declare function getPlayerIdentifiers(player: number | string): string[];
|
|
121
|
+
declare function getPlayerTokens(player: number | string): string[];
|
|
122
|
+
declare function getPlayers(): string[];
|
|
123
|
+
|
|
124
|
+
declare function SendNUIMessage(data: any): void;
|
|
125
|
+
|
|
126
|
+
declare function emitNet(
|
|
127
|
+
eventName: string,
|
|
128
|
+
target: number | string,
|
|
129
|
+
...args: any[]
|
|
130
|
+
): void;
|
|
131
|
+
declare function TriggerClientEvent(
|
|
132
|
+
eventName: string,
|
|
133
|
+
target: number | string,
|
|
134
|
+
...args: any[]
|
|
135
|
+
): void;
|
|
136
|
+
declare function TriggerLatentClientEvent(
|
|
137
|
+
eventName: string,
|
|
138
|
+
target: number | string,
|
|
139
|
+
bps: number,
|
|
140
|
+
...args: any[]
|
|
141
|
+
): void;
|
|
142
|
+
|
|
143
|
+
declare function removeEventListener(
|
|
144
|
+
eventName: string,
|
|
145
|
+
callback: Function,
|
|
146
|
+
): void;
|
|
147
|
+
|
|
148
|
+
declare function setTimeout<T extends any[]>(
|
|
149
|
+
callback: (...args: T) => void,
|
|
150
|
+
ms?: number,
|
|
151
|
+
...args: T
|
|
152
|
+
): CitizenTimer;
|
|
153
|
+
declare function clearTimeout(timeout: CitizenTimer): void;
|
|
154
|
+
|
|
155
|
+
declare function setInterval<T extends any[]>(
|
|
156
|
+
callback: (...args: T) => void,
|
|
157
|
+
ms?: number,
|
|
158
|
+
...args: T
|
|
159
|
+
): CitizenTimer;
|
|
160
|
+
declare function clearInterval(interval: CitizenTimer): void;
|
|
161
|
+
|
|
162
|
+
declare function setImmediate<T extends any[]>(
|
|
163
|
+
callback: (...args: T) => void,
|
|
164
|
+
...args: T
|
|
165
|
+
): CitizenImmediate;
|
|
166
|
+
declare function clearImmediate(immediate: CitizenImmediate): void;
|
|
167
|
+
|
|
168
|
+
declare function setTick(callback: Function): number;
|
|
169
|
+
declare function clearTick(callback: number): void;
|
|
170
|
+
|
|
171
|
+
declare function NewStateBag(name: string): StateBagInterface;
|
|
172
|
+
declare function Entity(entity: number): EntityInterface;
|
|
173
|
+
declare let GlobalState: StateBagInterface;
|
|
174
|
+
declare function Player(entity: number | string): EntityInterface;
|
|
175
|
+
declare let LocalPlayer: EntityInterface;
|
|
176
|
+
|
|
177
|
+
declare let exports: any;
|
|
178
|
+
|
|
179
|
+
declare let source: number;
|
|
180
|
+
|
|
181
|
+
// Commented methods are not implemented yet
|
|
182
|
+
interface Console {
|
|
183
|
+
assert(condition?: boolean, ...data: any[]): void;
|
|
184
|
+
// clear(): void;
|
|
185
|
+
count(label?: string): void;
|
|
186
|
+
countReset(label?: string): void;
|
|
187
|
+
debug(...data: any[]): void;
|
|
188
|
+
dir(item?: any, options?: any): void;
|
|
189
|
+
// dirxml(...data: any[]): void;
|
|
190
|
+
error(...data: any[]): void;
|
|
191
|
+
// group(...data: any[]): void;
|
|
192
|
+
// groupCollapsed(...data: any[]): void;
|
|
193
|
+
// groupEnd(): void;
|
|
194
|
+
info(...data: any[]): void;
|
|
195
|
+
log(...data: any[]): void;
|
|
196
|
+
// table(tabularData?: any, properties?: string[]): void;
|
|
197
|
+
time(label?: string): void;
|
|
198
|
+
timeEnd(label?: string): void;
|
|
199
|
+
// timeLog(label?: string, ...data: any[]): void;
|
|
200
|
+
// timeStamp(label?: string): void;
|
|
201
|
+
trace(...data: any[]): void;
|
|
202
|
+
warn(...data: any[]): void;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
declare let console: Console;
|