Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion frontend/src/components/BotList.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,6 @@ function filterBots(
}

function scriptDuplicateAgentIdWarning(d: ToggleableScript): string | null {

const agentId = d.info.config.settings.agentId;

if (!agentId) {
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/Teams/TeamBotList.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import cannotAutoRunIcon from "../../assets/cannot_play.svg";
import defaultIcon from "../../assets/rlbot_mono.png";

import PlayerOverridesModal from "./PlayerOverridesModal.svelte";
import {Browser} from "@wailsio/runtime";
import { Browser } from "@wailsio/runtime";
import warningIcon from "../../assets/exclamation-triangle-fill.svg";

let {
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/pages/Home.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ function collectDuplicateAgentIds(
bots: DraggablePlayer[],
scripts: ToggleableScript[],
): Set<string> {
const agentIdTomlMap: { [id: string]: string } = {}
const agentIdTomlMap: { [id: string]: string } = {};
const duplicateAgentIds = new Set<string>();

for (const bot of bots) {
Expand Down
98 changes: 82 additions & 16 deletions players.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"path/filepath"
"runtime"
"sort"
"strings"

"github.com/BurntSushi/toml"
"github.com/RLBot/go-interface/flat"
Expand Down Expand Up @@ -188,31 +189,83 @@ func findTorchLibDir(fromPath string) string {
return ""
}

// setTorchEnv populates the Environment field with PATH/LD_LIBRARY_PATH
// pointing to the torch-archive lib directory, if it exists.
// pathSeparator returns the platform-specific path list separator as a string.
func pathSeparator() string {
if runtime.GOOS == "windows" {
return ";"
}
return ":"
}

// resolveEnvironmentVariables resolves path-like prepend/postpend markers in
// environment variable values. If a value starts with the platform path
// separator, it is prepended to the current value (falling back to os.Getenv).
// If it ends with the separator, it is postpended. Otherwise the value is used
// as-is.
func resolveEnvironmentVariables(env []*flat.EnvironmentVariableT) []*flat.EnvironmentVariableT {
sep := pathSeparator()
resolvedMap := make(map[string]string)
result := make([]*flat.EnvironmentVariableT, 0, len(env))

for _, ev := range env {
existing := resolvedMap[ev.Name]
if existing == "" {
existing = os.Getenv(ev.Name)
}

value := ev.Value
if strings.HasPrefix(value, sep) {
cleanValue := strings.TrimPrefix(value, sep)
if existing == "" {
value = cleanValue
} else {
value = cleanValue + sep + existing
}
} else if strings.HasSuffix(value, sep) {
cleanValue := strings.TrimSuffix(value, sep)
if existing == "" {
value = cleanValue
} else {
value = existing + sep + cleanValue
}
}

resolvedMap[ev.Name] = value
result = append(result, &flat.EnvironmentVariableT{
Name: ev.Name,
Value: value,
})
}

return result
}

// setTorchEnv appends a PATH/LD_LIBRARY_PATH entry pointing to the
// torch-archive lib directory, if it exists. The value begins with the
// platform path separator so resolveEnvironmentVariables prepends it to the
// existing path.
func setTorchEnv(tomlPath string, env *[]*flat.EnvironmentVariableT) {
torchLibDir := findTorchLibDir(tomlPath)
if torchLibDir == "" {
return
}

varName := "LD_LIBRARY_PATH"
if runtime.GOOS == "windows" {
*env = append(*env, &flat.EnvironmentVariableT{
Name: "PATH",
Value: torchLibDir + ";" + os.Getenv("PATH"),
})
} else {
ldLibPath := os.Getenv("LD_LIBRARY_PATH")
if ldLibPath != "" {
ldLibPath = torchLibDir + ":" + ldLibPath
} else {
ldLibPath = torchLibDir
varName = "PATH"
}

for _, ev := range *env {
if ev.Name == varName {
return
}
*env = append(*env, &flat.EnvironmentVariableT{
Name: "LD_LIBRARY_PATH",
Value: ldLibPath,
})
}

sep := pathSeparator()
*env = append(*env, &flat.EnvironmentVariableT{
Name: varName,
Value: sep + torchLibDir,
})
}

func (botInfo BotInfo) ToPlayerConfig(team uint32) *flat.PlayerConfigurationT {
Expand Down Expand Up @@ -244,8 +297,19 @@ func (botInfo BotInfo) ToPlayerConfig(team uint32) *flat.PlayerConfigurationT {
Hivemind: botInfo.Config.Settings.Hivemind,
}

// Add environment variables from the bot's config toml first
for k, v := range botInfo.Config.Settings.Environment {
customBot.Environment = append(customBot.Environment, &flat.EnvironmentVariableT{
Name: k,
Value: v,
})
}

// Then append torch paths (if found) so they combine properly with any toml-specified paths
setTorchEnv(botInfo.TomlPath, &customBot.Environment)

customBot.Environment = resolveEnvironmentVariables(customBot.Environment)

return &flat.PlayerConfigurationT{
Variety: &flat.PlayerClassT{
Type: flat.PlayerClassCustomBot,
Expand Down Expand Up @@ -279,6 +343,8 @@ type BotSettings struct {
RunCommandLinux string `toml:"run_command_linux" json:"runCommandLinux"`
// If bot can handle multiple agents with one client
Hivemind bool `toml:"hivemind" json:"hivemind"`
// Additional environment variables to set for the bot process
Environment map[string]string `toml:"environment" json:"environment"`
}

type BotDetails struct {
Expand Down
11 changes: 11 additions & 0 deletions scripts.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,19 @@ func (botInfo BotInfo) ToScriptConfig() *flat.ScriptConfigurationT {
ScriptId: 0, // let core do this
}

// Add environment variables from the script's config toml first
for k, v := range botInfo.Config.Settings.Environment {
scriptConfig.Environment = append(scriptConfig.Environment, &flat.EnvironmentVariableT{
Name: k,
Value: v,
})
}

// Then append torch paths (if found) so they combine properly with any toml-specified paths
setTorchEnv(botInfo.TomlPath, &scriptConfig.Environment)

scriptConfig.Environment = resolveEnvironmentVariables(scriptConfig.Environment)

return scriptConfig
}

Expand Down