sourcemod icon indicating copy to clipboard operation
sourcemod copied to clipboard

[Feature Request] Convert from Valve filesystem search paths

Open Alienmario opened this issue 8 months ago • 0 comments

Help us help you

  • [x] I have checked that my issue doesn't exist yet.
  • [x] I have tried my absolute best to reduce the problem-space and have provided the absolute smallest test-case possible.
  • [x] I can always reproduce the issue with the provided description below.

Environment

  • Operating System version: Windows 11
  • Game/AppID (with version if applicable): hl2dm
  • Current SourceMod version: 1.12.0.7031

Description

While reading a file from the custom folder using Valve filesystem is effortless, as soon as you try opening it with a mode that is able to write, the file is not found. As far as I understand, this is a Valve limitation.

For a workaround (and other use cases) I suggest adding a function that either

  • Returns all Valve search paths as real paths, so we can iterate over them
  • Finds occurrences of a file in Valve FS and returns its real paths.

That way we can open the files for writing with normal filesystem.

Problematic Code (or Steps to Reproduce)

// custom/test/maps/myconfig.txt
OpenFile("maps/myconfig.txt", "r", true); // valid
OpenFile("maps/myconfig.txt", "r+", true); // null
OpenFile("custom/test/maps/myconfig.txt", "r+") // valid

SP workaround:


/**
 * This is a workaround for opening existing files, potentially located in the custom folder, with the Valve filesystem, for both reading and writing.
 * Normally, opening an existing file with Valve FS using any writable modes ("r+", "a", ..) will only look for files in root game folder.
 * This function currently accounts for the custom folder only, other additional Valve search paths are ignored.
 * 
 * https://github.com/alliedmodders/sourcemod/issues/2175
 */
stock File OpenFileEx(const char[] file, const char[] mode, bool use_valve_fs=false, const char[] valve_path_id="GAME")
{
	if (use_valve_fs && !StrEqual(mode, "r", false) && !StrEqual(mode, "rb", false) && !StrEqual(mode, "rt", false))
	{
		char szFullPath[PLATFORM_MAX_PATH];
		if (ResolveValveFile(file, szFullPath, sizeof(szFullPath)))
		{
			return OpenFile(szFullPath, mode);
		}
	}
	return OpenFile(file, mode, use_valve_fs, valve_path_id);
}

/**
 * Should only be used as last resort.
 */
stock bool ResolveValveFile(const char[] szFile, char[] szFullPath, int maxLen)
{
	DirectoryListing dir = OpenDirectory("custom");
	if (dir)
	{
		char buffer[PLATFORM_MAX_PATH];
		FileType ft;
		
		while (dir.GetNext(buffer, sizeof(buffer), ft))
		{
			if (ft == FileType_Directory && !StrEqual(buffer, ".") && !StrEqual(buffer, ".."))
			{
				Format(buffer, sizeof(buffer), "custom/%s/%s", buffer, szFile);
				if (FileExists(buffer))
				{
					dir.Close();
					Format(szFullPath, maxLen, buffer);
					return true;
				}
			}
		}

		dir.Close();
	}
	return false;
}

Alienmario avatar Jun 02 '24 15:06 Alienmario