1 //       _________ __                 __
2 //      /   _____//  |_____________ _/  |______     ____  __ __  ______
3 //      \_____  \\   __\_  __ \__  \\   __\__  \   / ___\|  |  \/  ___/
4 //      /        \|  |  |  | \// __ \|  |  / __ \_/ /_/  >  |  /\___ |
5 //     /_______  /|__|  |__|  (____  /__| (____  /\___  /|____//____  >
6 //             \/                  \/          \//_____/            \/
7 //  ______________________                           ______________________
8 //                        T H E   W A R   B E G I N S
9 //         Stratagus - A free fantasy real time strategy game engine
10 //
11 /**@name games.cpp - Basic games query process. */
12 //
13 //      (c) Copyright 2005 by Jimmy Salmon
14 //
15 //      This program is free software; you can redistribute it and/or modify
16 //      it under the terms of the GNU General Public License as published by
17 //      the Free Software Foundation; only version 2 of the License.
18 //
19 //      This program is distributed in the hope that it will be useful,
20 //      but WITHOUT ANY WARRANTY; without even the implied warranty of
21 //      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 //      GNU General Public License for more details.
23 //
24 //      You should have received a copy of the GNU General Public License
25 //      along with this program; if not, write to the Free Software
26 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 //      02111-1307, USA.
28 //
29 
30 //@{
31 
32 /*----------------------------------------------------------------------------
33 --  Includes
34 ----------------------------------------------------------------------------*/
35 
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 
40 #include "stratagus.h"
41 #include "games.h"
42 #include "netdriver.h"
43 
44 /*----------------------------------------------------------------------------
45 --  Variables
46 ----------------------------------------------------------------------------*/
47 
48 static GameData *Games;
49 int GameID;
50 
51 /*----------------------------------------------------------------------------
52 --  Functions
53 ----------------------------------------------------------------------------*/
54 
55 /**
56 **  Create a game
57 */
CreateGame(Session * session,char * description,char * map,char * players,char * ip,char * port,char * password)58 void CreateGame(Session *session, char *description, char *map,
59 	char *players, char *ip, char *port, char *password)
60 {
61 	GameData *game;
62 
63 	game = new GameData;
64 
65 	strcpy(game->IP, ip);
66 	strcpy(game->Port, port);
67 	strcpy(game->Description, description);
68 	strcpy(game->Map, map);
69 	game->MaxSlots = atoi(players);
70 	game->OpenSlots = game->MaxSlots - 1;
71 	if (password) {
72 		strcpy(game->Password, password);
73 	} else {
74 		game->Password[0] = '\0';
75 	}
76 
77 	game->NumSessions = 1;
78 	game->Sessions[0] = session;
79 	game->ID = GameID++;
80 	game->Started = 0;
81 
82 	game->GameName = session->UserData.GameName;
83 	game->Version = session->UserData.Version;
84 
85 	if (Games) {
86 		Games->Prev = game;
87 	}
88 	game->Next = Games;
89 	game->Prev = NULL;
90 	Games = game;
91 
92 	session->Game = game;
93 }
94 
95 /**
96 **  Cancel a game
97 */
CancelGame(Session * session)98 int CancelGame(Session *session)
99 {
100 	GameData *game;
101 	int i;
102 
103 	game = session->Game;
104 
105 	if (game->Sessions[0] != session) {
106 		return -1; // Not the host
107 	}
108 
109 	if (game->Next) {
110 		game->Next->Prev = game->Prev;
111 	}
112 	if (game->Prev) {
113 		game->Prev->Next = game->Next;
114 	}
115 	if (Games == game) {
116 		Games = game->Next;
117 	}
118 
119 	for (i = 0; i < game->NumSessions; ++i) {
120 		game->Sessions[i]->Game = NULL;
121 	}
122 
123 	delete game;
124 	return 0;
125 }
126 
127 /**
128 **  Start a game
129 */
StartGame(Session * session)130 int StartGame(Session *session)
131 {
132 	if (session->Game->Sessions[0] != session) {
133 		return -1; // Not the host
134 	}
135 
136 	session->Game->Started = 1;
137 	return 0;
138 }
139 
140 /**
141 **  Join a game
142 */
JoinGame(Session * session,int id,char * password)143 int JoinGame(Session *session, int id, char *password)
144 {
145 	GameData *game;
146 
147 	if (session->Game) {
148 		return -1; // Already in a game
149 	}
150 
151 	game = Games;
152 	while (game) {
153 		if (game->ID == id) {
154 			break;
155 		}
156 		game = game->Next;
157 	}
158 	if (!game) {
159 		return -2; // ID not found
160 	}
161 
162 	if (game->Password[0]) {
163 		if (!password || strcmp(game->Password, password)) {
164 			return -3; // Wrong password
165 		}
166 	}
167 	if (!game->OpenSlots) {
168 		return -4; // Game full
169 	}
170 	game->Sessions[game->NumSessions++] = session;
171 	session->Game = game;
172 
173 	return 0;
174 }
175 
176 /**
177 **  Leave a game
178 */
PartGame(Session * session)179 int PartGame(Session *session)
180 {
181 	GameData *game;
182 	int i;
183 
184 	game = session->Game;
185 
186 	if (!game) {
187 		return -1; // Not in a game
188 	}
189 	if (game->Started) {
190 		return -2;
191 	}
192 
193 	if (game->Sessions[0] == session) {
194 		// The host left, cancel the game
195 		CancelGame(session);
196 		return 0;
197 	}
198 
199 	for (i = 1; i < game->NumSessions; ++i) {
200 		if (game->Sessions[i] == session) {
201 			for (; i < game->NumSessions - 1; ++i) {
202 				game->Sessions[i] = game->Sessions[i + 1];
203 			}
204 			game->NumSessions--;
205 			break;
206 		}
207 	}
208 
209 	session->Game = NULL;
210 
211 	return 0;
212 }
213 
MatchGameType(Session * session,GameData * game)214 static int MatchGameType(Session *session, GameData *game)
215 {
216 	return (!*game->GameName || !strcmp(session->UserData.GameName, game->GameName)) &&
217 		(!*game->Version || !strcmp(session->UserData.Version, game->Version));
218 }
219 
220 /**
221 **  List games
222 */
ListGames(Session * session)223 void ListGames(Session *session)
224 {
225 	GameData *game;
226 	char buf[1024];
227 
228 	game = Games;
229 	while (game) {
230 		if (!game->Started && MatchGameType(session, game)) {
231 			sprintf(buf, "LISTGAMES %d \"%s\" \"%s\" %d %d %s %s\n",
232 				game->ID, game->Description, game->Map,
233 				game->OpenSlots, game->MaxSlots, game->IP, game->Port);
234 			Send(session, buf);
235 		}
236 		game = game->Next;
237 	}
238 }
239