Nilorea Library gui networking api test.
#define WIDTH 640
#define HEIGHT 480
#define HAVE_ALLEGRO 1
{
{
{
memcpy( peer -> position, position, 3 * sizeof( double ) );
peer -> life_time = 10000000 ;
}
else
{
memcpy( peer -> position, position, 3 * sizeof( double ) );
peer -> id = id ;
peer -> life_time = 10000000 ;
}
return TRUE ;
}
{
{
peer -> life_time -= delta_t ;
if( peer -> life_time < 0 )
}
{
if( node && node -> ptr )
{
}
}
return TRUE ;
}
{
{
al_draw_line( peer -> position[ 0 ] - 5, peer -> position[ 1 ], peer -> position[ 0 ] + 5, peer -> position[ 1 ], al_map_rgb( 255, 0, 0 ), 1 );
al_draw_line( peer -> position[ 0 ], peer -> position[ 1 ] + 5, peer -> position[ 0 ], peer -> position[ 1 ] - 5, al_map_rgb( 255, 0, 0 ), 1 );
al_draw_text( font, color, peer -> position[ 0 ] + 10, peer -> position[ 1 ], ALLEGRO_ALIGN_LEFT,
_nstr( textout) );
}
return TRUE ;
}
{
fprintf( stderr, " -v version\n"
" -V log level: LOG_INFO, LOG_NOTICE, LOG_ERR, LOG_DEBUG\n"
" -h help\n"
" -a serveur address name/ip to bind (server mode) (optionnal)\n"
" -s serveur address name/ip to connect (client mode)\n"
" -p port\n"
" -i [v4,v6] ip version (default support both ipv4 and ipv6 )\n" );
}
{
if( argc == 1 )
{
fprintf( stderr, "No arguments given, help:\n" );
exit( 1 );
}
while( (
getoptret = getopt( argc, argv,
"hvs:p:i:V:" ) ) != EOF)
{
{
case 'i' :
if( !strcmp( "v4", optarg ) )
{
}
else if( !strcmp( "v6", optarg ) )
{
}
else
{
}
break;
case 'v' :
fprintf( stderr, "Date de compilation : %s a %s.\n", __DATE__, __TIME__ );
exit( 1 );
case 'V' :
if( !strncmp( "LOG_NULL", optarg, 8 ) )
{
}
else
{
if( !strncmp( "LOG_NOTICE", optarg, 10 ) )
{
}
else
{
if( !strncmp( "LOG_INFO", optarg, 8 ) )
{
}
else
{
if( !strncmp( "LOG_ERR", optarg, 7 ) )
{
}
else
{
if( !strncmp( "LOG_DEBUG", optarg, 9 ) )
{
}
else
{
fprintf( stderr, "%s n'est pas un niveau de log valide.\n", optarg );
exit( -1 );
}
}
}
}
}
break;
case 's' :
(*server) = strdup( optarg );
break ;
case 'p' :
(*port) = strdup( optarg );
break ;
default :
case '?' :
{
if( optopt == 'V' )
{
fprintf( stderr, "\n Missing log level\n" );
}
else if( optopt == 'p' )
{
fprintf( stderr, "\n Missing port\n" );
}
else if( optopt != 's' )
{
fprintf( stderr, "\n Unknow missing option %c\n", optopt );
}
exit( 1 );
}
break ;
case 'h' :
{
exit( 1 );
}
break ;
}
}
}
{
};
int key[ 7 ] = {
false,
false,
false,
false,
false,
false,
false};
int main(
int argc,
char *argv[] )
{
int DONE = 0, QUIT_ASKED = 0,
ALLEGRO_TIMER *network_heartbeat_timer = NULL ;
char *port = NULL ;
ALLEGRO_USTR *chat_line = NULL;
*password = NULL ;
unsigned long ping_time = 0 ;
int mx = 0, my = 0, mouse_b1 = 0, mouse_b2 = 0 ;
int do_draw = 0, do_logic = 0, do_network_update = 0;
N_STR *netw_exchange = NULL ;
int it = -1, ident = -1 ;
ALLEGRO_COLOR white_color = al_map_rgba_f(1, 1, 1, 1);
ALLEGRO_FONT *font = NULL ;
{
exit( -1 );
}
if( !port )
{
exit( -1 );
}
#ifdef __linux__
struct sigaction sa;
sa.sa_handler = netw_sigchld_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1)
{
perror("sigaction");
exit(1);
}
#endif
if (!al_init())
{
n_abort(
"Could not init Allegro.\n");
}
if (!al_install_audio())
{
n_abort(
"Unable to initialize audio addon\n");
}
if (!al_init_acodec_addon())
{
n_abort(
"Unable to initialize acoded addon\n");
}
if (!al_init_image_addon())
{
n_abort(
"Unable to initialize image addon\n");
}
if (!al_init_primitives_addon() )
{
n_abort(
"Unable to initialize primitives addon\n");
}
if( !al_init_font_addon() )
{
n_abort(
"Unable to initialize font addon\n");
}
if( !al_init_ttf_addon() )
{
n_abort(
"Unable to initialize ttf_font addon\n");
}
if( !al_install_keyboard() )
{
n_abort(
"Unable to initialize keyboard handler\n");
}
if( !al_install_mouse())
{
n_abort(
"Unable to initialize mouse handler\n");
}
ALLEGRO_EVENT_QUEUE *event_queue = NULL;
event_queue = al_create_event_queue();
if(!event_queue)
{
fprintf(stderr, "failed to create event_queue!\n");
return -1;
}
network_heartbeat_timer = al_create_timer( 1.0/10.0 );
al_set_new_display_flags( ALLEGRO_OPENGL|ALLEGRO_WINDOWED );
{
n_abort(
"Unable to create display\n");
}
al_set_window_title(
display, argv[ 0 ] );
al_set_new_bitmap_flags( ALLEGRO_VIDEO_BITMAP );
chat_line = al_ustr_new( "" );
font = al_load_font( "2Dumb.ttf", 18, 0 );
if (! font )
{
exit( 1 );
}
al_register_event_source(event_queue, al_get_display_event_source(
display));
al_start_timer( network_heartbeat_timer );
al_register_event_source(event_queue, al_get_timer_event_source(
fps_timer));
al_register_event_source(event_queue, al_get_timer_event_source(
logic_timer));
al_register_event_source(event_queue, al_get_timer_event_source(network_heartbeat_timer));
al_register_event_source(event_queue, al_get_keyboard_event_source());
al_register_event_source(event_queue, al_get_mouse_event_source());
ALLEGRO_BITMAP *scrbuf = al_create_bitmap(
WIDTH,
HEIGHT );
{
}
{
goto exit_client;
}
unsigned long int ident_timeout = 10000000 ;
do
{
if( netw_exchange )
{
{
break ;
}
{
goto exit_client ;
}
}
ident_timeout -= 1000 ;
usleep( 1000 );
}
while( ident_timeout > 0 );
n_log(
LOG_INFO,
"Id Message received, pointer:%p size %d id %d", netw_exchange -> data, netw_exchange -> length, ident );
if( ident == -1 )
{
goto exit_client;
}
QUIT_ASKED = 0 ;
al_clear_keyboard_state( NULL );
al_flush_event_queue( event_queue );
do
{
do
{
ALLEGRO_EVENT ev ;
al_wait_for_event(event_queue, &ev);
if(ev.type == ALLEGRO_EVENT_KEY_DOWN)
{
switch(ev.keyboard.keycode)
{
case ALLEGRO_KEY_UP:
break;
case ALLEGRO_KEY_DOWN:
break;
case ALLEGRO_KEY_LEFT:
break;
case ALLEGRO_KEY_RIGHT:
break;
case ALLEGRO_KEY_ESCAPE:
break;
case ALLEGRO_KEY_SPACE:
break;
case ALLEGRO_KEY_LCTRL:
case ALLEGRO_KEY_RCTRL:
default:
break;
}
}
else if(ev.type == ALLEGRO_EVENT_KEY_UP)
{
switch(ev.keyboard.keycode)
{
case ALLEGRO_KEY_UP:
break;
case ALLEGRO_KEY_DOWN:
break;
case ALLEGRO_KEY_LEFT:
break;
case ALLEGRO_KEY_RIGHT:
break;
case ALLEGRO_KEY_ESCAPE:
break;
case ALLEGRO_KEY_SPACE:
break;
case ALLEGRO_KEY_LCTRL:
case ALLEGRO_KEY_RCTRL:
default:
break;
}
}
else if( ev.keyboard.keycode == ALLEGRO_KEY_ENTER )
{
al_ustr_trim_ws( chat_line ) ;
al_ustr_to_buffer( chat_line, txtmsg -> data, txtmsg -> length );
}
else if( ev.type == ALLEGRO_EVENT_TIMER )
{
if( al_get_timer_event_source(
fps_timer ) == ev.any.source )
{
do_draw = 1 ;
}
else if( al_get_timer_event_source(
logic_timer ) == ev.any.source )
{
do_logic = 1;
}
else if( al_get_timer_event_source( network_heartbeat_timer ) == ev.any.source )
{
do_network_update = 1;
}
}
else if( ev.type == ALLEGRO_EVENT_MOUSE_AXES )
{
mx = ev.mouse.x;
my = ev.mouse.y;
}
else if( ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN )
{
if( ev.mouse.button == 1 )
mouse_b1 = 1 ;
if( ev.mouse.button == 2 )
mouse_b2 = 1 ;
}
else if( ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP )
{
if( ev.mouse.button == 1 )
mouse_b1 = 0 ;
if( ev.mouse.button == 2 )
mouse_b2 = 0 ;
}
else if( ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE )
{
}
else if( ev.type == ALLEGRO_EVENT_DISPLAY_SWITCH_IN || ev.type == ALLEGRO_EVENT_DISPLAY_SWITCH_OUT )
{
al_clear_keyboard_state(
display );
al_flush_event_queue( event_queue );
}
else
{
}
}
while( !al_is_event_queue_empty( event_queue) );
if( do_logic == 1 )
{
if( netmsg )
{
int type = -1 ;
switch( type )
{
break ;
break ;
{
double pos[ 3 ];
double spe[ 3 ];
int id = -1, timestamp = -1 ;
netw_get_position( netmsg, &
id, &pos[ 0 ],&pos[ 1 ],&pos[ 2 ], &spe[ 0 ], &spe[ 1 ], &spe[ 2 ], ×tamp );
}
break;
{
int id = -1, color = -1 ;
N_STR *name = NULL, *txt = NULL, *chan = NULL ;
n_log(
LOG_INFO,
"Received chat from %s:%s:%s (id: %d , color:%d)", name, chan, txt,
id, color );
}
break;
break;
break;
break ;
default:
break ;
}
}
ping_time += 1.0 / 60.0 ;
{
if( QUIT_ASKED != 1 )
{
QUIT_ASKED = 1 ;
}
}
do_logic = 0 ;
}
if( do_draw == 1 )
{
int w = al_get_display_width(
display );
int h = al_get_display_height(
display );
al_set_target_bitmap( scrbuf );
al_clear_to_color( al_map_rgba( 0, 0, 0, 255 ) );
al_set_target_bitmap( al_get_backbuffer(
display ) );
al_clear_to_color( al_map_rgba( 0, 0, 0, 255 ) );
al_draw_bitmap( scrbuf, 0, 0, 0 );
al_draw_ustr( font, white_color, 0,
HEIGHT - 20, ALLEGRO_ALIGN_LEFT, chat_line );
al_flip_display();
do_draw = 0 ;
}
if( do_network_update == 1 )
{
do_network_update = 0 ;
}
}
exit_client:
return 0;
}
void process_args(int argc, char **argv)
ALLEGRO_TIMER * fps_timer
ALLEGRO_TIMER * logic_timer
ALLEGRO_DISPLAY * display
long int life_time
current life time, updated when receiving a position from a peer.
int draw_peers(HASH_TABLE *peer_table, ALLEGRO_FONT *font, ALLEGRO_COLOR color)
double position[3]
last received object position
int update_peer(HASH_TABLE *peer_table, int id, double position[3])
int manage_peers(HASH_TABLE *peer_table, int delta_t)
a simple structure to hold objects positions / timeouts
static pthread_t netw_thr
NETWORK * netw
Network for server mode, accepting incomming.
int get_keyboard(ALLEGRO_USTR *str, ALLEGRO_EVENT event)
update a keyboard buffer from an event
#define Malloc(__ptr, __struct, __size)
Malloc Handler to get errors and set to 0.
#define __n_assert(__ptr, __ret)
macro to assert things
#define _str(__PTR)
define true
void n_abort(char const *format,...)
abort program with a text
#define _nstr(__PTR)
N_STR or "NULL" string for logging purposes.
int ht_put_ptr_ex(HASH_TABLE *table, unsigned long int hash_value, void *val, void(*destructor)(void *ptr))
put a pointer value with given key in the targeted hash table (HASH_CLASSIC only)
#define ht_foreach(__ITEM_, __HASH_)
ForEach macro helper (classic / old)
int ht_remove_ex(HASH_TABLE *table, unsigned long int hash_value)
Remove a key from a hash table (HASH_CLASSIC only)
HASH_TABLE * new_ht(unsigned long int size)
Create a hash table with the given size.
int ht_get_ptr_ex(HASH_TABLE *table, unsigned long int hash_value, void **val)
Retrieve a pointer value in the hash table, at the given key.
#define hash_val(node, type)
Cast a HASH_NODE element.
structure of a hash table
int list_push(LIST *list, void *ptr, void(*destructor)(void *ptr))
Add a pointer to the end of the list.
#define list_foreach(__ITEM_, __LIST_)
ForEach macro helper.
LIST * new_generic_list(int max_items)
Initialiaze a generic list container to max_items pointers.
Structure of a generic LIST container.
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
#define LOG_DEBUG
debug-level messages
#define LOG_ERR
error conditions
void set_log_level(const int log_level)
Set the global log level value ( static int LOG_LEVEL )
#define LOG_NOTICE
normal but significant condition
#define LOG_NULL
no log output
#define LOG_INFO
informational
#define free_nstr(__ptr)
free a N_STR structure and set the pointer to NULL
#define nstrprintf(__nstr_var,...)
Macro to quickly allocate and sprintf to N_STR *.
N_STR * char_to_nstr(const char *src)
Convert a char into a N_STR, short version.
N_STR * new_nstr(NSTRBYTE size)
create a new N_STR string
A box including a string and his lenght.
#define NETMSG_IDENT_REQUEST
Network Message is identification request: (int)type , (int)id , (N_STR *)name , (N_STR *)password.
int netw_get_position(N_STR *msg, int *id, double *X, double *Y, double *vx, double *vy, double *acc_x, double *acc_y, int *time_stamp)
Retrieves position from netwmsg.
#define NETMSG_PING_REQUEST
Network Message is ping request: (int)type , (int)id_from , (int)id_to.
#define NETMSG_IDENT_REPLY_NOK
Network Message is identification reply NON OK: (int)type , (int)id , (N_STR *)name ,...
#define NETMSG_STRING
Network Message is string: (int)type , (int)id , (N_STR *)name , (N_STR *)chan , (N_STR *)text ,...
#define NETMSG_PING_REPLY
Network Message is ping reply: (int)type , (int)id_from , (int)id_to.
#define NETMSG_QUIT
Network asking for exit.
#define NETMSG_POSITION
Network Message position: (int)type , (int)id , (int)X , (int)Y , (int)x_shift , (int)y_shift ,...
int netw_msg_get_type(N_STR *msg)
Get the type of message without killing the first number. Use with netw_get_XXX.
#define NETMSG_BOX
Network Message is box retrieving reply: (int x , int y , int z , N_STR *data )
#define NETMSG_GET_BOX
Network Message is box retrieve: int x , int y , int z.
#define NETMSG_IDENT_REPLY_OK
Network Message is identification reply OK : (int)type , (int)id , (N_STR *)name ,...
int netw_get_string(N_STR *msg, int *id, N_STR **name, N_STR **chan, N_STR **txt, int *color)
Retrieves string from netwmsg.
int netw_get_ident(N_STR *msg, int *type, int *ident, N_STR **name, N_STR **passwd)
Retrieves identification from netwmsg.
N_STR * netmsg_make_string_msg(int id_from, int id_to, N_STR *name, N_STR *chan, N_STR *txt, int color)
make a network NETMSG_STRING message with given parameters
N_STR * netw_get_msg(NETWORK *netw)
Get a message from aimed NETWORK.
int netw_add_msg(NETWORK *netw, N_STR *msg)
Add a message to send in aimed NETWORK.
#define NETWORK_IPV6
Flag to force IPV6
int netw_start_thr_engine(NETWORK *netw)
Start the NETWORK netw Threaded Engine.
#define NETWORK_IPV4
Flag to force IPV4
int netw_wait_close(NETWORK **netw)
Wait for peer closing a specified Network, destroy queues, free the structure.
#define NETWORK_IPALL
Flag for auto detection by OS of ip version to use.
int netw_send_quit(NETWORK *netw)
Add a formatted NETMSG_QUIT message to the specified network.
int netw_connect(NETWORK **netw, char *host, char *port, int ip_version)
Use this to connect a NETWORK to any listening one, unrestricted send/recv lists.
int netw_send_ident(NETWORK *netw, int type, int id, N_STR *name, N_STR *passwd)
Add a formatted NETWMSG_IDENT message to the specified network.
int netw_send_position(NETWORK *netw, int id, double X, double Y, double vx, double vy, double acc_x, double acc_y, int time_stamp)
Add a formatted NETWMSG_IDENT message to the specified network.
Common headers and low-level hugly functions & define.
Hash functions and table.
List structures and definitions.
Network messages , serialization tools.
N_STR and string function declaration.