tene presente una cosa.
en el piso. puede estar alguien parado. arriba de un item. arriba de un muerto.
sumale 22bytes extras del nombre del item.
ahora imagínate la pantalla llena con esto.
fijate el tamaño del buffer q estas cargando con la info q te proporcionan ambas funciones.
si la info es demasiada, estarias provocando un overflow.
y te va a tirar un "no responde" el hg y se te va a cerrar. y se te callo el server.
y este tipo de bugs no lo vas a encontrar facilmente.
//edit
las funciones RequestInitDataHandler y RequestTeleportHandler
envia este mensajes: MSGID_RESPONSE_INITDATA
cada buffer(pBuffer), tiene un array de "DEF_MSGBUFFERSIZE+1"
ese macro vale "30000", eso serian casi 30kilobytes. un poco mas de 29(29*1024bytes, 1kbyte = 1024bytes)
la info q se envia, vienen de ciclos dobles, son de 21(x) * 16(y)
- Code:
-
for (iy = 0; iy < 16; iy++)
for (ix = 0; ix < 21; ix++) {...}
del 0 al < 16, escanea datos de 16 espacios. del 0 al 15 son 16.
idem del 0 al < 21.
esos son 336 espacios en tu pantalla q pueden albergar datos.
alguien vivo, alguien muerto. un ítem, o un ob dinámico
en realidad son menos por que tenes la barra de hp, mp, sp.
y toda la demas botonera. pero el hg manda todo igual.
lo primero q copia iComposeInitMapData en el pBuffer es iTileExists
esa variable dice cuantos tiles albergan datos.
despues copia el XY de la coord. para q el client copie los datos de ese tile para esa coord.
esta variable: ucHeader, se usa para decir q es lo que hay en ese tile.
primero se inicialisa
- Code:
-
ucHeader = 0
una variable char/unsigned char, como en este caso, un unsigned char.
se representa mediante 1 byte de informacion.
1 byte se representa mediante un conjunto de 8 bits, un octeto le dicen algunos.
en este caso, ucHeader se representa asi:
- Code:
-
[0][0][0][0][0][0][0][0]
cada corchete es un bit, suponete.
son todos ceros por q se inicializa de forma decimal con un "= 0"
en este if, pregunta si hay alguna "cosa" viva, un bicho o un player.
- Code:
-
if (pTile->m_sOwner != 0)
si es cierto q hay algo "vivo" hace esta operación:
- Code:
-
ucHeader = ucHeader | 0x01;
la barrita vertical | es el OR, significa el O(OR) logico entre bits.
la doble barrita || es otro cuento. no interesa.
el |(OR) es 0 cuando ambos bits lo son, y es 1
cuando al menos 1 bit en el operando es 1.
0x01 es la representacion hexadecimal del 1 decimal.
tomas los dos primeros bits mas a la izquierda de cada uno
y haces el OR logico entre bits
y asi con cada uno.
internamente, c++ hace esto:
- Code:
-
[0][0][0][0][0][0][0][0]
OR
[0][0][0][0][0][0][0][1]
resultado:
[0][0][0][0][0][0][0][1]
ahora, ucHeader es 1(decimal).
por que la represtacion en bits del 1 es
- Code:
-
[0][0][0][0][0][0][0][1]
si no hay nada vivo, ucHeader queda en 0.
ahora preguntas si hay algo muerto, bicho o player:
- Code:
-
if (pTile->m_sDeadOwner != 0)
de nuevo, si es cierto opera asi:
- Code:
-
ucHeader = ucHeader | 0x02;
en este caso, ucHeader era 1.
y 0x02 hexa es 2 decimal. en bits, es: [0][0][0][0][0][0][1][0]
internamente.
- Code:
-
[0][0][0][0][0][0][0][1]
OR
[0][0][0][0][0][0][1][0]
resultado:
[0][0][0][0][0][0][1][1]
ahora ucHeader vale 3 decimal, por que ese resultado en bits es la
representacion del 3 decimal.
si no hay NADA muerto, ucHeader se qda como esta.
ahora pregunta:
- Code:
-
if (pTile->CItem[0] != nullptr)
si hay un item, opera: - Code:
-
ucHeader = ucHeader | 0x04;
0x04 es 4 en decimal
internamente(si suponemos q ucHeader es 3):
- Code:
-
[0][0][0][0][0][0][1][1]
OR
[0][0][0][0][0][1][0][0]
resultado:
[0][0][0][0][0][1][1][1]
el resultado, es 7. por que esa representacion en bits, es del 7 decimal.
si no hay item. no pasa nada.
por ultimo preguntas si hay algun objecto dinamico.
- Code:
-
ucHeader = ucHeader | 0x08;
internamente, si ucHeader era 15.
- Code:
-
[0][0][0][0][0][1][1][1]
OR
[0][0][0][0][1][0][0][0]
resultado:
[0][0][0][0][1][1][1][1]
el resultado es 15 decimal.
si no hay nada. no se hace nada.
copia ucHeader en el buffer de datos.
- Code:
-
*cp = ucHeader;
cp++;
ahora hace 4 preguntas usando ucHeader, en realidad 2 pero bue.
- Code:
-
if ((ucHeader & 0x01) != 0){...}
if ((ucHeader & 0x02) != 0){...}
if (pTile->CItem[0] != nullptr){...}
if (pTile->m_sDynamicObjectType != 0){...}
hubiera sido lo mismo asi:
- Code:
-
if ((ucHeader & 0x01) != 0){...}
if ((ucHeader & 0x02) != 0){...}
if ((ucHeader & 0x04) != 0){...}
if ((ucHeader & 0x08) != 0){...}
te explico 1 solo y fue.
imaginate que ucHeader es 15, y preguntas "15 & 1"
internamente:
- Code:
-
[0][0][0][0][1][1][1][1]
OR
[0][0][0][0][0][0][0][1]
resultado:
[0][0][0][0][0][0][0][1]
el & entre bits es 1, cuando ambos son 1, sino, 0.
como podras ver.
0|1 es 1
1|2 es 3
3|4 es 7
7|8 es 15
el | es conocido como la "suma logica".
y el & es el "producto logico"
los resultados serian
15&1 es 1
15&2 es 2
15&4 es 4
15&8 es 8
1 es != 0, 2 , 4 y 8 tambien.
todos los if son verdaderos
entonces se copia la info de:
algo vivo
algo muerto
un item
un ob din
suponete q algo vivo es un player, 31 bytes vas a copiar al bufer
16 en caso del bicho.
alguien muerto, es lo mismo. 31 o 16.
un item 5.
un ob din, 4.
vos hasta ahora copiaste las coords xy(4bytes), el ucHeader(1byte)
vamos a suponer q las 4 if son verdaderas. son 4 informaciones adicionales.
suponiendo el peor de los casos. vas a tener q copiar 31, 31, 5 y 4.
tenes un total de 4 + 1 + 31 + 31 + 5 + 4 = 76bytes
para una sola posicion de coordenada.
pero suponte el caso de la PANTALLA LLENA.
vas a tener 76bytes para 336 espacios
eso suma 26536.
acordate q pBuffer era un array de 30mil +1.
tiene espacio suficiente.
pero si vos le agregas ese nombre del item.
vas a tener 20 bytes adicionales.
no me acuerdo bien si eran 20 o 22 el array, ponele q eran 20.
el caso es que de 76, te salta a 96.
y 96*336 son 32256.
pero el buffer es de 30mil + 1.
y le queres copiar informacion de mas. vas a provocar un overflow terrible.
TENE CUIDADO CON ESO.