Class: Sc2::Paths

Inherits:
Object
  • Object
show all
Defined in:
lib/sc2ai/paths.rb

Overview

Helps determine common paths to sc2 install dir, executable and maps. It maintains some semblance of compatibility with python-sc2 config

ENV can be set manually to StarCraft 2 base directory for Linux ENV can and should be manually set to “WineLinux” when running Wine Credit to Hannes, Sean and Burny for setting the standard

Constant Summary collapse

PF_WINDOWS =

Platform name for Windows

Returns:

  • (String)

    “Windows”

"Windows"
PF_WSL1 =

Platform name for WSL1

Returns:

  • (String)

    “WSL”

"WSL1"
PF_WSL2 =

Platform name for WSL2

Returns:

  • (String)

    “WSL2”

"WSL2"
PF_DARWIN =

Platform name macOS

Returns:

  • (String)

    “Darwin”

"Darwin"
PF_LINUX =

Platform name Linux

Returns:

  • (String)

    “Linux”

"Linux"
PF_WINE =

Platform name for Wine

Returns:

  • (String)

    “WineLinux”

"WineLinux"
BASE_DIR =

Where within user directory to locate ExecuteInfo.txt

Returns:

  • (Hash<String, String>)

    PF_* => “/path/to/StarCraft II”

{
  PF_WINDOWS => "C:/Program Files (x86)/StarCraft II",
  PF_WSL1 => "/mnt/c/Program Files (x86)/StarCraft II",
  PF_WSL2 => "/mnt/c/Program Files (x86)/StarCraft II",
  PF_DARWIN => "/Applications/StarCraft II",
  PF_LINUX => "~/StarCraftII",
  PF_WINE => "~/.wine/drive_c/Program Files (x86)/StarCraft II"
}.freeze
EXEC_INFO_PATH =

Where within user directory to locate ExecuteInfo.txt

Returns:

  • (Hash<String, String>)

    PF_* => “/path/to/ExecuteInfo.txt”

{
  PF_WINDOWS => "Documents/StarCraft II/ExecuteInfo.txt",
  PF_WSL1 => "Documents/StarCraft II/ExecuteInfo.txt",
  PF_WSL2 => "Documents/StarCraft II/ExecuteInfo.txt",
  PF_DARWIN => "Library/Application Support/Blizzard/StarCraft II/ExecuteInfo.txt",
  PF_LINUX => nil,
  PF_WINE => nil
}.freeze
BIN_PATH =

Path helper for finding executable

Returns:

  • (Hash<String, String>)

    PF_* => “SC2_binary.exe”

{
  PF_WINDOWS => "SC2_x64.exe",
  PF_WSL1 => "SC2_x64.exe",
  PF_WSL2 => "SC2_x64.exe",
  PF_DARWIN => "SC2.app/Contents/MacOS/SC2",
  PF_LINUX => "SC2_x64",
  PF_WINE => "SC2_x64.exe"
}.freeze
WORKING_DIR =

Working directory sub-folder per platform. Used when spawning client process on some platforms.

Returns:

  • (Hash<String, String>)

    PF_* => “Directory”

{
  PF_WINDOWS => "Support64",
  PF_WSL1 => "Support64",
  PF_WSL2 => "Support64",
  PF_DARWIN => nil,
  PF_LINUX => nil,
  PF_WINE => "Support64"
}.freeze

Class Method Summary collapse

Class Method Details

.bot_data_dirString

For local and ladder play, your files modified at runtime should live in ./data

Returns:

  • (String)

    path to ./data



187
188
189
190
191
# File 'lib/sc2ai/paths.rb', line 187

def bot_data_dir
  dir = Pathname("./data")
  dir.mkdir unless dir.exist?
  dir.to_s
end

.bot_data_replay_dirString

Returns the local replay folder For local play, your replay filse are saved to ./replays

Returns:

  • (String)

    path to ./replays



196
197
198
199
200
# File 'lib/sc2ai/paths.rb', line 196

def bot_data_replay_dir
  dir = Pathname("./replays")
  dir.mkdir unless dir.exist?
  dir.to_s
end

.exec_working_dirString?

Working directory if required by platform Some platforms the correct working directory for launch to find linked libraries

Returns:

  • (String, nil)

    string path or nil if not required



151
152
153
154
155
156
# File 'lib/sc2ai/paths.rb', line 151

def exec_working_dir
  cwd = WORKING_DIR[platform]
  return nil if cwd.nil?

  Pathname(install_dir).join(cwd).to_s
end

.executable(base_build: nil) ⇒ String?

Gets a path to latest Sc2 executable, or specific build’s executable if defined noinspection RubyMismatchedReturnType

Parameters:

  • base_build (Integer, nil) (defaults to: nil)

    version to use if installed

Returns:

  • (String, nil)

    path to executable



162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/sc2ai/paths.rb', line 162

def executable(base_build: nil)
  # Use base_build if supplied
  unless base_build.nil?
    path = Pathname.new(version_dir).join("Base#{base_build}")
    return path.join(BIN_PATH[platform]).to_s if path.exist?
  end
  # Get highest build number for folders /^Base\d$/
  pattern = /Base(\d+)$/
  path = Pathname.new(version_dir).glob("Base*")
    .max { |a, b| a.to_s.match(pattern)[1] <=> b.to_s.match(pattern)[1] }
  return path.join(BIN_PATH[platform]).to_s if path&.exist?

  nil
end

.gem_data_versions_pathPathname

Path to shipped versions.json

Returns:

  • (Pathname)

    path



219
220
221
# File 'lib/sc2ai/paths.rb', line 219

def gem_data_versions_path
  Pathname.new(gem_root).join("data", "versions.json")
end

.gem_rootPathname

Root directory of gem itself for other bundled files

Returns:

  • (Pathname)

    path to gem folder which contains lib/,data/,etc.



205
206
207
# File 'lib/sc2ai/paths.rb', line 205

def gem_root
  Pathname.new(__dir__.to_s).parent.parent.expand_path
end

.generate_temp_dirString

Gets system temp directory and creates /sc2ai

Returns:

  • (String)

    temporary directory for use with -tempDir



225
226
227
228
# File 'lib/sc2ai/paths.rb', line 225

def generate_temp_dir
  temp_dir = Pathname(Dir.tmpdir).join("sc2ai").mkpath
  temp_dir.to_s
end

.install_dirString

Attempts to auto-detect the user’s install directory via ExecuteInfo.txt

SC2PATH is required on WineLinux and Linux

Returns:

  • (String)

    path



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/sc2ai/paths.rb', line 111

def install_dir
  if ENV.fetch("SC2PATH", false)
    # Use if set via environment
    path = ENV.fetch("SC2PATH")
  else
    # Otherwise try read from ExecuteInfo.txt
    path = read_exec_info
    if path.to_s.strip.empty?
      # If not present in ExecuteInfo, try use sensible default
      path = BASE_DIR[platform]
    end
  end
  path = File.expand_path(path) if platform != PF_WINDOWS

  ENV["SC2PATH"] = path
end

.maps_dirString

Maps directory based on install_dir

Returns:

  • (String)

    maps directory



136
137
138
139
140
141
142
143
144
145
146
# File 'lib/sc2ai/paths.rb', line 136

def maps_dir
  # Use Maps if exists, or as fallback if alternative not found
  dir = Pathname(install_dir).join("Maps")
  return dir.to_s if dir.exist?

  # Use lowercase "maps" only if it exists
  dir_alt = Pathname(install_dir).join("maps")
  dir = dir_alt if dir_alt.exist?

  dir.to_s
end

.platformString

Bucketed platform names follows convention Uses ENV if configured. This is the only way to set “WineLinux”

Returns:

  • (String)

    string platform name



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/sc2ai/paths.rb', line 88

def platform
  return ENV.fetch("SC2PF", nil) unless ENV["SC2PF"].to_s.strip.empty?

  if Gem.win_platform?
    ENV["SC2PF"] = PF_WINDOWS
  elsif Gem::Platform.local.os == "darwin"
    ENV["SC2PF"] = PF_DARWIN
  elsif Gem::Platform.local.os == "linux"
    ENV["SC2PF"] = PF_LINUX
    if wsl?
      ENV["SC2PF"] = wsl2? ? PF_WSL2 : PF_WSL1
    end
  end

  unless ENV.fetch("SC2PF", false)
    Sc2.logger.warn "unknown platform detected #{Gem::Platform.local.os}. manually set ENV['SC2PF']"
  end
  ENV.fetch("SC2PF", nil)
end

.platformsArray<String>

An array of available platforms

Returns:

  • (Array<String>)

    an array of valid platforms



81
82
83
# File 'lib/sc2ai/paths.rb', line 81

def platforms
  [PF_WINDOWS, PF_WSL1, PF_WSL2, PF_DARWIN, PF_LINUX, PF_WINE]
end

.project_root_dirString

Returns project root directory

Returns:

  • (String)

    path because bundler does.



179
180
181
182
183
# File 'lib/sc2ai/paths.rb', line 179

def project_root_dir
  return Bundler.root.to_s if defined?(Bundler)

  Dir.pwd
end

.replay_dirString

Replays directory based on install_dir

Returns:

  • (String)

    replays directory



130
131
132
# File 'lib/sc2ai/paths.rb', line 130

def replay_dir
  Pathname(install_dir).join("Replays").to_s
end

.template_rootPathname

Directory of template folders

Returns:

  • (Pathname)

    path to where template directories live, i.e. “new” and “ladder”



212
213
214
# File 'lib/sc2ai/paths.rb', line 212

def template_root
  Pathname.new(__dir__.to_s).parent.join("templates").expand_path
end

.win_to_wsl(path:) ⇒ String

Convert a path like “C:\path\To a\Location” to “/mnt/c/path/To a/Location”

Parameters:

  • path (String)

Returns:

  • (String)

    path converted



245
246
247
# File 'lib/sc2ai/paths.rb', line 245

def win_to_wsl(path:)
  "/mnt/" + path.sub(/\A([A-Z])(:)/) { ::Regexp.last_match(1).to_s.downcase }.tr("\\", "/")
end

.wsl2?Boolean

Checks if running WSL2 specifically on top of wsl? being true

Returns:

  • (Boolean)


238
239
240
# File 'lib/sc2ai/paths.rb', line 238

def wsl2?
  wsl? && ENV.fetch("WSL_INTEROP", false)
end

.wsl?Boolean

Checks if running WSL

Returns:

  • (Boolean)


232
233
234
# File 'lib/sc2ai/paths.rb', line 232

def wsl?
  Gem::Platform.local.os == "linux" && (ENV.fetch("IS_WSL", false) || ENV.fetch("WSL_DISTRO_NAME", false))
end

.wsl_to_win(path:) ⇒ String

Convert a path like “/mnt/c/path/To a/Location” to “C:\path\To a\Location”

Parameters:

  • path (String)

Returns:

  • (String)

    path converted



252
253
254
# File 'lib/sc2ai/paths.rb', line 252

def wsl_to_win(path:)
  path.sub(%r{\A/mnt/([a-z])}) { "#{::Regexp.last_match(1).to_s.upcase}:" }.tr("/", "\\")
end