project_files/frontlib/net/netconn_send.c
changeset 10017 de822cd3df3a
parent 7580 c92596feac0d
equal deleted inserted replaced
10015:4feced261c68 10017:de822cd3df3a
    31 #include <string.h>
    31 #include <string.h>
    32 #include <limits.h>
    32 #include <limits.h>
    33 
    33 
    34 // cmdname is always given as literal from functions in this file, so it is never null.
    34 // cmdname is always given as literal from functions in this file, so it is never null.
    35 static int sendVoid(flib_netconn *conn, const char *cmdname) {
    35 static int sendVoid(flib_netconn *conn, const char *cmdname) {
    36 	if(log_e_if(!conn, "Invalid parameter sending %s command", cmdname)) {
    36     if(log_e_if(!conn, "Invalid parameter sending %s command", cmdname)) {
    37 		return -1;
    37         return -1;
    38 	}
    38     }
    39 	return flib_netbase_sendf(conn->netBase, "%s\n\n", cmdname);
    39     return flib_netbase_sendf(conn->netBase, "%s\n\n", cmdname);
    40 }
    40 }
    41 
    41 
    42 // Testing for !*str prevents sending 0-length parameters (they trip up the protocol)
    42 // Testing for !*str prevents sending 0-length parameters (they trip up the protocol)
    43 static int sendStr(flib_netconn *conn, const char *cmdname, const char *str) {
    43 static int sendStr(flib_netconn *conn, const char *cmdname, const char *str) {
    44 	if(log_e_if(!conn || flib_strempty(str), "Invalid parameter sending %s command", cmdname)) {
    44     if(log_e_if(!conn || flib_strempty(str), "Invalid parameter sending %s command", cmdname)) {
    45 		return -1;
    45         return -1;
    46 	}
    46     }
    47 	return flib_netbase_sendf(conn->netBase, "%s\n%s\n\n", cmdname, str);
    47     return flib_netbase_sendf(conn->netBase, "%s\n%s\n\n", cmdname, str);
    48 }
    48 }
    49 
    49 
    50 static int sendInt(flib_netconn *conn, const char *cmdname, int param) {
    50 static int sendInt(flib_netconn *conn, const char *cmdname, int param) {
    51 	if(log_e_if(!conn, "Invalid parameter sending %s command", cmdname)) {
    51     if(log_e_if(!conn, "Invalid parameter sending %s command", cmdname)) {
    52 		return -1;
    52         return -1;
    53 	}
    53     }
    54 	return flib_netbase_sendf(conn->netBase, "%s\n%i\n\n", cmdname, param);
    54     return flib_netbase_sendf(conn->netBase, "%s\n%i\n\n", cmdname, param);
    55 }
    55 }
    56 
    56 
    57 int flib_netconn_send_nick(flib_netconn *conn, const char *nick) {
    57 int flib_netconn_send_nick(flib_netconn *conn, const char *nick) {
    58 	int result = -1;
    58     int result = -1;
    59 	if(!log_badargs_if2(conn==NULL, flib_strempty(nick))) {
    59     if(!log_badargs_if2(conn==NULL, flib_strempty(nick))) {
    60 		char *tmpName = flib_strdupnull(nick);
    60         char *tmpName = flib_strdupnull(nick);
    61 		if(tmpName) {
    61         if(tmpName) {
    62 			if(!flib_netbase_sendf(conn->netBase, "%s\n%s\n\n", "NICK", nick)) {
    62             if(!flib_netbase_sendf(conn->netBase, "%s\n%s\n\n", "NICK", nick)) {
    63 				free(conn->playerName);
    63                 free(conn->playerName);
    64 				conn->playerName = tmpName;
    64                 conn->playerName = tmpName;
    65 				tmpName = NULL;
    65                 tmpName = NULL;
    66 				result = 0;
    66                 result = 0;
    67 			}
    67             }
    68 		}
    68         }
    69 		free(tmpName);
    69         free(tmpName);
    70 	}
    70     }
    71 	return result;
    71     return result;
    72 }
    72 }
    73 
    73 
    74 int flib_netconn_send_password(flib_netconn *conn, const char *passwd) {
    74 int flib_netconn_send_password(flib_netconn *conn, const char *passwd) {
    75 	int result = -1;
    75     int result = -1;
    76 	if(!log_badargs_if2(conn==NULL, passwd==NULL)) {
    76     if(!log_badargs_if2(conn==NULL, passwd==NULL)) {
    77 		md5_state_t md5state;
    77         md5_state_t md5state;
    78 		uint8_t md5bytes[16];
    78         uint8_t md5bytes[16];
    79 		char md5hex[33];
    79         char md5hex[33];
    80 		md5_init(&md5state);
    80         md5_init(&md5state);
    81 		md5_append(&md5state, (unsigned char*)passwd, strlen(passwd));
    81         md5_append(&md5state, (unsigned char*)passwd, strlen(passwd));
    82 		md5_finish(&md5state, md5bytes);
    82         md5_finish(&md5state, md5bytes);
    83 		for(int i=0;i<sizeof(md5bytes); i++) {
    83         for(int i=0;i<sizeof(md5bytes); i++) {
    84 			// Needs to be lowercase - server checks case sensitive
    84             // Needs to be lowercase - server checks case sensitive
    85 			snprintf(md5hex+i*2, 3, "%02x", (unsigned)md5bytes[i]);
    85             snprintf(md5hex+i*2, 3, "%02x", (unsigned)md5bytes[i]);
    86 		}
    86         }
    87 		result = flib_netbase_sendf(conn->netBase, "%s\n%s\n\n", "PASSWORD", md5hex);
    87         result = flib_netbase_sendf(conn->netBase, "%s\n%s\n\n", "PASSWORD", md5hex);
    88 	}
    88     }
    89 	return result;
    89     return result;
    90 }
    90 }
    91 
    91 
    92 int flib_netconn_send_quit(flib_netconn *conn, const char *quitmsg) {
    92 int flib_netconn_send_quit(flib_netconn *conn, const char *quitmsg) {
    93 	return sendStr(conn, "QUIT", (quitmsg && *quitmsg) ? quitmsg : "User quit");
    93     return sendStr(conn, "QUIT", (quitmsg && *quitmsg) ? quitmsg : "User quit");
    94 }
    94 }
    95 
    95 
    96 int flib_netconn_send_chat(flib_netconn *conn, const char *chat) {
    96 int flib_netconn_send_chat(flib_netconn *conn, const char *chat) {
    97 	if(!flib_strempty(chat)) {
    97     if(!flib_strempty(chat)) {
    98 		return sendStr(conn, "CHAT", chat);
    98         return sendStr(conn, "CHAT", chat);
    99 	}
    99     }
   100 	return 0;
   100     return 0;
   101 }
   101 }
   102 
   102 
   103 int flib_netconn_send_kick(flib_netconn *conn, const char *playerName) {
   103 int flib_netconn_send_kick(flib_netconn *conn, const char *playerName) {
   104 	return sendStr(conn, "KICK", playerName);
   104     return sendStr(conn, "KICK", playerName);
   105 }
   105 }
   106 
   106 
   107 int flib_netconn_send_playerInfo(flib_netconn *conn, const char *playerName) {
   107 int flib_netconn_send_playerInfo(flib_netconn *conn, const char *playerName) {
   108 	return sendStr(conn, "INFO", playerName);
   108     return sendStr(conn, "INFO", playerName);
   109 }
   109 }
   110 
   110 
   111 int flib_netconn_send_request_roomlist(flib_netconn *conn) {
   111 int flib_netconn_send_request_roomlist(flib_netconn *conn) {
   112 	return sendVoid(conn, "LIST");
   112     return sendVoid(conn, "LIST");
   113 }
   113 }
   114 
   114 
   115 int flib_netconn_send_joinRoom(flib_netconn *conn, const char *room) {
   115 int flib_netconn_send_joinRoom(flib_netconn *conn, const char *room) {
   116 	if(!sendStr(conn, "JOIN_ROOM", room)) {
   116     if(!sendStr(conn, "JOIN_ROOM", room)) {
   117 		conn->isChief = false;
   117         conn->isChief = false;
   118 		return 0;
   118         return 0;
   119 	}
   119     }
   120 	return -1;
   120     return -1;
   121 }
   121 }
   122 
   122 
   123 int flib_netconn_send_playerFollow(flib_netconn *conn, const char *playerName) {
   123 int flib_netconn_send_playerFollow(flib_netconn *conn, const char *playerName) {
   124 	return sendStr(conn, "FOLLOW", playerName);
   124     return sendStr(conn, "FOLLOW", playerName);
   125 }
   125 }
   126 
   126 
   127 int flib_netconn_send_createRoom(flib_netconn *conn, const char *room) {
   127 int flib_netconn_send_createRoom(flib_netconn *conn, const char *room) {
   128 	if(!sendStr(conn, "CREATE_ROOM", room)) {
   128     if(!sendStr(conn, "CREATE_ROOM", room)) {
   129 		conn->isChief = true;
   129         conn->isChief = true;
   130 		return 0;
   130         return 0;
   131 	}
   131     }
   132 	return -1;
   132     return -1;
   133 }
   133 }
   134 
   134 
   135 int flib_netconn_send_ban(flib_netconn *conn, const char *playerName) {
   135 int flib_netconn_send_ban(flib_netconn *conn, const char *playerName) {
   136 	return sendStr(conn, "BAN", playerName);
   136     return sendStr(conn, "BAN", playerName);
   137 }
   137 }
   138 
   138 
   139 int flib_netconn_send_clearAccountsCache(flib_netconn *conn) {
   139 int flib_netconn_send_clearAccountsCache(flib_netconn *conn) {
   140 	return sendVoid(conn, "CLEAR_ACCOUNTS_CACHE");
   140     return sendVoid(conn, "CLEAR_ACCOUNTS_CACHE");
   141 }
   141 }
   142 
   142 
   143 int flib_netconn_send_setServerVar(flib_netconn *conn, const char *name, const char *value) {
   143 int flib_netconn_send_setServerVar(flib_netconn *conn, const char *name, const char *value) {
   144 	if(log_badargs_if3(conn==NULL, flib_strempty(name), flib_strempty(value))) {
   144     if(log_badargs_if3(conn==NULL, flib_strempty(name), flib_strempty(value))) {
   145 		return -1;
   145         return -1;
   146 	}
   146     }
   147 	return flib_netbase_sendf(conn->netBase, "%s\n%s\n%s\n\n", "SET_SERVER_VAR", name, value);
   147     return flib_netbase_sendf(conn->netBase, "%s\n%s\n%s\n\n", "SET_SERVER_VAR", name, value);
   148 }
   148 }
   149 
   149 
   150 int flib_netconn_send_getServerVars(flib_netconn *conn) {
   150 int flib_netconn_send_getServerVars(flib_netconn *conn) {
   151 	return sendVoid(conn, "GET_SERVER_VAR");
   151     return sendVoid(conn, "GET_SERVER_VAR");
   152 }
   152 }
   153 int flib_netconn_send_leaveRoom(flib_netconn *conn, const char *str) {
   153 int flib_netconn_send_leaveRoom(flib_netconn *conn, const char *str) {
   154 	int result = -1;
   154     int result = -1;
   155 	if(conn->netconnState==NETCONN_STATE_ROOM) {
   155     if(conn->netconnState==NETCONN_STATE_ROOM) {
   156 		result = (str && *str) ? sendStr(conn, "PART", str) : sendVoid(conn, "PART");
   156         result = (str && *str) ? sendStr(conn, "PART", str) : sendVoid(conn, "PART");
   157 		if(!result) {
   157         if(!result) {
   158 			netconn_leaveRoom(conn);
   158             netconn_leaveRoom(conn);
   159 		}
   159         }
   160 	}
   160     }
   161 	return result;
   161     return result;
   162 }
   162 }
   163 
   163 
   164 int flib_netconn_send_toggleReady(flib_netconn *conn) {
   164 int flib_netconn_send_toggleReady(flib_netconn *conn) {
   165 	return sendVoid(conn, "TOGGLE_READY");
   165     return sendVoid(conn, "TOGGLE_READY");
   166 }
   166 }
   167 
   167 
   168 static void addTeamToPendingList(flib_netconn *conn, const flib_team *team) {
   168 static void addTeamToPendingList(flib_netconn *conn, const flib_team *team) {
   169 	flib_team *teamcopy = flib_team_copy(team);
   169     flib_team *teamcopy = flib_team_copy(team);
   170 	if(teamcopy) {
   170     if(teamcopy) {
   171 		teamcopy->remoteDriven = false;
   171         teamcopy->remoteDriven = false;
   172 		free(teamcopy->ownerName);
   172         free(teamcopy->ownerName);
   173 		teamcopy->ownerName = flib_strdupnull(conn->playerName);
   173         teamcopy->ownerName = flib_strdupnull(conn->playerName);
   174 		if(teamcopy->ownerName) {
   174         if(teamcopy->ownerName) {
   175 			flib_teamlist_delete(&conn->pendingTeamlist, team->name);
   175             flib_teamlist_delete(&conn->pendingTeamlist, team->name);
   176 			if(!flib_teamlist_insert(&conn->pendingTeamlist, teamcopy, 0)) {
   176             if(!flib_teamlist_insert(&conn->pendingTeamlist, teamcopy, 0)) {
   177 				teamcopy = NULL;
   177                 teamcopy = NULL;
   178 			}
   178             }
   179 		}
   179         }
   180 	}
   180     }
   181 	flib_team_destroy(teamcopy);
   181     flib_team_destroy(teamcopy);
   182 }
   182 }
   183 
   183 
   184 int flib_netconn_send_addTeam(flib_netconn *conn, const flib_team *team) {
   184 int flib_netconn_send_addTeam(flib_netconn *conn, const flib_team *team) {
   185 	int result = -1;
   185     int result = -1;
   186 	if(!log_badargs_if2(conn==NULL, team==NULL)) {
   186     if(!log_badargs_if2(conn==NULL, team==NULL)) {
   187 		bool missingInfo = flib_strempty(team->name) || flib_strempty(team->grave) || flib_strempty(team->fort) || flib_strempty(team->voicepack) || flib_strempty(team->flag);
   187         bool missingInfo = flib_strempty(team->name) || flib_strempty(team->grave) || flib_strempty(team->fort) || flib_strempty(team->voicepack) || flib_strempty(team->flag);
   188 		for(int i=0; i<HEDGEHOGS_PER_TEAM; i++) {
   188         for(int i=0; i<HEDGEHOGS_PER_TEAM; i++) {
   189 			missingInfo |= flib_strempty(team->hogs[i].name) || flib_strempty(team->hogs[i].hat);
   189             missingInfo |= flib_strempty(team->hogs[i].name) || flib_strempty(team->hogs[i].hat);
   190 		}
   190         }
   191 		if(!log_e_if(missingInfo, "Incomplete team definition")) {
   191         if(!log_e_if(missingInfo, "Incomplete team definition")) {
   192 			flib_vector *vec = flib_vector_create();
   192             flib_vector *vec = flib_vector_create();
   193 			if(vec) {
   193             if(vec) {
   194 				bool error = false;
   194                 bool error = false;
   195 				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);
   195                 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);
   196 				for(int i=0; i<HEDGEHOGS_PER_TEAM; i++) {
   196                 for(int i=0; i<HEDGEHOGS_PER_TEAM; i++) {
   197 					error |= flib_vector_appendf(vec, "%s\n%s\n", team->hogs[i].name, team->hogs[i].hat);
   197                     error |= flib_vector_appendf(vec, "%s\n%s\n", team->hogs[i].name, team->hogs[i].hat);
   198 				}
   198                 }
   199 				error |= flib_vector_appendf(vec, "\n");
   199                 error |= flib_vector_appendf(vec, "\n");
   200 				if(!error && !flib_netbase_send_raw(conn->netBase, flib_vector_data(vec), flib_vector_size(vec))) {
   200                 if(!error && !flib_netbase_send_raw(conn->netBase, flib_vector_data(vec), flib_vector_size(vec))) {
   201 					addTeamToPendingList(conn, team);
   201                     addTeamToPendingList(conn, team);
   202 					result = 0;
   202                     result = 0;
   203 				}
   203                 }
   204 			}
   204             }
   205 			flib_vector_destroy(vec);
   205             flib_vector_destroy(vec);
   206 		}
   206         }
   207 	}
   207     }
   208 	return result;
   208     return result;
   209 }
   209 }
   210 
   210 
   211 int flib_netconn_send_removeTeam(flib_netconn *conn, const char *teamname) {
   211 int flib_netconn_send_removeTeam(flib_netconn *conn, const char *teamname) {
   212 	flib_team *team = flib_teamlist_find(&conn->teamlist, teamname);
   212     flib_team *team = flib_teamlist_find(&conn->teamlist, teamname);
   213 	if(team && !team->remoteDriven && !sendStr(conn, "REMOVE_TEAM", teamname)) {
   213     if(team && !team->remoteDriven && !sendStr(conn, "REMOVE_TEAM", teamname)) {
   214 		flib_teamlist_delete(&conn->teamlist, teamname);
   214         flib_teamlist_delete(&conn->teamlist, teamname);
   215 		return 0;
   215         return 0;
   216 	}
   216     }
   217 	return -1;
   217     return -1;
   218 }
   218 }
   219 
   219 
   220 int flib_netconn_send_renameRoom(flib_netconn *conn, const char *roomName) {
   220 int flib_netconn_send_renameRoom(flib_netconn *conn, const char *roomName) {
   221 	return sendStr(conn, "ROOM_NAME", roomName);
   221     return sendStr(conn, "ROOM_NAME", roomName);
   222 }
   222 }
   223 
   223 
   224 int flib_netconn_send_teamHogCount(flib_netconn *conn, const char *teamname, int hogcount) {
   224 int flib_netconn_send_teamHogCount(flib_netconn *conn, const char *teamname, int hogcount) {
   225 	if(!log_badargs_if5(conn==NULL, flib_strempty(teamname), hogcount<1, hogcount>HEDGEHOGS_PER_TEAM, !conn->isChief)
   225     if(!log_badargs_if5(conn==NULL, flib_strempty(teamname), hogcount<1, hogcount>HEDGEHOGS_PER_TEAM, !conn->isChief)
   226 			&& !flib_netbase_sendf(conn->netBase, "HH_NUM\n%s\n%i\n\n", teamname, hogcount)) {
   226             && !flib_netbase_sendf(conn->netBase, "HH_NUM\n%s\n%i\n\n", teamname, hogcount)) {
   227 		flib_team *team = flib_teamlist_find(&conn->teamlist, teamname);
   227         flib_team *team = flib_teamlist_find(&conn->teamlist, teamname);
   228 		if(team) {
   228         if(team) {
   229 			team->hogsInGame = hogcount;
   229             team->hogsInGame = hogcount;
   230 		}
   230         }
   231 		return 0;
   231         return 0;
   232 	}
   232     }
   233 	return -1;
   233     return -1;
   234 }
   234 }
   235 
   235 
   236 int flib_netconn_send_teamColor(flib_netconn *conn, const char *teamname, int colorIndex) {
   236 int flib_netconn_send_teamColor(flib_netconn *conn, const char *teamname, int colorIndex) {
   237 	if(!log_badargs_if3(conn==NULL, flib_strempty(teamname), !conn->isChief)
   237     if(!log_badargs_if3(conn==NULL, flib_strempty(teamname), !conn->isChief)
   238 			&& !flib_netbase_sendf(conn->netBase, "TEAM_COLOR\n%s\n%i\n\n", teamname, colorIndex)) {
   238             && !flib_netbase_sendf(conn->netBase, "TEAM_COLOR\n%s\n%i\n\n", teamname, colorIndex)) {
   239 		flib_team *team = flib_teamlist_find(&conn->teamlist, teamname);
   239         flib_team *team = flib_teamlist_find(&conn->teamlist, teamname);
   240 		if(team) {
   240         if(team) {
   241 			team->colorIndex = colorIndex;
   241             team->colorIndex = colorIndex;
   242 		}
   242         }
   243 		return 0;
   243         return 0;
   244 	}
   244     }
   245 	return -1;
   245     return -1;
   246 }
   246 }
   247 
   247 
   248 int flib_netconn_send_weaponset(flib_netconn *conn, const flib_weaponset *weaponset) {
   248 int flib_netconn_send_weaponset(flib_netconn *conn, const flib_weaponset *weaponset) {
   249 	if(!log_badargs_if3(conn==NULL, weaponset==NULL, flib_strempty(weaponset->name))) {
   249     if(!log_badargs_if3(conn==NULL, weaponset==NULL, flib_strempty(weaponset->name))) {
   250 		char ammostring[WEAPONS_COUNT*4+1];
   250         char ammostring[WEAPONS_COUNT*4+1];
   251 		strcpy(ammostring, weaponset->loadout);
   251         strcpy(ammostring, weaponset->loadout);
   252 		strcat(ammostring, weaponset->crateprob);
   252         strcat(ammostring, weaponset->crateprob);
   253 		strcat(ammostring, weaponset->delay);
   253         strcat(ammostring, weaponset->delay);
   254 		strcat(ammostring, weaponset->crateammo);
   254         strcat(ammostring, weaponset->crateammo);
   255 		if(conn->isChief) {
   255         if(conn->isChief) {
   256 			if(!flib_netbase_sendf(conn->netBase, "CFG\nAMMO\n%s\n%s\n\n", weaponset->name, ammostring)) {
   256             if(!flib_netbase_sendf(conn->netBase, "CFG\nAMMO\n%s\n%s\n\n", weaponset->name, ammostring)) {
   257 				netconn_setWeaponset(conn, weaponset);
   257                 netconn_setWeaponset(conn, weaponset);
   258 				return 0;
   258                 return 0;
   259 			}
   259             }
   260 		}
   260         }
   261 	}
   261     }
   262 	return -1;
   262     return -1;
   263 }
   263 }
   264 
   264 
   265 int flib_netconn_send_map(flib_netconn *conn, const flib_map *map) {
   265 int flib_netconn_send_map(flib_netconn *conn, const flib_map *map) {
   266 	if(log_badargs_if2(conn==NULL, map==NULL)) {
   266     if(log_badargs_if2(conn==NULL, map==NULL)) {
   267 		return -1;
   267         return -1;
   268 	}
   268     }
   269 	bool error = false;
   269     bool error = false;
   270 
   270 
   271 	if(map->seed) {
   271     if(map->seed) {
   272 		error |= flib_netconn_send_mapSeed(conn, map->seed);
   272         error |= flib_netconn_send_mapSeed(conn, map->seed);
   273 	}
   273     }
   274 	error |= flib_netconn_send_mapTemplate(conn, map->templateFilter);
   274     error |= flib_netconn_send_mapTemplate(conn, map->templateFilter);
   275 	if(map->theme) {
   275     if(map->theme) {
   276 		error |= flib_netconn_send_mapTheme(conn, map->theme);
   276         error |= flib_netconn_send_mapTheme(conn, map->theme);
   277 	}
   277     }
   278 	error |= flib_netconn_send_mapGen(conn, map->mapgen);
   278     error |= flib_netconn_send_mapGen(conn, map->mapgen);
   279 	error |= flib_netconn_send_mapMazeSize(conn, map->mazeSize);
   279     error |= flib_netconn_send_mapMazeSize(conn, map->mazeSize);
   280 	if(map->drawData && map->drawDataSize>0) {
   280     if(map->drawData && map->drawDataSize>0) {
   281 		error |= flib_netconn_send_mapDrawdata(conn, map->drawData, map->drawDataSize);
   281         error |= flib_netconn_send_mapDrawdata(conn, map->drawData, map->drawDataSize);
   282 	}
   282     }
   283 	// Name is sent last, because the QtFrontend uses this to update its preview, and to show/hide
   283     // Name is sent last, because the QtFrontend uses this to update its preview, and to show/hide
   284 	// certain fields
   284     // certain fields
   285 	if(map->name) {
   285     if(map->name) {
   286 		error |= flib_netconn_send_mapName(conn, map->name);
   286         error |= flib_netconn_send_mapName(conn, map->name);
   287 	}
   287     }
   288 	return error;
   288     return error;
   289 }
   289 }
   290 
   290 
   291 int flib_netconn_send_mapName(flib_netconn *conn, const char *mapName) {
   291 int flib_netconn_send_mapName(flib_netconn *conn, const char *mapName) {
   292 	if(log_badargs_if2(conn==NULL, mapName==NULL)) {
   292     if(log_badargs_if2(conn==NULL, mapName==NULL)) {
   293 		return -1;
   293         return -1;
   294 	}
   294     }
   295 	if(conn->isChief) {
   295     if(conn->isChief) {
   296 		if(!sendStr(conn, "CFG\nMAP", mapName)) {
   296         if(!sendStr(conn, "CFG\nMAP", mapName)) {
   297 			char *copy = flib_strdupnull(mapName);
   297             char *copy = flib_strdupnull(mapName);
   298 			if(copy) {
   298             if(copy) {
   299 				free(conn->map->name);
   299                 free(conn->map->name);
   300 				conn->map->name = copy;
   300                 conn->map->name = copy;
   301 				return 0;
   301                 return 0;
   302 			}
   302             }
   303 		}
   303         }
   304 	}
   304     }
   305 	return -1;
   305     return -1;
   306 }
   306 }
   307 
   307 
   308 int flib_netconn_send_mapGen(flib_netconn *conn, int mapGen) {
   308 int flib_netconn_send_mapGen(flib_netconn *conn, int mapGen) {
   309 	if(log_badargs_if(conn==NULL)) {
   309     if(log_badargs_if(conn==NULL)) {
   310 		return -1;
   310         return -1;
   311 	}
   311     }
   312 	if(conn->isChief) {
   312     if(conn->isChief) {
   313 		if(!sendInt(conn, "CFG\nMAPGEN", mapGen)) {
   313         if(!sendInt(conn, "CFG\nMAPGEN", mapGen)) {
   314 			conn->map->mapgen = mapGen;
   314             conn->map->mapgen = mapGen;
   315 			return 0;
   315             return 0;
   316 		}
   316         }
   317 	}
   317     }
   318 	return -1;
   318     return -1;
   319 }
   319 }
   320 
   320 
   321 int flib_netconn_send_mapTemplate(flib_netconn *conn, int templateFilter) {
   321 int flib_netconn_send_mapTemplate(flib_netconn *conn, int templateFilter) {
   322 	if(log_badargs_if(conn==NULL)) {
   322     if(log_badargs_if(conn==NULL)) {
   323 		return -1;
   323         return -1;
   324 	}
   324     }
   325 	if(conn->isChief) {
   325     if(conn->isChief) {
   326 		if(!sendInt(conn, "CFG\nTEMPLATE", templateFilter)) {
   326         if(!sendInt(conn, "CFG\nTEMPLATE", templateFilter)) {
   327 			conn->map->templateFilter = templateFilter;
   327             conn->map->templateFilter = templateFilter;
   328 			return 0;
   328             return 0;
   329 		}
   329         }
   330 	}
   330     }
   331 	return -1;
   331     return -1;
   332 }
   332 }
   333 
   333 
   334 int flib_netconn_send_mapMazeSize(flib_netconn *conn, int mazeSize) {
   334 int flib_netconn_send_mapMazeSize(flib_netconn *conn, int mazeSize) {
   335 	if(log_badargs_if(conn==NULL)) {
   335     if(log_badargs_if(conn==NULL)) {
   336 		return -1;
   336         return -1;
   337 	}
   337     }
   338 	if(conn->isChief) {
   338     if(conn->isChief) {
   339 		if(!sendInt(conn, "CFG\nMAZE_SIZE", mazeSize)) {
   339         if(!sendInt(conn, "CFG\nMAZE_SIZE", mazeSize)) {
   340 			conn->map->mazeSize = mazeSize;
   340             conn->map->mazeSize = mazeSize;
   341 			return 0;
   341             return 0;
   342 		}
   342         }
   343 	}
   343     }
   344 	return -1;
   344     return -1;
   345 }
   345 }
   346 
   346 
   347 int flib_netconn_send_mapSeed(flib_netconn *conn, const char *seed) {
   347 int flib_netconn_send_mapSeed(flib_netconn *conn, const char *seed) {
   348 	if(log_badargs_if2(conn==NULL, seed==NULL)) {
   348     if(log_badargs_if2(conn==NULL, seed==NULL)) {
   349 		return -1;
   349         return -1;
   350 	}
   350     }
   351 	if(conn->isChief) {
   351     if(conn->isChief) {
   352 		if(!sendStr(conn, "CFG\nSEED", seed)) {
   352         if(!sendStr(conn, "CFG\nSEED", seed)) {
   353 			char *copy = flib_strdupnull(seed);
   353             char *copy = flib_strdupnull(seed);
   354 			if(copy) {
   354             if(copy) {
   355 				free(conn->map->seed);
   355                 free(conn->map->seed);
   356 				conn->map->seed = copy;
   356                 conn->map->seed = copy;
   357 				return 0;
   357                 return 0;
   358 			}
   358             }
   359 		}
   359         }
   360 	}
   360     }
   361 	return -1;
   361     return -1;
   362 }
   362 }
   363 
   363 
   364 int flib_netconn_send_mapTheme(flib_netconn *conn, const char *theme) {
   364 int flib_netconn_send_mapTheme(flib_netconn *conn, const char *theme) {
   365 	if(log_badargs_if2(conn==NULL, theme==NULL)) {
   365     if(log_badargs_if2(conn==NULL, theme==NULL)) {
   366 		return -1;
   366         return -1;
   367 	}
   367     }
   368 	if(conn->isChief) {
   368     if(conn->isChief) {
   369 		if(!sendStr(conn, "CFG\nTHEME", theme)) {
   369         if(!sendStr(conn, "CFG\nTHEME", theme)) {
   370 			char *copy = flib_strdupnull(theme);
   370             char *copy = flib_strdupnull(theme);
   371 			if(copy) {
   371             if(copy) {
   372 				free(conn->map->theme);
   372                 free(conn->map->theme);
   373 				conn->map->theme = copy;
   373                 conn->map->theme = copy;
   374 				return 0;
   374                 return 0;
   375 			}
   375             }
   376 		}
   376         }
   377 	}
   377     }
   378 	return -1;
   378     return -1;
   379 }
   379 }
   380 
   380 
   381 int flib_netconn_send_mapDrawdata(flib_netconn *conn, const uint8_t *drawData, size_t size) {
   381 int flib_netconn_send_mapDrawdata(flib_netconn *conn, const uint8_t *drawData, size_t size) {
   382 	int result = -1;
   382     int result = -1;
   383 	if(!log_badargs_if3(conn==NULL, drawData==NULL && size>0, size>SIZE_MAX/2) && conn->isChief) {
   383     if(!log_badargs_if3(conn==NULL, drawData==NULL && size>0, size>SIZE_MAX/2) && conn->isChief) {
   384 		uLongf zippedSize = compressBound(size);
   384         uLongf zippedSize = compressBound(size);
   385 		uint8_t *zipped = flib_malloc(zippedSize+4); // 4 extra bytes for header
   385         uint8_t *zipped = flib_malloc(zippedSize+4); // 4 extra bytes for header
   386 		if(zipped) {
   386         if(zipped) {
   387 			// Create the QCompress size header (uint32 big endian)
   387             // Create the QCompress size header (uint32 big endian)
   388 			zipped[0] = (size>>24) & 0xff;
   388             zipped[0] = (size>>24) & 0xff;
   389 			zipped[1] = (size>>16) & 0xff;
   389             zipped[1] = (size>>16) & 0xff;
   390 			zipped[2] = (size>>8) & 0xff;
   390             zipped[2] = (size>>8) & 0xff;
   391 			zipped[3] = (size) & 0xff;
   391             zipped[3] = (size) & 0xff;
   392 
   392 
   393 			if(compress(zipped+4, &zippedSize, drawData, size) != Z_OK) {
   393             if(compress(zipped+4, &zippedSize, drawData, size) != Z_OK) {
   394 				flib_log_e("Error compressing drawn map data.");
   394                 flib_log_e("Error compressing drawn map data.");
   395 			} else {
   395             } else {
   396 				char *base64encout = NULL;
   396                 char *base64encout = NULL;
   397 				base64_encode_alloc((const char*)zipped, zippedSize+4, &base64encout);
   397                 base64_encode_alloc((const char*)zipped, zippedSize+4, &base64encout);
   398 				if(!base64encout) {
   398                 if(!base64encout) {
   399 					flib_log_e("Error base64-encoding drawn map data.");
   399                     flib_log_e("Error base64-encoding drawn map data.");
   400 				} else {
   400                 } else {
   401 					result = flib_netbase_sendf(conn->netBase, "CFG\nDRAWNMAP\n%s\n\n", base64encout);
   401                     result = flib_netbase_sendf(conn->netBase, "CFG\nDRAWNMAP\n%s\n\n", base64encout);
   402 				}
   402                 }
   403 				free(base64encout);
   403                 free(base64encout);
   404 			}
   404             }
   405 		}
   405         }
   406 		free(zipped);
   406         free(zipped);
   407 	}
   407     }
   408 
   408 
   409 	if(!result) {
   409     if(!result) {
   410 		uint8_t *copy = flib_bufdupnull(drawData, size);
   410         uint8_t *copy = flib_bufdupnull(drawData, size);
   411 		if(copy) {
   411         if(copy) {
   412 			free(conn->map->drawData);
   412             free(conn->map->drawData);
   413 			conn->map->drawData = copy;
   413             conn->map->drawData = copy;
   414 			conn->map->drawDataSize = size;
   414             conn->map->drawDataSize = size;
   415 		}
   415         }
   416 	}
   416     }
   417 	return result;
   417     return result;
   418 }
   418 }
   419 
   419 
   420 int flib_netconn_send_script(flib_netconn *conn, const char *scriptName) {
   420 int flib_netconn_send_script(flib_netconn *conn, const char *scriptName) {
   421 	if(log_badargs_if2(conn==NULL, scriptName==NULL)) {
   421     if(log_badargs_if2(conn==NULL, scriptName==NULL)) {
   422 		return -1;
   422         return -1;
   423 	}
   423     }
   424 	if(conn->isChief) {
   424     if(conn->isChief) {
   425 		if(!sendStr(conn, "CFG\nSCRIPT", scriptName)) {
   425         if(!sendStr(conn, "CFG\nSCRIPT", scriptName)) {
   426 			netconn_setScript(conn, scriptName);
   426             netconn_setScript(conn, scriptName);
   427 			return 0;
   427             return 0;
   428 		}
   428         }
   429 	}
   429     }
   430 	return -1;
   430     return -1;
   431 }
   431 }
   432 
   432 
   433 int flib_netconn_send_scheme(flib_netconn *conn, const flib_scheme *scheme) {
   433 int flib_netconn_send_scheme(flib_netconn *conn, const flib_scheme *scheme) {
   434 	int result = -1;
   434     int result = -1;
   435 	if(!log_badargs_if3(conn==NULL, scheme==NULL, flib_strempty(scheme->name)) && conn->isChief) {
   435     if(!log_badargs_if3(conn==NULL, scheme==NULL, flib_strempty(scheme->name)) && conn->isChief) {
   436 		flib_vector *vec = flib_vector_create();
   436         flib_vector *vec = flib_vector_create();
   437 		if(vec) {
   437         if(vec) {
   438 			bool error = false;
   438             bool error = false;
   439 			error |= flib_vector_appendf(vec, "CFG\nSCHEME\n%s\n", scheme->name);
   439             error |= flib_vector_appendf(vec, "CFG\nSCHEME\n%s\n", scheme->name);
   440 			for(int i=0; i<flib_meta.modCount; i++) {
   440             for(int i=0; i<flib_meta.modCount; i++) {
   441 				error |= flib_vector_appendf(vec, "%s\n", scheme->mods[i] ? "true" : "false");
   441                 error |= flib_vector_appendf(vec, "%s\n", scheme->mods[i] ? "true" : "false");
   442 			}
   442             }
   443 			for(int i=0; i<flib_meta.settingCount; i++) {
   443             for(int i=0; i<flib_meta.settingCount; i++) {
   444 				error |= flib_vector_appendf(vec, "%i\n", scheme->settings[i]);
   444                 error |= flib_vector_appendf(vec, "%i\n", scheme->settings[i]);
   445 			}
   445             }
   446 			error |= flib_vector_appendf(vec, "\n");
   446             error |= flib_vector_appendf(vec, "\n");
   447 			if(!error) {
   447             if(!error) {
   448 				result = flib_netbase_send_raw(conn->netBase, flib_vector_data(vec), flib_vector_size(vec));
   448                 result = flib_netbase_send_raw(conn->netBase, flib_vector_data(vec), flib_vector_size(vec));
   449 			}
   449             }
   450 		}
   450         }
   451 		flib_vector_destroy(vec);
   451         flib_vector_destroy(vec);
   452 	}
   452     }
   453 
   453 
   454 	if(!result) {
   454     if(!result) {
   455 		netconn_setScheme(conn, scheme);
   455         netconn_setScheme(conn, scheme);
   456 	}
   456     }
   457 	return result;
   457     return result;
   458 }
   458 }
   459 
   459 
   460 int flib_netconn_send_startGame(flib_netconn *conn) {
   460 int flib_netconn_send_startGame(flib_netconn *conn) {
   461 	return sendVoid(conn, "START_GAME");
   461     return sendVoid(conn, "START_GAME");
   462 }
   462 }
   463 
   463 
   464 int flib_netconn_send_toggleRestrictJoins(flib_netconn *conn) {
   464 int flib_netconn_send_toggleRestrictJoins(flib_netconn *conn) {
   465 	return sendVoid(conn, "TOGGLE_RESTRICT_JOINS");
   465     return sendVoid(conn, "TOGGLE_RESTRICT_JOINS");
   466 }
   466 }
   467 
   467 
   468 int flib_netconn_send_toggleRestrictTeams(flib_netconn *conn) {
   468 int flib_netconn_send_toggleRestrictTeams(flib_netconn *conn) {
   469 	return sendVoid(conn, "TOGGLE_RESTRICT_TEAMS");
   469     return sendVoid(conn, "TOGGLE_RESTRICT_TEAMS");
   470 }
   470 }
   471 
   471 
   472 int flib_netconn_send_teamchat(flib_netconn *conn, const char *chat) {
   472 int flib_netconn_send_teamchat(flib_netconn *conn, const char *chat) {
   473 	if(!flib_strempty(chat)) {
   473     if(!flib_strempty(chat)) {
   474 		return sendStr(conn, "TEAMCHAT", chat);
   474         return sendStr(conn, "TEAMCHAT", chat);
   475 	}
   475     }
   476 	return 0;
   476     return 0;
   477 }
   477 }
   478 
   478 
   479 int flib_netconn_send_engineMessage(flib_netconn *conn, const uint8_t *message, size_t size) {
   479 int flib_netconn_send_engineMessage(flib_netconn *conn, const uint8_t *message, size_t size) {
   480 	int result = -1;
   480     int result = -1;
   481 	if(!log_badargs_if2(conn==NULL, message==NULL && size>0)) {
   481     if(!log_badargs_if2(conn==NULL, message==NULL && size>0)) {
   482 		char *base64encout = NULL;
   482         char *base64encout = NULL;
   483 		base64_encode_alloc((const char*)message, size, &base64encout);
   483         base64_encode_alloc((const char*)message, size, &base64encout);
   484 		if(base64encout) {
   484         if(base64encout) {
   485 			result = flib_netbase_sendf(conn->netBase, "EM\n%s\n\n", base64encout);
   485             result = flib_netbase_sendf(conn->netBase, "EM\n%s\n\n", base64encout);
   486 		}
   486         }
   487 		free(base64encout);
   487         free(base64encout);
   488 	}
   488     }
   489 	return result;
   489     return result;
   490 }
   490 }
   491 
   491 
   492 int flib_netconn_send_roundfinished(flib_netconn *conn, bool withoutError) {
   492 int flib_netconn_send_roundfinished(flib_netconn *conn, bool withoutError) {
   493 	return sendInt(conn, "ROUNDFINISHED", withoutError ? 1 : 0);
   493     return sendInt(conn, "ROUNDFINISHED", withoutError ? 1 : 0);
   494 }
   494 }
   495 
   495