Exemple #1
0
/**
 * @return @c true if are a compatible client and nothing else must be downloaded or no downloads are still running,
 * @c false if the start of the match must get a little bit postponed (running downloads).
 * @note throws ERR_DISCONNECT if we are not compatible to the server
 */
static bool CL_CanMultiplayerStart (void)
{
	const int day = CL_GetConfigStringInteger(CS_LIGHTMAP);
	const char* serverVersion = CL_GetConfigString(CS_VERSION);

	/* checksum doesn't match with the one the server gave us via configstring */
	if (!Q_streq(UFO_VERSION, serverVersion)) {
		Com_sprintf(popupText, sizeof(popupText), _("Local game version (%s) differs from the server version (%s)"), UFO_VERSION, serverVersion);
		UI_Popup(_("Error"), popupText);
		Com_Error(ERR_DISCONNECT, "Local game version (%s) differs from the server version (%s)", UFO_VERSION, serverVersion);
	/* amount of objects from script files doesn't match */
	} else if (csi.numODs != CL_GetConfigStringInteger(CS_OBJECTAMOUNT)) {
		UI_Popup(_("Error"), _("Script files are not the same"));
		Com_Error(ERR_DISCONNECT, "Script files are not the same");
	}

	/* activate the map loading screen for multiplayer, too */
	SCR_BeginLoadingPlaque();

	/* check download */
	if (cls.downloadMaps) { /* confirm map */
		if (CL_DownloadMap(CL_GetConfigString(CS_NAME)))
			return false;
		cls.downloadMaps = false;
	}

	/* map might still be downloading? */
	if (CL_PendingHTTPDownloads())
		return false;

	if (Com_GetScriptChecksum() != CL_GetConfigStringInteger(CS_UFOCHECKSUM))
		Com_Printf("You are using modified ufo script files - might produce problems\n");

	CM_LoadMap(CL_GetConfigString(CS_TILES), day, CL_GetConfigString(CS_POSITIONS), CL_GetConfigString(CS_ENTITYSTRING), cl.mapData, cl.mapTiles);

#if 0
	if (cl.mapData->mapChecksum != CL_GetConfigStringInteger(CS_MAPCHECKSUM)) {
		UI_Popup(_("Error"), _("Local map version differs from server"));
		Com_Error(ERR_DISCONNECT, "Local map version differs from server: %u != '%i'",
			cl.mapData->mapChecksum, CL_GetConfigStringInteger(CS_MAPCHECKSUM));
	}
#endif

	return true;
}
Exemple #2
0
/**
 * @brief Change the server to a new map, taking all connected clients along with it.
 * @note the full syntax is: @code map [day|night] [+]<map> [<assembly>] @endcode
 * @sa SV_AssembleMap
 * @sa CM_LoadMap
 * @sa Com_SetServerState
 */
void SV_Map (qboolean day, const char *levelstring, const char *assembly)
{
	int i;
	unsigned checksum = 0;
	char * map = SV_GetConfigString(CS_TILES);
	char * pos = SV_GetConfigString(CS_POSITIONS);
	mapInfo_t *randomMap = NULL;
	client_t *cl;

	/* any partially connected client will be restarted */
	Com_SetServerState(ss_restart);

	/* the game is just starting */
	SV_InitGame();

	if (!svs.initialized) {
		Com_Printf("Could not spawn the server\n");
		return;
	}

	assert(levelstring[0] != '\0');

	Com_DPrintf(DEBUG_SERVER, "SpawnServer: %s\n", levelstring);

	/* save name for levels that don't set message */
	SV_SetConfigString(CS_NAME, levelstring);
	SV_SetConfigString(CS_LIGHTMAP, day);

	Q_strncpyz(sv->name, levelstring, sizeof(sv->name));

	/* set serverinfo variable */
	sv_mapname = Cvar_FullSet("sv_mapname", sv->name, CVAR_SERVERINFO | CVAR_NOSET);

	/* notify the client in case of a listening server */
	SCR_BeginLoadingPlaque();

	if (assembly)
		Q_strncpyz(sv->assembly, assembly, sizeof(sv->assembly));
	else
		sv->assembly[0] = '\0';

	/* leave slots at start for clients only */
	cl = NULL;
	while ((cl = SV_GetNextClient(cl)) != NULL) {
		/* needs to reconnect */
		if (cl->state >= cs_spawning)
			SV_SetClientState(cl, cs_connected);
	}

	/* assemble and load the map */
	if (levelstring[0] == '+') {
		randomMap = SV_AssembleMap(levelstring + 1, assembly, map, pos, 0);
		if (!randomMap) {
			Com_Printf("Could not load assembly for map '%s'\n", levelstring);
			return;
		}
	} else {
		SV_SetConfigString(CS_TILES, levelstring);
		SV_SetConfigString(CS_POSITIONS, assembly ? assembly : "");
	}

	CM_LoadMap(map, day, pos, &sv->mapData, &sv->mapTiles);

	Com_Printf("checksum for the map '%s': %u\n", levelstring, sv->mapData.mapChecksum);
	SV_SetConfigString(CS_MAPCHECKSUM, sv->mapData.mapChecksum);

	checksum = Com_GetScriptChecksum();

	Com_Printf("ufo script checksum %u\n", checksum);
	SV_SetConfigString(CS_UFOCHECKSUM, checksum);
	SV_SetConfigString(CS_OBJECTAMOUNT, csi.numODs);
	SV_SetConfigString(CS_VERSION, UFO_VERSION);
	SV_SetConfigString(CS_MAPTITLE, SV_GetMapTitle(randomMap, levelstring));
	if (Q_strstart(SV_GetConfigString(CS_MAPTITLE), "b/")) {
		/* For base attack, CS_MAPTITLE contains too many chars */
		SV_SetConfigString(CS_MAPTITLE, "Base attack");
		SV_SetConfigString(CS_NAME, ".baseattack");
	}

	/* clear random-map assembly data */
	Mem_Free(randomMap);
	randomMap = NULL;

	/* clear physics interaction links */
	SV_ClearWorld();

	/* fix this! */
	for (i = 1; i <= sv->mapData.numInline; i++)
		sv->models[i] = CM_InlineModel(&sv->mapTiles, va("*%i", i));

	/* precache and static commands can be issued during map initialization */
	Com_SetServerState(ss_loading);

	TH_MutexLock(svs.serverMutex);
	/* load and spawn all other entities */
	svs.ge->SpawnEntities(sv->name, SV_GetConfigStringInteger(CS_LIGHTMAP), sv->mapData.mapEntityString);
	TH_MutexUnlock(svs.serverMutex);

	/* all precaches are complete */
	Com_SetServerState(ss_game);

	Com_Printf("-------------------------------------\n");

	Cbuf_CopyToDefer();
}