Skip to content

Instantly share code, notes, and snippets.

@kdrnic
Created November 15, 2024 20:50
Show Gist options
  • Save kdrnic/f5fc0c48cb86d34ad8cd6ae896097950 to your computer and use it in GitHub Desktop.
Save kdrnic/f5fc0c48cb86d34ad8cd6ae896097950 to your computer and use it in GitHub Desktop.
#include <allegro.h>
#include <winalleg.h>
#include <libnet.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <time.h>
#include <stdint.h>
#include <assert.h>
#include <ctype.h>
static char config_filename[] = "nettest.cfg";
static double realtime;
static char logp_temp[5000];
static char error_string[5000];
static char name[32] = "Guest12345";
static char logp_buffer[99999];
static double tick_interval = 1.0 / 20.0;
static double last_tick = -999.0;
static int tick_count = 0;
static int has_logput;
static void log_puts(const char *str)
{
if(!*str) str++;
if(strlen(str) + strlen(logp_buffer) + 1 > sizeof(logp_buffer)) logp_buffer[0] = 0;
strcat(logp_buffer, str);
strcat(logp_buffer, "\n");
has_logput = 1;
}
#include "net.h"
static void NET_GAME_CL_JOIN(kdrnet_cl_t *cls){}
static void NET_GAME_CL_LEAVE(kdrnet_cl_t *cls){}
static void NET_GAME_SV_JOIN(kdrnet_sv_t *svs, kdrnet_sv_client *c){}
static void NET_GAME_SV_LEAVE(kdrnet_sv_t *svs, kdrnet_sv_client *c){}
static void NET_GAME_SV_READ(kdrnet_sv_t *svs, struct kdrnet_sv_client *cl);
static void NET_GAME_SV_WRITERELIABLE(kdrnet_sv_t *svs, struct kdrnet_sv_client *cl);
static int NET_GAME_SV_WRITEDGRAM(kdrnet_sv_t *svs, struct kdrnet_sv_client *cl, struct sizedbuf *buf);
static void NET_GAME_CL_READ(kdrnet_cl_t *cls);
static void NET_GAME_CL_WRITE(kdrnet_cl_t *cls, struct sizedbuf *buf);
static void NET_GAME_SV_BEGINWRITE(kdrnet_sv_t *svs);
static void NET_GAME_SV_ENDWRITE(kdrnet_sv_t *svs);
static double get_realtime(void)
{
return realtime;
}
#define base_nc {.log_puts = log_puts, .get_realtime = get_realtime}
static kdrnet_cl_t cls = {
base_nc,
.on_join = NET_GAME_CL_JOIN,
.on_leave = NET_GAME_CL_LEAVE,
.on_read = NET_GAME_CL_READ,
.do_write = NET_GAME_CL_WRITE
};
static kdrnet_sv_t svs = {
base_nc,
.on_join = NET_GAME_SV_JOIN,
.on_leave = NET_GAME_SV_LEAVE,
.on_read = NET_GAME_SV_READ,
.do_write_reliable = NET_GAME_SV_WRITERELIABLE,
.do_write_dgram = NET_GAME_SV_WRITEDGRAM,
.on_begin_write = NET_GAME_SV_BEGINWRITE,
.on_end_write = NET_GAME_SV_ENDWRITE
};
static kdrnet_common *nc = 0;
static char address[NET_MAX_ADDRESS_LENGTH] = "127.0.0.1";
static NET_DRIVERNAME *drivernames;
static NET_DRIVERLIST avail;
static char status[640 / 8] = "Set up connection settings below";
static int num_messages_rec = 0;
static int num_messages_snt = 0;
static int first_connected = 0;
static char str_mrec[20] = "0";
static char str_msnt[20] = "0";
static int wave_y, their_wave_y;
static int foolish_counter = 0;
static char send_string[256] = "";
static char peer_name[32] = "";
static int send_reset = 0;
static char broadcast_string[4096];
#define WHITE 0xFFFFFF
#define BLUE 0xff
#define GREEN 0xFF00
static char chat_string[128] = "";
enum
{
CMD_SETWAVEY = 45,
CMD_PRINT = 79,
CMD_RESET = 97
};
void NET_GAME_SV_BEGINWRITE(kdrnet_sv_t *svs)
{
}
void NET_GAME_SV_ENDWRITE(kdrnet_sv_t *svs)
{
broadcast_string[0] = 0;
}
static void parsecmd(int c);
static void parsecmd_sv(int c)
{
if(c == CMD_PRINT){
char str[2048], *line;
szb_readstring(&nc->message, str);
line = strtok(str, "\n");
while(line){
if(strstr(line, "PRIVMSG ") != line){
if(strlen(broadcast_string)) strcat(broadcast_string, "\n");
strcat(broadcast_string, line);
}
else
{
line += 8;
}
log_puts(line);
line = strtok(0, "\n");
}
return;
}
switch(c){
default:
parsecmd(c);
}
}
void parsecmd(int c)
{
char str[2048];
switch(c){
case CMD_SETWAVEY:
their_wave_y = SZB_READ(&nc->message, int);
break;
case CMD_PRINT:
szb_readstring(&nc->message, str);
log_puts(str);
break;
case CMD_RESET:
foolish_counter = 0;
break;
default:
kdrnet_dumpmessage(nc, 0);
}
}
void NET_GAME_SV_READ(kdrnet_sv_t *svs, struct kdrnet_sv_client *cl)
{
num_messages_rec++;
while(szb_canread(&nc->message)) parsecmd_sv(SZB_READ(&nc->message, unsigned char));
}
void NET_GAME_SV_WRITERELIABLE(kdrnet_sv_t *svs, struct kdrnet_sv_client *cl)
{
if(strlen(send_string)){
SZB_WRITE(&cl->link.message, (unsigned char) CMD_PRINT);
szb_writestring(&cl->link.message, send_string);
send_string[0] = 0;
}
if(strlen(broadcast_string)){
SZB_WRITE(&cl->link.message, (unsigned char) CMD_PRINT);
szb_writestring(&cl->link.message, broadcast_string);
}
if(send_reset){
SZB_WRITE(&cl->link.message, (unsigned char) CMD_RESET);
send_reset = 0;
}
}
int NET_GAME_SV_WRITEDGRAM(kdrnet_sv_t *svs, struct kdrnet_sv_client *cl, struct sizedbuf *buf)
{
num_messages_snt++;
SZB_WRITE(buf, (unsigned char) CMD_SETWAVEY);
SZB_WRITE(buf, wave_y);
return 1;
}
void NET_GAME_CL_READ(kdrnet_cl_t *cls)
{
num_messages_rec++;
while(szb_canread(&nc->message)) parsecmd(SZB_READ(&nc->message, unsigned char));
}
void NET_GAME_CL_WRITE(kdrnet_cl_t *cls, struct sizedbuf *buf)
{
num_messages_snt++;
if(strlen(send_string)){
SZB_WRITE(&cls->link.message, (unsigned char) CMD_PRINT);
szb_writestring(&cls->link.message, send_string);
send_string[0] = 0;
}
if(send_reset){
SZB_WRITE(&cls->link.message, (unsigned char) CMD_RESET);
send_reset = 0;
}
SZB_WRITE(buf, (unsigned char) CMD_SETWAVEY);
SZB_WRITE(buf, wave_y);
}
static char *driverlist_getter(int index, int *list_size)
{
NET_DRIVERNAME *drv = drivernames;
int numdrvs = 0;
while(drv->name){
if(index == numdrvs) return drv->name;
drv++;
numdrvs++;
}
if(index < 0){
*list_size = numdrvs;
}
return 0;
}
static int update_proc(int msg, DIALOG *d, int c);
static BITMAP *wave_bmp;
static int wave_x = 0;
DIALOG the_dialog[] =
{
// (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3)
{d_clear_proc, 0, 0, 0, 0, WHITE, 0, 0, 0, 0, 0, NULL, NULL, NULL },//0
{d_rtext_proc, 96, 32, 0, 0, WHITE, 0, 0, 0, 0, 0, "Address:", 0, 0 },//1
{d_edit_proc, 96, 32, 224, 8, WHITE, 0, 0, 0, sizeof(address)-1, 0, address, NULL, NULL },//2
{d_radio_proc, 320, 32, 160, 16, WHITE, 0, 0, D_SELECTED, 0, 0, "Server", 0, 0 },//3
{d_radio_proc, 480, 32, 160, 16, WHITE, 0, 0, 0, 0, 0, "Client", 0, 0 },//4
{d_button_proc, 80, 64, 160, 16, WHITE, 0, 0, D_EXIT, 0, 0, "Connect/Listen", NULL, NULL },//5
{d_ctext_proc, 320, 8, 0, 0, WHITE, 0, 0, 0, 0, 0, status, 0, 0 },//6
{d_list_proc, 340, 64, 280, 64, WHITE, 0, 0, D_EXIT, 1, 0, driverlist_getter, 0, 0 },//7
{d_textbox_proc, 16, 136, 608, 96, WHITE, 0, 0, D_SELECTED, 0, 0, logp_buffer, 0, 0 },//8
{update_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },//9
{d_edit_proc, 96, 48, 224, 16, WHITE, 0, 0, 0, sizeof(name)-1, 0, name, 0, 0 },//10
{d_rtext_proc, 96, 48, 0, 0, WHITE, 0, 0, 0, 0, 0, "Client name:", 0, 0 },//11
{d_button_proc, 16, 240, 160, 16, WHITE, 0, 0, D_EXIT, 0, 0, "Click me", 0, 0 },//12
{d_text_proc, 128, 96, 0, 0, WHITE, 0, 0, 0, 0, 0, str_mrec, 0, 0 },//13
{d_rtext_proc, 128, 96, 0, 0, WHITE, 0, 0, 0, 0, 0, "Msgs. received:", 0, 0 },//14
{d_text_proc, 128, 104, 0, 0, WHITE, 0, 0, 0, 0, 0, str_msnt, 0, 0 },//15
{d_rtext_proc, 128, 104, 0, 0, WHITE, 0, 0, 0, 0, 0, "Msgs. sent:", 0, 0 },//16
{d_bitmap_proc, 16, 272, 608, 96, WHITE, 0, 0, 0, 0, 0, 0, 0, 0, },//17
{d_button_proc, 320, 240, 160, 16, WHITE, 0, 0, D_EXIT, 0, 0, "Clear buffer", 0, 0 },//18
{d_button_proc, 16, 376, 160, 16, WHITE, 0, 0, D_EXIT, 0, 0, "Send RESET", 0, 0 },//19
{d_check_proc, 320, 376, 160, 16, WHITE, 0, 0, D_SELECTED, 1, 0, "Send time msgs.", 0, 0 },//20
{d_edit_proc, 16, 400, 464, 8, WHITE, 0, 0, 0, sizeof(chat_string)-1, 0, chat_string, 0, 0 },//21
{d_button_proc, 496, 400, 128, 16, WHITE, 0, 0, D_EXIT, 0, 0, "Send", 0, 0 },//22
{NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
};
#define sendstring_printf(str, ...) if(1){sprintf(logp_temp, str, ##__VA_ARGS__); put_in_sendstring(logp_temp);}
static void put_in_sendstring(char *str)
{
char *ss = send_string;
if(strlen(send_string)){
while(*ss) ss++;
*ss = '\n';
ss++;
*ss = 0;
}
strcat(send_string, str);
}
int update_proc(int msg, DIALOG *d, int c)
{
LARGE_INTEGER frq, cnt;
int need_redraw = 0;
if(has_logput){
has_logput = 0;
the_dialog[8].flags |= D_DIRTY;
}
if(!(the_dialog[3].flags & D_SELECTED) != !(the_dialog[10].flags & D_DISABLED)){
the_dialog[10].flags ^= D_DISABLED;
the_dialog[10].flags |= D_DIRTY;
}
if(!first_connected){
need_redraw = 1;
first_connected = 1;
if((nc && nc->mode == KDRNET_MODE_CLIENT) && cls.state) strcpy(status, "Connected");
else if((nc && nc->mode == KDRNET_MODE_SERVER) && num_messages_rec) strcpy(status, "Serving clients");
else
{
need_redraw = 0;
first_connected = 0;
}
}
if(atoi(str_mrec) != num_messages_rec){
sprintf(str_mrec, "%d", num_messages_rec);
the_dialog[13].flags |= D_DIRTY;
}
if(atoi(str_msnt) != num_messages_snt){
sprintf(str_msnt, "%d", num_messages_snt);
the_dialog[15].flags |= D_DIRTY;
}
QueryPerformanceCounter(&cnt);
QueryPerformanceFrequency(&frq);
realtime = ((double) cnt.QuadPart) / ((double) frq.QuadPart);
if(last_tick + tick_interval < realtime){
if(nc) kdrnet_update(nc);
last_tick = realtime;
tick_count++;
wave_x++;
wave_y = wave_bmp->h / 2 + fixtoi(fixmul(fixsin(itofix(wave_x)), itofix(wave_bmp->h / 2 - 1)));
if(wave_y < 1) wave_y = 1;
if(wave_y >= wave_bmp->h - 1) wave_y = wave_bmp->h - 2;
vline(wave_bmp, wave_x % wave_bmp->w, 0, wave_bmp->h - 1, 0);
putpixel(wave_bmp, wave_x % wave_bmp->w, wave_y, BLUE);
putpixel(wave_bmp, wave_x % wave_bmp->w, their_wave_y, GREEN);
rect(wave_bmp, 0, 0, wave_bmp->w - 1, wave_bmp->h - 1, WHITE);
the_dialog[17].flags |= D_DIRTY;
if(tick_count % 40 == 0){
if(the_dialog[20].flags & D_SELECTED) sendstring_printf("PRIVMSG %02d Peer time: %02.2f", (foolish_counter++) % 99, (float) realtime);
}
}
if(msg != MSG_IDLE) return need_redraw ? D_REDRAW : D_O_K;
return need_redraw ? D_REDRAW : D_O_K;
}
static void driverlist_parse(void)
{
NET_DRIVERNAME *drv = drivernames;
int numdrvs = 0;
while(drv->name){
if(the_dialog[7].d1 == numdrvs) if(nc) nc->driver = drv->num;
drv++;
numdrvs++;
}
}
int main(int argc, char **argv)
{
allegro_init();
set_color_depth(32);
set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);
install_keyboard();
install_mouse();
set_display_switch_mode(SWITCH_BACKGROUND);
wave_bmp = create_bitmap(608, 96);
clear_to_color(wave_bmp, 0);
the_dialog[17].dp = wave_bmp;
logp_buffer[0] = 0;
realtime = 0;
net_init();
net_loadconfig(config_filename);
avail = net_detectdrivers(net_drivers_all);
drivernames = net_getdrivernames(avail);
while(!key[KEY_ESC]){
int ret = do_dialog(the_dialog, -1);
switch(ret){
case 5:
the_dialog[10].flags |= D_DISABLED;
the_dialog[7].flags |= D_DISABLED;
the_dialog[5].flags |= D_DISABLED;
the_dialog[4].flags |= D_DISABLED;
the_dialog[3].flags |= D_DISABLED;
the_dialog[2].flags |= D_DISABLED;
driverlist_parse();
if(the_dialog[3].flags & D_SELECTED){
nc = (kdrnet_common *) &svs;
nc->driver = 3;
nc->timeout = 5;
nc->zombietime = 5;
kdrnet_sv_init(&svs);
strcpy(status, "Listening for new clients");
}
if(the_dialog[4].flags & D_SELECTED){
nc = (kdrnet_common *) &cls;
nc->driver = 3;
nc->timeout = 5;
nc->zombietime = 5;
if(!kdrnet_cl_init(&cls, address)) strcpy(cls.name, name);
strcpy(status, "Connecting to server");
}
break;
case 12:
log_puts("Clicked, lol");
break;
case 18:
logp_buffer[0] = 0;
break;
case 19:
send_reset = 1;
break;
case 22:
sendstring_printf("%s", chat_string);
chat_string[0] = 0;
break;
}
}
return 0;
}
END_OF_MAIN();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment