diff --git a/package/client/resource/index.ts b/package/client/resource/index.ts index a271ed00e..065c9cddc 100644 --- a/package/client/resource/index.ts +++ b/package/client/resource/index.ts @@ -12,3 +12,4 @@ export * from './interface/radial'; export * from './streaming'; export * from './vehicleProperties'; export * from './callback'; +export * from './points'; diff --git a/package/client/resource/points/index.ts b/package/client/resource/points/index.ts new file mode 100644 index 000000000..b88c5ed85 --- /dev/null +++ b/package/client/resource/points/index.ts @@ -0,0 +1,105 @@ +import { Vector3 } from '@nativewrappers/client'; + +let points: Point[] = []; +let nearbyPoints: Point[] = []; +let nearbyCount: number = 0; +let closestPoint: Point | undefined; +let tick: number | undefined; + +interface LibPoint { + coords: number[]; + distance: number; + onEnter?: () => void; + onExit?: () => void; + nearby?: () => void; +} + +export class Point { + id: number = 0; + coords: Vector3; + distance: number = 0; + onEnter?: () => void; + onExit?: () => void; + nearby?: () => void; + inside: boolean = false; + currentDistance?: number; + isClosest: boolean = false; + + constructor(point: LibPoint) { + this.id = points.length + 1; + this.coords = Vector3.fromArray(point.coords); + this.distance = point.distance; + this.onEnter = point.onEnter; + this.onExit = point.onExit; + this.nearby = point.nearby; + points.push(this); + } + + remove = () => { + points = points.filter((point) => point.id !== this.id); + }; +} + +setInterval(() => { + if (nearbyCount !== 0) { + nearbyPoints = []; + nearbyCount = 0; + } + + const coords = Vector3.fromArray(GetEntityCoords(PlayerPedId(), false)); + + if (closestPoint && coords.distance(closestPoint.coords) > closestPoint.distance) { + closestPoint = undefined; + } + + for (let i = 0; i < points.length; i++) { + const point = points[i]; + const distance = coords.distance(point.coords); + + if (distance <= point.distance) { + point.currentDistance = distance; + + if (closestPoint && closestPoint.currentDistance) { + if (distance < closestPoint.currentDistance) { + closestPoint.isClosest = false; + point.isClosest = true; + closestPoint = point; + } + } else if (distance < point.distance) { + point.isClosest = true; + closestPoint = point; + } + + if (point.nearby) { + nearbyCount++; + nearbyPoints[nearbyCount - 1] = point; + } + + if (point.onEnter && !point.inside) { + point.inside = true; + point.onEnter(); + } + } else if (point.currentDistance) { + if (point.onExit) point.onExit(); + point.inside = false; + point.currentDistance = undefined; + } + } + + if (!tick) { + if (nearbyCount !== 0) { + tick = setTick(() => { + for (let i = 0; i < nearbyCount; i++) { + const point = nearbyPoints[i]; + + if (point && point.nearby) { + point.nearby(); + } + } + }); + } + } else if (nearbyCount === 0) { + clearTick(tick); + tick = undefined; + } +}, 300); diff --git a/package/package.json b/package/package.json index a683df344..541b38067 100644 --- a/package/package.json +++ b/package/package.json @@ -26,6 +26,7 @@ "@citizenfx/client": "2.0.5885-1", "@citizenfx/server": "2.0.5885-1", "@fortawesome/fontawesome-common-types": "6.1.1", + "@nativewrappers/client": "^1.7.33", "@types/node": "16.9.1", "@types/react": "^18.0.26", "typescript": "^4.9.4" diff --git a/package/pnpm-lock.yaml b/package/pnpm-lock.yaml index 8e2612dad..68df78d3b 100644 --- a/package/pnpm-lock.yaml +++ b/package/pnpm-lock.yaml @@ -4,6 +4,7 @@ specifiers: '@citizenfx/client': 2.0.5885-1 '@citizenfx/server': 2.0.5885-1 '@fortawesome/fontawesome-common-types': 6.1.1 + '@nativewrappers/client': ^1.7.33 '@types/node': 16.9.1 '@types/react': ^18.0.26 prettier: ^2.8.1 @@ -13,6 +14,7 @@ dependencies: '@citizenfx/client': 2.0.5885-1 '@citizenfx/server': 2.0.5885-1 '@fortawesome/fontawesome-common-types': 6.1.1 + '@nativewrappers/client': 1.7.33 '@types/node': 16.9.1 '@types/react': 18.0.26 typescript: 4.9.4 @@ -36,6 +38,10 @@ packages: requiresBuild: true dev: false + /@nativewrappers/client/1.7.33: + resolution: {integrity: sha512-phuBBGdDPxZiZyw5CaFs1XWfvllnEtwATMdLaNucwMofVg/O/FjlP1bTUq4SOm4qhSZ4Zdo351ijHzBSIbZs6g==} + dev: false + /@types/node/16.9.1: resolution: {integrity: sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==} dev: false