Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Dudas Sobre Dead Reckoning

Iniciado por Lord Trancos 2, 13 de Mayo de 2006, 12:44:51 AM

« anterior - próximo »

Lord Trancos 2

 Estaba yo aburrido en casa y me ha dado por programar el Half Life 3.  :rolleyes:  Y tengo algunas dudillas sobre como realizar la parte de multiplayer (el resto esta chupao).

Llevo toda la tarde/noche leyendo "papers" y "posts" sobre el tema, e incluso me he mirado un poco el codigo fuente del Quake 2, por lo que es comprensible que tenga la sensacion de tener un lio impresionante en la cabeza, asi que si no suelto aqui mis dudas no voy a poder dormir.

Mas o menos tengo claro que:
- Tengo que usar UDP.
- Evitar "floodear" a los clientes o al servidor.
- Tener en cuenta que voy a perder paquetes.
- Tener en cuenta que los paquetes me van a llegar desordenados.
- Tener en cuenta que los paquetes me pueden llegar corruptos.
- Para evitar el lag, deberia de usar algo como el "Dead Reckoning"

Y en este ultimo punto es donde me lio un poco.

Si un cliente dispara a la cabeza de otro jugador (en el juego, se entiende), ¿quien deberia de decidir el impacto? ¿El cliente que dispara o el servidor? Entiendo que si es el cliente puede darse el caso de que alguien haga "cheating"  <_< por no decir que la posicion de su victima en su simulacion no tiene pq ser correcta, pero por otro lado si manda el servidor el cliente puede tener la impresion de que el juego no funciona bien o que estan haciendole trampas.

Luego, que pasa si se dejan de recibir paquetes durante un periodo importante de tiempo,... digamos 2 segundos. La diferencia entre la posicion calculada por el servidor y la real seria muy brusca y eso produciria una especie de "teletrasportacion", ¿como se podria solucionar esto?

Mas dudas,...
> Hoy en dia, ¿cuantos bytes por segundo para un juego de 8 players (por ejemplo)?
> ¿Enviar informacion duplicada para evitar problemas derivados de paquetes perdidos?
> ¿Comprimir los paquetes? ¿Con que algoritmo?

Y por ultimo, ¿alguien ha hecho algo asi (juego multiplayer por red, usando UDP y dead Reckoning? ¿Algo cuyo codigo se pueda usmear?  :rolleyes: ¿Consejos? ¿Experiencias traumaticas?

pd. mi intencion es usar SDL_net, ya que aunque tengo experiencia con winsock+UDP, me gustaria hacerlo multiplataforma. ¿que tal SDL_net?

ale, ya puedo dormir tranquilo  :lol:  
on los años y mucho esfuerzo he llegado a atesorar una ignorancia total sobre casi todas las cosas.
Gate to Avalon (mi Blog)

Zaelsius

 Respecto al ancho de banda usado, aquí hay algunos datos de gente corriendo servidores de Counter-Strike(rebusca un poco en las respuestas)

http://www.webhostingtalk.com/archive/thre...d/277091-1.html

Extracto:
CitarNote: CPU says 0 because we use FreeBSD)

CPU In Out Uptime Users FPS Players
0.00 56.96 73.14 983 698 98.23 20

This is on a 20 man public de_inferno server.

Also, that is at a high usage time. Here is a lower usage time:

CPU In Out Uptime Users FPS Players
0.00 32.41 36.01 984 698 100.17 20

Also, here is about what it looks most of the time:

CPU In Out Uptime Users FPS Players
0.00 47.99 61.78 986 698 99.65 20

Respecto al "teletransporte", es algo que sigue pasando en los juegos modernos y no se puede hacer mucho al respecto si dejas de recibir datos durante un largo tiempo. Lo bueno es que las conexiones han mejorado, tanto en capacidad como en latencia(en esto no tanto).

seryu

Cita de: "Lord Trancos 2"



Mas dudas,...




Y por ultimo, ¿alguien ha hecho algo asi (juego multiplayer por red, usando UDP y dead Reckoning? ¿Algo cuyo codigo se pueda usmear?  :rolleyes: ¿Consejos? ¿Experiencias traumaticas?



CitarLlevo toda la tarde/noche leyendo "papers" y "posts" sobre el tema, e incluso me he mirado un poco el codigo fuente del Quake 2, por lo que es comprensible que tenga la sensacion de tener un lio impresionante en la cabeza, asi que si no suelto aqui mis dudas no voy a poder dormir.

No me extraña, carmack programa como el culo. No me extraña que programe solo (Nadie le quiere como compañero).

Citar
Si un cliente dispara a la cabeza de otro jugador (en el juego, se entiende), ¿quien deberia de decidir el impacto? ¿El cliente que dispara o el servidor? Entiendo que si es el cliente puede darse el caso de que alguien haga "cheating"  <_< por no decir que la posicion de su victima en su simulacion no tiene pq ser correcta, pero por otro lado si manda el servidor el cliente puede tener la impresion de que el juego no funciona bien o que estan haciendole trampas.

Lo mejor es que el servidor envie una informacion al resto de clientes y el cliente que originó el disparo siga viendo el juego tal cual le paso a él, asi todos ganan, y todos son felices.

Citar
Luego, que pasa si se dejan de recibir paquetes durante un periodo importante de tiempo,... digamos 2 segundos. La diferencia entre la posicion calculada por el servidor y la real seria muy brusca y eso produciria una especie de "teletrasportacion", ¿como se podria solucionar esto?

Dejale andando en el cliente y cuando tenga que recolocar normalmente estara cerquita. Si no puedes hacer como el paso anterior.

Citar> Hoy en dia, ¿cuantos bytes por segundo para un juego de 8 players (por ejemplo)?

¿Para 8 players en LAN o en Internet?

Citar> ¿Enviar informacion duplicada para evitar problemas derivados de paquetes perdidos?

Si la conexion es tan mala que pierde paquetes es mejor que jueguen a otro juego y no te molesten.

Citar> ¿Comprimir los paquetes? ¿Con que algoritmo?

Puedes usar zlib.

Citarpd. mi intencion es usar SDL_net, ya que aunque tengo experiencia con winsock+UDP, me gustaria hacerlo multiplataforma. ¿que tal SDL_net?

Si todo lo anterior no era de coña, mejor que pases de sdl_net y te centres en winsocks.

Citarale, ya puedo dormir tranquilo  :lol:

Pues yo no.. como duele la cabrona de la muela  (nooo)  

senior wapo

 ---EDITADO, que aprete enviar pronto sin querer---

Si quieres algo mas pequeñito que raknet, usa la libreria enet.
No uses winsock, usa una libreria hecha, de verdad :)

Lo principal es que colapses muchos paquetes en uno solo de ser posible, digamos que tengas un manager que no transmita los paquetes inmediatamente si es posible (cuando no es un paquete urgente) sino en el siguiente slot de envío (pon que solo envias cada 15ms x ejemplo). Asi reduces la sobrecarga de las cabeceras de paquete IP.

El tema del warping es complicado, quieras que no el cliente va a tener que predecir el movimiento de las demas unidades y corregir cuando reciba la posición real desde el servidor. Notarse, se va a notar, pero el jugador se acostumbra.

El tema de la simulación hazlo siempre en el servidor. Hay servidores que solo hacen de hub que reenvia paquetes en lugar de correr simulación y queda fatal. Recuerdo cuando trastee con warbirds (googlea) que los aciertos de los disparos los gestionaba el propio cliente del avion derribado (es decir la victima detecta todos los comandos de disparo del resto y mira si alguno le daria). Era facilente hackeable y tenia un lag y latencias del copón por ser bajo TCP.

En cuanto a comprimir, no te lo recomiendo, y menos con zlib, o cargarás mucho la CPU del servidor. Si no descartas paquetes puedes usar deltas o comandos de movimiento relativos, y si descartas paquetes de movimiento viejos, pues entonces tienes que enviar la posición completa. La mayoria de los paquetes que no son de movimiento los necesitas enviar de forma fiable (retransmitir).

Si te sirve de algo, ni Everquest 1 (UDP), ni Everquest 2 (UDP), ni WoW (TCP posiblemente trucado) descartan paquetes. Final Fantasy es raro en que junta todos los paquetes en uno tocho y lo envia periódicamente (UDP) cada X milisegundos (o algo asi), supongo que comprimido.
EQ incluso llega a comprimir ciertos paquetes con zlib (consultas al bazaar, algo asi como la auction house del WoW).


Ah, otra cosa: Para el servidor usa un socket UDP con un tamaño de buffer de sistema muy grande y procesalo en serie en lugar de muchos sockets o de usar multithread.

Es una verdadera lástima que se perdieran los archivos viejos de la lista Mud-Dev, había info a toneladas sobre red, algoritmos, estructuras para servidores masivos...

jazcks

 tiene muy buena pinta esta lib:
http://www.zoidcom.com/

alguien la ha usado? :P

pd.parece que puede prever el movimiento del jugador, algo critico en fps tipo quake...

vicho

 hola. el dead reckoning no es tan complicado como parece. basicamente es usando el ping del cliente dar una aproximacion de donde deberia estar.
no es tan complicado imaginate que si el jugador esta en la posicion x=20[L] con un ping de 10[T], y a una velocidad de 5[L/T]  el servidor realmente va recivir un movimiento del cliente desde la posicion X=20[L] pero realmente deberia estar en X=20[L]+10[T]*5[L/T], por lo tanto estaria en X=70[L] lo cual haria predecir en el servidor donde deberia estar el cliente.

el problema de este metodo es que pasa si un hacker malicioso (xD) dice ¿que tal si lageo al juego y le doy 100[T]? bueh pues resulta que va a avanzar rapidizimo, pudiendo crear speedhacks para el juego. como solucionar esto. pues no hay una "solucion" lo que se puede hacer es simplemente no aceptar jugadores bajo tal ping(por lo menos yo hago eso xD).

sobre lo del warping, pues bueno eso se debe al cliente side prediction. lo cual hace que el cliente tambien prediga donde deberia estar.
una cosa corta. por regla el servidor es SIEMPRE el que decide donde estan los jugadores

si necesitas alguna implementacion no dudes en mandarme un PM ;)

te doy un link para leer bastante bueno
http://www.gaffer.org/articles/NetworkedPhysics.html

senior wapo

Cita de: "vicho"el problema de este metodo es que pasa si un hacker malicioso (xD) dice ¿que tal si lageo al juego y le doy 100[T]? bueh pues resulta que va a avanzar rapidizimo, pudiendo crear speedhacks para el juego. como solucionar esto. pues no hay una "solucion" lo que se puede hacer es simplemente no aceptar jugadores bajo tal ping(por lo menos yo hago eso xD).
Al hilo de esto, comentar que la frecuencia de los paquetes de movimiento debe estar auditada por el servidor. De hecho, es recomendable que los paquetes de movimiento al menos, lleven un timestamp. Normalmente el servidor conoce la velocidad máxima a la que el cliente puede moverse, y la frecuencia de envio de paquetes. No debe aceptar paquetes individuales que se muevan más distancia de la debida entre las "fechas" del paquete anterior y el actual. El servidor debe llevar su propia cuenta de paquetes y tiempos y comparar también.

Implementar la gestión de los paquetes de movimiento es algo así como el santo grial en un juego online. Volviendo a los ejemplos de juegos que conozco, la información era precisa a enero del 2005, no se si ahora es distinto:

Everquest 1: Envia posiciones absolutas, el cliente tiene la autoridad sobre donde se encuentra el personaje. El personaje propio nunca es corregido, los de los demás presentan warping cuando el servidor envia la posición correcta al cliente. Ha tenido graves problemas de hacking con jugadores haciendo speedhack y teleportándose (bueno, y en todas sus demas áreas también, ya que el cliente tenia la autoridad en demasiadas cosas inicialmente, pero es que el juego debía poder correr en servidores NT del año 98...).

Everquest 2: Envía deltas en lugar de posiciones absolutas. El servidor es la autoridad sobre la posición y si el cliente es malicioso solo consigue dessincronizar su simulación.

World of Warcraft: Envía eventos con timestamps del tipo "Empieza a avanzar", "parate", "empieza a girar a la derecha", etc... Se podría considerar que es similar a envíar la entrada de teclado/ratón al servidor con predicción en el cliente.

 

Lord Trancos 2

 
Citar
No me extraña, carmack programa como el culo. No me extraña que programe solo (Nadie le quiere como compañero).

En el curro he visto cosas mucho peores, asi que no me parecio malo el codigo. Solo que no lo acabo de entender pq no le he dedicado suficiente tiempo. Pero bueno, no entremos en discursiones metafisicas. :rolleyes:

Citar
¿Para 8 players en LAN o en Internet?

Inet.

Citar
Si todo lo anterior no era de coña, mejor que pases de sdl_net y te centres en winsocks.

¿Por? He usado winsock para enviar recibir UDP y me parece demasiado sencillo como para que una libreria como SDL_net no lo haya podido implementar correctamente. Ademas, ya he dicho que quiero multiplataforma.

Citar
Si quieres algo mas pequeñito que raknet, usa la libreria enet.
No uses winsock, usa una libreria hecha, de verdad

Quiero usar SDL_net, o algo multiplataforma sencillito. Mirare las que me comentas a ver si me sirven, pero me gustaria saber que ventajas me ofrecen frente a SDL_net.

Citar
La mayoria de los paquetes que no son de movimiento los necesitas enviar de forma fiable (retransmitir).

Como por ejemplo cuando un jugador cae en combate, no? Y los mensajes de chat?

vicho, cualquier implementacion que pueda ser me sera de ayuda, te envio un PM ;)
ah, y muy interesante el link! me lo he leido ya 3 veces, pero sigo sin comprenderlo todo. (nooo)

Gracias a todos por vuestras respuestas (ole)
on los años y mucho esfuerzo he llegado a atesorar una ignorancia total sobre casi todas las cosas.
Gate to Avalon (mi Blog)

seryu

 Raknet es multiplataforma.

Sdl_net está hecho en plan chapuza, es una libreria simple que está pensada para aplicaciones que no hagan un uso exhaustivo de la red. Por supuesto, si es la que te gusta, úsala, pero es poco recomendable a menos que no te importe optimizar la velocidad de la red.

Tambien tienes la de torque: http://www.opentnl.org/

vicho

 porfavor dinos que no entiendes del link para explicarlo  (ole)  

Lord Trancos 2

 Bueno, estoy haciendo una pequeña prueba a ver si soy capaz de implementar el asunto.

Mas o menos ya lo entiendo y empieza a funcionar.

Básciamente, lo que no entiendo es como implementar el "client side prediction". Entiendo el concepto y por que se hace. Como el imput del usuario tiene que ir al servidor, aquel realiza el movimiento, y envia de nuevo la posicion al cliente, existe un tiempo de espera (latencia) desde que el usuario pulsa la tecla hasta que puede ver que su muñequito empieza a moverse. Y entiendo que ese prediccion se basará en en el input del usuario. Pero no se como hacerlo :(

Me explico...

El link que ha puesto vicho, muestra como realiza la prediccion mediante la funcion clientCorrection. Pero no explica (o al menos yo no lo cogo) que es una correccion y cuando la envia el servidor al cliente. Ademas, no tengo claro si la prediccion se debe de realizar solo con el objeto que mueve el usuario o con todos los objetos que se mueven (de otros usuarios o del server). Imagino que no.... pero en ese caso como hago que el movimiento de los otros objetos sea suave. Para no pasarme con el ancho de banda, envio las posiciones de los objetos cada 100 msec o cada vez que el servidor recibe un cambio en el input de dicho objeto. Por lo que los objetos se me mueven un poco a trompicones...

En fins... que si pruebo lo que he hecho en LAN y con envios cada 10msec la cosa va bien... pero con lag debe de dar miedo. :(
on los años y mucho esfuerzo he llegado a atesorar una ignorancia total sobre casi todas las cosas.
Gate to Avalon (mi Blog)

Lord Trancos 2

 Nada... ya consigo que los objetos se muevan de forma mas suave. Lo unico que he hecho ha sido predecir su posicion basandome en su ultima velocidad multiplicada por el tiempo empleado en renderizar el ultimo frame.

No obstante sigo sin comprender para que sirve la funcion clientCorrection, pq almacena en un buffer circular las ultimas posiciones, y que es una correccion :(
on los años y mucho esfuerzo he llegado a atesorar una ignorancia total sobre casi todas las cosas.
Gate to Avalon (mi Blog)

senior wapo

 
CitarComo el imput del usuario tiene que ir al servidor, aquel realiza el movimiento, y envia de nuevo la posicion al cliente, existe un tiempo de espera (latencia) desde que el usuario pulsa la tecla hasta que puede ver que su muñequito empieza a moverse. Y entiendo que ese prediccion se basará en en el input del usuario. Pero no se como hacerlo

No lo hagas así para el personaje manejado en ese cliente. Corre 2 simulaciones paralelas de la posición del jugador, una en el cliente y otra en el servidor. Si usan los mismos algoritmos y los mismos datos, estarán sincronizadas (en la medida de lo posible) y el cliente no necesitará confirmación. Normalmente el cliente solo actualiza SU posición cuando hay "pausas" de juego (al teleportarse, al cargar una nueva zona/instancia de disco).

CitarAdemas, no tengo claro si la prediccion se debe de realizar solo con el objeto que mueve el usuario o con todos los objetos que se mueven (de otros usuarios o del server). Imagino que no.... pero en ese caso como hago que el movimiento de los otros objetos sea suave.

Con el del usuario no, con los otros si. Para que sea suave interpola (añade el rumbo a la última posición conocida multiplicado por tiempo transcurrido), para que sea preciso, actualiza la posición y renuncia a la suavidad. Elije uno u otro.

En general, lo que ve el cliente no necesita ser preciso, solo una imagen aproximada de lo que ocurre realmente en el servidor.

AK47

 Yo no tengo experiencia en programacion de redes con las exigencias de un juego de accion, pero me gustaria compartir con el foro mis ideas al respecto, que son las siguientes:

- El cliente no debe esperar a la respuestas del servidor para moverse. Siempre se mueve, porque ya conoce la geometria del escenario y eso se puede calcular perfectamente en la parte del cliente, y las colisiones con los demas jugadores se pueden hacer con los datos que se tienen en ese momento.

- En cuanto a los disparos, yo probaria a que cuando el cliente le de a disparar, el disparo salga siempre, pero que el servidor calcule si el disparo ha alcanzado su objetivo o no. El cliente veria que la mayoria de los disparos que dan en el blanco realmente lo hacen, y una parte que simplemente atraviesa su objetivo :P

- Las posiciones de los demas jugadores se pasan en coordenadas absolutas, ya que se admite la perdida de este tipo de mensajes. Obviamente, los mensajes de disparo y otros datos vitales deben enviarse en modo seguro (es decir, que se reenvien si hace falta).

- La teleportacion es inevitable, pero se puede paliar con interpolaciones entre la posicion actual en cierto cliente y su verdadera posicion en el servidor, digo yo >_<

Ala, ya me direis que os parecen mis ideas... pero no seais demasiado duros, ein?

Por cierto, aunque UDP no garantiza casi nada, si garantiza que lo que llegue llegue integro, verdad? Es decir, que nunca tendremos un paquete UDP corrupto.

vicho

 hola. lord trancos el servidor no envia correcciones al cliente solo envia las posiciones reales del cliente. yo lo que hacia era enviar cada 20ms la posicion del cliente. la correccion es algo que realiza el cliente.

sobre udp o tcp, olvidate de TCP, usar tcp para un fps es perder el tiempo. mi codigo antes usaba tcp y realmente se noto bastante la diferencia cuando lo pase a udp(lo cual no fue nada dificil). sobre perder datos, pues no importa, generalmente son datos q se mandan muchas veces por segundo. por lo tanto si nos perdimos un paquete de una posicion lo maximo que podria pasar seria un salto.

una correccion es basicamente corregir en el cliente la posicion de lo que tengamos que corregir :P. cuando un cliente hace los teleports o saltos es por que se hizo una correccion.

ahora una correccion en un servidor es algo mas parecido a un dead reckoning. donde el servidor mediante el ping del jugador decide donde deberia estar.

como trato de explicar ;) son dos correcciones distintas :P






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.