xxshady/altv-esbuild

Add playerDisconnect emit on resource restart

stanislawkrowicki opened this issue · 6 comments

Players reconnect emulation emits playerConnect, so why not emit playerDisconnect as well?

playerDisconnect event listener in many gamemodes will probably contain async code (database stuff), and by default altv js module will not wait to async listeners of playerDisconnect to end.

So I think it would only confuse users. Of course I can add waiting for async handlers of playerDisconnect before stopping resource to the plugin, but will it be worth it?

Running playerDisconnect before restart would be indeed a mediocre idea, but what about running it after restart?
Probably best disabled by default.
Of course only if altV does not change any player data at all on resource restart, which im not 100% sure.
Resource restart -> playerDisconnect event -> playerConnect event

I think its possible to do it on resource start but then another problems appear: when playerDisconnect is emitted, alt.Player.all will still contain "disconnected" player instance on clientside and serverside, also under normal circumstances player instance (baseobject) becomes invalid, and all this stuff should be emulated in order not to cause differences with altv api

I think it would be nice to emulate full reconnect, like the one built into altV debug mode, but if you think it's not worth it then it's fine - we can reconnect when really needed ourselves, as lack of emitted playerDisconnect should not be so crucial most of the times.

I will think about it

Okay, I think the time of this issue has come. I will not implement player disconnect emulation to the plugin because it will be too complicated (baseobject invalidation Error: "baseobject is invalid"; removal player instance from alt.Player.all, alt.Entity.all; etc.) and not worth it, it is better to implement such option yourself in your own gamemode:

class MyPlayer {
  /** @type {Map<alt.Player, MyPlayer>} */
  static myPlayersByAltPlayer = new Map()

  static onDisconnect = async (myPlayer) => {
    // custom invalidation of the original altv player instance
    MyPlayer.myPlayersByAltPlayer.delete(myPlayer._altPlayer)
    myPlayer._altPlayer = null

    // your custom async logic
    await alt.Utils.wait(1000)

    alt.log('done!')
  }

  _altPlayer
  constructor(altPlayer) {
    this._altPlayer = altPlayer

    MyPlayer.myPlayersByAltPlayer.set(altPlayer, this)
  }
}

alt.on('playerConnect', (altPlayer) => {
  new MyPlayer(altPlayer)
})

alt.on('playerDisconnect', (altPlayer) => {
  const myPlayer = MyPlayer.myPlayersByAltPlayer.get(altPlayer)
  if (!myPlayer) throw new Error('invalid altPlayer')

  MyPlayer.onDisconnect(myPlayer)
})

// your own dev mode variable or esbuild `define` https://esbuild.github.io/api/#define
if (DEV_MODE) {
  // "disconnecting" all `MyPlayer` players from the server in parallel
  // and yes alt:V JS module and altv-esbuild both support async resourceStop handler
  alt.on('resourceStop', async () => {
    const promises = [...MyPlayer.myPlayersByAltPlayer.values()] // all MyPlayer instances
      .map((myPlayer) => MyPlayer.onDisconnect(myPlayer))
    
    await Promise.all(promises)
  })
}

Although if your gamemode is heavily dependent on the alt:V JS API it will be hard to do it for sure xd