--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/frontlib/cmdlineClient.c Wed Jun 27 18:02:45 2012 +0200
@@ -0,0 +1,474 @@
+#include "frontlib.h"
+#include "util/logging.h"
+#include "util/buffer.h"
+#include "util/util.h"
+#include "util/list.h"
+#include "model/map.h"
+#include "model/weapon.h"
+#include "model/schemelist.h"
+#include "ipc/mapconn.h"
+#include "ipc/gameconn.h"
+#include "net/netconn.h"
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <string.h>
+#include <conio.h>
+#include <windows.h>
+
+#define ENGINE_DIR ".\\"
+#define CONFIG_DIR "..\\share\\hedgewars"
+#define DATA_DIR CONFIG_DIR"\\Data"
+
+static flib_netconn *netconn;
+static flib_gameconn *gameconn;
+static flib_mapconn *mapconn;
+static char nickname[128];
+static flib_cfg_meta *metacfg;
+static bool netConnected = false;
+
+// Callback function that will be called when the map is rendered
+static void handleMapGenerated(void *context, const uint8_t *bitmap, int numHedgehogs) {
+ printf("Drawing map for %i brave little hogs...", numHedgehogs);
+
+ // Draw the map as ASCII art
+ for(int y=0; y<MAPIMAGE_HEIGHT; y+=8) {
+ for(int x=0; x<MAPIMAGE_WIDTH; x+=6) {
+ int pixelnum = x + y*MAPIMAGE_WIDTH;
+ bool pixel = bitmap[pixelnum>>3] & (1<<(7-(pixelnum&7)));
+ printf(pixel ? "#" : " ");
+ }
+ printf("\n");
+ }
+
+ // Destroy the connection object (this will end the "tick" loop below)
+ flib_mapconn_destroy(mapconn);
+ mapconn = NULL;
+}
+
+static void onGameDisconnect(void *context, int reason) {
+ flib_log_i("Connection closed. Reason: %i", reason);
+ flib_gameconn_destroy(gameconn);
+ gameconn = NULL;
+}
+
+// Callback function that will be called on error
+static void handleMapFailure(void *context, const char *errormessage) {
+ flib_log_e("Map rendering failed: %s", errormessage);
+
+ // Destroy the connection object (this will end the "tick" loop below)
+ flib_mapconn_destroy(mapconn);
+ mapconn = NULL;
+}
+
+static void startEngineMap(int port) {
+ char cmdbuffer[255];
+ char argbuffer[255];
+ snprintf(cmdbuffer, 255, "%shwengine.exe", ENGINE_DIR);
+ snprintf(argbuffer, 255, "%s %i landpreview", CONFIG_DIR, port);
+ ShellExecute(NULL, NULL, cmdbuffer, argbuffer, NULL, SW_HIDE);
+}
+
+static void startEngineGame(int port) {
+ char cmdbuffer[255];
+ char argbuffer[255];
+ snprintf(cmdbuffer, 255, "%shwengine.exe", ENGINE_DIR);
+ snprintf(argbuffer, 255, "%s 1024 768 32 %i 0 0 0 10 10 %s 0 0 TWVkbzQy 0 0 en.txt", CONFIG_DIR, port, DATA_DIR);
+ ShellExecute(NULL, NULL, cmdbuffer, argbuffer, NULL, SW_HIDE);
+}
+
+void testMapPreview() {
+ // Create a map description and check that there was no error
+ flib_map *map = flib_map_create_maze("This is the seed value", "Jungle", MAZE_SIZE_SMALL_TUNNELS);
+ assert(map);
+
+ // Create a new connection to the engine and check that there was no error
+ flib_mapconn *mapConnection = flib_mapconn_create(map);
+ assert(mapConnection);
+
+ // We don't need the map description anymore
+ flib_map_release(map);
+ map = NULL;
+
+ // Register the callback functions
+ flib_mapconn_onFailure(mapConnection, &handleMapFailure, &mapConnection);
+ flib_mapconn_onSuccess(mapConnection, &handleMapGenerated, &mapConnection);
+
+ // Start the engine process and tell it which port the frontlib is listening on
+ startEngineMap(flib_mapconn_getport(mapConnection));
+
+ // Usually, flib_mapconn_tick will be called in an event loop that runs several
+ // times per second. It handles I/O operations and progress, and calls
+ // callbacks when something interesting happens.
+ while(mapConnection) {
+ flib_mapconn_tick(mapConnection);
+ }
+}
+
+void handleNetDisconnect(void *context, int reason, const char *message) {
+ printf("Disconnected: %s", message);
+ flib_netconn_destroy(netconn);
+ netconn = NULL;
+}
+
+void printRoomList() {
+ const flib_roomlist *roomlist = flib_netconn_get_roomlist(netconn);
+ if(roomlist) {
+ for(int i=0; i<roomlist->roomCount; i++) {
+ if(i>0) {
+ printf(", ");
+ }
+ flib_room *room = roomlist->rooms[i];
+ printf("%s", room->name);
+ }
+ puts("\n");
+ } else {
+ puts("Sorry, due to an error the room list is not available.");
+ }
+}
+
+void printTeamList() {
+ flib_gamesetup *setup = flib_netconn_create_gameSetup(netconn);
+ if(setup) {
+ puts("The following teams are in this room:");
+ for(int i=0; i<setup->teamlist->teamCount; i++) {
+ if(i>0) {
+ printf(", ");
+ }
+ printf("%s", setup->teamlist->teams[i]->name);
+ }
+ puts("\n");
+ } else {
+ puts("Sorry, due to an error the team list is not available.");
+ }
+ flib_gamesetup_destroy(setup);
+}
+
+void handleNetConnected(void *context) {
+ printf("You enter a strange house inhabited by dozens of hedgehogs. There are many rooms in here:\n");
+ printRoomList();
+ printf("\n\nNow, you can chat by just entering text, or join a room with /join <roomname>.");
+ 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");
+ netConnected = true;
+}
+
+void handleChat(void *context, const char *nick, const char *msg) {
+ printf("%s: %s\n", nick, msg);
+}
+
+void handleEnterRoom(void *context, bool isChief) {
+ puts("You have entered the room.");
+}
+
+void handleRoomJoin(void *context, const char *nick) {
+ if(strcmp(nick, nickname)) {
+ printf("%s is here.\n", nick);
+ }
+}
+
+void handleRoomLeave(void *context, const char *nick, const char *partmsg) {
+ if(strcmp(nick, nickname)) {
+ printf("%s leaves.\n", nick);
+ }
+}
+
+void handleReady(void *context, const char *nick, bool ready) {
+ if(strcmp(nick, nickname)) {
+ if(ready) {
+ printf("%s is ready to go.\n", nick);
+ } else {
+ printf("%s is not ready.\n", nick);
+ }
+ } else {
+ if(ready) {
+ printf("You are ready to go.\n");
+ } else {
+ printf("You are not ready.\n");
+ }
+ }
+}
+
+void handleEmFromNet(void *context, const uint8_t *em, size_t size) {
+ if(gameconn) {
+ flib_gameconn_send_enginemsg(gameconn, (const uint8_t*)em, size);
+ }
+}
+
+void handleEmFromEngine(void *context, const uint8_t *em, size_t size) {
+ if(netconn) {
+ flib_netconn_send_engineMessage(netconn, em, size);
+ }
+}
+
+void handleChatFromGame(void *context, const char *message, bool teamchat) {
+ if(netconn) {
+ if(teamchat) {
+ flib_netconn_send_teamchat(netconn, message);
+ } else {
+ flib_netconn_send_chat(netconn, message);
+ }
+ }
+}
+
+void handleRunGame(void *context) {
+ flib_gamesetup *gamesetup = flib_netconn_create_gameSetup(netconn);
+ if(gamesetup) {
+ gameconn = flib_gameconn_create(nickname, gamesetup, true);
+ flib_gameconn_onEngineMessage(gameconn, handleEmFromEngine, NULL);
+ flib_gameconn_onDisconnect(gameconn, onGameDisconnect, NULL);
+ flib_gameconn_onChat(gameconn, handleChatFromGame, NULL);
+ startEngineGame(flib_gameconn_getport(gameconn));
+ }
+ flib_gamesetup_destroy(gamesetup);
+}
+
+void handleNickTaken(void *context, const char *nick) {
+ printf("The nickname %s is already in use, please choose a different one:\n", nick);
+ flib_gets(nickname, sizeof(nickname));
+ flib_netconn_send_nick(netconn, nickname);
+}
+
+void handlePwRequest(void *context, const char *nick) {
+ printf("A password is required to log in as %s, please enter (warning: shown in cleartext):\n", nick);
+ char password[256];
+ flib_gets(password, sizeof(password));
+ flib_netconn_send_password(netconn, password);
+}
+
+void handleMessage(void *context, int type, const char *msg) {
+ printf("*** %s\n", msg);
+}
+
+void handleTeamAccepted(void *context, const char *teamname) {
+ printf("The team %s has been accepted.\n", teamname);
+}
+
+void handleMapChanged(void *context, const flib_map *map, int changetype) {
+ if(map->mapgen != MAPGEN_NAMED && changetype != NETCONN_MAPCHANGE_THEME) {
+ if(mapconn) {
+ flib_mapconn_destroy(mapconn);
+ mapconn = NULL;
+ }
+ mapconn = flib_mapconn_create(map);
+ if(mapconn) {
+ flib_mapconn_onSuccess(mapconn, handleMapGenerated, NULL);
+ flib_mapconn_onFailure(mapconn, handleMapFailure, NULL);
+ startEngineMap(flib_mapconn_getport(mapconn));
+ }
+ }
+}
+
+void handleLeaveRoom(void *context, int reason, const char *msg) {
+ if(reason == NETCONN_ROOMLEAVE_ABANDONED) {
+ printf("The chief has abandoned the room.");
+ } else if(reason == NETCONN_ROOMLEAVE_KICKED) {
+ printf("You have been kicked from the room.");
+ }
+ if(msg) {
+ printf(" (%s)", msg);
+ }
+ puts(" You are back in the lobby.");
+}
+
+void handleSchemeChanged(void *context, flib_cfg *scheme) {
+ printf("Game scheme: %s.\n", scheme->name);
+}
+
+void handleWeaponsetChanged(void *context, flib_weaponset *weaponset) {
+ printf("Weaponset: %s.\n", weaponset->name);
+}
+
+void handleHogcountChanged(void *context, const char *team, int count) {
+ printf("Team %s will send %i hogs into the fight.\n", team, count);
+}
+
+void handleRoomAdd(void *context, const flib_room *room) {
+ printf("%s created a new room called %s.\n", room->owner, room->name);
+}
+
+void handleRoomDelete(void *context, const char *roomName) {
+ printf("The room %s has collapsed.\n", roomName);
+}
+
+void handleScriptChanged(void *context, const char *script) {
+ printf("Game Type: %s\n", script);
+}
+
+void handleTeamAdd(void *context, flib_team *team) {
+ printf("%s puts the team %s to the planning board.\n", team->ownerName, team->name);
+}
+
+void handleTeamDelete(void *context, const char *teamName) {
+ printf("The team %s decided not to fight this battle after all.\n", teamName);
+}
+
+void handleTeamColorChanged(void *context, const char *name, int colorIndex) {
+ static const char* colorNames[] = {"red", "blue", "teal", "purple", "pink", "green", "orange", "brown", "yellow"};
+ const char *colorName = "strange";
+ if(colorIndex>=0 && colorIndex < 9) {
+ colorName = colorNames[colorIndex];
+ }
+ printf("The team %s will wear %s uniforms today.\n", name, colorName);
+}
+
+void tick() {
+ if(gameconn) {
+ flib_gameconn_tick(gameconn);
+ }
+ if(netconn) {
+ flib_netconn_tick(netconn);
+ }
+ if(mapconn) {
+ flib_mapconn_tick(mapconn);
+ }
+}
+
+static HANDLE hStdin;
+
+static int init() {
+ hStdin = GetStdHandle(STD_INPUT_HANDLE);
+ if(hStdin == INVALID_HANDLE_VALUE) {
+ flib_log_e("Unable to get stdin handle");
+ return 1;
+ }
+ if(!flib_init(0)) {
+ flib_log_setLevel(FLIB_LOGLEVEL_WARNING);
+ freopen( "CON", "w", stdout );
+ freopen( "CON", "w", stderr );
+ metacfg = flib_cfg_meta_from_ini("metasettings.ini");
+ if(!metacfg) {
+ flib_quit();
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+ return -1;
+}
+
+int main(int argc, char *argv[]) {
+ if(init()) {
+ return -1;
+ }
+
+ puts("Please enter a nickname:");
+ flib_gets(nickname, sizeof(nickname));
+
+ netconn = flib_netconn_create(nickname, metacfg, DATA_DIR"\\", "140.247.62.101", 46631);
+ if(!netconn) {
+ flib_quit();
+ return -1;
+ }
+
+ flib_netconn_onConnected(netconn, handleNetConnected, NULL);
+ flib_netconn_onDisconnected(netconn, handleNetDisconnect, NULL);
+ flib_netconn_onChat(netconn, handleChat, NULL);
+ flib_netconn_onEnterRoom(netconn, handleEnterRoom, NULL);
+ flib_netconn_onRunGame(netconn, handleRunGame, NULL);
+ flib_netconn_onEngineMessage(netconn, handleEmFromNet, NULL);
+ flib_netconn_onRoomJoin(netconn, handleRoomJoin, NULL);
+ flib_netconn_onRoomLeave(netconn, handleRoomLeave, NULL);
+ flib_netconn_onReadyState(netconn, handleReady, NULL);
+ flib_netconn_onNickTaken(netconn, handleNickTaken, NULL);
+ flib_netconn_onPasswordRequest(netconn, handlePwRequest, NULL);
+ flib_netconn_onMessage(netconn, handleMessage, NULL);
+ flib_netconn_onTeamAccepted(netconn, handleTeamAccepted, NULL);
+ flib_netconn_onMapChanged(netconn, handleMapChanged, NULL);
+ flib_netconn_onLeaveRoom(netconn, handleLeaveRoom, NULL);
+ flib_netconn_onCfgScheme(netconn, handleSchemeChanged, NULL);
+ flib_netconn_onWeaponsetChanged(netconn, handleWeaponsetChanged, NULL);
+ flib_netconn_onHogCountChanged(netconn, handleHogcountChanged, NULL);
+ flib_netconn_onRoomAdd(netconn, handleRoomAdd, NULL);
+ flib_netconn_onRoomDelete(netconn, handleRoomDelete, NULL);
+ flib_netconn_onScriptChanged(netconn, handleScriptChanged, NULL);
+ flib_netconn_onTeamAdd(netconn, handleTeamAdd, NULL);
+ flib_netconn_onTeamDelete(netconn, handleTeamDelete, NULL);
+ flib_netconn_onTeamColorChanged(netconn, handleTeamColorChanged, NULL);
+
+ INPUT_RECORD inputRecord;
+ DWORD eventCount = 0;
+
+ while(netconn || gameconn) {
+ tick();
+ if(netconn && netConnected) {
+ while(PeekConsoleInput(hStdin, &inputRecord, 1, &eventCount) && eventCount>0) {
+ if(inputRecord.EventType != KEY_EVENT) {
+ ReadConsoleInput(hStdin, &inputRecord, 1, &eventCount);
+ } else {
+ printf("%s: ", nickname);
+ char input[256];
+ if(!flib_gets(input, sizeof(input))) {
+ if(!memcmp("/quit", input, strlen("/quit"))) {
+ flib_netconn_send_quit(netconn, "Player quit.");
+ } else if(!memcmp("/describe ", input, strlen("/describe "))) {
+ const char *roomname = input+strlen("/describe ");
+ const flib_roomlist *roomlist = flib_netconn_get_roomlist(netconn);
+ flib_room *room = flib_roomlist_find(roomlist, roomname);
+ if(!room) {
+ puts("Unknown room.");
+ } else {
+ char *text = flib_asprintf(
+ "%s is a room created by %s, where %i players (%i teams) are %s on %s%s, using the %s scheme and %s weaponset.",
+ room->name,
+ room->owner,
+ room->playerCount,
+ room->teamCount,
+ room->inProgress ? "fighting" : "preparing to fight",
+ room->map[0]=='+' ? "" : "the map ",
+ !strcmp("+rnd+", room->map) ? "a random map" :
+ !strcmp("+maze+", room->map) ? "a random maze" :
+ !strcmp("+drawn+", room->map) ? "a hand-drawn map" :
+ room->map,
+ room->scheme,
+ room->weapons);
+ if(text) {
+ puts(text);
+ }
+ free(text);
+ }
+ } else if(!memcmp("/join ", input, strlen("/join "))) {
+ const char *roomname = input+strlen("/join ");
+ flib_netconn_send_joinRoom(netconn, roomname);
+ } else if(!memcmp("/ready", input, strlen("/ready"))) {
+ flib_netconn_send_toggleReady(netconn);
+ } else if(!memcmp("/loglevel ", input, strlen("/loglevel "))) {
+ int loglevel = atoi(input+strlen("/loglevel "));
+ flib_log_setLevel(loglevel);
+ } else if(!memcmp("/list", input, strlen("/list"))) {
+ if(flib_netconn_is_in_room_context(netconn)) {
+ printTeamList();
+ } else {
+ puts("From this big and expansive lobby, hallways branch off to these rooms:");
+ printRoomList();
+ }
+ } else if(!memcmp("/addteam ", input, strlen("/addteam "))) {
+ const char *teamname = input+strlen("/addteam ");
+ if(!flib_contains_dir_separator(teamname)) {
+ char *teamfilename = flib_asprintf("%s.hwt", teamname);
+ if(teamfilename) {
+ flib_team *team = flib_team_from_ini(teamfilename);
+ if(team) {
+ flib_netconn_send_addTeam(netconn, team);
+ } else {
+ printf("Teamfile %s not found.\n", teamfilename);
+ }
+ flib_team_release(team);
+ }
+ free(teamfilename);
+ }
+ } else if(strlen(input)>0) {
+ flib_netconn_send_chat(netconn, input);
+ }
+ }
+ }
+ }
+ }
+ fflush(stdout);
+ Sleep(10);
+ }
+
+
+ flib_cfg_meta_release(metacfg);
+ return 0;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/frontlib/hwconsts.c Wed Jun 27 18:02:45 2012 +0200
@@ -0,0 +1,4 @@
+#include "hwconsts.h"
+
+const uint32_t flib_teamcolor_defaults[] = HW_TEAMCOLOR_ARRAY;
+const size_t flib_teamcolor_defaults_len = sizeof(flib_teamcolor_defaults)/sizeof(uint32_t)-1;
--- a/project_files/frontlib/hwconsts.h Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/hwconsts.h Wed Jun 27 18:02:45 2012 +0200
@@ -1,3 +1,22 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2012 Simeon Maxein <smaxein@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
/**
* This file contains important constants which might need to be changed to adapt to
* changes in the engine or protocols.
@@ -6,14 +25,34 @@
#ifndef HWCONSTS_H_
#define HWCONSTS_H_
+#include <inttypes.h>
+#include <stddef.h>
+
#define HEDGEHOGS_PER_TEAM 8
#define NETGAME_DEFAULT_PORT 46631
-#define PROTOCOL_VERSION 41
+#define PROTOCOL_VERSION 42
#define MIN_SERVER_VERSION 1
-#define GAMEMOD_PERHOGAMMO_MASKBIT 22
-#define GAMEMOD_SHAREDAMMO_MASKBIT 16
+// Used for sending scripts to the engine
+#define MULTIPLAYER_SCRIPT_PATH "Scripts/Multiplayer/"
#define WEAPONS_COUNT 55
+/* A merge of mikade/bugq colours w/ a bit of channel feedback */
+#define HW_TEAMCOLOR_ARRAY { UINT32_C(0xffff0204), /* red */ \
+ UINT32_C(0xff4980c1), /* blue */ \
+ UINT32_C(0xff1de6ba), /* teal */ \
+ UINT32_C(0xffb541ef), /* purple */ \
+ UINT32_C(0xffe55bb0), /* pink */ \
+ UINT32_C(0xff20bf00), /* green */ \
+ UINT32_C(0xfffe8b0e), /* orange */ \
+ UINT32_C(0xff5f3605), /* brown */ \
+ UINT32_C(0xffffff01), /* yellow */ \
+ /* add new colors here */ \
+ 0 } /* Keep this 0 at the end or the length will be calculated wrong */
+
+// TODO allow setting alternative color lists?
+extern const size_t flib_teamcolor_defaults_len;
+extern const uint32_t flib_teamcolor_defaults[];
+
#endif
--- a/project_files/frontlib/ipc/gameconn.c Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/ipc/gameconn.c Wed Jun 27 18:02:45 2012 +0200
@@ -38,7 +38,7 @@
void (*onGameRecordedCb)(void *context, const uint8_t *record, int size, bool isSavegame);
void *onGameRecordedCtx;
- void (*onEngineMessageCb)(void *context, const uint8_t *em, int size);
+ void (*onEngineMessageCb)(void *context, const uint8_t *em, size_t size);
void *onEngineMessageCtx;
bool running;
@@ -52,7 +52,7 @@
}
static void defaultCallback_onChat(void* context, const char *msg, bool teamchat) {}
static void defaultCallback_onGameRecorded(void *context, const uint8_t *record, int size, bool isSavegame) {}
-static void defaultCallback_onEngineMessage(void *context, const uint8_t *em, int size) {}
+static void defaultCallback_onEngineMessage(void *context, const uint8_t *em, size_t size) {}
static void clearCallbacks(flib_gameconn *conn) {
conn->onConnectCb = &defaultCallback_onConnect;
@@ -65,23 +65,25 @@
static flib_gameconn *flib_gameconn_create_partial(bool record, const char *playerName, bool netGame) {
flib_gameconn *result = NULL;
- flib_gameconn *tempConn = flib_calloc(1, sizeof(flib_gameconn));
- if(tempConn) {
- tempConn->ipcBase = flib_ipcbase_create();
- tempConn->configBuffer = flib_vector_create();
- tempConn->playerName = flib_strdupnull(playerName);
- if(tempConn->ipcBase && tempConn->configBuffer && tempConn->playerName) {
- if(record) {
- tempConn->demoBuffer = flib_vector_create();
+ if(!log_badparams_if(!playerName)) {
+ flib_gameconn *tempConn = flib_calloc(1, sizeof(flib_gameconn));
+ if(tempConn) {
+ tempConn->ipcBase = flib_ipcbase_create();
+ tempConn->configBuffer = flib_vector_create();
+ tempConn->playerName = flib_strdupnull(playerName);
+ if(tempConn->ipcBase && tempConn->configBuffer && tempConn->playerName) {
+ if(record) {
+ tempConn->demoBuffer = flib_vector_create();
+ }
+ tempConn->state = AWAIT_CONNECTION;
+ tempConn->netgame = netGame;
+ clearCallbacks(tempConn);
+ result = tempConn;
+ tempConn = NULL;
}
- tempConn->state = AWAIT_CONNECTION;
- tempConn->netgame = netGame;
- clearCallbacks(tempConn);
- result = tempConn;
- tempConn = NULL;
}
+ flib_gameconn_destroy(tempConn);
}
- flib_gameconn_destroy(tempConn);
return result;
}
@@ -89,7 +91,9 @@
flib_gameconn *result = NULL;
flib_gameconn *tempConn = flib_gameconn_create_partial(true, playerName, netgame);
if(tempConn) {
- if(!flib_ipc_append_fullconfig(tempConn->configBuffer, setup, netgame)) {
+ if(flib_ipc_append_fullconfig(tempConn->configBuffer, setup, netgame)) {
+ flib_log_e("Error generating full game configuration for the engine.");
+ } else {
result = tempConn;
tempConn = NULL;
}
@@ -102,7 +106,7 @@
flib_gameconn *result = NULL;
flib_gameconn *tempConn = flib_gameconn_create_partial(false, "Player", false);
if(tempConn) {
- if(flib_vector_append(tempConn->configBuffer, demo, size) == size) {
+ if(!flib_vector_append(tempConn->configBuffer, demo, size)) {
result = tempConn;
tempConn = NULL;
}
@@ -115,7 +119,7 @@
flib_gameconn *result = NULL;
flib_gameconn *tempConn = flib_gameconn_create_partial(true, playerName, false);
if(tempConn) {
- if(flib_vector_append(tempConn->configBuffer, save, size) == size) {
+ if(!flib_vector_append(tempConn->configBuffer, save, size)) {
result = tempConn;
tempConn = NULL;
}
@@ -161,17 +165,15 @@
}
int flib_gameconn_getport(flib_gameconn *conn) {
- if(!conn) {
- flib_log_e("null parameter in flib_gameconn_getport");
- return 0;
- } else {
+ if(!log_badparams_if(!conn)) {
return flib_ipcbase_port(conn->ipcBase);
}
+ return 0;
}
static void demo_append(flib_gameconn *conn, const void *data, size_t len) {
if(conn->demoBuffer) {
- if(flib_vector_append(conn->demoBuffer, data, len) < len) {
+ if(flib_vector_append(conn->demoBuffer, data, len)) {
flib_log_e("Error recording demo: Out of memory.");
flib_vector_destroy(conn->demoBuffer);
conn->demoBuffer = NULL;
@@ -213,11 +215,10 @@
}
}
-int flib_gameconn_send_enginemsg(flib_gameconn *conn, uint8_t *data, int len) {
+int flib_gameconn_send_enginemsg(flib_gameconn *conn, const uint8_t *data, size_t len) {
int result = -1;
- if(!conn || (!data && len>0)) {
- flib_log_e("null parameter in flib_gameconn_send_enginemsg");
- } else if(!flib_ipcbase_send_raw(conn->ipcBase, data, len)) {
+ if(!log_badparams_if(!conn || (!data && len>0))
+ && !flib_ipcbase_send_raw(conn->ipcBase, data, len)) {
demo_append(conn, data, len);
result = 0;
}
@@ -301,7 +302,7 @@
}
}
-void flib_gameconn_onEngineMessage(flib_gameconn *conn, void (*callback)(void *context, const uint8_t *em, int size), void* context) {
+void flib_gameconn_onEngineMessage(flib_gameconn *conn, void (*callback)(void *context, const uint8_t *em, size_t size), void* context) {
if(!conn) {
flib_log_e("null parameter in flib_gameconn_onEngineMessage");
} else {
--- a/project_files/frontlib/ipc/gameconn.h Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/ipc/gameconn.h Wed Jun 27 18:02:45 2012 +0200
@@ -34,7 +34,7 @@
*/
void flib_gameconn_tick(flib_gameconn *conn);
-int flib_gameconn_send_enginemsg(flib_gameconn *conn, uint8_t *data, int len);
+int flib_gameconn_send_enginemsg(flib_gameconn *conn, const uint8_t *data, size_t len);
int flib_gameconn_send_textmsg(flib_gameconn *conn, int msgtype, const char *msg);
int flib_gameconn_send_chatmsg(flib_gameconn *conn, const char *playername, const char *msg);
@@ -72,9 +72,9 @@
/**
* ...needs to be passed on to the server in a net game
- * handleEngineMessage(void *context, const uint8_t *em, int size)
+ * handleEngineMessage(void *context, const uint8_t *em, size_t size)
*/
-void flib_gameconn_onEngineMessage(flib_gameconn *conn, void (*callback)(void *context, const uint8_t *em, int size), void* context);
+void flib_gameconn_onEngineMessage(flib_gameconn *conn, void (*callback)(void *context, const uint8_t *em, size_t size), void* context);
// TODO efinish
--- a/project_files/frontlib/ipc/ipcprotocol.c Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/ipc/ipcprotocol.c Wed Jun 27 18:02:45 2012 +0200
@@ -10,9 +10,7 @@
int flib_ipc_append_message(flib_vector *vec, const char *fmt, ...) {
int result = -1;
- if(!vec || !fmt) {
- flib_log_e("null parameter in flib_ipc_appendmessage");
- } else {
+ if(!log_badparams_if(!vec || !fmt)) {
// 1 byte size prefix, 255 bytes max message length, 1 0-byte for vsnprintf
char msgbuffer[257];
@@ -22,18 +20,13 @@
int msgSize = vsnprintf(msgbuffer+1, 256, fmt, argp);
va_end(argp);
- if(msgSize > 255) {
- flib_log_e("Message too long (%u bytes) in flib_ipc_appendmessage", (unsigned)msgSize);
- } else if(msgSize<0) {
- flib_log_e("printf error in flib_ipc_appendmessage");
- } else {
+ if(!log_e_if(msgSize > 255, "Message too long (%u bytes)", (unsigned)msgSize)
+ && !log_e_if(msgSize < 0, "printf error")) {
// Add the length prefix
((uint8_t*)msgbuffer)[0] = msgSize;
// Append it to the vector
- if(flib_vector_append(vec, msgbuffer, msgSize+1) == msgSize+1) {
- result = 0;
- }
+ result = flib_vector_append(vec, msgbuffer, msgSize+1);
}
}
return result;
@@ -42,26 +35,16 @@
int flib_ipc_append_mapconf(flib_vector *vec, const flib_map *map, bool mappreview) {
int result = -1;
flib_vector *tempvector = flib_vector_create();
- if(!vec || !map) {
- flib_log_e("null parameter in flib_ipc_append_mapconf");
- } else if(tempvector) {
+ if(!log_badparams_if(!vec || !map)) {
bool error = false;
if(map->mapgen == MAPGEN_NAMED) {
- if(map->name) {
- error |= flib_ipc_append_message(tempvector, "emap %s", map->name);
- } else {
- flib_log_e("Missing map name");
- error = true;
- }
+ error |= log_e_if(!map->name, "Missing map name")
+ || flib_ipc_append_message(tempvector, "emap %s", map->name);
}
- if(map->theme && !mappreview) {
- if(map->theme) {
- error |= flib_ipc_append_message(tempvector, "etheme %s", map->theme);
- } else {
- flib_log_e("Missing map theme");
- error = true;
- }
+ if(!mappreview) {
+ error |= log_e_if(!map->theme, "Missing map theme")
+ || flib_ipc_append_message(tempvector, "etheme %s", map->theme);
}
error |= flib_ipc_append_seed(tempvector, map->seed);
error |= flib_ipc_append_message(tempvector, "e$template_filter %i", map->templateFilter);
@@ -81,16 +64,16 @@
int bytesRemaining = map->drawDataSize-offset;
int fragmentsize = bytesRemaining < 200 ? bytesRemaining : 200;
uint8_t messagesize = edrawlen + fragmentsize;
- error |= (flib_vector_append(tempvector, &messagesize, 1) != 1);
- error |= (flib_vector_append(tempvector, edraw, edrawlen) != edrawlen);
- error |= (flib_vector_append(tempvector, map->drawData+offset, fragmentsize) != fragmentsize);
+ error |= flib_vector_append(tempvector, &messagesize, 1);
+ error |= flib_vector_append(tempvector, edraw, edrawlen);
+ error |= flib_vector_append(tempvector, map->drawData+offset, fragmentsize);
}
}
- if(!error) {
+ if(!log_e_if(error, "Error generating map config")) {
// Message created, now we can copy everything.
flib_constbuffer constbuf = flib_vector_as_constbuffer(tempvector);
- if(flib_vector_append(vec, constbuf.data, constbuf.size) == constbuf.size) {
+ if(!flib_vector_append(vec, constbuf.data, constbuf.size)) {
result = 0;
}
}
@@ -100,53 +83,69 @@
}
int flib_ipc_append_seed(flib_vector *vec, const char *seed) {
- if(!vec || !seed) {
- flib_log_e("null parameter in flib_ipc_append_seed");
- return -1;
- } else {
+ if(!log_badparams_if(!vec || !seed)) {
return flib_ipc_append_message(vec, "eseed %s", seed);
}
+ return -1;
}
int flib_ipc_append_script(flib_vector *vec, const char *script) {
- if(!vec || !script) {
- flib_log_e("null parameter in flib_ipc_append_script");
- return -1;
- } else {
- return flib_ipc_append_message(vec, "escript %s", script);
+ int result = -1;
+ char *copy = flib_strdupnull(script);
+ if(!log_badparams_if(!vec) && copy) {
+ if(!strcmp("Normal", copy)) {
+ // "Normal" means no gametype script
+ result = 0;
+ } else {
+ size_t len = strlen(copy);
+ for(size_t i=0; i<len; i++) {
+ if(copy[i] == ' ') {
+ copy[i] = '_';
+ }
+ }
+
+ result = flib_ipc_append_message(vec, "escript %s%s.lua", MULTIPLAYER_SCRIPT_PATH, copy);
+ }
}
+ free(copy);
+ return result;
+}
+
+uint32_t buildModFlags(const flib_cfg *scheme) {
+ uint32_t result = 0;
+ for(int i=0; i<scheme->meta->modCount; i++) {
+ if(scheme->mods[i]) {
+ int bitmaskIndex = scheme->meta->mods[i].bitmaskIndex;
+ result |= (UINT32_C(1) << bitmaskIndex);
+ }
+ }
+ return result;
}
int flib_ipc_append_gamescheme(flib_vector *vec, const flib_cfg *scheme) {
int result = -1;
flib_vector *tempvector = flib_vector_create();
- if(!vec || !scheme) {
- flib_log_e("null parameter in flib_ipc_append_gamescheme");
- } else if(tempvector) {
+ if(!log_badparams_if(!vec || !scheme) && tempvector) {
const flib_cfg_meta *meta = scheme->meta;
bool error = false;
- uint32_t gamemods = 0;
- for(int i=0; i<meta->modCount; i++) {
- if(scheme->mods[i]) {
- gamemods |= (1<<meta->mods[i].bitmaskIndex);
- }
- }
- error |= flib_ipc_append_message(tempvector, "e$gmflags %"PRIu32, gamemods);
+ error |= flib_ipc_append_message(tempvector, "e$gmflags %"PRIu32, buildModFlags(scheme));
for(int i=0; i<meta->settingCount; i++) {
- int value = scheme->settings[i];
- if(meta->settings[i].maxMeansInfinity) {
- value = value>=meta->settings[i].max ? 9999 : value;
+ if(meta->settings[i].engineCommand) {
+ int value = scheme->settings[i];
+ if(meta->settings[i].maxMeansInfinity) {
+ value = value>=meta->settings[i].max ? 9999 : value;
+ }
+ if(meta->settings[i].times1000) {
+ value *= 1000;
+ }
+ error |= flib_ipc_append_message(tempvector, "%s %i", meta->settings[i].engineCommand, value);
}
- if(meta->settings[i].times1000) {
- value *= 1000;
- }
- error |= flib_ipc_append_message(tempvector, "%s %i", meta->settings[i].engineCommand, value);
}
if(!error) {
// Message created, now we can copy everything.
flib_constbuffer constbuf = flib_vector_as_constbuffer(tempvector);
- if(flib_vector_append(vec, constbuf.data, constbuf.size) == constbuf.size) {
+ if(!flib_vector_append(vec, constbuf.data, constbuf.size)) {
result = 0;
}
}
@@ -165,19 +164,23 @@
int flib_ipc_append_addteam(flib_vector *vec, const flib_team *team, bool perHogAmmo, bool noAmmoStore) {
int result = -1;
flib_vector *tempvector = flib_vector_create();
- if(!vec || !team) {
- flib_log_e("invalid parameter in flib_ipc_append_addteam");
- } else if(tempvector) {
+ if(!log_badparams_if(!vec || !team) && tempvector) {
bool error = false;
if(!perHogAmmo && !noAmmoStore) {
- error |= appendWeaponSet(tempvector, team->hogs[0].weaponset);
- error |= flib_ipc_append_message(tempvector, "eammstore");
+ error = error
+ || appendWeaponSet(tempvector, team->hogs[0].weaponset)
+ || flib_ipc_append_message(tempvector, "eammstore");
}
// TODO
char *hash = team->ownerName ? team->ownerName : "00000000000000000000000000000000";
- error |= flib_ipc_append_message(tempvector, "eaddteam %s %"PRIu32" %s", hash, team->color, team->name);
+ if(team->colorIndex<0 || team->colorIndex>=flib_teamcolor_defaults_len) {
+ flib_log_e("Color index out of bounds for team %s: %i", team->name, team->colorIndex);
+ error = true;
+ } else {
+ error |= flib_ipc_append_message(tempvector, "eaddteam %s %"PRIu32" %s", hash, flib_teamcolor_defaults[team->colorIndex], team->name);
+ }
if(team->remoteDriven) {
error |= flib_ipc_append_message(tempvector, "erdriven");
@@ -203,7 +206,7 @@
if(!error) {
// Message created, now we can copy everything.
flib_constbuffer constbuf = flib_vector_as_constbuffer(tempvector);
- if(flib_vector_append(vec, constbuf.data, constbuf.size) == constbuf.size) {
+ if(!flib_vector_append(vec, constbuf.data, constbuf.size)) {
result = 0;
}
}
@@ -212,22 +215,20 @@
return result;
}
-static bool getGameMod(const flib_cfg *conf, int maskbit) {
+static bool getGameMod(const flib_cfg *conf, const char *name) {
for(int i=0; i<conf->meta->modCount; i++) {
- if(conf->meta->mods[i].bitmaskIndex == maskbit) {
+ if(!strcmp(conf->meta->mods[i].name, name)) {
return conf->mods[i];
}
}
- flib_log_e("Unable to find game mod with mask bit %i", maskbit);
+ flib_log_e("Unable to find game mod %s", name);
return false;
}
int flib_ipc_append_fullconfig(flib_vector *vec, const flib_gamesetup *setup, bool netgame) {
int result = -1;
flib_vector *tempvector = flib_vector_create();
- if(!vec || !setup) {
- flib_log_e("null parameter in flib_ipc_append_fullconfig");
- } else if(tempvector) {
+ if(!log_badparams_if(!vec || !setup) && tempvector) {
bool error = false;
bool perHogAmmo = false;
bool sharedAmmo = false;
@@ -237,40 +238,37 @@
error |= flib_ipc_append_mapconf(tempvector, setup->map, false);
}
if(setup->script) {
- error |= flib_ipc_append_message(tempvector, "escript %s", setup->script);
+ error |= flib_ipc_append_script(tempvector, setup->script);
}
if(setup->gamescheme) {
error |= flib_ipc_append_gamescheme(tempvector, setup->gamescheme);
- sharedAmmo = getGameMod(setup->gamescheme, GAMEMOD_SHAREDAMMO_MASKBIT);
+ sharedAmmo = getGameMod(setup->gamescheme, "sharedammo");
// Shared ammo has priority over per-hog ammo
- perHogAmmo = !sharedAmmo && getGameMod(setup->gamescheme, GAMEMOD_PERHOGAMMO_MASKBIT);
+ perHogAmmo = !sharedAmmo && getGameMod(setup->gamescheme, "perhogammo");
}
- if(setup->teams && setup->teamCount>0) {
- uint32_t *clanColors = flib_calloc(setup->teamCount, sizeof(uint32_t));
+ if(setup->teamlist->teams && setup->teamlist->teamCount>0) {
+ int *clanColors = flib_calloc(setup->teamlist->teamCount, sizeof(int));
if(!clanColors) {
error = true;
} else {
int clanCount = 0;
- for(int i=0; i<setup->teamCount; i++) {
- flib_team *team = setup->teams[i];
- bool newClan = false;
-
+ for(int i=0; !error && i<setup->teamlist->teamCount; i++) {
+ flib_team *team = setup->teamlist->teams[i];
// Find the clan index of this team (clans are identified by color).
- // The upper 8 bits (alpha) are ignored in the engine as well.
- uint32_t color = team->color&UINT32_C(0x00ffffff);
+ bool newClan = false;
int clan = 0;
- while(clan<clanCount && clanColors[clan] != color) {
+ while(clan<clanCount && clanColors[clan] != team->colorIndex) {
clan++;
}
if(clan==clanCount) {
newClan = true;
clanCount++;
- clanColors[clan] = color;
+ clanColors[clan] = team->colorIndex;
}
// If shared ammo is active, only add an ammo store for the first team in each clan.
bool noAmmoStore = sharedAmmo&&!newClan;
- error |= flib_ipc_append_addteam(tempvector, setup->teams[i], perHogAmmo, noAmmoStore);
+ error |= flib_ipc_append_addteam(tempvector, setup->teamlist->teams[i], perHogAmmo, noAmmoStore);
}
}
free(clanColors);
@@ -280,7 +278,7 @@
if(!error) {
// Message created, now we can copy everything.
flib_constbuffer constbuf = flib_vector_as_constbuffer(tempvector);
- if(flib_vector_append(vec, constbuf.data, constbuf.size) == constbuf.size) {
+ if(!flib_vector_append(vec, constbuf.data, constbuf.size)) {
result = 0;
}
}
--- a/project_files/frontlib/ipc/mapconn.c Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/ipc/mapconn.c Wed Jun 27 18:02:45 2012 +0200
@@ -39,7 +39,7 @@
conn->onFailureCb = &noop_handleFailure;
}
-static flib_vector *createConfigBuffer(flib_map *mapdesc) {
+static flib_vector *createConfigBuffer(const flib_map *mapdesc) {
flib_vector *result = NULL;
flib_vector *tempbuffer = flib_vector_create();
if(tempbuffer) {
@@ -55,7 +55,7 @@
return result;
}
-flib_mapconn *flib_mapconn_create(flib_map *mapdesc) {
+flib_mapconn *flib_mapconn_create(const flib_map *mapdesc) {
flib_mapconn *result = NULL;
flib_mapconn *tempConn = flib_calloc(1, sizeof(flib_mapconn));
if(tempConn) {
--- a/project_files/frontlib/ipc/mapconn.h Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/ipc/mapconn.h Wed Jun 27 18:02:45 2012 +0200
@@ -17,10 +17,14 @@
* engine process. Once this connection is established, the required information
* will be sent to the engine, and the reply is read.
*
+ * The map must be a regular, maze or drawn map - for a preview of a named map,
+ * use the preview images in the map's directory, and for the hog count read the
+ * map information (flib_mapcfg_read).
+ *
* No NULL parameters allowed, returns NULL on failure.
* Use flib_mapconn_destroy to free the returned object.
*/
-flib_mapconn *flib_mapconn_create(flib_map *mapdesc);
+flib_mapconn *flib_mapconn_create(const flib_map *mapdesc);
/**
* Destroy the mapconn object. Passing NULL is allowed and does nothing.
--- a/project_files/frontlib/model/cfg.c Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/model/cfg.c Wed Jun 27 18:02:45 2012 +0200
@@ -170,7 +170,7 @@
return result;
}
-flib_cfg *flib_cfg_copy(flib_cfg *cfg) {
+flib_cfg *flib_cfg_copy(const flib_cfg *cfg) {
flib_cfg *result = NULL;
if(cfg) {
result = flib_cfg_create(cfg->meta, cfg->name);
--- a/project_files/frontlib/model/cfg.h Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/model/cfg.h Wed Jun 27 18:02:45 2012 +0200
@@ -73,7 +73,7 @@
/**
* Create a copy of the scheme. Returns NULL on error or if NULL was passed.
*/
-flib_cfg *flib_cfg_copy(flib_cfg *cfg);
+flib_cfg *flib_cfg_copy(const flib_cfg *cfg);
/**
* Increase the reference count of the object. Call this if you store a pointer to it somewhere.
--- a/project_files/frontlib/model/gamesetup.c Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/model/gamesetup.c Wed Jun 27 18:02:45 2012 +0200
@@ -1,2 +1,13 @@
#include "gamesetup.h"
+#include <stdlib.h>
+
+void flib_gamesetup_destroy(flib_gamesetup *gamesetup) {
+ if(gamesetup) {
+ free(gamesetup->script);
+ flib_cfg_release(gamesetup->gamescheme);
+ flib_map_release(gamesetup->map);
+ flib_teamlist_destroy(gamesetup->teamlist);
+ free(gamesetup);
+ }
+}
--- a/project_files/frontlib/model/gamesetup.h Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/model/gamesetup.h Wed Jun 27 18:02:45 2012 +0200
@@ -9,14 +9,15 @@
#include "cfg.h"
#include "weapon.h"
#include "map.h"
-#include "team.h"
+#include "teamlist.h"
typedef struct {
char *script;
flib_cfg *gamescheme;
flib_map *map;
- int teamCount;
- flib_team **teams;
+ flib_teamlist *teamlist;
} flib_gamesetup;
+void flib_gamesetup_destroy(flib_gamesetup *gamesetup);
+
#endif
--- a/project_files/frontlib/model/map.h Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/model/map.h Wed Jun 27 18:02:45 2012 +0200
@@ -1,12 +1,3 @@
-/**
- * Data structure for defining a map. This contains the whole recipe to
- * exactly recreate a particular map. For named maps, you also need the
- * corresponding files.
- *
- * The required fields depend on the map generator, see the comments
- * at the struct for details.
- */
-
#ifndef MODEL_MAP_H_
#define MODEL_MAP_H_
@@ -32,12 +23,20 @@
#define MAZE_SIZE_MEDIUM_ISLANDS 4
#define MAZE_SIZE_LARGE_ISLANDS 5
+/**
+ * Data structure for defining a map. This contains the whole recipe to
+ * exactly recreate a particular map. For named maps, you also need the
+ * corresponding files.
+ *
+ * The required fields depend on the map generator, see the comments
+ * at the struct for details.
+ */
typedef struct {
int _referenceCount;
int mapgen; // Always one of the MAPGEN_ constants
char *name; // The name of the map for MAPGEN_NAMED, otherwise one of "+rnd+", "+maze+" or "+drawn+".
char *seed; // Used for all maps
- char *theme; // Used for all except MAPGEN_NAMED
+ char *theme; // Used for all maps
uint8_t *drawData; // Used for MAPGEN_DRAWN
int drawDataSize; // Used for MAPGEN_DRAWN
int templateFilter; // Used for MAPGEN_REGULAR
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/frontlib/model/mapcfg.c Wed Jun 27 18:02:45 2012 +0200
@@ -0,0 +1,44 @@
+#include "mapcfg.h"
+
+#include "../util/util.h"
+#include "../util/logging.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+void removeNewline(char *str) {
+ for(;*str;str++) {
+ if(*str=='\n' || *str=='\r') {
+ *str = 0;
+ return;
+ }
+ }
+}
+
+int flib_mapcfg_read(const char *dataDirPath, const char *mapname, flib_mapcfg *out) {
+ int result = -1;
+ if(!log_badparams_if(!dataDirPath || !mapname || !out)
+ && !log_e_if(flib_contains_dir_separator(mapname), "Illegal character in mapname %s", mapname)) {
+ char *path = flib_asprintf("%sMaps/%s/map.cfg", dataDirPath, mapname);
+ if(path) {
+ FILE *file = fopen(path, "rb");
+ if(!log_e_if(!file, "Unable to open map config file %s", path)) {
+ if(!log_e_if(!fgets(out->theme, sizeof(out->theme), file), "Error reading theme from %s", path)) {
+ removeNewline(out->theme);
+ char buf[64];
+ if(!log_e_if(!fgets(buf, sizeof(buf), file), "Error reading hoglimit from %s", path)) {
+ removeNewline(buf);
+ errno = 0;
+ out->hogLimit = strtol(buf, NULL, 10);
+ result = !log_e_if(errno, "Invalid hoglimit in %s: %i", path, buf);
+ }
+ }
+ fclose(file);
+ }
+ }
+ free(path);
+ }
+ return result;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/frontlib/model/mapcfg.h Wed Jun 27 18:02:45 2012 +0200
@@ -0,0 +1,19 @@
+/*
+ * Data structure and functions for accessing the map.cfg of named maps.
+ */
+
+#ifndef MAPCFG_H_
+#define MAPCFG_H_
+
+typedef struct {
+ char theme[256];
+ int hogLimit;
+} flib_mapcfg;
+
+/**
+ * Read the map configuration for the map with this name.
+ * The dataDirPath must end in a path separator.
+ */
+int flib_mapcfg_read(const char *dataDirPath, const char *mapname, flib_mapcfg *out);
+
+#endif /* MAPCFG_H_ */
--- a/project_files/frontlib/model/roomlist.c Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/model/roomlist.c Wed Jun 27 18:02:45 2012 +0200
@@ -11,7 +11,7 @@
return flib_calloc(1, sizeof(flib_roomlist));
}
-static void flib_roomlist_room_destroy(flib_roomlist_room *room) {
+static void flib_roomlist_room_destroy(flib_room *room) {
if(room) {
free(room->map);
free(room->name);
@@ -27,13 +27,14 @@
for(int i=0; i<list->roomCount; i++) {
flib_roomlist_room_destroy(list->rooms[i]);
}
+ free(list->rooms);
free(list);
}
}
-static flib_roomlist_room *fillRoomFromParams(char **params) {
- flib_roomlist_room *result = NULL;
- flib_roomlist_room *tmpRoom = flib_calloc(1, sizeof(flib_roomlist_room));
+static flib_room *fillRoomFromParams(char **params) {
+ flib_room *result = NULL;
+ flib_room *tmpRoom = flib_calloc(1, sizeof(flib_room));
if(tmpRoom) {
tmpRoom->inProgress = !strcmp(params[0], "True");
tmpRoom->name = flib_strdupnull(params[1]);
@@ -52,16 +53,26 @@
return result;
}
+GENERATE_STATIC_LIST_INSERT(insertRoom, flib_room*)
+GENERATE_STATIC_LIST_DELETE(deleteRoom, flib_room*)
+
+static int findRoom(const flib_roomlist *list, const char *name) {
+ for(int i=0; i<list->roomCount; i++) {
+ if(!strcmp(name, list->rooms[i]->name)) {
+ return i;
+ }
+ }
+ return -1;
+}
+
int flib_roomlist_add(flib_roomlist *list, char **params) {
int result = -1;
if(!list || !params) {
flib_log_e("null parameter in flib_roomlist_add");
} else {
- flib_roomlist_room *tmpRoom = fillRoomFromParams(params);
+ flib_room *tmpRoom = fillRoomFromParams(params);
if(tmpRoom) {
- flib_roomlist_room **rooms = flib_list_insert(list->rooms, &list->roomCount, sizeof(*list->rooms), &tmpRoom, 0);
- if(rooms) {
- list->rooms = rooms;
+ if(!insertRoom(&list->rooms, &list->roomCount, tmpRoom, 0)) {
tmpRoom = NULL;
result = 0;
}
@@ -71,13 +82,23 @@
return result;
}
-static int findRoom(flib_roomlist *list, const char *name) {
- for(int i=0; i<list->roomCount; i++) {
- if(!strcmp(name, list->rooms[i]->name)) {
- return i;
+int flib_roomlist_delete(flib_roomlist *list, const char *name) {
+ int result = -1;
+ if(!list || !name) {
+ flib_log_e("null parameter in flib_roomlist_delete");
+ } else {
+ int roomid = findRoom(list, name);
+ if(roomid<0) {
+ flib_log_w("Attempt to delete unknown room %s", name);
+ } else {
+ flib_room *room = list->rooms[roomid];
+ if(!deleteRoom(&list->rooms, &list->roomCount, roomid)) {
+ flib_roomlist_room_destroy(room);
+ result = 0;
+ }
}
}
- return -1;
+ return result;
}
int flib_roomlist_update(flib_roomlist *list, const char *name, char **params) {
@@ -85,7 +106,7 @@
if(!list || !name || !params) {
flib_log_e("null parameter in flib_roomlist_update");
} else {
- flib_roomlist_room *tmpRoom = fillRoomFromParams(params);
+ flib_room *tmpRoom = fillRoomFromParams(params);
int roomid = findRoom(list, name);
if(tmpRoom && roomid>=0) {
flib_roomlist_room_destroy(list->rooms[roomid]);
@@ -98,8 +119,8 @@
return result;
}
-flib_roomlist_room *flib_roomlist_find(flib_roomlist *list, const char *name) {
- flib_roomlist_room *result = NULL;
+flib_room *flib_roomlist_find(const flib_roomlist *list, const char *name) {
+ flib_room *result = NULL;
if(!list || !name) {
flib_log_e("null parameter in flib_roomlist_find");
} else {
@@ -123,24 +144,3 @@
list->roomCount = 0;
}
}
-
-int flib_roomlist_delete(flib_roomlist *list, const char *name) {
- int result = -1;
- if(!list || !name) {
- flib_log_e("null parameter in flib_roomlist_delete");
- } else {
- int roomid = findRoom(list, name);
- if(roomid<0) {
- flib_log_w("Attempt to delete unknown room %s", name);
- } else {
- flib_roomlist_room *room = list->rooms[roomid];
- flib_roomlist_room **rooms = flib_list_delete(list->rooms, &list->roomCount, sizeof(*list->rooms), roomid);
- if(rooms || list->roomCount==0) {
- list->rooms = rooms;
- flib_roomlist_room_destroy(room);
- result = 0;
- }
- }
- }
- return result;
-}
--- a/project_files/frontlib/model/roomlist.h Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/model/roomlist.h Wed Jun 27 18:02:45 2012 +0200
@@ -16,11 +16,11 @@
char *map; // This is either a map name, or one of +rnd+, +maze+ or +drawn+.
char *scheme;
char *weapons;
-} flib_roomlist_room;
+} flib_room;
typedef struct {
int roomCount;
- flib_roomlist_room **rooms;
+ flib_room **rooms;
} flib_roomlist;
flib_roomlist *flib_roomlist_create();
@@ -45,7 +45,7 @@
/**
* Returns the room with the name [name] from the list if it exists, NULL otherwise
*/
-flib_roomlist_room *flib_roomlist_find(flib_roomlist *list, const char *name);
+flib_room *flib_roomlist_find(const flib_roomlist *list, const char *name);
/**
* Removes all rooms from the list
--- a/project_files/frontlib/model/schemelist.c Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/model/schemelist.c Wed Jun 27 18:02:45 2012 +0200
@@ -16,6 +16,7 @@
for(int i=0; i<list->schemeCount; i++) {
flib_cfg_release(list->schemes[i]);
}
+ free(list->schemes);
free(list);
}
}
@@ -192,29 +193,28 @@
return NULL;
}
+GENERATE_STATIC_LIST_INSERT(insertScheme, flib_cfg*)
+GENERATE_STATIC_LIST_DELETE(deleteScheme, flib_cfg*)
+
int flib_schemelist_insert(flib_schemelist *list, flib_cfg *cfg, int pos) {
- flib_cfg **changedList = flib_list_insert(list->schemes, &list->schemeCount, sizeof(*list->schemes), &cfg, pos);
- if(changedList) {
- list->schemes = changedList;
+ if(!list) {
+ flib_log_e("Invalid parameter in flib_schemelist_insert");
+ } else if(!insertScheme(&list->schemes, &list->schemeCount, cfg, pos)) {
flib_cfg_retain(cfg);
return 0;
- } else {
- return -1;
}
+ return -1;
}
int flib_schemelist_delete(flib_schemelist *list, int pos) {
- int result = -1;
- if(!list || pos<0 || pos>=list->schemeCount) {
+ if(!list) {
flib_log_e("Invalid parameter in flib_schemelist_delete");
} else {
flib_cfg *elem = list->schemes[pos];
- flib_cfg **changedList = flib_list_delete(list->schemes, &list->schemeCount, sizeof(*list->schemes), pos);
- if(changedList || list->schemeCount==0) {
- list->schemes = changedList;
+ if(!deleteScheme(&list->schemes, &list->schemeCount, pos)) {
flib_cfg_release(elem);
- result = 0;
+ return 0;
}
}
- return result;
+ return -1;
}
--- a/project_files/frontlib/model/team.c Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/model/team.c Wed Jun 27 18:02:45 2012 +0200
@@ -231,6 +231,14 @@
}
}
+void flib_team_set_health(flib_team *team, int health) {
+ if(team) {
+ for(int i=0; i<HEDGEHOGS_PER_TEAM; i++) {
+ team->hogs[i].initialHealth = health;
+ }
+ }
+}
+
char *strdupWithError(const char *in, bool *error) {
char *out = flib_strdupnull(in);
if(in && !out) {
@@ -239,7 +247,7 @@
return out;
}
-flib_team *flib_team_copy(flib_team *team) {
+flib_team *flib_team_copy(const flib_team *team) {
flib_team *result = NULL;
if(team) {
flib_team *tmpTeam = flib_team_retain(flib_calloc(1, sizeof(flib_team)));
@@ -282,7 +290,7 @@
tmpTeam->wins = team->wins;
tmpTeam->campaignProgress = team->campaignProgress;
- tmpTeam->color = team->color;
+ tmpTeam->colorIndex = team->colorIndex;
tmpTeam->hogsInGame = team->hogsInGame;
tmpTeam->remoteDriven = team->remoteDriven;
--- a/project_files/frontlib/model/team.h Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/model/team.h Wed Jun 27 18:02:45 2012 +0200
@@ -62,7 +62,7 @@
int campaignProgress;
// Transient settings used in game setup
- uint32_t color;
+ int colorIndex; // Index into a color table
int hogsInGame;
bool remoteDriven;
char *ownerName;
@@ -98,6 +98,11 @@
void flib_team_set_weaponset(flib_team *team, flib_weaponset *set);
/**
+ * Set the same initial health for every hog.
+ */
+void flib_team_set_health(flib_team *team, int health);
+
+/**
* Increase the reference count of the object. Call this if you store a pointer to it somewhere.
* Returns the parameter.
*/
@@ -113,6 +118,6 @@
* The referenced weaponsets are not copied, so the new
* team references the same weaponsets.
*/
-flib_team *flib_team_copy(flib_team *team);
+flib_team *flib_team_copy(const flib_team *team);
#endif /* TEAM_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/frontlib/model/teamlist.c Wed Jun 27 18:02:45 2012 +0200
@@ -0,0 +1,87 @@
+#include "teamlist.h"
+
+#include "../util/util.h"
+#include "../util/list.h"
+#include "../util/logging.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+flib_teamlist *flib_teamlist_create() {
+ return flib_calloc(1, sizeof(flib_teamlist));
+}
+
+void flib_teamlist_destroy(flib_teamlist *list) {
+ if(list) {
+ for(int i=0; i<list->teamCount; i++) {
+ flib_team_release(list->teams[i]);
+ }
+ free(list->teams);
+ free(list);
+ }
+}
+
+GENERATE_STATIC_LIST_INSERT(insertTeam, flib_team*)
+GENERATE_STATIC_LIST_DELETE(deleteTeam, flib_team*)
+
+static int findTeam(const flib_teamlist *list, const char *name) {
+ for(int i=0; i<list->teamCount; i++) {
+ if(!strcmp(name, list->teams[i]->name)) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+int flib_teamlist_insert(flib_teamlist *list, flib_team *team, int pos) {
+ if(!list || !team) {
+ flib_log_e("null parameter in flib_teamlist_insert");
+ } else if(!insertTeam(&list->teams, &list->teamCount, team, pos)) {
+ flib_team_retain(team);
+ return 0;
+ }
+ return -1;
+}
+
+int flib_teamlist_delete(flib_teamlist *list, const char *name) {
+ int result = -1;
+ if(!list || !name) {
+ flib_log_e("null parameter in flib_teamlist_delete");
+ } else {
+ int itemid = findTeam(list, name);
+ if(itemid>=0) {
+ flib_team *team = list->teams[itemid];
+ if(!deleteTeam(&list->teams, &list->teamCount, itemid)) {
+ flib_team_release(team);
+ result = 0;
+ }
+ }
+ }
+ return result;
+}
+
+flib_team *flib_teamlist_find(const flib_teamlist *list, const char *name) {
+ flib_team *result = NULL;
+ if(!list || !name) {
+ flib_log_e("null parameter in flib_teamlist_find");
+ } else {
+ int itemid = findTeam(list, name);
+ if(itemid>=0) {
+ result = list->teams[itemid];
+ }
+ }
+ return result;
+}
+
+void flib_teamlist_clear(flib_teamlist *list) {
+ if(!list) {
+ flib_log_e("null parameter in flib_teamlist_clear");
+ } else {
+ for(int i=0; i<list->teamCount; i++) {
+ flib_team_release(list->teams[i]);
+ }
+ free(list->teams);
+ list->teams = NULL;
+ list->teamCount = 0;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/frontlib/model/teamlist.h Wed Jun 27 18:02:45 2012 +0200
@@ -0,0 +1,36 @@
+#ifndef TEAMLIST_H_
+#define TEAMLIST_H_
+
+#include "team.h"
+
+typedef struct {
+ int teamCount;
+ flib_team **teams;
+} flib_teamlist;
+
+flib_teamlist *flib_teamlist_create();
+
+void flib_teamlist_destroy(flib_teamlist *list);
+
+/**
+ * Insert a team into the list. Returns 0 on success.
+ */
+int flib_teamlist_insert(flib_teamlist *list, flib_team *team, int pos);
+
+/**
+ * Delete the item with the name [name] from the list.
+ * Returns 0 on success.
+ */
+int flib_teamlist_delete(flib_teamlist *list, const char *name);
+
+/**
+ * Returns the team with the name [name] from the list if it exists, NULL otherwise
+ */
+flib_team *flib_teamlist_find(const flib_teamlist *list, const char *name);
+
+/**
+ * Removes all items from the list and frees "teams".
+ */
+void flib_teamlist_clear(flib_teamlist *list);
+
+#endif
--- a/project_files/frontlib/model/weapon.c Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/model/weapon.c Wed Jun 27 18:02:45 2012 +0200
@@ -72,11 +72,28 @@
}
}
+flib_weaponset *flib_weaponset_copy(const flib_weaponset *weaponset) {
+ if(!weaponset) {
+ return NULL;
+ }
+
+ flib_weaponset *result = flib_weaponset_create(weaponset->name);
+ if(result) {
+ memcpy(result->loadout, weaponset->loadout, WEAPONS_COUNT+1);
+ memcpy(result->crateprob, weaponset->crateprob, WEAPONS_COUNT+1);
+ memcpy(result->delay, weaponset->delay, WEAPONS_COUNT+1);
+ memcpy(result->crateammo, weaponset->crateammo, WEAPONS_COUNT+1);
+ }
+
+ return result;
+}
+
static void flib_weaponsetlist_destroy(flib_weaponsetlist *list) {
if(list) {
for(int i=0; i<list->weaponsetCount; i++) {
flib_weaponset_release(list->weaponsets[i]);
}
+ free(list->weaponsets);
free(list);
}
}
@@ -196,31 +213,30 @@
return flib_weaponsetlist_retain(flib_calloc(1, sizeof(flib_weaponsetlist)));
}
+GENERATE_STATIC_LIST_INSERT(insertWeaponset, flib_weaponset*)
+GENERATE_STATIC_LIST_DELETE(deleteWeaponset, flib_weaponset*)
+
int flib_weaponsetlist_insert(flib_weaponsetlist *list, flib_weaponset *set, int pos) {
- flib_weaponset **changedList = flib_list_insert(list->weaponsets, &list->weaponsetCount, sizeof(*list->weaponsets), &set, pos);
- if(changedList) {
- list->weaponsets = changedList;
+ if(!list) {
+ flib_log_e("Invalid parameter in flib_weaponsetlist_insert");
+ } else if(!insertWeaponset(&list->weaponsets, &list->weaponsetCount, set, pos)) {
flib_weaponset_retain(set);
return 0;
- } else {
- return -1;
}
+ return -1;
}
int flib_weaponsetlist_delete(flib_weaponsetlist *list, int pos) {
- int result = -1;
- if(!list || pos<0 || pos>=list->weaponsetCount) {
+ if(!list) {
flib_log_e("Invalid parameter in flib_weaponsetlist_delete");
} else {
flib_weaponset *elem = list->weaponsets[pos];
- flib_weaponset **changedList = flib_list_delete(list->weaponsets, &list->weaponsetCount, sizeof(*list->weaponsets), pos);
- if(changedList || list->weaponsetCount==0) {
- list->weaponsets = changedList;
+ if(!deleteWeaponset(&list->weaponsets, &list->weaponsetCount, pos)) {
flib_weaponset_release(elem);
- result = 0;
+ return 0;
}
}
- return result;
+ return -1;
}
flib_weaponsetlist *flib_weaponsetlist_retain(flib_weaponsetlist *list) {
--- a/project_files/frontlib/model/weapon.h Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/model/weapon.h Wed Jun 27 18:02:45 2012 +0200
@@ -44,6 +44,8 @@
*/
void flib_weaponset_release(flib_weaponset *weaponset);
+flib_weaponset *flib_weaponset_copy(const flib_weaponset *weaponset);
+
/**
* Create a weaponset from an ammostring. This format is used both in the ini files
* and in the net protocol.
--- a/project_files/frontlib/net/netbase.c Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/net/netbase.c Wed Jun 27 18:02:45 2012 +0200
@@ -105,8 +105,7 @@
return 0;
} else {
int size = flib_socket_nbrecv(net->sock, buffer, sizeof(buffer));
- if(size>=0) {
- flib_vector_append(net->readBuffer, buffer, size);
+ if(size>=0 && !flib_vector_append(net->readBuffer, buffer, size)) {
return size;
} else {
flib_socket_close(net->sock);
--- a/project_files/frontlib/net/netconn.c Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/net/netconn.c Wed Jun 27 18:02:45 2012 +0200
@@ -27,31 +27,44 @@
#include "../model/roomlist.h"
#include "../md5/md5.h"
#include "../base64/base64.h"
+#include "../model/mapcfg.h"
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
-flib_netconn *flib_netconn_create(const char *playerName, flib_cfg_meta *metacfg, const char *host, uint16_t port) {
+flib_netconn *flib_netconn_create(const char *playerName, flib_cfg_meta *metacfg, const char *dataDirPath, const char *host, uint16_t port) {
flib_netconn *result = NULL;
if(!playerName || !metacfg || !host) {
flib_log_e("null parameter in flib_netconn_create");
} else {
flib_netconn *newConn = flib_calloc(1, sizeof(flib_netconn));
if(newConn) {
+ newConn->netBase = flib_netbase_create(host, port);
+ newConn->playerName = flib_strdupnull(playerName);
+ newConn->dataDirPath = flib_strdupnull(dataDirPath);
+
newConn->netconnState = NETCONN_STATE_CONNECTING;
newConn->isAdmin = false;
+ newConn->metaCfg = flib_cfg_meta_retain(metacfg);
+ newConn->roomList.roomCount = 0;
+ newConn->roomList.rooms = NULL;
+
newConn->isChief = false;
- newConn->metaCfg = flib_cfg_meta_retain(metacfg);
- newConn->roomList = flib_roomlist_create();
newConn->map = flib_map_create_named("", "NoSuchMap");
+ newConn->pendingTeamlist.teamCount = 0;
+ newConn->pendingTeamlist.teams = NULL;
+ newConn->teamlist.teamCount = 0;
+ newConn->teamlist.teams = NULL;
+ newConn->scheme = NULL;
+ newConn->script = NULL;
+ newConn->weaponset = NULL;
+
newConn->running = false;
newConn->destroyRequested = false;
- clearCallbacks(newConn);
- newConn->netBase = flib_netbase_create(host, port);
- newConn->playerName = flib_strdupnull(playerName);
- if(newConn->netBase && newConn->playerName && newConn->roomList) {
+ netconn_clearCallbacks(newConn);
+ if(newConn->netBase && newConn->playerName && newConn->dataDirPath && newConn->map) {
result = newConn;
newConn = NULL;
}
@@ -69,14 +82,23 @@
* and we delay the actual destruction. We ensure no further callbacks will be
* sent to prevent surprises.
*/
- clearCallbacks(conn);
+ netconn_clearCallbacks(conn);
conn->destroyRequested = true;
} else {
flib_netbase_destroy(conn->netBase);
+ free(conn->playerName);
+ free(conn->dataDirPath);
+
flib_cfg_meta_release(conn->metaCfg);
- flib_roomlist_destroy(conn->roomList);
+ flib_roomlist_clear(&conn->roomList);
+
flib_map_release(conn->map);
- free(conn->playerName);
+ flib_teamlist_clear(&conn->pendingTeamlist);
+ flib_teamlist_clear(&conn->teamlist);
+ flib_cfg_release(conn->scheme);
+ free(conn->script);
+ flib_weaponset_release(conn->weaponset);
+
free(conn);
}
}
@@ -87,7 +109,7 @@
if(!conn) {
flib_log_e("null parameter in flib_netconn_get_roomlist");
} else {
- result = conn->roomList;
+ result = &conn->roomList;
}
return result;
}
@@ -102,16 +124,92 @@
return result;
}
-void leaveRoom(flib_netconn *conn) {
+void netconn_leaveRoom(flib_netconn *conn) {
conn->netconnState = NETCONN_STATE_LOBBY;
conn->isChief = false;
- flib_map *map = flib_map_create_named("", "NoSuchMap");
- if(map) {
+ flib_map_release(conn->map);
+ conn->map = flib_map_create_named("", "NoSuchMap");
+ flib_teamlist_clear(&conn->pendingTeamlist);
+ flib_teamlist_clear(&conn->teamlist);
+ flib_cfg_release(conn->scheme);
+ conn->scheme = NULL;
+ free(conn->script);
+ conn->script = NULL;
+ flib_weaponset_release(conn->weaponset);
+ conn->weaponset = NULL;
+}
+
+bool flib_netconn_is_in_room_context(flib_netconn *conn) {
+ return conn && (conn->netconnState == NETCONN_STATE_ROOM || conn->netconnState == NETCONN_STATE_INGAME);
+}
+
+void netconn_setMap(flib_netconn *conn, const flib_map *map) {
+ flib_map *copy = flib_map_copy(map);
+ if(copy) {
flib_map_release(conn->map);
- conn->map = map;
+ conn->map = copy;
+ }
+}
+
+void netconn_setWeaponset(flib_netconn *conn, const flib_weaponset *weaponset) {
+ flib_weaponset *copy = flib_weaponset_copy(weaponset);
+ if(copy) {
+ flib_weaponset_release(conn->weaponset);
+ conn->weaponset = copy;
+ }
+}
+
+void netconn_setScript(flib_netconn *conn, const char *script) {
+ char *copy = flib_strdupnull(script);
+ if(copy) {
+ free(conn->script);
+ conn->script = copy;
+ }
+}
+
+void netconn_setScheme(flib_netconn *conn, const flib_cfg *scheme) {
+ flib_cfg *copy = flib_cfg_copy(scheme);
+ if(copy) {
+ flib_cfg_release(conn->scheme);
+ conn->scheme = copy;
+ }
+}
+
+flib_gamesetup *flib_netconn_create_gameSetup(flib_netconn *conn) {
+ flib_gamesetup *result = NULL;
+ if(!conn) {
+ flib_log_e("null parameter in flib_netconn_create_gameSetup");
} else {
- flib_log_e("Error resetting netconn.map");
+ if(conn->teamlist.teamCount==0 || !conn->scheme || !conn->weaponset) {
+ flib_log_e("Incomplete room state to create game setup.");
+ } else {
+ result = flib_calloc(1, sizeof(flib_gamesetup));
+ if(result) {
+ result->gamescheme = flib_cfg_copy(conn->scheme);
+ result->map = flib_map_copy(conn->map);
+ result->script = flib_strdupnull(conn->script);
+ result->teamlist = flib_teamlist_create();
+ for(int i=0; i<conn->teamlist.teamCount; i++) {
+ flib_team *copy = flib_team_copy(conn->teamlist.teams[i]);
+ if(copy) {
+ flib_team_set_weaponset(copy, conn->weaponset);
+ flib_team_set_health(copy, conn->scheme->settings[2]); // TODO by name
+ flib_teamlist_insert(result->teamlist, copy, result->teamlist->teamCount);
+ }
+ flib_team_release(copy);
+ }
+ if(result->map->mapgen == MAPGEN_NAMED && result->map->name) {
+ flib_mapcfg mapcfg;
+ if(!flib_mapcfg_read(conn->dataDirPath, result->map->name, &mapcfg)) {
+ free(result->map->theme);
+ result->map->theme = flib_strdupnull(mapcfg.theme);
+ }
+ }
+ // TODO handle errors
+ }
+ }
}
+ return result;
}
static void flib_netconn_wrappedtick(flib_netconn *conn) {
@@ -184,9 +282,9 @@
if(netmsg->partCount % 8 != 1) {
flib_log_w("Net: Malformed ROOMS message");
} else {
- flib_roomlist_clear(conn->roomList);
+ flib_roomlist_clear(&conn->roomList);
for(int i=1; i<netmsg->partCount; i+=8) {
- if(flib_roomlist_add(conn->roomList, netmsg->parts+i)) {
+ if(flib_roomlist_add(&conn->roomList, netmsg->parts+i)) {
flib_log_e("Error adding room to list in ROOMS message");
}
}
@@ -233,7 +331,7 @@
switch(flags[i]) {
case 'r':
for(int j = 2; j < netmsg->partCount; ++j) {
- conn->onReadyStateCb(conn->onReadyStateCtx, netmsg->parts[i], setFlag);
+ conn->onReadyStateCb(conn->onReadyStateCtx, netmsg->parts[j], setFlag);
}
break;
default:
@@ -243,31 +341,36 @@
}
}
} else if (!strcmp(cmd, "ADD_TEAM")) {
- if(netmsg->partCount != 24) {
+ if(netmsg->partCount != 24 || !flib_netconn_is_in_room_context(conn)) {
flib_log_w("Net: Bad ADD_TEAM message");
} else {
flib_team *team = flib_team_from_netmsg(netmsg->parts+1);
- if(!team) {
+ flib_team *teamcopy = flib_team_from_netmsg(netmsg->parts+1);
+ if(!team || !teamcopy) {
conn->netconnState = NETCONN_STATE_DISCONNECTED;
conn->onDisconnectedCb(conn->onDisconnectedCtx, NETCONN_DISCONNECT_INTERNAL_ERROR, "Internal error");
exit = true;
} else {
team->remoteDriven = true;
+ teamcopy->remoteDriven = true;
+ flib_teamlist_insert(&conn->teamlist, teamcopy, conn->teamlist.teamCount);
conn->onTeamAddCb(conn->onTeamAddCtx, team);
}
flib_team_release(team);
+ flib_team_release(teamcopy);
}
} else if (!strcmp(cmd, "REMOVE_TEAM")) {
- if(netmsg->partCount != 2) {
+ if(netmsg->partCount != 2 || !flib_netconn_is_in_room_context(conn)) {
flib_log_w("Net: Bad REMOVETEAM message");
} else {
+ flib_teamlist_delete(&conn->teamlist, netmsg->parts[1]);
conn->onTeamDeleteCb(conn->onTeamDeleteCtx, netmsg->parts[1]);
}
} else if(!strcmp(cmd, "ROOMABANDONED")) {
- leaveRoom(conn);
+ netconn_leaveRoom(conn);
conn->onLeaveRoomCb(conn->onLeaveRoomCtx, NETCONN_ROOMLEAVE_ABANDONED, "Room destroyed");
} else if(!strcmp(cmd, "KICKED")) {
- leaveRoom(conn);
+ netconn_leaveRoom(conn);
conn->onLeaveRoomCb(conn->onLeaveRoomCtx, NETCONN_ROOMLEAVE_KICKED, "You got kicked");
} else if(!strcmp(cmd, "JOINED")) {
if(netmsg->partCount < 2) {
@@ -312,19 +415,19 @@
} else if(!strcmp(cmd, "ROOM") && netmsg->partCount >= 2) {
const char *subcmd = netmsg->parts[1];
if(!strcmp(subcmd, "ADD") && netmsg->partCount == 10) {
- if(flib_roomlist_add(conn->roomList, netmsg->parts+2)) {
+ if(flib_roomlist_add(&conn->roomList, netmsg->parts+2)) {
flib_log_e("Error adding new room to list");
} else {
- conn->onRoomAddCb(conn->onRoomAddCtx, conn->roomList->rooms[0]);
+ conn->onRoomAddCb(conn->onRoomAddCtx, conn->roomList.rooms[0]);
}
} else if(!strcmp(subcmd, "UPD") && netmsg->partCount == 11) {
- if(flib_roomlist_update(conn->roomList, netmsg->parts[2], netmsg->parts+3)) {
+ if(flib_roomlist_update(&conn->roomList, netmsg->parts[2], netmsg->parts+3)) {
flib_log_e("Error updating room in list");
} else {
- conn->onRoomUpdateCb(conn->onRoomUpdateCtx, netmsg->parts[2], flib_roomlist_find(conn->roomList, netmsg->parts[2]));
+ conn->onRoomUpdateCb(conn->onRoomUpdateCtx, netmsg->parts[2], flib_roomlist_find(&conn->roomList, netmsg->parts[2]));
}
} else if(!strcmp(subcmd, "DEL") && netmsg->partCount == 3) {
- if(flib_roomlist_delete(conn->roomList, netmsg->parts[2])) {
+ if(flib_roomlist_delete(&conn->roomList, netmsg->parts[2])) {
flib_log_e("Error deleting room from list");
} else {
conn->onRoomDeleteCb(conn->onRoomDeleteCtx, netmsg->parts[2]);
@@ -340,6 +443,7 @@
}
} else if (!strcmp(cmd, "RUN_GAME")) {
conn->netconnState = NETCONN_STATE_INGAME;
+ // TODO send along the config
conn->onRunGameCb(conn->onRunGameCtx);
} else if (!strcmp(cmd, "ASKPASSWORD")) {
conn->onPasswordRequestCb(conn->onPasswordRequestCtx, conn->playerName);
@@ -358,19 +462,27 @@
}
}
} else if (!strcmp(cmd, "TEAM_ACCEPTED")) {
- if (netmsg->partCount != 2) {
+ if (netmsg->partCount != 2 || !flib_netconn_is_in_room_context(conn)) {
flib_log_w("Net: Bad TEAM_ACCEPTED message");
} else {
+ flib_team *team = flib_teamlist_find(&conn->pendingTeamlist, netmsg->parts[1]);
+ if(team) {
+ flib_teamlist_insert(&conn->teamlist, team, conn->teamlist.teamCount);
+ flib_teamlist_delete(&conn->pendingTeamlist, netmsg->parts[1]);
+ } else {
+ flib_log_e("Team accepted that was not requested: %s", netmsg->parts[1]);
+ }
conn->onTeamAcceptedCb(conn->onTeamAcceptedCtx, netmsg->parts[1]);
}
} else if (!strcmp(cmd, "CFG")) {
- if(netmsg->partCount < 3) {
+ if(netmsg->partCount < 3 || !flib_netconn_is_in_room_context(conn)) {
flib_log_w("Net: Bad CFG message");
} else {
const char *subcmd = netmsg->parts[1];
if(!strcmp(subcmd, "SCHEME") && netmsg->partCount == conn->metaCfg->modCount + conn->metaCfg->settingCount + 3) {
flib_cfg *cfg = flib_netmsg_to_cfg(conn->metaCfg, netmsg->parts+2);
if(cfg) {
+ netconn_setScheme(conn, cfg);
conn->onCfgSchemeCb(conn->onCfgSchemeCtx, cfg);
} else {
flib_log_e("Error processing CFG SCHEME message");
@@ -379,12 +491,12 @@
} else if(!strcmp(subcmd, "FULLMAPCONFIG") && netmsg->partCount == 7) {
flib_map *map = flib_netmsg_to_map(netmsg->parts+2);
if(map) {
- flib_map_release(conn->map);
- conn->map = map;
+ netconn_setMap(conn, map);
conn->onMapChangedCb(conn->onMapChangedCtx, conn->map, NETCONN_MAPCHANGE_FULL);
} else {
flib_log_e("Error processing CFG FULLMAPCONFIG message");
}
+ flib_map_release(map);
} else if(!strcmp(subcmd, "MAP") && netmsg->partCount == 3) {
char *mapname = flib_strdupnull(netmsg->parts[2]);
if(mapname) {
@@ -423,8 +535,8 @@
conn->onMapChangedCb(conn->onMapChangedCtx, conn->map, NETCONN_MAPCHANGE_MAZE_SIZE);
} else if(!strcmp(subcmd, "DRAWNMAP") && netmsg->partCount == 3) {
size_t drawnMapSize = 0;
- uint8_t *drawnMapData = flib_netmsg_to_drawnmapdata(&drawnMapSize, netmsg->parts[2]);
- if(drawnMapData) {
+ uint8_t *drawnMapData = NULL;
+ if(!flib_netmsg_to_drawnmapdata(netmsg->parts[2], &drawnMapData, &drawnMapSize)) {
free(conn->map->drawData);
conn->map->drawData = drawnMapData;
conn->map->drawDataSize = drawnMapSize;
@@ -433,10 +545,12 @@
flib_log_e("Error processing CFG DRAWNMAP message");
}
} else if(!strcmp(subcmd, "SCRIPT") && netmsg->partCount == 3) {
+ netconn_setScript(conn, netmsg->parts[2]);
conn->onScriptChangedCb(conn->onScriptChangedCtx, netmsg->parts[2]);
} else if(!strcmp(subcmd, "AMMO") && netmsg->partCount == 4) {
flib_weaponset *weapons = flib_weaponset_from_ammostring(netmsg->parts[2], netmsg->parts[3]);
if(weapons) {
+ netconn_setWeaponset(conn, weapons);
conn->onWeaponsetChangedCb(conn->onWeaponsetChangedCtx, weapons);
} else {
flib_log_e("Error processing CFG AMMO message");
@@ -447,23 +561,35 @@
}
}
} else if (!strcmp(cmd, "HH_NUM")) {
- if (netmsg->partCount != 3) {
+ if (netmsg->partCount != 3 || !flib_netconn_is_in_room_context(conn)) {
flib_log_w("Net: Bad HH_NUM message");
} else {
int hogs = atoi(netmsg->parts[2]);
if(hogs<=0 || hogs>HEDGEHOGS_PER_TEAM) {
flib_log_w("Net: Bad HH_NUM message: %s hogs", netmsg->parts[2]);
} else {
+ flib_team *team = flib_teamlist_find(&conn->teamlist, netmsg->parts[1]);
+ if(team) {
+ team->hogsInGame = hogs;
+ } else {
+ flib_log_e("HH_NUM message for unknown team %s", netmsg->parts[1]);
+ }
conn->onHogCountChangedCb(conn->onHogCountChangedCtx, netmsg->parts[1], hogs);
}
}
} else if (!strcmp(cmd, "TEAM_COLOR")) {
- if (netmsg->partCount != 3) {
+ if (netmsg->partCount != 3 || !flib_netconn_is_in_room_context(conn)) {
flib_log_w("Net: Bad TEAM_COLOR message");
} else {
long color;
- if(sscanf(netmsg->parts[2], "#%lx", &color)) {
- conn->onTeamColorChangedCb(conn->onTeamColorChangedCtx, netmsg->parts[1], (uint32_t)color);
+ if(sscanf(netmsg->parts[2], "%lu", &color) && color>=0 && color<flib_teamcolor_defaults_len) {
+ flib_team *team = flib_teamlist_find(&conn->teamlist, netmsg->parts[1]);
+ if(team) {
+ team->colorIndex = color;
+ } else {
+ flib_log_e("TEAM_COLOR message for unknown team %s", netmsg->parts[1]);
+ }
+ conn->onTeamColorChangedCb(conn->onTeamColorChangedCtx, netmsg->parts[1], color);
} else {
flib_log_w("Net: Bad TEAM_COLOR message: Color %s", netmsg->parts[2]);
}
@@ -477,7 +603,7 @@
size_t outlen;
bool ok = base64_decode_alloc(netmsg->parts[i], strlen(netmsg->parts[i]), &out, &outlen);
if(ok && outlen) {
- conn->onEngineMessageCb(conn->onEngineMessageCtx, out, outlen);
+ conn->onEngineMessageCb(conn->onEngineMessageCtx, (uint8_t*)out, outlen);
} else {
flib_log_e("Net: Malformed engine message: %s", netmsg->parts[i]);
}
--- a/project_files/frontlib/net/netconn.h Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/net/netconn.h Wed Jun 27 18:02:45 2012 +0200
@@ -40,7 +40,11 @@
// TODO: Order of functions, and match the order in netconn.c
typedef struct _flib_netconn flib_netconn;
-flib_netconn *flib_netconn_create(const char *playerName, flib_cfg_meta *metacfg, const char *host, uint16_t port);
+/**
+ * Create a new netplay connection with these parameters.
+ * The path to the data directory must end with a path delimiter (e.g. C:\Games\Hedgewars\Data\)
+ */
+flib_netconn *flib_netconn_create(const char *playerName, flib_cfg_meta *metacfg, const char *dataDirPath, const char *host, uint16_t port);
void flib_netconn_destroy(flib_netconn *conn);
/**
@@ -62,6 +66,20 @@
bool flib_netconn_is_chief(flib_netconn *conn);
/**
+ * Are you in the context of a room, i.e. either in room or ingame state?
+ */
+bool flib_netconn_is_in_room_context(flib_netconn *conn);
+
+/**
+ * Generate a game setup from the current room state.
+ * Returns NULL if the room state does not contain enough information
+ * for a complete game setup, or if an error occurs.
+ *
+ * The new gamesetup must be destroyed TODO function for that...
+ */
+flib_gamesetup *flib_netconn_create_gameSetup(flib_netconn *conn);
+
+/**
* quitmsg may be null
*/
int flib_netconn_send_quit(flib_netconn *conn, const char *quitmsg);
@@ -146,7 +164,7 @@
* Set the teamcolor of a team. Only makes sense in room state and if you are chief.
* The server does not send a reply.
*/
-int flib_netconn_send_teamColor(flib_netconn *conn, const char *teamname, uint32_t colorRGB);
+int flib_netconn_send_teamColor(flib_netconn *conn, const char *teamname, int colorIndex);
/**
* Set the weaponset for the room. Only makes sense in room state and if you are chief.
@@ -318,9 +336,9 @@
* flib_netconn_get_roomlist() as soon as the onConnected callback is fired. These callbacks
* provide notification about changes.
*/
-void flib_netconn_onRoomAdd(flib_netconn *conn, void (*callback)(void *context, const flib_roomlist_room *room), void* context);
+void flib_netconn_onRoomAdd(flib_netconn *conn, void (*callback)(void *context, const flib_room *room), void* context);
void flib_netconn_onRoomDelete(flib_netconn *conn, void (*callback)(void *context, const char *name), void* context);
-void flib_netconn_onRoomUpdate(flib_netconn *conn, void (*callback)(void *context, const char *oldName, const flib_roomlist_room *room), void* context);
+void flib_netconn_onRoomUpdate(flib_netconn *conn, void (*callback)(void *context, const char *oldName, const flib_room *room), void* context);
/**
* Callbacks for players joining or leaving the lobby. If join is true it's a join, otherwise a leave.
@@ -417,9 +435,9 @@
* The color of a team has been changed by the room chief. If you are the chief and change the color yourself,
* you will not receive this callback!
*/
-void flib_netconn_onTeamColorChanged(flib_netconn *conn, void (*callback)(void *context, const char *teamName, uint32_t colorARGB), void *context);
+void flib_netconn_onTeamColorChanged(flib_netconn *conn, void (*callback)(void *context, const char *teamName, int colorIndex), void *context);
-void flib_netconn_onEngineMessage(flib_netconn *conn, void (*callback)(void *context, const char *message, int size), void *context);
+void flib_netconn_onEngineMessage(flib_netconn *conn, void (*callback)(void *context, const uint8_t *message, size_t size), void *context);
void flib_netconn_onCfgScheme(flib_netconn *conn, void (*callback)(void *context, flib_cfg *scheme), void *context);
--- a/project_files/frontlib/net/netconn_callbacks.c Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/net/netconn_callbacks.c Wed Jun 27 18:02:45 2012 +0200
@@ -41,7 +41,7 @@
flib_netconn_send_quit((flib_netconn*)context, "Authentication failed");
}
-void clearCallbacks(flib_netconn *conn) {
+void netconn_clearCallbacks(flib_netconn *conn) {
flib_netconn_onMessage(conn, NULL, NULL);
flib_netconn_onConnected(conn, NULL, NULL);
flib_netconn_onDisconnected(conn, NULL, NULL);
@@ -102,9 +102,9 @@
GENERATE_CB_SETTER(onMessage, (void *context, int msgtype, const char *msg), defaultCallback_onMessage);
GENERATE_CB_SETTER_AND_DEFAULT(onConnected, (void *context));
GENERATE_CB_SETTER_AND_DEFAULT(onDisconnected, (void *context, int reason, const char *message));
-GENERATE_CB_SETTER_AND_DEFAULT(onRoomAdd, (void *context, const flib_roomlist_room *room));
+GENERATE_CB_SETTER_AND_DEFAULT(onRoomAdd, (void *context, const flib_room *room));
GENERATE_CB_SETTER_AND_DEFAULT(onRoomDelete, (void *context, const char *name));
-GENERATE_CB_SETTER_AND_DEFAULT(onRoomUpdate, (void *context, const char *oldName, const flib_roomlist_room *room));
+GENERATE_CB_SETTER_AND_DEFAULT(onRoomUpdate, (void *context, const char *oldName, const flib_room *room));
GENERATE_CB_SETTER(onChat, (void *context, const char *nick, const char *msg), defaultCallback_onChat);
GENERATE_CB_SETTER_AND_DEFAULT(onLobbyJoin, (void *context, const char *nick));
GENERATE_CB_SETTER_AND_DEFAULT(onLobbyLeave, (void *context, const char *nick, const char *partMsg));
@@ -121,8 +121,8 @@
GENERATE_CB_SETTER_AND_DEFAULT(onRunGame, (void *context));
GENERATE_CB_SETTER_AND_DEFAULT(onTeamAccepted, (void *context, const char *teamName));
GENERATE_CB_SETTER_AND_DEFAULT(onHogCountChanged, (void *context, const char *teamName, int hogs));
-GENERATE_CB_SETTER_AND_DEFAULT(onTeamColorChanged, (void *context, const char *teamName, uint32_t colorRGB));
-GENERATE_CB_SETTER_AND_DEFAULT(onEngineMessage, (void *context, const char *message, int size));
+GENERATE_CB_SETTER_AND_DEFAULT(onTeamColorChanged, (void *context, const char *teamName, int colorIndex));
+GENERATE_CB_SETTER_AND_DEFAULT(onEngineMessage, (void *context, const uint8_t *message, size_t size));
GENERATE_CB_SETTER_AND_DEFAULT(onCfgScheme, (void *context, flib_cfg *scheme));
GENERATE_CB_SETTER_AND_DEFAULT(onMapChanged, (void *context, const flib_map *map, int changetype));
GENERATE_CB_SETTER_AND_DEFAULT(onScriptChanged, (void *context, const char *script));
--- a/project_files/frontlib/net/netconn_internal.h Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/net/netconn_internal.h Wed Jun 27 18:02:45 2012 +0200
@@ -20,14 +20,21 @@
struct _flib_netconn {
flib_netbase *netBase;
char *playerName;
+ char *dataDirPath;
+
+ int netconnState; // One of the NETCONN_STATE constants
+ bool isAdmin; // Player is server administrator
+
flib_cfg_meta *metaCfg;
- flib_roomlist *roomList;
+ flib_roomlist roomList;
- int netconnState; // One of the NETCONN_STATE constants
-
- bool isAdmin; // Player is server administrator
- bool isChief; // Player can modify the current room
- flib_map *map; // Map settings in the current room.
+ bool isChief; // Player can modify the current room
+ flib_map *map;
+ flib_teamlist pendingTeamlist;
+ flib_teamlist teamlist;
+ flib_cfg *scheme;
+ char *script;
+ flib_weaponset *weaponset;
void (*onMessageCb)(void *context, int msgtype, const char *msg);
void *onMessageCtx;
@@ -38,13 +45,13 @@
void (*onDisconnectedCb)(void *context, int reason, const char *message);
void *onDisconnectedCtx;
- void (*onRoomAddCb)(void *context, const flib_roomlist_room *room);
+ void (*onRoomAddCb)(void *context, const flib_room *room);
void *onRoomAddCtx;
void (*onRoomDeleteCb)(void *context, const char *name);
void *onRoomDeleteCtx;
- void (*onRoomUpdateCb)(void *context, const char *oldName, const flib_roomlist_room *room);
+ void (*onRoomUpdateCb)(void *context, const char *oldName, const flib_room *room);
void *onRoomUpdateCtx;
void (*onChatCb)(void *context, const char *nick, const char *msg);
@@ -95,10 +102,10 @@
void (*onHogCountChangedCb)(void *context, const char *teamName, int hogs);
void *onHogCountChangedCtx;
- void (*onTeamColorChangedCb)(void *context, const char *teamName, uint32_t colorRGB);
+ void (*onTeamColorChangedCb)(void *context, const char *teamName, int colorIndex);
void *onTeamColorChangedCtx;
- void (*onEngineMessageCb)(void *context, const char *message, int size);
+ void (*onEngineMessageCb)(void *context, const uint8_t *message, size_t size);
void *onEngineMessageCtx;
void (*onCfgSchemeCb)(void *context, flib_cfg *scheme);
@@ -123,6 +130,11 @@
bool destroyRequested;
};
-void clearCallbacks(flib_netconn *conn);
+void netconn_clearCallbacks(flib_netconn *conn);
+void netconn_leaveRoom(flib_netconn *conn);
+void netconn_setMap(flib_netconn *conn, const flib_map *map);
+void netconn_setWeaponset(flib_netconn *conn, const flib_weaponset *weaponset);
+void netconn_setScript(flib_netconn *conn, const char *script);
+void netconn_setScheme(flib_netconn *conn, const flib_cfg *scheme);
#endif
--- a/project_files/frontlib/net/netconn_send.c Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/net/netconn_send.c Wed Jun 27 18:02:45 2012 +0200
@@ -10,50 +10,50 @@
#include <string.h>
#include <zlib.h>
-// TODO state changes
-
// cmdname is always given as literal from functions in this file, so it is never null.
static int sendVoid(flib_netconn *conn, const char *cmdname) {
- if(!conn) {
- flib_log_e("null parameter trying to send %s command.", cmdname);
+ if(log_e_if(!conn, "Invalid parameter sending %s command", cmdname)) {
return -1;
}
return flib_netbase_sendf(conn->netBase, "%s\n\n", cmdname);
}
+// Testing for !*str prevents sending 0-length parameters (they trip up the protocol)
static int sendStr(flib_netconn *conn, const char *cmdname, const char *str) {
- if(!conn || !str) {
- flib_log_e("null parameter trying to send %s command.", cmdname);
+ if(log_e_if(!conn || !str || !*str, "Invalid parameter sending %s command", cmdname)) {
return -1;
}
return flib_netbase_sendf(conn->netBase, "%s\n%s\n\n", cmdname, str);
}
static int sendInt(flib_netconn *conn, const char *cmdname, int param) {
- if(!conn) {
- flib_log_e("null parameter trying to send %s command.", cmdname);
+ if(log_e_if(!conn, "Invalid parameter sending %s command", cmdname)) {
return -1;
}
return flib_netbase_sendf(conn->netBase, "%s\n%i\n\n", cmdname, param);
}
int flib_netconn_send_quit(flib_netconn *conn, const char *quitmsg) {
- return sendStr(conn, "QUIT", quitmsg ? quitmsg : "User quit");
+ return sendStr(conn, "QUIT", (quitmsg && *quitmsg) ? quitmsg : "User quit");
}
int flib_netconn_send_chat(flib_netconn *conn, const char *chat) {
- return sendStr(conn, "CHAT", chat);
+ if(chat && *chat) {
+ return sendStr(conn, "CHAT", chat);
+ }
+ return 0;
}
int flib_netconn_send_teamchat(flib_netconn *conn, const char *chat) {
- return sendStr(conn, "TEAMCHAT", chat);
+ if(chat && *chat) {
+ return sendStr(conn, "TEAMCHAT", chat);
+ }
+ return 0;
}
int flib_netconn_send_nick(flib_netconn *conn, const char *nick) {
int result = -1;
- if(!conn || !nick) {
- flib_log_e("null parameter in flib_netconn_send_nick");
- } else {
+ if(!log_badparams_if(!conn || !nick || !*nick)) {
char *tmpName = flib_strdupnull(nick);
if(tmpName) {
if(!flib_netbase_sendf(conn->netBase, "%s\n%s\n\n", "NICK", nick)) {
@@ -70,9 +70,7 @@
int flib_netconn_send_password(flib_netconn *conn, const char *latin1Passwd) {
int result = -1;
- if(!conn || !latin1Passwd) {
- flib_log_e("null parameter in flib_netconn_send_password");
- } else {
+ if(!log_badparams_if(!conn || !latin1Passwd)) {
md5_state_t md5state;
uint8_t md5bytes[16];
char md5hex[33];
@@ -89,11 +87,19 @@
}
int flib_netconn_send_joinRoom(flib_netconn *conn, const char *room) {
- return sendStr(conn, "JOIN_ROOM", room);
+ if(!sendStr(conn, "JOIN_ROOM", room)) {
+ conn->isChief = false;
+ return 0;
+ }
+ return -1;
}
int flib_netconn_send_createRoom(flib_netconn *conn, const char *room) {
- return sendStr(conn, "CREATE_ROOM", room);
+ if(!sendStr(conn, "CREATE_ROOM", room)) {
+ conn->isChief = true;
+ return 0;
+ }
+ return -1;
}
int flib_netconn_send_renameRoom(flib_netconn *conn, const char *roomName) {
@@ -101,35 +107,50 @@
}
int flib_netconn_send_leaveRoom(flib_netconn *conn) {
- return sendVoid(conn, "PART");
+ if(flib_netconn_is_in_room_context(conn) && !sendVoid(conn, "PART")) {
+ netconn_leaveRoom(conn);
+ return 0;
+ }
+ return -1;
}
int flib_netconn_send_toggleReady(flib_netconn *conn) {
return sendVoid(conn, "TOGGLE_READY");
}
+static void addTeamToPendingList(flib_netconn *conn, const flib_team *team) {
+ flib_team *teamcopy = flib_team_copy(team);
+ if(teamcopy) {
+ teamcopy->remoteDriven = false;
+ free(teamcopy->ownerName);
+ teamcopy->ownerName = flib_strdupnull(conn->playerName);
+ if(teamcopy->ownerName) {
+ flib_teamlist_delete(&conn->pendingTeamlist, team->name);
+ flib_teamlist_insert(&conn->pendingTeamlist, teamcopy, 0);
+ }
+ }
+ flib_team_release(teamcopy);
+}
+
int flib_netconn_send_addTeam(flib_netconn *conn, const flib_team *team) {
int result = -1;
- if(!conn || !team) {
- flib_log_e("null parameter in flib_netconn_send_addTeam");
- } else {
- bool missingInfo = !team->name || !team->color || !team->grave || !team->fort || !team->voicepack || !team->flag;
+ if(!log_badparams_if(!conn || !team)) {
+ bool missingInfo = !team->name || !team->grave || !team->fort || !team->voicepack || !team->flag;
for(int i=0; i<HEDGEHOGS_PER_TEAM; i++) {
missingInfo |= !team->hogs[i].name || !team->hogs[i].hat;
}
- if(missingInfo) {
- flib_log_e("Incomplete team definition for flib_netconn_send_addTeam");
- } else {
+ if(!log_e_if(missingInfo, "Incomplete team definition")) {
flib_vector *vec = flib_vector_create();
if(vec) {
bool error = false;
- error |= flib_vector_appendf(vec, "ADD_TEAM\n%s\n%lu\n%s\n%s\n%s\n%s\n%i\n", team->name, (unsigned long)team->color, team->grave, team->fort, team->voicepack, team->flag, team->hogs[0].difficulty);
+ error |= flib_vector_appendf(vec, "ADD_TEAM\n%s\n%i\n%s\n%s\n%s\n%s\n%i\n", team->name, team->colorIndex, team->grave, team->fort, team->voicepack, team->flag, team->hogs[0].difficulty);
for(int i=0; i<HEDGEHOGS_PER_TEAM; i++) {
error |= flib_vector_appendf(vec, "%s\n%s\n", team->hogs[i].name, team->hogs[i].hat);
}
error |= flib_vector_appendf(vec, "\n");
- if(!error) {
- result = flib_netbase_send_raw(conn->netBase, flib_vector_data(vec), flib_vector_size(vec));
+ if(!error && !flib_netbase_send_raw(conn->netBase, flib_vector_data(vec), flib_vector_size(vec))) {
+ addTeamToPendingList(conn, team);
+ result = 0;
}
}
flib_vector_destroy(vec);
@@ -139,14 +160,19 @@
}
int flib_netconn_send_removeTeam(flib_netconn *conn, const char *teamname) {
- return sendStr(conn, "REMOVE_TEAM", teamname);
+ if(!sendStr(conn, "REMOVE_TEAM", teamname)) {
+ flib_team *team = flib_teamlist_find(&conn->teamlist, teamname);
+ if(team && !team->remoteDriven) {
+ flib_teamlist_delete(&conn->teamlist, teamname);
+ }
+ return 0;
+ }
+ return -1;
}
int flib_netconn_send_engineMessage(flib_netconn *conn, const uint8_t *message, size_t size) {
int result = -1;
- if(!conn || (!message && size>0)) {
- flib_log_e("null parameter in flib_netconn_send_engineMessage");
- } else {
+ if(!log_badparams_if(!conn || (!message && size>0))) {
char *base64encout = NULL;
base64_encode_alloc((const char*)message, size, &base64encout);
if(base64encout) {
@@ -158,38 +184,52 @@
}
int flib_netconn_send_teamHogCount(flib_netconn *conn, const char *teamname, int hogcount) {
- if(!conn || !teamname || hogcount<1 || hogcount>HEDGEHOGS_PER_TEAM) {
- flib_log_e("invalid parameter in flib_netconn_send_teamHogCount");
- return -1;
+ if(!log_badparams_if(!conn || !teamname || hogcount<1 || hogcount>HEDGEHOGS_PER_TEAM)
+ && !flib_netbase_sendf(conn->netBase, "HH_NUM\n%s\n%i\n\n", teamname, hogcount)) {
+ if(conn->isChief) {
+ flib_team *team = flib_teamlist_find(&conn->teamlist, teamname);
+ if(team) {
+ team->hogsInGame = hogcount;
+ }
+ }
+ return 0;
}
- return flib_netbase_sendf(conn->netBase, "HH_NUM\n%s\n%i\n\n", teamname, hogcount);
+ return -1;
}
-int flib_netconn_send_teamColor(flib_netconn *conn, const char *teamname, uint32_t colorRGB) {
- if(!conn || !teamname) {
- flib_log_e("null parameter in flib_netconn_send_teamColor");
- return -1;
+int flib_netconn_send_teamColor(flib_netconn *conn, const char *teamname, int colorIndex) {
+ if(!log_badparams_if(!conn || !teamname)
+ && !flib_netbase_sendf(conn->netBase, "TEAM_COLOR\n%s\n%i\n\n", teamname, colorIndex)) {
+ if(conn->isChief) {
+ flib_team *team = flib_teamlist_find(&conn->teamlist, teamname);
+ if(team) {
+ team->colorIndex = colorIndex;
+ }
+ }
+ return 0;
}
- return flib_netbase_sendf(conn->netBase, "TEAM_COLOR\n%s\n%lu\n\n", teamname, (unsigned long)colorRGB);
+ return -1;
}
int flib_netconn_send_weaponset(flib_netconn *conn, const flib_weaponset *weaponset) {
- if(!conn || !weaponset) {
- flib_log_e("null parameter in flib_netconn_send_weaponset");
- return -1;
+ if(!log_badparams_if(!conn || !weaponset)) {
+ char ammostring[WEAPONS_COUNT*4+1];
+ strcpy(ammostring, weaponset->loadout);
+ strcat(ammostring, weaponset->crateprob);
+ strcat(ammostring, weaponset->delay);
+ strcat(ammostring, weaponset->crateammo);
+ if(!flib_netbase_sendf(conn->netBase, "CFG\nAMMO\n%s\n%s\n\n", weaponset->name, ammostring)) {
+ if(conn->isChief) {
+ netconn_setWeaponset(conn, weaponset);
+ }
+ return 0;
+ }
}
-
- char ammostring[WEAPONS_COUNT*4+1];
- strcpy(ammostring, weaponset->loadout);
- strcat(ammostring, weaponset->crateprob);
- strcat(ammostring, weaponset->delay);
- strcat(ammostring, weaponset->crateammo);
- return flib_netbase_sendf(conn->netBase, "CFG\nAMMO\n%s\n%s\n\n", weaponset->name, ammostring);
+ return -1;
}
int flib_netconn_send_map(flib_netconn *conn, const flib_map *map) {
- if(!conn || !map) {
- flib_log_e("null parameter in flib_netconn_send_map");
+ if(log_badparams_if(!conn || !map)) {
return -1;
}
bool error = false;
@@ -213,34 +253,80 @@
}
int flib_netconn_send_mapName(flib_netconn *conn, const char *mapName) {
- return sendStr(conn, "CFG\nMAP", mapName);
+ if(!sendStr(conn, "CFG\nMAP", mapName)) {
+ if(conn->isChief) {
+ char *copy = flib_strdupnull(mapName);
+ if(copy) {
+ free(conn->map->name);
+ conn->map->name = copy;
+ }
+ }
+ return 0;
+ }
+ return -1;
}
int flib_netconn_send_mapGen(flib_netconn *conn, int mapGen) {
- return sendInt(conn, "CFG\nMAPGEN", mapGen);
+ if(!sendInt(conn, "CFG\nMAPGEN", mapGen)) {
+ if(conn->isChief) {
+ conn->map->mapgen = mapGen;
+ }
+ return 0;
+ }
+ return -1;
}
int flib_netconn_send_mapTemplate(flib_netconn *conn, int templateFilter) {
- return sendInt(conn, "CFG\nTEMPLATE", templateFilter);
+ if(!sendInt(conn, "CFG\nTEMPLATE", templateFilter)) {
+ if(conn->isChief) {
+ conn->map->templateFilter = templateFilter;
+ }
+ return 0;
+ }
+ return -1;
}
int flib_netconn_send_mapMazeSize(flib_netconn *conn, int mazeSize) {
- return sendInt(conn, "CFG\nMAZE_SIZE", mazeSize);
+ if(!sendInt(conn, "CFG\nMAZE_SIZE", mazeSize)) {
+ if(conn->isChief) {
+ conn->map->mazeSize = mazeSize;
+ }
+ return 0;
+ }
+ return -1;
}
int flib_netconn_send_mapSeed(flib_netconn *conn, const char *seed) {
- return sendStr(conn, "CFG\nSEED", seed);
+ if(!sendStr(conn, "CFG\nSEED", seed)) {
+ if(conn->isChief) {
+ char *copy = flib_strdupnull(seed);
+ if(copy) {
+ free(conn->map->seed);
+ conn->map->seed = copy;
+ }
+ }
+ return 0;
+ }
+ return -1;
}
int flib_netconn_send_mapTheme(flib_netconn *conn, const char *theme) {
- return sendStr(conn, "CFG\nTHEME", theme);
+ if(!sendStr(conn, "CFG\nTHEME", theme)) {
+ if(conn->isChief) {
+ char *copy = flib_strdupnull(theme);
+ if(copy) {
+ free(conn->map->theme);
+ conn->map->theme = copy;
+ }
+ }
+ return 0;
+ }
+ return -1;
}
int flib_netconn_send_mapDrawdata(flib_netconn *conn, const uint8_t *drawData, size_t size) {
int result = -1;
- if(!conn || (!drawData && size>0) || size>SIZE_MAX/2) {
- flib_log_e("invalid parameter in flib_netconn_send_map");
- } else {
+ if(!log_badparams_if(!conn || (!drawData && size>0) || size>SIZE_MAX/2)) {
uLongf zippedSize = compressBound(size);
uint8_t *zipped = flib_malloc(zippedSize+4); // 4 extra bytes for header
if(zipped) {
@@ -265,18 +351,31 @@
}
free(zipped);
}
+
+ if(!result && conn->isChief) {
+ uint8_t *copy = flib_bufdupnull(drawData, size);
+ if(copy) {
+ free(conn->map->drawData);
+ conn->map->drawData = copy;
+ conn->map->drawDataSize = size;
+ }
+ }
return result;
}
int flib_netconn_send_script(flib_netconn *conn, const char *scriptName) {
- return sendStr(conn, "CFG\nSCRIPT", scriptName);
+ if(!sendStr(conn, "CFG\nSCRIPT", scriptName)) {
+ if(conn->isChief) {
+ netconn_setScript(conn, scriptName);
+ }
+ return 0;
+ }
+ return -1;
}
int flib_netconn_send_scheme(flib_netconn *conn, const flib_cfg *scheme) {
int result = -1;
- if(!conn || !scheme) {
- flib_log_e("null parameter in flib_netconn_send_scheme");
- } else {
+ if(!log_badparams_if(!conn || !scheme)) {
flib_vector *vec = flib_vector_create();
if(vec) {
bool error = false;
@@ -294,11 +393,21 @@
}
flib_vector_destroy(vec);
}
+
+ if(!result && conn->isChief) {
+ netconn_setScheme(conn, scheme);
+ }
return result;
}
int flib_netconn_send_roundfinished(flib_netconn *conn, bool withoutError) {
- return sendInt(conn, "ROUNDFINISHED", withoutError ? 1 : 0);
+ if(!sendInt(conn, "ROUNDFINISHED", withoutError ? 1 : 0)) {
+ if(conn->netconnState == NETCONN_STATE_INGAME) {
+ conn->netconnState = NETCONN_STATE_ROOM;
+ }
+ return 0;
+ }
+ return -1;
}
int flib_netconn_send_ban(flib_netconn *conn, const char *playerName) {
@@ -334,8 +443,7 @@
}
int flib_netconn_send_setServerVar(flib_netconn *conn, const char *name, const char *value) {
- if(!conn || !name || !value) {
- flib_log_e("null parameter trying to send SET_SERVER_VAR command.");
+ if(log_badparams_if(!conn || !name || !value)) {
return -1;
}
return flib_netbase_sendf(conn->netBase, "%s\n%s\n%s\n\n", "SET_SERVER_VAR", name, value);
--- a/project_files/frontlib/net/netprotocol.c Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/net/netprotocol.c Wed Jun 27 18:02:45 2012 +0200
@@ -80,8 +80,8 @@
}
// TODO: Test with empty map
-uint8_t *flib_netmsg_to_drawnmapdata(size_t *outlen, char *netmsg) {
- uint8_t *result = NULL;
+int flib_netmsg_to_drawnmapdata(char *netmsg, uint8_t** outbuf, size_t *outlen) {
+ int result = -1;
// First step: base64 decoding
char *base64decout = NULL;
@@ -90,24 +90,32 @@
if(ok && base64declen>3) {
// Second step: unzip with the QCompress header. That header is just a big-endian
// uint32 indicating the length of the uncompressed data.
+ uint8_t *ubyteBuf = (uint8_t*)base64decout;
uint32_t unzipLen =
- (((uint32_t)base64decout[0])<<24)
- + (((uint32_t)base64decout[1])<<16)
- + (((uint32_t)base64decout[2])<<8)
- + base64decout[3];
- uint8_t *out = flib_malloc(unzipLen);
- if(out) {
- uLongf actualUnzipLen = unzipLen;
- int resultcode = uncompress(out, &actualUnzipLen, (Bytef*)(base64decout+4), base64declen-4);
- if(resultcode == Z_OK) {
- result = out;
- *outlen = actualUnzipLen;
- out = NULL;
- } else {
- flib_log_e("Uncompressing drawn map failed. Code: %i", resultcode);
+ (((uint32_t)ubyteBuf[0])<<24)
+ + (((uint32_t)ubyteBuf[1])<<16)
+ + (((uint32_t)ubyteBuf[2])<<8)
+ + ubyteBuf[3];
+ if(unzipLen==0) {
+ *outbuf = NULL;
+ *outlen = 0;
+ result = 0;
+ } else {
+ uint8_t *out = flib_malloc(unzipLen);
+ if(out) {
+ uLongf actualUnzipLen = unzipLen;
+ int resultcode = uncompress(out, &actualUnzipLen, (Bytef*)(base64decout+4), base64declen-4);
+ if(resultcode == Z_OK) {
+ *outbuf = out;
+ *outlen = actualUnzipLen;
+ out = NULL;
+ result = 0;
+ } else {
+ flib_log_e("Uncompressing drawn map failed. Code: %i", resultcode);
+ }
}
+ free(out);
}
- free(out);
} else {
flib_log_e("base64 decoding of drawn map failed.");
}
--- a/project_files/frontlib/net/netprotocol.h Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/net/netprotocol.h Wed Jun 27 18:02:45 2012 +0200
@@ -31,6 +31,6 @@
* is written to the variable pointed to by outlen.
* Returns NULL on error.
*/
-uint8_t *flib_netmsg_to_drawnmapdata(size_t *outlen, char *netmsg);
+int flib_netmsg_to_drawnmapdata(char *netmsg, uint8_t **outbuf, size_t *outlen);
#endif /* NETPROTOCOL_H_ */
--- a/project_files/frontlib/test.c Mon Jun 25 15:21:18 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,337 +0,0 @@
-#include "frontlib.h"
-#include "util/logging.h"
-#include "util/buffer.h"
-#include "util/util.h"
-#include "util/list.h"
-#include "model/map.h"
-#include "model/weapon.h"
-#include "model/schemelist.h"
-#include "ipc/mapconn.h"
-#include "ipc/gameconn.h"
-#include "net/netconn.h"
-
-#include <stdlib.h>
-#include <stdbool.h>
-#include <assert.h>
-#include <string.h>
-
-// Callback function that will be called when the map is rendered
-static void handleMapSuccess(void *context, const uint8_t *bitmap, int numHedgehogs) {
- printf("Drawing map for %i brave little hogs...", numHedgehogs);
-
- // Draw the map as ASCII art
- for(int y=0; y<MAPIMAGE_HEIGHT; y++) {
- for(int x=0; x<MAPIMAGE_WIDTH; x++) {
- int pixelnum = x + y*MAPIMAGE_WIDTH;
- bool pixel = bitmap[pixelnum>>3] & (1<<(7-(pixelnum&7)));
- printf(pixel ? "#" : " ");
- }
- printf("\n");
- }
-
- // Destroy the connection object (this will end the "tick" loop below)
- flib_mapconn **connptr = context;
- flib_mapconn_destroy(*connptr);
- *connptr = NULL;
-}
-
-static void onDisconnect(void *context, int reason) {
- flib_log_i("Connection closed. Reason: %i", reason);
- flib_gameconn **connptr = context;
- flib_gameconn_destroy(*connptr);
- *connptr = NULL;
-}
-
-static void onGameRecorded(void *context, const uint8_t *record, int size, bool isSavegame) {
- flib_log_i("Writing %s (%i bytes)...", isSavegame ? "savegame" : "demo", size);
- FILE *file = fopen(isSavegame ? "testsave.42.hws" : "testdemo.42.hwd", "wb");
- fwrite(record, 1, size, file);
- fclose(file);
-}
-
-// Callback function that will be called on error
-static void handleMapFailure(void *context, const char *errormessage) {
- flib_log_e("Map rendering failed: %s", errormessage);
-
- // Destroy the connection object (this will end the "tick" loop below)
- flib_mapconn **connptr = context;
- flib_mapconn_destroy(*connptr);
- *connptr = NULL;
-}
-
-static void startEngineMap(int port) {
- char commandbuffer[255];
- const char *enginePath = "C:\\Programmieren\\Hedgewars\\bin";
- const char *configPath = "C:\\Programmieren\\Hedgewars\\share\\hedgewars";
- snprintf(commandbuffer, 255, "start %s\\hwengine.exe %s %i landpreview", enginePath, configPath, port);
- system(commandbuffer);
-}
-
-static void startEngineGame(int port) {
- char commandbuffer[255];
- const char *enginePath = "C:\\Programmieren\\Hedgewars\\bin";
- const char *configPath = "C:\\Programmieren\\Hedgewars\\share\\hedgewars";
- const char *dataPath = "C:\\Programmieren\\Hedgewars\\share\\hedgewars\\Data";
- 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);
- flib_log_d("Starting engine with CMD: %s", commandbuffer);
- system(commandbuffer);
-}
-
-void testMapPreview() {
- // Create a map description and check that there was no error
- flib_map *map = flib_map_create_maze("This is the seed value", "Jungle", MAZE_SIZE_SMALL_TUNNELS);
- assert(map);
-
- // Create a new connection to the engine and check that there was no error
- flib_mapconn *mapConnection = flib_mapconn_create(map);
- assert(mapConnection);
-
- // We don't need the map description anymore
- flib_map_release(map);
- map = NULL;
-
- // Register the callback functions
- flib_mapconn_onFailure(mapConnection, &handleMapFailure, &mapConnection);
- flib_mapconn_onSuccess(mapConnection, &handleMapSuccess, &mapConnection);
-
- // Start the engine process and tell it which port the frontlib is listening on
- startEngineMap(flib_mapconn_getport(mapConnection));
-
- // Usually, flib_mapconn_tick will be called in an event loop that runs several
- // times per second. It handles I/O operations and progress, and calls
- // callbacks when something interesting happens.
- while(mapConnection) {
- flib_mapconn_tick(mapConnection);
- }
-}
-
-void testGame() {
- flib_cfg_meta *metaconf = flib_cfg_meta_from_ini("metasettings.ini");
- assert(metaconf);
- flib_weaponset *weapons = flib_weaponset_create("Defaultweaps");
- flib_schemelist *schemelist = flib_schemelist_from_ini(metaconf, "schemes.ini");
-
- flib_gamesetup setup;
- setup.gamescheme = flib_schemelist_find(schemelist, "Default");
- setup.map = flib_map_create_maze("asparagus", "Jungle", MAZE_SIZE_MEDIUM_TUNNELS);
- setup.script = NULL;
- setup.teamCount = 2;
- setup.teams = calloc(2, sizeof(flib_team*));
- setup.teams[0] = calloc(1, sizeof(flib_team));
- setup.teams[0]->color = 0xffff0000;
- setup.teams[0]->flag = "australia";
- setup.teams[0]->fort = "Plane";
- setup.teams[0]->grave = "Bone";
- setup.teams[0]->hogsInGame = 2;
- setup.teams[0]->name = "Team Awesome";
- setup.teams[0]->voicepack = "British";
- setup.teams[0]->hogs[0].difficulty = 2;
- setup.teams[0]->hogs[0].hat = "NoHat";
- setup.teams[0]->hogs[0].initialHealth = 100;
- setup.teams[0]->hogs[0].name = "Harry 120";
- setup.teams[0]->hogs[1].difficulty = 2;
- setup.teams[0]->hogs[1].hat = "chef";
- setup.teams[0]->hogs[1].initialHealth = 100;
- setup.teams[0]->hogs[1].name = "Chefkoch";
- setup.teams[1] = flib_team_from_ini("Cave Dwellers.hwt");
- setup.teams[1]->color = 0xFF0000F0;
- setup.teams[1]->hogsInGame = 8;
- flib_team_set_weaponset(setup.teams[0], weapons);
- flib_team_set_weaponset(setup.teams[1], weapons);
- flib_weaponset_release(weapons);
-
- flib_gameconn *gameconn = flib_gameconn_create("Medo42", &setup, false);
- assert(gameconn);
-
- flib_gameconn_onDisconnect(gameconn, &onDisconnect, &gameconn);
- //flib_gameconn_onGameRecorded(gameconn, &onGameRecorded, &gameconn);
-
- startEngineGame(flib_gameconn_getport(gameconn));
-
- while(gameconn) {
- flib_gameconn_tick(gameconn);
- }
-}
-
-void testDemo() {
- FILE *demofile = fopen("testdemo.42.hwd", "rb");
- assert(demofile);
- flib_vector *vec = flib_vector_create();
- uint8_t demobuf[512];
- int len;
- while((len=fread(demobuf, 1, 512, demofile))>0) {
- flib_vector_append(vec, demobuf, len);
- }
- fclose(demofile);
- flib_constbuffer constbuf = flib_vector_as_constbuffer(vec);
- flib_gameconn *gameconn = flib_gameconn_create_playdemo(constbuf.data, constbuf.size);
- flib_vector_destroy(vec);
- assert(gameconn);
- flib_gameconn_onDisconnect(gameconn, &onDisconnect, &gameconn);
- flib_gameconn_onGameRecorded(gameconn, &onGameRecorded, &gameconn);
- startEngineGame(flib_gameconn_getport(gameconn));
-
- while(gameconn) {
- flib_gameconn_tick(gameconn);
- }
-}
-
-void testSave() {
- FILE *demofile = fopen("testsave.42.hws", "rb");
- assert(demofile);
- flib_vector *vec = flib_vector_create();
- uint8_t demobuf[512];
- int len;
- while((len=fread(demobuf, 1, 512, demofile))>0) {
- flib_vector_append(vec, demobuf, len);
- }
- fclose(demofile);
- flib_constbuffer constbuf = flib_vector_as_constbuffer(vec);
- flib_gameconn *gameconn = flib_gameconn_create_loadgame("Medo42", constbuf.data, constbuf.size);
- flib_vector_destroy(vec);
- assert(gameconn);
- flib_gameconn_onDisconnect(gameconn, &onDisconnect, &gameconn);
- flib_gameconn_onGameRecorded(gameconn, &onGameRecorded, &gameconn);
- startEngineGame(flib_gameconn_getport(gameconn));
-
- while(gameconn) {
- flib_gameconn_tick(gameconn);
- }
-}
-
-void handleNetDisconnect(void *context, int reason, const char *message) {
- flib_log_i("Disconnected: %s", message);
- flib_netconn_destroy(*(flib_netconn**)context);
- *(flib_netconn**)context = NULL;
-}
-
-void handleNetConnected(void *context) {
- const flib_roomlist *roomlist = flib_netconn_get_roomlist(*(flib_netconn**)context);
- flib_log_i("List of rooms:");
- for(int i=0; i<roomlist->roomCount; i++) {
- flib_roomlist_room *room = roomlist->rooms[i];
- 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);
- }
-}
-
-void handleLobbyJoin(void *context, const char *nick) {
- flib_log_i("%s joined", nick);
-}
-
-void handleChat(void *context, const char *nick, const char *msg) {
- flib_log_i("%s: %s", nick, msg);
- if(!memcmp("frontbot ", msg, strlen("frontbot "))) {
- const char *command = msg+strlen("frontbot ");
- if(!memcmp("quit", command, strlen("quit"))) {
- flib_netconn_send_quit(*(flib_netconn**)context, "Yeth Mathter");
- } else if(!memcmp("describe ", command, strlen("describe "))) {
- const char *roomname = command+strlen("describe ");
- const flib_roomlist *roomlist = flib_netconn_get_roomlist(*(flib_netconn**)context);
- flib_roomlist_room *room = flib_roomlist_find((flib_roomlist*)roomlist, roomname);
- if(!room) {
- flib_netconn_send_chat(*(flib_netconn**)context, "Unknown room.");
- } else {
- char *text = flib_asprintf(
- "%s is a room created by %s, where %i players (%i teams) are %s on %s%s, using the %s scheme and %s weaponset.",
- room->name,
- room->owner,
- room->playerCount,
- room->teamCount,
- room->inProgress ? "fighting" : "preparing to fight",
- room->map[0]=='+' ? "" : "the map ",
- !strcmp("+rnd+", room->map) ? "a random map" :
- !strcmp("+maze+", room->map) ? "a random maze" :
- !strcmp("+drawn+", room->map) ? "a hand-drawn map" :
- room->map,
- room->scheme,
- room->weapons);
- if(text) {
- flib_netconn_send_chat(*(flib_netconn**)context, text);
- }
- free(text);
- }
- } else if(!memcmp("join ", command, strlen("join "))) {
- const char *roomname = command+strlen("join ");
- flib_netconn_send_joinRoom(*(flib_netconn**)context, roomname);
- } else if(!memcmp("ready", command, strlen("ready"))) {
- flib_netconn_send_toggleReady(*(flib_netconn**)context);
- }
- }
-}
-
-static flib_gamesetup gGamesetup = {0};
-static flib_weaponset *gWeaponset = NULL;
-
-void handleEnterRoom(void *context, bool isChief) {
- flib_netconn_send_toggleReady(*(flib_netconn**)context);
-}
-
-void handleMap(void *context, const flib_map *map, int changeType) {
- flib_map_release(gGamesetup.map);
- gGamesetup.map = flib_map_copy(map);
-}
-
-void handleCfgScheme(void *context, flib_cfg *cfg) {
- flib_cfg_release(gGamesetup.gamescheme);
- gGamesetup.gamescheme = flib_cfg_retain(cfg);
-}
-
-void handleWeaponset(void *context, flib_weaponset *weaponset) {
- flib_weaponset_release(gWeaponset);
- gWeaponset = flib_weaponset_retain(weaponset);
-}
-
-void handleScript(void *context, const char *script) {
- free(gGamesetup.script);
- gGamesetup.script = flib_strdupnull(script);
-}
-
-void handleTeamAdd(void *context, flib_team *team) {
- flib_team *teamptr = flib_team_retain(team);
- gGamesetup.teams = flib_list_insert(gGamesetup.teams, &gGamesetup.teamCount, sizeof(*gGamesetup.teams), &teamptr, 0);
-}
-
-void handleTeamRemove(void *context, const char *team) {
- for(int i=0; i<gGamesetup.teamCount; i++) {
- if(!strcmp(team, gGamesetup.teams[i]->name)) {
- flib_team_release(gGamesetup.teams[i]);
- gGamesetup.teams = flib_list_delete(gGamesetup.teams, &gGamesetup.teamCount, sizeof(*gGamesetup.teams), i);
- }
- }
-}
-
-int main(int argc, char *argv[]) {
- flib_init(0);
- flib_log_setLevel(FLIB_LOGLEVEL_ALL);
-
- //testMapPreview();
- //testDemo();
- //testSave();
- //testGame();
-
- flib_cfg_meta *meta = flib_cfg_meta_from_ini("metasettings.ini");
- assert(meta);
- flib_netconn *conn = flib_netconn_create("frontbot", meta, "140.247.62.101", 46631);
- assert(conn);
- flib_cfg_meta_release(meta);
-
- flib_netconn_onConnected(conn, handleNetConnected, &conn);
- flib_netconn_onDisconnected(conn, handleNetDisconnect, &conn);
- flib_netconn_onLobbyJoin(conn, handleLobbyJoin, &conn);
- flib_netconn_onChat(conn, handleChat, &conn);
- flib_netconn_onMapChanged(conn, handleMap, conn);
- flib_netconn_onEnterRoom(conn, handleEnterRoom, conn);
- flib_netconn_onCfgScheme(conn, handleCfgScheme, conn);
- flib_netconn_onWeaponsetChanged(conn, handleWeaponset, conn);
- flib_netconn_onScriptChanged(conn, handleScript, conn);
- flib_netconn_onTeamAdd(conn, handleTeamAdd, conn);
- flib_netconn_onTeamRemove(conn, handleTeamRemove, conn);
- flib_netconn_onHogCountChanged(conn, handleHogCountChanged, conn);
-
- while(conn) {
- flib_netconn_tick(conn);
- }
-
- flib_quit();
- return 0;
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/frontlib/test.c.nocompile Wed Jun 27 18:02:45 2012 +0200
@@ -0,0 +1,319 @@
+#include "frontlib.h"
+#include "util/logging.h"
+#include "util/buffer.h"
+#include "util/util.h"
+#include "util/list.h"
+#include "model/map.h"
+#include "model/weapon.h"
+#include "model/schemelist.h"
+#include "ipc/mapconn.h"
+#include "ipc/gameconn.h"
+#include "net/netconn.h"
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <string.h>
+
+// Callback function that will be called when the map is rendered
+static void handleMapSuccess(void *context, const uint8_t *bitmap, int numHedgehogs) {
+ printf("Drawing map for %i brave little hogs...", numHedgehogs);
+
+ // Draw the map as ASCII art
+ for(int y=0; y<MAPIMAGE_HEIGHT; y++) {
+ for(int x=0; x<MAPIMAGE_WIDTH; x++) {
+ int pixelnum = x + y*MAPIMAGE_WIDTH;
+ bool pixel = bitmap[pixelnum>>3] & (1<<(7-(pixelnum&7)));
+ printf(pixel ? "#" : " ");
+ }
+ printf("\n");
+ }
+
+ // Destroy the connection object (this will end the "tick" loop below)
+ flib_mapconn **connptr = context;
+ flib_mapconn_destroy(*connptr);
+ *connptr = NULL;
+}
+
+static void onDisconnect(void *context, int reason) {
+ flib_log_i("Connection closed. Reason: %i", reason);
+ flib_gameconn **connptr = context;
+ flib_gameconn_destroy(*connptr);
+ *connptr = NULL;
+}
+
+static void onGameRecorded(void *context, const uint8_t *record, int size, bool isSavegame) {
+ flib_log_i("Writing %s (%i bytes)...", isSavegame ? "savegame" : "demo", size);
+ FILE *file = fopen(isSavegame ? "testsave.42.hws" : "testdemo.42.hwd", "wb");
+ fwrite(record, 1, size, file);
+ fclose(file);
+}
+
+// Callback function that will be called on error
+static void handleMapFailure(void *context, const char *errormessage) {
+ flib_log_e("Map rendering failed: %s", errormessage);
+
+ // Destroy the connection object (this will end the "tick" loop below)
+ flib_mapconn **connptr = context;
+ flib_mapconn_destroy(*connptr);
+ *connptr = NULL;
+}
+
+static void startEngineMap(int port) {
+ char commandbuffer[255];
+ const char *enginePath = "C:\\Programmieren\\Hedgewars\\bin";
+ const char *configPath = "C:\\Programmieren\\Hedgewars\\share\\hedgewars";
+ snprintf(commandbuffer, 255, "start %s\\hwengine.exe %s %i landpreview", enginePath, configPath, port);
+ system(commandbuffer);
+}
+
+static void startEngineGame(int port) {
+ char commandbuffer[255];
+ const char *enginePath = "C:\\Programmieren\\Hedgewars\\bin";
+ const char *configPath = "C:\\Programmieren\\Hedgewars\\share\\hedgewars";
+ const char *dataPath = "C:\\Programmieren\\Hedgewars\\share\\hedgewars\\Data";
+ 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);
+ flib_log_d("Starting engine with CMD: %s", commandbuffer);
+ system(commandbuffer);
+}
+
+void testMapPreview() {
+ // Create a map description and check that there was no error
+ flib_map *map = flib_map_create_maze("This is the seed value", "Jungle", MAZE_SIZE_SMALL_TUNNELS);
+ assert(map);
+
+ // Create a new connection to the engine and check that there was no error
+ flib_mapconn *mapConnection = flib_mapconn_create(map);
+ assert(mapConnection);
+
+ // We don't need the map description anymore
+ flib_map_release(map);
+ map = NULL;
+
+ // Register the callback functions
+ flib_mapconn_onFailure(mapConnection, &handleMapFailure, &mapConnection);
+ flib_mapconn_onSuccess(mapConnection, &handleMapSuccess, &mapConnection);
+
+ // Start the engine process and tell it which port the frontlib is listening on
+ startEngineMap(flib_mapconn_getport(mapConnection));
+
+ // Usually, flib_mapconn_tick will be called in an event loop that runs several
+ // times per second. It handles I/O operations and progress, and calls
+ // callbacks when something interesting happens.
+ while(mapConnection) {
+ flib_mapconn_tick(mapConnection);
+ }
+}
+
+/*void testGame() {
+ flib_cfg_meta *metaconf = flib_cfg_meta_from_ini("metasettings.ini");
+ assert(metaconf);
+ flib_weaponset *weapons = flib_weaponset_create("Defaultweaps");
+ flib_schemelist *schemelist = flib_schemelist_from_ini(metaconf, "schemes.ini");
+
+ flib_gamesetup setup;
+ setup.gamescheme = flib_schemelist_find(schemelist, "Default");
+ setup.map = flib_map_create_maze("asparagus", "Jungle", MAZE_SIZE_MEDIUM_TUNNELS);
+ setup.script = NULL;
+ setup.teamCount = 2;
+ setup.teams = calloc(2, sizeof(flib_team*));
+ setup.teams[0] = calloc(1, sizeof(flib_team));
+ setup.teams[0]->color = 0xffff0000;
+ setup.teams[0]->flag = "australia";
+ setup.teams[0]->fort = "Plane";
+ setup.teams[0]->grave = "Bone";
+ setup.teams[0]->hogsInGame = 2;
+ setup.teams[0]->name = "Team Awesome";
+ setup.teams[0]->voicepack = "British";
+ setup.teams[0]->hogs[0].difficulty = 2;
+ setup.teams[0]->hogs[0].hat = "NoHat";
+ setup.teams[0]->hogs[0].initialHealth = 100;
+ setup.teams[0]->hogs[0].name = "Harry 120";
+ setup.teams[0]->hogs[1].difficulty = 2;
+ setup.teams[0]->hogs[1].hat = "chef";
+ setup.teams[0]->hogs[1].initialHealth = 100;
+ setup.teams[0]->hogs[1].name = "Chefkoch";
+ setup.teams[1] = flib_team_from_ini("Cave Dwellers.hwt");
+ setup.teams[1]->color = 0xFF0000F0;
+ setup.teams[1]->hogsInGame = 8;
+ flib_team_set_weaponset(setup.teams[0], weapons);
+ flib_team_set_weaponset(setup.teams[1], weapons);
+ flib_weaponset_release(weapons);
+
+ flib_gameconn *gameconn = flib_gameconn_create("Medo42", &setup, false);
+ assert(gameconn);
+
+ flib_gameconn_onDisconnect(gameconn, &onDisconnect, &gameconn);
+ //flib_gameconn_onGameRecorded(gameconn, &onGameRecorded, &gameconn);
+
+ startEngineGame(flib_gameconn_getport(gameconn));
+
+ while(gameconn) {
+ flib_gameconn_tick(gameconn);
+ }
+}*/
+
+void testDemo() {
+ FILE *demofile = fopen("testdemo.42.hwd", "rb");
+ assert(demofile);
+ flib_vector *vec = flib_vector_create();
+ uint8_t demobuf[512];
+ int len;
+ while((len=fread(demobuf, 1, 512, demofile))>0) {
+ flib_vector_append(vec, demobuf, len);
+ }
+ fclose(demofile);
+ flib_constbuffer constbuf = flib_vector_as_constbuffer(vec);
+ flib_gameconn *gameconn = flib_gameconn_create_playdemo(constbuf.data, constbuf.size);
+ flib_vector_destroy(vec);
+ assert(gameconn);
+ flib_gameconn_onDisconnect(gameconn, &onDisconnect, &gameconn);
+ flib_gameconn_onGameRecorded(gameconn, &onGameRecorded, &gameconn);
+ startEngineGame(flib_gameconn_getport(gameconn));
+
+ while(gameconn) {
+ flib_gameconn_tick(gameconn);
+ }
+}
+
+void testSave() {
+ FILE *demofile = fopen("testsave.42.hws", "rb");
+ assert(demofile);
+ flib_vector *vec = flib_vector_create();
+ uint8_t demobuf[512];
+ int len;
+ while((len=fread(demobuf, 1, 512, demofile))>0) {
+ flib_vector_append(vec, demobuf, len);
+ }
+ fclose(demofile);
+ flib_constbuffer constbuf = flib_vector_as_constbuffer(vec);
+ flib_gameconn *gameconn = flib_gameconn_create_loadgame("Medo42", constbuf.data, constbuf.size);
+ flib_vector_destroy(vec);
+ assert(gameconn);
+ flib_gameconn_onDisconnect(gameconn, &onDisconnect, &gameconn);
+ flib_gameconn_onGameRecorded(gameconn, &onGameRecorded, &gameconn);
+ startEngineGame(flib_gameconn_getport(gameconn));
+
+ while(gameconn) {
+ flib_gameconn_tick(gameconn);
+ }
+}
+
+void handleNetDisconnect(void *context, int reason, const char *message) {
+ flib_log_i("Disconnected: %s", message);
+ flib_netconn_destroy(*(flib_netconn**)context);
+ *(flib_netconn**)context = NULL;
+}
+
+void handleNetConnected(void *context) {
+ const flib_roomlist *roomlist = flib_netconn_get_roomlist(*(flib_netconn**)context);
+ flib_log_i("List of rooms:");
+ for(int i=0; i<roomlist->roomCount; i++) {
+ flib_roomlist_room *room = roomlist->rooms[i];
+ 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);
+ }
+ flib_netconn_send_joinRoom(*(flib_netconn**)context, "frontlib test");
+}
+
+void handleLobbyJoin(void *context, const char *nick) {
+ flib_log_i("%s joined", nick);
+}
+
+void handleChat(void *context, const char *nick, const char *msg) {
+ flib_log_i("%s: %s", nick, msg);
+ if(!memcmp("frontbot ", msg, strlen("frontbot "))) {
+ const char *command = msg+strlen("frontbot ");
+ if(!memcmp("quit", command, strlen("quit"))) {
+ flib_netconn_send_quit(*(flib_netconn**)context, "Yeth Mathter");
+ } else if(!memcmp("describe ", command, strlen("describe "))) {
+ const char *roomname = command+strlen("describe ");
+ const flib_roomlist *roomlist = flib_netconn_get_roomlist(*(flib_netconn**)context);
+ flib_roomlist_room *room = flib_roomlist_find((flib_roomlist*)roomlist, roomname);
+ if(!room) {
+ flib_netconn_send_chat(*(flib_netconn**)context, "Unknown room.");
+ } else {
+ char *text = flib_asprintf(
+ "%s is a room created by %s, where %i players (%i teams) are %s on %s%s, using the %s scheme and %s weaponset.",
+ room->name,
+ room->owner,
+ room->playerCount,
+ room->teamCount,
+ room->inProgress ? "fighting" : "preparing to fight",
+ room->map[0]=='+' ? "" : "the map ",
+ !strcmp("+rnd+", room->map) ? "a random map" :
+ !strcmp("+maze+", room->map) ? "a random maze" :
+ !strcmp("+drawn+", room->map) ? "a hand-drawn map" :
+ room->map,
+ room->scheme,
+ room->weapons);
+ if(text) {
+ flib_netconn_send_chat(*(flib_netconn**)context, text);
+ }
+ free(text);
+ }
+ } else if(!memcmp("join ", command, strlen("join "))) {
+ const char *roomname = command+strlen("join ");
+ flib_netconn_send_joinRoom(*(flib_netconn**)context, roomname);
+ } else if(!memcmp("ready", command, strlen("ready"))) {
+ flib_netconn_send_toggleReady(*(flib_netconn**)context);
+ }
+ }
+}
+
+void handleEnterRoom(void *context, bool isChief) {
+ flib_netconn_send_toggleReady(*(flib_netconn**)context);
+}
+
+flib_gameconn *gameconn = NULL;
+
+void emFromNetHandler(void *context, const char *em, int size) {
+ flib_gameconn_send_enginemsg(gameconn, (const uint8_t*)em, size);
+}
+
+void emFromEngineHandler(void *context, const uint8_t *em, int size) {
+ flib_netconn_send_engineMessage((flib_netconn*)context, em, size);
+}
+
+void handleRunGame(void *context) {
+ flib_gamesetup *gamesetup = flib_netconn_create_gameSetup((flib_netconn*)context);
+ if(gamesetup) {
+ gameconn = flib_gameconn_create("frontbot", gamesetup, true);
+ flib_gameconn_onEngineMessage(gameconn, emFromEngineHandler, context);
+ flib_gameconn_onDisconnect(gameconn, onDisconnect, &gameconn);
+ startEngineGame(flib_gameconn_getport(gameconn));
+ }
+}
+
+int main(int argc, char *argv[]) {
+ flib_init(0);
+ flib_log_setLevel(FLIB_LOGLEVEL_ALL);
+
+ //testMapPreview();
+ //testDemo();
+ //testSave();
+ //testGame();
+
+ flib_cfg_meta *meta = flib_cfg_meta_from_ini("metasettings.ini");
+ assert(meta);
+ flib_netconn *conn = flib_netconn_create("frontbot", meta, "140.247.62.101", 46631);
+ assert(conn);
+ flib_cfg_meta_release(meta);
+
+ flib_netconn_onConnected(conn, handleNetConnected, &conn);
+ flib_netconn_onDisconnected(conn, handleNetDisconnect, &conn);
+ flib_netconn_onLobbyJoin(conn, handleLobbyJoin, &conn);
+ flib_netconn_onChat(conn, handleChat, &conn);
+ flib_netconn_onEnterRoom(conn, handleEnterRoom, conn);
+ flib_netconn_onRunGame(conn, handleRunGame, conn);
+ flib_netconn_onEngineMessage(conn, emFromNetHandler, NULL);
+
+ while(conn) {
+ flib_netconn_tick(conn);
+ if(gameconn) {
+ flib_gameconn_tick(gameconn);
+ }
+ }
+
+ flib_quit();
+ return 0;
+}
--- a/project_files/frontlib/util/buffer.c Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/util/buffer.c Wed Jun 27 18:02:45 2012 +0200
@@ -94,29 +94,20 @@
}
int flib_vector_append(flib_vector *vec, const void *data, size_t len) {
- if(!vec) {
- flib_log_e("null parameter in flib_vector_append");
- return 0;
- }
-
- if(len > SIZE_MAX-vec->size) {
- return 0;
+ if(!log_badparams_if(!vec || (!data && len>0))
+ && !log_oom_if(len > SIZE_MAX-vec->size)) {
+ size_t oldSize = vec->size;
+ if(!log_oom_if(flib_vector_resize(vec, vec->size+len))) {
+ memmove(((uint8_t*)vec->data) + oldSize, data, len);
+ return 0;
+ }
}
-
- size_t oldSize = vec->size;
- if(flib_vector_resize(vec, vec->size+len)) {
- return 0;
- }
-
- memmove(((uint8_t*)vec->data) + oldSize, data, len);
- return len;
+ return -1;
}
int flib_vector_appendf(flib_vector *vec, const char *fmt, ...) {
int result = -1;
- if(!vec || !fmt) {
- flib_log_e("null parameter in flib_vector_appendf");
- } else {
+ if(!log_badparams_if(!vec || !fmt)) {
va_list argp;
va_start(argp, fmt);
char *formatted = flib_vasprintf(fmt, argp);
@@ -125,9 +116,7 @@
if(formatted) {
size_t len = strlen(formatted);
- if(flib_vector_append(vec, formatted, len) == len) {
- result = 0;
- }
+ result = flib_vector_append(vec, formatted, len);
}
}
return result;
--- a/project_files/frontlib/util/buffer.h Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/util/buffer.h Wed Jun 27 18:02:45 2012 +0200
@@ -48,8 +48,8 @@
/**
* Append the provided data to the end of the vector, enlarging it as required.
- * Returns the ammount of data appended, which is either len (success) or 0 (out of memory).
* The vector remains unchanged if appending fails.
+ * Returns 0 on success.
*/
int flib_vector_append(flib_vector *vec, const void *data, size_t len);
--- a/project_files/frontlib/util/list.c Mon Jun 25 15:21:18 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-#include "list.h"
-
-#include <string.h>
-#include "util.h"
-#include "logging.h"
-
-void *flib_list_insert(void *list, int *listSizePtr, size_t elementSize, void *elementPtr, int pos) {
- void *result = NULL;
- if(!listSizePtr || !elementPtr || pos < 0 || pos > *listSizePtr) {
- flib_log_e("Invalid parameter in flib_list_insert");
- } else {
- unsigned char *newList = flib_realloc(list, ((*listSizePtr)+1)*elementSize);
- if(newList) {
- memmove(newList + (pos+1)*elementSize, newList + pos*elementSize, ((*listSizePtr)-pos)*elementSize);
- memmove(newList + pos*elementSize, elementPtr, elementSize);
- (*listSizePtr)++;
- result = newList;
- }
- }
- return result;
-}
-
-void *flib_list_delete(void *list, int *listSizePtr, size_t elementSize, int pos) {
- void *result = NULL;
- if(!listSizePtr || pos < 0 || pos >= *listSizePtr) {
- flib_log_e("Invalid parameter in flib_list_delete");
- } else {
- unsigned char *charList = list;
- memmove(charList + (pos*elementSize), charList + (pos+1)*elementSize, (*listSizePtr-(pos+1))*elementSize);
- (*listSizePtr)--;
-
- // If the realloc fails, just keep using the old buffer...
- size_t newCharSize = (*listSizePtr)*elementSize;
- void *newList = flib_realloc(list, newCharSize);
- if(newList || newCharSize==0) {
- result = newList;
- } else {
- result = list;
- }
- }
- return result;
-}
--- a/project_files/frontlib/util/list.h Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/util/list.h Wed Jun 27 18:02:45 2012 +0200
@@ -6,19 +6,60 @@
#define LIST_H_
#include <stddef.h>
+#include <string.h>
+#include <stdlib.h>
+#include "util.h"
+#include "logging.h"
/**
- * Insert element into the list and increase listSize.
- * Returns a pointer to the modified list on success, NULL on failure. On success, the old
- * pointer is no longer valid, and on failure the list remains unchanged (similar to realloc)
+ * Generate a static function that inserts a new value into a heap array of the given type,
+ * using realloc and memmove to increase the capacity and shift existing values.
+ * The function takes a pointer to the array variable and a pointer to the size variable
+ * because both can be changed by this operation (realloc / increment).
+ * The function returns 0 on success and leaves the array unchanged on error.
*/
-void *flib_list_insert(void *list, int *listSizePtr, size_t elementSize, void *elementPtr, int pos);
+#define GENERATE_STATIC_LIST_INSERT(fname, type) \
+ static int fname(type **listptr, int *listSizePtr, type element, int pos) { \
+ int result = -1; \
+ if(!listptr || !listSizePtr || pos < 0 || pos > *listSizePtr) { \
+ flib_log_e("Invalid parameter in "#fname); \
+ } else { \
+ type *newList = flib_realloc(*listptr, ((*listSizePtr)+1)*sizeof(type)); \
+ if(newList) { \
+ memmove(newList + (pos+1), newList + pos, ((*listSizePtr)-pos)*sizeof(type)); \
+ newList[pos] = element; \
+ (*listSizePtr)++; \
+ *listptr = newList; \
+ result = 0; \
+ } \
+ } \
+ return result; \
+ }
/**
- * Remove an element from the list and decrease listSize.
- * Returns a pointer to the modified list on success, NULL on failure. On success, the old
- * pointer is no longer valid, and on failure the list remains unchanged (similar to realloc)
+ * Generate a static function that deletes a value from a heap array of the given type,
+ * using realloc and memmove to decrease the capacity and shift existing values.
+ * The function takes a pointer to the array variable and a pointer to the size variable
+ * because both can be changed by this operation (realloc / decrement).
+ * The function returns 0 on success and leaves the array unchanged on error.
*/
-void *flib_list_delete(void *list, int *listSizePtr, size_t elementSize, int pos);
+#define GENERATE_STATIC_LIST_DELETE(fname, type) \
+ static int fname(type **listPtr, int *listSizePtr, int pos) { \
+ int result = -1; \
+ if(!listPtr || !listSizePtr || pos < 0 || pos >= *listSizePtr) { \
+ flib_log_e("Invalid parameter in "#fname); \
+ } else { \
+ memmove((*listPtr) + pos, (*listPtr) + (pos+1), ((*listSizePtr)-(pos+1))*sizeof(type)); \
+ (*listSizePtr)--; \
+ \
+ size_t newCharSize = (*listSizePtr)*sizeof(type); \
+ type *newList = flib_realloc((*listPtr), newCharSize); \
+ if(newList || newCharSize==0) { \
+ (*listPtr) = newList; \
+ } /* If the realloc fails, just keep using the old buffer...*/ \
+ result = 0; \
+ } \
+ return result; \
+ }
#endif /* LIST_H_ */
--- a/project_files/frontlib/util/logging.c Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/util/logging.c Wed Jun 27 18:02:45 2012 +0200
@@ -34,44 +34,47 @@
fprintf(flib_log_getfile(), "%s", buffer);
}
-static void flib_vflog(const char *prefix, int level, const char *fmt, va_list args) {
+static const char *getPrefix(int level) {
+ switch(level) {
+ case FLIB_LOGLEVEL_ERROR: return "E";
+ case FLIB_LOGLEVEL_WARNING: return "W";
+ case FLIB_LOGLEVEL_INFO: return "I";
+ case FLIB_LOGLEVEL_DEBUG: return "D";
+ default: return "?";
+ }
+}
+
+static void _flib_vflog(const char *func, int level, const char *fmt, va_list args) {
FILE *logfile = flib_log_getfile();
if(level >= flib_loglevel) {
- fprintf(logfile, "%s ", prefix);
+ fprintf(logfile, "%s ", getPrefix(level));
log_time(logfile);
- fprintf(logfile, " ", prefix);
+ fprintf(logfile, " [%-30s] ", func);
vfprintf(logfile, fmt, args);
fprintf(logfile, "\n");
fflush(logfile);
}
}
-void flib_log_e(const char *fmt, ...) {
+void _flib_flog(const char *func, int level, const char *fmt, ...) {
va_list argp;
va_start(argp, fmt);
- flib_vflog("E", FLIB_LOGLEVEL_ERROR, fmt, argp);
+ _flib_vflog(func, level, fmt, argp);
va_end(argp);
}
-void flib_log_w(const char *fmt, ...) {
- va_list argp;
- va_start(argp, fmt);
- flib_vflog("W", FLIB_LOGLEVEL_WARNING, fmt, argp);
- va_end(argp);
+bool _flib_fassert(const char *func, int level, bool cond, const char *fmt, ...) {
+ if(!cond) {
+ va_list argp;
+ va_start(argp, fmt);
+ _flib_vflog(func, level, fmt, argp);
+ va_end(argp);
+ }
+ return !cond;
}
-void flib_log_i(const char *fmt, ...) {
- va_list argp;
- va_start(argp, fmt);
- flib_vflog("I", FLIB_LOGLEVEL_INFO, fmt, argp);
- va_end(argp);
-}
-
-void flib_log_d(const char *fmt, ...) {
- va_list argp;
- va_start(argp, fmt);
- flib_vflog("D", FLIB_LOGLEVEL_DEBUG, fmt, argp);
- va_end(argp);
+bool _flib_assert_params(const char *func, bool cond) {
+ return _flib_fassert(func, FLIB_LOGLEVEL_ERROR, cond, "Invalid parameter to function");
}
int flib_log_getLevel() {
--- a/project_files/frontlib/util/logging.h Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/util/logging.h Wed Jun 27 18:02:45 2012 +0200
@@ -17,10 +17,27 @@
*/
char* flib_format_ip(uint32_t numip);
-void flib_log_e(const char *fmt, ...);
-void flib_log_w(const char *fmt, ...);
-void flib_log_i(const char *fmt, ...);
-void flib_log_d(const char *fmt, ...);
+/**
+ * Evaluates the expression cond. If it is true, a formatted error will be logged.
+ * Returns true if an error is logged, false otherwise (i.e. the boolean value of the argument)
+ */
+#define log_e_if(cond, ...) _flib_fassert(__func__, FLIB_LOGLEVEL_ERROR, !(bool)(cond), __VA_ARGS__)
+#define log_w_if(cond, ...) _flib_fassert(__func__, FLIB_LOGLEVEL_WARNING, !(bool)(cond), __VA_ARGS__)
+
+/**
+ * Shorthand for some common error types
+ */
+#define log_badparams_if(cond) log_e_if(cond, "Invalid Parameters")
+#define log_oom_if(cond) log_e_if(cond, "Out of Memory")
+
+#define flib_log_e(...) _flib_flog(__func__, FLIB_LOGLEVEL_ERROR, __VA_ARGS__)
+#define flib_log_w(...) _flib_flog(__func__, FLIB_LOGLEVEL_WARNING, __VA_ARGS__)
+#define flib_log_i(...) _flib_flog(__func__, FLIB_LOGLEVEL_INFO, __VA_ARGS__)
+#define flib_log_d(...) _flib_flog(__func__, FLIB_LOGLEVEL_DEBUG, __VA_ARGS__)
+
+bool _flib_assert_params(const char *func, bool cond);
+bool _flib_fassert(const char *func, int level, bool cond, const char *fmt, ...);
+void _flib_flog(const char *func, int level, const char *fmt, ...);
int flib_log_getLevel();
void flib_log_setLevel(int level);
--- a/project_files/frontlib/util/util.c Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/util/util.c Wed Jun 27 18:02:45 2012 +0200
@@ -162,3 +162,27 @@
char *shrunk = realloc(outbuf, outpos+1);
return shrunk ? shrunk : outbuf;
}
+
+bool flib_contains_dir_separator(const char *str) {
+ if(!log_badparams_if(!str)) {
+ for(;*str;str++) {
+ if(*str=='\\' || *str=='/') {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+int flib_gets(char *str, size_t strlen) {
+ if(fgets(str, strlen, stdin)) {
+ for(char *s=str; *s; s++) {
+ if(*s=='\r' || *s=='\n') {
+ *s = 0;
+ break;
+ }
+ }
+ return 0;
+ }
+ return -1;
+}
--- a/project_files/frontlib/util/util.h Mon Jun 25 15:21:18 2012 +0200
+++ b/project_files/frontlib/util/util.h Wed Jun 27 18:02:45 2012 +0200
@@ -87,4 +87,12 @@
*/
char *flib_urldecode(const char *str);
+/**
+ * Figure out if the string contains / or \. Useful in routines that
+ * construct filenames.
+ */
+bool flib_contains_dir_separator(const char *str);
+
+int flib_gets(char *str, size_t strlen);
+
#endif