1 /* |
|
2 * Hedgewars, a free turn based strategy game |
|
3 * Copyright (C) 2012 Simeon Maxein <smaxein@googlemail.com> |
|
4 * |
|
5 * This program is free software; you can redistribute it and/or |
|
6 * modify it under the terms of the GNU General Public License |
|
7 * as published by the Free Software Foundation; either version 2 |
|
8 * of the License, or (at your option) any later version. |
|
9 * |
|
10 * This program is distributed in the hope that it will be useful, |
|
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
13 * GNU General Public License for more details. |
|
14 * |
|
15 * You should have received a copy of the GNU General Public License |
|
16 * along with this program; if not, write to the Free Software |
|
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
18 */ |
|
19 |
|
20 #include "frontlib.h" |
|
21 #include "util/logging.h" |
|
22 #include "util/buffer.h" |
|
23 #include "util/util.h" |
|
24 #include "util/list.h" |
|
25 #include "model/map.h" |
|
26 #include "model/weapon.h" |
|
27 #include "model/schemelist.h" |
|
28 #include "ipc/mapconn.h" |
|
29 #include "ipc/gameconn.h" |
|
30 #include "net/netconn.h" |
|
31 |
|
32 #include <stdlib.h> |
|
33 #include <stdbool.h> |
|
34 #include <assert.h> |
|
35 #include <string.h> |
|
36 |
|
37 // Callback function that will be called when the map is rendered |
|
38 static void handleMapSuccess(void *context, const uint8_t *bitmap, int numHedgehogs) { |
|
39 printf("Drawing map for %i brave little hogs...", numHedgehogs); |
|
40 |
|
41 // Draw the map as ASCII art |
|
42 for(int y=0; y<MAPIMAGE_HEIGHT; y++) { |
|
43 for(int x=0; x<MAPIMAGE_WIDTH; x++) { |
|
44 int pixelnum = x + y*MAPIMAGE_WIDTH; |
|
45 bool pixel = bitmap[pixelnum>>3] & (1<<(7-(pixelnum&7))); |
|
46 printf(pixel ? "#" : " "); |
|
47 } |
|
48 printf("\n"); |
|
49 } |
|
50 |
|
51 // Destroy the connection object (this will end the "tick" loop below) |
|
52 flib_mapconn **connptr = context; |
|
53 flib_mapconn_destroy(*connptr); |
|
54 *connptr = NULL; |
|
55 } |
|
56 |
|
57 static void onDisconnect(void *context, int reason) { |
|
58 flib_log_i("Connection closed. Reason: %i", reason); |
|
59 flib_gameconn **connptr = context; |
|
60 flib_gameconn_destroy(*connptr); |
|
61 *connptr = NULL; |
|
62 } |
|
63 |
|
64 static void onGameRecorded(void *context, const uint8_t *record, int size, bool isSavegame) { |
|
65 flib_log_i("Writing %s (%i bytes)...", isSavegame ? "savegame" : "demo", size); |
|
66 FILE *file = fopen(isSavegame ? "testsave.42.hws" : "testdemo.42.hwd", "wb"); |
|
67 fwrite(record, 1, size, file); |
|
68 fclose(file); |
|
69 } |
|
70 |
|
71 // Callback function that will be called on error |
|
72 static void handleMapFailure(void *context, const char *errormessage) { |
|
73 flib_log_e("Map rendering failed: %s", errormessage); |
|
74 |
|
75 // Destroy the connection object (this will end the "tick" loop below) |
|
76 flib_mapconn **connptr = context; |
|
77 flib_mapconn_destroy(*connptr); |
|
78 *connptr = NULL; |
|
79 } |
|
80 |
|
81 static void startEngineMap(int port) { |
|
82 char commandbuffer[255]; |
|
83 const char *enginePath = "C:\\Programmieren\\Hedgewars\\bin"; |
|
84 const char *configPath = "C:\\Programmieren\\Hedgewars\\share\\hedgewars"; |
|
85 snprintf(commandbuffer, 255, "start %s\\hwengine.exe %s %i landpreview", enginePath, configPath, port); |
|
86 system(commandbuffer); |
|
87 } |
|
88 |
|
89 static void startEngineGame(int port) { |
|
90 char commandbuffer[255]; |
|
91 const char *enginePath = "C:\\Programmieren\\Hedgewars\\bin"; |
|
92 const char *configPath = "C:\\Programmieren\\Hedgewars\\share\\hedgewars"; |
|
93 const char *dataPath = "C:\\Programmieren\\Hedgewars\\share\\hedgewars\\Data"; |
|
94 snprintf(commandbuffer, 255, "start %s\\hwengine.exe %s 1024 768 32 %i 0 0 0 10 10 %s 0 0 TWVkbzQy 0 0 en.txt", enginePath, configPath, port, dataPath); |
|
95 flib_log_d("Starting engine with CMD: %s", commandbuffer); |
|
96 system(commandbuffer); |
|
97 } |
|
98 |
|
99 void testMapPreview() { |
|
100 // Create a map description and check that there was no error |
|
101 flib_map *map = flib_map_create_maze("This is the seed value", "Jungle", MAZE_SIZE_SMALL_TUNNELS); |
|
102 assert(map); |
|
103 |
|
104 // Create a new connection to the engine and check that there was no error |
|
105 flib_mapconn *mapConnection = flib_mapconn_create(map); |
|
106 assert(mapConnection); |
|
107 |
|
108 // We don't need the map description anymore |
|
109 flib_map_release(map); |
|
110 map = NULL; |
|
111 |
|
112 // Register the callback functions |
|
113 flib_mapconn_onFailure(mapConnection, &handleMapFailure, &mapConnection); |
|
114 flib_mapconn_onSuccess(mapConnection, &handleMapSuccess, &mapConnection); |
|
115 |
|
116 // Start the engine process and tell it which port the frontlib is listening on |
|
117 startEngineMap(flib_mapconn_getport(mapConnection)); |
|
118 |
|
119 // Usually, flib_mapconn_tick will be called in an event loop that runs several |
|
120 // times per second. It handles I/O operations and progress, and calls |
|
121 // callbacks when something interesting happens. |
|
122 while(mapConnection) { |
|
123 flib_mapconn_tick(mapConnection); |
|
124 } |
|
125 } |
|
126 |
|
127 /*void testGame() { |
|
128 flib_cfg_meta *metaconf = flib_cfg_meta_from_ini("metasettings.ini"); |
|
129 assert(metaconf); |
|
130 flib_weaponset *weapons = flib_weaponset_create("Defaultweaps"); |
|
131 flib_schemelist *schemelist = flib_schemelist_from_ini(metaconf, "schemes.ini"); |
|
132 |
|
133 flib_gamesetup setup; |
|
134 setup.gamescheme = flib_schemelist_find(schemelist, "Default"); |
|
135 setup.map = flib_map_create_maze("asparagus", "Jungle", MAZE_SIZE_MEDIUM_TUNNELS); |
|
136 setup.script = NULL; |
|
137 setup.teamCount = 2; |
|
138 setup.teams = calloc(2, sizeof(flib_team*)); |
|
139 setup.teams[0] = calloc(1, sizeof(flib_team)); |
|
140 setup.teams[0]->color = 0xffff0000; |
|
141 setup.teams[0]->flag = "australia"; |
|
142 setup.teams[0]->fort = "Plane"; |
|
143 setup.teams[0]->grave = "Bone"; |
|
144 setup.teams[0]->hogsInGame = 2; |
|
145 setup.teams[0]->name = "Team Awesome"; |
|
146 setup.teams[0]->voicepack = "British"; |
|
147 setup.teams[0]->hogs[0].difficulty = 2; |
|
148 setup.teams[0]->hogs[0].hat = "NoHat"; |
|
149 setup.teams[0]->hogs[0].initialHealth = 100; |
|
150 setup.teams[0]->hogs[0].name = "Harry 120"; |
|
151 setup.teams[0]->hogs[1].difficulty = 2; |
|
152 setup.teams[0]->hogs[1].hat = "chef"; |
|
153 setup.teams[0]->hogs[1].initialHealth = 100; |
|
154 setup.teams[0]->hogs[1].name = "Chefkoch"; |
|
155 setup.teams[1] = flib_team_from_ini("Cave Dwellers.hwt"); |
|
156 setup.teams[1]->color = 0xFF0000F0; |
|
157 setup.teams[1]->hogsInGame = 8; |
|
158 flib_team_set_weaponset(setup.teams[0], weapons); |
|
159 flib_team_set_weaponset(setup.teams[1], weapons); |
|
160 flib_weaponset_release(weapons); |
|
161 |
|
162 flib_gameconn *gameconn = flib_gameconn_create("Medo42", &setup, false); |
|
163 assert(gameconn); |
|
164 |
|
165 flib_gameconn_onDisconnect(gameconn, &onDisconnect, &gameconn); |
|
166 //flib_gameconn_onGameRecorded(gameconn, &onGameRecorded, &gameconn); |
|
167 |
|
168 startEngineGame(flib_gameconn_getport(gameconn)); |
|
169 |
|
170 while(gameconn) { |
|
171 flib_gameconn_tick(gameconn); |
|
172 } |
|
173 }*/ |
|
174 |
|
175 void testDemo() { |
|
176 FILE *demofile = fopen("testdemo.42.hwd", "rb"); |
|
177 assert(demofile); |
|
178 flib_vector *vec = flib_vector_create(); |
|
179 uint8_t demobuf[512]; |
|
180 int len; |
|
181 while((len=fread(demobuf, 1, 512, demofile))>0) { |
|
182 flib_vector_append(vec, demobuf, len); |
|
183 } |
|
184 fclose(demofile); |
|
185 flib_constbuffer constbuf = flib_vector_as_constbuffer(vec); |
|
186 flib_gameconn *gameconn = flib_gameconn_create_playdemo(constbuf.data, constbuf.size); |
|
187 flib_vector_destroy(vec); |
|
188 assert(gameconn); |
|
189 flib_gameconn_onDisconnect(gameconn, &onDisconnect, &gameconn); |
|
190 flib_gameconn_onGameRecorded(gameconn, &onGameRecorded, &gameconn); |
|
191 startEngineGame(flib_gameconn_getport(gameconn)); |
|
192 |
|
193 while(gameconn) { |
|
194 flib_gameconn_tick(gameconn); |
|
195 } |
|
196 } |
|
197 |
|
198 void testSave() { |
|
199 FILE *demofile = fopen("testsave.42.hws", "rb"); |
|
200 assert(demofile); |
|
201 flib_vector *vec = flib_vector_create(); |
|
202 uint8_t demobuf[512]; |
|
203 int len; |
|
204 while((len=fread(demobuf, 1, 512, demofile))>0) { |
|
205 flib_vector_append(vec, demobuf, len); |
|
206 } |
|
207 fclose(demofile); |
|
208 flib_constbuffer constbuf = flib_vector_as_constbuffer(vec); |
|
209 flib_gameconn *gameconn = flib_gameconn_create_loadgame("Medo42", constbuf.data, constbuf.size); |
|
210 flib_vector_destroy(vec); |
|
211 assert(gameconn); |
|
212 flib_gameconn_onDisconnect(gameconn, &onDisconnect, &gameconn); |
|
213 flib_gameconn_onGameRecorded(gameconn, &onGameRecorded, &gameconn); |
|
214 startEngineGame(flib_gameconn_getport(gameconn)); |
|
215 |
|
216 while(gameconn) { |
|
217 flib_gameconn_tick(gameconn); |
|
218 } |
|
219 } |
|
220 |
|
221 void handleNetDisconnect(void *context, int reason, const char *message) { |
|
222 flib_log_i("Disconnected: %s", message); |
|
223 flib_netconn_destroy(*(flib_netconn**)context); |
|
224 *(flib_netconn**)context = NULL; |
|
225 } |
|
226 |
|
227 void handleNetConnected(void *context) { |
|
228 const flib_roomlist *roomlist = flib_netconn_get_roomlist(*(flib_netconn**)context); |
|
229 flib_log_i("List of rooms:"); |
|
230 for(int i=0; i<roomlist->roomCount; i++) { |
|
231 flib_roomlist_room *room = roomlist->rooms[i]; |
|
232 flib_log_i("%1s %20s %20s %2i %2i %20s %20s %20s", room->inProgress ? "X" : " ", room->name, room->owner, room->playerCount, room->teamCount, room->map, room->scheme, room->weapons); |
|
233 } |
|
234 flib_netconn_send_joinRoom(*(flib_netconn**)context, "frontlib test"); |
|
235 } |
|
236 |
|
237 void handleLobbyJoin(void *context, const char *nick) { |
|
238 flib_log_i("%s joined", nick); |
|
239 } |
|
240 |
|
241 void handleChat(void *context, const char *nick, const char *msg) { |
|
242 flib_log_i("%s: %s", nick, msg); |
|
243 if(!memcmp("frontbot ", msg, strlen("frontbot "))) { |
|
244 const char *command = msg+strlen("frontbot "); |
|
245 if(!memcmp("quit", command, strlen("quit"))) { |
|
246 flib_netconn_send_quit(*(flib_netconn**)context, "Yeth Mathter"); |
|
247 } else if(!memcmp("describe ", command, strlen("describe "))) { |
|
248 const char *roomname = command+strlen("describe "); |
|
249 const flib_roomlist *roomlist = flib_netconn_get_roomlist(*(flib_netconn**)context); |
|
250 flib_roomlist_room *room = flib_roomlist_find((flib_roomlist*)roomlist, roomname); |
|
251 if(!room) { |
|
252 flib_netconn_send_chat(*(flib_netconn**)context, "Unknown room."); |
|
253 } else { |
|
254 char *text = flib_asprintf( |
|
255 "%s is a room created by %s, where %i players (%i teams) are %s on %s%s, using the %s scheme and %s weaponset.", |
|
256 room->name, |
|
257 room->owner, |
|
258 room->playerCount, |
|
259 room->teamCount, |
|
260 room->inProgress ? "fighting" : "preparing to fight", |
|
261 room->map[0]=='+' ? "" : "the map ", |
|
262 !strcmp("+rnd+", room->map) ? "a random map" : |
|
263 !strcmp("+maze+", room->map) ? "a random maze" : |
|
264 !strcmp("+drawn+", room->map) ? "a hand-drawn map" : |
|
265 room->map, |
|
266 room->scheme, |
|
267 room->weapons); |
|
268 if(text) { |
|
269 flib_netconn_send_chat(*(flib_netconn**)context, text); |
|
270 } |
|
271 free(text); |
|
272 } |
|
273 } else if(!memcmp("join ", command, strlen("join "))) { |
|
274 const char *roomname = command+strlen("join "); |
|
275 flib_netconn_send_joinRoom(*(flib_netconn**)context, roomname); |
|
276 } else if(!memcmp("ready", command, strlen("ready"))) { |
|
277 flib_netconn_send_toggleReady(*(flib_netconn**)context); |
|
278 } |
|
279 } |
|
280 } |
|
281 |
|
282 void handleEnterRoom(void *context, bool isChief) { |
|
283 flib_netconn_send_toggleReady(*(flib_netconn**)context); |
|
284 } |
|
285 |
|
286 flib_gameconn *gameconn = NULL; |
|
287 |
|
288 void emFromNetHandler(void *context, const char *em, int size) { |
|
289 flib_gameconn_send_enginemsg(gameconn, (const uint8_t*)em, size); |
|
290 } |
|
291 |
|
292 void emFromEngineHandler(void *context, const uint8_t *em, int size) { |
|
293 flib_netconn_send_engineMessage((flib_netconn*)context, em, size); |
|
294 } |
|
295 |
|
296 void handleRunGame(void *context) { |
|
297 flib_gamesetup *gamesetup = flib_netconn_create_gameSetup((flib_netconn*)context); |
|
298 if(gamesetup) { |
|
299 gameconn = flib_gameconn_create("frontbot", gamesetup, true); |
|
300 flib_gameconn_onEngineMessage(gameconn, emFromEngineHandler, context); |
|
301 flib_gameconn_onDisconnect(gameconn, onDisconnect, &gameconn); |
|
302 startEngineGame(flib_gameconn_getport(gameconn)); |
|
303 } |
|
304 } |
|
305 |
|
306 int main(int argc, char *argv[]) { |
|
307 flib_init(0); |
|
308 flib_log_setLevel(FLIB_LOGLEVEL_ALL); |
|
309 |
|
310 //testMapPreview(); |
|
311 //testDemo(); |
|
312 //testSave(); |
|
313 //testGame(); |
|
314 |
|
315 flib_cfg_meta *meta = flib_cfg_meta_from_ini("metasettings.ini"); |
|
316 assert(meta); |
|
317 flib_netconn *conn = flib_netconn_create("frontbot", meta, "140.247.62.101", 46631); |
|
318 assert(conn); |
|
319 flib_cfg_meta_release(meta); |
|
320 |
|
321 flib_netconn_onConnected(conn, handleNetConnected, &conn); |
|
322 flib_netconn_onDisconnected(conn, handleNetDisconnect, &conn); |
|
323 flib_netconn_onLobbyJoin(conn, handleLobbyJoin, &conn); |
|
324 flib_netconn_onChat(conn, handleChat, &conn); |
|
325 flib_netconn_onEnterRoom(conn, handleEnterRoom, conn); |
|
326 flib_netconn_onRunGame(conn, handleRunGame, conn); |
|
327 flib_netconn_onEngineMessage(conn, emFromNetHandler, NULL); |
|
328 |
|
329 while(conn) { |
|
330 flib_netconn_tick(conn); |
|
331 if(gameconn) { |
|
332 flib_gameconn_tick(gameconn); |
|
333 } |
|
334 } |
|
335 |
|
336 flib_quit(); |
|
337 return 0; |
|
338 } |
|