18#include <allegro5/allegro.h>
19#include <allegro5/allegro_audio.h>
20#include <allegro5/allegro_acodec.h>
21#include <allegro5/allegro_font.h>
22#include <allegro5/allegro_image.h>
23#include <allegro5/allegro_primitives.h>
24#include <allegro5/allegro_ttf.h>
28 fprintf( stderr,
" -v version\n"
29 " -V log level: LOG_INFO, LOG_NOTICE, LOG_ERR, LOG_DEBUG\n"
31 " -a serveur address name/ip to bind (server mode)\n"
33 " -i [v4,v6] ip version (default support both ipv4 and ipv6 )\n" );
54 fprintf( stderr,
"No arguments given, help:\n" );
58 while( (
getoptret = getopt( argc, argv,
"hva:p:i:V:" ) ) != EOF)
63 if( !strcmp(
"v4", optarg ) )
68 else if( !strcmp(
"v6", optarg ) )
79 fprintf( stderr,
"Date de compilation : %s a %s.\n", __DATE__, __TIME__ );
82 if( !strncmp(
"LOG_NULL", optarg, 8 ) )
88 if( !strncmp(
"LOG_NOTICE", optarg, 10 ) )
94 if( !strncmp(
"LOG_INFO", optarg, 8 ) )
100 if( !strncmp(
"LOG_ERR", optarg, 7 ) )
106 if( !strncmp(
"LOG_DEBUG", optarg, 9 ) )
112 fprintf( stderr,
"%s n'est pas un niveau de log valide.\n", optarg );
121 (*bind_addr) = strdup( optarg );
124 (*port) = strdup( optarg );
130 fprintf( stderr,
"\n Missing log level\n" );
132 else if( optopt ==
'p' )
134 fprintf( stderr,
"\n Missing port\n" );
136 else if( optopt !=
's' )
138 fprintf( stderr,
"\n Unknow missing option %c\n", optopt );
158 LIST *netw_to_close = NULL ;
166 N_STR *netw_exchange = NULL ;
169 int thr_engine_status = -1 ;
191 int id_from = -1, id_to = -1, time = -1, type = -1 ;
192 netw_get_ping( netw_exchange, &id_from, &id_to, &time, &type );
210 N_STR *name = NULL, *passwd = NULL ;
211 int d_it = 0, ident = 0 ;
230 unlock( netw_pool -> rwlock );
233 LIST_NODE *node = netw_to_close -> start ;
234 while( node && node -> ptr )
247 node = node -> next ;
256int main(
int argc,
char *argv[] )
258 ALLEGRO_DISPLAY *
display = NULL ;
265 ALLEGRO_BITMAP *
scr_buf = NULL ;
269 ALLEGRO_TIMER *network_heartbeat_timer = NULL ;
274 char *bind_addr = NULL,
288 sa.sa_handler = netw_sigchld_handler;
289 sigemptyset(&sa.sa_mask);
290 sa.sa_flags = SA_RESTART;
291 if (sigaction(SIGCHLD, &sa, NULL) == -1)
308 n_log(
LOG_ERR,
"Fatal error with network initialization" );
316 n_abort(
"Could not init Allegro.\n");
318 if (!al_install_audio())
320 n_abort(
"Unable to initialize audio addon\n");
322 if (!al_init_acodec_addon())
324 n_abort(
"Unable to initialize acoded addon\n");
326 if (!al_init_image_addon())
328 n_abort(
"Unable to initialize image addon\n");
330 if (!al_init_primitives_addon() )
332 n_abort(
"Unable to initialize primitives addon\n");
334 if( !al_init_font_addon() )
336 n_abort(
"Unable to initialize font addon\n");
338 if( !al_init_ttf_addon() )
340 n_abort(
"Unable to initialize ttf_font addon\n");
342 if( !al_install_keyboard() )
344 n_abort(
"Unable to initialize keyboard handler\n");
346 if( !al_install_mouse())
348 n_abort(
"Unable to initialize mouse handler\n");
350 ALLEGRO_EVENT_QUEUE *event_queue = NULL;
352 event_queue = al_create_event_queue();
355 fprintf(stderr,
"failed to create event_queue!\n");
362 network_heartbeat_timer = al_create_timer( 1.0/10.0 );
364 al_set_new_display_flags( ALLEGRO_OPENGL|ALLEGRO_WINDOWED );
368 n_abort(
"Unable to create display\n");
370 al_set_window_title(
display, argv[ 0 ] );
372 al_set_new_bitmap_flags( ALLEGRO_VIDEO_BITMAP );
382 int key[ 7 ] = {
false,
false,
false,
false,
false,
false,
false};
384 al_register_event_source(event_queue, al_get_display_event_source(
display));
385 al_register_event_source(event_queue, al_get_keyboard_event_source());
386 al_register_event_source(event_queue, al_get_mouse_event_source());
391 al_register_event_source(event_queue, al_get_timer_event_source(
fps_timer));
392 al_register_event_source(event_queue, al_get_timer_event_source(
logic_timer));
393 al_register_event_source(event_queue, al_get_timer_event_source(
logic_timer));
395 ALLEGRO_BITMAP *scrbuf = al_create_bitmap(
WIDTH,
HEIGHT );
396 ALLEGRO_COLOR white_color = al_map_rgba_f(1, 1, 1, 1);
397 ALLEGRO_FONT *font = NULL ;
398 font = al_load_font(
"2Dumb.ttf", 18, 0 );
407 int mx = 0, my = 0, mouse_b1 = 0, mouse_b2 = 0 ;
408 int do_draw = 0, do_logic = 0, do_network = 0 ;
410 al_clear_keyboard_state( NULL );
411 al_flush_event_queue( event_queue );
419 al_wait_for_event(event_queue, &ev);
421 if(ev.type == ALLEGRO_EVENT_KEY_DOWN)
423 switch(ev.keyboard.keycode)
428 case ALLEGRO_KEY_DOWN:
431 case ALLEGRO_KEY_LEFT:
434 case ALLEGRO_KEY_RIGHT:
437 case ALLEGRO_KEY_ESCAPE:
440 case ALLEGRO_KEY_SPACE:
443 case ALLEGRO_KEY_LCTRL:
444 case ALLEGRO_KEY_RCTRL:
450 else if(ev.type == ALLEGRO_EVENT_KEY_UP)
452 switch(ev.keyboard.keycode)
457 case ALLEGRO_KEY_DOWN:
460 case ALLEGRO_KEY_LEFT:
463 case ALLEGRO_KEY_RIGHT:
466 case ALLEGRO_KEY_ESCAPE:
469 case ALLEGRO_KEY_SPACE:
472 case ALLEGRO_KEY_LCTRL:
473 case ALLEGRO_KEY_RCTRL:
479 else if( ev.type == ALLEGRO_EVENT_TIMER )
481 if( al_get_timer_event_source(
fps_timer ) == ev.any.source )
485 else if( al_get_timer_event_source(
logic_timer ) == ev.any.source )
489 else if( al_get_timer_event_source( network_heartbeat_timer ) == ev.any.source )
494 else if( ev.type == ALLEGRO_EVENT_MOUSE_AXES )
499 else if( ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN )
501 if( ev.mouse.button == 1 )
503 if( ev.mouse.button == 2 )
506 else if( ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP )
508 if( ev.mouse.button == 1 )
510 if( ev.mouse.button == 2 )
513 else if( ev.type == ALLEGRO_EVENT_DISPLAY_SWITCH_IN || ev.type == ALLEGRO_EVENT_DISPLAY_SWITCH_OUT )
515 al_clear_keyboard_state(
display );
516 al_flush_event_queue( event_queue );
524 while( !al_is_event_queue_empty( event_queue) );
570 if( do_network == 1 )
579 al_acknowledge_resize(
display );
580 int w = al_get_display_width(
display );
581 int h = al_get_display_height(
display );
583 al_set_target_bitmap( scrbuf );
584 al_clear_to_color( al_map_rgba( 0, 0, 0, 255 ) );
586 al_set_target_bitmap( al_get_backbuffer(
display ) );
588 al_clear_to_color( al_map_rgba( 0, 0, 0, 255 ) );
589 al_draw_bitmap( scrbuf, 0, 0, 0 );
592 al_draw_line( mx - 5, my, mx + 5, my, al_map_rgb( 255, 0, 0 ), 1 );
593 al_draw_line( mx, my + 5, mx, my - 5, al_map_rgb( 255, 0, 0 ), 1 );
596 N_STR *textout = NULL ;
598 al_draw_text( font, white_color, 5, 5, ALLEGRO_ALIGN_LEFT,
_nstr( textout ) );
void process_args(int argc, char **argv)
ALLEGRO_TIMER * fps_timer
ALLEGRO_TIMER * logic_timer
ALLEGRO_DISPLAY * display
int process_clients(NETWORK_POOL *netw_pool, N_USERLIST *userlist)
NETWORK * netw
Network for server mode, accepting incomming.
#define __n_assert(__ptr, __ret)
macro to assert things
#define _str(__PTR)
define true
#define unlock(__rwlock_mutex)
Macro for releasing read/write lock a rwlock mutex.
void n_abort(char const *format,...)
abort program with a text
#define read_lock(__rwlock_mutex)
Macro for acquiring a read lock on a rwlock mutex.
#define _nstr(__PTR)
N_STR or "NULL" string for logging purposes.
#define HASH_VAL(node, type)
Cast a HASH_NODE element.
#define HT_FOREACH(__ITEM_, __HASH_,...)
ForEach macro helper.
int list_push(LIST *list, void *ptr, void(*destructor)(void *ptr))
Add a pointer to the end of the list.
int list_destroy(LIST **list)
Empty and Free a list container.
LIST * new_generic_list(int max_items)
Initialiaze a generic list container to max_items pointers.
Structure of a generic LIST container.
Structure of a generic list node.
#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 *.
A box including a string and his lenght.
int userlist_del_user(N_USERLIST *ulist, int id)
delete an user from the list
int userlist_add_msg_to(N_USERLIST *ulist, N_STR *msg, int id)
add a N_STR *message to user list (USERLIST_ONE)
N_USERLIST * userlist_new(int max)
create a new N_USERLIST user list with 'max' users
int userlist_add_msg_to_all(N_USERLIST *ulist, N_STR *msg)
add a N_STR *message to user list (USERLIST_ALL)
int userlist_send_waiting_msgs(N_USERLIST *ulist)
send all waiting messages ofr each user of the lsit
int userlist_add_user(N_USERLIST *ulist, NETWORK *netw)
add an user to the list
#define NETMSG_IDENT_REQUEST
Network Message is identification request: (int)type , (int)id , (N_STR *)name , (N_STR *)password.
#define NETMSG_PING_REQUEST
Network Message is ping request: (int)type , (int)id_from , (int)id_to.
#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.
int netw_get_ping(N_STR *msg, int *type, int *from, int *to, int *time)
Retrieves a ping travel elapsed time.
#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_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 ,...
N_STR * netmsg_make_ping(int type, int id_from, int id_to, int time)
Make a ping message to send to a network.
int netw_get_ident(N_STR *msg, int *type, int *ident, N_STR **name, N_STR **passwd)
Retrieves identification from netwmsg.
int netw_pool_broadcast(NETWORK_POOL *netw_pool, NETWORK *from, N_STR *net_msg)
add net_msg to all network in netork pool
N_STR * netw_get_msg(NETWORK *netw)
Get a message from aimed NETWORK.
int netw_pool_nbclients(NETWORK_POOL *netw_pool)
return the number of networks in netw_pool
#define NETWORK_IPV6
Flag to force IPV6
int netw_set_user_id(NETWORK *netw, int id)
associate an id and a network
int netw_make_listening(NETWORK **netw, char *addr, char *port, int nbpending, int ip_version)
Make a NETWORK be a Listening network.
int netw_start_thr_engine(NETWORK *netw)
Start the NETWORK netw Threaded Engine.
#define NETWORK_IPV4
Flag to force IPV4
NETWORK * netw_accept_from_ex(NETWORK *from, int send_list_limit, int recv_list_limit, int non_blocking, int *retval)
make a normal 'accept' .
#define NETWORK_IPALL
Flag for auto detection by OS of ip version to use.
int netw_close(NETWORK **netw)
Closing a specified Network, destroy queues, free the structure.
int netw_send_quit(NETWORK *netw)
Add a formatted NETMSG_QUIT message to the specified network.
int netw_send_ping(NETWORK *netw, int type, int id_from, int id_to, int time)
Add a ping reply to the network.
NETWORK_POOL * netw_new_pool(int nb_min_element)
return a new network pool of nb_min_element
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_pool_add(NETWORK_POOL *netw_pool, NETWORK *netw)
add a NETWORK *netw to a NETWORK_POOL *pool
int netw_get_state(NETWORK *netw, int *state, int *thr_engine_status)
Get the state of a network.
@ NETW_THR_ENGINE_STARTED
structure of a network pool
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.
USERS handling for tiny game apps.