// Programa basico de conexion de fenix bidireccional
// Para dos jugaodres y listo para implemarlo como quieras
// Por Eclipseok
// Con sistema de escritura creado por Xwolf
// Usando la libreria Net.dll
program conex;
import "net.dll";//importa la libreria
const todato=1;//Indica total de datos que guardan datos y datos1
global
string texto; // Guarda el texto creado con Teclado
string KeyBuf; // Bufer de escritura de Teclado
int datos[todato]; //Paquete para envio
int datos1[todato]; //Paquete para recepcion
int puerto=1200; // Almacena el puerto de conexion por defecto el 1200
int option; // Controla la salida del primer menu de opciones
int mata_tex;//Si es igual a 1 mata los procesos de teclado y todos los relaccionados con el desde dentro
int posi_pro=0;// Controlador de avertura de procesos
int recibido; //Cantidad de datos recibidos
int envi,reci;//variables de tados para enviar y para recibir

begin
 set_mode(400,300,16);
 graph_mode=mode_16bits;
 net_init(); //Inicializamos la libreria net
 load_fpg("p.fpg");
 write(0,5,5,0,"1. Servidor");
 write(0,5,15,0,"2. Cliente");
 write(0,5,25,0,"3. Salir");

 while (option==0)
  if (key(_1)) option=1;server();end //Vamos al proceso server
  if (key(_2)) option=1;posi_pro=1;end //Salimos del menu y vamos al bucler principal con la opcion 1
  if (key(_3)) option=1;net_quit();exit();end; // Cerramos el programa
  frame;
 end;

 // Bucler principal y controlador del programa
 // Desde aqui se controlan todos los procesos
 // para menus, fases, pantallas o lo que quieras
 // El controlador es posi_pro
 // Tambien mantiene la occion de salir con esc todo el tiempo
 loop
 if(key(_esc)==1)net_tcp_close(0);net_quit();exit();end // Si pulsamos esc salimos del programa
  if (posi_pro==1) posi_pro=0;
   while(scan_code<>0) //Asegura que no se entrara con una tecla pulsada
   frame;
   end
  menu1();//Llama al proceso menu1
  end
 if (posi_pro==3) client(texto);posi_pro=0;end //Llama al proceso client()
  if (posi_pro==2) //Llama al proceso jugador(), jugador1(), depura() y pone los textos de pantalla
  delete_text(0);
  write(0,10,60,0,"Jugador de la maquina activo");
  write(0,10,50,0,"Jugador esterior activo");
  write_var(0,100,10,0,datos1[0]);
  write(0,10,10,0,"Recive x");
  write_var(0,100,20,0,datos1[1]);
  write(0,10,20,0,"Recive y");
  write_var(0,100,90,0,datos[0]);
  write(0,10,90,0,"Envia x");
  write_var(0,100,100,0,datos[1]);
  write(0,10,100,0,"Envia y");
  jugador();jugador2();depura();posi_pro=0;
  end

 frame;
 end
end //Fin programa principal

//Este proceso se activa si eres el servidor para crear la conexion
//Si eres el cliente no se llega a leer nunca
process Server();
 private
 int se=-1; // Bariable para asegurar la conexion
begin
delete_text(0);
net_resolvehost(0,0,puerto); // El host es 0 pq es para server
net_tcp_open(0);//Abre la conexion
write(0,10,10,3,"Server");
write(0,10,40,0,"Esperando conexion....");
  repeat //Repite mientras no haya conexion entrante
  se=net_tcp_accept(0);
  frame;
  until(se==0)
posi_pro=2; // Activa la posicion 2 del proceso principal
 loop
  if(net_tcp_recv(0,&reci,sizeof(reci))>0);//Se encarga de la recepcion de datos
  recibido++;
  end
 net_tcp_send(0,&envi,sizeof(envi));//Se encarga del envio de datos
 frame;
 end
end // Fin proceso server


//Igual que el proceso server() pero si eres el cliente
process client(string ip_conex);
private
int seguco,inten;
begin
delete_text(0);
write(0,10,10,0,"Conectando...");
write(0,10,20,0,"intentos: ");
write_var(0,65,20,0,inten);
net_resolvehost(0,ip_conex,puerto);//Prepara la conexion
 	 repeat //Se encarga de intentar conectar la veces que haga falta
 	 seguco=net_tcp_open(0);//Abre la conexion
 	 inten++;
 	 frame;
 	 until(seguco==0);
delete_text(0);
net_tcp_send(0,&envi,sizeof(envi));//Envia datos por la conexion abierta
write(0,10,10,0,"Asegurando conexion....");
  repeat //Comprueba que hay envio de datos del otro lado
  frame;
  until(net_tcp_recv(0,&reci,sizeof(reci))>0);
posi_pro=2; // Activa la posicion 2 del proceso principal
delete_text(0);
recibido++;
  loop
  net_tcp_send(0,&envi,sizeof(envi));//se encarga del envio de datos
   if(net_tcp_recv(0,&reci,sizeof(reci))>0);//se encarga de la recepcion de datos
   recibido++;
   end
  frame;
  end
end  //Fin del proceso cliente

//Este proceso es el encargado de recoger la Ip del cliente y llamar al proceso client()
process menu1();
begin
 delete_text(0);
 write(0,10,20,0,"Escriba la IP del host : ");
 mata_tex=0;teclado(10,30);//Esta linea llama a las funciones de escritura, mata_tex deve ser 0
 loop
  if(mata_tex==1)//Si se a matado el teclado
  posi_pro=3;//cambia el estado en el bucler principal
  break;//y mata este proceso
  end
 frame;
 end
end //Fin proceso menu1

// Sistema emcriptador desemcriptador de datos para envio y recepcion
// Puesto que la forma mas fiable y creo que la unica de enviar
// datos es, si son numericos y lo mas rapido es que sea de una
// sola vez, hay que hacer esto o algo parecido para apañarselas.
process depura();
private
string te1,te2,te3,te4,dam,dam1,tat,tat1,tat2,tat3;
int da1,da2,dat,dat2;
begin

 loop

   //Emcripta
   da1=len(datos[0]);//tamaño de datos
   da2=len(datos[1]);//tamaño de datos
   te1=itoa(datos[0]);//convierte datos a cadena
   te2=itoa(datos[1]);//convierte datos a cadena
   te3=itoa(da1);//convierte datos a cadena
   te4=itoa(da2);//convierte datos a cadena
   dam=te3+te1+te4+te2;//monta la cadena para envio
   envi=atoi(dam);//vuelve a convertir la cadena en datos para mandarlos


   //Desemcripta
   dam1=itoa(reci);//Convertimos los datos en una cadena
   tat=substr(dam1,0,1);//Extraemos el tamaño del primer dato en texto
   dat=atoi(tat);//Lo cambiamos a numerico
   tat1=substr(dam1,1,dat);//Extraemos el primer dato completo
   datos1[0]=atoi(tat1);//Lo cambiamos a numerico y listo el 1
   tat2=substr(dam1,dat,dat+1);//Extremos el tamaño del segundo dato
   dat2=atoi(tat2);//Lo cambiamos a numerico
   tat3=substr(dam1,dat+2,dat+dat2);//Extraemos el segundo dato
   datos1[1]=atoi(tat3);//Lo cambiamos a numerico y listo el 2

 frame;
 end
end //Fin del sistema de encriptacion desemcriptacion


// Proceso para jugador del sistema
process jugador();

begin

 loop
 datos[0]=mouse.x;
 datos[1]=mouse.y;
 x=mouse.x;
 y=mouse.y;
  graph=1;
 frame;
 end
end //fin del proceso de jugador

// proceso para jugador de fuera
process jugador2();

begin

 loop
 x=datos1[0];
 y=datos1[1];

 graph=2;
 frame;
 end
end //fin del proceso de jugador2




process Teclado(xtex,ytex); // Usa el teclado de la fórma típica algoritmo usado en FenXEdit ][

Private string zona,int i;
begin

// lanzamos el demonio del teclado (el manager)
Keyer();
// Texto

Write_var(0,xtex,ytex,0,Zona); //linea de escritura

loop
 while ((i=NextKey())<>0) // asigna y compara a la vez // para ver los efectos uno a uno cambiar "while" por "if"
  switch (i) // tratamiento de los caracteres recibidos, ejemplo
   Case 8: // si es la tecla borrar ...
    zona=substr(zona,0,-2);// ...se borra
   end;
   case 32..255: // si es caracter imprimible ...
    zona+=chr(i); // ... se añade
   end;
  end;
 end;
 texto=zona;
 //if (mata_tex==1)break;end;
 if(key(28)==1)//si pulsamos return matamos Teclado
  mata_tex=1; //mata el proceso teclado y todos los relaccionados con èl
  break; //mata este proceso
  end

frame;
end;
end;
// demonio de teclado
Process Keyer();
private aascii;
begin
loop
 // asignacion virtual de ascii para incorporar las letras que ignora
 if (mata_tex==1)break;end;
 If (key(_del))  Ascii=7;end;
 If (key(_up))   Ascii=14;end;
 If (key(_Down)) Ascii=15;end;
 If (key(_Right))Ascii=16;end;
 If (key(_Left)) Ascii=17;end;
 if (key(_Home)) Ascii=18;end;
 if (key(_end))  Ascii=19;end;
 // tratamiento de la variable ascii
 if (ascii>0) // si se pulsa tecla ...
  if (aascii<>ascii or y<0) // ... y el caracter es distinto o se puede repetir ...
   KeyBuf+=chr(ascii);  // ... añade al buffer
   If (ascii==aascii) // si la tecla es la anterior ...
    y=1; // ... se espera poco (al mantener pulsada)
   else // sino ...
    y=10; // se espera mas
   end;
  end;
 end;
 aascii=ascii;y--; // actualizacion de tecla anterior y de tiempo de espera
 frame;
end;
end;


// Proceso que funciona como ascii pero despues de pasar por el manajer
Process NextKey()
private i;
begin
 if (len(Keybuf)==0) // Si no hay tecla en espera ...
  Return(0);     // ... retorna 0 y sale
 end;
 i=asc(KeyBuf[0]); // coje el siguiente valor
 // quita este valor del buffer
 if (Len(keybuf)==1) // si es el ultimo substr no funciona ...
  Keybuf=""; // ... asi que la limpia
 else // sino ...
  Keybuf=substr(Keybuf,1,-1); // quita solo la primera letra
 end;
 Return(i); // retorna i (la tecla)
end;
