* changed behaviour of network games with internal errors (because of
different client frame counters) from immediately terminating R'n'D
to displaying an error message requester and stopping only the game
(also to prevent impression of crashes under non command-line runs)
* fixed playing network games with the EMC engine (did not work before)
* fixed bug with not scrolling the screen in multi-player mode with the
focus on player 1 when all players are moving in different directions
* fixed bug with keeping pointer to gadget even after its deallocation
* uploaded pre-release (test) version 3.2.0-7 binary and source code
+2006-03-29
+ * changed behaviour of network games with internal errors (because of
+ different client frame counters) from immediately terminating R'n'D
+ to displaying an error message requester and stopping only the game
+ (also to prevent impression of crashes under non command-line runs)
+ * fixed playing network games with the EMC engine (did not work before)
+ * fixed bug with not scrolling the screen in multi-player mode with the
+ focus on player 1 when all players are moving in different directions
+ * fixed bug with keeping pointer to gadget even after its deallocation
+
+2006-03-22
+ * uploaded pre-release (test) version 3.2.0-7 binary and source code
+
2006-03-19
* code cleanup for game action control for R'n'D and EMC game engine
2006-03-19
* code cleanup for game action control for R'n'D and EMC game engine
-#define COMPILE_DATE_STRING "[2006-03-23 10:55]"
+#define COMPILE_DATE_STRING "[2006-03-29 19:24]"
+#if 0
+ Error(ERR_NETWORK_CLIENT, "advancing frame counter from %d to %d",
+ FrameCounter, FrameCounter + 1);
+#endif
+
/* advance frame counters (global frame counter and time frame counter) */
FrameCounter++;
TimeFrames++;
/* advance frame counters (global frame counter and time frame counter) */
FrameCounter++;
TimeFrames++;
void StartGameActions(boolean init_network_game, boolean record_tape,
long random_seed)
{
void StartGameActions(boolean init_network_game, boolean record_tape,
long random_seed)
{
unsigned long new_random_seed = InitRND(random_seed);
if (record_tape)
TapeStartRecording(new_random_seed);
unsigned long new_random_seed = InitRND(random_seed);
if (record_tape)
TapeStartRecording(new_random_seed);
-#else
- if (record_tape)
- TapeStartRecording(random_seed);
-#endif
#if defined(NETWORK_AVALIABLE)
if (init_network_game)
#if defined(NETWORK_AVALIABLE)
if (init_network_game)
game_status = GAME_MODE_PLAYING;
game_status = GAME_MODE_PLAYING;
-#if 0
- InitRND(random_seed);
-#endif
-
if (!network_player_action_received)
return; /* failed to get network player actions in time */
if (!network_player_action_received)
return; /* failed to get network player actions in time */
+
+ /* do not yet reset "network_player_action_received" (for tape.pausing) */
}
if (tape.pausing)
return;
}
if (tape.pausing)
return;
+ /* at this point we know that we really continue executing the game */
+
+#if 1
+ network_player_action_received = FALSE;
+#endif
+
recorded_player_action = (tape.playing ? TapePlayAction() : NULL);
if (tape.set_centered_player)
recorded_player_action = (tape.playing ? TapePlayAction() : NULL);
if (tape.set_centered_player)
ScrollPlayer(&stored_player[i], SCROLL_GO_ON);
}
ScrollPlayer(&stored_player[i], SCROLL_GO_ON);
}
network_player_action_received = FALSE;
network_player_action_received = FALSE;
ScrollScreen(NULL, SCROLL_GO_ON);
ScrollScreen(NULL, SCROLL_GO_ON);
{
#if defined(NETWORK_AVALIABLE)
if (options.network)
{
#if defined(NETWORK_AVALIABLE)
if (options.network)
- SendToServer_StopPlaying();
+ SendToServer_StopPlaying(NETWORK_STOP_BY_PLAYER);
int game.centered_player_nr_next = getCenteredPlayerNr_EM();
#endif
#if 1
int game.centered_player_nr_next = getCenteredPlayerNr_EM();
#endif
#if 1
- int player_nr = getMaxCenterDistancePlayerNr(screen_x, screen_y);
+ int max_center_distance_player_nr =
+ getMaxCenterDistancePlayerNr(screen_x, screen_y);
#else
int player_nr = game_em.last_moving_player;
#endif
#else
int player_nr = game_em.last_moving_player;
#endif
- sx = PLAYER_SCREEN_X(player_nr);
- sy = PLAYER_SCREEN_Y(player_nr);
+ sx = PLAYER_SCREEN_X(max_center_distance_player_nr);
+ sy = PLAYER_SCREEN_Y(max_center_distance_player_nr);
#else
sx = PLAYER_SCREEN_X(game_em.last_moving_player);
sy = PLAYER_SCREEN_Y(game_em.last_moving_player);
#else
sx = PLAYER_SCREEN_X(game_em.last_moving_player);
sy = PLAYER_SCREEN_Y(game_em.last_moving_player);
#if 0
int player_nr = game_em.last_moving_player;
#endif
#if 0
int player_nr = game_em.last_moving_player;
#endif
+ int player_nr = (game.centered_player_nr == -1 ?
+ max_center_distance_player_nr : game.centered_player_nr);
int player_move_dir = game_em.last_player_direction[player_nr];
int dx = SIGN(screen_x - screen_x_old);
int dy = SIGN(screen_y - screen_y_old);
int player_move_dir = game_em.last_player_direction[player_nr];
int dx = SIGN(screen_x - screen_x_old);
int dy = SIGN(screen_y - screen_y_old);
static struct GadgetInfo *gadget_list_first_entry = NULL;
static struct GadgetInfo *gadget_list_last_entry = NULL;
static struct GadgetInfo *gadget_list_first_entry = NULL;
static struct GadgetInfo *gadget_list_last_entry = NULL;
+static struct GadgetInfo *last_info_gi = NULL;
static int next_free_gadget_id = 1;
static boolean gadget_id_wrapped = FALSE;
static int next_free_gadget_id = 1;
static boolean gadget_id_wrapped = FALSE;
{
struct GadgetInfo *gi_previous = gadget_list_first_entry;
{
struct GadgetInfo *gi_previous = gadget_list_first_entry;
+ /* prevent "last_info_gi" from pointing to memory that will be freed */
+ if (last_info_gi == gi)
+ last_info_gi = NULL;
+
while (gi_previous != NULL && gi_previous->next != gi)
gi_previous = gi_previous->next;
while (gi_previous != NULL && gi_previous->next != gi)
gi_previous = gi_previous->next;
boolean HandleGadgets(int mx, int my, int button)
{
boolean HandleGadgets(int mx, int my, int button)
{
- static struct GadgetInfo *last_info_gi = NULL;
static unsigned long pressed_delay = 0;
static int last_button = 0;
static int last_mx = 0, last_my = 0;
static unsigned long pressed_delay = 0;
static int last_button = 0;
static int last_mx = 0, last_my = 0;
#define PROGRAM_VERSION_MAJOR 3
#define PROGRAM_VERSION_MINOR 2
#define PROGRAM_VERSION_PATCH 0
#define PROGRAM_VERSION_MAJOR 3
#define PROGRAM_VERSION_MINOR 2
#define PROGRAM_VERSION_PATCH 0
-#define PROGRAM_VERSION_BUILD 7
+#define PROGRAM_VERSION_BUILD 8
#define PROGRAM_TITLE_STRING "Rocks'n'Diamonds"
#define PROGRAM_AUTHOR_STRING "Holger Schemel"
#define PROGRAM_TITLE_STRING "Rocks'n'Diamonds"
#define PROGRAM_AUTHOR_STRING "Holger Schemel"
if (options.verbose)
Error(ERR_NETWORK_SERVER,
if (options.verbose)
Error(ERR_NETWORK_SERVER,
- "client %d (%s) starts game [level %d from levedir %d (%s)]",
+ "client %d (%s) starts game [level %d from leveldir %d (%s)]",
player->number, player->player_name,
(buffer[2] << 8) + buffer[3],
(buffer[4] << 8) + buffer[5],
player->number, player->player_name,
(buffer[2] << 8) + buffer[3],
(buffer[4] << 8) + buffer[5],
for (w = first_player; w; w = w->next)
if (w->introduced)
for (w = first_player; w; w = w->next)
if (w->introduced)
/* reset frame counter */
ServerFrameCounter = 0;
/* reset frame counter */
ServerFrameCounter = 0;
+ Error(ERR_NETWORK_SERVER, "resetting ServerFrameCounter to 0");
+
/* reset player actions */
for (v = first_player; v; v = v->next)
{
/* reset player actions */
for (v = first_player; v; v = v->next)
{
static void Handle_OP_STOP_PLAYING(struct NetworkServerPlayerInfo *player)
{
static void Handle_OP_STOP_PLAYING(struct NetworkServerPlayerInfo *player)
{
+ int cause_for_stopping = buffer[2];
+
- Error(ERR_NETWORK_SERVER, "client %d (%s) stops game",
- player->number, player->player_name);
- broadcast(NULL, 2, 0);
+ Error(ERR_NETWORK_SERVER, "client %d (%s) stops game [%d]",
+ player->number, player->player_name, cause_for_stopping);
+ broadcast(NULL, 3, 0);
}
static void Handle_OP_MOVE_PLAYER(struct NetworkServerPlayerInfo *player)
}
static void Handle_OP_MOVE_PLAYER(struct NetworkServerPlayerInfo *player)
broadcast(NULL, 6 + last_client_nr, 0);
broadcast(NULL, 6 + last_client_nr, 0);
+#if 0
+ Error(ERR_NETWORK_SERVER, "sending ServerFrameCounter value %d",
+ ServerFrameCounter);
+#endif
+
static byte readbuffer[MAX_BUFFER_SIZE], writbuffer[MAX_BUFFER_SIZE];
static byte *buffer = realbuffer + 4;
static int nread = 0, nwrite = 0;
static byte readbuffer[MAX_BUFFER_SIZE], writbuffer[MAX_BUFFER_SIZE];
static byte *buffer = realbuffer + 4;
static int nread = 0, nwrite = 0;
+static boolean stop_network_game = FALSE;
static void SendBufferToServer(int size)
{
static void SendBufferToServer(int size)
{
-void SendToServer_StopPlaying()
+void SendToServer_StopPlaying(int cause_for_stopping)
{
buffer[1] = OP_STOP_PLAYING;
{
buffer[1] = OP_STOP_PLAYING;
+ buffer[2] = cause_for_stopping;
}
void SendToServer_MovePlayer(byte player_action)
}
void SendToServer_MovePlayer(byte player_action)
static void Handle_OP_STOP_PLAYING()
{
static void Handle_OP_STOP_PLAYING()
{
- printf("OP_STOP_PLAYING: %d\n", buffer[0]);
- Error(ERR_NETWORK_CLIENT, "client %d stops game", buffer[0]);
+ printf("OP_STOP_PLAYING: %d [%d]\n", buffer[0], buffer[2]);
+ Error(ERR_NETWORK_CLIENT, "client %d stops game [%d]", buffer[0], buffer[2]);
+
+ if (game_status == GAME_MODE_PLAYING)
+ {
+ if (buffer[2] == NETWORK_STOP_BY_PLAYER)
+ Request("Network game stopped by player!", REQ_CONFIRM);
+ else if (buffer[2] == NETWORK_STOP_BY_ERROR)
+ Request("Network game stopped due to internal error!", REQ_CONFIRM);
+ else
+ Request("Network game stopped !", REQ_CONFIRM);
+ }
game_status = GAME_MODE_MAIN;
DrawMainMenu();
game_status = GAME_MODE_MAIN;
DrawMainMenu();
server_frame_counter =
(buffer[2] << 24) | (buffer[3] << 16) | (buffer[4] << 8) | (buffer[5]);
server_frame_counter =
(buffer[2] << 24) | (buffer[3] << 16) | (buffer[4] << 8) | (buffer[5]);
+#if 0
+ Error(ERR_NETWORK_CLIENT, "receiving server frame counter value %d [%d]",
+ server_frame_counter, FrameCounter);
+#endif
+
if (server_frame_counter != FrameCounter)
{
Error(ERR_RETURN, "client and servers frame counters out of sync");
Error(ERR_RETURN, "frame counter of client is %d", FrameCounter);
Error(ERR_RETURN, "frame counter of server is %d", server_frame_counter);
if (server_frame_counter != FrameCounter)
{
Error(ERR_RETURN, "client and servers frame counters out of sync");
Error(ERR_RETURN, "frame counter of client is %d", FrameCounter);
Error(ERR_RETURN, "frame counter of server is %d", server_frame_counter);
+
+#if 1
+ Error(ERR_RETURN, "this should not happen -- please debug");
+
+ stop_network_game = TRUE;
+
+ return;
+#else
Error(ERR_EXIT, "this should not happen -- please debug");
Error(ERR_EXIT, "this should not happen -- please debug");
}
/* copy valid player actions */
}
/* copy valid player actions */
{
unsigned int message_length;
{
unsigned int message_length;
+ stop_network_game = FALSE;
+
while (nread >= 4 && nread >= 4 + readbuffer[3])
{
message_length = readbuffer[3];
while (nread >= 4 && nread >= 4 + readbuffer[3])
{
message_length = readbuffer[3];
+
+ /* in case of internal error, stop network game */
+ if (stop_network_game)
+ SendToServer_StopPlaying(NETWORK_STOP_BY_ERROR);
+#define NETWORK_STOP_BY_PLAYER 0
+#define NETWORK_STOP_BY_ERROR 1
+
boolean ConnectToServer(char *, int);
void SendToServer_PlayerName(char *);
void SendToServer_ProtocolVersion(void);
boolean ConnectToServer(char *, int);
void SendToServer_PlayerName(char *);
void SendToServer_ProtocolVersion(void);
void SendToServer_StartPlaying(void);
void SendToServer_PausePlaying(void);
void SendToServer_ContinuePlaying(void);
void SendToServer_StartPlaying(void);
void SendToServer_PausePlaying(void);
void SendToServer_ContinuePlaying(void);
-void SendToServer_StopPlaying(void);
+void SendToServer_StopPlaying(int);
void SendToServer_MovePlayer(byte);
void HandleNetworking(void);
void SendToServer_MovePlayer(byte);
void HandleNetworking(void);
if (game_status == GAME_MODE_PLAYING &&
level.game_engine_type == GAME_ENGINE_TYPE_EM)
{
if (game_status == GAME_MODE_PLAYING &&
level.game_engine_type == GAME_ENGINE_TYPE_EM)
{
-#if 1
- RedrawPlayfield_EM(force_redraw);
-#else
- BlitScreenToBitmap_EM(backbuffer);
-#endif
+ /* currently there is no partial redraw -- always redraw whole playfield */
+
+ RedrawPlayfield_EM(TRUE);
}
else if (game_status == GAME_MODE_PLAYING && !game.envelope_active)
{
}
else if (game_status == GAME_MODE_PLAYING && !game.envelope_active)
{