project_files/frontlib/ipc/ipcprotocol.c
changeset 10017 de822cd3df3a
parent 7497 7e1d72fc03c7
equal deleted inserted replaced
10015:4feced261c68 10017:de822cd3df3a
    27 #include <string.h>
    27 #include <string.h>
    28 #include <inttypes.h>
    28 #include <inttypes.h>
    29 #include <stdlib.h>
    29 #include <stdlib.h>
    30 
    30 
    31 int flib_ipc_append_message(flib_vector *vec, const char *fmt, ...) {
    31 int flib_ipc_append_message(flib_vector *vec, const char *fmt, ...) {
    32 	int result = -1;
    32     int result = -1;
    33 	if(!log_badargs_if2(vec==NULL, fmt==NULL)) {
    33     if(!log_badargs_if2(vec==NULL, fmt==NULL)) {
    34 		// 1 byte size prefix, 255 bytes max message length, 1 0-byte for vsnprintf
    34         // 1 byte size prefix, 255 bytes max message length, 1 0-byte for vsnprintf
    35 		char msgbuffer[257];
    35         char msgbuffer[257];
    36 
    36 
    37 		// Format the message, leaving one byte at the start for the length
    37         // Format the message, leaving one byte at the start for the length
    38 		va_list argp;
    38         va_list argp;
    39 		va_start(argp, fmt);
    39         va_start(argp, fmt);
    40 		int msgSize = vsnprintf(msgbuffer+1, 256, fmt, argp);
    40         int msgSize = vsnprintf(msgbuffer+1, 256, fmt, argp);
    41 		va_end(argp);
    41         va_end(argp);
    42 
    42 
    43 		if(!log_e_if(msgSize > 255, "Message too long (%u bytes)", (unsigned)msgSize)
    43         if(!log_e_if(msgSize > 255, "Message too long (%u bytes)", (unsigned)msgSize)
    44 				&& !log_e_if(msgSize < 0, "printf error")) {
    44                 && !log_e_if(msgSize < 0, "printf error")) {
    45 			// Add the length prefix
    45             // Add the length prefix
    46 			((uint8_t*)msgbuffer)[0] = msgSize;
    46             ((uint8_t*)msgbuffer)[0] = msgSize;
    47 
    47 
    48 			// Append it to the vector
    48             // Append it to the vector
    49 			result = flib_vector_append(vec, msgbuffer, msgSize+1);
    49             result = flib_vector_append(vec, msgbuffer, msgSize+1);
    50 		}
    50         }
    51 	}
    51     }
    52 	return result;
    52     return result;
    53 }
    53 }
    54 
    54 
    55 int flib_ipc_append_mapconf(flib_vector *vec, const flib_map *map, bool mappreview) {
    55 int flib_ipc_append_mapconf(flib_vector *vec, const flib_map *map, bool mappreview) {
    56 	int result = -1;
    56     int result = -1;
    57 	flib_vector *tempvector = flib_vector_create();
    57     flib_vector *tempvector = flib_vector_create();
    58 	if(!log_badargs_if2(vec==NULL, map==NULL)) {
    58     if(!log_badargs_if2(vec==NULL, map==NULL)) {
    59 		bool error = false;
    59         bool error = false;
    60 
    60 
    61 		if(map->mapgen == MAPGEN_NAMED) {
    61         if(map->mapgen == MAPGEN_NAMED) {
    62 			error |= log_e_if(!map->name, "Missing map name")
    62             error |= log_e_if(!map->name, "Missing map name")
    63 					|| flib_ipc_append_message(tempvector, "emap %s", map->name);
    63                     || flib_ipc_append_message(tempvector, "emap %s", map->name);
    64 		}
    64         }
    65 		if(!mappreview) {
    65         if(!mappreview) {
    66 			error |= log_e_if(!map->theme, "Missing map theme")
    66             error |= log_e_if(!map->theme, "Missing map theme")
    67 					|| flib_ipc_append_message(tempvector, "etheme %s", map->theme);
    67                     || flib_ipc_append_message(tempvector, "etheme %s", map->theme);
    68 		}
    68         }
    69 		error |= flib_ipc_append_seed(tempvector, map->seed);
    69         error |= flib_ipc_append_seed(tempvector, map->seed);
    70 		error |= flib_ipc_append_message(tempvector, "e$template_filter %i", map->templateFilter);
    70         error |= flib_ipc_append_message(tempvector, "e$template_filter %i", map->templateFilter);
    71 		error |= flib_ipc_append_message(tempvector, "e$mapgen %i", map->mapgen);
    71         error |= flib_ipc_append_message(tempvector, "e$mapgen %i", map->mapgen);
    72 
    72 
    73 		if(map->mapgen == MAPGEN_MAZE) {
    73         if(map->mapgen == MAPGEN_MAZE) {
    74 			error |= flib_ipc_append_message(tempvector, "e$maze_size %i", map->mazeSize);
    74             error |= flib_ipc_append_message(tempvector, "e$maze_size %i", map->mazeSize);
    75 		}
    75         }
    76 		if(map->mapgen == MAPGEN_DRAWN) {
    76         if(map->mapgen == MAPGEN_DRAWN) {
    77 			/*
    77             /*
    78 			 * We have to split the drawn map data into several edraw messages here because
    78              * We have to split the drawn map data into several edraw messages here because
    79 			 * it can be longer than the maximum message size.
    79              * it can be longer than the maximum message size.
    80 			 */
    80              */
    81 			const char *edraw = "edraw ";
    81             const char *edraw = "edraw ";
    82 			int edrawlen = strlen(edraw);
    82             int edrawlen = strlen(edraw);
    83 			for(size_t offset=0; offset<map->drawDataSize; offset+=200) {
    83             for(size_t offset=0; offset<map->drawDataSize; offset+=200) {
    84 				size_t bytesRemaining = map->drawDataSize-offset;
    84                 size_t bytesRemaining = map->drawDataSize-offset;
    85 				int fragmentsize = bytesRemaining < 200 ? bytesRemaining : 200;
    85                 int fragmentsize = bytesRemaining < 200 ? bytesRemaining : 200;
    86 				uint8_t messagesize = edrawlen + fragmentsize;
    86                 uint8_t messagesize = edrawlen + fragmentsize;
    87 				error |= flib_vector_append(tempvector, &messagesize, 1);
    87                 error |= flib_vector_append(tempvector, &messagesize, 1);
    88 				error |= flib_vector_append(tempvector, edraw, edrawlen);
    88                 error |= flib_vector_append(tempvector, edraw, edrawlen);
    89 				error |= flib_vector_append(tempvector, map->drawData+offset, fragmentsize);
    89                 error |= flib_vector_append(tempvector, map->drawData+offset, fragmentsize);
    90 			}
    90             }
    91 		}
    91         }
    92 
    92 
    93 		if(!log_e_if(error, "Error generating map config")) {
    93         if(!log_e_if(error, "Error generating map config")) {
    94 			// Message created, now we can copy everything.
    94             // Message created, now we can copy everything.
    95 			flib_constbuffer constbuf = flib_vector_as_constbuffer(tempvector);
    95             flib_constbuffer constbuf = flib_vector_as_constbuffer(tempvector);
    96 			if(!flib_vector_append(vec, constbuf.data, constbuf.size)) {
    96             if(!flib_vector_append(vec, constbuf.data, constbuf.size)) {
    97 				result = 0;
    97                 result = 0;
    98 			}
    98             }
    99 		}
    99         }
   100 	}
   100     }
   101 	flib_vector_destroy(tempvector);
   101     flib_vector_destroy(tempvector);
   102 	return result;
   102     return result;
   103 }
   103 }
   104 
   104 
   105 int flib_ipc_append_seed(flib_vector *vec, const char *seed) {
   105 int flib_ipc_append_seed(flib_vector *vec, const char *seed) {
   106 	if(log_badargs_if2(vec==NULL, seed==NULL)) {
   106     if(log_badargs_if2(vec==NULL, seed==NULL)) {
   107 		return -1;
   107         return -1;
   108 	}
   108     }
   109 	return flib_ipc_append_message(vec, "eseed %s", seed);
   109     return flib_ipc_append_message(vec, "eseed %s", seed);
   110 }
   110 }
   111 
   111 
   112 int flib_ipc_append_script(flib_vector *vec, const char *script) {
   112 int flib_ipc_append_script(flib_vector *vec, const char *script) {
   113 	int result = -1;
   113     int result = -1;
   114 	if(!log_badargs_if2(vec==NULL, script==NULL)) {
   114     if(!log_badargs_if2(vec==NULL, script==NULL)) {
   115 		result = flib_ipc_append_message(vec, "escript %s", script);
   115         result = flib_ipc_append_message(vec, "escript %s", script);
   116 	}
   116     }
   117 	return result;
   117     return result;
   118 }
   118 }
   119 
   119 
   120 int flib_ipc_append_style(flib_vector *vec, const char *style) {
   120 int flib_ipc_append_style(flib_vector *vec, const char *style) {
   121 	int result = -1;
   121     int result = -1;
   122 	char *copy = flib_strdupnull(style);
   122     char *copy = flib_strdupnull(style);
   123 	if(!log_badargs_if(vec==NULL) && copy) {
   123     if(!log_badargs_if(vec==NULL) && copy) {
   124 		if(!strcmp("Normal", copy)) {
   124         if(!strcmp("Normal", copy)) {
   125 			// "Normal" means no gametype script
   125             // "Normal" means no gametype script
   126 			// TODO if an empty script called "Normal" is added to the scripts directory this can be removed
   126             // TODO if an empty script called "Normal" is added to the scripts directory this can be removed
   127 			result = 0;
   127             result = 0;
   128 		} else {
   128         } else {
   129 			size_t len = strlen(copy);
   129             size_t len = strlen(copy);
   130 			for(size_t i=0; i<len; i++) {
   130             for(size_t i=0; i<len; i++) {
   131 				if(copy[i] == ' ') {
   131                 if(copy[i] == ' ') {
   132 					copy[i] = '_';
   132                     copy[i] = '_';
   133 				}
   133                 }
   134 			}
   134             }
   135 
   135 
   136 			result = flib_ipc_append_message(vec, "escript %s%s.lua", MULTIPLAYER_SCRIPT_PATH, copy);
   136             result = flib_ipc_append_message(vec, "escript %s%s.lua", MULTIPLAYER_SCRIPT_PATH, copy);
   137 		}
   137         }
   138 	}
   138     }
   139 	free(copy);
   139     free(copy);
   140 	return result;
   140     return result;
   141 }
   141 }
   142 
   142 
   143 static uint32_t buildModFlags(const flib_scheme *scheme) {
   143 static uint32_t buildModFlags(const flib_scheme *scheme) {
   144 	uint32_t result = 0;
   144     uint32_t result = 0;
   145 	for(int i=0; i<flib_meta.modCount; i++) {
   145     for(int i=0; i<flib_meta.modCount; i++) {
   146 		if(scheme->mods[i]) {
   146         if(scheme->mods[i]) {
   147 			int bitmaskIndex = flib_meta.mods[i].bitmaskIndex;
   147             int bitmaskIndex = flib_meta.mods[i].bitmaskIndex;
   148 			result |= (UINT32_C(1) << bitmaskIndex);
   148             result |= (UINT32_C(1) << bitmaskIndex);
   149 		}
   149         }
   150 	}
   150     }
   151 	return result;
   151     return result;
   152 }
   152 }
   153 
   153 
   154 int flib_ipc_append_gamescheme(flib_vector *vec, const flib_scheme *scheme) {
   154 int flib_ipc_append_gamescheme(flib_vector *vec, const flib_scheme *scheme) {
   155 	int result = -1;
   155     int result = -1;
   156 	flib_vector *tempvector = flib_vector_create();
   156     flib_vector *tempvector = flib_vector_create();
   157 	if(!log_badargs_if2(vec==NULL, scheme==NULL) && tempvector) {
   157     if(!log_badargs_if2(vec==NULL, scheme==NULL) && tempvector) {
   158 		bool error = false;
   158         bool error = false;
   159 		error |= flib_ipc_append_message(tempvector, "e$gmflags %"PRIu32, buildModFlags(scheme));
   159         error |= flib_ipc_append_message(tempvector, "e$gmflags %"PRIu32, buildModFlags(scheme));
   160 		for(int i=0; i<flib_meta.settingCount; i++) {
   160         for(int i=0; i<flib_meta.settingCount; i++) {
   161 			if(flib_meta.settings[i].engineCommand) {
   161             if(flib_meta.settings[i].engineCommand) {
   162 				int value = scheme->settings[i];
   162                 int value = scheme->settings[i];
   163 				if(flib_meta.settings[i].maxMeansInfinity) {
   163                 if(flib_meta.settings[i].maxMeansInfinity) {
   164 					value = value>=flib_meta.settings[i].max ? 9999 : value;
   164                     value = value>=flib_meta.settings[i].max ? 9999 : value;
   165 				}
   165                 }
   166 				if(flib_meta.settings[i].times1000) {
   166                 if(flib_meta.settings[i].times1000) {
   167 					value *= 1000;
   167                     value *= 1000;
   168 				}
   168                 }
   169 				error |= flib_ipc_append_message(tempvector, "%s %i", flib_meta.settings[i].engineCommand, value);
   169                 error |= flib_ipc_append_message(tempvector, "%s %i", flib_meta.settings[i].engineCommand, value);
   170 			}
   170             }
   171 		}
   171         }
   172 
   172 
   173 		if(!error) {
   173         if(!error) {
   174 			// Message created, now we can copy everything.
   174             // Message created, now we can copy everything.
   175 			flib_constbuffer constbuf = flib_vector_as_constbuffer(tempvector);
   175             flib_constbuffer constbuf = flib_vector_as_constbuffer(tempvector);
   176 			if(!flib_vector_append(vec, constbuf.data, constbuf.size)) {
   176             if(!flib_vector_append(vec, constbuf.data, constbuf.size)) {
   177 				result = 0;
   177                 result = 0;
   178 			}
   178             }
   179 		}
   179         }
   180 	}
   180     }
   181 	flib_vector_destroy(tempvector);
   181     flib_vector_destroy(tempvector);
   182 	return result;
   182     return result;
   183 }
   183 }
   184 
   184 
   185 static int appendWeaponSet(flib_vector *vec, flib_weaponset *set) {
   185 static int appendWeaponSet(flib_vector *vec, flib_weaponset *set) {
   186 	return flib_ipc_append_message(vec, "eammloadt %s", set->loadout)
   186     return flib_ipc_append_message(vec, "eammloadt %s", set->loadout)
   187 		|| flib_ipc_append_message(vec, "eammprob %s", set->crateprob)
   187         || flib_ipc_append_message(vec, "eammprob %s", set->crateprob)
   188 		|| flib_ipc_append_message(vec, "eammdelay %s", set->delay)
   188         || flib_ipc_append_message(vec, "eammdelay %s", set->delay)
   189 		|| flib_ipc_append_message(vec, "eammreinf %s", set->crateammo);
   189         || flib_ipc_append_message(vec, "eammreinf %s", set->crateammo);
   190 }
   190 }
   191 
   191 
   192 static void calculateMd5Hex(const char *in, char out[33]) {
   192 static void calculateMd5Hex(const char *in, char out[33]) {
   193 	md5_state_t md5state;
   193     md5_state_t md5state;
   194 	uint8_t md5bytes[16];
   194     uint8_t md5bytes[16];
   195 	md5_init(&md5state);
   195     md5_init(&md5state);
   196 	md5_append(&md5state, (unsigned char*)in, strlen(in));
   196     md5_append(&md5state, (unsigned char*)in, strlen(in));
   197 	md5_finish(&md5state, md5bytes);
   197     md5_finish(&md5state, md5bytes);
   198 	for(int i=0;i<sizeof(md5bytes); i++) {
   198     for(int i=0;i<sizeof(md5bytes); i++) {
   199 		snprintf(out+i*2, 3, "%02x", (unsigned)md5bytes[i]);
   199         snprintf(out+i*2, 3, "%02x", (unsigned)md5bytes[i]);
   200 	}
   200     }
   201 }
   201 }
   202 
   202 
   203 static int flib_ipc_append_addteam(flib_vector *vec, const flib_team *team, bool perHogAmmo, bool noAmmoStore) {
   203 static int flib_ipc_append_addteam(flib_vector *vec, const flib_team *team, bool perHogAmmo, bool noAmmoStore) {
   204 	int result = -1;
   204     int result = -1;
   205 	flib_vector *tempvector = flib_vector_create();
   205     flib_vector *tempvector = flib_vector_create();
   206 	if(!log_badargs_if2(vec==NULL, team==NULL) && tempvector) {
   206     if(!log_badargs_if2(vec==NULL, team==NULL) && tempvector) {
   207 		bool error = false;
   207         bool error = false;
   208 
   208 
   209 		if(!perHogAmmo && !noAmmoStore) {
   209         if(!perHogAmmo && !noAmmoStore) {
   210 			error = error
   210             error = error
   211 					|| appendWeaponSet(tempvector, team->hogs[0].weaponset)
   211                     || appendWeaponSet(tempvector, team->hogs[0].weaponset)
   212 					|| flib_ipc_append_message(tempvector, "eammstore");
   212                     || flib_ipc_append_message(tempvector, "eammstore");
   213 		}
   213         }
   214 
   214 
   215 		char md5Hex[33];
   215         char md5Hex[33];
   216 		calculateMd5Hex(team->ownerName ? team->ownerName : "", md5Hex);
   216         calculateMd5Hex(team->ownerName ? team->ownerName : "", md5Hex);
   217 		if(team->colorIndex<0 || team->colorIndex>=flib_teamcolor_count) {
   217         if(team->colorIndex<0 || team->colorIndex>=flib_teamcolor_count) {
   218 			flib_log_e("Color index out of bounds for team %s: %i", team->name, team->colorIndex);
   218             flib_log_e("Color index out of bounds for team %s: %i", team->name, team->colorIndex);
   219 			error = true;
   219             error = true;
   220 		} else {
   220         } else {
   221 			error |= flib_ipc_append_message(tempvector, "eaddteam %s %"PRIu32" %s", md5Hex, flib_teamcolors[team->colorIndex], team->name);
   221             error |= flib_ipc_append_message(tempvector, "eaddteam %s %"PRIu32" %s", md5Hex, flib_teamcolors[team->colorIndex], team->name);
   222 		}
   222         }
   223 
   223 
   224 		if(team->remoteDriven) {
   224         if(team->remoteDriven) {
   225 			error |= flib_ipc_append_message(tempvector, "erdriven");
   225             error |= flib_ipc_append_message(tempvector, "erdriven");
   226 		}
   226         }
   227 
   227 
   228 		error |= flib_ipc_append_message(tempvector, "egrave %s", team->grave);
   228         error |= flib_ipc_append_message(tempvector, "egrave %s", team->grave);
   229 		error |= flib_ipc_append_message(tempvector, "efort %s", team->fort);
   229         error |= flib_ipc_append_message(tempvector, "efort %s", team->fort);
   230 		error |= flib_ipc_append_message(tempvector, "evoicepack %s", team->voicepack);
   230         error |= flib_ipc_append_message(tempvector, "evoicepack %s", team->voicepack);
   231 		error |= flib_ipc_append_message(tempvector, "eflag %s", team->flag);
   231         error |= flib_ipc_append_message(tempvector, "eflag %s", team->flag);
   232 
   232 
   233 		for(int i=0; i<team->bindingCount; i++) {
   233         for(int i=0; i<team->bindingCount; i++) {
   234 			error |= flib_ipc_append_message(tempvector, "ebind %s %s", team->bindings[i].binding, team->bindings[i].action);
   234             error |= flib_ipc_append_message(tempvector, "ebind %s %s", team->bindings[i].binding, team->bindings[i].action);
   235 		}
   235         }
   236 
   236 
   237 		for(int i=0; i<team->hogsInGame; i++) {
   237         for(int i=0; i<team->hogsInGame; i++) {
   238 			if(perHogAmmo && !noAmmoStore) {
   238             if(perHogAmmo && !noAmmoStore) {
   239 				error |= appendWeaponSet(tempvector, team->hogs[i].weaponset);
   239                 error |= appendWeaponSet(tempvector, team->hogs[i].weaponset);
   240 			}
   240             }
   241 			error |= flib_ipc_append_message(tempvector, "eaddhh %i %i %s", team->hogs[i].difficulty, team->hogs[i].initialHealth, team->hogs[i].name);
   241             error |= flib_ipc_append_message(tempvector, "eaddhh %i %i %s", team->hogs[i].difficulty, team->hogs[i].initialHealth, team->hogs[i].name);
   242 			error |= flib_ipc_append_message(tempvector, "ehat %s", team->hogs[i].hat);
   242             error |= flib_ipc_append_message(tempvector, "ehat %s", team->hogs[i].hat);
   243 		}
   243         }
   244 
   244 
   245 		if(!error) {
   245         if(!error) {
   246 			// Message created, now we can copy everything.
   246             // Message created, now we can copy everything.
   247 			flib_constbuffer constbuf = flib_vector_as_constbuffer(tempvector);
   247             flib_constbuffer constbuf = flib_vector_as_constbuffer(tempvector);
   248 			if(!flib_vector_append(vec, constbuf.data, constbuf.size)) {
   248             if(!flib_vector_append(vec, constbuf.data, constbuf.size)) {
   249 				result = 0;
   249                 result = 0;
   250 			}
   250             }
   251 		}
   251         }
   252 	}
   252     }
   253 	flib_vector_destroy(tempvector);
   253     flib_vector_destroy(tempvector);
   254 	return result;
   254     return result;
   255 }
   255 }
   256 
   256 
   257 int flib_ipc_append_fullconfig(flib_vector *vec, const flib_gamesetup *setup, bool netgame) {
   257 int flib_ipc_append_fullconfig(flib_vector *vec, const flib_gamesetup *setup, bool netgame) {
   258 	int result = -1;
   258     int result = -1;
   259 	flib_vector *tempvector = flib_vector_create();
   259     flib_vector *tempvector = flib_vector_create();
   260 	if(!log_badargs_if2(vec==NULL, setup==NULL) && tempvector) {
   260     if(!log_badargs_if2(vec==NULL, setup==NULL) && tempvector) {
   261 		bool error = false;
   261         bool error = false;
   262 		bool perHogAmmo = false;
   262         bool perHogAmmo = false;
   263 		bool sharedAmmo = false;
   263         bool sharedAmmo = false;
   264 
   264 
   265 		error |= flib_ipc_append_message(vec, netgame ? "TN" : "TL");
   265         error |= flib_ipc_append_message(vec, netgame ? "TN" : "TL");
   266 		if(setup->map) {
   266         if(setup->map) {
   267 			error |= flib_ipc_append_mapconf(tempvector, setup->map, false);
   267             error |= flib_ipc_append_mapconf(tempvector, setup->map, false);
   268 		}
   268         }
   269 		if(setup->style) {
   269         if(setup->style) {
   270 			error |= flib_ipc_append_style(tempvector, setup->style);
   270             error |= flib_ipc_append_style(tempvector, setup->style);
   271 		}
   271         }
   272 		if(setup->gamescheme) {
   272         if(setup->gamescheme) {
   273 			error |= flib_ipc_append_gamescheme(tempvector, setup->gamescheme);
   273             error |= flib_ipc_append_gamescheme(tempvector, setup->gamescheme);
   274 			sharedAmmo = flib_scheme_get_mod(setup->gamescheme, "sharedammo");
   274             sharedAmmo = flib_scheme_get_mod(setup->gamescheme, "sharedammo");
   275 			// Shared ammo has priority over per-hog ammo
   275             // Shared ammo has priority over per-hog ammo
   276 			perHogAmmo = !sharedAmmo && flib_scheme_get_mod(setup->gamescheme, "perhogammo");
   276             perHogAmmo = !sharedAmmo && flib_scheme_get_mod(setup->gamescheme, "perhogammo");
   277 		}
   277         }
   278 		if(setup->teamlist->teams && setup->teamlist->teamCount>0) {
   278         if(setup->teamlist->teams && setup->teamlist->teamCount>0) {
   279 			int *clanColors = flib_calloc(setup->teamlist->teamCount, sizeof(int));
   279             int *clanColors = flib_calloc(setup->teamlist->teamCount, sizeof(int));
   280 			if(!clanColors) {
   280             if(!clanColors) {
   281 				error = true;
   281                 error = true;
   282 			} else {
   282             } else {
   283 				int clanCount = 0;
   283                 int clanCount = 0;
   284 				for(int i=0; !error && i<setup->teamlist->teamCount; i++) {
   284                 for(int i=0; !error && i<setup->teamlist->teamCount; i++) {
   285 					flib_team *team = setup->teamlist->teams[i];
   285                     flib_team *team = setup->teamlist->teams[i];
   286 					// Find the clan index of this team (clans are identified by color).
   286                     // Find the clan index of this team (clans are identified by color).
   287 					bool newClan = false;
   287                     bool newClan = false;
   288 					int clan = 0;
   288                     int clan = 0;
   289 					while(clan<clanCount && clanColors[clan] != team->colorIndex) {
   289                     while(clan<clanCount && clanColors[clan] != team->colorIndex) {
   290 						clan++;
   290                         clan++;
   291 					}
   291                     }
   292 					if(clan==clanCount) {
   292                     if(clan==clanCount) {
   293 						newClan = true;
   293                         newClan = true;
   294 						clanCount++;
   294                         clanCount++;
   295 						clanColors[clan] = team->colorIndex;
   295                         clanColors[clan] = team->colorIndex;
   296 					}
   296                     }
   297 
   297 
   298 					// If shared ammo is active, only add an ammo store for the first team in each clan.
   298                     // If shared ammo is active, only add an ammo store for the first team in each clan.
   299 					bool noAmmoStore = sharedAmmo&&!newClan;
   299                     bool noAmmoStore = sharedAmmo&&!newClan;
   300 					error |= flib_ipc_append_addteam(tempvector, setup->teamlist->teams[i], perHogAmmo, noAmmoStore);
   300                     error |= flib_ipc_append_addteam(tempvector, setup->teamlist->teams[i], perHogAmmo, noAmmoStore);
   301 				}
   301                 }
   302 			}
   302             }
   303 			free(clanColors);
   303             free(clanColors);
   304 		}
   304         }
   305 		error |= flib_ipc_append_message(tempvector, "!");
   305         error |= flib_ipc_append_message(tempvector, "!");
   306 
   306 
   307 		if(!error) {
   307         if(!error) {
   308 			// Message created, now we can copy everything.
   308             // Message created, now we can copy everything.
   309 			flib_constbuffer constbuf = flib_vector_as_constbuffer(tempvector);
   309             flib_constbuffer constbuf = flib_vector_as_constbuffer(tempvector);
   310 			if(!flib_vector_append(vec, constbuf.data, constbuf.size)) {
   310             if(!flib_vector_append(vec, constbuf.data, constbuf.size)) {
   311 				result = 0;
   311                 result = 0;
   312 			}
   312             }
   313 		}
   313         }
   314 	}
   314     }
   315 	return result;
   315     return result;
   316 }
   316 }