project_files/frontlib/ipc/ipcprotocol.c
changeset 7275 15f722e0b96f
parent 7271 5608ac657362
child 7314 6171f0bad318
equal deleted inserted replaced
7273:8eed495fd8da 7275:15f722e0b96f
     8 #include <inttypes.h>
     8 #include <inttypes.h>
     9 #include <stdlib.h>
     9 #include <stdlib.h>
    10 
    10 
    11 int flib_ipc_append_message(flib_vector *vec, const char *fmt, ...) {
    11 int flib_ipc_append_message(flib_vector *vec, const char *fmt, ...) {
    12 	int result = -1;
    12 	int result = -1;
    13 	if(!vec || !fmt) {
    13 	if(!log_badparams_if(!vec || !fmt)) {
    14 		flib_log_e("null parameter in flib_ipc_appendmessage");
       
    15 	} else {
       
    16 		// 1 byte size prefix, 255 bytes max message length, 1 0-byte for vsnprintf
    14 		// 1 byte size prefix, 255 bytes max message length, 1 0-byte for vsnprintf
    17 		char msgbuffer[257];
    15 		char msgbuffer[257];
    18 
    16 
    19 		// Format the message, leaving one byte at the start for the length
    17 		// Format the message, leaving one byte at the start for the length
    20 		va_list argp;
    18 		va_list argp;
    21 		va_start(argp, fmt);
    19 		va_start(argp, fmt);
    22 		int msgSize = vsnprintf(msgbuffer+1, 256, fmt, argp);
    20 		int msgSize = vsnprintf(msgbuffer+1, 256, fmt, argp);
    23 		va_end(argp);
    21 		va_end(argp);
    24 
    22 
    25 		if(msgSize > 255) {
    23 		if(!log_e_if(msgSize > 255, "Message too long (%u bytes)", (unsigned)msgSize)
    26 			flib_log_e("Message too long (%u bytes) in flib_ipc_appendmessage", (unsigned)msgSize);
    24 				&& !log_e_if(msgSize < 0, "printf error")) {
    27 		} else if(msgSize<0) {
       
    28 			flib_log_e("printf error in flib_ipc_appendmessage");
       
    29 		} else {
       
    30 			// Add the length prefix
    25 			// Add the length prefix
    31 			((uint8_t*)msgbuffer)[0] = msgSize;
    26 			((uint8_t*)msgbuffer)[0] = msgSize;
    32 
    27 
    33 			// Append it to the vector
    28 			// Append it to the vector
    34 			if(flib_vector_append(vec, msgbuffer, msgSize+1) == msgSize+1) {
    29 			result = flib_vector_append(vec, msgbuffer, msgSize+1);
    35 				result = 0;
       
    36 			}
       
    37 		}
    30 		}
    38 	}
    31 	}
    39 	return result;
    32 	return result;
    40 }
    33 }
    41 
    34 
    42 int flib_ipc_append_mapconf(flib_vector *vec, const flib_map *map, bool mappreview) {
    35 int flib_ipc_append_mapconf(flib_vector *vec, const flib_map *map, bool mappreview) {
    43 	int result = -1;
    36 	int result = -1;
    44 	flib_vector *tempvector = flib_vector_create();
    37 	flib_vector *tempvector = flib_vector_create();
    45 	if(!vec || !map) {
    38 	if(!log_badparams_if(!vec || !map)) {
    46 		flib_log_e("null parameter in flib_ipc_append_mapconf");
       
    47 	} else if(tempvector) {
       
    48 		bool error = false;
    39 		bool error = false;
    49 
    40 
    50 		if(map->mapgen == MAPGEN_NAMED) {
    41 		if(map->mapgen == MAPGEN_NAMED) {
    51 			if(map->name) {
    42 			error |= log_e_if(!map->name, "Missing map name")
    52 				error |= flib_ipc_append_message(tempvector, "emap %s", map->name);
    43 					|| flib_ipc_append_message(tempvector, "emap %s", map->name);
    53 			} else {
    44 		}
    54 				flib_log_e("Missing map name");
    45 		if(!mappreview) {
    55 				error = true;
    46 			error |= log_e_if(!map->theme, "Missing map theme")
    56 			}
    47 					|| flib_ipc_append_message(tempvector, "etheme %s", map->theme);
    57 		}
       
    58 		if(map->theme && !mappreview) {
       
    59 			if(map->theme) {
       
    60 				error |= flib_ipc_append_message(tempvector, "etheme %s", map->theme);
       
    61 			} else {
       
    62 				flib_log_e("Missing map theme");
       
    63 				error = true;
       
    64 			}
       
    65 		}
    48 		}
    66 		error |= flib_ipc_append_seed(tempvector, map->seed);
    49 		error |= flib_ipc_append_seed(tempvector, map->seed);
    67 		error |= flib_ipc_append_message(tempvector, "e$template_filter %i", map->templateFilter);
    50 		error |= flib_ipc_append_message(tempvector, "e$template_filter %i", map->templateFilter);
    68 		error |= flib_ipc_append_message(tempvector, "e$mapgen %i", map->mapgen);
    51 		error |= flib_ipc_append_message(tempvector, "e$mapgen %i", map->mapgen);
    69 
    52 
    79 			int edrawlen = strlen(edraw);
    62 			int edrawlen = strlen(edraw);
    80 			for(int offset=0; offset<map->drawDataSize; offset+=200) {
    63 			for(int offset=0; offset<map->drawDataSize; offset+=200) {
    81 				int bytesRemaining = map->drawDataSize-offset;
    64 				int bytesRemaining = map->drawDataSize-offset;
    82 				int fragmentsize = bytesRemaining < 200 ? bytesRemaining : 200;
    65 				int fragmentsize = bytesRemaining < 200 ? bytesRemaining : 200;
    83 				uint8_t messagesize = edrawlen + fragmentsize;
    66 				uint8_t messagesize = edrawlen + fragmentsize;
    84 				error |= (flib_vector_append(tempvector, &messagesize, 1) != 1);
    67 				error |= flib_vector_append(tempvector, &messagesize, 1);
    85 				error |= (flib_vector_append(tempvector, edraw, edrawlen) != edrawlen);
    68 				error |= flib_vector_append(tempvector, edraw, edrawlen);
    86 				error |= (flib_vector_append(tempvector, map->drawData+offset, fragmentsize) != fragmentsize);
    69 				error |= flib_vector_append(tempvector, map->drawData+offset, fragmentsize);
       
    70 			}
       
    71 		}
       
    72 
       
    73 		if(!log_e_if(error, "Error generating map config")) {
       
    74 			// Message created, now we can copy everything.
       
    75 			flib_constbuffer constbuf = flib_vector_as_constbuffer(tempvector);
       
    76 			if(!flib_vector_append(vec, constbuf.data, constbuf.size)) {
       
    77 				result = 0;
       
    78 			}
       
    79 		}
       
    80 	}
       
    81 	flib_vector_destroy(tempvector);
       
    82 	return result;
       
    83 }
       
    84 
       
    85 int flib_ipc_append_seed(flib_vector *vec, const char *seed) {
       
    86 	if(!log_badparams_if(!vec || !seed)) {
       
    87 		return flib_ipc_append_message(vec, "eseed %s", seed);
       
    88 	}
       
    89 	return -1;
       
    90 }
       
    91 
       
    92 int flib_ipc_append_script(flib_vector *vec, const char *script) {
       
    93 	int result = -1;
       
    94 	char *copy = flib_strdupnull(script);
       
    95 	if(!log_badparams_if(!vec) && copy) {
       
    96 		if(!strcmp("Normal", copy)) {
       
    97 			// "Normal" means no gametype script
       
    98 			result = 0;
       
    99 		} else {
       
   100 			size_t len = strlen(copy);
       
   101 			for(size_t i=0; i<len; i++) {
       
   102 				if(copy[i] == ' ') {
       
   103 					copy[i] = '_';
       
   104 				}
       
   105 			}
       
   106 
       
   107 			result = flib_ipc_append_message(vec, "escript %s%s.lua", MULTIPLAYER_SCRIPT_PATH, copy);
       
   108 		}
       
   109 	}
       
   110 	free(copy);
       
   111 	return result;
       
   112 }
       
   113 
       
   114 uint32_t buildModFlags(const flib_cfg *scheme) {
       
   115 	uint32_t result = 0;
       
   116 	for(int i=0; i<scheme->meta->modCount; i++) {
       
   117 		if(scheme->mods[i]) {
       
   118 			int bitmaskIndex = scheme->meta->mods[i].bitmaskIndex;
       
   119 			result |= (UINT32_C(1) << bitmaskIndex);
       
   120 		}
       
   121 	}
       
   122 	return result;
       
   123 }
       
   124 
       
   125 int flib_ipc_append_gamescheme(flib_vector *vec, const flib_cfg *scheme) {
       
   126 	int result = -1;
       
   127 	flib_vector *tempvector = flib_vector_create();
       
   128 	if(!log_badparams_if(!vec || !scheme) && tempvector) {
       
   129 		const flib_cfg_meta *meta = scheme->meta;
       
   130 		bool error = false;
       
   131 		error |= flib_ipc_append_message(tempvector, "e$gmflags %"PRIu32, buildModFlags(scheme));
       
   132 		for(int i=0; i<meta->settingCount; i++) {
       
   133 			if(meta->settings[i].engineCommand) {
       
   134 				int value = scheme->settings[i];
       
   135 				if(meta->settings[i].maxMeansInfinity) {
       
   136 					value = value>=meta->settings[i].max ? 9999 : value;
       
   137 				}
       
   138 				if(meta->settings[i].times1000) {
       
   139 					value *= 1000;
       
   140 				}
       
   141 				error |= flib_ipc_append_message(tempvector, "%s %i", meta->settings[i].engineCommand, value);
    87 			}
   142 			}
    88 		}
   143 		}
    89 
   144 
    90 		if(!error) {
   145 		if(!error) {
    91 			// Message created, now we can copy everything.
   146 			// Message created, now we can copy everything.
    92 			flib_constbuffer constbuf = flib_vector_as_constbuffer(tempvector);
   147 			flib_constbuffer constbuf = flib_vector_as_constbuffer(tempvector);
    93 			if(flib_vector_append(vec, constbuf.data, constbuf.size) == constbuf.size) {
   148 			if(!flib_vector_append(vec, constbuf.data, constbuf.size)) {
    94 				result = 0;
       
    95 			}
       
    96 		}
       
    97 	}
       
    98 	flib_vector_destroy(tempvector);
       
    99 	return result;
       
   100 }
       
   101 
       
   102 int flib_ipc_append_seed(flib_vector *vec, const char *seed) {
       
   103 	if(!vec || !seed) {
       
   104 		flib_log_e("null parameter in flib_ipc_append_seed");
       
   105 		return -1;
       
   106 	} else {
       
   107 		return flib_ipc_append_message(vec, "eseed %s", seed);
       
   108 	}
       
   109 }
       
   110 
       
   111 int flib_ipc_append_script(flib_vector *vec, const char *script) {
       
   112 	if(!vec || !script) {
       
   113 		flib_log_e("null parameter in flib_ipc_append_script");
       
   114 		return -1;
       
   115 	} else {
       
   116 		return flib_ipc_append_message(vec, "escript %s", script);
       
   117 	}
       
   118 }
       
   119 
       
   120 int flib_ipc_append_gamescheme(flib_vector *vec, const flib_cfg *scheme) {
       
   121 	int result = -1;
       
   122 	flib_vector *tempvector = flib_vector_create();
       
   123 	if(!vec || !scheme) {
       
   124 		flib_log_e("null parameter in flib_ipc_append_gamescheme");
       
   125 	} else if(tempvector) {
       
   126 		const flib_cfg_meta *meta = scheme->meta;
       
   127 		bool error = false;
       
   128 		uint32_t gamemods = 0;
       
   129 		for(int i=0; i<meta->modCount; i++) {
       
   130 			if(scheme->mods[i]) {
       
   131 				gamemods |= (1<<meta->mods[i].bitmaskIndex);
       
   132 			}
       
   133 		}
       
   134 		error |= flib_ipc_append_message(tempvector, "e$gmflags %"PRIu32, gamemods);
       
   135 		for(int i=0; i<meta->settingCount; i++) {
       
   136 			int value = scheme->settings[i];
       
   137 			if(meta->settings[i].maxMeansInfinity) {
       
   138 				value = value>=meta->settings[i].max ? 9999 : value;
       
   139 			}
       
   140 			if(meta->settings[i].times1000) {
       
   141 				value *= 1000;
       
   142 			}
       
   143 			error |= flib_ipc_append_message(tempvector, "%s %i", meta->settings[i].engineCommand, value);
       
   144 		}
       
   145 
       
   146 		if(!error) {
       
   147 			// Message created, now we can copy everything.
       
   148 			flib_constbuffer constbuf = flib_vector_as_constbuffer(tempvector);
       
   149 			if(flib_vector_append(vec, constbuf.data, constbuf.size) == constbuf.size) {
       
   150 				result = 0;
   149 				result = 0;
   151 			}
   150 			}
   152 		}
   151 		}
   153 	}
   152 	}
   154 	flib_vector_destroy(tempvector);
   153 	flib_vector_destroy(tempvector);
   163 }
   162 }
   164 
   163 
   165 int flib_ipc_append_addteam(flib_vector *vec, const flib_team *team, bool perHogAmmo, bool noAmmoStore) {
   164 int flib_ipc_append_addteam(flib_vector *vec, const flib_team *team, bool perHogAmmo, bool noAmmoStore) {
   166 	int result = -1;
   165 	int result = -1;
   167 	flib_vector *tempvector = flib_vector_create();
   166 	flib_vector *tempvector = flib_vector_create();
   168 	if(!vec || !team) {
   167 	if(!log_badparams_if(!vec || !team) && tempvector) {
   169 		flib_log_e("invalid parameter in flib_ipc_append_addteam");
       
   170 	} else if(tempvector) {
       
   171 		bool error = false;
   168 		bool error = false;
   172 
   169 
   173 		if(!perHogAmmo && !noAmmoStore) {
   170 		if(!perHogAmmo && !noAmmoStore) {
   174 			error |= appendWeaponSet(tempvector, team->hogs[0].weaponset);
   171 			error = error
   175 			error |= flib_ipc_append_message(tempvector, "eammstore");
   172 					|| appendWeaponSet(tempvector, team->hogs[0].weaponset)
       
   173 					|| flib_ipc_append_message(tempvector, "eammstore");
   176 		}
   174 		}
   177 
   175 
   178 		// TODO
   176 		// TODO
   179 		char *hash = team->ownerName ? team->ownerName : "00000000000000000000000000000000";
   177 		char *hash = team->ownerName ? team->ownerName : "00000000000000000000000000000000";
   180 		error |= flib_ipc_append_message(tempvector, "eaddteam %s %"PRIu32" %s", hash, team->color, team->name);
   178 		if(team->colorIndex<0 || team->colorIndex>=flib_teamcolor_defaults_len) {
       
   179 			flib_log_e("Color index out of bounds for team %s: %i", team->name, team->colorIndex);
       
   180 			error = true;
       
   181 		} else {
       
   182 			error |= flib_ipc_append_message(tempvector, "eaddteam %s %"PRIu32" %s", hash, flib_teamcolor_defaults[team->colorIndex], team->name);
       
   183 		}
   181 
   184 
   182 		if(team->remoteDriven) {
   185 		if(team->remoteDriven) {
   183 			error |= flib_ipc_append_message(tempvector, "erdriven");
   186 			error |= flib_ipc_append_message(tempvector, "erdriven");
   184 		}
   187 		}
   185 
   188 
   201 		}
   204 		}
   202 
   205 
   203 		if(!error) {
   206 		if(!error) {
   204 			// Message created, now we can copy everything.
   207 			// Message created, now we can copy everything.
   205 			flib_constbuffer constbuf = flib_vector_as_constbuffer(tempvector);
   208 			flib_constbuffer constbuf = flib_vector_as_constbuffer(tempvector);
   206 			if(flib_vector_append(vec, constbuf.data, constbuf.size) == constbuf.size) {
   209 			if(!flib_vector_append(vec, constbuf.data, constbuf.size)) {
   207 				result = 0;
   210 				result = 0;
   208 			}
   211 			}
   209 		}
   212 		}
   210 	}
   213 	}
   211 	flib_vector_destroy(tempvector);
   214 	flib_vector_destroy(tempvector);
   212 	return result;
   215 	return result;
   213 }
   216 }
   214 
   217 
   215 static bool getGameMod(const flib_cfg *conf, int maskbit) {
   218 static bool getGameMod(const flib_cfg *conf, const char *name) {
   216 	for(int i=0; i<conf->meta->modCount; i++) {
   219 	for(int i=0; i<conf->meta->modCount; i++) {
   217 		if(conf->meta->mods[i].bitmaskIndex == maskbit) {
   220 		if(!strcmp(conf->meta->mods[i].name, name)) {
   218 			return conf->mods[i];
   221 			return conf->mods[i];
   219 		}
   222 		}
   220 	}
   223 	}
   221 	flib_log_e("Unable to find game mod with mask bit %i", maskbit);
   224 	flib_log_e("Unable to find game mod %s", name);
   222 	return false;
   225 	return false;
   223 }
   226 }
   224 
   227 
   225 int flib_ipc_append_fullconfig(flib_vector *vec, const flib_gamesetup *setup, bool netgame) {
   228 int flib_ipc_append_fullconfig(flib_vector *vec, const flib_gamesetup *setup, bool netgame) {
   226 	int result = -1;
   229 	int result = -1;
   227 	flib_vector *tempvector = flib_vector_create();
   230 	flib_vector *tempvector = flib_vector_create();
   228 	if(!vec || !setup) {
   231 	if(!log_badparams_if(!vec || !setup) && tempvector) {
   229 		flib_log_e("null parameter in flib_ipc_append_fullconfig");
       
   230 	} else if(tempvector) {
       
   231 		bool error = false;
   232 		bool error = false;
   232 		bool perHogAmmo = false;
   233 		bool perHogAmmo = false;
   233 		bool sharedAmmo = false;
   234 		bool sharedAmmo = false;
   234 
   235 
   235 		error |= flib_ipc_append_message(vec, netgame ? "TN" : "TL");
   236 		error |= flib_ipc_append_message(vec, netgame ? "TN" : "TL");
   236 		if(setup->map) {
   237 		if(setup->map) {
   237 			error |= flib_ipc_append_mapconf(tempvector, setup->map, false);
   238 			error |= flib_ipc_append_mapconf(tempvector, setup->map, false);
   238 		}
   239 		}
   239 		if(setup->script) {
   240 		if(setup->script) {
   240 			error |= flib_ipc_append_message(tempvector, "escript %s", setup->script);
   241 			error |= flib_ipc_append_script(tempvector, setup->script);
   241 		}
   242 		}
   242 		if(setup->gamescheme) {
   243 		if(setup->gamescheme) {
   243 			error |= flib_ipc_append_gamescheme(tempvector, setup->gamescheme);
   244 			error |= flib_ipc_append_gamescheme(tempvector, setup->gamescheme);
   244 			sharedAmmo = getGameMod(setup->gamescheme, GAMEMOD_SHAREDAMMO_MASKBIT);
   245 			sharedAmmo = getGameMod(setup->gamescheme, "sharedammo");
   245 			// Shared ammo has priority over per-hog ammo
   246 			// Shared ammo has priority over per-hog ammo
   246 			perHogAmmo = !sharedAmmo && getGameMod(setup->gamescheme, GAMEMOD_PERHOGAMMO_MASKBIT);
   247 			perHogAmmo = !sharedAmmo && getGameMod(setup->gamescheme, "perhogammo");
   247 		}
   248 		}
   248 		if(setup->teams && setup->teamCount>0) {
   249 		if(setup->teamlist->teams && setup->teamlist->teamCount>0) {
   249 			uint32_t *clanColors = flib_calloc(setup->teamCount, sizeof(uint32_t));
   250 			int *clanColors = flib_calloc(setup->teamlist->teamCount, sizeof(int));
   250 			if(!clanColors) {
   251 			if(!clanColors) {
   251 				error = true;
   252 				error = true;
   252 			} else {
   253 			} else {
   253 				int clanCount = 0;
   254 				int clanCount = 0;
   254 				for(int i=0; i<setup->teamCount; i++) {
   255 				for(int i=0; !error && i<setup->teamlist->teamCount; i++) {
   255 					flib_team *team = setup->teams[i];
   256 					flib_team *team = setup->teamlist->teams[i];
       
   257 					// Find the clan index of this team (clans are identified by color).
   256 					bool newClan = false;
   258 					bool newClan = false;
   257 
       
   258 					// Find the clan index of this team (clans are identified by color).
       
   259 					// The upper 8 bits (alpha) are ignored in the engine as well.
       
   260 					uint32_t color = team->color&UINT32_C(0x00ffffff);
       
   261 					int clan = 0;
   259 					int clan = 0;
   262 					while(clan<clanCount && clanColors[clan] != color) {
   260 					while(clan<clanCount && clanColors[clan] != team->colorIndex) {
   263 						clan++;
   261 						clan++;
   264 					}
   262 					}
   265 					if(clan==clanCount) {
   263 					if(clan==clanCount) {
   266 						newClan = true;
   264 						newClan = true;
   267 						clanCount++;
   265 						clanCount++;
   268 						clanColors[clan] = color;
   266 						clanColors[clan] = team->colorIndex;
   269 					}
   267 					}
   270 
   268 
   271 					// If shared ammo is active, only add an ammo store for the first team in each clan.
   269 					// If shared ammo is active, only add an ammo store for the first team in each clan.
   272 					bool noAmmoStore = sharedAmmo&&!newClan;
   270 					bool noAmmoStore = sharedAmmo&&!newClan;
   273 					error |= flib_ipc_append_addteam(tempvector, setup->teams[i], perHogAmmo, noAmmoStore);
   271 					error |= flib_ipc_append_addteam(tempvector, setup->teamlist->teams[i], perHogAmmo, noAmmoStore);
   274 				}
   272 				}
   275 			}
   273 			}
   276 			free(clanColors);
   274 			free(clanColors);
   277 		}
   275 		}
   278 		error |= flib_ipc_append_message(tempvector, "!");
   276 		error |= flib_ipc_append_message(tempvector, "!");
   279 
   277 
   280 		if(!error) {
   278 		if(!error) {
   281 			// Message created, now we can copy everything.
   279 			// Message created, now we can copy everything.
   282 			flib_constbuffer constbuf = flib_vector_as_constbuffer(tempvector);
   280 			flib_constbuffer constbuf = flib_vector_as_constbuffer(tempvector);
   283 			if(flib_vector_append(vec, constbuf.data, constbuf.size) == constbuf.size) {
   281 			if(!flib_vector_append(vec, constbuf.data, constbuf.size)) {
   284 				result = 0;
   282 				result = 0;
   285 			}
   283 			}
   286 		}
   284 		}
   287 	}
   285 	}
   288 	return result;
   286 	return result;
   289 }
   287 }