#ifndef _NETWORK_H
#define _NETWORK_H
/*=
Network
2800
**/

// Bases of Raydium's networking API
/**
Raydium supports networking via UDP/IP, providing high level functions
for multiplayer game development.
Raydium servers are limited to 256 clients for now.

You will find in network.c a set of "low level" functions and vars dedicated to
networked games: players names, event callbacks, UDP sockets,
broadcasts, ...
See a few chapters below for higher level functions.

All this is ready to use. As it's not done in the introduction of this
guide, We will explain here some variables defined in common.h.

%%(c)
#define RAYDIUM_NETWORK_PORT          29104
#define RAYDIUM_NETWORK_PACKET_SIZE   230
#define RAYDIUM_NETWORK_TIMEOUT       5
#define RAYDIUM_NETWORK_PACKET_OFFSET 4
#define RAYDIUM_NETWORK_MAX_CLIENTS   8
#define RAYDIUM_NETWORK_MODE_NONE     0
#define RAYDIUM_NETWORK_MODE_CLIENT   1
#define RAYDIUM_NETWORK_MODE_SERVER   2
%%

Here, we can find network port declaration (Raydium will use only one
port, allowing easy port forwarding management, if needed), default timeout
(unit: second), and the three mode possible for a Raydium application.

But there is also two other very important defines: packet size
(unit: byte) and max number of clients.. This is important because
Raydium uses UDP sockets, and UDP sockets required fixed
length packets, and as you need to set packet size as small as possible
(for obvious speed reasons), you must calculate your maximum
information packet size (players position, for example), multiply
it by ##RAYDIUM_NETWORK_MAX_CLIENTS##,and add ##RAYDIUM_NETWORK_PACKET_OFFSET##
wich represent the required header of the packet.

It's more easy than it seems, look:
//
My game will support 8 players.
I will send players state with 3 floats (x,y,z).
My packet size must be: 8*3*sizeof(float)+RAYDIUM_NETWORK_PACKET_OFFSET = 100 bytes.
//
Please, do not change packet offset size, since Raydium will use it
for packet header.

%%(c)
#define RAYDIUM_NETWORK_DATA_OK     1
#define RAYDIUM_NETWORK_DATA_NONE   0
#define RAYDIUM_NETWORK_DATA_ERROR -1
%%

This three defines are used as network functions result:

%%(c)
if(raydium_network_read_flushed(&id,&type,buff)==RAYDIUM_NETWORK_DATA_OK)
{
...
%%

%%(c) #define RAYDIUM_NETWORK_PACKET_BASE 20 %%

In most network functions, you will find a "type" argument, used to
determine packet goal. This type is 8 bits long (256 possible values),
but Raydium is already using some of them. So you can use
##RAYDIUM_NETWORK_PACKET_BASE## as a base for your own types:

%%(c)
#define NORMAL_DATA RAYDIUM_NETWORK_PACKET_BASE
#define BALL_TAKEN (NORMAL_DATA+1)
#define SCORE_INFO (NORMAL_DATA+2)
#define HORN (NORMAL_DATA+3)
...
%%

===Variables:===

Your own player id (0<= id < RAYDIUM_NETWORK_MAX_CLIENTS),
read only: ##int raydium_network_uid;##
Special value "-1" means that you're not connected (see below).

Current network mode (none, client, server),
read only: ##signed char raydium_network_mode;##

Boolean used to determine client state (connected or not), read only:
##signed char raydium_network_client[RAYDIUM_NETWORK_MAX_CLIENTS];##

example:
%%(c)
if(raydium_network_client[4])
    draw_player(4);
%%

Can be used by a server to send data to his clients. Read only:
##struct sockaddr raydium_network_client_addr[RAYDIUM_NETWORK_MAX_CLIENTS];##

Players names, read only:
##char raydium_network_name[RAYDIUM_NETWORK_MAX_CLIENTS][RAYDIUM_MAX_NAME_LEN];##

##OnConnect## and ##OnDisconnect## events (server only):
##void * raydium_network_on_connect;
void * raydium_network_on_disconnect;##

You can place your owns callbacks (##void(int)##) on these events, as in
this example:

%%(c)
void new_client(int client)
{
raydium_log("New player: %s", raydium_network_nameclient);
}

...

int main(int argc, char **argv)
{
...
raydium_network_on_connect=new_client;
...
%%
**/

// Reliablility versus Speed
/**
As explained above, Raydium is using UDP network packets, and as
you may know, UDP is not a reliable protocol, aiming speed before all.
This system is interesting for sending non-sensible data,r_variable(&scale,RAYDIUM_REGISTER_FLOAT,"force_scale");
        raydium_register_variable(&verbose,RAYDIUM_REGISTER_INT,"verbose");
        raydium_register_variable(&force_face,RAYDIUM_REGISTER_INT,"force_face");
        raydium_file_basename(triname,kmzname);
        strcpy(strrchr(triname,'.'),".tri");
        raydium_php_exec("kmz_2_tri.php");
        raydium_register_variable_unregister_last();
        raydium_register_variable_unregister_last();
        raydium_register_variable_unregister_last();
        raydium_register_variable_unregister_last();
        if (strlen(kmzname))
            {
            if (raydium_ode_element_find("test")!=-1)
                raydium_ode_element_delete_name("test",1);

            raydium_ode_object_box_add("test",0,1,RAYDIUM_ODE_AUTODETECT,0,0,RAYDIUM_ODE_STATIC,0,triname);
            mode=follow;
            raydium_gui_hide();
            }
        }
}

void gui_main(){

    raydium_gui_theme_load("theme-raydium2.gui");

    if (raydium_gui_window_isvalid(handle=raydium_gui_window_find("info")))
        raydium_gui_window_delete_name("info");
    if (raydium_gui_window_isvalid(handle=raydium_gui_window_find("Model"))){
        char str[RAYDIUM_MAX_NAME_LEN];
            kmz=raydium_gui_check_read(handle,wkmz,str);
            dae=raydium_gui_check_read(handle,wdae,str);
            raydium_gui_window_delete_name("Model");
    }
    raydium_gui_widget_sizes(0,0,16);
    handle=raydium_gui_window_create("info",15,25,70,40);
    {
    int i=0;
    char * infos[]={"Raydium Sketchup to Raydium Converter",
                    "",
                    "1) Sketchup file->export->3D model .kmz format",
                    "",
                    "2) Select name and click Load",
                    "",
                    "3) Converted .tri file and created tga textures",
                    "Are now in your writable directory",
                    "Note: You can specify an output mesh scale",
                    "",0};
    char tmp[4];
        while(infos[i])
            {
            snprintf(tmp,4,"%2.2d",i);
            raydium_gui_label_create(tmp,handle,50,90-i*10,infos[i],0,0,0);
            i++;
            }

    }
    handle=raydium_gui_window_create("Model",45,75,55,25);

    refresh_list(list);

    raydium_gui_widget_sizes(25,4,18);
    raydium_gui_combo_create("list",handle,47,75,list,0);
    raydium_gui_widget_sizes(0,0,18);
    raydium_gui_label_create("Model Name",handle,25,85,"Model Name :",0,0,0);

    raydium_gui_widget_sizes(4,4,18);
    wkmz=raydium_gui_check_create("edtkmz",handle,55,52,".kmz",kmz);
    wdae=raydium_gui_check_create("edtdae",handle,75,52,".dae",dae);

    raydium_gui_check_create("edtVerbose",handle,65,18," Verbose",0);
    
    raydium_gui_check_create("edtTwoSides",handle,10,34," Force Single Face",force_face);

    raydium_gui_widget_sizes(0,0,18);
    raydium_gui_label_create("Scale",handle,28,25,"Scale :",0,0,0);
    raydium_gui_widget_sizes(8,4,18);
    raydium_gui_edit_create("edtScale",handle,42,17,"1.0");

    raydium_gui_widget_sizes(15,5,18);
    raydium_gui_button_create("btnOk",handle,10,50,"Load",loadclick);

    raydium_gui_show();
}


void display(void)
{

if(raydium_key_last==1027)
    exit(0);

if(raydium_mouse_click==2)
    {
    if (mode==menu)
        {
        raydium_gui_hide();
        mode=follow;
        }
    else
        {
        raydium_init_purgemem();
        gui_main();
        raydium_gui_show();
        mode=menu;
        }
    }
if (kmz!=raydium_gui_check_read(handle,wkmz,NULL)){
    refresh_list(list);
    kmz=raydium_gui_check_read(handle,wkmz,NULL);
    gui_main();
}
if (dae!=raydium_gui_check_read(handle,wdae,NULL)){
    refresh_list(list);
    dae=raydium_gui_check_read(handle,wdae,NULL);
    gui_main();
}

raydium_clear_frame();

if (mode==menu)
    raydium_camera_freemove(RAYDIUM_CAMERA_FREEMOVE_FIXED);
else
    raydium_camera_freemove(RAYDIUM_CAMERA_FREEMOVE_NORMAL);

raydium_ode_draw_all(RAYDIUM_ODE_DRAW_NORMAL);

if(raydium_key[GLUT_KEY_F1])
    raydium_ode_draw_all(RAYDIUM_ODE_DRAW_DEBUG);

//raydium_log("%d",raydium_gui_button_clicked());

raydium_osd_logo("logo.tga");

raydium_rendering_finish();
}



int main(int argc, char **argv)
{
    raydium_init_args(argc,argv);
    raydium_window_create(640,480,RAYDIUM_RENDERING_WINDOW,"Sketchup .kmz to Raydium .tri converter");
    raydium_texture_filter_change(RAYDIUM_TEXTURE_FILTER_TRILINEAR);
    raydium_window_view_perspective(60,0.01,2500);
    raydium_fog_disable();
    raydium_window_view_update();

    raydium_background_color_change(1,0.9,0.7,1);

    raydium_light_enable();
    raydium_light_on(0);
    raydium_light_conf_7f(0,50,150,200,1000000,1,0.9,0.7);

    raydium_gui_theme_load("theme-raydium2.gui");

    gui_main();

    raydium_callback(&display);
    return(0);
}
// EOF