[Tutorial] Entendiendo la sincronizaciуn de SA-MP
#1

[Tutorial] Entendiendo la sincronizaciуn de SA-MP
> Tutorial original por g_aSlice - traducciуn por MrDeath



Introducciуn:
Quote:
Originally Posted by g_aSlice
Me enterй de un montуn de bugs y problemas que las personas tienen por falta de conocimientos, luego de leer esto, espero haber aclarado algunas cosas.

Secciones:
  • Introducciуn
  • Secciones
  • El servidor corre en un sуlo hilo
    • Cosas que podrнan tomar mucho tiempo
    • Beneficios
  • Actualizaciones del jugador
    • їQuй pasa cuando un jugador mueve la cбmara, se mueve, cambia de teclas, etc?
    • їQuй pasa cuando retorno 0 en OnPlayerUpdate?
    • Ejemplo de buen uso
    • Ejemplo de mal uso
      • Mejor cуdigo
  • Jugador afectando las funciones del servidor
    • їQuй significa esto?
  • Sincronizaciуn de las teclas
  • Sincronizando a un jugador descincronizado
  • Teclas enviadas al servidor
  • Avanzado
    • Perdida de paquetes
      • їCуmo puedo prevenir perdida de paquetes y esos bugs de script?
      • Prevenir este ban fraudulento (continuaciуn del ejemplo del punto anterior)
    • Desorden de paquetes
      • їCуmo prevenir este ban fraudulento? (continuaciуn del ejemplo de Desorden de paquetes)
  • Notas


El servidor corre en un sуlo hilo:
El servidor corre en un sуlo hilo, esto podrнa sonar complicado para algunas personas, permitanme explorarlo: Todas las acciones que el server hace deben esperar a que la anterior finalize.
Por ejemplo, si tienes un cуdigo que toma 3 segundos en OnPlayerConnect (como el viejo plugin GeoIP) el servidor esperarб que termine ese cуdigo para luego hacer cualquier otra cosa.
  • Cosas que podrнan tomar mucho tiempo:
    • Usar largos strings.
    • Hacer un loop entre los players haciendo muchas cosas dentro.
    • Escribir y leer muchos archivos (EJ: el modo en el cuбl funciona DIni)
    El servidor esperarб que esas cosas terminen para hacer otras, por eso debes tratar de mantener tus scripts lo mбs rбpidos posibles.

  • Beneficios:
    Los beneficios de tener un servidor corriendo en un sуlo hilo (en mi opiniуn) es que tienes todo el control sobre la informaciуn que pase por el server: Siempre procesarб cada aciуn en el servidor. Si el servidor fuese multi hilo, entonces las informaciones de los jugadores podrнan ser actualizadas mientras los scripts estбn corriendo, honestamente no creo que esto pueda ser mejor.


Actualizaciones del jugador:
Cuando alguna de las siguientes cosas cambian para el cliente, йl enviarб la informaciуn al servidor, y el servidor ejecutarб OnPlayerUpdate, lista de cosas:
  • Salud / Chaleco
  • Salud del vehнculo, daсo visual, colores, tuning ...
  • Muerto
  • Velocidad
  • Posiciуn y rotaciуn
  • Animaciуn
  • Teclas presionadas
  • Arma / municiуn
  • Posiciуn de la cбmara (sуlo cuando estб apuntando, de lo contrario, se actualiza 2 veces por segundo aproximadamente)
Scripteando podйs detectar almenos todas las cosas que cambian en OnPlayerUpdate.

  • їQuй pasa cuando un jugador mueve la cбmara, se mueve, cambia de teclas, etc?:

    1) Si el jugador estб apuntando o disparando, los бngulos de la cбmara y del jugador serбn enviados al mismo tiempo, y OnPlayerUpdate serб llamada. Si el jugador no estб apuntando o disparando, OnPlayerUpdate podrнa o no ser ejecutado en el momento (posiblemente no)
    2) OnPlayerUpdate es ejecutado para el nuevo estado de teclas; OnPlayerKeyStateChange no es ejecutado porque la tecla es derecha/izquierda o arriba/abajo. La animaciуn del jugador tambiйn sera actualizada despuйs de que OnPlayerUpdate sea ejecutado.

    Nota: No estoy totalmente seguro si la animaciуn serб actualizada en el mismo momento en el que se actualizan las teclas, y no puedo testearlo en este momento.

    La ID que retorna la funciуn GetPlayerAnimationIndex cambiarб tan rбpido como una nueva animaciуn es iniciada para el cliente. Por ejemplo, cuando empiezas a correr la animaciуn serб actualizada en el momento en el que preciones la tecla de moverte (lo cuбl no serб instantaneo).


  • їQuй pasa cuando retorno 0 en OnPlayerUpdate?:
    OnPlayerUpdate es ejecutado antes de que el servidor envнe la informaciуn a los otros jugadores. Si tъ pones "return 0" en cualquier OnPlayerUpdate (tanto filterscripts o gamemode), el update no serб enviado a los otros jugadores.


  • Ejemplo de buen uso:
    Esto detendrб las acciones del jugador mientras estй congelado. No mбs "disparo fantasma" o como sea que le digas :P.

    pawn Код:
    new
        bool:g_IsPlayerFroze[ MAX_PLAYERS ] // Variable global
    ;

    // --------------------------------------------------------

    public OnPlayerSpawn( playerid )
    {
        g_IsPlayerFroze[ playerid ] = false; // Descongelar luego de spawnear
    }

    // --------------------------------------------------------

    public OnPlayerUpdate( playerid )
    {
        static // Usamos variables estбticas para no tener que iniciarlas cada vez que se use OnPlayerUpdate
            s_Keys,
            s_UpDown,
            s_LeftRight
        ;
       
        GetPlayerKeys( playerid, s_Keys, s_UpDown, s_LeftRight ); // Obtenemos las teclas
       
        if ( g_IsPlayerFroze[ playerid ] && ( s_Keys || s_UpDown || s_LeftRight ) ) // Si alguna de las teclas es precionada mientras estб congelado, desincronizarlo.
            return 0;
       
        return 1;
    }

    // --------------------------------------------------------

    stock FreezePlayer( playerid )
    {
        g_IsPlayerFroze[ playerid ] = true; // The server now treats the player as a froze player
       
        TogglePlayerControllable( playerid, false );
    }

    // --------------------------------------------------------

    stock UnfreezePlayer( playerid )
    {
        g_IsPlayerFroze[ playerid ] = false; // Opposite of the comment above!
       
        TogglePlayerControllable( playerid, true );
    }

  • Ejemplo de mal uso:
    Debajo si "return 1" no estб en la funciуn cada una de las actualizaciones de los jugadores no serб sincronizada.

    pawn Код:
    public OnPlayerUpdate( playerid )
    {
        if ( GetPlayerWeapon( playerid ) == WEAPON_MINIGUN )
            Ban( playerid );
    }
    • Mejor cуdigo:
      pawn Код:
      public OnPlayerUpdate( playerid )
      {
          if ( GetPlayerWeapon( playerid ) == WEAPON_MINIGUN )
              Ban( playerid );
         
          return 1;
      }


Jugador afectando las funciones del servidor:
Las funciones como SetPlayerHealth, GivePlayerMoney, PutPlayerInVehicle y otras envнan un mensaje del servidor sуlo al jugador que serб afectado (SetPlayerVirtualWord es un excepciуn).
  • їQuй significa esto?:
    Bueno, supongamos que un jugador tiene 73% de salud, y tъ lo curas con SetPlayerHealth, esto es lo que ocurre:
    • SetPlayerHealth(playerid, 100.0) -> El servidor envнa un mensaje para afectar al cliente cuando йste ol reciba (actualizando su salud al 100%)
    • El cliente estб pausado, entonces el mensaje estб pausado y afectarб al jugador cuando йste salga de la pausa.
    • Un Timer en el gamemode usa GetPlayerHealth en el jugador y йste devolverб 73
    • El cliente sale de la pausa, todos los mensajes "pausados" lo afectarбn.
    • La salud cambia para el jugador.
    • La actualizaciуn de eso es enviada al servidor
    • OnPlayerUpdate es ejecutado.
    • La nueva salud es enviada a todos los otros jugadores, y ellos lo ven ahora con el 100% de la salud.


Sincronizaciуn de las teclas:
SA-MP es sincronizado copiando las teclas que precionas y aplicandoselas a los otros jugadores. Si tъ precionas la tecla de apuntar y la de disparar, tъ estarнas apretando las teclas de apuntar y disparar para los otros jugadores. Esto significa que cuando estбs disparando en tu pantalla deberнas estar en frente de un vehнculo descincronizado o ser apuсalado o una explosiуn de algъn vehнculo y en las pantallas de otros jugadores esto serнa llamada descincronizaciуn.



Sincronizando a un jugador descincronizado:
Para corregir a un jugador descincronizado es ocultarlo y volverlo a mostrar para otros jugadors (haciendolo respawnear). Esto podrнa tardar un segundo, de todas formas, respawnearlo es la mejor soluciуn.



Teclas enviadas al servidor:
Algunas cosas que creen; si tъ precionas y sueltas alguna tecla rбpidamente el servidor no lo notarб. ЎEquivocado! Por ejemplo si tъ precionas y sueltas le tecla de disparo, el servidor recivirб 2 actualizaciones: que precionaste la telca de disparo, y que la soltaste.



Avanzado:
  • Perdida de paquetes:
    Algunas veces cuando un jugador envнa una actualizaciуn al servidor, este podrнa perder el paquete en alguna parte del mundo. Esto podrнa causar problemas o bugs en el script, Ўestate preparado para la perdida de paquetes!

    • їCуmo puedo prevenir perdida de paquetes y esos bugs de script?:
      Nunca confнes en el cliente, nunca sabrбs si el cliente es un script intentado hacer un lнo con tu servidor, o alguien con una mala conexiуn, o alguien con una perdida de paquetes.
      La perdida de paquetes usualmente causa confuciуn con la informaciуn del jugador, por ejemplo:
      • El jugador 1 tiene 50% de armadura.
      • El servidor tiene un nuevo anticheat de armadura basado en actualizaciones del jugador.
      • El anticheat de armadura serб detectado si la armadura del jugador cambia, y el jugador no perdiу $240 cuando estaba en el ammunation.
      • El jugador 1 entra al ammunation. El server sabe eso gracias al callback OnPlayerInteriorChange.
      • El jugador 1 compra una armadura y envнa un paquete al servidor con la informaciуn de que ahora tiene 100% de armadura y que perdiуn $240.
      • El jugador 1 envнa el paquete; ЎEl paquete se pierde!
      • El jugador 1 empieza a moverse alrededor, las actualizaciones no son enviadas porque el servidor no tiene idea sobre los $240 o sobre la armadura.
      • Le disparan al jugador 1, el cliente envнa una actualizaciуn al servidor sobre la nueva cantidad de armadura. El servidor sigue sin saber que el jugador perdio $240 y que comprу la armadura.
      • El anticheat del servidor detecta esto, y se banйa al jugador por hackear su armadura.

    • Prevenir este ban fraudulento:
      • Notificar a los administradores quй pasу secretamente o sumar una advertencia en el script y a las 3 banearlo.
      • Darle al jugador $1 y esperar una nueva actualizaciуn de dinero, posiblemente remover la armadura y volverla a poner sуlo si el nuevo dinero del jugador es recibido en los siguientes 1~3 paquetes.
  • Desorden de paquetes:
    Los desordenes de paquetes es cuando los paquetes no llegan el orden enviado.
    Por ejemplo:
    • El jugador 1 tiene 85% de armadura
    • El servidor tiene un anticheat de armadura basado en actualizaciones de jugadores.
    • El anticheat de armadura detectarа si el jugador cambiу su cantidad de armadura, y si йl no perdiу $240 en el ammunation.
    • El jugador 1 esta haciendo un DM (duelo)
    • El jugador 1 es atacado 2 veces, pierde un 10% de vida por cada ataque (-10%, -10% = -20%) esas dos actualizaciones serбn enviadas al servidor.
    • ЎLos paquetes se desordenan!
    • El primero que llega desordenado es el segundo (cuando ya perdiу el 20% de armadura, le queda 65%)
    • El segundo que llega desordenado es el primero (cuando habнa perdido 10% de armadura, le queda 75%)
    • El servidor detecta que su armadura se incremento y banea al jugador por error.
    • їCуmo prevenir este ban fraudulento:
      • Notificar a los administradores quй pasу secretamente o sumar una advertencia en el script y a las 3 banearlo.
      • No tomar acciones acciones hasta las siguientes 2~3 actualizaciones, sуlo tomar advertencias.
      • Tomar acciones sуlo si la nueva armadura es mayor o igual a 100


Notas:
Quote:
Originally Posted by g_aSlice
Espero que hallas aprendido algunas cosas de este tutorial, Ўsi me he equivocado en algo haganmelo saber y corregirй/agregarй mбs informaciуn a este posteo!
g_aSlice me diу permiso para traducir su tutorial:
Quote:
Originally Posted by g_aSlice por PM
I would be really glad if you could translate it. I'll put a link in my topic once you're done.
Quote:
Originally Posted by g_aSlice por PM traducido
Estarнa realmente contento si puedes traducirlo. Pondrй un link en mi posteo una vez que hallas terminado.
Reply
#2

Buen post
Me sirvio para una duda que tenia
Reply
#3

Quote:
Originally Posted by Nicolas_Soria
Посмотреть сообщение
Buen post
Me sirvio para una duda que tenia
Me alegro que halla servido.
Reply
#4

Muchas gracнas por la info
Reply
#5

Muy bien. Te debo un plбtano.
Reply
#6

Excelente gracias
Reply
#7

Gracias por tu tiempo MrDeath, muy ъtil
Reply
#8

Quote:
Originally Posted by g_aSlice
Посмотреть сообщение
Muy bien. Te debo un plбtano.
Me gusta tu estilo.

Realmente es muy ъtil saber Inglйs, yo, por ejemplo, no tengo la necesidad de preocuparme si alguien tradujo mal el texto original y generalmente el traductor ****** es una MALA COSTUMBRE.

Por cierto, me da flojera leer el tema pero habнa una parte interesante que hablaba que SA-MP es single-threaded.

ЎAl que le interese aprender que lo lea!
Reply
#9

Quote:
Originally Posted by Miguel
Посмотреть сообщение
Me gusta tu estilo.

Realmente es muy ъtil saber Inglйs, yo, por ejemplo, no tengo la necesidad de preocuparme si alguien tradujo mal el texto original y generalmente el traductor ****** es una MALA COSTUMBRE.

Por cierto, me da flojera leer el tema pero habнa una parte interesante que hablaba que SA-MP es single-threaded.

ЎAl que le interese aprender que lo lea!
їPor quй single-threaded?

Hay varias razones para afirmar este sistema

1є: La sincronizacion seria una caos, como dice ahi el script correria al mismo tiempo que el jugador dando un lag.

Hasta ahora se me ocurre solo esa.
Reply
#10

Quote:
Originally Posted by xenowort
Посмотреть сообщение
Aprende ingles y no seas vago xD.

Es muy util y si lo conocia hace muchas semanas. (3) o eso creo.
se ingles, solo di una alternativa para aquellos que no, de hecho el 16 de diciembre doy el FCE.
Reply


Forum Jump:


Users browsing this thread: 3 Guest(s)