10017
+ − 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/util.h>
+ − 23
#include <base64/base64.h>
+ − 24
#include <model/schemelist.h>
+ − 25
+ − 26
#include <stdlib.h>
+ − 27
#include <stdbool.h>
+ − 28
#include <assert.h>
+ − 29
#include <string.h>
+ − 30
#include <conio.h>
+ − 31
#include <windows.h>
+ − 32
+ − 33
#define ENGINE_DIR ".\\"
+ − 34
#define CONFIG_DIR "..\\share\\hedgewars"
+ − 35
#define DATA_DIR CONFIG_DIR"\\Data"
+ − 36
+ − 37
static flib_netconn *netconn;
+ − 38
static flib_gameconn *gameconn;
+ − 39
static flib_mapconn *mapconn;
+ − 40
static char nickname[128];
+ − 41
static flib_metascheme *metacfg;
+ − 42
static bool netConnected = false;
+ − 43
+ − 44
// Callback function that will be called when the map is rendered
+ − 45
static void handleMapGenerated(void *context, const uint8_t *bitmap, int numHedgehogs) {
+ − 46
printf("Drawing map for %i brave little hogs...", numHedgehogs);
+ − 47
+ − 48
// Draw the map as ASCII art
+ − 49
for(int y=0; y<MAPIMAGE_HEIGHT; y+=8) {
+ − 50
for(int x=0; x<MAPIMAGE_WIDTH; x+=6) {
+ − 51
int pixelnum = x + y*MAPIMAGE_WIDTH;
+ − 52
bool pixel = bitmap[pixelnum>>3] & (1<<(7-(pixelnum&7)));
+ − 53
printf(pixel ? "#" : " ");
+ − 54
}
+ − 55
printf("\n");
+ − 56
}
+ − 57
+ − 58
flib_mapconn_destroy(mapconn);
+ − 59
mapconn = NULL;
+ − 60
}
+ − 61
+ − 62
static void onGameDisconnect(void *context, int reason) {
+ − 63
flib_log_i("Connection closed. Reason: %i", reason);
+ − 64
flib_gameconn_destroy(gameconn);
+ − 65
gameconn = NULL;
+ − 66
if(netconn) {
+ − 67
flib_netconn_send_roundfinished(netconn, reason==GAME_END_FINISHED);
+ − 68
}
+ − 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
flib_mapconn_destroy(mapconn);
+ − 75
mapconn = NULL;
+ − 76
}
+ − 77
+ − 78
static void startEngineMap(int port) {
+ − 79
char cmdbuffer[255];
+ − 80
char argbuffer[255];
+ − 81
snprintf(cmdbuffer, 255, "%shwengine.exe", ENGINE_DIR);
+ − 82
snprintf(argbuffer, 255, "%s %i landpreview", CONFIG_DIR, port);
+ − 83
ShellExecute(NULL, NULL, cmdbuffer, argbuffer, NULL, SW_HIDE);
+ − 84
}
+ − 85
+ − 86
static void startEngineGame(int port) {
+ − 87
char cmdbuffer[255];
+ − 88
char argbuffer[255];
+ − 89
char base64PlayerName[255];
+ − 90
base64_encode(nickname, strlen(nickname), base64PlayerName, sizeof(base64PlayerName));
+ − 91
snprintf(cmdbuffer, 255, "%shwengine.exe", ENGINE_DIR);
+ − 92
snprintf(argbuffer, 255, "%s 1024 768 32 %i 0 0 0 10 10 %s 0 0 %s 0 0 en.txt", CONFIG_DIR, port, DATA_DIR, base64PlayerName);
+ − 93
ShellExecute(NULL, NULL, cmdbuffer, argbuffer, NULL, SW_HIDE);
+ − 94
}
+ − 95
+ − 96
void handleNetDisconnect(void *context, int reason, const char *message) {
+ − 97
printf("Disconnected: %s", message);
+ − 98
flib_netconn_destroy(netconn);
+ − 99
netconn = NULL;
+ − 100
}
+ − 101
+ − 102
/*void printRoomList() {
+ − 103
const flib_roomlist *roomlist = flib_netconn_get_roomlist(netconn);
+ − 104
if(roomlist) {
+ − 105
if(roomlist->roomCount>0) {
+ − 106
for(int i=0; i<roomlist->roomCount; i++) {
+ − 107
if(i>0) {
+ − 108
printf(", ");
+ − 109
}
+ − 110
flib_room *room = roomlist->rooms[i];
+ − 111
printf("%s", room->name);
+ − 112
}
+ − 113
} else {
+ − 114
puts("Unfortunately, there are no rooms at the moment.");
+ − 115
}
+ − 116
} else {
+ − 117
puts("Sorry, due to an error the room list is not available.");
+ − 118
}
+ − 119
puts("\n");
+ − 120
}*/
+ − 121
+ − 122
void printTeamList() {
+ − 123
flib_gamesetup *setup = flib_netconn_create_gamesetup(netconn);
+ − 124
if(setup) {
+ − 125
puts("The following teams are in this room:");
+ − 126
for(int i=0; i<setup->teamlist->teamCount; i++) {
+ − 127
if(i>0) {
+ − 128
printf(", ");
+ − 129
}
+ − 130
printf("%s", setup->teamlist->teams[i]->name);
+ − 131
}
+ − 132
puts("\n");
+ − 133
} else {
+ − 134
puts("Sorry, due to an error the team list is not available.");
+ − 135
}
+ − 136
flib_gamesetup_destroy(setup);
+ − 137
}
+ − 138
+ − 139
void handleNetConnected(void *context) {
+ − 140
printf("You enter the lobby of a strange house inhabited by hedgehogs. Looking around, you see hallways branching off to these rooms:\n");
+ − 141
//printRoomList();
+ − 142
printf("\n\nNow, you can chat by just entering text, or join a room with /join <roomname>.");
+ − 143
printf(" You can also /quit or let me /describe <roomname>. Once in a room, you can /add <teamname> and set yourself /ready. You can also /list the available rooms (in the lobby) or the teams (in a room).\n");
+ − 144
netConnected = true;
+ − 145
}
+ − 146
+ − 147
void handleChat(void *context, const char *nick, const char *msg) {
+ − 148
if(gameconn) {
+ − 149
flib_gameconn_send_chatmsg(gameconn, nick, msg);
+ − 150
}
+ − 151
printf("%s: %s\n", nick, msg);
+ − 152
}
+ − 153
+ − 154
void handleEnterRoom(void *context, bool isChief) {
+ − 155
puts("You have entered the room.");
+ − 156
}
+ − 157
+ − 158
void handleRoomJoin(void *context, const char *nick) {
+ − 159
if(strcmp(nick, nickname)) {
+ − 160
printf("%s is here.\n", nick);
+ − 161
}
+ − 162
}
+ − 163
+ − 164
void handleRoomLeave(void *context, const char *nick, const char *partmsg) {
+ − 165
if(strcmp(nick, nickname)) {
+ − 166
printf("%s leaves.\n", nick);
+ − 167
}
+ − 168
}
+ − 169
+ − 170
void handleReady(void *context, const char *nick, bool ready) {
+ − 171
if(strcmp(nick, nickname)) {
+ − 172
if(ready) {
+ − 173
printf("%s is ready to go.\n", nick);
+ − 174
} else {
+ − 175
printf("%s is not ready.\n", nick);
+ − 176
}
+ − 177
} else {
+ − 178
if(ready) {
+ − 179
printf("You are ready to go.\n");
+ − 180
} else {
+ − 181
printf("You are not ready.\n");
+ − 182
}
+ − 183
}
+ − 184
}
+ − 185
+ − 186
void handleEmFromNet(void *context, const uint8_t *em, size_t size) {
+ − 187
if(gameconn) {
+ − 188
flib_gameconn_send_enginemsg(gameconn, em, size);
+ − 189
}
+ − 190
}
+ − 191
+ − 192
void handleEmFromEngine(void *context, const uint8_t *em, size_t size) {
+ − 193
if(netconn) {
+ − 194
flib_netconn_send_engineMessage(netconn, em, size);
+ − 195
}
+ − 196
}
+ − 197
+ − 198
void handleChatFromGame(void *context, const char *message, bool teamchat) {
+ − 199
if(netconn) {
+ − 200
if(teamchat) {
+ − 201
flib_netconn_send_teamchat(netconn, message);
+ − 202
} else {
+ − 203
flib_netconn_send_chat(netconn, message);
+ − 204
}
+ − 205
}
+ − 206
}
+ − 207
+ − 208
void handleRunGame(void *context) {
+ − 209
flib_gamesetup *gamesetup = flib_netconn_create_gamesetup(netconn);
+ − 210
if(gameconn) {
+ − 211
flib_log_e("Request to start game, but a game is already running.");
+ − 212
} else if(gamesetup) {
+ − 213
gameconn = flib_gameconn_create(nickname, gamesetup, true);
+ − 214
flib_gameconn_onEngineMessage(gameconn, handleEmFromEngine, NULL);
+ − 215
flib_gameconn_onDisconnect(gameconn, onGameDisconnect, NULL);
+ − 216
flib_gameconn_onChat(gameconn, handleChatFromGame, NULL);
+ − 217
startEngineGame(flib_gameconn_getport(gameconn));
+ − 218
}
+ − 219
flib_gamesetup_destroy(gamesetup);
+ − 220
}
+ − 221
+ − 222
void handleNickTaken(void *context, const char *nick) {
+ − 223
printf("The nickname %s is already in use, please choose a different one:\n", nick);
+ − 224
flib_gets(nickname, sizeof(nickname));
+ − 225
flib_netconn_send_nick(netconn, nickname);
+ − 226
}
+ − 227
+ − 228
void handlePwRequest(void *context, const char *nick) {
+ − 229
printf("A password is required to log in as %s, please enter (warning: shown in cleartext):\n", nick);
+ − 230
char password[256];
+ − 231
flib_gets(password, sizeof(password));
+ − 232
flib_netconn_send_password(netconn, password);
+ − 233
}
+ − 234
+ − 235
void handleMessage(void *context, int type, const char *msg) {
+ − 236
if(gameconn) {
+ − 237
flib_gameconn_send_textmsg(gameconn, 1, msg);
+ − 238
}
+ − 239
printf("*** %s\n", msg);
+ − 240
}
+ − 241
+ − 242
void handleTeamAccepted(void *context, const char *teamname) {
+ − 243
printf("The team %s has been accepted.\n", teamname);
+ − 244
}
+ − 245
+ − 246
void handleMapChanged(void *context, const flib_map *map, int changetype) {
+ − 247
if(map->mapgen != MAPGEN_NAMED && changetype != NETCONN_MAPCHANGE_THEME) {
+ − 248
if(mapconn) {
+ − 249
flib_mapconn_destroy(mapconn);
+ − 250
mapconn = NULL;
+ − 251
}
+ − 252
mapconn = flib_mapconn_create(map);
+ − 253
if(mapconn) {
+ − 254
flib_mapconn_onSuccess(mapconn, handleMapGenerated, NULL);
+ − 255
flib_mapconn_onFailure(mapconn, handleMapFailure, NULL);
+ − 256
startEngineMap(flib_mapconn_getport(mapconn));
+ − 257
}
+ − 258
} else if(map->mapgen == MAPGEN_NAMED) {
+ − 259
printf("The map %s has been selected.\n", map->name);
+ − 260
}
+ − 261
}
+ − 262
+ − 263
void handleLeaveRoom(void *context, int reason, const char *msg) {
+ − 264
if(reason == NETCONN_ROOMLEAVE_ABANDONED) {
+ − 265
printf("The chief has abandoned the room.");
+ − 266
} else if(reason == NETCONN_ROOMLEAVE_KICKED) {
+ − 267
printf("You have been kicked from the room.");
+ − 268
}
+ − 269
if(msg) {
+ − 270
printf(" (%s)", msg);
+ − 271
}
+ − 272
puts(" You are back in the lobby.");
+ − 273
}
+ − 274
+ − 275
void handleSchemeChanged(void *context, const flib_scheme *scheme) {
+ − 276
printf("Game scheme: %s.\n", scheme->name);
+ − 277
}
+ − 278
+ − 279
void handleWeaponsetChanged(void *context, const flib_weaponset *weaponset) {
+ − 280
printf("Weaponset: %s.\n", weaponset->name);
+ − 281
}
+ − 282
+ − 283
void handleHogcountChanged(void *context, const char *team, int count) {
+ − 284
printf("Team %s will send %i hogs into the fight.\n", team, count);
+ − 285
}
+ − 286
+ − 287
void handleRoomAdd(void *context, const flib_room *room) {
+ − 288
printf("%s created a new room called %s.\n", room->owner, room->name);
+ − 289
}
+ − 290
+ − 291
void handleRoomDelete(void *context, const char *roomName) {
+ − 292
printf("The room %s has collapsed.\n", roomName);
+ − 293
}
+ − 294
+ − 295
void handleScriptChanged(void *context, const char *script) {
+ − 296
printf("Game Type: %s\n", script);
+ − 297
}
+ − 298
+ − 299
void handleTeamAdd(void *context, const flib_team *team) {
+ − 300
printf("%s puts the team %s to the planning board.\n", team->ownerName, team->name);
+ − 301
}
+ − 302
+ − 303
void handleTeamDelete(void *context, const char *teamName) {
+ − 304
printf("The team %s decided not to fight this battle after all.\n", teamName);
+ − 305
}
+ − 306
+ − 307
void handleTeamColorChanged(void *context, const char *name, int colorIndex) {
+ − 308
static const char* colorNames[] = {"red", "blue", "teal", "purple", "pink", "green", "orange", "brown", "yellow"};
+ − 309
const char *colorName = "strange";
+ − 310
if(colorIndex>=0 && colorIndex < 9) {
+ − 311
colorName = colorNames[colorIndex];
+ − 312
}
+ − 313
printf("The team %s will wear %s uniforms today.\n", name, colorName);
+ − 314
}
+ − 315
+ − 316
void tick() {
+ − 317
if(gameconn) {
+ − 318
flib_gameconn_tick(gameconn);
+ − 319
}
+ − 320
if(netconn) {
+ − 321
flib_netconn_tick(netconn);
+ − 322
}
+ − 323
if(mapconn) {
+ − 324
flib_mapconn_tick(mapconn);
+ − 325
}
+ − 326
}
+ − 327
+ − 328
static HANDLE hStdin;
+ − 329
+ − 330
static int init() {
+ − 331
hStdin = GetStdHandle(STD_INPUT_HANDLE);
+ − 332
if(hStdin == INVALID_HANDLE_VALUE) {
+ − 333
flib_log_e("Unable to get stdin handle");
+ − 334
return 1;
+ − 335
}
+ − 336
if(!flib_init(0)) {
+ − 337
flib_log_setLevel(FLIB_LOGLEVEL_WARNING);
+ − 338
freopen( "CON", "w", stdout );
+ − 339
freopen( "CON", "w", stderr );
+ − 340
metacfg = flib_metascheme_from_ini("metasettings.ini");
+ − 341
if(!metacfg) {
+ − 342
flib_quit();
+ − 343
return -1;
+ − 344
} else {
+ − 345
return 0;
+ − 346
}
+ − 347
}
+ − 348
return -1;
+ − 349
}
+ − 350
+ − 351
int main(int argc, char *argv[]) {
+ − 352
if(init()) {
+ − 353
return -1;
+ − 354
}
+ − 355
+ − 356
puts("Please enter a nickname:");
+ − 357
flib_gets(nickname, sizeof(nickname));
+ − 358
+ − 359
netconn = flib_netconn_create(nickname, metacfg, DATA_DIR"\\", "140.247.62.101", 46631);
+ − 360
if(!netconn) {
+ − 361
flib_quit();
+ − 362
return -1;
+ − 363
}
+ − 364
+ − 365
flib_netconn_onConnected(netconn, handleNetConnected, NULL);
+ − 366
flib_netconn_onDisconnected(netconn, handleNetDisconnect, NULL);
+ − 367
flib_netconn_onChat(netconn, handleChat, NULL);
+ − 368
flib_netconn_onEnterRoom(netconn, handleEnterRoom, NULL);
+ − 369
flib_netconn_onRunGame(netconn, handleRunGame, NULL);
+ − 370
flib_netconn_onEngineMessage(netconn, handleEmFromNet, NULL);
+ − 371
flib_netconn_onRoomJoin(netconn, handleRoomJoin, NULL);
+ − 372
flib_netconn_onRoomLeave(netconn, handleRoomLeave, NULL);
+ − 373
flib_netconn_onReadyState(netconn, handleReady, NULL);
+ − 374
flib_netconn_onNickTaken(netconn, handleNickTaken, NULL);
+ − 375
flib_netconn_onPasswordRequest(netconn, handlePwRequest, NULL);
+ − 376
flib_netconn_onMessage(netconn, handleMessage, NULL);
+ − 377
flib_netconn_onTeamAccepted(netconn, handleTeamAccepted, NULL);
+ − 378
flib_netconn_onMapChanged(netconn, handleMapChanged, NULL);
+ − 379
flib_netconn_onLeaveRoom(netconn, handleLeaveRoom, NULL);
+ − 380
flib_netconn_onCfgScheme(netconn, handleSchemeChanged, NULL);
+ − 381
flib_netconn_onWeaponsetChanged(netconn, handleWeaponsetChanged, NULL);
+ − 382
flib_netconn_onHogCountChanged(netconn, handleHogcountChanged, NULL);
+ − 383
flib_netconn_onRoomAdd(netconn, handleRoomAdd, NULL);
+ − 384
flib_netconn_onRoomDelete(netconn, handleRoomDelete, NULL);
+ − 385
flib_netconn_onScriptChanged(netconn, handleScriptChanged, NULL);
+ − 386
flib_netconn_onTeamAdd(netconn, handleTeamAdd, NULL);
+ − 387
flib_netconn_onTeamDelete(netconn, handleTeamDelete, NULL);
+ − 388
flib_netconn_onTeamColorChanged(netconn, handleTeamColorChanged, NULL);
+ − 389
+ − 390
INPUT_RECORD inputRecord;
+ − 391
DWORD eventCount = 0;
+ − 392
+ − 393
while(netconn || gameconn) {
+ − 394
tick();
+ − 395
if(netconn && netConnected) {
+ − 396
while(PeekConsoleInput(hStdin, &inputRecord, 1, &eventCount) && eventCount>0) {
+ − 397
if(inputRecord.EventType != KEY_EVENT) {
+ − 398
ReadConsoleInput(hStdin, &inputRecord, 1, &eventCount);
+ − 399
} else {
+ − 400
printf("%s: ", nickname);
+ − 401
char input[256];
+ − 402
if(!flib_gets(input, sizeof(input))) {
+ − 403
if(!memcmp("/quit", input, strlen("/quit"))) {
+ − 404
flib_netconn_send_quit(netconn, "Player quit.");
+ − 405
} else if(!memcmp("/describe ", input, strlen("/describe "))) {
+ − 406
const char *roomname = input+strlen("/describe ");
+ − 407
/*const flib_roomlist *roomlist = flib_netconn_get_roomlist(netconn);
+ − 408
flib_room *room = flib_roomlist_find(roomlist, roomname);
+ − 409
if(!room) {
+ − 410
puts("Unknown room.");
+ − 411
} else {
+ − 412
char *text = flib_asprintf(
+ − 413
"%s is a room created by %s, where %i players (%i teams) are %s on %s%s, using the %s scheme and %s weaponset.",
+ − 414
room->name,
+ − 415
room->owner,
+ − 416
room->playerCount,
+ − 417
room->teamCount,
+ − 418
room->inProgress ? "fighting" : "preparing to fight",
+ − 419
room->map[0]=='+' ? "" : "the map ",
+ − 420
!strcmp("+rnd+", room->map) ? "a random map" :
+ − 421
!strcmp("+maze+", room->map) ? "a random maze" :
+ − 422
!strcmp("+drawn+", room->map) ? "a hand-drawn map" :
+ − 423
room->map,
+ − 424
room->scheme,
+ − 425
room->weapons);
+ − 426
if(text) {
+ − 427
puts(text);
+ − 428
}
+ − 429
free(text);
+ − 430
}*/
+ − 431
} else if(!memcmp("/join ", input, strlen("/join "))) {
+ − 432
const char *roomname = input+strlen("/join ");
+ − 433
flib_netconn_send_joinRoom(netconn, roomname);
+ − 434
} else if(!memcmp("/ready", input, strlen("/ready"))) {
+ − 435
flib_netconn_send_toggleReady(netconn);
+ − 436
} else if(!memcmp("/loglevel ", input, strlen("/loglevel "))) {
+ − 437
int loglevel = atoi(input+strlen("/loglevel "));
+ − 438
flib_log_setLevel(loglevel);
+ − 439
} else if(!memcmp("/list", input, strlen("/list"))) {
+ − 440
if(flib_netconn_is_in_room_context(netconn)) {
+ − 441
printTeamList();
+ − 442
} else {
+ − 443
puts("From this big and expansive lobby, hallways branch off to these rooms:");
+ − 444
//printRoomList();
+ − 445
}
+ − 446
} else if(!memcmp("/addteam ", input, strlen("/addteam "))) {
+ − 447
const char *teamname = input+strlen("/addteam ");
+ − 448
if(!flib_contains_dir_separator(teamname)) {
+ − 449
char *teamfilename = flib_asprintf("%s.hwt", teamname);
+ − 450
if(teamfilename) {
+ − 451
flib_team *team = flib_team_from_ini(teamfilename);
+ − 452
if(team) {
+ − 453
flib_netconn_send_addTeam(netconn, team);
+ − 454
} else {
+ − 455
printf("Teamfile %s not found.\n", teamfilename);
+ − 456
}
+ − 457
flib_team_destroy(team);
+ − 458
}
+ − 459
free(teamfilename);
+ − 460
}
+ − 461
} else if(strlen(input)>0) {
+ − 462
flib_netconn_send_chat(netconn, input);
+ − 463
}
+ − 464
}
+ − 465
}
+ − 466
}
+ − 467
}
+ − 468
fflush(stdout);
+ − 469
Sleep(10);
+ − 470
}
+ − 471
+ − 472
+ − 473
flib_metascheme_release(metacfg);
+ − 474
return 0;
+ − 475
}