use surf for random, async game search
This commit is contained in:
parent
c5aa13ac27
commit
94df5eb6dd
2
Makefile
2
Makefile
@ -11,7 +11,7 @@ sdlbomber: announce.o bomber.o draw.o game.o gfx.o sound.o list.o network.o menu
|
|||||||
|
|
||||||
matcher: matcher.c
|
matcher: matcher.c
|
||||||
|
|
||||||
announce.o: announce.c announce.h
|
announce.o: announce.c announce.h network.h
|
||||||
|
|
||||||
bomber.o: bomber.c announce.h bomber.h draw.h game.h gfx.h list.h menu.h network.h sound.h utils.h
|
bomber.o: bomber.c announce.h bomber.h draw.h game.h gfx.h list.h menu.h network.h sound.h utils.h
|
||||||
|
|
||||||
|
1
TODO
1
TODO
@ -31,4 +31,3 @@ For internet this would be intolerable. I've never tried though...
|
|||||||
Better docs, online explanations, attract mode...
|
Better docs, online explanations, attract mode...
|
||||||
|
|
||||||
Single player with computer controlled figures that must be killed/avoided.
|
Single player with computer controlled figures that must be killed/avoided.
|
||||||
|
|
||||||
|
112
announce.c
112
announce.c
@ -1,5 +1,6 @@
|
|||||||
|
|
||||||
#include "announce.h"
|
#include "announce.h"
|
||||||
|
#include "network.h"
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -22,13 +23,16 @@
|
|||||||
static AvahiClient *client = NULL;
|
static AvahiClient *client = NULL;
|
||||||
static AvahiThreadedPoll *threaded_poll = NULL;
|
static AvahiThreadedPoll *threaded_poll = NULL;
|
||||||
static AvahiEntryGroup *group = NULL;
|
static AvahiEntryGroup *group = NULL;
|
||||||
|
static AvahiServiceBrowser *browser = NULL;
|
||||||
|
|
||||||
static char* name = NULL;
|
static char* name = NULL;
|
||||||
|
|
||||||
static uint16_t port = 0;
|
static uint16_t port = 0;
|
||||||
static uint32_t version = 0;
|
static uint32_t version = 0;
|
||||||
|
|
||||||
static volatile int all_for_now;
|
static gamelistentry buffer_glentries[10];
|
||||||
|
static int buffer_glsize = 0;
|
||||||
|
static char buffer_glchanged[10];
|
||||||
|
|
||||||
gamelistentry gamelistentries[10];
|
gamelistentry gamelistentries[10];
|
||||||
int gamelistsize = 0;
|
int gamelistsize = 0;
|
||||||
@ -150,7 +154,7 @@ int registergame(const char *playername, uint16_t p, const unsigned char v[4]) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void unregistergame() {
|
void unregistergame(void) {
|
||||||
port = 0;
|
port = 0;
|
||||||
|
|
||||||
avahi_threaded_poll_lock(threaded_poll);
|
avahi_threaded_poll_lock(threaded_poll);
|
||||||
@ -159,15 +163,33 @@ void unregistergame() {
|
|||||||
avahi_threaded_poll_unlock(threaded_poll);
|
avahi_threaded_poll_unlock(threaded_poll);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void remove_game_with_name(const char *name) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < buffer_glsize; i++) {
|
||||||
|
if (0 == strcmp(buffer_glentries[i].name, name)) {
|
||||||
|
/* Remove it */
|
||||||
|
buffer_glsize--;
|
||||||
|
if (i != buffer_glsize) {
|
||||||
|
buffer_glentries[i] = buffer_glentries[buffer_glsize];
|
||||||
|
buffer_glchanged[i] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void resolve_callback(AvahiServiceResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event,
|
static void resolve_callback(AvahiServiceResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event,
|
||||||
const char *name, const char *type, const char *domain, const char *host_name, const AvahiAddress *address,
|
const char *name, const char *type, const char *domain, const char *host_name, const AvahiAddress *address,
|
||||||
uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags flags, void* userdata) {
|
uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags flags, void* userdata) {
|
||||||
int i;
|
int i;
|
||||||
uint32_t want_version = *(uint32_t*) userdata;
|
uint32_t want_version;
|
||||||
assert(r);
|
assert(r);
|
||||||
|
|
||||||
if (protocol != AVAHI_PROTO_INET) goto done; /* ignore non IPv4 for now */
|
if (protocol != AVAHI_PROTO_INET) goto done; /* ignore non IPv4 for now */
|
||||||
if (gamelistsize >= GAMELIST_MAXSIZE) goto done;
|
if (buffer_glsize >= GAMELIST_MAXSIZE) goto done;
|
||||||
|
|
||||||
|
memcpy(&want_version, gameversion, 4);
|
||||||
|
want_version = htonl(want_version);
|
||||||
|
|
||||||
/* Called whenever a service has been resolved successfully or timed out */
|
/* Called whenever a service has been resolved successfully or timed out */
|
||||||
|
|
||||||
@ -189,13 +211,15 @@ static void resolve_callback(AvahiServiceResolver *r, AvahiIfIndex interface, Av
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!have_version) goto done;
|
if (!have_version) goto done;
|
||||||
i = gamelistsize++;
|
remove_game_with_name(name);
|
||||||
ge = &gamelistentries[i];
|
i = buffer_glsize++;
|
||||||
|
ge = &buffer_glentries[i];
|
||||||
|
buffer_glchanged[i] = 1;
|
||||||
memset(ge, 0, sizeof(*ge));
|
memset(ge, 0, sizeof(*ge));
|
||||||
ge->netname.sin_addr.s_addr = address->data.ipv4.address;
|
ge->netname.sin_addr.s_addr = address->data.ipv4.address;
|
||||||
ge->netname.sin_family = AF_INET;
|
ge->netname.sin_family = AF_INET;
|
||||||
ge->netname.sin_port = port;
|
ge->netname.sin_port = port;
|
||||||
ge->name = avahi_strdup(name);
|
strncpy(ge->name, name, 15);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,40 +255,31 @@ static void browse_callback(AvahiServiceBrowser *b, AvahiIfIndex interface, Avah
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case AVAHI_BROWSER_REMOVE:
|
case AVAHI_BROWSER_REMOVE:
|
||||||
|
remove_game_with_name(name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AVAHI_BROWSER_ALL_FOR_NOW:
|
case AVAHI_BROWSER_ALL_FOR_NOW:
|
||||||
all_for_now = 1;
|
|
||||||
break;
|
break;
|
||||||
case AVAHI_BROWSER_CACHE_EXHAUSTED:
|
case AVAHI_BROWSER_CACHE_EXHAUSTED:
|
||||||
all_for_now = 1;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void freefoundgames() {
|
static void freefoundgames(void) {
|
||||||
int i;
|
memset(gamelistentries, 0, sizeof(gamelistentries));
|
||||||
|
memset(buffer_glentries, 0, sizeof(buffer_glentries));
|
||||||
|
memset(buffer_glchanged, 0, sizeof(buffer_glchanged));
|
||||||
|
|
||||||
for (i = 0; i < gamelistsize; i++) {
|
|
||||||
avahi_free(gamelistentries[i].name);
|
|
||||||
}
|
|
||||||
gamelistsize = 0;
|
gamelistsize = 0;
|
||||||
|
buffer_glsize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int searchgames(const unsigned char version[4]) {
|
int searchgames(void) {
|
||||||
int i;
|
|
||||||
AvahiServiceBrowser *sb = NULL;
|
|
||||||
uint32_t gameversion;
|
|
||||||
memcpy(&gameversion, version, 4);
|
|
||||||
gameversion = htonl(gameversion);
|
|
||||||
|
|
||||||
freefoundgames();
|
freefoundgames();
|
||||||
|
|
||||||
avahi_threaded_poll_lock(threaded_poll);
|
avahi_threaded_poll_lock(threaded_poll);
|
||||||
|
|
||||||
all_for_now = 0;
|
if (NULL == (browser = avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, SERVICE_TYPE, NULL, 0, browse_callback, &gameversion))) {
|
||||||
|
|
||||||
if (NULL == (sb = avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, SERVICE_TYPE, NULL, 0, browse_callback, &gameversion))) {
|
|
||||||
fprintf(stderr, "Failed to create service browser: %s\n", avahi_strerror(avahi_client_errno(client)));
|
fprintf(stderr, "Failed to create service browser: %s\n", avahi_strerror(avahi_client_errno(client)));
|
||||||
avahi_threaded_poll_unlock(threaded_poll);
|
avahi_threaded_poll_unlock(threaded_poll);
|
||||||
return 0;
|
return 0;
|
||||||
@ -272,29 +287,40 @@ int searchgames(const unsigned char version[4]) {
|
|||||||
|
|
||||||
avahi_threaded_poll_unlock(threaded_poll);
|
avahi_threaded_poll_unlock(threaded_poll);
|
||||||
|
|
||||||
for (i = 0; i < 10; i++) {
|
usleep(200000);
|
||||||
usleep(200000);
|
find_more_games();
|
||||||
|
|
||||||
avahi_threaded_poll_lock(threaded_poll);
|
|
||||||
|
|
||||||
if (all_for_now) {
|
|
||||||
avahi_service_browser_free(sb);
|
|
||||||
avahi_threaded_poll_unlock(threaded_poll);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
avahi_threaded_poll_unlock(threaded_poll);
|
|
||||||
}
|
|
||||||
|
|
||||||
avahi_threaded_poll_lock(threaded_poll);
|
|
||||||
avahi_service_browser_free(sb);
|
|
||||||
avahi_threaded_poll_unlock(threaded_poll);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int find_more_games(void) {
|
||||||
|
int i, res = 0;
|
||||||
|
|
||||||
int initannouncer() {
|
avahi_threaded_poll_lock(threaded_poll);
|
||||||
|
|
||||||
|
for (i = 0; i < buffer_glsize; i++) {
|
||||||
|
if (!buffer_glchanged[i]) continue;
|
||||||
|
buffer_glchanged[i] = 0;
|
||||||
|
gamelistentries[i] = buffer_glentries[i];
|
||||||
|
res = 1;
|
||||||
|
}
|
||||||
|
if (gamelistsize != buffer_glsize) {
|
||||||
|
res = 1;
|
||||||
|
gamelistsize = buffer_glsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
avahi_threaded_poll_unlock(threaded_poll);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void stop_search(void) {
|
||||||
|
avahi_threaded_poll_lock(threaded_poll);
|
||||||
|
avahi_service_browser_free(browser);
|
||||||
|
avahi_threaded_poll_unlock(threaded_poll);
|
||||||
|
}
|
||||||
|
|
||||||
|
int initannouncer(void) {
|
||||||
if (!(threaded_poll = avahi_threaded_poll_new())) {
|
if (!(threaded_poll = avahi_threaded_poll_new())) {
|
||||||
fprintf(stderr, "avahi_threaded_poll_new failed\n");
|
fprintf(stderr, "avahi_threaded_poll_new failed\n");
|
||||||
return 0;
|
return 0;
|
||||||
@ -319,7 +345,7 @@ int initannouncer() {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void freeannouncer() {
|
void freeannouncer(void) {
|
||||||
freefoundgames();
|
freefoundgames();
|
||||||
|
|
||||||
avahi_threaded_poll_stop(threaded_poll);
|
avahi_threaded_poll_stop(threaded_poll);
|
||||||
|
13
announce.h
13
announce.h
@ -6,15 +6,18 @@
|
|||||||
typedef struct gamelistentry gamelistentry;
|
typedef struct gamelistentry gamelistentry;
|
||||||
struct gamelistentry {
|
struct gamelistentry {
|
||||||
struct sockaddr_in netname;
|
struct sockaddr_in netname;
|
||||||
char *name;
|
char name[16];
|
||||||
};
|
};
|
||||||
|
|
||||||
int registergame(const char *playername, uint16_t port, const unsigned char version[4]);
|
int registergame(const char *playername, uint16_t port, const unsigned char version[4]);
|
||||||
void unregistergame();
|
void unregistergame(void);
|
||||||
int searchgames(const unsigned char version[4]);
|
|
||||||
|
|
||||||
int initannouncer();
|
int searchgames(void);
|
||||||
void freeannouncer();
|
int find_more_games(void);
|
||||||
|
void stop_search(void);
|
||||||
|
|
||||||
|
int initannouncer(void);
|
||||||
|
void freeannouncer(void);
|
||||||
|
|
||||||
#define GAMELIST_MAXSIZE 10
|
#define GAMELIST_MAXSIZE 10
|
||||||
|
|
||||||
|
2
bomber.c
2
bomber.c
@ -27,7 +27,7 @@ int main(int argc,char **argv) {
|
|||||||
p=getenv("USER");
|
p=getenv("USER");
|
||||||
if(p) strncpy(playername,p,sizeof(playername));
|
if(p) strncpy(playername,p,sizeof(playername));
|
||||||
|
|
||||||
create_unique();
|
create_seed_unique();
|
||||||
|
|
||||||
opengfx(argc, argv);
|
opengfx(argc, argv);
|
||||||
getsocket();
|
getsocket();
|
||||||
|
77
bomber.h
77
bomber.h
@ -213,79 +213,4 @@ extern char exitflag;
|
|||||||
extern uchar needwhole;
|
extern uchar needwhole;
|
||||||
extern figure walking[MAXSETS][60];
|
extern figure walking[MAXSETS][60];
|
||||||
|
|
||||||
#define GO_DENSITY 0
|
#endif /* BOMBER_H */
|
||||||
#define GO_FLAMES 1
|
|
||||||
#define GO_BOMBS 2
|
|
||||||
#define GO_GENEROSITY 3
|
|
||||||
|
|
||||||
// network packet types
|
|
||||||
// slave -> master packets
|
|
||||||
#define PKT_MYDATA 0 // 4 bytes unique #,4 bytes frame #, 1 byte data
|
|
||||||
#define PKT_JOIN 1 // 4 bytes version #,16 bytes name
|
|
||||||
// master -> slave packets
|
|
||||||
#define PKT_INVITE 9 // 4 bytes unique #, any # of 1:slot,16:name sets (-1 end)
|
|
||||||
#define PKT_BEGIN 10 // clone of INVITE
|
|
||||||
#define PKT_STEP 11 // 4 bytes unique #, 4 bytes frame #, 8 bytes ACT_*
|
|
||||||
#define PKT_QUIT 12 // 4 bytes unique #
|
|
||||||
// master -> matcher packets
|
|
||||||
#define PKT_REGISTER 16 // 4:unique #,4:pword hash,4:version #,16:name, 1:status
|
|
||||||
// matcher -> master packets
|
|
||||||
#define PKT_ACK 24 // perfect copy of packet received
|
|
||||||
// slave -> matcher packets
|
|
||||||
#define PKT_QUERY 32 // 4 bytes password hash
|
|
||||||
// matcher -> slave packets
|
|
||||||
#define PKT_INFO 40 // 4: pword hash, 2: count,#(4:unique,4:IP,2:port,16:name)
|
|
||||||
|
|
||||||
// all bytes stored MSB first
|
|
||||||
|
|
||||||
/*
|
|
||||||
game startup:
|
|
||||||
<master and matcher>
|
|
||||||
Master: send REGISTER to matcher with optional password, wait for ack. If
|
|
||||||
timout, resend.
|
|
||||||
matcher: Wait for REGISTER packet, when received maintain database. respond
|
|
||||||
to sender with ACK. REGISTER packet can close a game also. The REGISTER
|
|
||||||
packet sent by the master has a unique word to be used to avoid confusion.
|
|
||||||
REGISTER packet also contains a game version #
|
|
||||||
|
|
||||||
After master registers game and receives ACK, just waits for slaves to contact.
|
|
||||||
|
|
||||||
<slave and matcher>
|
|
||||||
slave: send QUERY to matcher with optional password, wait for INFO, if timeout,
|
|
||||||
resend.
|
|
||||||
matcher: respond to QUERY with INFO packet. matcher need not maintain any
|
|
||||||
database for slave requests. INFO packet contains IP addr and port for each
|
|
||||||
master machine that matches the QUERY spec (ALL or password). Only a
|
|
||||||
certain MAX # of entries are sent if there are too many to choose from.
|
|
||||||
|
|
||||||
<slave and master>
|
|
||||||
slave: send JOIN to master, wait for INVITE. If timeout, resend. JOIN packet
|
|
||||||
contains the unique word the master created. JOIN also contains username.
|
|
||||||
master: Respond to JOIN with INVITE. INVITE contains unique word from JOIN
|
|
||||||
packet. INVITE either contains NO meaning game no longer exists or is closed
|
|
||||||
or player is not invited. IF yes, INVITE contains info on other players
|
|
||||||
already in the game (username and slot # for each). Master allocates the
|
|
||||||
slots and avoids confusion based on IP addr and port #. INVITE also contains
|
|
||||||
game options structure. Whenever a new player JOINS and is admitted, master
|
|
||||||
sends updated INVITE packets to everyone already in the JOIN list. Whenever
|
|
||||||
master changes game options, master sends out another set of INVITES
|
|
||||||
|
|
||||||
Duplicate JOINS are answered with updated INVITE but nothing changes as far
|
|
||||||
as allocation.
|
|
||||||
|
|
||||||
Master player launches game after he's satisfied everyone has joined.
|
|
||||||
|
|
||||||
Master sends BEGIN packet to everyone. BEGIN is identical to INVITE except
|
|
||||||
that the data is final. Slave must respond with its first MYDATA packet with
|
|
||||||
frame # of 0. If master times out waiting, master sends duplicate BEGIN to
|
|
||||||
wayward slaves. Once master has received MYDATA from everyone, game starts.
|
|
||||||
|
|
||||||
Within game slave sends MYDATA to master and waits for STEP packet. If
|
|
||||||
timeout, slave sends duplicate MYDATA.
|
|
||||||
|
|
||||||
If master times out waiting for a slave's MYDATA, slave gets dropped. MYDATAs
|
|
||||||
received will be answered with PKT_QUIT.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#endif // BOMBER_H
|
|
||||||
|
23
game.c
23
game.c
@ -51,7 +51,7 @@ TILE_TURTLE,5,
|
|||||||
TILE_NONE,160
|
TILE_NONE,160
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned char gameoptions[10];
|
static GameOptions gameoptions;
|
||||||
|
|
||||||
static const unsigned char playerpositions[] = { /* color, x, y */
|
static const unsigned char playerpositions[] = { /* color, x, y */
|
||||||
2,0,0,
|
2,0,0,
|
||||||
@ -79,8 +79,8 @@ static void initplayer(int color,int x,int y,int controller) {
|
|||||||
pl->flags=0;
|
pl->flags=0;
|
||||||
pl->fixx=-4;
|
pl->fixx=-4;
|
||||||
pl->fixy=-40;
|
pl->fixy=-40;
|
||||||
pl->flamelength=gameoptions[GO_FLAMES]+1;
|
pl->flamelength=gameoptions.flames+1;
|
||||||
pl->bombsavailable=gameoptions[GO_BOMBS]+1;
|
pl->bombsavailable=gameoptions.bombs+1;
|
||||||
pl->controller=controller;
|
pl->controller=controller;
|
||||||
field[y][x]=FIELD_EMPTY;
|
field[y][x]=FIELD_EMPTY;
|
||||||
if(x) field[y][x-1]=FIELD_EMPTY;
|
if(x) field[y][x-1]=FIELD_EMPTY;
|
||||||
@ -123,7 +123,7 @@ static void initgame() {
|
|||||||
int comp;
|
int comp;
|
||||||
|
|
||||||
if (network != NETWORK_SLAVE)
|
if (network != NETWORK_SLAVE)
|
||||||
set_game_options(configopts);
|
set_game_options(&configopts);
|
||||||
gameframe=0;
|
gameframe=0;
|
||||||
allocthings();
|
allocthings();
|
||||||
initheader(&activebombs);
|
initheader(&activebombs);
|
||||||
@ -142,9 +142,9 @@ static void initgame() {
|
|||||||
if(i==TILE_NONE) break;
|
if(i==TILE_NONE) break;
|
||||||
bonustotal+=*p++;
|
bonustotal+=*p++;
|
||||||
}
|
}
|
||||||
bonustotal += 64*(3-gameoptions[GO_GENEROSITY]);
|
bonustotal += 64*(3-gameoptions.generosity);
|
||||||
memset(field,0,sizeof(field));
|
memset(field,0,sizeof(field));
|
||||||
comp=gameoptions[GO_DENSITY];
|
comp=gameoptions.density;
|
||||||
for(j=0;j<arraynumy;++j)
|
for(j=0;j<arraynumy;++j)
|
||||||
for(i=0;i<arraynumx;++i) {
|
for(i=0;i<arraynumx;++i) {
|
||||||
/* if((i&j)&1) {
|
/* if((i&j)&1) {
|
||||||
@ -837,10 +837,9 @@ static void processplayers(void) {
|
|||||||
static void processquits(void) {
|
static void processquits(void) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if(network!=NETWORK_SLAVE) return;
|
if (network != NETWORK_SLAVE) return;
|
||||||
for(i=0;i<MAXNETNODES;++i)
|
for (i = 0; i < MAXNETNODES; ++i) {
|
||||||
{
|
if (netnodes[i].used && actions[i]==ACT_QUIT)
|
||||||
if(netnodes[i].used && actions[i]==ACT_QUIT)
|
|
||||||
netnodes[i].used=0;
|
netnodes[i].used=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -939,6 +938,6 @@ int iterate(void) {
|
|||||||
return CODE_CONT;
|
return CODE_CONT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_game_options(unsigned char options[10]) {
|
void set_game_options(GameOptions *options) {
|
||||||
memmove(gameoptions, options, sizeof(gameoptions));
|
gameoptions = *options;
|
||||||
}
|
}
|
||||||
|
7
game.h
7
game.h
@ -10,10 +10,15 @@
|
|||||||
|
|
||||||
#define TEMPNODES 2
|
#define TEMPNODES 2
|
||||||
|
|
||||||
|
typedef struct GameOptions GameOptions;
|
||||||
|
struct GameOptions {
|
||||||
|
unsigned char density, flames, bombs, generosity;
|
||||||
|
};
|
||||||
|
|
||||||
void run_single_player(void);
|
void run_single_player(void);
|
||||||
void run_network_game(void);
|
void run_network_game(void);
|
||||||
|
|
||||||
void set_game_options(unsigned char options[10]);
|
void set_game_options(GameOptions *options);
|
||||||
|
|
||||||
extern char playername[16];
|
extern char playername[16];
|
||||||
extern int gamemode;
|
extern int gamemode;
|
||||||
|
170
menu.c
170
menu.c
@ -9,15 +9,24 @@
|
|||||||
#include "announce.h"
|
#include "announce.h"
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
|
|
||||||
unsigned char configopts[10]={2,1,0,2,0,0,0,0,0};
|
GameOptions configopts = { 2, 1, 0, 2 };
|
||||||
|
|
||||||
/* Generic menu */
|
/* Generic menu */
|
||||||
|
|
||||||
int menuhistory[32]={0};
|
typedef enum {
|
||||||
char menustring[1024];
|
MENU_ANY = -1,
|
||||||
char *menuput,*menuitems[40],*menutitle;
|
MENU_MAIN = 0,
|
||||||
int menunum;
|
MENU_CONFIG = 2,
|
||||||
int menudelta;
|
MENU_JOIN = 3
|
||||||
|
} menuname;
|
||||||
|
|
||||||
|
#define MENU_SELECT(x) ((menuname) (-x-1))
|
||||||
|
|
||||||
|
static int menuhistory[32]={0};
|
||||||
|
static char menustring[1024];
|
||||||
|
static char *menuput,*menuitems[40],*menutitle;
|
||||||
|
static int menunum, menuexit;
|
||||||
|
static int menudelta;
|
||||||
|
|
||||||
static void drawmenu(int selected) {
|
static void drawmenu(int selected) {
|
||||||
int i,j;
|
int i,j;
|
||||||
@ -41,7 +50,7 @@ static void drawmenu(int selected) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int domenu(int whichmenu) {
|
static int domenu(menuname whichmenu, int (*pause)(void)) {
|
||||||
char redraw;
|
char redraw;
|
||||||
int selected;
|
int selected;
|
||||||
int mcount=0;
|
int mcount=0;
|
||||||
@ -49,7 +58,9 @@ static int domenu(int whichmenu) {
|
|||||||
if(whichmenu>=0)
|
if(whichmenu>=0)
|
||||||
selected=menuhistory[whichmenu];
|
selected=menuhistory[whichmenu];
|
||||||
else
|
else
|
||||||
selected=0;
|
selected=-whichmenu-1;
|
||||||
|
|
||||||
|
if (!pause) pause=mypause;
|
||||||
|
|
||||||
redraw=1;
|
redraw=1;
|
||||||
clearspritelist();
|
clearspritelist();
|
||||||
@ -58,7 +69,7 @@ static int domenu(int whichmenu) {
|
|||||||
drawmenu(selected);
|
drawmenu(selected);
|
||||||
redraw=0;
|
redraw=0;
|
||||||
}
|
}
|
||||||
mypause();
|
if (!pause()) return -1;
|
||||||
scaninput();
|
scaninput();
|
||||||
++mcount;
|
++mcount;
|
||||||
|
|
||||||
@ -70,7 +81,7 @@ static int domenu(int whichmenu) {
|
|||||||
copyup();
|
copyup();
|
||||||
|
|
||||||
if(anydown()) playsound(3);
|
if(anydown()) playsound(3);
|
||||||
while(anydown())
|
while(anydown()) {
|
||||||
switch(takedown()) {
|
switch(takedown()) {
|
||||||
case MYLEFT:
|
case MYLEFT:
|
||||||
menudelta=-1;
|
menudelta=-1;
|
||||||
@ -82,29 +93,29 @@ static int domenu(int whichmenu) {
|
|||||||
return selected;
|
return selected;
|
||||||
case 'k':
|
case 'k':
|
||||||
case MYUP:
|
case MYUP:
|
||||||
if(selected) --selected;
|
if (selected) --selected;
|
||||||
else selected=menunum-1;
|
else selected=menunum-1;
|
||||||
if(whichmenu>=0)
|
if (whichmenu>=0)
|
||||||
menuhistory[whichmenu]=selected;
|
menuhistory[whichmenu]=selected;
|
||||||
redraw=1;
|
redraw=1;
|
||||||
break;
|
break;
|
||||||
case 'j':
|
case 'j':
|
||||||
case MYDOWN:
|
case MYDOWN:
|
||||||
++selected;
|
++selected;
|
||||||
if(selected==menunum) selected=0;
|
if (selected==menunum) selected=0;
|
||||||
if(whichmenu>=0)
|
if (whichmenu>=0)
|
||||||
menuhistory[whichmenu]=selected;
|
menuhistory[whichmenu]=selected;
|
||||||
redraw=1;
|
redraw=1;
|
||||||
break;
|
break;
|
||||||
case 0x1b:
|
case 0x1b:
|
||||||
if(!whichmenu && selected)
|
if (MENU_MAIN == whichmenu && menuexit != selected) {
|
||||||
{
|
selected = menuexit;
|
||||||
selected=0;
|
redraw = 1;
|
||||||
redraw=1;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
menudelta=1;
|
menudelta = 1;
|
||||||
return 0;
|
return menuexit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -114,24 +125,49 @@ static void menustart() {
|
|||||||
menunum=-1;
|
menunum=-1;
|
||||||
menuput=menustring;
|
menuput=menustring;
|
||||||
*menuput=0;
|
*menuput=0;
|
||||||
|
menuexit = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void additem(char *item,...) {
|
static void additem_s(char *item, int len) {
|
||||||
char output[256];
|
if (len < 0 || (menustring+sizeof(menustring)-menuput <= len)) return;
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, item);
|
|
||||||
|
|
||||||
vsprintf(output,item,ap);
|
|
||||||
if(menunum<0)
|
if(menunum<0)
|
||||||
menutitle=menuput;
|
menutitle=menuput;
|
||||||
else
|
else
|
||||||
menuitems[menunum]=menuput;
|
menuitems[menunum]=menuput;
|
||||||
++menunum;
|
++menunum;
|
||||||
strcpy(menuput,output);
|
memcpy(menuput,item,len+1);
|
||||||
menuput+=strlen(output)+1;
|
menuput += len+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void additem(char *item,...) {
|
||||||
|
char output[256];
|
||||||
|
va_list ap;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
va_start(ap, item);
|
||||||
|
|
||||||
|
len = vsnprintf(output,sizeof(output),item,ap);
|
||||||
|
if (len >= 256) len = 255; /* truncated string */
|
||||||
|
|
||||||
|
additem_s(output, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void addexit(char *item,...) {
|
||||||
|
char output[256];
|
||||||
|
va_list ap;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
va_start(ap, item);
|
||||||
|
|
||||||
|
len = vsnprintf(output,sizeof(output),item,ap);
|
||||||
|
if (len >= 256) len = 255; /* truncated string */
|
||||||
|
|
||||||
|
menuexit = menunum;
|
||||||
|
additem_s(output, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* end generic menu */
|
/* end generic menu */
|
||||||
|
|
||||||
/* game menues */
|
/* game menues */
|
||||||
@ -198,7 +234,7 @@ static void main_menu(void) {
|
|||||||
// additem("REMAP MOVEMENT KEYS");
|
// additem("REMAP MOVEMENT KEYS");
|
||||||
additem("START NETWORK GAME");
|
additem("START NETWORK GAME");
|
||||||
additem("JOIN NETWORK GAME");
|
additem("JOIN NETWORK GAME");
|
||||||
sel=domenu(0);
|
sel=domenu(MENU_MAIN, NULL);
|
||||||
if(!sel) {exitflag=1;break;}
|
if(!sel) {exitflag=1;break;}
|
||||||
if(sel==1) {gamemode=1;break;}
|
if(sel==1) {gamemode=1;break;}
|
||||||
if(sel==2) {gamemode=2;break;}
|
if(sel==2) {gamemode=2;break;}
|
||||||
@ -217,27 +253,27 @@ static void config_menu(void) {
|
|||||||
menustart();
|
menustart();
|
||||||
additem("GAME OPTIONS");
|
additem("GAME OPTIONS");
|
||||||
additem("RETURN TO MAIN MENU");
|
additem("RETURN TO MAIN MENU");
|
||||||
additem("DENSITY: %s",densities[configopts[GO_DENSITY]]);
|
additem("DENSITY: %s",densities[configopts.density]);
|
||||||
additem("GENEROSITY: %s",generosities[configopts[GO_GENEROSITY]]);
|
additem("GENEROSITY: %s",generosities[configopts.generosity]);
|
||||||
additem("INITIAL FLAME LENGTH: %d",configopts[GO_FLAMES]+1);
|
additem("INITIAL FLAME LENGTH: %d",configopts.flames+1);
|
||||||
additem("INITIAL NUMBER OF BOMBS: %d",configopts[GO_BOMBS]+1);
|
additem("INITIAL NUMBER OF BOMBS: %d",configopts.bombs+1);
|
||||||
sel=domenu(2);
|
sel=domenu(MENU_CONFIG, NULL);
|
||||||
if(!sel) {gamemode=0;break;}
|
if(!sel) {gamemode=0;break;}
|
||||||
if(sel==1) {
|
if(sel==1) {
|
||||||
configopts[GO_DENSITY]+=menudelta;
|
configopts.density+=menudelta;
|
||||||
configopts[GO_DENSITY]&=3;
|
configopts.density&=3;
|
||||||
}
|
}
|
||||||
if(sel==2) {
|
if(sel==2) {
|
||||||
configopts[GO_GENEROSITY]+=menudelta;
|
configopts.generosity+=menudelta;
|
||||||
configopts[GO_GENEROSITY]&=3;
|
configopts.generosity&=3;
|
||||||
}
|
}
|
||||||
if(sel==3) {
|
if(sel==3) {
|
||||||
configopts[GO_FLAMES]+=menudelta;
|
configopts.flames+=menudelta;
|
||||||
configopts[GO_FLAMES]&=7;
|
configopts.flames&=7;
|
||||||
}
|
}
|
||||||
if(sel==4) {
|
if(sel==4) {
|
||||||
configopts[GO_BOMBS]+=menudelta;
|
configopts.bombs+=menudelta;
|
||||||
configopts[GO_BOMBS]&=7;
|
configopts.bombs&=7;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -269,7 +305,7 @@ static void draw_host_game(void) {
|
|||||||
|
|
||||||
|
|
||||||
static void host_game(void) {
|
static void host_game(void) {
|
||||||
create_unique();
|
create_seed_unique();
|
||||||
if (!start_network_game()) {
|
if (!start_network_game()) {
|
||||||
failure("COULD NOT REGISTER GAME");
|
failure("COULD NOT REGISTER GAME");
|
||||||
return;
|
return;
|
||||||
@ -306,36 +342,44 @@ static void host_game(void) {
|
|||||||
gamemode=0;
|
gamemode=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int join_game_pause(void) {
|
||||||
|
if (find_more_games()) return 0;
|
||||||
|
mypause();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static void join_game(void) {
|
static void join_game(void) {
|
||||||
int i;
|
int i;
|
||||||
int sel;
|
int sel = -1;
|
||||||
|
|
||||||
if (!searchgames(gameversion)) {
|
if (!searchgames()) {
|
||||||
gamemode = 0;
|
gamemode = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (gamelistsize == 0) {
|
|
||||||
|
menuhistory[MENU_JOIN] = 0;
|
||||||
|
|
||||||
|
while (-1 == sel) {
|
||||||
menustart();
|
menustart();
|
||||||
additem("NO GAMES AVAILABLE");
|
if (gamelistsize == 0) {
|
||||||
domenu(-1);
|
additem("JOIN NETWORK GAME - NO GAMES AVAILABLE");
|
||||||
|
addexit("EXIT");
|
||||||
|
} else {
|
||||||
|
additem("JOIN NETWORK GAME");
|
||||||
|
for (i = 0; i < gamelistsize; i++) {
|
||||||
|
additem(gamelistentries[i].name);
|
||||||
|
}
|
||||||
|
addexit("EXIT");
|
||||||
|
}
|
||||||
|
sel = domenu(MENU_JOIN, join_game_pause);
|
||||||
|
}
|
||||||
|
stop_search();
|
||||||
|
|
||||||
|
if(menuexit == sel || !gamelistsize) {
|
||||||
gamemode=0;
|
gamemode=0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if(!tryjoin(sel)) {
|
||||||
menustart();
|
|
||||||
additem("JOIN NETWORK GAME");
|
|
||||||
additem("EXIT");
|
|
||||||
|
|
||||||
for (i = 0; i < gamelistsize; i++) {
|
|
||||||
additem(gamelistentries[i].name);
|
|
||||||
}
|
|
||||||
|
|
||||||
sel=domenu(-1);
|
|
||||||
if(!sel) {
|
|
||||||
gamemode=0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(!tryjoin(sel-1)) {
|
|
||||||
gamemode=0;
|
gamemode=0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
2
menu.h
2
menu.h
@ -5,6 +5,6 @@ void mainloop(void);
|
|||||||
|
|
||||||
int iterate(void); /* bomber.c */
|
int iterate(void); /* bomber.c */
|
||||||
|
|
||||||
extern unsigned char configopts[10];
|
extern struct GameOptions configopts;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
417
network.c
417
network.c
@ -9,7 +9,7 @@
|
|||||||
#define MAXMSG 4096
|
#define MAXMSG 4096
|
||||||
|
|
||||||
int udpsocket;
|
int udpsocket;
|
||||||
const unsigned char gameversion[4]={0xda,0x01,0x00,0x04};
|
const unsigned char gameversion[4]={0xda,0x01,0x00,0x05};
|
||||||
|
|
||||||
struct netnode netnodes[64];
|
struct netnode netnodes[64];
|
||||||
|
|
||||||
@ -36,6 +36,84 @@ unsigned char actions[MAXNETNODES];
|
|||||||
unsigned char latestactions[MAXNETNODES];
|
unsigned char latestactions[MAXNETNODES];
|
||||||
long latestcounts[MAXNETNODES];
|
long latestcounts[MAXNETNODES];
|
||||||
|
|
||||||
|
enum network_packet_types {
|
||||||
|
PKT_ACK, /* perfect copy of packet received */
|
||||||
|
/* join / host game */
|
||||||
|
/* slave -> master packets */
|
||||||
|
PKT_JOIN, /* 4 bytes version #, 4 bytes joinunique #, 16 bytes name */
|
||||||
|
PKT_QUIT, /* 4 bytes unique # */
|
||||||
|
/* master -> slave packets */
|
||||||
|
PKT_INVITE, /* 4 bytes unique #, 1 byte your slot (0xff for kick, no data following it) #, any # of 1:slot,16:name sets (-1 end) */
|
||||||
|
PKT_BEGIN, /* clone of INVITE */
|
||||||
|
PKT_CONFIG, /* 4 bytes unique #, config */
|
||||||
|
PKT_ACCEPT, /* 4 bytes join unique #, 132 bytes seed + unique #, config, slot info (see invite) */
|
||||||
|
PKT_REJECT, /* 4 bytes join unique #, 4 bytes version #, 1: reason */
|
||||||
|
/* ingame actions */
|
||||||
|
/* slave -> master packets */
|
||||||
|
PKT_MYDATA, /* 4 bytes unique #,4 bytes frame #, 1 byte data */
|
||||||
|
/* master -> slave packets */
|
||||||
|
PKT_STEP, /* 4 bytes unique #, 4 bytes frame #, 8 bytes ACT_* */
|
||||||
|
|
||||||
|
PKT_INVALID = 0xff
|
||||||
|
};
|
||||||
|
|
||||||
|
enum reject_reason {
|
||||||
|
REJECT_FULL,
|
||||||
|
REJECT_VERSION
|
||||||
|
/* TODO: password? */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* all bytes stored MSB first */
|
||||||
|
|
||||||
|
/*
|
||||||
|
game startup:
|
||||||
|
<master and matcher>
|
||||||
|
Master: send REGISTER to matcher with optional password, wait for ack. If
|
||||||
|
timout, resend.
|
||||||
|
matcher: Wait for REGISTER packet, when received maintain database. respond
|
||||||
|
to sender with ACK. REGISTER packet can close a game also. The REGISTER
|
||||||
|
packet sent by the master has a unique word to be used to avoid confusion.
|
||||||
|
REGISTER packet also contains a game version #
|
||||||
|
|
||||||
|
After master registers game and receives ACK, just waits for slaves to contact.
|
||||||
|
|
||||||
|
<slave and matcher>
|
||||||
|
slave: send QUERY to matcher with optional password, wait for INFO, if timeout,
|
||||||
|
resend.
|
||||||
|
matcher: respond to QUERY with INFO packet. matcher need not maintain any
|
||||||
|
database for slave requests. INFO packet contains IP addr and port for each
|
||||||
|
master machine that matches the QUERY spec (ALL or password). Only a
|
||||||
|
certain MAX # of entries are sent if there are too many to choose from.
|
||||||
|
|
||||||
|
<slave and master>
|
||||||
|
slave: send JOIN to master, wait for INVITE. If timeout, resend. JOIN packet
|
||||||
|
contains the unique word the master created. JOIN also contains username.
|
||||||
|
master: Respond to JOIN with INVITE. INVITE contains unique word from JOIN
|
||||||
|
packet. INVITE either contains NO meaning game no longer exists or is closed
|
||||||
|
or player is not invited. IF yes, INVITE contains info on other players
|
||||||
|
already in the game (username and slot # for each). Master allocates the
|
||||||
|
slots and avoids confusion based on IP addr and port #. INVITE also contains
|
||||||
|
game options structure. Whenever a new player JOINS and is admitted, master
|
||||||
|
sends updated INVITE packets to everyone already in the JOIN list. Whenever
|
||||||
|
master changes game options, master sends out another set of INVITES
|
||||||
|
|
||||||
|
Duplicate JOINS are answered with updated INVITE but nothing changes as far
|
||||||
|
as allocation.
|
||||||
|
|
||||||
|
Master player launches game after he's satisfied everyone has joined.
|
||||||
|
|
||||||
|
Master sends BEGIN packet to everyone. BEGIN is identical to INVITE except
|
||||||
|
that the data is final. Slave must respond with its first MYDATA packet with
|
||||||
|
frame # of 0. If master times out waiting, master sends duplicate BEGIN to
|
||||||
|
wayward slaves. Once master has received MYDATA from everyone, game starts.
|
||||||
|
|
||||||
|
Within game slave sends MYDATA to master and waits for STEP packet. If
|
||||||
|
timeout, slave sends duplicate MYDATA.
|
||||||
|
|
||||||
|
If master times out waiting for a slave's MYDATA, slave gets dropped. MYDATAs
|
||||||
|
received will be answered with PKT_QUIT.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/* Network I/O, building/checking packets */
|
/* Network I/O, building/checking packets */
|
||||||
@ -132,17 +210,17 @@ static Uint32 readuint32(unsigned char *p) {
|
|||||||
return (p[0]<<24L) | (p[1]<<16L) | (p[2]<<8) | p[3];
|
return (p[0]<<24L) | (p[1]<<16L) | (p[2]<<8) | p[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned char* writeunique(unsigned char *p) {
|
static unsigned char* write_unique(unsigned char *p) {
|
||||||
memcpy(p, &network_unique, 4);
|
memcpy(p, &network_unique, 4);
|
||||||
return p + 4;
|
return p + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned char* writeversion(unsigned char *p) {
|
static unsigned char* write_version(unsigned char *p) {
|
||||||
memcpy(p, &gameversion, 4);
|
memcpy(p, &gameversion, 4);
|
||||||
return p + 4;
|
return p + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int isvalidmsg() {
|
static int isvalidmsg_from_slave() {
|
||||||
int i;
|
int i;
|
||||||
void *host;
|
void *host;
|
||||||
void *port;
|
void *port;
|
||||||
@ -158,6 +236,13 @@ static int isvalidmsg() {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int isvalidmsg_from_master() {
|
||||||
|
if (sender.sin_family != mastername.sin_family
|
||||||
|
|| sender.sin_addr.s_addr != mastername.sin_addr.s_addr
|
||||||
|
|| sender.sin_port != mastername.sin_port) return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Handling game actions */
|
/* Handling game actions */
|
||||||
|
|
||||||
static void addactions(void) {
|
static void addactions(void) {
|
||||||
@ -190,7 +275,7 @@ static void sendactions(int which) {
|
|||||||
unsigned char msg[512];
|
unsigned char msg[512];
|
||||||
|
|
||||||
msg[0] = PKT_STEP;
|
msg[0] = PKT_STEP;
|
||||||
writeunique(msg+1);
|
write_unique(msg+1);
|
||||||
writeuint32(msg+5, actioncount);
|
writeuint32(msg+5, actioncount);
|
||||||
memcpy(msg+9,actionblock,MAXNETNODES*ACTIONHIST);
|
memcpy(msg+9,actionblock,MAXNETNODES*ACTIONHIST);
|
||||||
putmsg(&netnodes[which].netname,msg,MAXNETNODES*ACTIONHIST+9);
|
putmsg(&netnodes[which].netname,msg,MAXNETNODES*ACTIONHIST+9);
|
||||||
@ -200,7 +285,7 @@ static void sendmine(int frame) {
|
|||||||
unsigned char msg[64];
|
unsigned char msg[64];
|
||||||
|
|
||||||
msg[0] = PKT_MYDATA;
|
msg[0] = PKT_MYDATA;
|
||||||
writeunique(msg+1);
|
write_unique(msg+1);
|
||||||
writeuint32(msg+5, frame);
|
writeuint32(msg+5, frame);
|
||||||
msg[9]=myaction;
|
msg[9]=myaction;
|
||||||
putmsg(&mastername,msg,10);
|
putmsg(&mastername,msg,10);
|
||||||
@ -229,7 +314,7 @@ int networktraffic(void) {
|
|||||||
// for example JOIN on frame 0, respond with BEGIN if player already in game
|
// for example JOIN on frame 0, respond with BEGIN if player already in game
|
||||||
// respond with uninvite INVITE on JOIN from others
|
// respond with uninvite INVITE on JOIN from others
|
||||||
if(length<10) continue;
|
if(length<10) continue;
|
||||||
whosent=isvalidmsg();
|
whosent = isvalidmsg_from_slave();
|
||||||
if(whosent<=0) continue;
|
if(whosent<=0) continue;
|
||||||
count=readuint32(mesg+5);
|
count=readuint32(mesg+5);
|
||||||
if(count>latestcounts[whosent]) {
|
if(count>latestcounts[whosent]) {
|
||||||
@ -333,120 +418,86 @@ void freesocket(void) {
|
|||||||
|
|
||||||
/* Join / Host Games */
|
/* Join / Host Games */
|
||||||
|
|
||||||
static void buildinform(unsigned char type) {
|
/* Master side */
|
||||||
unsigned char *put;
|
|
||||||
|
static unsigned char* write_inform(unsigned char* put) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
put=mesg;
|
*put++ = 0xff; /* slot specific for each slave */
|
||||||
*put++=type;
|
|
||||||
put = writeunique(put);
|
|
||||||
++put; // slot specific for each slave
|
|
||||||
for (i = 0; i < MAXNETNODES; ++i) {
|
for (i = 0; i < MAXNETNODES; ++i) {
|
||||||
if(!netnodes[i].used) continue;
|
if(!netnodes[i].used) continue;
|
||||||
*put++=i;
|
*put++ = i;
|
||||||
memmove(put,netnodes[i].name,16);
|
memmove(put, netnodes[i].name, 16);
|
||||||
put+=16;
|
put += 16;
|
||||||
}
|
}
|
||||||
*put++=0xff;
|
*put++ = 0xff;
|
||||||
memcpy(put, configopts, sizeof(configopts));
|
return put;
|
||||||
put += sizeof(configopts);
|
}
|
||||||
|
|
||||||
|
static void send_inform_all(unsigned char type) {
|
||||||
|
int i;
|
||||||
|
unsigned char *put = mesg;
|
||||||
|
|
||||||
|
*put++ = type;
|
||||||
|
put = write_unique(put);
|
||||||
|
put = write_inform(put);
|
||||||
|
informsize = put-mesg;
|
||||||
|
|
||||||
|
for(i=1;i<MAXNETNODES;++i) {
|
||||||
|
if(netnodes[i].used) {
|
||||||
|
mesg[5] = i;
|
||||||
|
putmsg(&netnodes[i].netname, mesg, informsize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned char* write_config(unsigned char* put) {
|
||||||
|
*put++ = configopts.density;
|
||||||
|
*put++ = configopts.flames;
|
||||||
|
*put++ = configopts.bombs;
|
||||||
|
*put++ = configopts.generosity;
|
||||||
|
return put;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void build_config() {
|
||||||
|
unsigned char *put;
|
||||||
|
|
||||||
|
put=mesg;
|
||||||
|
*put++=PKT_CONFIG;
|
||||||
|
put = write_config(put);
|
||||||
informsize=put-mesg;
|
informsize=put-mesg;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void inform1(int which) {
|
static void send_config1(int which) {
|
||||||
mesg[5]=which;
|
|
||||||
putmsg(&netnodes[which].netname,mesg,informsize);
|
putmsg(&netnodes[which].netname,mesg,informsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void inform(unsigned char type) {
|
void send_config() {
|
||||||
int i;
|
int i;
|
||||||
buildinform(type);
|
build_config();
|
||||||
for(i=1;i<MAXNETNODES;++i)
|
for (i = 1; i < MAXNETNODES; ++i)
|
||||||
if(netnodes[i].used)
|
if (netnodes[i].used)
|
||||||
inform1(i);
|
send_config1(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
//returns 0=ignore packet,1=we're rejected,2=INVITE,3=BEGIN
|
static void send_reject(struct sockaddr_in *toname, Uint32 network_join_unique, unsigned char reason) {
|
||||||
int scaninvite(int msec) {
|
mesg[0] = PKT_REJECT;
|
||||||
int i, size;
|
memcpy(mesg+1, &network_join_unique, sizeof(network_join_unique));
|
||||||
unsigned char *take;
|
write_version(mesg+5);
|
||||||
Uint32 unique = 0;
|
mesg[9] = reason;
|
||||||
|
putmsg(&sender,mesg,10);
|
||||||
size = getmsg(msec);
|
|
||||||
|
|
||||||
if (size < 6) return 0;
|
|
||||||
if (*mesg!=PKT_INVITE && *mesg!=PKT_BEGIN) return 0;
|
|
||||||
if (sender.sin_family != mastername.sin_family
|
|
||||||
|| sender.sin_addr.s_addr != mastername.sin_addr.s_addr
|
|
||||||
|| sender.sin_port != mastername.sin_port) return 0;
|
|
||||||
|
|
||||||
myslot=mesg[5];
|
|
||||||
if (6 == size || 0xff == mesg[5] || 0xff == mesg[6]) return 1;
|
|
||||||
|
|
||||||
/* update unique */
|
|
||||||
memcpy(&unique, mesg+1, 4);
|
|
||||||
if (unique != network_unique)
|
|
||||||
set_unique(ntohl(unique));
|
|
||||||
|
|
||||||
memset(netnodes,0,sizeof(netnodes));
|
|
||||||
size-=6;
|
|
||||||
take=mesg+6;
|
|
||||||
while(*take!=0xff && size>=17) {
|
|
||||||
if((i=*take)<MAXNETNODES) {
|
|
||||||
netnodes[i].used=1;
|
|
||||||
memmove(netnodes[i].name,take+1,16);
|
|
||||||
}
|
|
||||||
take+=17;
|
|
||||||
size-=17;
|
|
||||||
}
|
|
||||||
take++; size--; /* read 0xff */
|
|
||||||
|
|
||||||
if(*mesg==PKT_INVITE) {
|
|
||||||
return 2;
|
|
||||||
} else { /* BEGIN */
|
|
||||||
if (size != sizeof(configopts)) {
|
|
||||||
fprintf(stderr, "PKT_BEGIN has wrong size: %i != %i\n", size, (int) sizeof(configopts));
|
|
||||||
return 1; /* broken packet */
|
|
||||||
}
|
|
||||||
set_game_options(take);
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int send_join(struct sockaddr_in *netname, char playername[16]) {
|
static void send_accept(Uint32 network_join_unique) {
|
||||||
int res = 0;
|
unsigned char *put = mesg;
|
||||||
long now;
|
|
||||||
|
|
||||||
set_unique(-1); /* reset unique and random */
|
*put++ = PKT_ACCEPT;
|
||||||
|
memcpy(put, &network_join_unique, sizeof(network_join_unique));
|
||||||
mastername = *netname;
|
put += sizeof(network_join_unique);
|
||||||
*regpacket=PKT_JOIN;
|
put = write_seed_unique(put);
|
||||||
writeversion(regpacket + 1);
|
put = write_config(put);
|
||||||
memmove(regpacket+5, playername, 16);
|
put = write_inform(put);
|
||||||
now=longtime();
|
putmsg(&sender,mesg,put-mesg);
|
||||||
while(longtime()-now<10) {
|
|
||||||
putmsg(&mastername,regpacket,1+4+16);
|
|
||||||
if (0 == (res=scaninvite(1000))) continue;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void send_quit() {
|
|
||||||
long now;
|
|
||||||
int size;
|
|
||||||
|
|
||||||
*regpacket = PKT_QUIT;
|
|
||||||
writeunique(regpacket+1);
|
|
||||||
now=longtime();
|
|
||||||
while(longtime()-now<10) {
|
|
||||||
putmsg(&mastername,regpacket,5);
|
|
||||||
size=getmsg(1000);
|
|
||||||
if(size<6) continue;
|
|
||||||
if(mesg[0] != PKT_ACK || mesg[1] != PKT_QUIT) continue;
|
|
||||||
if (isvalidunique(mesg+2))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int start_network_game() {
|
int start_network_game() {
|
||||||
@ -459,21 +510,21 @@ int start_network_game() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int begin_network_game() {
|
int begin_network_game() {
|
||||||
inform(PKT_BEGIN);
|
send_inform_all(PKT_BEGIN);
|
||||||
network = NETWORK_MASTER;
|
network = NETWORK_MASTER;
|
||||||
/* TODO: wait for ack */
|
/* TODO: wait for ack */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void send_invites() {
|
void send_invites() {
|
||||||
inform(PKT_INVITE);
|
send_inform_all(PKT_INVITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cancel_network_game() {
|
void cancel_network_game() {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
mesg[0] = PKT_INVITE;
|
mesg[0] = PKT_INVITE;
|
||||||
writeunique(mesg+1);
|
write_unique(mesg+1);
|
||||||
mesg[5] = 0xff;
|
mesg[5] = 0xff;
|
||||||
|
|
||||||
for(i=1;i<MAXNETNODES;++i) {
|
for(i=1;i<MAXNETNODES;++i) {
|
||||||
@ -487,11 +538,17 @@ int handle_joins() {
|
|||||||
int size;
|
int size;
|
||||||
int i, j;
|
int i, j;
|
||||||
unsigned char temp[64];
|
unsigned char temp[64];
|
||||||
|
Uint32 network_join_unique;
|
||||||
|
|
||||||
size=getmsg(40);
|
size=getmsg(40);
|
||||||
switch (*mesg) {
|
switch (*mesg) {
|
||||||
case PKT_JOIN:
|
case PKT_JOIN:
|
||||||
if (size < 21 || !isvalidversion(mesg+1)) return 0;
|
if (size < 25) return 0;
|
||||||
|
memcpy(&network_join_unique, mesg+5, sizeof(network_join_unique));
|
||||||
|
if (!isvalidversion(mesg+1)) {
|
||||||
|
send_reject(&sender, network_join_unique, REJECT_VERSION);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case PKT_QUIT:
|
case PKT_QUIT:
|
||||||
if (size < 5 || !isvalidunique(mesg+1)) return 0;
|
if (size < 5 || !isvalidunique(mesg+1)) return 0;
|
||||||
@ -519,23 +576,21 @@ int handle_joins() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(*mesg==PKT_QUIT) {
|
switch (*mesg) {
|
||||||
|
case PKT_QUIT:
|
||||||
if(i < MAXNETNODES) /* if host found, reset entry */
|
if(i < MAXNETNODES) /* if host found, reset entry */
|
||||||
memset(netnodes+i,0,sizeof(struct netnode));
|
memset(netnodes+i,0,sizeof(struct netnode));
|
||||||
/* send always ACK for QUITs */
|
/* send always ACK for QUITs */
|
||||||
*temp=PKT_ACK;
|
*temp=PKT_ACK;
|
||||||
memmove(temp+1,mesg,5);
|
memmove(temp+1,mesg,5);
|
||||||
putmsg(&sender,temp,6);
|
putmsg(&sender,temp,6);
|
||||||
} else {
|
break;
|
||||||
|
case PKT_JOIN:
|
||||||
if (i==MAXNETNODES && j==-1) { /* reject */
|
if (i==MAXNETNODES && j==-1) { /* reject */
|
||||||
*mesg=PKT_INVITE;
|
send_reject(&sender, network_join_unique, REJECT_FULL);
|
||||||
writeunique(mesg+1);
|
|
||||||
mesg[5]=0xff;
|
|
||||||
putmsg(&sender,mesg,6);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* no explicit ack, send invites to all later */
|
|
||||||
if(i==MAXNETNODES) i=j;
|
if(i==MAXNETNODES) i=j;
|
||||||
memmove(&netnodes[i].netname.sin_addr.s_addr,
|
memmove(&netnodes[i].netname.sin_addr.s_addr,
|
||||||
&sender.sin_addr.s_addr,4);
|
&sender.sin_addr.s_addr,4);
|
||||||
@ -543,8 +598,138 @@ int handle_joins() {
|
|||||||
&sender.sin_port,2);
|
&sender.sin_port,2);
|
||||||
netnodes[i].netname.sin_family=AF_INET;
|
netnodes[i].netname.sin_family=AF_INET;
|
||||||
netnodes[i].used=1;
|
netnodes[i].used=1;
|
||||||
memmove(netnodes[i].name,mesg+5,16);
|
memcpy(netnodes[i].name,mesg+9,16);
|
||||||
netnodes[i].name[15] = '\0';
|
netnodes[i].name[15] = '\0';
|
||||||
|
|
||||||
|
send_accept(network_join_unique);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Client side */
|
||||||
|
|
||||||
|
static int read_inform(unsigned char** pbuf, int *psize) {
|
||||||
|
unsigned char *buf = *pbuf;
|
||||||
|
int size = *psize;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (size < 1) return 0;
|
||||||
|
myslot = *buf++; size--;
|
||||||
|
if (0xff == myslot) return 1;
|
||||||
|
|
||||||
|
if (size < 1) return 0;
|
||||||
|
while (0xff != *buf) {
|
||||||
|
i = *buf++; size--;
|
||||||
|
if (size < 17 || i >= MAXNETNODES) return 0;
|
||||||
|
netnodes[i].used = 1;
|
||||||
|
memcpy(netnodes[i].name, buf, 16);
|
||||||
|
buf += 16;
|
||||||
|
size -= 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
*psize = size;
|
||||||
|
*pbuf = buf;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void read_config(unsigned char* buf) {
|
||||||
|
GameOptions opts;
|
||||||
|
memset(&opts, 0, sizeof(opts));
|
||||||
|
opts.density = *buf++;
|
||||||
|
opts.flames = *buf++;
|
||||||
|
opts.bombs = *buf++;
|
||||||
|
opts.generosity = *buf++;
|
||||||
|
set_game_options(&opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* returns 0=ignore packet,1=we're rejected,2=INVITE/CONFIG,3=BEGIN */
|
||||||
|
int scaninvite(int msec) {
|
||||||
|
int size;
|
||||||
|
unsigned char *take;
|
||||||
|
|
||||||
|
size = getmsg(msec);
|
||||||
|
|
||||||
|
if (size < 6) return 0;
|
||||||
|
if (*mesg!=PKT_INVITE && *mesg!=PKT_BEGIN && *mesg!=PKT_CONFIG) return 0;
|
||||||
|
if (!isvalidmsg_from_master()) return 0;
|
||||||
|
if (!isvalidunique(mesg+1)) return 0;
|
||||||
|
|
||||||
|
take = mesg+5;
|
||||||
|
size -= 5;
|
||||||
|
|
||||||
|
switch (*mesg) {
|
||||||
|
case PKT_INVITE:
|
||||||
|
case PKT_BEGIN:
|
||||||
|
if (!read_inform(&take, &size)) return 0;
|
||||||
|
if (0xff == myslot) return 1; /* master closed game */
|
||||||
|
break;
|
||||||
|
case PKT_CONFIG:
|
||||||
|
if (size < 4) return 0;
|
||||||
|
read_config(take);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*mesg == PKT_BEGIN) {
|
||||||
|
return 3;
|
||||||
|
} else {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int send_join(struct sockaddr_in *netname, char playername[16]) {
|
||||||
|
int size;
|
||||||
|
long now;
|
||||||
|
Uint32 join_unique = gtime();
|
||||||
|
unsigned char *buf;
|
||||||
|
|
||||||
|
mastername = *netname;
|
||||||
|
*regpacket=PKT_JOIN;
|
||||||
|
write_version(regpacket + 1);
|
||||||
|
writeuint32(regpacket+5, join_unique);
|
||||||
|
memcpy(regpacket+9, playername, 16);
|
||||||
|
now=longtime();
|
||||||
|
putmsg(&mastername,regpacket,1+4+4+16);
|
||||||
|
while(longtime()-now < 3) {
|
||||||
|
if (0 == (size = getmsg(1000))) {
|
||||||
|
/* got no message, send join again */
|
||||||
|
putmsg(&mastername,regpacket,1+4+4+16);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (size < 5) continue;
|
||||||
|
if (readuint32(mesg+1) != join_unique) continue;
|
||||||
|
switch (*mesg) {
|
||||||
|
case PKT_ACCEPT:
|
||||||
|
if (size < 1+4+132+4+2) continue;
|
||||||
|
read_seed_unique(mesg + 5);
|
||||||
|
read_config(mesg+137);
|
||||||
|
buf = mesg+141;
|
||||||
|
size -= 141;
|
||||||
|
if (!read_inform(&buf,&size)) return 0;
|
||||||
|
return 2;
|
||||||
|
case PKT_REJECT:
|
||||||
|
/* TODO: print reject message */
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void send_quit() {
|
||||||
|
long now;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
*regpacket = PKT_QUIT;
|
||||||
|
write_unique(regpacket+1);
|
||||||
|
now=longtime();
|
||||||
|
while(longtime()-now<10) {
|
||||||
|
putmsg(&mastername,regpacket,5);
|
||||||
|
size=getmsg(1000);
|
||||||
|
if(size<6) continue;
|
||||||
|
if(mesg[0] != PKT_ACK || mesg[1] != PKT_QUIT) continue;
|
||||||
|
if (isvalidunique(mesg+2))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -17,12 +17,12 @@ void getsocket(void);
|
|||||||
void freesocket(void);
|
void freesocket(void);
|
||||||
|
|
||||||
int send_join(struct sockaddr_in *netname, char playername[16]);
|
int send_join(struct sockaddr_in *netname, char playername[16]);
|
||||||
|
void send_config();
|
||||||
void send_quit();
|
void send_quit();
|
||||||
int scaninvite(int msec);
|
int scaninvite(int msec);
|
||||||
|
|
||||||
int start_network_game();
|
int start_network_game();
|
||||||
int handle_joins();
|
int handle_joins();
|
||||||
// void inform(unsigned char type);
|
|
||||||
int begin_network_game();
|
int begin_network_game();
|
||||||
void send_invites();
|
void send_invites();
|
||||||
void cancel_network_game();
|
void cancel_network_game();
|
||||||
@ -53,6 +53,4 @@ extern unsigned char actions[MAXNETNODES];
|
|||||||
extern unsigned char latestactions[MAXNETNODES];
|
extern unsigned char latestactions[MAXNETNODES];
|
||||||
extern long latestcounts[MAXNETNODES];
|
extern long latestcounts[MAXNETNODES];
|
||||||
|
|
||||||
// extern int netframe;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
115
utils.c
115
utils.c
@ -5,6 +5,11 @@
|
|||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
int volatile hc=0;
|
int volatile hc=0;
|
||||||
char volatile interrupted=0;
|
char volatile interrupted=0;
|
||||||
static Uint32 cur_unique;
|
static Uint32 cur_unique;
|
||||||
@ -18,6 +23,112 @@ Uint32 longtime(void) {
|
|||||||
return gtime()/1000;
|
return gtime()/1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* surf random generator: x (Daniel J. Bernstein) */
|
||||||
|
#define ROT(x, b) (((x) << (b)) | ((x) >> (32-(b))))
|
||||||
|
#define MUSH(i, b) x = t[i] += (((x ^ seed[i]) + sum) ^ ROT(x,b))
|
||||||
|
static void surf(Uint32 out[8], const Uint32 in[12], const Uint32 seed[32]) {
|
||||||
|
Uint32 t[12], x, sum = 0;
|
||||||
|
int r, i, loop;
|
||||||
|
for (i = 0; i < 12; ++i) t[i] = in[i] ^ seed[12 + i];
|
||||||
|
for (i = 0; i < 8; ++i) out[i] = seed[24 + i];
|
||||||
|
x = t[11];
|
||||||
|
for (loop = 0; loop < 2; ++loop) {
|
||||||
|
for (r = 0; r < 16; ++r) {
|
||||||
|
sum += 0x9e3779b9;
|
||||||
|
MUSH(0, 5); MUSH(1, 7); MUSH(2, 9); MUSH(3, 13);
|
||||||
|
MUSH(4, 5); MUSH(5, 7); MUSH(6, 9); MUSH(7, 13);
|
||||||
|
MUSH(8, 5); MUSH(9, 7); MUSH(10, 9); MUSH(11, 13);
|
||||||
|
}
|
||||||
|
for (i = 0; i < 8; ++i) out[i] ^= t[i+4];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#undef ROT
|
||||||
|
#undef MUSH
|
||||||
|
|
||||||
|
static Uint32 surf_seed[32];
|
||||||
|
static Uint32 surf_in[12], surf_out[8];
|
||||||
|
static int surf_left;
|
||||||
|
|
||||||
|
static Uint32 surf_init(void) {
|
||||||
|
Uint32 unique = 0;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
memset(surf_in, 0, sizeof(surf_in));
|
||||||
|
memset(surf_out, 0, sizeof(surf_out));
|
||||||
|
memset(surf_seed, 0, sizeof(surf_seed));
|
||||||
|
surf_left = 0;
|
||||||
|
|
||||||
|
fd = open("/dev/urandom", O_RDONLY);
|
||||||
|
if (-1 == fd) {
|
||||||
|
Uint32 genseed[4][8];
|
||||||
|
surf_seed[0] = surf_seed[1] = gtime();
|
||||||
|
surf_in[0]++; surf(genseed[0], surf_in, surf_seed);
|
||||||
|
surf_in[0]++; surf(genseed[1], surf_in, surf_seed);
|
||||||
|
surf_in[0]++; surf(genseed[2], surf_in, surf_seed);
|
||||||
|
surf_in[0]++; surf(genseed[3], surf_in, surf_seed);
|
||||||
|
memcpy(surf_seed, genseed[0], 32);
|
||||||
|
memcpy(surf_seed, genseed[1], 32);
|
||||||
|
memcpy(surf_seed, genseed[2], 32);
|
||||||
|
memcpy(surf_seed, genseed[3], 32);
|
||||||
|
surf_in[0] = gtime();
|
||||||
|
surf(genseed[0], surf_in, surf_seed);
|
||||||
|
surf_in[0] = 0;
|
||||||
|
unique = genseed[0][0];
|
||||||
|
} else {
|
||||||
|
read(fd, &unique, sizeof(unique));
|
||||||
|
read(fd, &surf_seed, sizeof(surf_seed));
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return unique;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Uint32 surf_random(void) {
|
||||||
|
if (surf_left == 0) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; (i < 12) && !(++surf_in[i]); i++) ;
|
||||||
|
surf_left = 8;
|
||||||
|
surf(surf_out, surf_in, surf_seed);
|
||||||
|
}
|
||||||
|
return surf_out[--surf_left];
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_seed_unique(unsigned char *buf) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
memset(surf_in, 0, sizeof(surf_in));
|
||||||
|
memset(surf_out, 0, sizeof(surf_out));
|
||||||
|
surf_left = 0;
|
||||||
|
|
||||||
|
memcpy(&surf_seed, buf, sizeof(surf_seed));
|
||||||
|
memcpy(&network_unique, buf+sizeof(surf_seed), sizeof(network_unique));
|
||||||
|
cur_unique = ntohl(network_unique);
|
||||||
|
for (i = 0; i < 32; i++) surf_seed[i] = ntohl(surf_seed[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char* write_seed_unique(unsigned char *buf) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 32; i++) {
|
||||||
|
Uint32 l = htonl(surf_seed[i]);
|
||||||
|
memcpy(buf, &l, sizeof(l));
|
||||||
|
buf += sizeof(l);
|
||||||
|
}
|
||||||
|
memcpy(buf, &network_unique, sizeof(network_unique));
|
||||||
|
buf += sizeof(network_unique);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void create_seed_unique(void) {
|
||||||
|
cur_unique = surf_init();
|
||||||
|
network_unique = htonl(cur_unique);
|
||||||
|
}
|
||||||
|
|
||||||
|
int myrand(void) {
|
||||||
|
return surf_random() & 0xffffu;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* random generator */
|
/* random generator */
|
||||||
|
|
||||||
#define TAP1 250
|
#define TAP1 250
|
||||||
@ -87,18 +198,20 @@ void set_unique(Uint32 unique) {
|
|||||||
Uint32 get_unique(void) {
|
Uint32 get_unique(void) {
|
||||||
return cur_unique;
|
return cur_unique;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void nomem(char *str) {
|
void nomem(char *str) {
|
||||||
printf("No memory!!![%s]\n",str);
|
printf("No memory!!![%s]\n",str);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mypause(void) {
|
int mypause(void) {
|
||||||
while(!interrupted) {
|
while(!interrupted) {
|
||||||
pollinput();
|
pollinput();
|
||||||
SDL_Delay(1);
|
SDL_Delay(1);
|
||||||
}
|
}
|
||||||
interrupted=0;
|
interrupted=0;
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Uint32 sdlhandler(Uint32 time) {
|
static Uint32 sdlhandler(Uint32 time) {
|
||||||
|
9
utils.h
9
utils.h
@ -4,9 +4,16 @@
|
|||||||
Uint32 gtime(void);
|
Uint32 gtime(void);
|
||||||
Uint32 longtime(void);
|
Uint32 longtime(void);
|
||||||
|
|
||||||
|
#if 0
|
||||||
void create_unique(void);
|
void create_unique(void);
|
||||||
void set_unique(Uint32 unique);
|
void set_unique(Uint32 unique);
|
||||||
Uint32 get_unique(void);
|
Uint32 get_unique(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SEED_UNIQUE_SIZE (32*4+4)
|
||||||
|
void read_seed_unique(unsigned char *buf);
|
||||||
|
unsigned char* write_seed_unique(unsigned char *buf);
|
||||||
|
void create_seed_unique(void);
|
||||||
|
|
||||||
extern Uint32 network_unique;
|
extern Uint32 network_unique;
|
||||||
|
|
||||||
@ -14,7 +21,7 @@ int myrand(void);
|
|||||||
|
|
||||||
void nomem(char *str);
|
void nomem(char *str);
|
||||||
|
|
||||||
void mypause(void);
|
int mypause(void);
|
||||||
void pulseon(void);
|
void pulseon(void);
|
||||||
|
|
||||||
void hexdump(unsigned char *p, int len);
|
void hexdump(unsigned char *p, int len);
|
||||||
|
Loading…
Reference in New Issue
Block a user