+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
-#define COMPILE_DATE_STRING "[2006-03-23 10:55]"
+#define COMPILE_DATE_STRING "[2006-03-29 19:24]"
{
int i;
+#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++;
void StartGameActions(boolean init_network_game, boolean record_tape,
long random_seed)
{
-#if 1
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)
game_status = GAME_MODE_PLAYING;
-#if 0
- InitRND(random_seed);
-#endif
-
InitGame();
}
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;
+ /* 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)
ScrollPlayer(&stored_player[i], SCROLL_GO_ON);
}
+#if 0
network_player_action_received = FALSE;
+#endif
ScrollScreen(NULL, SCROLL_GO_ON);
{
#if defined(NETWORK_AVALIABLE)
if (options.network)
- SendToServer_StopPlaying();
+ SendToServer_StopPlaying(NETWORK_STOP_BY_PLAYER);
else
#endif
{
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
{
#if 1
- 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);
#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);
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;
{
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;
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;
#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"
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],
- &buffer[6]);
+ &buffer[10]);
for (w = first_player; w; w = w->next)
if (w->introduced)
/* reset frame counter */
ServerFrameCounter = 0;
+ Error(ERR_NETWORK_SERVER, "resetting ServerFrameCounter to 0");
+
/* reset player actions */
for (v = first_player; v; v = v->next)
{
static void Handle_OP_STOP_PLAYING(struct NetworkServerPlayerInfo *player)
{
+ int cause_for_stopping = buffer[2];
+
if (options.verbose)
- 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)
broadcast(NULL, 6 + last_client_nr, 0);
+#if 0
+ Error(ERR_NETWORK_SERVER, "sending ServerFrameCounter value %d",
+ ServerFrameCounter);
+#endif
+
ServerFrameCounter++;
}
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)
{
SendBufferToServer(2);
}
-void SendToServer_StopPlaying()
+void SendToServer_StopPlaying(int cause_for_stopping)
{
buffer[1] = OP_STOP_PLAYING;
+ buffer[2] = cause_for_stopping;
- SendBufferToServer(2);
+ SendBufferToServer(3);
}
void SendToServer_MovePlayer(byte player_action)
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();
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 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");
+#endif
}
/* copy valid player actions */
{
unsigned int message_length;
+ stop_network_game = FALSE;
+
while (nread >= 4 && nread >= 4 + readbuffer[3])
{
message_length = readbuffer[3];
}
fflush(stdout);
+
+ /* in case of internal error, stop network game */
+ if (stop_network_game)
+ SendToServer_StopPlaying(NETWORK_STOP_BY_ERROR);
}
/* TODO */
#include "main.h"
+#define NETWORK_STOP_BY_PLAYER 0
+#define NETWORK_STOP_BY_ERROR 1
+
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_StopPlaying(void);
+void SendToServer_StopPlaying(int);
void SendToServer_MovePlayer(byte);
void HandleNetworking(void);
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)
{