frontlib improvements:
authorMedo <smaxein@googlemail.com>
Sun, 12 Aug 2012 22:37:57 +0200
changeset 7482 d70a5b0d1190
parent 7479 c8c552ee3acb
child 7485 0481bd74267c
frontlib improvements: - Added README with overview documentation - Improved code documentation/comments - Added flib_gameconn_send_quit to gracefully exit a running game - Changed the type of some size variables to size_t - Fixed starting a mission/training sending the mission script like a multiplayer script - Removed reference counters from flib_scheme and flib_map - Removed INGAME state from netconn (there is no useful difference to ROOM state) - Added extras/jnacontrol.c to warn when functions signatures used by Hedgeroid change - Other small code improvements
project_files/frontlib/Android.mk
project_files/frontlib/extra/jnacontrol.c
project_files/frontlib/frontlib.h
project_files/frontlib/ipc/gameconn.c
project_files/frontlib/ipc/gameconn.h
project_files/frontlib/ipc/ipcprotocol.c
project_files/frontlib/ipc/ipcprotocol.h
project_files/frontlib/ipc/mapconn.h
project_files/frontlib/model/gamesetup.c
project_files/frontlib/model/gamesetup.h
project_files/frontlib/model/map.c
project_files/frontlib/model/map.h
project_files/frontlib/model/scheme.c
project_files/frontlib/model/scheme.h
project_files/frontlib/model/schemelist.c
project_files/frontlib/model/schemelist.h
project_files/frontlib/model/team.h
project_files/frontlib/model/weapon.h
project_files/frontlib/net/netconn.c
project_files/frontlib/net/netconn.h
project_files/frontlib/net/netconn_callbacks.c
project_files/frontlib/net/netconn_internal.h
project_files/frontlib/net/netconn_send.c
project_files/frontlib/net/netprotocol.c
project_files/frontlib/net/netprotocol.h
project_files/frontlib/util/logging.h
--- a/project_files/frontlib/Android.mk	Sun Aug 12 22:21:09 2012 +0200
+++ b/project_files/frontlib/Android.mk	Sun Aug 12 22:37:57 2012 +0200
@@ -14,7 +14,7 @@
 	net/netbase.c net/netconn_callbacks.c net/netconn_send.c \
 	net/netconn.c net/netprotocol.c util/buffer.c util/inihelper.c \
 	util/logging.c util/refcounter.c util/util.c frontlib.c \
-	hwconsts.c socket.c
+	hwconsts.c socket.c extra/jnacontrol.c
 
 LOCAL_SHARED_LIBRARIES += SDL_net
 LOCAL_LDLIBS += -lz
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/frontlib/extra/jnacontrol.c	Sun Aug 12 22:37:57 2012 +0200
@@ -0,0 +1,235 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * 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; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/*
+ * This file is not directly part of the frontlib and is not required to build it.
+ * However, it is recommended to include it in compilation when building for Android. The purpose of this file
+ * is to ensure consistency between the function signatures of the JNA Java bindings of the Android port and the
+ * frontlib functions.
+ *
+ * This file, in essence, consists only of function declarations. They are duplicates of function declarations
+ * from the frontlib headers that are referenced from JNA bindings. If the signature of one of these functions
+ * changes in the frontlib, it will no longer match the signature in this file, and the compiler will show an error.
+ * If that happens, you need to update the JNA bindings in Hedgeroid to match the new function signature, and then
+ * update this file.
+ *
+ * The reason for all this is that JNA does not actually know the function signatures of the functions it binds,
+ * it derives them from Java method declarations. If those do not match the actual function signatures, you will
+ * only notice when you suddenly get strange (and possibly hard to track down) problems at runtime. This file is
+ * an attempt to detect these problems at compile time instead. Notice that it will NOT detect changes to structs
+ * or constants though, which also require updates to the JNA bindings.
+ */
+
+/*
+ * Before we include the frontlib headers, we define away the const keyword. This is necessary because there is no
+ * distinction between const and non-const types on the JNA side, and we don't want the compiler to complain because
+ * of bad constness.
+ *
+ * This is so evil, but it works...
+ */
+#define const
+
+#include "../frontlib.h"
+
+/*
+ * Now we map the Java types to the corresponding C types...
+ */
+typedef flib_netconn *NetconnPtr;
+typedef flib_gameconn *GameconnPtr;
+typedef flib_mapconn *MapconnPtr;
+typedef flib_metascheme *MetaschemePtr;
+typedef flib_room **RoomArrayPtr;
+typedef flib_weaponset *WeaponsetPtr;
+typedef flib_weaponsetlist *WeaponsetListPtr;
+typedef flib_map *MapRecipePtr;
+typedef flib_scheme *SchemePtr;
+typedef flib_schemelist *SchemelistPtr;
+
+typedef flib_room *RoomPtr;
+typedef flib_team *TeamPtr;
+typedef flib_gamesetup *GameSetupPtr;
+typedef bool boolean;
+typedef size_t NativeLong;
+typedef void *Pointer;
+typedef char *String;
+typedef uint8_t *Buffer;
+
+/*
+ * Mapping callback types
+ */
+typedef void (*VoidCallback)(Pointer context);
+typedef void (*StrCallback)(Pointer context, String arg1);
+typedef void (*IntCallback)(Pointer context, int arg1);
+typedef void (*IntStrCallback)(Pointer context, int arg1, String arg2);
+typedef void (*StrIntCallback)(Pointer context, String arg1, int arg2);
+typedef void (*StrStrCallback)(Pointer context, String arg1, String arg2);
+typedef void (*RoomCallback)(Pointer context, RoomPtr arg1);
+typedef void (*RoomListCallback)(Pointer context, RoomArrayPtr arg1, int arg2);
+typedef void (*StrRoomCallback)(Pointer context, String arg1, RoomPtr arg2);
+typedef void (*BoolCallback)(Pointer context, boolean arg1);
+typedef void (*StrBoolCallback)(Pointer context, String arg1, boolean arg2);
+typedef void (*TeamCallback)(Pointer context, TeamPtr arg1);
+typedef void (*BytesCallback)(Pointer context, const uint8_t *buffer, NativeLong size);
+typedef void (*BytesBoolCallback)(Pointer context, const uint8_t *buffer, NativeLong size, boolean arg3);
+typedef void (*SchemeCallback)(Pointer context, SchemePtr arg1);
+typedef void (*MapIntCallback)(Pointer context, MapRecipePtr arg1, int arg2);
+typedef void (*WeaponsetCallback)(Pointer context, WeaponsetPtr arg1);
+typedef void (*MapimageCallback)(Pointer context, const uint8_t *mapimage, int hogs);
+typedef void (*LogCallback)(int arg1, String arg2);
+
+/*
+ * Below here are the copypasted method declarations from the JNA bindings
+ */
+
+// frontlib.h
+int flib_init();
+void flib_quit();
+
+// net/netconn.h
+NetconnPtr flib_netconn_create(String playerName, MetaschemePtr meta, String dataDirPath, String host, int port);
+void flib_netconn_destroy(NetconnPtr conn);
+
+void flib_netconn_tick(NetconnPtr conn);
+boolean flib_netconn_is_chief(NetconnPtr conn);
+String flib_netconn_get_playername(NetconnPtr conn);
+GameSetupPtr flib_netconn_create_gamesetup(NetconnPtr conn);
+int flib_netconn_send_quit(NetconnPtr conn, String quitmsg);
+int flib_netconn_send_chat(NetconnPtr conn, String chat);
+int flib_netconn_send_teamchat(NetconnPtr conn, String msg);
+int flib_netconn_send_password(NetconnPtr conn, String passwd);
+int flib_netconn_send_nick(NetconnPtr conn, String nick);
+int flib_netconn_send_request_roomlist(NetconnPtr conn);
+int flib_netconn_send_joinRoom(NetconnPtr conn, String room);
+int flib_netconn_send_createRoom(NetconnPtr conn, String room);
+int flib_netconn_send_renameRoom(NetconnPtr conn, String roomName);
+int flib_netconn_send_leaveRoom(NetconnPtr conn, String msg);
+int flib_netconn_send_toggleReady(NetconnPtr conn);
+int flib_netconn_send_addTeam(NetconnPtr conn, TeamPtr team);
+int flib_netconn_send_removeTeam(NetconnPtr conn, String teamname);
+int flib_netconn_send_engineMessage(NetconnPtr conn, Buffer message, NativeLong size);
+int flib_netconn_send_teamHogCount(NetconnPtr conn, String teamname, int hogcount);
+int flib_netconn_send_teamColor(NetconnPtr conn, String teamname, int colorIndex);
+int flib_netconn_send_weaponset(NetconnPtr conn, WeaponsetPtr weaponset);
+int flib_netconn_send_map(NetconnPtr conn, MapRecipePtr map);
+int flib_netconn_send_mapName(NetconnPtr conn, String mapName);
+int flib_netconn_send_mapGen(NetconnPtr conn, int mapGen);
+int flib_netconn_send_mapTemplate(NetconnPtr conn, int templateFilter);
+int flib_netconn_send_mapMazeSize(NetconnPtr conn, int mazeSize);
+int flib_netconn_send_mapSeed(NetconnPtr conn, String seed);
+int flib_netconn_send_mapTheme(NetconnPtr conn, String theme);
+int flib_netconn_send_mapDrawdata(NetconnPtr conn, Buffer drawData, NativeLong size);
+int flib_netconn_send_script(NetconnPtr conn, String scriptName);
+int flib_netconn_send_scheme(NetconnPtr conn, SchemePtr scheme);
+int flib_netconn_send_roundfinished(NetconnPtr conn, boolean withoutError);
+int flib_netconn_send_ban(NetconnPtr conn, String playerName);
+int flib_netconn_send_kick(NetconnPtr conn, String playerName);
+int flib_netconn_send_playerInfo(NetconnPtr conn, String playerName);
+int flib_netconn_send_playerFollow(NetconnPtr conn, String playerName);
+int flib_netconn_send_startGame(NetconnPtr conn);
+int flib_netconn_send_toggleRestrictJoins(NetconnPtr conn);
+int flib_netconn_send_toggleRestrictTeams(NetconnPtr conn);
+int flib_netconn_send_clearAccountsCache(NetconnPtr conn);
+int flib_netconn_send_setServerVar(NetconnPtr conn, String name, String value);
+int flib_netconn_send_getServerVars(NetconnPtr conn);
+
+void flib_netconn_onMessage(NetconnPtr conn, IntStrCallback callback, Pointer context);
+void flib_netconn_onChat(NetconnPtr conn, StrStrCallback callback, Pointer context);
+void flib_netconn_onConnected(NetconnPtr conn, VoidCallback callback, Pointer context);
+void flib_netconn_onDisconnected(NetconnPtr conn, IntStrCallback callback, Pointer context);
+void flib_netconn_onRoomlist(NetconnPtr conn, RoomListCallback callback, Pointer context);
+void flib_netconn_onRoomAdd(NetconnPtr conn, RoomCallback callback, Pointer context);
+void flib_netconn_onRoomDelete(NetconnPtr conn, StrCallback callback, Pointer context);
+void flib_netconn_onRoomUpdate(NetconnPtr conn, StrRoomCallback callback, Pointer context);
+void flib_netconn_onLobbyJoin(NetconnPtr conn, StrCallback callback, Pointer context);
+void flib_netconn_onLobbyLeave(NetconnPtr conn, StrStrCallback callback, Pointer context);
+void flib_netconn_onNickTaken(NetconnPtr conn, StrCallback callback, Pointer context);
+void flib_netconn_onPasswordRequest(NetconnPtr conn, StrCallback callback, Pointer context);
+void flib_netconn_onEnterRoom(NetconnPtr conn, BoolCallback callback, Pointer context);
+void flib_netconn_onRoomChiefStatus(NetconnPtr conn, BoolCallback callback, Pointer context);
+void flib_netconn_onReadyState(NetconnPtr conn, StrBoolCallback callback, Pointer context);
+void flib_netconn_onLeaveRoom(NetconnPtr conn, IntStrCallback callback, Pointer context);
+void flib_netconn_onTeamAdd(NetconnPtr conn, TeamCallback callback, Pointer context);
+void flib_netconn_onTeamDelete(NetconnPtr conn, StrCallback callback, Pointer context);
+void flib_netconn_onRoomJoin(NetconnPtr conn, StrCallback callback, Pointer context);
+void flib_netconn_onRoomLeave(NetconnPtr conn, StrStrCallback callback, Pointer context);
+void flib_netconn_onRunGame(NetconnPtr conn, VoidCallback callback, Pointer context);
+void flib_netconn_onTeamAccepted(NetconnPtr conn, StrCallback callback, Pointer context);
+void flib_netconn_onHogCountChanged(NetconnPtr conn, StrIntCallback callback, Pointer context);
+void flib_netconn_onTeamColorChanged(NetconnPtr conn, StrIntCallback callback, Pointer context);
+void flib_netconn_onEngineMessage(NetconnPtr conn, BytesCallback callback, Pointer context);
+void flib_netconn_onCfgScheme(NetconnPtr conn, SchemeCallback callback, Pointer context);
+void flib_netconn_onMapChanged(NetconnPtr conn, MapIntCallback callback, Pointer context);
+void flib_netconn_onScriptChanged(NetconnPtr conn, StrCallback callback, Pointer context);
+void flib_netconn_onWeaponsetChanged(NetconnPtr conn, WeaponsetCallback callback, Pointer context);
+void flib_netconn_onAdminAccess(NetconnPtr conn, VoidCallback callback, Pointer context);
+void flib_netconn_onServerVar(NetconnPtr conn, StrStrCallback callback, Pointer context);
+
+// ipc/gameconn.h
+GameconnPtr flib_gameconn_create(String playerName, GameSetupPtr setup, boolean netgame);
+GameconnPtr flib_gameconn_create_playdemo(Buffer demo, NativeLong size);
+GameconnPtr flib_gameconn_create_loadgame(String playerName, Buffer save, NativeLong size);
+GameconnPtr flib_gameconn_create_campaign(String playerName, String seed, String script);
+
+void flib_gameconn_destroy(GameconnPtr conn);
+int flib_gameconn_getport(GameconnPtr conn);
+void flib_gameconn_tick(GameconnPtr conn);
+
+int flib_gameconn_send_enginemsg(GameconnPtr conn, Buffer data, NativeLong len);
+int flib_gameconn_send_textmsg(GameconnPtr conn, int msgtype, String msg);
+int flib_gameconn_send_chatmsg(GameconnPtr conn, String playername, String msg);
+int flib_gameconn_send_quit(GameconnPtr conn);
+
+void flib_gameconn_onConnect(GameconnPtr conn, VoidCallback callback, Pointer context);
+void flib_gameconn_onDisconnect(GameconnPtr conn, IntCallback callback, Pointer context);
+void flib_gameconn_onErrorMessage(GameconnPtr conn, StrCallback callback, Pointer context);
+void flib_gameconn_onChat(GameconnPtr conn, StrBoolCallback callback, Pointer context);
+void flib_gameconn_onGameRecorded(GameconnPtr conn, BytesBoolCallback callback, Pointer context);
+void flib_gameconn_onEngineMessage(GameconnPtr conn, BytesCallback callback, Pointer context);
+
+// ipc/mapconn.h
+MapconnPtr flib_mapconn_create(MapRecipePtr mapdesc);
+void flib_mapconn_destroy(MapconnPtr conn);
+int flib_mapconn_getport(MapconnPtr conn);
+void flib_mapconn_onSuccess(MapconnPtr conn, MapimageCallback callback, Pointer context);
+void flib_mapconn_onFailure(MapconnPtr conn, StrCallback callback, Pointer context);
+void flib_mapconn_tick(MapconnPtr conn);
+
+// model/scheme.h
+MetaschemePtr flib_metascheme_from_ini(String filename);
+MetaschemePtr flib_metascheme_retain(MetaschemePtr metainfo);
+void flib_metascheme_release(MetaschemePtr metainfo);
+
+// model/schemelist.h
+SchemelistPtr flib_schemelist_from_ini(MetaschemePtr meta, String filename);
+int flib_schemelist_to_ini(String filename, SchemelistPtr list);
+void flib_schemelist_destroy(SchemelistPtr list);
+
+// model/team.h
+TeamPtr flib_team_from_ini(String filename);
+int flib_team_to_ini(String filename, TeamPtr team);
+void flib_team_destroy(TeamPtr team);
+
+// model/weapon.h
+WeaponsetListPtr flib_weaponsetlist_from_ini(String filename);
+int flib_weaponsetlist_to_ini(String filename, WeaponsetListPtr weaponsets);
+void flib_weaponsetlist_destroy(WeaponsetListPtr list);
+
+// util/logging.h
+void flib_log_setLevel(int level);
+void flib_log_setCallback(LogCallback callback);
--- a/project_files/frontlib/frontlib.h	Sun Aug 12 22:21:09 2012 +0200
+++ b/project_files/frontlib/frontlib.h	Sun Aug 12 22:37:57 2012 +0200
@@ -30,6 +30,7 @@
 #include "ipc/mapconn.h"
 #include "net/netconn.h"
 #include "util/logging.h"
+#include "model/schemelist.h"
 
 /**
  * Call this function before anything else in this library.
--- a/project_files/frontlib/ipc/gameconn.c	Sun Aug 12 22:21:09 2012 +0200
+++ b/project_files/frontlib/ipc/gameconn.c	Sun Aug 12 22:37:57 2012 +0200
@@ -117,14 +117,14 @@
 	return result;
 }
 
-flib_gameconn *flib_gameconn_create_playdemo(const uint8_t *demo, size_t size) {
-	if(log_badargs_if(demo==NULL && size>0)) {
+flib_gameconn *flib_gameconn_create_playdemo(const uint8_t *demoFileContent, size_t size) {
+	if(log_badargs_if(demoFileContent==NULL && size>0)) {
 		return NULL;
 	}
 	flib_gameconn *result = NULL;
 	flib_gameconn *tempConn = flib_gameconn_create_partial(false, "Player", false);
 	if(tempConn) {
-		if(!flib_vector_append(tempConn->configBuffer, demo, size)) {
+		if(!flib_vector_append(tempConn->configBuffer, demoFileContent, size)) {
 			result = tempConn;
 			tempConn = NULL;
 		}
@@ -133,14 +133,14 @@
 	return result;
 }
 
-flib_gameconn *flib_gameconn_create_loadgame(const char *playerName, const uint8_t *save, size_t size) {
-	if(log_badargs_if(save==NULL && size>0)) {
+flib_gameconn *flib_gameconn_create_loadgame(const char *playerName, const uint8_t *saveFileContent, size_t size) {
+	if(log_badargs_if(saveFileContent==NULL && size>0)) {
 		return NULL;
 	}
 	flib_gameconn *result = NULL;
 	flib_gameconn *tempConn = flib_gameconn_create_partial(true, playerName, false);
 	if(tempConn) {
-		if(!flib_vector_append(tempConn->configBuffer, save, size)) {
+		if(!flib_vector_append(tempConn->configBuffer, saveFileContent, size)) {
 			result = tempConn;
 			tempConn = NULL;
 		}
@@ -280,6 +280,18 @@
 	return -1;
 }
 
+int flib_gameconn_send_quit(flib_gameconn *conn) {
+	if(log_badargs_if(conn==NULL)) {
+		return -1;
+	}
+	const char *msg = "\x07""efinish";
+	if(!flib_ipcbase_send_raw(conn->ipcBase, msg, msg[0]+1)) {
+		demo_append(conn, msg, msg[0]+1);
+		return 0;
+	}
+	return -1;
+}
+
 /**
  * This macro generates a callback setter function. It uses the name of the callback to
  * automatically generate the function name and the fields to set, so a consistent naming
--- a/project_files/frontlib/ipc/gameconn.h	Sun Aug 12 22:21:09 2012 +0200
+++ b/project_files/frontlib/ipc/gameconn.h	Sun Aug 12 22:37:57 2012 +0200
@@ -17,6 +17,26 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
+/**
+ * This file contains functions for starting and interacting with a game run by the engine.
+ * The general usage is to first create a gameconn object by calling one of the flib_gameconn_create
+ * functions. That will cause the frontlib to listen on a random port which can be queried using
+ * flib_gameconn_getport(). You should also register your callback functions right at the start
+ * to ensure you don't miss any callbacks.
+ *
+ * Next, start the engine (that part is up to you) with the appropriate command line arguments
+ * for starting a game.
+ *
+ * In order to allow the gameconn to run, you should regularly call flib_gameconn_tick(), which
+ * performs network I/O and calls your callbacks on interesting events.
+ *
+ * Once the engine connects, the gameconn will send it the required commands for starting the
+ * game you requested in your flib_gameconn_create call.
+ *
+ * When the game is finished (or the connection is lost), you will receive the onDisconnect
+ * message. This is the signal to destroy the gameconn and stop calling tick().
+ */
+
 #ifndef GAMECONN_H_
 #define GAMECONN_H_
 
@@ -26,6 +46,9 @@
 #include <stdint.h>
 #include <stdbool.h>
 
+/*
+ * Different reasons for a disconnect. Only GAME_END_FINISHED signals a correctly completed game.
+ */
 #define GAME_END_FINISHED 0
 #define GAME_END_INTERRUPTED 1
 #define GAME_END_HALTED 2
@@ -33,11 +56,33 @@
 
 typedef struct _flib_gameconn flib_gameconn;
 
+/**
+ * Create a gameconn that will start a local or network game with the indicated configuration.
+ */
 flib_gameconn *flib_gameconn_create(const char *playerName, const flib_gamesetup *setup, bool netgame);
-flib_gameconn *flib_gameconn_create_playdemo(const uint8_t *demo, size_t size);
-flib_gameconn *flib_gameconn_create_loadgame(const char *playerName, const uint8_t *save, size_t size);
+
+/**
+ * Create a gameconn that will play back a demo.
+ */
+flib_gameconn *flib_gameconn_create_playdemo(const uint8_t *demoFileContent, size_t size);
+
+/**
+ * Create a gameconn that will continue from a saved game.
+ */
+flib_gameconn *flib_gameconn_create_loadgame(const char *playerName, const uint8_t *saveFileContent, size_t size);
+
+/**
+ * Create a gameconn that will start a campaign or training mission with the indicated script.
+ * seed is the random seed to use as entropy source (any string).
+ * script is the path and filename of a Campaign or Training script, relative to the Data directory
+ * (e.g. "Missions/Training/Basic_Training_-_Bazooka.lua")
+ */
 flib_gameconn *flib_gameconn_create_campaign(const char *playerName, const char *seed, const char *script);
 
+/**
+ * Release all resources of this gameconn, including the network connection, and free its memory.
+ * It is safe to call this function from a callback.
+ */
 void flib_gameconn_destroy(flib_gameconn *conn);
 
 /**
@@ -52,48 +97,76 @@
  */
 void flib_gameconn_tick(flib_gameconn *conn);
 
+/**
+ * Send an engine message to the engine. Only needed in net games, where you receive engine
+ * messages from the server and have to pass them here.
+ */
 int flib_gameconn_send_enginemsg(flib_gameconn *conn, const uint8_t *data, size_t len);
+
+/**
+ * Send an info message to the engine that will be displayed in the game's chatlog.
+ * The msgtype determines the color of the message;  in the QTFrontend, info messages and
+ * normal chat messages use 1, emote-messages (those starting with /me) use 2, and
+ * join/leave messages use 3. You should use flib_gameconn_send_chatmsg for chat messages
+ * though because it automatically formats /me messages.
+ *
+ * Generally only needed in net games.
+ */
 int flib_gameconn_send_textmsg(flib_gameconn *conn, int msgtype, const char *msg);
+
+/**
+ * Send a chat message to be displayed in the game's chatlog. Messages starting with /me are
+ * automatically formatted correctly.
+ *
+ * Generally only needed in net games.
+ */
 int flib_gameconn_send_chatmsg(flib_gameconn *conn, const char *playername, const char *msg);
 
 /**
- * handleConnect(void *context)
+ * Request the engine to stop the game.
+ * You can use this to shut down a game early without directly killing the engine process.
+ */
+int flib_gameconn_send_quit(flib_gameconn *conn);
+
+/**
+ * Expected callback signature: void handleConnect(void *context)
+ * The engine has successfully connected. You don't have to react to this in any way.
  */
 void flib_gameconn_onConnect(flib_gameconn *conn, void (*callback)(void* context), void* context);
 
 /**
- * handleDisconnect(void *context, int reason)
+ * Expected callback signature: void handleDisconnect(void *context, int reason)
+ * The connection to the engine was closed, either because the game has ended normally, or
+ * because it was interrupted/halted, or because of an error. The reason is provided as one
+ * of the GAME_END_xxx constants.
+ *
+ * You should destroy the gameconn and - in a netgame - notify the server that the game has ended.
  */
 void flib_gameconn_onDisconnect(flib_gameconn *conn, void (*callback)(void* context, int reason), void* context);
 
 /**
- * Receives error messages sent by the engine
- * handleErrorMessage(void* context, const char *msg)
+ * Expected callback signature: void handleErrorMessage(void* context, const char *msg)
+ * The engine sent an error message, you should probably display it to the user or at least log it.
  */
 void flib_gameconn_onErrorMessage(flib_gameconn *conn, void (*callback)(void* context, const char *msg), void* context);
 
 /**
- * handleChat(void* context, const char *msg, bool teamchat)
+ * Expected callback signature: void handleChat(void* context, const char *msg, bool teamchat)
+ * The player entered a chat or teamchat message. In a netgame, you should send it on to the server.
  */
 void flib_gameconn_onChat(flib_gameconn *conn, void (*callback)(void* context, const char *msg, bool teamchat), void* context);
 
 /**
- * Called when the game ends
- * handleGameRecorded(void *context, const uint8_t *record, int size, bool isSavegame)
+ * Expected callback signature: void handleGameRecorded(void *context, const uint8_t *record, size_t size, bool isSavegame)
+ * The game has stopped, and a demo or savegame is available. You can store it in a file and later pass it back
+ * to the engine to either watch a replay (if it's a demo) or to continue playing (if it's a savegame).
  */
 void flib_gameconn_onGameRecorded(flib_gameconn *conn, void (*callback)(void *context, const uint8_t *record, size_t size, bool isSavegame), void* context);
 
 /**
- * Called when the game ends
- * TODO handleStats(???)
- */
-
-/**
- * ...needs to be passed on to the server in a net game
- * handleEngineMessage(void *context, const uint8_t *em, size_t size)
+ * Expected callback signature: void handleEngineMessage(void *context, const uint8_t *em, size_t size)
+ * The engine has generated a message with player input. In a netgame, you should send it on to the server.
  */
 void flib_gameconn_onEngineMessage(flib_gameconn *conn, void (*callback)(void *context, const uint8_t *em, size_t size), void* context);
 
-// TODO efinish
-
 #endif
--- a/project_files/frontlib/ipc/ipcprotocol.c	Sun Aug 12 22:21:09 2012 +0200
+++ b/project_files/frontlib/ipc/ipcprotocol.c	Sun Aug 12 22:37:57 2012 +0200
@@ -80,8 +80,8 @@
 			 */
 			const char *edraw = "edraw ";
 			int edrawlen = strlen(edraw);
-			for(int offset=0; offset<map->drawDataSize; offset+=200) {
-				int bytesRemaining = map->drawDataSize-offset;
+			for(size_t offset=0; offset<map->drawDataSize; offset+=200) {
+				size_t bytesRemaining = map->drawDataSize-offset;
 				int fragmentsize = bytesRemaining < 200 ? bytesRemaining : 200;
 				uint8_t messagesize = edrawlen + fragmentsize;
 				error |= flib_vector_append(tempvector, &messagesize, 1);
@@ -111,10 +111,19 @@
 
 int flib_ipc_append_script(flib_vector *vec, const char *script) {
 	int result = -1;
-	char *copy = flib_strdupnull(script);
+	if(!log_badargs_if2(vec==NULL, script==NULL)) {
+		result = flib_ipc_append_message(vec, "escript %s", script);
+	}
+	return result;
+}
+
+int flib_ipc_append_style(flib_vector *vec, const char *style) {
+	int result = -1;
+	char *copy = flib_strdupnull(style);
 	if(!log_badargs_if(vec==NULL) && copy) {
 		if(!strcmp("Normal", copy)) {
 			// "Normal" means no gametype script
+			// TODO if an empty script called "Normal" is added to the scripts directory this can be removed
 			result = 0;
 		} else {
 			size_t len = strlen(copy);
@@ -192,7 +201,7 @@
 	}
 }
 
-int flib_ipc_append_addteam(flib_vector *vec, const flib_team *team, bool perHogAmmo, bool noAmmoStore) {
+static 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(!log_badargs_if2(vec==NULL, team==NULL) && tempvector) {
@@ -206,11 +215,11 @@
 
 		char md5Hex[33];
 		calculateMd5Hex(team->ownerName ? team->ownerName : "", md5Hex);
-		if(team->colorIndex<0 || team->colorIndex>=flib_teamcolor_defaults_len) {
+		if(team->colorIndex<0 || team->colorIndex>=flib_teamcolor_count) {
 			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", md5Hex, flib_teamcolor_defaults[team->colorIndex], team->name);
+			error |= flib_ipc_append_message(tempvector, "eaddteam %s %"PRIu32" %s", md5Hex, flib_teamcolors[team->colorIndex], team->name);
 		}
 
 		if(team->remoteDriven) {
@@ -258,8 +267,8 @@
 		if(setup->map) {
 			error |= flib_ipc_append_mapconf(tempvector, setup->map, false);
 		}
-		if(setup->script) {
-			error |= flib_ipc_append_script(tempvector, setup->script);
+		if(setup->style) {
+			error |= flib_ipc_append_style(tempvector, setup->style);
 		}
 		if(setup->gamescheme) {
 			error |= flib_ipc_append_gamescheme(tempvector, setup->gamescheme);
--- a/project_files/frontlib/ipc/ipcprotocol.h	Sun Aug 12 22:21:09 2012 +0200
+++ b/project_files/frontlib/ipc/ipcprotocol.h	Sun Aug 12 22:37:57 2012 +0200
@@ -58,7 +58,7 @@
 int flib_ipc_append_seed(flib_vector *vec, const char *seed);
 
 /**
- * Append a script message to the buffer.
+ * Append a script to the buffer (e.g. "Missions/Training/Basic_Training_-_Bazooka.lua")
  *
  * Returns nonzero if something goes wrong. In that case the buffer
  * contents are unaffected.
@@ -66,15 +66,28 @@
 int flib_ipc_append_script(flib_vector *vec, const char *script);
 
 /**
+ * Append a game style to the buffer. (e.g. "Capture the Flag")
+ *
+ * Returns nonzero if something goes wrong. In that case the buffer
+ * contents are unaffected.
+ */
+int flib_ipc_append_style(flib_vector *vec, const char *style);
+
+/**
  * Append the game scheme to the buffer.
  *
  * Returns nonzero if something goes wrong. In that case the buffer
  * contents are unaffected.
  */
-int flib_ipc_append_gamescheme(flib_vector *vec, const flib_scheme *cfg);
+int flib_ipc_append_gamescheme(flib_vector *vec, const flib_scheme *scheme);
 
-int flib_ipc_append_addteam(flib_vector *vec, const flib_team *team, bool perHogAmmo, bool noAmmoStore);
-
+/**
+ * Append the entire game config to the buffer (including the final "!" that marks the
+ * end of configuration data for the engine)
+ *
+ * Returns nonzero if something goes wrong. In that case the buffer
+ * contents are unaffected.
+ */
 int flib_ipc_append_fullconfig(flib_vector *vec, const flib_gamesetup *setup, bool netgame);
 
 #endif /* IPCPROTOCOL_H_ */
--- a/project_files/frontlib/ipc/mapconn.h	Sun Aug 12 22:21:09 2012 +0200
+++ b/project_files/frontlib/ipc/mapconn.h	Sun Aug 12 22:37:57 2012 +0200
@@ -17,6 +17,24 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
+/**
+ * Functions for querying a map preview from the engine, which includes both a two-color image
+ * and the number of hogs this map is suitable for.
+ *
+ * The general usage is to first create a mapconn object by calling flib_mapconn_create.
+ * That will cause the frontlib to listen on a random port which can be queried using
+ * flib_mapconn_getport(). You should also register your callback functions right at the start
+ * to ensure you don't miss any callbacks.
+ *
+ * Next, start the engine (that part is up to you) with the appropriate command line arguments
+ * for a map preview request.
+ *
+ * In order to allow the mapconn to run, you should regularly call flib_mapconn_tick(), which
+ * performs network I/O and calls your callbacks if the map has been generated or an error
+ * has occurred. Once either the onSuccess or onFailure callback is called, you should destroy
+ * the mapconn and stop calling tick().
+ */
+
 #ifndef IPC_MAPCONN_H_
 #define IPC_MAPCONN_H_
 
@@ -38,7 +56,7 @@
  *
  * 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).
+ * map information (e.g. using flib_mapcfg_read).
  *
  * No NULL parameters allowed, returns NULL on failure.
  * Use flib_mapconn_destroy to free the returned object.
@@ -59,7 +77,6 @@
 
 /**
  * Set a callback which will receive the rendered map if the rendering succeeds.
- * You can pass callback=NULL to unset a callback.
  *
  * Expected callback signature:
  * void handleSuccess(void *context, const uint8_t *bitmap, int numHedgehogs)
@@ -77,7 +94,6 @@
 
 /**
  * Set a callback which will receive an error message if rendering fails.
- * You can pass callback=NULL to unset a callback.
  *
  * Expected callback signature:
  * void handleFailure(void *context, const char *errormessage)
--- a/project_files/frontlib/model/gamesetup.c	Sun Aug 12 22:21:09 2012 +0200
+++ b/project_files/frontlib/model/gamesetup.c	Sun Aug 12 22:37:57 2012 +0200
@@ -24,9 +24,9 @@
 
 void flib_gamesetup_destroy(flib_gamesetup *gamesetup) {
 	if(gamesetup) {
-		free(gamesetup->script);
-		flib_scheme_release(gamesetup->gamescheme);
-		flib_map_release(gamesetup->map);
+		free(gamesetup->style);
+		flib_scheme_destroy(gamesetup->gamescheme);
+		flib_map_destroy(gamesetup->map);
 		flib_teamlist_destroy(gamesetup->teamlist);
 		free(gamesetup);
 	}
@@ -39,11 +39,11 @@
 
 	flib_gamesetup *result = flib_calloc(1, sizeof(flib_gamesetup));
 	if(result) {
-		result->script = flib_strdupnull(setup->script);
+		result->style = flib_strdupnull(setup->style);
 		result->gamescheme = flib_scheme_copy(setup->gamescheme);
 		result->map = flib_map_copy(setup->map);
 		result->teamlist = flib_teamlist_copy(setup->teamlist);
-		if((setup->script && !result->script)
+		if((setup->style && !result->style)
 				|| (setup->gamescheme && !result->gamescheme)
 				|| (setup->map && !result->map)
 				|| (setup->teamlist && !result->teamlist)) {
--- a/project_files/frontlib/model/gamesetup.h	Sun Aug 12 22:21:09 2012 +0200
+++ b/project_files/frontlib/model/gamesetup.h	Sun Aug 12 22:37:57 2012 +0200
@@ -18,7 +18,7 @@
  */
 
 /**
- * A complete game configuration that contains all settings for a
+ * A complete game configuration that contains all settings the engine needs to start a
  * local or networked game.
  */
 
@@ -31,7 +31,7 @@
 #include "teamlist.h"
 
 typedef struct {
-    char *script;
+    char *style;				// e.g. "Capture the Flag"
     flib_scheme *gamescheme;
     flib_map *map;
 	flib_teamlist *teamlist;
--- a/project_files/frontlib/model/map.c	Sun Aug 12 22:21:09 2012 +0200
+++ b/project_files/frontlib/model/map.c	Sun Aug 12 22:37:57 2012 +0200
@@ -26,16 +26,6 @@
 
 #include <stdlib.h>
 
-static void flib_map_destroy(flib_map *map) {
-	if(map) {
-		free(map->seed);
-		free(map->drawData);
-		free(map->name);
-		free(map->theme);
-		free(map);
-	}
-}
-
 flib_map *flib_map_create_regular(const char *seed, const char *theme, int templateFilter) {
 	if(log_badargs_if2(seed==NULL, theme==NULL)) {
 		return NULL;
@@ -74,7 +64,7 @@
 }
 
 flib_map *flib_map_create_drawn(const char *seed, const char *theme, const uint8_t *drawData, size_t drawDataSize) {
-	if(log_badargs_if3(seed==NULL, theme==NULL, drawData==NULL && drawDataSize>0)) {
+	if(log_badargs_if3(seed==NULL, theme==NULL, drawData==NULL)) {
 		return NULL;
 	}
 	flib_map newmap = {0};
@@ -90,7 +80,7 @@
 flib_map *flib_map_copy(const flib_map *map) {
 	flib_map *result = NULL;
 	if(map) {
-		flib_map *newmap = flib_map_retain(flib_calloc(1, sizeof(flib_map)));
+		flib_map *newmap = flib_calloc(1, sizeof(flib_map));
 		if(newmap) {
 			newmap->mapgen = map->mapgen;
 			newmap->drawDataSize = map->drawDataSize;
@@ -105,20 +95,17 @@
 				newmap = NULL;
 			}
 		}
-		flib_map_release(newmap);
+		flib_map_destroy(newmap);
 	}
 	return result;
 }
 
-flib_map *flib_map_retain(flib_map *map) {
+void flib_map_destroy(flib_map *map) {
 	if(map) {
-		flib_retain(&map->_referenceCount, "flib_map");
-	}
-	return map;
-}
-
-void flib_map_release(flib_map *map) {
-	if(map && flib_release(&map->_referenceCount, "flib_map")) {
-		flib_map_destroy(map);
+		free(map->seed);
+		free(map->drawData);
+		free(map->name);
+		free(map->theme);
+		free(map);
 	}
 }
--- a/project_files/frontlib/model/map.h	Sun Aug 12 22:21:09 2012 +0200
+++ b/project_files/frontlib/model/map.h	Sun Aug 12 22:37:57 2012 +0200
@@ -45,22 +45,20 @@
 
 /**
  * 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.
+ * exactly recreate a particular map.
  *
  * 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 maps
+	char *name;				// The name of the map for MAPGEN_NAMED (e.g. "Cogs"), otherwise one of "+rnd+", "+maze+" or "+drawn+".
+	char *seed;				// Used for all maps. This is a random seed for all (non-AI) entropy in the round. Typically a random UUID, but can be any string.
+	char *theme;			// Used for all maps. This is the name of a directory in Data/Themes (e.g. "Beach")
 	uint8_t *drawData;		// Used for MAPGEN_DRAWN
-	int drawDataSize;		// Used for MAPGEN_DRAWN TODO size_t
-	int templateFilter;		// Used for MAPGEN_REGULAR
-	int mazeSize;			// Used for MAPGEN_MAZE
+	size_t drawDataSize;	// Used for MAPGEN_DRAWN
+	int templateFilter;		// Used for MAPGEN_REGULAR. One of the TEMPLATEFILTER_xxx constants.
+	int mazeSize;			// Used for MAPGEN_MAZE. One of the MAZE_SIZE_xxx constants.
 } flib_map;
 
 /**
@@ -108,15 +106,9 @@
 flib_map *flib_map_copy(const flib_map *map);
 
 /**
- * Increase the reference count of the object. Call this if you store a pointer to it somewhere.
- * Returns the parameter.
- */
-flib_map *flib_map_retain(flib_map *map);
-
-/**
  * Decrease the reference count of the object and free it if this was the last reference.
  */
-void flib_map_release(flib_map *map);
+void flib_map_destroy(flib_map *map);
 
 
 #endif
--- a/project_files/frontlib/model/scheme.c	Sun Aug 12 22:21:09 2012 +0200
+++ b/project_files/frontlib/model/scheme.c	Sun Aug 12 22:37:57 2012 +0200
@@ -48,16 +48,6 @@
 	}
 }
 
-static void flib_scheme_destroy(flib_scheme* scheme) {
-	if(scheme) {
-		flib_metascheme_release(scheme->meta);
-		free(scheme->mods);
-		free(scheme->settings);
-		free(scheme->name);
-		free(scheme);
-	}
-}
-
 static flib_metascheme *flib_metascheme_from_ini_handleError(flib_metascheme *result, flib_ini *ini) {
 	flib_metascheme_destroy(result);
 	flib_ini_destroy(ini);
@@ -166,7 +156,7 @@
 }
 
 flib_scheme *flib_scheme_create(flib_metascheme *meta, const char *schemeName) {
-	flib_scheme *result = flib_scheme_retain(flib_calloc(1, sizeof(flib_scheme)));
+	flib_scheme *result = flib_calloc(1, sizeof(flib_scheme));
 	if(log_badargs_if2(meta==NULL, schemeName==NULL) || result==NULL) {
 		return NULL;
 	}
@@ -199,16 +189,13 @@
 	return result;
 }
 
-flib_scheme *flib_scheme_retain(flib_scheme *scheme) {
+void flib_scheme_destroy(flib_scheme* scheme) {
 	if(scheme) {
-		flib_retain(&scheme->_referenceCount, "flib_scheme");
-	}
-	return scheme;
-}
-
-void flib_scheme_release(flib_scheme *scheme) {
-	if(scheme && flib_release(&scheme->_referenceCount, "flib_scheme")) {
-		flib_scheme_destroy(scheme);
+		flib_metascheme_release(scheme->meta);
+		free(scheme->mods);
+		free(scheme->settings);
+		free(scheme->name);
+		free(scheme);
 	}
 }
 
--- a/project_files/frontlib/model/scheme.h	Sun Aug 12 22:21:09 2012 +0200
+++ b/project_files/frontlib/model/scheme.h	Sun Aug 12 22:37:57 2012 +0200
@@ -19,6 +19,10 @@
 
 /**
  * Data structures for game scheme information.
+ *
+ * The scheme consists of settings (integers) and mods (booleans). These are not fixed, but
+ * described in a "metascheme" file, which describes how each setting and mod is sent to the
+ * engine, and in which order they appear in the network protocol.
  */
 
 #ifndef SCHEME_H_
@@ -27,18 +31,19 @@
 #include <stdbool.h>
 
 typedef struct {
-    char *name;
-    char *engineCommand;
-    bool maxMeansInfinity;
-    bool times1000;
-    int min;
-    int max;
-    int def;
+    char *name;				// A name identifying this setting (used as key in the schemes file)
+    char *engineCommand;	// The command needed to send the setting to the engine. May be null if the setting is not sent to the engine (for the "health" setting)
+    bool maxMeansInfinity;	// If true, send a very high number to the engine if the setting is equal to its maximum
+    bool times1000;			// If true (for time-based settings), multiply the setting by 1000 before sending it to the engine.
+    int min;				// The smallest allowed value
+    int max;				// The highest allowed value
+    int def;				// The default value
 } flib_metascheme_setting;
 
 typedef struct {
-    char *name;
-    int bitmaskIndex;
+    char *name;				// A name identifying this mod (used as key in the schemes file)
+    int bitmaskIndex;		// Mods are sent to the engine in a single integer, this field describes which bit of that integer is used
+    						// for this particular mod.
 } flib_metascheme_mod;
 
 /**
@@ -53,8 +58,11 @@
 	flib_metascheme_mod *mods;
 } flib_metascheme;
 
+/**
+ * The settings and mods arrays have the same number and order of elements
+ * as the corresponding arrays in the metascheme.
+ */
 typedef struct {
-	int _referenceCount;
 	flib_metascheme *meta;
 
     char *name;
@@ -93,15 +101,9 @@
 flib_scheme *flib_scheme_copy(const flib_scheme *scheme);
 
 /**
- * Increase the reference count of the object. Call this if you store a pointer to it somewhere.
- * Returns the parameter.
- */
-flib_scheme *flib_scheme_retain(flib_scheme *scheme);
-
-/**
  * Decrease the reference count of the object and free it if this was the last reference.
  */
-void flib_scheme_release(flib_scheme* scheme);
+void flib_scheme_destroy(flib_scheme* scheme);
 
 /**
  * Retrieve a mod setting by its name. If the mod is not found, logs an error and returns false.
--- a/project_files/frontlib/model/schemelist.c	Sun Aug 12 22:21:09 2012 +0200
+++ b/project_files/frontlib/model/schemelist.c	Sun Aug 12 22:37:57 2012 +0200
@@ -72,13 +72,14 @@
 	if(schemeNameKey) {
 		char *schemeName = NULL;
 		if(!flib_ini_get_str_opt(ini, &schemeName, schemeNameKey, "Unnamed")) {
-			flib_scheme *scheme = flib_scheme_create(meta, schemeName);
-			if(scheme) {
-				if(!readSettingsFromIni(ini, scheme, index) && !readModsFromIni(ini, scheme, index)) {
-					result = flib_scheme_retain(scheme);
+			flib_scheme *tmpScheme = flib_scheme_create(meta, schemeName);
+			if(tmpScheme) {
+				if(!readSettingsFromIni(ini, tmpScheme, index) && !readModsFromIni(ini, tmpScheme, index)) {
+					result = tmpScheme;
+					tmpScheme = NULL;
 				}
 			}
-			flib_scheme_release(scheme);
+			flib_scheme_destroy(tmpScheme);
 		}
 		free(schemeName);
 	}
@@ -118,11 +119,10 @@
 	for(int i=0; i<schemeCount; i++) {
 		flib_scheme *scheme = readSchemeFromIni(meta, ini, i);
 		if(!scheme || flib_schemelist_insert(list, scheme, i)) {
-			flib_scheme_release(scheme);
+			flib_scheme_destroy(scheme);
 			flib_log_e("Error reading scheme %i from config file %s.", i, filename);
 			return fromIniHandleError(list, ini);
 		}
-		flib_scheme_release(scheme);
 	}
 
 
@@ -130,7 +130,7 @@
 	return list;
 }
 
-static int writeSchemeToIni(flib_scheme *scheme, flib_ini *ini, int index) {
+static int writeSchemeToIni(const flib_scheme *scheme, flib_ini *ini, int index) {
 	flib_metascheme *meta = scheme->meta;
 	bool error = false;
 
@@ -179,7 +179,7 @@
 void flib_schemelist_destroy(flib_schemelist *list) {
 	if(list) {
 		for(int i=0; i<list->schemeCount; i++) {
-			flib_scheme_release(list->schemes[i]);
+			flib_scheme_destroy(list->schemes[i]);
 		}
 		free(list->schemes);
 		free(list);
@@ -203,7 +203,6 @@
 int flib_schemelist_insert(flib_schemelist *list, flib_scheme *cfg, int pos) {
 	if(!log_badargs_if2(list==NULL, cfg==NULL)
 			&& !insertScheme(&list->schemes, &list->schemeCount, cfg, pos)) {
-		flib_scheme_retain(cfg);
 		return 0;
 	}
 	return -1;
@@ -213,7 +212,7 @@
 	if(!log_badargs_if(list==NULL)) {
 		flib_scheme *elem = list->schemes[pos];
 		if(!deleteScheme(&list->schemes, &list->schemeCount, pos)) {
-			flib_scheme_release(elem);
+			flib_scheme_destroy(elem);
 			return 0;
 		}
 	}
--- a/project_files/frontlib/model/schemelist.h	Sun Aug 12 22:21:09 2012 +0200
+++ b/project_files/frontlib/model/schemelist.h	Sun Aug 12 22:37:57 2012 +0200
@@ -19,7 +19,7 @@
 
 /**
  * Functions for managing a list of schemes.
- * This is in here because the scheme config file of the QtFrontend (which we are staying compatble with) contains
+ * This is in here because the scheme config file of the QtFrontend (which we are staying compatible with) contains
  * all the schemes at once, so we need functions to work with a list like that.
  */
 
@@ -53,14 +53,14 @@
 /**
  * Insert a new scheme into the list at position pos, moving all higher schemes to make place.
  * pos must be at least 0 (insert at the start) and at most list->schemeCount (insert at the end).
- * The scheme is retained automatically.
+ * Ownership of the scheme is transferred to the list.
  * Returns 0 on success.
  */
 int flib_schemelist_insert(flib_schemelist *list, flib_scheme *cfg, int pos);
 
 /**
  * Delete a scheme from the list at position pos, moving down all higher schemes.
- * The scheme is released automatically.
+ * The scheme is destroyed.
  * Returns 0 on success.
  */
 int flib_schemelist_delete(flib_schemelist *list, int pos);
@@ -71,7 +71,7 @@
 flib_scheme *flib_schemelist_find(flib_schemelist *list, const char *name);
 
 /**
- * Free this schemelist.
+ * Free this schemelist and all contained schemes
  */
 void flib_schemelist_destroy(flib_schemelist *list);
 
--- a/project_files/frontlib/model/team.h	Sun Aug 12 22:21:09 2012 +0200
+++ b/project_files/frontlib/model/team.h	Sun Aug 12 22:37:57 2012 +0200
@@ -24,7 +24,7 @@
  * extra information about teams. For example, the weaponset is important
  * to the engine, but not for ini reading/writing, and with the team statistics it is the
  * other way around. To keep things simple, the data structure can hold all information
- * used in any context. On the downside, tat means we can't use static typing to ensure
+ * used in any context. On the downside, that means we can't use static typing to ensure
  * that team information is "complete" for a particular purpose.
  */
 #ifndef TEAM_H_
@@ -39,6 +39,9 @@
 
 #define TEAM_DEFAULT_HEALTH 100
 
+/**
+ * Struct representing a single keybinding.
+ */
 typedef struct {
 	char *action;
 	char *binding;
@@ -46,7 +49,7 @@
 
 typedef struct {
 	char *name;
-	char *hat;
+	char *hat;			// e.g. hair_yellow; References a .png file in Data/Graphics/Hats
 
 	// Statistics. They are irrelevant for the engine or server,
 	// but provided for ini reading/writing by the frontend.
@@ -55,7 +58,7 @@
 	int deaths;
 	int suicides;
 
-	int difficulty;
+	int difficulty;		// 0 = human, 1 = most difficult bot ... 5 = least difficult bot (somewhat counterintuitive)
 
 	// Transient setting used in game setup
 	int initialHealth;
@@ -65,10 +68,10 @@
 typedef struct {
 	flib_hog hogs[HEDGEHOGS_PER_TEAM];
 	char *name;
-	char *grave;
-	char *fort;
-	char *voicepack;
-	char *flag;
+	char *grave;		// e.g. "Bone"; References a .png file in Data/Graphics/Graves
+	char *fort;			// e.g. "Castle"; References a series of files in Data/Forts
+	char *voicepack;	// e.g. "Classic"; References a directory in Data/Sounds/voices
+	char *flag;			// e.g. "hedgewars"; References a .png file in Data/Graphics/Flags
 
 	flib_binding *bindings;
 	int bindingCount;
@@ -81,9 +84,9 @@
 
 	// Transient settings used in game setup
 	int colorIndex;		// Index into a color table
-	int hogsInGame;
-	bool remoteDriven;
-	char *ownerName;
+	int hogsInGame;		// The number of hogs that will actually play
+	bool remoteDriven;	// true for non-local teams in a network game
+	char *ownerName;	// Username of the owner of a team in a network game
 } flib_team;
 
 /**
--- a/project_files/frontlib/model/weapon.h	Sun Aug 12 22:21:09 2012 +0200
+++ b/project_files/frontlib/model/weapon.h	Sun Aug 12 22:37:57 2012 +0200
@@ -23,10 +23,12 @@
 #include "../hwconsts.h"
 
 /**
- * These values are all in the range 0..9
+ * These values are all ASCII characters in the range '0'..'9'
+ * The fields are zero-terminated so they can easily be used as strings.
  *
  * For loadout, 9 means inifinite ammo.
  * For the other setting, 9 is invalid.
+ * TODO stop reference counting, it complects everything
  */
 typedef struct {
 	int _referenceCount;
--- a/project_files/frontlib/net/netconn.c	Sun Aug 12 22:21:09 2012 +0200
+++ b/project_files/frontlib/net/netconn.c	Sun Aug 12 22:37:57 2012 +0200
@@ -18,8 +18,6 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  */
 
-// TODO: Check the state transitions. Document with a diagram or something
-
 #include "netconn_internal.h"
 #include "netprotocol.h"
 #include "../util/logging.h"
@@ -53,7 +51,7 @@
 			newConn->teamlist.teamCount = 0;
 			newConn->teamlist.teams = NULL;
 			newConn->scheme = NULL;
-			newConn->script = NULL;
+			newConn->style = NULL;
 			newConn->weaponset = NULL;
 
 			newConn->running = false;
@@ -86,11 +84,11 @@
 
 			flib_metascheme_release(conn->metaCfg);
 
-			flib_map_release(conn->map);
+			flib_map_destroy(conn->map);
 			flib_teamlist_clear(&conn->pendingTeamlist);
 			flib_teamlist_clear(&conn->teamlist);
-			flib_scheme_release(conn->scheme);
-			free(conn->script);
+			flib_scheme_destroy(conn->scheme);
+			free(conn->style);
 			flib_weaponset_release(conn->weaponset);
 
 			free(conn);
@@ -99,7 +97,7 @@
 }
 
 bool flib_netconn_is_chief(flib_netconn *conn) {
-	if(!log_badargs_if(conn==NULL) && flib_netconn_is_in_room_context(conn)) {
+	if(!log_badargs_if(conn==NULL) && conn->netconnState==NETCONN_STATE_ROOM) {
 		return conn->isChief;
 	}
 	return false;
@@ -115,26 +113,22 @@
 void netconn_leaveRoom(flib_netconn *conn) {
 	conn->netconnState = NETCONN_STATE_LOBBY;
 	conn->isChief = false;
-	flib_map_release(conn->map);
+	flib_map_destroy(conn->map);
 	conn->map = flib_map_create_named("", "NoSuchMap");
 	flib_teamlist_clear(&conn->pendingTeamlist);
 	flib_teamlist_clear(&conn->teamlist);
-	flib_scheme_release(conn->scheme);
+	flib_scheme_destroy(conn->scheme);
 	conn->scheme = NULL;
-	free(conn->script);
-	conn->script = NULL;
+	free(conn->style);
+	conn->style = 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);
+		flib_map_destroy(conn->map);
 		conn->map = copy;
 	}
 }
@@ -150,15 +144,15 @@
 void netconn_setScript(flib_netconn *conn, const char *script) {
 	char *copy = flib_strdupnull(script);
 	if(copy) {
-		free(conn->script);
-		conn->script = copy;
+		free(conn->style);
+		conn->style = copy;
 	}
 }
 
 void netconn_setScheme(flib_netconn *conn, const flib_scheme *scheme) {
 	flib_scheme *copy = flib_scheme_copy(scheme);
 	if(copy) {
-		flib_scheme_release(conn->scheme);
+		flib_scheme_destroy(conn->scheme);
 		conn->scheme = copy;
 	}
 }
@@ -172,7 +166,7 @@
 			flib_gamesetup stackSetup = {0};
 			stackSetup.gamescheme = conn->scheme;
 			stackSetup.map = conn->map;
-			stackSetup.script = conn->script;
+			stackSetup.style = conn->style;
 			stackSetup.teamlist = &conn->teamlist;
 			flib_gamesetup *tmpSetup = flib_gamesetup_copy(&stackSetup);
 			if(tmpSetup) {
@@ -322,7 +316,7 @@
 				}
 	        }
 	    } else if (!strcmp(cmd, "ADD_TEAM")) {
-	        if(netmsg->partCount != 24 || !flib_netconn_is_in_room_context(conn)) {
+	        if(netmsg->partCount != 24 || conn->netconnState!=NETCONN_STATE_ROOM) {
 	            flib_log_w("Net: Bad ADD_TEAM message");
 	        } else {
 	        	flib_team *team = flib_team_from_netmsg(netmsg->parts+1);
@@ -337,7 +331,7 @@
 	        	}
 	        }
 	    } else if (!strcmp(cmd, "REMOVE_TEAM")) {
-	        if(netmsg->partCount != 2 || !flib_netconn_is_in_room_context(conn)) {
+	        if(netmsg->partCount != 2 || conn->netconnState!=NETCONN_STATE_ROOM) {
 	            flib_log_w("Net: Bad REMOVETEAM message");
 	        } else {
 	        	flib_teamlist_delete(&conn->teamlist, netmsg->parts[1]);
@@ -410,8 +404,6 @@
 	        	conn->onLobbyLeaveCb(conn->onLobbyLeaveCtx, netmsg->parts[1], netmsg->partCount>2 ? netmsg->parts[2] : NULL);
 	        }
 	    } 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);
@@ -430,10 +422,10 @@
 				}
 	        }
 	    } else if (!strcmp(cmd, "TEAM_ACCEPTED")) {
-	        if (netmsg->partCount != 2 || !flib_netconn_is_in_room_context(conn)) {
+	        if (netmsg->partCount != 2 || conn->netconnState!=NETCONN_STATE_ROOM) {
 	            flib_log_w("Net: Bad TEAM_ACCEPTED message");
 	        } else {
-	        	flib_team *team = flib_teamlist_find(&conn->pendingTeamlist, netmsg->parts[1]);
+	        	flib_team *team = flib_team_copy(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]);
@@ -443,28 +435,28 @@
 	        	conn->onTeamAcceptedCb(conn->onTeamAcceptedCtx, netmsg->parts[1]);
 	        }
 	    } else if (!strcmp(cmd, "CFG")) {
-	        if(netmsg->partCount < 3 || !flib_netconn_is_in_room_context(conn)) {
+	        if(netmsg->partCount < 3 || conn->netconnState!=NETCONN_STATE_ROOM) {
 	            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_scheme *cfg = flib_netmsg_to_cfg(conn->metaCfg, netmsg->parts+2);
+					flib_scheme *cfg = flib_scheme_from_netmsg(conn->metaCfg, netmsg->parts+2);
 					if(cfg) {
-						netconn_setScheme(conn, cfg);
+						flib_scheme_destroy(conn->scheme);
+						conn->scheme = cfg;
 						conn->onCfgSchemeCb(conn->onCfgSchemeCtx, cfg);
 					} else {
 						flib_log_e("Error processing CFG SCHEME message");
 					}
-					flib_scheme_release(cfg);
 				} else if(!strcmp(subcmd, "FULLMAPCONFIG") && netmsg->partCount == 7) {
-					flib_map *map = flib_netmsg_to_map(netmsg->parts+2);
+					flib_map *map = flib_map_from_netmsg(netmsg->parts+2);
 					if(map) {
-						netconn_setMap(conn, map);
+						flib_map_destroy(conn->map);
+						conn->map = 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) {
@@ -504,7 +496,7 @@
 				} else if(!strcmp(subcmd, "DRAWNMAP") && netmsg->partCount == 3) {
 					size_t drawnMapSize = 0;
 					uint8_t *drawnMapData = NULL;
-					if(!flib_netmsg_to_drawnmapdata(netmsg->parts[2], &drawnMapData, &drawnMapSize)) {
+					if(!flib_drawnmapdata_from_netmsg(netmsg->parts[2], &drawnMapData, &drawnMapSize)) {
 						free(conn->map->drawData);
 						conn->map->drawData = drawnMapData;
 						conn->map->drawDataSize = drawnMapSize;
@@ -529,7 +521,7 @@
 				}
 	        }
 	    } else if (!strcmp(cmd, "HH_NUM")) {
-	        if (netmsg->partCount != 3 || !flib_netconn_is_in_room_context(conn)) {
+	        if (netmsg->partCount != 3 || conn->netconnState!=NETCONN_STATE_ROOM) {
 	            flib_log_w("Net: Bad HH_NUM message");
 	        } else {
 	        	int hogs = atoi(netmsg->parts[2]);
@@ -546,11 +538,11 @@
 	        	}
 	        }
 	    } else if (!strcmp(cmd, "TEAM_COLOR")) {
-	        if (netmsg->partCount != 3 || !flib_netconn_is_in_room_context(conn)) {
+	        if (netmsg->partCount != 3 || conn->netconnState!=NETCONN_STATE_ROOM) {
 	            flib_log_w("Net: Bad TEAM_COLOR message");
 	        } else {
 	        	long color;
-	        	if(sscanf(netmsg->parts[2], "%lu", &color) && color>=0 && color<flib_teamcolor_defaults_len) {
+	        	if(sscanf(netmsg->parts[2], "%lu", &color) && color>=0 && color<flib_teamcolor_count) {
 	        		flib_team *team = flib_teamlist_find(&conn->teamlist, netmsg->parts[1]);
 	        		if(team) {
 	        			team->colorIndex = color;
--- a/project_files/frontlib/net/netconn.h	Sun Aug 12 22:21:09 2012 +0200
+++ b/project_files/frontlib/net/netconn.h	Sun Aug 12 22:37:57 2012 +0200
@@ -17,6 +17,42 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
+/**
+ * This file contains functions for communicating with a Hedgewars server to chat, prepare
+ * and play rounds of Hedgewars.
+ *
+ * To use this, first create a netconn object by calling flib_netconn_create. This will
+ * start the connection to the game server (which might fail right away, the function
+ * returns null then). You should also register your callback functions right at the start
+ * to ensure you don't miss any callbacks.
+ *
+ * In order to allow the netconn to run, you should regularly call flib_netconn_tick(), which
+ * performs network I/O and calls your callbacks on interesting events.
+ *
+ * When the connection is closed, you will receive the onDisconnect callback. This is the
+ * signal to destroy the netconn and stop calling tick().
+ *
+ * The connection process lasts from the time you create the netconn until you receive the
+ * onConnected callback (or onDisconnected in case something goes wrong). During that time,
+ * you might receive the onNickTaken and onPasswordRequest callbacks; see their description
+ * for more information on how to handle them. You could also receive other callbacks during
+ * connecting (e.g. about the room list), but it should be safe to ignore them.
+ *
+ * Once you are connected, you are in the lobby, and you can enter rooms and leave them again.
+ * The room and lobby states have different protocols, so many commands only work in either
+ * one or the other. If you are in a room you might also be in a game, but that does not
+ * change the protocol. The functions below are grouped by the states in which they make
+ * sense, or (for the callbacks) the states in which you would typically receive them.
+ *
+ * The state changes from lobby to room when the server tells you that you just entered one,
+ * which will also trigger the onEnterRoom callback. This usually happens in reply to either
+ * a joinRoom, createRoom or playerFollow command.
+ *
+ * The state changes back to lobby when the room is dissolved, when you are kicked from the
+ * room, or when you actively leave the room using flib_netconn_send_leaveRoom. The first
+ * two events will trigger the onLeaveRoom callback.
+ */
+
 #ifndef NETCONN_H_
 #define NETCONN_H_
 
@@ -31,22 +67,21 @@
 #define NETCONN_STATE_CONNECTING 0
 #define NETCONN_STATE_LOBBY 1
 #define NETCONN_STATE_ROOM 2
-#define NETCONN_STATE_INGAME 3
 #define NETCONN_STATE_DISCONNECTED 10
 
-#define NETCONN_DISCONNECT_NORMAL 0
-#define NETCONN_DISCONNECT_SERVER_TOO_OLD 1
-#define NETCONN_DISCONNECT_AUTH_FAILED 2 // TODO can you retry instead?
-#define NETCONN_DISCONNECT_CONNLOST 3
-#define NETCONN_DISCONNECT_INTERNAL_ERROR 100
+#define NETCONN_DISCONNECT_NORMAL 0				// The connection was closed normally
+#define NETCONN_DISCONNECT_SERVER_TOO_OLD 1		// The server has a lower protocol version than we do
+#define NETCONN_DISCONNECT_AUTH_FAILED 2		// You sent a password with flib_netconn_send_password that was not accepted
+#define NETCONN_DISCONNECT_CONNLOST 3			// The network connection was lost
+#define NETCONN_DISCONNECT_INTERNAL_ERROR 100	// Something went wrong in frontlib itself
 
-#define NETCONN_ROOMLEAVE_ABANDONED 0
-#define NETCONN_ROOMLEAVE_KICKED 1
+#define NETCONN_ROOMLEAVE_ABANDONED 0			// The room was closed because the chief left
+#define NETCONN_ROOMLEAVE_KICKED 1				// You have been kicked from the room
 
-#define NETCONN_MSG_TYPE_PLAYERINFO 0
-#define NETCONN_MSG_TYPE_SERVERMESSAGE 1
-#define NETCONN_MSG_TYPE_WARNING 2
-#define NETCONN_MSG_TYPE_ERROR 3
+#define NETCONN_MSG_TYPE_PLAYERINFO 0			// A response to flib_netconn_send_playerInfo
+#define NETCONN_MSG_TYPE_SERVERMESSAGE 1		// The welcome message when connecting to the lobby
+#define NETCONN_MSG_TYPE_WARNING 2				// A general warning message
+#define NETCONN_MSG_TYPE_ERROR 3				// A general error message
 
 #define NETCONN_MAPCHANGE_FULL 0
 #define NETCONN_MAPCHANGE_MAP 1
@@ -80,11 +115,6 @@
 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);
-
-/**
  * Returns the playername. This is *probably* the one provided on creation, but
  * if that name was already taken, a different one could have been set by the
  * onNickTaken callback or its default implementation.
@@ -116,6 +146,7 @@
 
 /**
  * Send the password in reply to a password request.
+ * If the server does not accept the password, you will be disconnected (NETCONN_DISCONNECT_AUTH_FAILED)
  */
 int flib_netconn_send_password(flib_netconn *conn, const char *passwd);
 
@@ -165,9 +196,9 @@
 int flib_netconn_send_toggleReady(flib_netconn *conn);
 
 /**
- * Add a team to the current room. The message includes the team color, but not
- * the number of hogs. Only makes sense when in room state. If the action succeeds, you will
- * receive an onTeamAccepted callback with the name of the team.
+ * Add a team to the current room. Apart from the "fixed" team information, this also includes
+ * the color, but not the number of hogs. Only makes sense when in room state. If the action
+ * succeeds, you will receive an onTeamAccepted callback with the name of the team.
  */
 int flib_netconn_send_addTeam(flib_netconn *conn, const flib_team *team);
 
@@ -269,12 +300,14 @@
 int flib_netconn_send_roundfinished(flib_netconn *conn, bool withoutError);
 
 /**
- * Ban a player. TODO: Figure out details
+ * Ban a player. You need to be in the lobby and a server admin for this to work.
  */
 int flib_netconn_send_ban(flib_netconn *conn, const char *playerName);
 
 /**
- * Kick a player. TODO: Figure out details
+ * Kick a player. This has different meanings in the lobby and in a room;
+ * In the lobby, it will kick the player from the server, and you need to be a server admin to do it.
+ * In a room, it will kick the player from the room, and you need to be room chief.
  */
 int flib_netconn_send_kick(flib_netconn *conn, const char *playerName);
 
@@ -286,13 +319,17 @@
 int flib_netconn_send_playerInfo(flib_netconn *conn, const char *playerName);
 
 /**
- * Follow a player. TODO figure out details
+ * Follow a player. Only valid in the lobby. If the player is in a room (or in a game),
+ * this command is analogous to calling flib_netconn_send_joinRoom with that room.
  */
 int flib_netconn_send_playerFollow(flib_netconn *conn, const char *playerName);
 
 /**
  * Signal that you want to start the game. Only makes sense in room state and if you are chief.
- * TODO details
+ * The server will check whether all players are ready and whether it believes the setup makes
+ * sense (e.g. more than one clan). If the server is satisfied, you will receive an onRunGame
+ * callback (all other clients in the room are notified the same way). Otherwise the server
+ * might answer with a warning, or might not answer at all.
  */
 int flib_netconn_send_startGame(flib_netconn *conn);
 
@@ -309,19 +346,19 @@
 int flib_netconn_send_toggleRestrictTeams(flib_netconn *conn);
 
 /**
- * Probably does something administrator-y.
+ * Does something administrator-y. At any rate you need to be an administrator and in the lobby
+ * to use this command.
  */
 int flib_netconn_send_clearAccountsCache(flib_netconn *conn);
 
 /**
  * Sets a server variable to the indicated value. Only makes sense if you are server admin.
  * Known variables are MOTD_NEW, MOTD_OLD and LATEST_PROTO.
- * TODO reply?
  */
 int flib_netconn_send_setServerVar(flib_netconn *conn, const char *name, const char *value);
 
 /**
- * Queries all server variables. Only makes sense if you are server admin. (TODO: try)
+ * Queries all server variables. Only makes sense if you are server admin.
  * If the action succeeds, you will receive several onServerVar callbacks with the
  * current values of all server variables.
  */
@@ -435,6 +472,9 @@
 /**
  * A new team was added to the room. The person who adds a team does NOT receive this callback (he gets onTeamAccepted instead).
  * The team does not contain bindings, stats, weaponset, color or the number of hogs.
+ *
+ * If you receive this message and you are the room chief, you are expected to provide a color and hog count for this team using
+ * flib_netconn_send_teamHogCount / teamColor.
  */
 void flib_netconn_onTeamAdd(flib_netconn *conn, void (*callback)(void *context, const flib_team *team), void *context);
 
@@ -456,8 +496,12 @@
  * When you ask for a team to be added, the server might reject it for several reasons, e.g. because it has the same name
  * as an existing team, or because the room chief restricted adding new teams. If the team is accepted by the server,
  * this callback is fired.
+ *
+ * If you are the room chief, you are expected to provide the hog count for your own team now using flib_netconn_send_teamHogCount.
+ * The color of the team is already set to the one you provided in addTeam, but the QtFrontend apparently always uses 0 there and
+ * instead sets the color after the team is accepted.
  */
-void flib_netconn_onTeamAccepted(flib_netconn *conn, void (*callback)(void *context, const char *teamName), void *context);
+void flib_netconn_onTeamAccepted(flib_netconn *conn, void (*callback)(void *context, const char *team), void *context);
 
 /**
  * The number of hogs in a team has been changed by the room chief. If you are the chief and change the number of hogs yourself,
@@ -505,7 +549,7 @@
 void flib_netconn_onAdminAccess(flib_netconn *conn, void (*callback)(void *context), void *context);
 
 /**
- * When you query the server vars with GET_SERVER_VAR (TODO probably only works as admin), the server
+ * When you query the server vars with flib_netconn_send_getServerVars (only works as admin), the server
  * replies with a list of them. This callback is called for each entry in that list.
  */
 void flib_netconn_onServerVar(flib_netconn *conn, void (*callback)(void *context, const char *name, const char *value), void *context);
--- a/project_files/frontlib/net/netconn_callbacks.c	Sun Aug 12 22:21:09 2012 +0200
+++ b/project_files/frontlib/net/netconn_callbacks.c	Sun Aug 12 22:37:57 2012 +0200
@@ -117,7 +117,6 @@
 	static void _noop_callback_##cbName cbParameterTypes {} \
 	GENERATE_CB_SETTER(cbName, cbParameterTypes, _noop_callback_##cbName)
 
-// TODO Disallow transfer of ownership?
 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));
--- a/project_files/frontlib/net/netconn_internal.h	Sun Aug 12 22:21:09 2012 +0200
+++ b/project_files/frontlib/net/netconn_internal.h	Sun Aug 12 22:37:57 2012 +0200
@@ -50,7 +50,7 @@
 	flib_teamlist pendingTeamlist;
 	flib_teamlist teamlist;
 	flib_scheme *scheme;
-	char *script;
+	char *style;
 	flib_weaponset *weaponset;
 
 	void (*onMessageCb)(void *context, int msgtype, const char *msg);
--- a/project_files/frontlib/net/netconn_send.c	Sun Aug 12 22:21:09 2012 +0200
+++ b/project_files/frontlib/net/netconn_send.c	Sun Aug 12 22:37:57 2012 +0200
@@ -133,7 +133,7 @@
 
 int flib_netconn_send_leaveRoom(flib_netconn *conn, const char *str) {
 	int result = -1;
-	if(flib_netconn_is_in_room_context(conn)) {
+	if(conn->netconnState==NETCONN_STATE_ROOM) {
 		result = (str && *str) ? sendStr(conn, "PART", str) : sendVoid(conn, "PART");
 		if(!result) {
 			netconn_leaveRoom(conn);
@@ -190,11 +190,9 @@
 }
 
 int flib_netconn_send_removeTeam(flib_netconn *conn, const char *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);
-		}
+	flib_team *team = flib_teamlist_find(&conn->teamlist, teamname);
+	if(team && !team->remoteDriven && !sendStr(conn, "REMOVE_TEAM", teamname)) {
+		flib_teamlist_delete(&conn->teamlist, teamname);
 		return 0;
 	}
 	return -1;
@@ -214,13 +212,11 @@
 }
 
 int flib_netconn_send_teamHogCount(flib_netconn *conn, const char *teamname, int hogcount) {
-	if(!log_badargs_if4(conn==NULL, flib_strempty(teamname), hogcount<1, hogcount>HEDGEHOGS_PER_TEAM)
+	if(!log_badargs_if5(conn==NULL, flib_strempty(teamname), hogcount<1, hogcount>HEDGEHOGS_PER_TEAM, !conn->isChief)
 			&& !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;
-			}
+		flib_team *team = flib_teamlist_find(&conn->teamlist, teamname);
+		if(team) {
+			team->hogsInGame = hogcount;
 		}
 		return 0;
 	}
@@ -228,13 +224,11 @@
 }
 
 int flib_netconn_send_teamColor(flib_netconn *conn, const char *teamname, int colorIndex) {
-	if(!log_badargs_if2(conn==NULL, flib_strempty(teamname))
+	if(!log_badargs_if3(conn==NULL, flib_strempty(teamname), !conn->isChief)
 			&& !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;
-			}
+		flib_team *team = flib_teamlist_find(&conn->teamlist, teamname);
+		if(team) {
+			team->colorIndex = colorIndex;
 		}
 		return 0;
 	}
@@ -431,13 +425,7 @@
 }
 
 int flib_netconn_send_roundfinished(flib_netconn *conn, bool withoutError) {
-	if(!sendInt(conn, "ROUNDFINISHED", withoutError ? 1 : 0)) {
-		if(conn->netconnState == NETCONN_STATE_INGAME) {
-			conn->netconnState = NETCONN_STATE_ROOM;
-		}
-		return 0;
-	}
-	return -1;
+	return sendInt(conn, "ROUNDFINISHED", withoutError ? 1 : 0);
 }
 
 int flib_netconn_send_ban(flib_netconn *conn, const char *playerName) {
--- a/project_files/frontlib/net/netprotocol.c	Sun Aug 12 22:21:09 2012 +0200
+++ b/project_files/frontlib/net/netprotocol.c	Sun Aug 12 22:37:57 2012 +0200
@@ -75,7 +75,7 @@
 	return result;
 }
 
-flib_scheme *flib_netmsg_to_cfg(flib_metascheme *meta, char **parts) {
+flib_scheme *flib_scheme_from_netmsg(flib_metascheme *meta, char **parts) {
 	flib_scheme *result = flib_scheme_create(meta, parts[0]);
 	if(result) {
 		for(int i=0; i<meta->modCount; i++) {
@@ -88,7 +88,7 @@
 	return result;
 }
 
-flib_map *flib_netmsg_to_map(char **parts) {
+flib_map *flib_map_from_netmsg(char **parts) {
 	flib_map *result = flib_map_create_named(parts[3], parts[0]);
 	if(result) {
 		result->mapgen = atoi(parts[1]);
@@ -98,7 +98,7 @@
 	return result;
 }
 
-int flib_netmsg_to_drawnmapdata(char *netmsg, uint8_t** outbuf, size_t *outlen) {
+int flib_drawnmapdata_from_netmsg(char *netmsg, uint8_t** outbuf, size_t *outlen) {
 	int result = -1;
 
 	// First step: base64 decoding
--- a/project_files/frontlib/net/netprotocol.h	Sun Aug 12 22:21:09 2012 +0200
+++ b/project_files/frontlib/net/netprotocol.h	Sun Aug 12 22:37:57 2012 +0200
@@ -27,8 +27,6 @@
 
 #include <stddef.h>
 
-// TODO unify naming
-
 /**
  * Create a new team from this 23-part net message
  */
@@ -38,12 +36,12 @@
  * Create a new scheme from this net message, which must have
  * meta->modCount+meta->settingCount+1 parts.
  */
-flib_scheme *flib_netmsg_to_cfg(flib_metascheme *meta, char **parts);
+flib_scheme *flib_scheme_from_netmsg(flib_metascheme *meta, char **parts);
 
 /**
  * Create a new map from this five-part netmsg
  */
-flib_map *flib_netmsg_to_map(char **parts);
+flib_map *flib_map_from_netmsg(char **parts);
 
 /**
  * Decode the drawn map data from this netmessage line.
@@ -53,7 +51,7 @@
  * is written to the variable pointed to by outlen.
  * Returns NULL on error.
  */
-int flib_netmsg_to_drawnmapdata(char *netmsg, uint8_t **outbuf, size_t *outlen);
+int flib_drawnmapdata_from_netmsg(char *netmsg, uint8_t **outbuf, size_t *outlen);
 
 /**
  * Create a new room from this 8-part net message
--- a/project_files/frontlib/util/logging.h	Sun Aug 12 22:21:09 2012 +0200
+++ b/project_files/frontlib/util/logging.h	Sun Aug 12 22:37:57 2012 +0200
@@ -39,6 +39,7 @@
 /**
  * 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)
+ * Usage: log_e_if(errorHasHappened, "Format string", formatArg, ...);
  */
 #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__)
@@ -79,9 +80,21 @@
 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();
+/**
+ * Only log messages that are at least the indicated level
+ */
 void flib_log_setLevel(int level);
+int flib_log_getLevel();
+
+/**
+ * Log to the indicated file. You can pass NULL to log to stdout.
+ * This overrides setCallback and vice versa.
+ */
 void flib_log_setFile(FILE *logfile);
+
+/**
+ * Returns whether messages of this level are logged at the moment.
+ */
 bool flib_log_isActive(int level);
 
 /**