Skip to content

Commit 2559249

Browse files
tarehartDarxeal
andauthored
Updating the GUI to handle scripts. (#82)
* Updating the GUI to handle scripts. * Fix loading scripts by file * Fix bot/script pool reloading on folder settings changes Co-authored-by: Jiří Pihrt <jira.pihrt@volny.cz>
1 parent 0334e72 commit 2559249

5 files changed

Lines changed: 103 additions & 23 deletions

File tree

rlbot_gui/gui.py

Lines changed: 57 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,17 @@
88
from rlbot.parsing.agent_config_parser import create_looks_configurations, BOT_CONFIG_LOADOUT_HEADER, \
99
BOT_CONFIG_LOADOUT_ORANGE_HEADER, BOT_CONFIG_LOADOUT_PAINT_BLUE_HEADER, BOT_CONFIG_LOADOUT_PAINT_ORANGE_HEADER, \
1010
load_bot_appearance
11-
from rlbot.parsing.bot_config_bundle import get_bot_config_bundle, BotConfigBundle
12-
from rlbot.parsing.directory_scanner import scan_directory_for_bot_configs
11+
from rlbot.parsing.bot_config_bundle import get_bot_config_bundle, get_script_config_bundle, RunnableConfigBundle
12+
from rlbot.parsing.directory_scanner import scan_directory_for_bot_configs, scan_directory_for_script_configs
1313
from rlbot.parsing.match_settings_config_parser import map_types, game_mode_types, \
1414
boost_amount_mutator_types, match_length_types, max_score_types, overtime_mutator_types, \
1515
series_length_mutator_types, game_speed_mutator_types, ball_max_speed_mutator_types, ball_type_mutator_types, \
1616
ball_weight_mutator_types, ball_size_mutator_types, ball_bounciness_mutator_types, rumble_mutator_types, \
1717
boost_strength_mutator_types, gravity_mutator_types, demolish_mutator_types, respawn_time_mutator_types, \
1818
existing_match_behavior_types
1919

20-
from rlbot_gui.bot_management.bot_creation import bootstrap_python_bot, bootstrap_scratch_bot, bootstrap_python_hivemind, convert_to_filename
20+
from rlbot_gui.bot_management.bot_creation import bootstrap_python_bot, bootstrap_scratch_bot, \
21+
bootstrap_python_hivemind, convert_to_filename
2122
from rlbot_gui.bot_management.downloader import BotpackDownloader, get_json_from_url
2223
from rlbot_gui.match_runner.match_runner import hot_reload_bots, shut_down, start_match_helper, \
2324
do_infinite_loop_content, spawn_car_in_showroom, set_game_state, fetch_game_tick_packet
@@ -80,7 +81,18 @@ def serialize_bundle(bundle):
8081
}
8182

8283

83-
def load_bundle(filename):
84+
def serialize_script_bundle(bundle):
85+
return {
86+
'name': bundle.name,
87+
'type': 'script',
88+
'image': 'imgs/rlbot.png',
89+
'path': bundle.config_path,
90+
'info': read_info(bundle),
91+
'logo': try_copy_logo(bundle)
92+
}
93+
94+
95+
def load_bot_bundle(filename):
8496
try:
8597
bundle = get_bot_config_bundle(filename)
8698
return [serialize_bundle(bundle)]
@@ -90,10 +102,20 @@ def load_bundle(filename):
90102
return []
91103

92104

105+
def load_script_bundle(filename):
106+
try:
107+
bundle = get_script_config_bundle(filename)
108+
return [serialize_script_bundle(bundle)]
109+
except Exception as e:
110+
print(e)
111+
112+
return []
113+
114+
93115
@eel.expose
94116
def pick_bot_config():
95117
filename = pick_location(False)
96-
bundle = load_bundle(filename)
118+
bundle = load_script_bundle(filename) or load_bot_bundle(filename)
97119

98120
if bundle:
99121
bot_folder_settings["files"][filename] = {"visible": True}
@@ -124,7 +146,7 @@ def validate_bots(bots):
124146

125147
for bot in bots:
126148
if bot["type"] in ('rlbot', 'party_member_bot'):
127-
valid_bots += load_bundle(bot["path"])
149+
valid_bots += load_bot_bundle(bot["path"])
128150
else:
129151
valid_bots.append(bot)
130152

@@ -186,7 +208,7 @@ def pick_location(is_folder):
186208
return filename
187209

188210

189-
def read_info(bundle: BotConfigBundle):
211+
def read_info(bundle: RunnableConfigBundle):
190212
details_header = 'Details'
191213
if bundle.base_agent_config.has_section(details_header):
192214
return {
@@ -263,14 +285,33 @@ def scan_for_bots():
263285

264286
for file, props in bot_folder_settings['files'].items():
265287
if props['visible']:
266-
bots = load_bundle(file) # Returns a list of size 1
288+
bots = load_bot_bundle(file) # Returns a list of size 1
267289
for bot in bots:
268290
bot_hash[bot['path']] = bot
269291

270292
return list(bot_hash.values())
271293

272294

273-
def try_copy_logo(bundle: BotConfigBundle):
295+
@eel.expose
296+
def scan_for_scripts():
297+
script_hash = {}
298+
299+
for folder, props in bot_folder_settings['folders'].items():
300+
if props['visible']:
301+
bots = get_scripts_from_directory(folder)
302+
for bot in bots:
303+
script_hash[bot['path']] = bot
304+
305+
for file, props in bot_folder_settings['files'].items():
306+
if props['visible']:
307+
bots = load_script_bundle(file) # Returns a list of size 1
308+
for bot in bots:
309+
script_hash[bot['path']] = bot
310+
311+
return list(script_hash.values())
312+
313+
314+
def try_copy_logo(bundle: RunnableConfigBundle):
274315
logo_path = bundle.get_logo_file()
275316
if logo_path is not None and os.path.exists(logo_path):
276317
web_url = 'imgs/logos/' + convert_to_filename(bundle.name) + '/' + convert_to_filename(logo_path)
@@ -285,6 +326,10 @@ def get_bots_from_directory(bot_directory):
285326
return [serialize_bundle(bundle) for bundle in scan_directory_for_bot_configs(bot_directory)]
286327

287328

329+
def get_scripts_from_directory(bot_directory):
330+
return [serialize_script_bundle(bundle) for bundle in scan_directory_for_script_configs(bot_directory)]
331+
332+
288333
@eel.expose
289334
def get_language_support():
290335
java_return_code = os.system("java -version")
@@ -402,7 +447,7 @@ def begin_python_bot(bot_name):
402447

403448
try:
404449
config_file = bootstrap_python_bot(bot_name, bot_directory)
405-
return {'bots': load_bundle(config_file)}
450+
return {'bots': load_bot_bundle(config_file)}
406451
except FileExistsError as e:
407452
return {'error': str(e)}
408453

@@ -414,7 +459,7 @@ def begin_scratch_bot(bot_name):
414459
try:
415460
config_file = bootstrap_scratch_bot(bot_name, bot_directory)
416461
install_package('webdriver_manager') # Scratch bots need this, and the GUI's python doesn't have it by default.
417-
return {'bots': load_bundle(config_file)}
462+
return {'bots': load_bot_bundle(config_file)}
418463
except FileExistsError as e:
419464
return {'error': str(e)}
420465

@@ -425,7 +470,7 @@ def begin_python_hivemind(hive_name):
425470

426471
try:
427472
config_file = bootstrap_python_hivemind(hive_name, bot_directory)
428-
return {'bots': load_bundle(config_file)}
473+
return {'bots': load_bot_bundle(config_file)}
429474
except FileExistsError as e:
430475
return {'error': str(e)}
431476

rlbot_gui/gui/css/style.css

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,16 @@ body {
6868
opacity: 0.4;
6969
}
7070

71+
.draggable {
72+
cursor: move;
73+
}
74+
7175
.bot-card {
7276
margin: 5px;
73-
cursor: move;
77+
}
78+
79+
.bot-card .md-switch {
80+
margin: 5px 8px;
7481
}
7582

7683
.center-flex {

rlbot_gui/gui/main.vue

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@
9898
</md-card-header>
9999

100100
<draggable v-model="botPool" :options="{group: {name:'bots', pull:'clone', put:false}, sort: false}">
101-
<md-card class="bot-card md-elevation-3" v-for="bot in botPool" :class="{'filtered': !passesFilter(bot.name)}">
101+
<md-card class="bot-card draggable md-elevation-3" v-for="bot in botPool" :class="{'filtered': !passesFilter(bot.name)}">
102102
<button class="center-flex secret-button" @click="addToTeam(bot, teamSelection)">
103103
<img v-if="!bot.logo" class="darkened" v-bind:src="bot.image">
104104
<img v-if="bot.logo" v-bind:src="bot.logo">
@@ -114,6 +114,13 @@
114114
</button>
115115
</md-card>
116116
</draggable>
117+
<md-card class="bot-card md-elevation-3" v-for="script in scriptPool">
118+
<md-switch v-model="script.enabled">{{script.name}}</md-switch>
119+
<md-button class="md-icon-button md-dense bot-hover-reveal" v-if="script.info"
120+
@click.stop="activeBot = script; showBotInfo = true;">
121+
<md-icon>blur_on</md-icon>
122+
</md-button>
123+
</md-card>
117124
</md-card>
118125

119126
<div id="teamSwitcher" style="text-align: center;">
@@ -130,7 +137,7 @@
130137
<div class="md-title">Blue Team</div>
131138
</md-card-header>
132139
<draggable v-model="blueTeam" class="team-entries" :options="{group:'bots'}">
133-
<md-card class="bot-card center-flex md-elevation-3" v-for="(bot, index) in blueTeam">
140+
<md-card class="bot-card draggable center-flex md-elevation-3" v-for="(bot, index) in blueTeam">
134141
<img v-if="!bot.logo" class="darkened" v-bind:src="bot.image">
135142
<img v-if="bot.logo" v-bind:src="bot.logo">
136143
<span class="bot-name">{{ bot.name }}</span>
@@ -148,7 +155,7 @@
148155
<div class="md-title">Orange Team</div>
149156
</md-card-header>
150157
<draggable v-model="orangeTeam" class="team-entries" :options="{group:'bots'}">
151-
<md-card class="bot-card center-flex md-elevation-3" v-for="(bot, index) in orangeTeam">
158+
<md-card class="bot-card draggable center-flex md-elevation-3" v-for="(bot, index) in orangeTeam">
152159
<img v-if="!bot.logo" class="darkened" v-bind:src="bot.image">
153160
<img v-if="bot.logo" v-bind:src="bot.logo">
154161
<span class="bot-name">{{ bot.name }}</span>
@@ -301,7 +308,7 @@
301308
</md-dialog-content>
302309

303310
<md-dialog-actions>
304-
<md-button @click="showAppearanceEditor(activeBot.looks_path)">
311+
<md-button v-if="activeBot.type !== 'script'" @click="showAppearanceEditor(activeBot.looks_path)">
305312
<md-icon>palette</md-icon> Edit Appearance
306313
</md-button>
307314
<md-button v-if="activeBot.path" @click="showBotInExplorer(activeBot.path)">
@@ -446,6 +453,7 @@
446453
data () {
447454
return {
448455
botPool: STARTING_BOT_POOL,
456+
scriptPool: [],
449457
blueTeam: [],
450458
orangeTeam: [],
451459
teamSelection: "blue",
@@ -479,6 +487,7 @@
479487
enable_rendering: false,
480488
enable_state_setting: false,
481489
auto_save_replay: false,
490+
scripts: [],
482491
},
483492
randomMapPool: [],
484493
showMutatorDialog: false,
@@ -514,6 +523,7 @@
514523
startMatch: async function (event) {
515524
if (this.matchSettings.randomizeMap) await this.setRandomMap();
516525
526+
this.matchSettings.scripts = this.scriptPool.filter((val) => { return val.enabled });
517527
eel.save_match_settings(this.matchSettings);
518528
eel.save_team_settings(this.blueTeam, this.orangeTeam);
519529
@@ -571,6 +581,7 @@
571581
this.matchSettings.enable_rendering = false;
572582
this.matchSettings.enable_state_setting = true;
573583
this.matchSettings.auto_save_replay = false;
584+
this.matchSettings.scripts = [];
574585
this.resetMutatorsToDefault();
575586
576587
this.updateBGImage(this.matchSettings.map);
@@ -621,10 +632,12 @@
621632
eel.get_folder_settings()(this.folderSettingsReceived);
622633
this.showFolderSettingsDialog = true;
623634
},
624-
applyFolderSettings: function() {
625-
eel.save_folder_settings(this.folderSettings);
635+
applyFolderSettings: async function() {
636+
await eel.save_folder_settings(this.folderSettings)();
626637
this.botPool = STARTING_BOT_POOL;
638+
this.scriptPool = [];
627639
eel.scan_for_bots()(this.botsReceived);
640+
eel.scan_for_scripts()(this.scriptsReceived);
628641
},
629642
passesFilter: function(botName) {
630643
return botName.toLowerCase().includes(this.botNameFilter.toLowerCase());
@@ -651,6 +664,16 @@
651664
this.showProgressSpinner = false;
652665
},
653666
667+
scriptsReceived: function (scripts) {
668+
const freshScripts = scripts.filter( (script) =>
669+
!this.scriptPool.find( (element) => element.path === script.path ));
670+
freshScripts.forEach((script) => {script.enabled = !!this.matchSettings.scripts.find( (element) => element.path === script.path )});
671+
672+
this.scriptPool = this.scriptPool.concat(freshScripts).sort((a, b) => a.name.localeCompare(b.name));
673+
674+
this.showProgressSpinner = false;
675+
},
676+
654677
applyLanguageWarnings: function () {
655678
if (this.languageSupport) {
656679
this.botPool.forEach((bot) => {
@@ -674,6 +697,7 @@
674697
if (matchSettings) {
675698
Object.assign(this.matchSettings, matchSettings);
676699
this.updateBGImage(this.matchSettings.map);
700+
this.scriptPool.forEach((script) => {script.enabled = !!this.matchSettings.scripts.find( (element) => element.path === script.path )});
677701
} else {
678702
this.resetMatchSettingsToDefault();
679703
}
@@ -687,6 +711,8 @@
687711
688712
folderSettingsReceived: function (folderSettings) {
689713
this.folderSettings = folderSettings;
714+
eel.scan_for_bots()(this.botsReceived);
715+
eel.scan_for_scripts()(this.scriptsReceived);
690716
},
691717
botpackUpdateChecked: function (isBotpackUpToDate) {
692718
this.showBotpackUpdateSnackbar = !isBotpackUpToDate;
@@ -697,7 +723,6 @@
697723
this.showSnackbar = true;
698724
this.showDownloadProgressDialog = false;
699725
eel.get_folder_settings()(this.folderSettingsReceived);
700-
eel.scan_for_bots()(this.botsReceived);
701726
},
702727
703728
onInstallationComplete: function (result) {
@@ -714,7 +739,6 @@
714739
},
715740
created: function () {
716741
eel.get_folder_settings()(this.folderSettingsReceived);
717-
eel.scan_for_bots()(this.botsReceived);
718742
eel.get_match_options()(this.matchOptionsReceived);
719743
eel.get_match_settings()(this.matchSettingsReceived);
720744
eel.get_team_settings()(this.teamSettingsReceived);

rlbot_gui/match_runner/match_runner.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from rlbot.gateway_util import NetworkingRole
44
from rlbot.matchconfig.loadout_config import LoadoutConfig
5-
from rlbot.matchconfig.match_config import PlayerConfig, MatchConfig, MutatorConfig
5+
from rlbot.matchconfig.match_config import PlayerConfig, MatchConfig, MutatorConfig, ScriptConfig
66
from rlbot.parsing.incrementing_integer import IncrementingInteger
77
from rlbot.setup_manager import SetupManager
88
from rlbot.utils.structures.bot_input_struct import PlayerInput
@@ -26,6 +26,9 @@ def create_player_config(bot, human_index_tracker: IncrementingInteger):
2626
player_config.config_path = bot['path']
2727
return player_config
2828

29+
def create_script_config(script):
30+
return ScriptConfig(script['path'])
31+
2932

3033
def spawn_car_in_showroom(loadout_config: LoadoutConfig, team: int, showcase_type: str, map_name: str):
3134
match_config = MatchConfig()
@@ -150,6 +153,7 @@ def start_match_helper(bot_list, match_settings):
150153

151154
human_index_tracker = IncrementingInteger(0)
152155
match_config.player_configs = [create_player_config(bot, human_index_tracker) for bot in bot_list]
156+
match_config.script_configs = [create_script_config(script) for script in match_settings['scripts']]
153157

154158
global sm
155159
if sm is not None:

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import setuptools
22

3-
__version__ = '0.0.58'
3+
__version__ = '0.0.59'
44

55
with open("README.md", "r") as readme_file:
66
long_description = readme_file.read()

0 commit comments

Comments
 (0)