1 /*
2 * main.cpp
3 *
4 * This file is part of Leges Motus, a networked, 2D shooter set in zero gravity.
5 *
6 * Copyright 2009-2010 Andrew Ayer, Nathan Partlan, Jeffrey Pfau
7 *
8 * Leges Motus is free and open source software. You may redistribute it and/or
9 * modify it under the terms of version 2, or (at your option) version 3, of the
10 * GNU General Public License (GPL), as published by the Free Software Foundation.
11 *
12 * Leges Motus is distributed in the hope that it will be useful, but WITHOUT ANY
13 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
14 * PARTICULAR PURPOSE. See the full text of the GNU General Public License for
15 * further detail.
16 *
17 * For a full copy of the GNU General Public License, please see the COPYING file
18 * in the root of the source code tree. You may also retrieve a copy from
19 * <http://www.gnu.org/licenses/gpl-2.0.txt>, or request a copy by writing to the
20 * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 * 02111-1307 USA
22 *
23 */
24
25 #include "GameController.hpp"
26 #include "ClientSDL.hpp"
27 #include "ClientConfiguration.hpp"
28 #include "common/Exception.hpp"
29 #include "common/PathManager.hpp"
30 #include "common/misc.hpp"
31 #include "common/network.hpp"
32 #include "common/team.hpp"
33 #include <iostream>
34 #include <sstream>
35
36 #ifdef __APPLE__
37 extern "C" {
38 #include "mac_bridge.h"
39 }
40 #elif defined(__WIN32)
41 #include <Windows.h>
42 #endif
43
44 using namespace LM;
45 using namespace std;
46
clean_exit()47 extern "C" void clean_exit() {
48 SDL_Event quit_event;
49 quit_event.type = SDL_QUIT;
50 SDL_PushEvent(&quit_event);
51 }
52
53 namespace {
54 bool run_from_finder = false;
55
display_usage(const char * progname)56 void display_usage(const char* progname) {
57 cout << "Usage: " << progname << " [OPTION]" << endl;
58 cout << "Options:" << endl;
59 cout << " -n NAME set your player name" << endl;
60 cout << " -t red|blue set your team" << endl;
61 cout << " -s SERVER set the hostname of the server" << endl;
62 cout << " -p PORTNO set the port number of the server" << endl;
63 cout << " -w WIDTH set the screen width, in pixels" << endl;
64 cout << " -h HEIGHT set the screen height, in pixels" << endl;
65 cout << " -f run the game in fullscreen" << endl;
66 cout << " -?, --help display this help, and exit" << endl;
67 cout << " --version\tdisplay version information and exit" << endl;
68 }
69
display_legalese()70 void display_legalese() {
71 cout << "Copyright 2009-2010 Andrew Ayer, Nathan Partlan, Jeffrey Pfau" << endl;
72 cout << "Leges Motus is free and open source software; see the source for copying conditions." << endl;
73 cout << "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." << endl;
74 }
75
display_version()76 void display_version() {
77 cout << "Leges Motus" << endl;
78 cout << "A networked, 2D shooter set in zero gravity" << endl;
79 cout << endl;
80 display_legalese();
81 }
82 }
83
main(int argc,char * argv[])84 extern "C" int main(int argc, char* argv[]) try {
85 ClientSDL client_sdl;
86 GameController* game_controller;
87 int width = 0;
88 int height = 0;
89 bool fullscreen = false;
90 char team = 0;
91 string server = "";
92 unsigned int portno = DEFAULT_PORTNO;
93 string name = "";
94 IPAddress server_address;
95
96 for (int i = 1; i < argc; i++) {
97 if (strcmp(argv[i], "-f") == 0) {
98 fullscreen = true;
99 } else if (strcmp(argv[i], "-w") == 0 && argc > i+1) {
100 width = atoi(argv[i+1]);
101 ++i;
102 } else if (strcmp(argv[i], "-h") == 0 && argc > i+1) {
103 height = atoi(argv[i+1]);
104 ++i;
105 } else if (strcmp(argv[i], "-s") == 0 && argc > i+1) {
106 server = argv[i+1];
107 ++i;
108 } else if (strcmp(argv[i], "-p") == 0 && argc > i+1) {
109 portno = atoi(argv[i+1]);
110 ++i;
111 } else if (strcmp(argv[i], "-n") == 0 && argc > i+1) {
112 name = argv[i+1];
113 ++i;
114 } else if (strcmp(argv[i], "-t") == 0 && argc > i+1) {
115 team = parse_team_string(argv[i+1]);
116 if (!is_valid_team(team)) {
117 cerr << argv[0] << ": Unrecognized team `" << argv[i+1] << "'" << endl;
118 display_usage(argv[0]);
119 return 2;
120 }
121 ++i;
122 } else if (strcmp(argv[i], "--version") == 0) {
123 display_version();
124 return 0;
125 } else if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-?") == 0) {
126 display_usage(argv[0]);
127 return 0;
128 } else if (strncmp(argv[i], "-psn", 4) == 0) {
129 run_from_finder = true;
130 } else {
131 cerr << argv[0] << ": Unrecognized option `" << argv[i] << "'" << endl;
132 display_usage(argv[0]);
133 return 2;
134 }
135 }
136
137 PathManager pathman(argv[0]);
138
139 bool restart = true;
140 while(restart) {
141 if (!server.empty() && !resolve_hostname(server_address, server.c_str(), portno)) {
142 cerr << "Hostname of requested server not found: " << server << endl;
143 return 1;
144 }
145
146 if (has_terminal_output()) {
147 cout << "Welcome to Leges Motus." << endl;
148 display_legalese();
149 }
150
151 ClientConfiguration config;
152
153 if (width > 0 && height > 0) {
154 // Use the specified width and height
155 game_controller = new GameController(pathman, &config, width, height, fullscreen);
156 } else if (fullscreen) {
157 // Use optimal settings
158 game_controller = new GameController(pathman, &config);
159 } else {
160 width = config.get_int_value("screen_width");
161 height = config.get_int_value("screen_height");
162 fullscreen = config.get_bool_value("fullscreen");
163 if (width == -1) {
164 width = 800;
165 }
166 if (height == -1) {
167 height = 600;
168 }
169 // Use the default from the config
170 game_controller = new GameController(pathman, &config, width, height, fullscreen);
171 }
172
173 if (!name.empty()) {
174 config.set_string_value("name", name);
175 } else {
176 if (config.get_string_value("name") == "" || config.get_string_value("name") == "Unnamed") {
177 config.set_string_value("name", get_username());
178 }
179 name = config.get_string_value("name");
180 }
181
182 game_controller->set_player_name(!name.empty() ? name : get_username());
183 if (!server.empty()) {
184 game_controller->connect_to_server(server_address, team);
185 }
186
187 game_controller->run();
188
189 if (game_controller->wants_restart()) {
190 // Allow the resolution to be re-specified by the config.
191 width = 0;
192 height = 0;
193 fullscreen = false;
194
195 // Reconnect to the server we were on.
196 server = game_controller->get_server_address();
197 size_t portdelim = server.find(":");
198 if (portdelim != string::npos) {
199 portno = atoi(server.substr(portdelim+1).c_str());
200 server = server.substr(0, portdelim);
201 }
202 name = game_controller->get_player_name();
203 game_controller->disconnect();
204 } else {
205 restart = false;
206 }
207
208 delete game_controller;
209 }
210
211 if (has_terminal_output()) {
212 cout << "Leges Motus is now exiting. Thanks for playing!" << endl;
213 }
214
215 return 0;
216
217 } catch (const Exception& e) {
218 cerr << "Error: " << e.what() << endl;
219 cerr << "1. If on X11, check that your $DISPLAY environment variable is set properly." << endl;
220 cerr << "2. Make sure that Leges Motus has been properly installed (if compiling from source, you should have run 'make install'), OR that your $LM_DATA_DIR environment variable is set to the directory containing the game resources." << endl;
221
222 #ifdef __APPLE__
223 if (run_from_finder) {
224 toplevel_exception(e.what());
225 }
226 #elif defined(__WIN32)
227 stringstream s;
228 s << e.what() << endl;
229 s << "Please ensure that you are running Leges Motus from the same directory as the game resources" << flush;
230 MessageBox(NULL, s.str().c_str(), NULL, MB_OK|MB_ICONERROR);
231 #endif
232
233 return 1;
234 }
235