UNPKG

@duydang2311/ragemp-utils

Version:

A collection of utilities for RAGE Multiplayer JavaScript module.

376 lines (374 loc) 9.24 kB
// src/lib/vector.ts var distanceSquared = (a, b) => { const dx = a.x - b.x; const dy = a.y - b.y; if ("z" in a && "z" in b) { const dz = a.z - b.z; return dx * dx + dy * dy + dz * dz; } return dx * dx + dy * dy; }; // src/lib/spatial-grid.ts var SpatialGrid2D = class _SpatialGrid2D { static DEFAULT_MIN_X = -4e3; static DEFAULT_MAX_X = 4e3; static DEFAULT_MIN_Y = -4e3; static DEFAULT_MAX_Y = 8e3; static DEFAULT_CELL_SIZE = 128; #idCounter; #min; #max; #rows; #columns; #cells; #cellSize; #idLookup = /* @__PURE__ */ new Map(); constructor(options) { this.#idCounter = 0; this.#min = options?.min ?? { x: _SpatialGrid2D.DEFAULT_MIN_X, y: _SpatialGrid2D.DEFAULT_MIN_Y }; this.#max = options?.max ?? { x: _SpatialGrid2D.DEFAULT_MAX_X, y: _SpatialGrid2D.DEFAULT_MAX_Y }; this.#cellSize = options?.cellSize ?? _SpatialGrid2D.DEFAULT_CELL_SIZE; this.#rows = Math.ceil((this.#max.y - this.#min.y) / this.#cellSize); this.#columns = Math.ceil((this.#max.x - this.#min.x) / this.#cellSize); this.#cells = new Array(this.#rows * this.#columns).fill(0).map(() => []); } get min() { return this.#min; } get max() { return this.#max; } get cellSize() { return this.#cellSize; } get rows() { return this.#rows; } get columns() { return this.#columns; } cellAt(coords) { this.#assertInBounds(coords); return this.#safeCellAt(coords); } nearbyCells(coords, radius) { this.#assertInBounds(coords); const minCol = Math.max( 0, Math.floor((coords.x - radius - this.#min.x) / this.#cellSize) ); const maxCol = Math.min( this.#columns - 1, Math.floor((coords.x + radius - this.#min.x) / this.#cellSize) ); const minRow = Math.max( 0, Math.floor((coords.y - radius - this.#min.y) / this.#cellSize) ); const maxRow = Math.min( this.#rows - 1, Math.floor((coords.y + radius - this.#min.y) / this.#cellSize) ); const cells = new Array( (maxRow - minRow + 1) * (maxCol - minCol + 1) ); let index = 0; for (let row = minRow; row <= maxRow; ++row) { for (let col = minCol; col <= maxCol; ++col) { cells[index++] = row * this.#columns + col; } } return cells; } add(item, coords, radius) { this.#assertInBounds(coords); const id = ++this.#idCounter; if (radius == null) { const cellIndex = this.#safeCellAt(coords); this.#cells[cellIndex].push([id, item]); this.#idLookup.set(id, [[cellIndex]]); return id; } const minCol = Math.max( 0, Math.floor( (coords.x - (radius ?? 0) - this.#min.x) / this.#cellSize ) ); const maxCol = Math.min( this.#columns - 1, Math.floor( (coords.x + (radius ?? 0) - this.#min.x) / this.#cellSize ) ); const minRow = Math.max( 0, Math.floor( (coords.y - (radius ?? 0) - this.#min.y) / this.#cellSize ) ); const maxRow = Math.min( this.#rows - 1, Math.floor( (coords.y + (radius ?? 0) - this.#min.y) / this.#cellSize ) ); const cells = []; for (let row = minRow; row <= maxRow; ++row) { for (let col = minCol; col <= maxCol; ++col) { const cellIndex = row * this.#columns + col; cells.push(cellIndex); this.#cells[cellIndex].push([id, item, radius]); } } this.#idLookup.set(id, [cells]); return id; } update(id, coords, radius) { const itemLookup = this.#idLookup.get(id); if (!itemLookup) { return false; } const [lookUpCells] = itemLookup; let item; for (const cell of lookUpCells) { item = this.#cells[cell].find( (cellItem) => cellItem[0] === id )?.[1]; if (item) { break; } } if (!item || !this.remove(id)) { return false; } if (radius == null) { const cellIndex = this.#safeCellAt(coords); this.#cells[cellIndex].push([id, item]); this.#idLookup.set(id, [[cellIndex]]); return true; } const minCol = Math.max( 0, Math.floor( (coords.x - (radius ?? 0) - this.#min.x) / this.#cellSize ) ); const maxCol = Math.min( this.#columns - 1, Math.floor( (coords.x + (radius ?? 0) - this.#min.x) / this.#cellSize ) ); const minRow = Math.max( 0, Math.floor( (coords.y - (radius ?? 0) - this.#min.y) / this.#cellSize ) ); const maxRow = Math.min( this.#rows - 1, Math.floor( (coords.y + (radius ?? 0) - this.#min.y) / this.#cellSize ) ); const cells = []; for (let row = minRow; row <= maxRow; ++row) { for (let col = minCol; col <= maxCol; ++col) { const cellIndex = row * this.#columns + col; cells.push(cellIndex); this.#cells[cellIndex].push([id, item, radius]); } } this.#idLookup.set(id, [cells]); return true; } remove(id) { const itemLookup = this.#idLookup.get(id); if (!itemLookup) { return false; } const [cells] = itemLookup; for (const cellIndex of cells) { const cellItems = this.#cells[cellIndex]; const itemIndex = cellItems.findIndex( (cellItem) => cellItem[0] === id ); if (itemIndex !== -1) { cellItems.splice(itemIndex, 1); } } return this.#idLookup.delete(id); } #safeCellAt(coords) { const col = Math.floor((coords.x - this.#min.x) / this.#cellSize); const row = Math.floor((coords.y - this.#min.y) / this.#cellSize); return row * this.#columns + col; } #assertInBounds(coords) { if (coords.x < this.#min.x || coords.x >= this.#max.x || coords.y < this.#min.y || coords.y >= this.#max.y) { throw new Error( `Coordinates (${coords.x}, ${coords.y}) are out of bounds for the grid.` ); } } }; // src/lib/local-marker.ts var RageMpLocalMarker = class { #type; #position; #destination; #direction; #rotation; #scale; #radius; #color; #bobUpAndDown; #faceCamera; #rotate; #textureDict; #textureName; #drawOnEnts; constructor(type, position, destination, rotation, scale, radius, color, bobUpAndDown = false, faceCamera = false, rotate = false, textureDict = null, textureName = null, drawOnEnts = false) { this.#type = type; this.#position = position; this.#destination = destination; this.#rotation = rotation; this.#scale = scale; this.#radius = radius; this.#color = color; this.#bobUpAndDown = bobUpAndDown; this.#faceCamera = faceCamera; this.#rotate = rotate; this.#textureDict = textureDict; this.#textureName = textureName; this.#drawOnEnts = drawOnEnts; this.#direction = this.#getDirectionVector(); } get type() { return this.#type; } get position() { return this.#position; } get destination() { return this.#destination; } get rotation() { return this.#rotation; } get scale() { return this.#scale; } get radius() { return this.#radius; } get color() { return this.#color; } get bobUpAndDown() { return this.#bobUpAndDown; } get faceCamera() { return this.#faceCamera; } get rotate() { return this.#rotate; } get textureDict() { return this.#textureDict; } get textureName() { return this.#textureName; } get drawOnEnts() { return this.#drawOnEnts; } set type(value) { this.#type = value; } set position(value) { this.#position = value; } set destination(value) { this.#destination = value; this.#direction = this.#getDirectionVector(); } set rotation(value) { this.#rotation = value; } set scale(value) { this.#scale = value; } set radius(value) { this.#radius = value; } set color(value) { this.#color = value; } set bobUpAndDown(value) { this.#bobUpAndDown = value; } set faceCamera(value) { this.#faceCamera = value; } set rotate(value) { this.#rotate = value; } set textureDict(value) { this.#textureDict = value; } set textureName(value) { this.#textureName = value; } set drawOnEnts(value) { this.#drawOnEnts = value; } render() { mp.game.graphics.drawMarker( this.#type, this.#position.x, this.#position.y, this.#position.z, this.#direction.x, this.#direction.y, this.#direction.z, this.#rotation.x, this.#rotation.y, this.#rotation.z, this.#scale.x, this.#scale.y, this.#scale.z, this.#color[0], this.#color[1], this.#color[2], this.#color[3], this.#bobUpAndDown, this.#faceCamera, 2, this.#rotate, this.#textureDict, this.#textureName, this.#drawOnEnts ); } #getDirectionVector() { return new mp.Vector3( this.#destination.x - this.#position.x, this.#destination.y - this.#position.y, this.#destination.z - this.#position.z ); } }; export { RageMpLocalMarker, SpatialGrid2D, distanceSquared }; //# sourceMappingURL=index.js.map