From b424a1656773eb39f0d9acb12c55075e01589e30 Mon Sep 17 00:00:00 2001 From: xtreme8000 Date: Mon, 30 Jul 2018 22:34:07 +0200 Subject: [PATCH] See desc * remove duplicates in weapon.c * add log.c to library list * locally ping servers in off-work-thread * remove shotgun reload bug, caused by too early PacketWeaponReload * pull down block and show tools when picking a color --- README.md | 2 + src/common.h | 1 + src/hud.c | 70 +++++++++++++++++++------ src/list.c | 5 +- src/main.c | 13 ++--- src/network.c | 25 ++++++++- src/network.h | 7 +-- src/ping.c | 89 +++++++++++++++++++++++++++++++ src/ping.h | 13 +++++ src/player.c | 2 +- src/weapon.c | 142 +++++++++++++++++++++++--------------------------- src/weapon.h | 3 +- 12 files changed, 264 insertions(+), 108 deletions(-) create mode 100644 src/ping.c create mode 100644 src/ping.h diff --git a/README.md b/README.md index b056404..f3073a5 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,8 @@ This means: | `parson.c` and `parson.h` | → | `src/parson.c` and `src/parson.h` | | `http.h` | → | `src/http.h` | | `stb_truetype.h` | → | `src/stb_truetype.h` | +| `log.h` and `log.c` | → | `src/log.h` and `src/log.c` | + Because state of copyright of 0.75 assets is unknown, you will need to get them *[here](http://aos.party/bsresources.zip)*. Unzip the file and extract all contents to `resources/` manually. diff --git a/src/common.h b/src/common.h index 247c028..b3da441 100644 --- a/src/common.h +++ b/src/common.h @@ -110,6 +110,7 @@ #define MOUSE_SENSITIVITY 0.002F +#include "ping.h" #include "glx.h" #include "list.h" #include "window.h" diff --git a/src/hud.c b/src/hud.c index 6bd3165..5d28b84 100644 --- a/src/hud.c +++ b/src/hud.c @@ -1285,7 +1285,11 @@ static void hud_ingame_keyboard(int key, int action, int mods, int internal) { screen_current = SCREEN_NONE; } } - if(key==WINDOW_KEY_PICKCOLOR) { + if(key==WINDOW_KEY_PICKCOLOR && players[local_player_id].held_item==TOOL_BLOCK) { + players[local_player_id].item_disabled = window_time(); + players[local_player_id].items_show_start = window_time(); + players[local_player_id].items_show = 1; + int* pos = camera_terrain_pick(1); if(pos!=NULL) { players[local_player_id].block.packed = map_get(pos[0],pos[1],pos[2]); @@ -1356,30 +1360,35 @@ static struct serverlist_entry* serverlist; static float serverlist_scroll; static int serverlist_hover; static int serverlist_is_outdated; +static pthread_mutex_t serverlist_lock; static void hud_serverlist_init() { - network_disconnect(); + network_disconnect(); - window_mousemode(WINDOW_CURSOR_ENABLED); + window_mousemode(WINDOW_CURSOR_ENABLED); - player_count = 0; - server_count = 0; - serverlist_scroll = 0.0F; - serverlist_hover = -1; - request_serverlist = http_get("http://services.buildandshoot.com/serverlist.json",NULL); - request_version = http_get("http://aos.party/bs/version/",NULL); + player_count = 0; + server_count = 0; + serverlist_scroll = 0.0F; + serverlist_hover = -1; + request_serverlist = http_get("http://services.buildandshoot.com/serverlist.json",NULL); + request_version = http_get("http://aos.party/bs/version/",NULL); - chat_input_mode = CHAT_ALL_INPUT; - chat[0][0][0] = 0; - serverlist_is_outdated = 0; + chat_input_mode = CHAT_ALL_INPUT; + chat[0][0][0] = 0; + serverlist_is_outdated = 0; + + pthread_mutex_init(&serverlist_lock,NULL); } static int hud_serverlist_sort(const void* a, const void* b) { struct serverlist_entry* aa = (struct serverlist_entry*)a; struct serverlist_entry* bb = (struct serverlist_entry*)b; - if(aa->current+bb->current==0) { - return aa->ping-bb->ping; - } + if(abs(aa->current-bb->current)==0) + if(abs(aa->ping-bb->ping)==0) + return strcmp(aa->name,bb->name); + else + return aa->ping-bb->ping; if(aa->current<0) { return -1; } @@ -1389,6 +1398,18 @@ static int hud_serverlist_sort(const void* a, const void* b) { return bb->current-aa->current; } +static void hud_serverlist_pingupdate(struct ping_entry* e, float time_delta, void* user_data) { + pthread_mutex_lock(&serverlist_lock); + (*(int*)user_data) = ceil(time_delta*1000.0F); + pthread_mutex_unlock(&serverlist_lock); +} + +static void hud_serverlist_pingcomplete() { + pthread_mutex_lock(&serverlist_lock); + qsort(serverlist,server_count,sizeof(struct serverlist_entry),hud_serverlist_sort); + pthread_mutex_unlock(&serverlist_lock); +} + static void hud_serverlist_render(float scalex, float scaley) { glColor3f(0.5F,0.5F,0.5F); float t = window_time()*0.03125F; @@ -1461,6 +1482,8 @@ static void hud_serverlist_render(float scalex, float scaley) { tmp = k; } + pthread_mutex_lock(&serverlist_lock); + float f = ((serverlist[k].current && serverlist[k].currentresponse_data)); server_count = json_array_get_count(servers)+1; + + pthread_mutex_lock(&serverlist_lock); serverlist = realloc(serverlist,server_count*sizeof(struct serverlist_entry)); CHECK_ALLOCATION_ERROR(serverlist) player_count = 0; @@ -1557,13 +1584,18 @@ static void hud_serverlist_render(float scalex, float scaley) { serverlist[k].current = (int)json_object_get_number(s,"players_current"); serverlist[k].max = (int)json_object_get_number(s,"players_max"); - serverlist[k].ping = (int)json_object_get_number(s,"latency"); strncpy(serverlist[k].name,json_object_get_string(s,"name"),31); strncpy(serverlist[k].map,json_object_get_string(s,"map"),20); strncpy(serverlist[k].gamemode,json_object_get_string(s,"game_mode"),7); strncpy(serverlist[k].identifier,json_object_get_string(s,"identifier"),31); strncpy(serverlist[k].country,json_object_get_string(s,"country"),3); + + int port; + char ip[32]; + if(network_identifier_split(serverlist[k].identifier,ip,&port)) + ping_check(ip,port,&serverlist[k].ping,hud_serverlist_pingupdate); + player_count += serverlist[k].current; } serverlist[0].current = serverlist[0].max = -1; @@ -1574,7 +1606,11 @@ static void hud_serverlist_render(float scalex, float scaley) { strcpy(serverlist[0].identifier,"aos://16777343:32887"); strcpy(serverlist[0].country,"US"); + ping_start(hud_serverlist_pingcomplete); + qsort(serverlist,server_count,sizeof(struct serverlist_entry),hud_serverlist_sort); + pthread_mutex_unlock(&serverlist_lock); + http_release(request_serverlist); request_serverlist = NULL; break; @@ -1613,7 +1649,9 @@ static void hud_serverlist_mouseclick(int button, int action, int mods) { return; } if(serverlist_hover>=0) { + pthread_mutex_lock(&serverlist_lock); server_c(serverlist[serverlist_hover].identifier); + pthread_mutex_unlock(&serverlist_lock); } double x,y; window_mouseloc(&x,&y); diff --git a/src/list.c b/src/list.c index ec21cdd..dd4fce8 100644 --- a/src/list.c +++ b/src/list.c @@ -21,7 +21,10 @@ void* list_add(struct list* l, void* e) { l->data = realloc(l->data,l->mem_size); CHECK_ALLOCATION_ERROR(l->data) } - memcpy(l->data+l->elements*l->element_size,e,l->element_size); + if(e) + memcpy(l->data+l->elements*l->element_size,e,l->element_size); + else + memset(l->data+l->elements*l->element_size,0,l->element_size); return l->data+(l->elements++)*l->element_size; } diff --git a/src/main.c b/src/main.c index 75ef7b5..a45e52e 100644 --- a/src/main.c +++ b/src/main.c @@ -449,7 +449,7 @@ void init() { //set minimap borders (white on 64x64 chunks, black map border) memset(map_minimap,0xCCCCCCFF,map_size_x*map_size_z*sizeof(unsigned char)*4); - glx_init(); + glx_init(); font_init(); player_init(); @@ -460,7 +460,8 @@ void init() { sound_init(); tracer_init(); hud_init(); - chunk_init(); + chunk_init(); + ping_init(); weapon_set(); } @@ -556,10 +557,12 @@ void mouse_scroll(struct window_instance* window, double xoffset, double yoffset } void deinit() { - if(settings.show_news) - file_url("https://www.buildandshoot.com/news/"); + ping_deinit(); + if(settings.show_news) + file_url("https://www.buildandshoot.com/news/"); if(network_connected) network_disconnect(); + window_deinit(); } void on_error(int i, const char* s) { @@ -660,6 +663,4 @@ int main(int argc, char** argv) { } fps = 1.0F/(window_time()-last_frame_start); } - - window_deinit(); } diff --git a/src/network.c b/src/network.c index 2be2d32..1f79329 100644 --- a/src/network.c +++ b/src/network.c @@ -589,7 +589,7 @@ void read_PacketKillAction(void* data, int len) { } void read_PacketShortPlayerData(void* data, int len) { - //should never be received, but process it anyway + //should never be received struct PacketShortPlayerData* p = (struct PacketShortPlayerData*)data; log_warn("Unexpected ShortPlayerDataPacket"); } @@ -642,7 +642,6 @@ void read_PacketChangeWeapon(void* data, int len) { void read_PacketWeaponReload(void* data, int len) { struct PacketWeaponReload* p = (struct PacketWeaponReload*)data; if(p->player_id==local_player_id) { - weapon_set(); local_player_ammo = p->ammo; local_player_ammo_reserved = p->reserved; } else { @@ -917,6 +916,28 @@ int network_connect(char* ip, int port) { return 0; } +int network_identifier_split(char* addr, char* ip_out, int* port_out) { + char* ip_start = strstr(addr,"aos://")+6; + if((size_t)ip_start<=6) + return 0; + char* port_start = strchr(ip_start,':'); + if(port_start) + *port_start = 0; + + if(strchr(ip_start,'.')) { + *port_out = port_start?atoi(port_start+1):32887; + strcpy(ip_out,ip_start); + } else { + int ip = atoi(ip_start); + char ip_str[32]; + sprintf(ip_str,"%i.%i.%i.%i",ip&255,(ip>>8)&255,(ip>>16)&255,(ip>>24)&255); + + *port_out = port_start?atoi(port_start+1):32887; + strcpy(ip_out,ip_str); + } + return 1; +} + int network_connect_string(char* addr) { char* ip_start = strstr(addr,"aos://")+6; if((size_t)ip_start<=6) diff --git a/src/network.h b/src/network.h index 90f0e2e..c89f245 100644 --- a/src/network.h +++ b/src/network.h @@ -23,6 +23,7 @@ unsigned int network_ping(void); void network_send(int id, void* data, int len); void network_updateColor(void); void network_disconnect(void); +int network_identifier_split(char* addr, char* ip_out, int* port_out); int network_connect(char* ip, int port); int network_connect_string(char* addr); int network_update(void); @@ -314,9 +315,9 @@ struct PacketChatMessage { unsigned char chat_type; char message[255]; }; -#define CHAT_ALL 0 -#define CHAT_TEAM 1 -#define CHAT_SYSTEM 2 +#define CHAT_ALL 0 +#define CHAT_TEAM 1 +#define CHAT_SYSTEM 2 #define PACKET_FOGCOLOR_ID 27 struct PacketFogColor { diff --git a/src/ping.c b/src/ping.c new file mode 100644 index 0000000..0bcd2aa --- /dev/null +++ b/src/ping.c @@ -0,0 +1,89 @@ +#include "common.h" + +struct list list_pings; +ENetSocket sock; +pthread_t ping_thread; +pthread_mutex_t list_ping_lock; +void (*ping_finished) (); + +void ping_init() { + list_create(&list_pings,sizeof(struct ping_entry)); + sock = enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM); + enet_socket_set_option(sock,ENET_SOCKOPT_NONBLOCK,1); + enet_socket_set_option(sock,ENET_SOCKOPT_NODELAY,1); + pthread_mutex_init(&list_ping_lock,NULL); +} + +void ping_deinit() { + enet_socket_destroy(sock); +} + +void* ping_update(void* data) { + while(1) { + ENetBuffer buf; + buf.dataLength = 32; + + pthread_mutex_lock(&list_ping_lock); + for(int k=list_size(&list_pings)-1;k>=0;k--) { + struct ping_entry* entry = list_get(&list_pings,k); + + if(window_time()-entry->time_start>3.0F) { //timeout + if(entry->trycount<3) { + log_warn("Ping timeout, retrying (%i)",entry->trycount); + ENetBuffer buffer; + buffer.data = "HELLO"; + buffer.dataLength = 5; + entry->time_start = window_time(); + enet_socket_send(sock,&entry->addr,&buffer,1); + entry->trycount++; + } else { + list_remove(&list_pings,k); + continue; + } + } + + char tmp[32] = {0}; + buf.data = tmp; + + switch(enet_socket_receive(sock,&entry->addr,&buf,1)) { + case 0: //would block + break; + default: //received something! + if(strcmp(buf.data,"HI")==0 && entry->callback) + entry->callback(entry,window_time()-entry->time_start,entry->user_data); + case -1: //connection was closed + list_remove(&list_pings,k); + } + } + + int size = list_size(&list_pings); + pthread_mutex_unlock(&list_ping_lock); + if(!size) { + ping_finished(); + return NULL; + } + } +} + +void ping_check(char* addr, int port, void* user_data, void (*callback) (struct ping_entry*, float time_delta, void* user_data)) { + struct ping_entry* entry = list_add(&list_pings,NULL); + + entry->callback = callback; + entry->user_data = user_data; + entry->trycount = 1; + + enet_address_set_host(&entry->addr,addr); + entry->addr.port = port; + + ENetBuffer buffer; + buffer.data = "HELLO"; + buffer.dataLength = 5; + + entry->time_start = window_time(); + enet_socket_send(sock,&entry->addr,&buffer,1); +} + +void ping_start(void (*callback) ()) { + pthread_create(&ping_thread,NULL,ping_update,NULL); + ping_finished = callback; +} diff --git a/src/ping.h b/src/ping.h new file mode 100644 index 0000000..c3e45a0 --- /dev/null +++ b/src/ping.h @@ -0,0 +1,13 @@ +struct ping_entry { + ENetAddress addr; + float time_start; + void* user_data; + int trycount; + void (*callback) (struct ping_entry*, float time_delta, void* user_data); +}; + +void ping_init(); +void ping_deinit(); +void ping_check(char* addr, int port, void* user_data, void (*callback) (struct ping_entry*, float time_delta, void* user_data)); +void* ping_update(void* data); +void ping_start(void (*callback) ()); diff --git a/src/player.c b/src/player.c index 69da152..36421f8 100644 --- a/src/player.c +++ b/src/player.c @@ -157,7 +157,7 @@ float* player_tool_translate_func(struct Player* p) { return ret; } if(p->held_item==TOOL_GUN && window_time()-weapon_last_shot0); + ret[2] = -(weapon_delay(players[local_player_id].weapon)-(window_time()-weapon_last_shot))/weapon_delay(players[local_player_id].weapon)*weapon_recoil_anim(players[local_player_id].weapon)*(local_player_ammo>0); return ret; } diff --git a/src/weapon.c b/src/weapon.c index 3424303..2e43eca 100644 --- a/src/weapon.c +++ b/src/weapon.c @@ -76,15 +76,17 @@ void weapon_update() { } } -float weapon_recoil(int gun) { - switch(gun) { - case WEAPON_RIFLE: - return 0.3F; - case WEAPON_SMG: - return 0.125F; - case WEAPON_SHOTGUN: - return 0.75F; - } +float weapon_recoil_anim(int gun) { + switch(gun) { + case WEAPON_RIFLE: + return 0.3F; + case WEAPON_SMG: + return 0.125F; + case WEAPON_SHOTGUN: + return 0.75F; + default: + return 0.0F; + } } int weapon_block_damage(int gun) { @@ -149,40 +151,60 @@ void weapon_spread(struct Player* p, float* d) { d[2] += (ms_rand()-ms_rand())/16383.0F*spread*(p->input.buttons.rmb?0.5F:1.0F)*((p->input.keys.crouch && p->weapon!=WEAPON_SHOTGUN)?0.5F:1.0F); } +void weapon_recoil(int gun, double* horiz_recoil, double* vert_recoil) { + switch(gun) { + case WEAPON_RIFLE: + *horiz_recoil = 0.0001; + *vert_recoil = 0.050000001; + break; + case WEAPON_SMG: + *horiz_recoil = 0.00005; + *vert_recoil = 0.0125; + break; + case WEAPON_SHOTGUN: + *horiz_recoil = 0.0002; + *vert_recoil = 0.1; + break; + default: + *horiz_recoil = 0.0F; + *vert_recoil = 0.0F; + } +} + int weapon_ammo(int gun) { - switch(players[local_player_id].weapon) { - case WEAPON_RIFLE: - return 10; - case WEAPON_SMG: - return 30; - case WEAPON_SHOTGUN: - return 6; - } + switch(players[local_player_id].weapon) { + case WEAPON_RIFLE: + return 10; + case WEAPON_SMG: + return 30; + case WEAPON_SHOTGUN: + return 6; + default: + return 0; + } } void weapon_set() { - //players[local_player_id].weapon = WEAPON_SHOTGUN; - switch(players[local_player_id].weapon) { - case WEAPON_RIFLE: - local_player_ammo = 10; - local_player_ammo_reserved = 50; - break; - case WEAPON_SMG: - local_player_ammo = 30; - local_player_ammo_reserved = 120; - break; - case WEAPON_SHOTGUN: - local_player_ammo = 6; - local_player_ammo_reserved = 48; - break; - } - weapon_reload_inprogress = 0; + //players[local_player_id].weapon = WEAPON_SHOTGUN; + local_player_ammo = weapon_ammo(players[local_player_id].weapon); + weapon_reload_inprogress = 0; + switch(players[local_player_id].weapon) { + case WEAPON_RIFLE: + local_player_ammo_reserved = 50; + return; + case WEAPON_SMG: + local_player_ammo_reserved = 120; + return; + case WEAPON_SHOTGUN: + local_player_ammo_reserved = 48; + return; + } } void weapon_reload() { - if(local_player_ammo_reserved==0 || weapon_reload_inprogress || !weapon_can_reload()) { - return; - } + if(local_player_ammo_reserved==0 || weapon_reload_inprogress || !weapon_can_reload()) + return; + weapon_reload_start = window_time(); weapon_reload_inprogress = 1; @@ -209,19 +231,8 @@ int weapon_reloading() { } int weapon_can_reload() { - int mag_size; - switch(players[local_player_id].weapon) { - case WEAPON_RIFLE: - mag_size = 10; - break; - case WEAPON_SMG: - mag_size = 30; - break; - case WEAPON_SHOTGUN: - mag_size = 6; - break; - } - return max(min(min(local_player_ammo_reserved,mag_size),mag_size-local_player_ammo),0); + int mag_size = weapon_ammo(players[local_player_id].weapon); + return max(min(min(local_player_ammo_reserved,mag_size),mag_size-local_player_ammo),0); } void weapon_shoot() { @@ -297,21 +308,8 @@ void weapon_shoot() { ); } - double horiz_recoil, vert_recoil; - switch(players[local_player_id].weapon) { - case WEAPON_RIFLE: - horiz_recoil = 0.0001; - vert_recoil = 0.050000001; - break; - case WEAPON_SMG: - horiz_recoil = 0.00005; - vert_recoil = 0.0125; - break; - case WEAPON_SHOTGUN: - horiz_recoil = 0.0002; - vert_recoil = 0.1; - break; - } + double horiz_recoil, vert_recoil; + weapon_recoil(players[local_player_id].weapon,&horiz_recoil,&vert_recoil); long triangle_wave = (long)(window_time()*1000)&511; horiz_recoil *= ((double)triangle_wave-255.5); @@ -349,19 +347,7 @@ void weapon_shoot() { camera_overflow_adjust(); - struct Sound_wav* shoot; - switch(players[local_player_id].weapon) { - case WEAPON_RIFLE: - shoot = &sound_rifle_shoot; - break; - case WEAPON_SMG: - shoot = &sound_smg_shoot; - break; - case WEAPON_SHOTGUN: - shoot = &sound_shotgun_shoot; - break; - } - - sound_create(NULL,SOUND_LOCAL,shoot,players[local_player_id].pos.x,players[local_player_id].pos.y,players[local_player_id].pos.z); + sound_create(NULL,SOUND_LOCAL,weapon_sound(players[local_player_id].weapon), + players[local_player_id].pos.x,players[local_player_id].pos.y,players[local_player_id].pos.z); particle_create_casing(&players[local_player_id]); } diff --git a/src/weapon.h b/src/weapon.h index ee1ddd1..56a430f 100644 --- a/src/weapon.h +++ b/src/weapon.h @@ -27,10 +27,11 @@ void weapon_shoot(void); int weapon_block_damage(int gun); float weapon_delay(int gun); int weapon_ammo(int gun); -float weapon_recoil(int gun); +float weapon_recoil_anim(int gun); struct Sound_wav* weapon_sound(int gun); struct Sound_wav* weapon_sound_reload(int gun); void weapon_spread(struct Player* p, float* d); +void weapon_recoil(int gun, double* horiz_recoil, double* vert_recoil); extern float weapon_reload_start, weapon_last_shot; extern unsigned char weapon_reload_inprogress;