Jump to content
alt:V Multiplayer Forum
Mafia

Useful snippets

Recommended Posts

Posted (edited)

Lets start sharing useful snippets that would be beneficial for everyone

[server] Players in range

//gets players in range (thanks to Tuxick for faster distance formula)
export const DistanceBetween = (distOne: Position, distTwo: Position) => {
  let distSqr = Math.pow(distOne.x - distTwo.x, 2) + Math.pow(distOne.y - distTwo.y, 2) + Math.pow(distOne.z - distTwo.z, 2);
  return distSqr;
}

export const playersInRange = (position: Position, range: number): Array<any[]> => {
    const playersInRange = [] as any;
    alt.players.forEach((p: Player) => {
        const d = DistanceBetween(p.pos, position);
        if (d <= range){
            p.dist = d;
            playersInRange.push(p);
        }
    })
    return playersInRange;
}

//USAGE
 playersInRange(player.pos, 225).forEach((p: Player) => {
        const dist = p.dist; // distance
   	console.log(p); // player
});
   interface Player {
      dist: number;
   }

[server] Command to save coords to a file

chat.registerCmd('savepos', (player: Player, name: string) => {
    if (!name) return chat.send(player, `/savepos [name]`);
    const savedPos = {
        pos: {x: player.pos.x, y: player.pos.y, z: player.pos.z},
        name
    }
    // file location is relative path from current file
    const fileLocation = new URL('../../../../../dev/savedPos.json', import.meta.url);
    fs.appendFile(fileLocation, JSON.stringify(savedPos) + '\r\n', function (err) {
        if (err) return chat.send(player, `Error saving to file. ${err}`);
        chat.send(player, `X:${savedPos.pos.x} Y:${savedPos.pos.y} Z:${savedPos.pos.z} | name: ${savedPos.name} saved to file!`);
    })
});

*if your using typescript add this to your types file for import.meta.url to work

interface ImportMeta {
   url: any
}

 

[server] MYSQL pool util

//./modules/pool.ts
import mysql from 'mysql';

const config = {
    connectionLimit: 50,
    host: '',
    user: '',
    password: '',
    database: ''
}

let pool: mysql.Pool;

export function getPool(): mysql.Pool {
    if (pool) return pool;
    pool = mysql.createPool(config);
    pool.on('acquire', function (connection) {
        console.log('Connection %d acquired', connection.threadId);
      });
      pool.on('release', function (connection) {
        console.log('Connection %d released', connection.threadId);
      });
    return pool;
}
//./modules/Db.ts
import mysql from 'mysql';
import {getPool} from './modules/pool';

class DbSingleton {
    private pool: mysql.Pool;
    private static _instance: DbSingleton;

    private constructor() {
        this.pool = getPool();
        console.log('connection created to mysql');
    }
    public static get Instance() {
        return this._instance || (this._instance = new this());
    }
    query(sql:any, args?:any): Promise<any>{
        return new Promise((resolve, reject) => {
            if (args){
                this.pool.query(sql,args, (err, rows) => {
                    if (err){
                        return reject(err);
    
                    } else {
                        resolve(rows)
                    }
                });
            } else {
                this.pool.query(sql, (err, rows) => {
                    if (err){
                        return reject(err);
    
                    } else {
                        resolve(rows)
                    }
                });
            }
        });

    }
    getConnection() {
        return new Promise((resolve, reject) => {
            this.pool.getConnection((err, connection) => {
                if (err) {
                    if (err.code === 'PROTOCOL_CONNECTION_LOST') {
                        console.error('db connection lost/closed.')
                    }
                    if (err.code === 'ER_CON_COUNT_ERROR') {
                        console.error('db too many connections.')
                    }
                    if (err.code === 'ECONNREFUSED') {
                        console.error('db connection was refused.')
                    }
                    return reject(err);
                }
                if (connection) {
                    connection.release()
                    resolve(connection)
                }
            })

        });
    }
}

const Db = DbSingleton.Instance;
export default Db;
//index.ts
import Db from './modules/db/db';

async function getData(accountId: number) {
 let data = await Db.query('select * from characters where accountId = ?', [accountId]);
}

[server] Generate random token on node (size is in bytes)

import crypto from 'crypto';

export async function randomToken(byte) {
    return new Promise((resolve, reject) => {
        crypto.randomBytes(byte, (err, buffer) => {
            if (err) {
                return reject('Error Generating Random Token.');
            } else {
                let token = "";
                token = buffer.toString('hex');
                return resolve(token);
            }
        });
    })
}

randomToken(3).then(token => {
    console.log(token)
}).catch(error => {
    console.log(error)
})

[client] Asycn models loading (credits: Tuxick)
 

import * as alt from 'alt';
import * as game from 'natives';

function loadModelAsync(model)
{
  return new Promise((resolve, reject) => {
    if(typeof model === 'string') {
      model = game.getHashKey(model);
    }
  
    if(!game.isModelValid(model))
      return resolve(false);

    if(game.hasModelLoaded(model))
      return resolve(true);

    game.requestModel(model);

    let interval = alt.setInterval(() => {
      if(game.hasModelLoaded(model)) {
        alt.clearInterval(interval);
        return resolve(true);
      }
    }, 0);
  });
}

[server/client] find player by id

export const findPlayerById = (id) => {
    if (typeof id !== 'number') return;
    const player = alt.Player.all.find(p => p.id === id)
    return player;
}

 

[server] Global timer

let timer: any = 0;

const changeTime = async (currentDate: Date, isFirstRunning: boolean) => {
    if (isFirstRunning) {
        return;
    }
    everyMinuteEvent();
    if (currentDate.getMinutes() === 0) {
        everyhourEvent();
    }
    if (currentDate.getMinutes() % 5 === 0) {
        every5MinutesEvent();
    }
};

const runTimer = (isFirstRunning?: boolean) => {
    const currentDate = new Date();
    const remainingMs= (60 - currentDate.getSeconds()) * 1000 + (1000 - currentDate.getMilliseconds());
    changeTime(currentDate, !!isFirstRunning);
    clearTimeout(timer);
    timer = setTimeout(() => {
        runTimer();
    }, remainingMs);
};

runTimer(true);

function everyhourEvent() {

}

function every5MinutesEvent() {
   
}

function everyMinuteEvent() {

}

 

Edited by Mafia
typo
  • Like 6

Share this post


Link to post
Share on other sites
Posted (edited)
import math3d from 'math3d';

const Utils = {
    clamp: (value, min, max) => {
        return value <= min ? min : value >= max ? max : value;
    },
    getUnixTimestamp: () => {
        return Math.round(Date.now() / 1000);
    },
    formatUnixTimestamp: (unixTimestamp) => {
        const date = new Date(unixTimestamp * 1000);
        const hours = date.getHours();
        const minutes = date.getMinutes();
        const seconds = date.getSeconds();
        return `${date.getDate()}/${date.getMonth() + 1}/${date.getFullYear()} ${hours < 10 ? "0" : ""}${hours}:${minutes < 10 ? "0" : ""}${minutes}:${seconds < 10 ? "0" : ""}${seconds}`;
    },
    getRandomInt: (min = 0, max = 100) => {
        return Math.floor(Math.random() * (max - min + 1)) + min;
    },
    radiansToDegrees: (radians) => {
        var pi = Math.PI;
        return radians * (180 / pi);
    },
    headingToDirection: (heading) => {
        heading = Utils.degreesToRadians(heading);
        return { x: - Math.sin(heading), y: Math.cos(heading), z: 0 };
    },
    rotationToDirection: (rot) => {
        let rotZ = Utils.degreesToRadians(rot.z);
        let rotX = Utils.degreesToRadians(rot.x);
        let cos = Math.cos(rotX);
        let multXY = Math.abs(cos);
        return { x: Math.sin(rotZ) * multXY, y: Math.cos(rotZ) * multXY, z: Math.sin(rotX) };
    },
    degreesToRadians: (degrees) => {
        var pi = Math.PI;
        return degrees * (pi / 180);
    },
    DistanceBetween: (One, Two) => {
        let v1 = new math3d.Vector3(One.x, One.y, One.z);
        let v2 = new math3d.Vector3(Two.x, Two.y, Two.z);
        return v1.distanceTo(v2);
    }
}

export default Utils;
Edited by DampflokTV
New Version
  • Like 2

Share this post


Link to post
Share on other sites

Callbacks, Get position in front of player, and get forward vector.

Server:

async function getForwardVector(player) {
    var result = await ClientCallback(player, 'getForwardVector', []);
    return result;
}

async function frontOfPlayer(player, distance) {
    var result = await getForwardVector(player);
    var pos = {
        x: player.pos.x + result.x * distance,
        y: player.pos.y + result.y * distance,
        z: player.pos.z + result.z * distance
    }
    return pos;
}

async function ClientCallback(player, clientEventName, argsArray) {
    alt.emitClient(player, clientEventName, argsArray);
    
    let promise = new Promise((res, rej) => {
        alt.onClient(clientEventName, (player, resultsArray) => {
            res(resultsArray);
        });
    });
    
    var result = await promise;
    return result;
}

Client:

alt.onServer('getForwardVector', () => {
    var result = game.getEntityForwardVector(alt.getLocalPlayer().scriptID);
    alt.emitServer('getForwardVector', result);
});

 

Share this post


Link to post
Share on other sites
Posted (edited)

Get current FPS:

var fps = [];
fps.countedFrames = 0;
fps.lastFPSReset = 0;
fps.value = 0;

export function getCurrentFPS() {
    return fps.value;
}

alt.on('update', () => {
    fps.countedFrames++;

    if(!fps.lastFPSReset) {
        fps.lastFPSReset = Date.now();
    }

    if(Date.now() - fps.lastFPSReset >= 1000) {
        fps.value = fps.countedFrames;
        fps.countedFrames = 0;
        fps.lastFPSReset = Date.now();
    }
})

export default { getCurrentFPS }

 

Edited by Legend

Share this post


Link to post
Share on other sites

 

C# SendMessage (Create new class)

 

internal static class ChatHandler
{
  public static void SendMessage(this IPlayer player, string message)
  {
  	player.Emit("chatmessage", null, message);
  }
}

now you can use

player.SendMessage("HELLO WORLD");
player.SendMessage("<b>Hello World</b>");
player.sendMessage("<font style='color: green; font-weight: bold;'>Hello World</font>");

 

Edited by Max Jackson

Share this post


Link to post
Share on other sites

MySQL snippet, ready-for-use query function

Requirements:

npm install --save mysql2

 

[server-side] database.mjs

import alt from 'alt';
import mysql from 'mysql2';

const hostname = 'localhost';
const username = 'root';
const password = '';
const database = 'altv';

const db = mysql.createPool({
    host: hostname,
    user: username,
    password: password,
    database: database
});

// query("SELECT * FROM ?? WHERE ?? = ?", ['accounts', 'username', 'Wanderer'], (error:boolean, result:object) => {
//      if(error) return;
// });
export function query(sql, values, callback) {
    // Is callback a function
    if (typeof(callback) !== "function") throw new Error('Callback must be a function (() => {}).');
    // Is values an object
    if (typeof(values) !== "object") throw new Error('Values must be an object(array) ([]).');

    // Format and escape query, put values inside
    sql = mysql.format(sql, values);

    // Execute query
    db.query(sql, (error, result) => {
        // If caught an error while executing query
        if (error) {
            callback((error) ? true : false, null);
            alt.logError(error.message);
            return;
        }
        // Got results, send data to callback
        callback((error) ? true : false, result);
    })
}

export default { query };

 

[server-side] index.mjs

import db from './utility/database';

db.query("SELECT * FROM ?? WHERE ?? = ?", ['accounts', 'username', 'Wanderer'], (error, result) => {
    if (error) return console.log('ERROR');
    console.log(`Got username: ${result[0].username}`);
});

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...