From 190ef7d905a016cc025b45ae0a20f7f95a8dd040 Mon Sep 17 00:00:00 2001 From: Benjamin Amos Date: Sat, 18 Jun 2022 11:27:41 +0100 Subject: [PATCH 1/2] feat(save): add module select UI for new games --- .../org/destinationsol/SolApplication.java | 3 + .../destinationsol/assets/AssetHelper.java | 4 + .../assets/music/OggMusicManager.java | 2 +- .../org/destinationsol/game/SaveManager.java | 32 +++++ .../org/destinationsol/game/WorldConfig.java | 17 ++- .../org/destinationsol/menu/MenuScreens.java | 3 + .../destinationsol/modules/ModuleManager.java | 18 ++- .../nui/screens/mainMenu/MainMenuScreen.java | 10 +- .../nui/screens/mainMenu/ModulesScreen.java | 109 ++++++++++++++++++ .../nui/screens/mainMenu/NewShipScreen.java | 56 +++++++-- .../destinationsol/assets/skins/mainMenu.skin | 3 + .../assets/ui/mainMenu/modulesScreen.ui | 106 +++++++++++++++++ .../assets/ui/mainMenu/newShipScreen.ui | 12 ++ 13 files changed, 360 insertions(+), 15 deletions(-) create mode 100644 engine/src/main/java/org/destinationsol/ui/nui/screens/mainMenu/ModulesScreen.java create mode 100644 engine/src/main/resources/org/destinationsol/assets/ui/mainMenu/modulesScreen.ui diff --git a/engine/src/main/java/org/destinationsol/SolApplication.java b/engine/src/main/java/org/destinationsol/SolApplication.java index 8cd6a54ba..50b9f58e4 100644 --- a/engine/src/main/java/org/destinationsol/SolApplication.java +++ b/engine/src/main/java/org/destinationsol/SolApplication.java @@ -333,6 +333,9 @@ private void draw() { public void play(boolean tut, String shipName, boolean isNewGame, WorldConfig worldConfig) { ModuleManager moduleManager = appContext.getBean(ModuleManager.class); + moduleManager.loadEnvironment(worldConfig.getModules()); + appContext.getBean(AssetHelper.class).switchEnvironment(moduleManager.getEnvironment()); + gameContext = appContext.getNestedContainer( new GameConfigurationServiceRegistry(worldConfig), new EventReceiverServiceRegistry(moduleManager.getEnvironment()), diff --git a/engine/src/main/java/org/destinationsol/assets/AssetHelper.java b/engine/src/main/java/org/destinationsol/assets/AssetHelper.java index c9cdb2c9d..79af1120d 100644 --- a/engine/src/main/java/org/destinationsol/assets/AssetHelper.java +++ b/engine/src/main/java/org/destinationsol/assets/AssetHelper.java @@ -131,6 +131,10 @@ public Set listAssets(Class> type, String asset, return list; } + public void switchEnvironment(ModuleEnvironment environment) { + assetTypeManager.switchEnvironment(environment); + } + public void dispose() { try { assetTypeManager.unloadEnvironment(); diff --git a/engine/src/main/java/org/destinationsol/assets/music/OggMusicManager.java b/engine/src/main/java/org/destinationsol/assets/music/OggMusicManager.java index c4c3619fb..cf7ff2b72 100644 --- a/engine/src/main/java/org/destinationsol/assets/music/OggMusicManager.java +++ b/engine/src/main/java/org/destinationsol/assets/music/OggMusicManager.java @@ -238,7 +238,7 @@ public void unregisterModuleMusic() { } public void resetMusic() { - musicMap.put(GAME_MUSIC_SET, new ArrayList<>()); + musicMap.clear(); } public String getCurrentMusicSet() { diff --git a/engine/src/main/java/org/destinationsol/game/SaveManager.java b/engine/src/main/java/org/destinationsol/game/SaveManager.java index cc4725006..b12359e32 100644 --- a/engine/src/main/java/org/destinationsol/game/SaveManager.java +++ b/engine/src/main/java/org/destinationsol/game/SaveManager.java @@ -36,10 +36,13 @@ import org.destinationsol.game.item.SolItem; import org.destinationsol.game.ship.SolShip; import org.destinationsol.game.ship.hulls.HullConfig; +import org.destinationsol.modules.ModuleManager; import org.destinationsol.ui.Waypoint; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.terasology.context.annotation.API; +import org.terasology.gestalt.module.Module; +import org.terasology.gestalt.naming.Name; import java.io.File; import java.io.FileNotFoundException; @@ -50,8 +53,10 @@ import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Optional; +import java.util.Set; @API public class SaveManager { @@ -263,6 +268,15 @@ public static void saveWorld(WorldConfig worldConfig) { } world.add("featureGenerators", featureGenerators); + JsonArray modulesArray = new JsonArray(); + for (Name module : ModuleManager.getEnvironmentStatic().getModuleIdsOrderedByDependencies()) { + // Exclude built-in modules + if (module.compareTo("engine") != 0 && module.compareTo("nui") != 0) { + modulesArray.add(module.toString()); + } + } + world.add("modules", modulesArray); + Gson gson = new GsonBuilder().setPrettyPrinting().create(); String stringToWrite = gson.toJson(world); @@ -316,6 +330,24 @@ public static Optional loadWorld() { config.setFeatureGenerators(featureGenerators); } + if (world.has("modules")) { + Set modules = new HashSet<>(); + for (JsonElement value : world.getAsJsonArray("modules")) { + if (value.isJsonPrimitive() && value.getAsJsonPrimitive().isString()) { + Module module = ModuleManager.getEnvironmentStatic().get(new Name(value.getAsString())); + if (module != null) { + modules.add(module); + } else { + logger.warn("The module \"" + value.getAsString() + "\" is missing!"); + } + } + } + config.setModules(modules); + } else { + // This is for compatibility with older saves, which always used all modules unconditionally. + config.setModules(new HashSet<>(ModuleManager.getEnvironmentStatic().getModulesOrderedByDependencies())); + } + logger.debug("Successfully loaded the world file"); return Optional.of(config); } catch (FileNotFoundException e) { diff --git a/engine/src/main/java/org/destinationsol/game/WorldConfig.java b/engine/src/main/java/org/destinationsol/game/WorldConfig.java index fcb636b44..23f077992 100644 --- a/engine/src/main/java/org/destinationsol/game/WorldConfig.java +++ b/engine/src/main/java/org/destinationsol/game/WorldConfig.java @@ -16,30 +16,37 @@ package org.destinationsol.game; import org.destinationsol.game.planet.SystemsBuilder; +import org.terasology.gestalt.module.Module; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; public class WorldConfig { protected long seed; protected int numberOfSystems; private List solarSystemGenerators; private List featureGenerators; + private Set modules; public WorldConfig() { seed = System.currentTimeMillis(); numberOfSystems = SystemsBuilder.DEFAULT_SYSTEM_COUNT; solarSystemGenerators = new ArrayList<>(); featureGenerators = new ArrayList<>(); + modules = new HashSet<>(); } public WorldConfig(long seed, int numberOfSystems, List solarSystemGenerators, - List featureGenerators) { + List featureGenerators, + Set modules) { this.seed = seed; this.numberOfSystems = numberOfSystems; this.solarSystemGenerators = solarSystemGenerators; this.featureGenerators = featureGenerators; + this.modules = modules; } public long getSeed() { @@ -73,4 +80,12 @@ public List getFeatureGenerators() { public void setSolarSystemGenerators(List solarSystemGenerators) { this.solarSystemGenerators = solarSystemGenerators; } + + public Set getModules() { + return modules; + } + + public void setModules(Set modules) { + this.modules = modules; + } } diff --git a/engine/src/main/java/org/destinationsol/menu/MenuScreens.java b/engine/src/main/java/org/destinationsol/menu/MenuScreens.java index 38ac08815..5d7c5e92c 100644 --- a/engine/src/main/java/org/destinationsol/menu/MenuScreens.java +++ b/engine/src/main/java/org/destinationsol/menu/MenuScreens.java @@ -22,6 +22,7 @@ import org.destinationsol.ui.nui.screens.mainMenu.InputMapScreen; import org.destinationsol.ui.nui.screens.mainMenu.LoadingScreen; import org.destinationsol.ui.nui.screens.mainMenu.MainMenuScreen; +import org.destinationsol.ui.nui.screens.mainMenu.ModulesScreen; import org.destinationsol.ui.nui.screens.mainMenu.NewGameScreen; import org.destinationsol.ui.nui.screens.mainMenu.NewShipScreen; import org.destinationsol.ui.nui.screens.mainMenu.OptionsScreen; @@ -36,6 +37,7 @@ public class MenuScreens { public final LoadingScreen loading; public final NewGameScreen newGame; public final NewShipScreen newShip; + public final ModulesScreen modules; public MenuScreens(SolLayouts layouts, boolean mobile, GameOptions gameOptions, NUIManager nuiManager) { MenuLayout menuLayout = layouts.menuLayout; @@ -47,5 +49,6 @@ public MenuScreens(SolLayouts layouts, boolean mobile, GameOptions gameOptions, loading = (LoadingScreen) nuiManager.createScreen("engine:loadingScreen"); newGame = (NewGameScreen) nuiManager.createScreen("engine:newGameScreen"); newShip = (NewShipScreen) nuiManager.createScreen("engine:newShipScreen"); + modules = (ModulesScreen) nuiManager.createScreen("engine:modulesScreen"); } } diff --git a/engine/src/main/java/org/destinationsol/modules/ModuleManager.java b/engine/src/main/java/org/destinationsol/modules/ModuleManager.java index fad354ab0..741c770e4 100644 --- a/engine/src/main/java/org/destinationsol/modules/ModuleManager.java +++ b/engine/src/main/java/org/destinationsol/modules/ModuleManager.java @@ -220,6 +220,7 @@ public class ModuleManager implements AutoCloseable { private final FacadeModuleConfig moduleConfig; protected ModuleRegistry registry; protected Module engineModule; + private Set builtInModules; @Inject public ModuleManager(BeanContext beanContext, ModuleFactory moduleFactory, ModuleRegistry moduleRegistry, @@ -240,9 +241,12 @@ public void init() throws Exception { File modulesRoot = moduleConfig.getModulesPath(); scanner.scan(registry, modulesRoot); + builtInModules = Sets.newHashSet(); + builtInModules.add(engineModule); + builtInModules.add(nuiModule); + registry.addAll(builtInModules); + Set requiredModules = Sets.newHashSet(); - registry.add(engineModule); - registry.add(nuiModule); requiredModules.addAll(registry); loadEnvironment(requiredModules); @@ -253,6 +257,8 @@ public void init() throws Exception { } public void loadEnvironment(Set modules) { + modules.addAll(builtInModules); + StandardPermissionProviderFactory permissionFactory = new StandardPermissionProviderFactory(); for (String api : API_WHITELIST) { permissionFactory.getBasePermissionSet().addAPIPackage(api); @@ -288,6 +294,10 @@ public ModuleEnvironment getEnvironment() { return environment; } + public Set getBuiltInModules() { + return builtInModules; + } + //TODO: REMOVE THIS public static ModuleEnvironment getEnvironmentStatic() { return environment; @@ -299,6 +309,10 @@ public void printAvailableModules() { } } + public ModuleRegistry getRegistry() { + return registry; + } + public void dispose() { environment.close(); } diff --git a/engine/src/main/java/org/destinationsol/ui/nui/screens/mainMenu/MainMenuScreen.java b/engine/src/main/java/org/destinationsol/ui/nui/screens/mainMenu/MainMenuScreen.java index 34ecb7759..d72e13293 100644 --- a/engine/src/main/java/org/destinationsol/ui/nui/screens/mainMenu/MainMenuScreen.java +++ b/engine/src/main/java/org/destinationsol/ui/nui/screens/mainMenu/MainMenuScreen.java @@ -20,12 +20,14 @@ import org.destinationsol.SolApplication; import org.destinationsol.assets.music.OggMusicManager; import org.destinationsol.game.WorldConfig; +import org.destinationsol.modules.ModuleManager; import org.destinationsol.ui.nui.NUIManager; import org.destinationsol.ui.nui.NUIScreenLayer; import org.terasology.nui.Canvas; import org.terasology.nui.widgets.UIButton; import javax.inject.Inject; +import java.util.HashSet; /** * The main menu screen. This is the first screen shown when you open the game. @@ -33,18 +35,22 @@ public class MainMenuScreen extends NUIScreenLayer { private final SolApplication solApplication; + private final ModuleManager moduleManager; private UIButton tutorialButton; @Inject - public MainMenuScreen(SolApplication solApplication) { + public MainMenuScreen(SolApplication solApplication, ModuleManager moduleManager) { this.solApplication = solApplication; + this.moduleManager = moduleManager; } @Override public void initialise() { tutorialButton = find("tutorialButton", UIButton.class); tutorialButton.subscribe(button -> { - solApplication.getMenuScreens().loading.setMode(true, "Imperial Small", true, new WorldConfig()); + WorldConfig worldConfig = new WorldConfig(); + worldConfig.setModules(new HashSet<>(moduleManager.getEnvironment().getModulesOrderedByDependencies())); + solApplication.getMenuScreens().loading.setMode(true, "Imperial Small", true, worldConfig); nuiManager.setScreen(solApplication.getMenuScreens().loading); }); diff --git a/engine/src/main/java/org/destinationsol/ui/nui/screens/mainMenu/ModulesScreen.java b/engine/src/main/java/org/destinationsol/ui/nui/screens/mainMenu/ModulesScreen.java new file mode 100644 index 000000000..7c0119f04 --- /dev/null +++ b/engine/src/main/java/org/destinationsol/ui/nui/screens/mainMenu/ModulesScreen.java @@ -0,0 +1,109 @@ +/* + * Copyright 2022 The Terasology Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.destinationsol.ui.nui.screens.mainMenu; + +import org.destinationsol.SolApplication; +import org.destinationsol.modules.ModuleManager; +import org.destinationsol.ui.nui.NUIScreenLayer; +import org.terasology.gestalt.module.Module; +import org.terasology.nui.databinding.ReadOnlyBinding; +import org.terasology.nui.itemRendering.StringTextRenderer; +import org.terasology.nui.widgets.UIButton; +import org.terasology.nui.widgets.UIList; + +import javax.inject.Inject; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * This screen is used to select the modules that should be active when playing a particular save. + * You can activate and de-activate modules only when initially creating a game. + * This is to prevent side-effects from new modules being introduced unexpectedly. + */ +public class ModulesScreen extends NUIScreenLayer { + private final SolApplication solApplication; + private final ModuleManager moduleManager; + private Set selectedModules; + + @Inject + public ModulesScreen(SolApplication solApplication, ModuleManager moduleManager) { + this.solApplication = solApplication; + this.moduleManager = moduleManager; + } + + @Override + public void initialise() { + selectedModules = new HashSet<>(); + + UIList moduleList = find("modulesList", UIList.class); + List modules = new ArrayList<>(moduleManager.getEnvironment().getModulesOrderedByDependencies()); + modules.removeAll(moduleManager.getBuiltInModules()); + moduleList.setList(modules); + moduleList.setItemRenderer(new StringTextRenderer() { + @Override + public String getString(Module value) { + if (!selectedModules.contains(value)) { + return value.getId().toString(); + } else { + return value.getId().toString() + " (Active)"; + } + } + }); + moduleList.subscribe((list, module) -> { + if (selectedModules.contains(module)) { + selectedModules.remove(module); + } else { + selectedModules.add(module); + } + }); + + UIButton activateButton = find("activateButton", UIButton.class); + activateButton.bindEnabled(new ReadOnlyBinding() { + @Override + public Boolean get() { + Module selectedModule = moduleList.getSelection(); + return selectedModule != null && !selectedModules.contains(selectedModule); + } + }); + activateButton.subscribe(button -> selectedModules.add(moduleList.getSelection())); + + UIButton deactivateButton = find("deactivateButton", UIButton.class); + deactivateButton.bindEnabled(new ReadOnlyBinding() { + @Override + public Boolean get() { + Module selectedModule = moduleList.getSelection(); + return selectedModule != null && selectedModules.contains(selectedModule); + } + }); + deactivateButton.subscribe(button -> selectedModules.remove(moduleList.getSelection())); + + UIButton confirmButton = find("confirmButton", UIButton.class); + confirmButton.subscribe(button -> { + nuiManager.setScreen(solApplication.getMenuScreens().newShip); + }); + } + + public Set getSelectedModules() { + return selectedModules; + } + + public void setSelectedModules(Set selectedModules) { + this.selectedModules = selectedModules; + } +} diff --git a/engine/src/main/java/org/destinationsol/ui/nui/screens/mainMenu/NewShipScreen.java b/engine/src/main/java/org/destinationsol/ui/nui/screens/mainMenu/NewShipScreen.java index a9d0e1b6c..d2b6dcdc4 100644 --- a/engine/src/main/java/org/destinationsol/ui/nui/screens/mainMenu/NewShipScreen.java +++ b/engine/src/main/java/org/destinationsol/ui/nui/screens/mainMenu/NewShipScreen.java @@ -21,6 +21,7 @@ import org.destinationsol.assets.json.Validator; import org.destinationsol.game.WorldConfig; import org.destinationsol.game.planet.SystemsBuilder; +import org.destinationsol.modules.ModuleManager; import org.destinationsol.ui.nui.NUIManager; import org.destinationsol.ui.nui.NUIScreenLayer; import org.destinationsol.ui.nui.widgets.KeyActivatedButton; @@ -28,6 +29,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.terasology.gestalt.assets.ResourceUrn; +import org.terasology.gestalt.module.Module; +import org.terasology.gestalt.naming.Name; import org.terasology.nui.Canvas; import org.terasology.nui.UITextureRegion; import org.terasology.nui.backends.libgdx.GDXInputUtil; @@ -36,32 +39,41 @@ import javax.inject.Inject; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Optional; +import java.util.Set; public class NewShipScreen extends NUIScreenLayer { private static final Logger logger = LoggerFactory.getLogger(NewShipScreen.class); private final SolApplication solApplication; - private int numberOfSystems = SystemsBuilder.DEFAULT_SYSTEM_COUNT; + private final ModuleManager moduleManager; private int playerSpawnConfigIndex = 0; private List playerSpawnConfigNames = new ArrayList<>(); private List playerSpawnConfigTextures = new ArrayList<>(); + private WorldConfig worldConfig; @Inject - public NewShipScreen(SolApplication solApplication) { + public NewShipScreen(SolApplication solApplication, ModuleManager moduleManager) { this.solApplication = solApplication; + this.moduleManager = moduleManager; } @Override public void initialise() { + worldConfig = new WorldConfig(); + worldConfig.setNumberOfSystems(SystemsBuilder.DEFAULT_SYSTEM_COUNT); + worldConfig.setModules(new HashSet<>(moduleManager.getEnvironment().getModulesOrderedByDependencies())); + UIButton systemsButton = find("systemsButton", UIButton.class); - systemsButton.setText("Systems: " + numberOfSystems); + systemsButton.setText("Systems: " + worldConfig.getNumberOfSystems()); systemsButton.subscribe(button -> { - int systemCount = (numberOfSystems + 1) % 10; + int systemCount = (worldConfig.getNumberOfSystems() + 1) % 10; if (systemCount < 2) { systemCount = 2; } - numberOfSystems = systemCount; - ((UIButton)button).setText("Systems: " + numberOfSystems); + worldConfig.setNumberOfSystems(systemCount); + ((UIButton)button).setText("Systems: " + worldConfig.getNumberOfSystems()); }); for (ResourceUrn configUrn : Assets.getAssetHelper().listAssets(Json.class, "playerSpawnConfig")) { @@ -90,13 +102,17 @@ public void initialise() { shipPreviewImage.setImage(playerSpawnConfigTextures.get(playerSpawnConfigIndex)); }); + UIButton modulesButton = find("modulesButton", UIButton.class); + modulesButton.subscribe(button -> { + ModulesScreen modulesScreen = solApplication.getMenuScreens().modules; + modulesScreen.setSelectedModules(worldConfig.getModules()); + nuiManager.setScreen(modulesScreen); + }); + // NOTE: The original code used getKeyEscape() for both the "OK" and "Cancel" buttons. This was probably a mistake. KeyActivatedButton okButton = find("okButton", KeyActivatedButton.class); okButton.setKey(GDXInputUtil.GDXToNuiKey(solApplication.getOptions().getKeyShoot())); okButton.subscribe(button -> { - WorldConfig worldConfig = new WorldConfig(); - worldConfig.setNumberOfSystems(numberOfSystems); - LoadingScreen loadingScreen = solApplication.getMenuScreens().loading; loadingScreen.setMode(false, playerSpawnConfigNames.get(playerSpawnConfigIndex), true, worldConfig); nuiManager.setScreen(loadingScreen); @@ -109,6 +125,28 @@ public void initialise() { }); } + @Override + public void onAdded() { + worldConfig.setSeed(System.currentTimeMillis()); + + String currentShip = playerSpawnConfigNames.get(playerSpawnConfigIndex); + playerSpawnConfigNames.clear(); + Set configUrns = Assets.getAssetHelper().listAssets(Json.class, "playerSpawnConfig"); + for (Module module : worldConfig.getModules()) { + ResourceUrn configUrn = new ResourceUrn(module.getId(), new Name("playerSpawnConfig")); + if (configUrns.contains(configUrn)) { + playerSpawnConfigNames.addAll(Validator.getValidatedJSON(configUrn.toString(), "engine:schemaPlayerSpawnConfig").keySet()); + } + } + + if (!playerSpawnConfigNames.contains(currentShip)) { + // The player picked a ship that's now invalid, so reset their selection. + playerSpawnConfigIndex = 0; + UIButton startingShipButton = find("startingShipButton", UIButton.class); + startingShipButton.setText("Starting Ship: " + playerSpawnConfigNames.get(playerSpawnConfigIndex)); + } + } + @Override public void update(float delta) { super.update(delta); diff --git a/engine/src/main/resources/org/destinationsol/assets/skins/mainMenu.skin b/engine/src/main/resources/org/destinationsol/assets/skins/mainMenu.skin index 685ba8726..bcb6b5703 100644 --- a/engine/src/main/resources/org/destinationsol/assets/skins/mainMenu.skin +++ b/engine/src/main/resources/org/destinationsol/assets/skins/mainMenu.skin @@ -61,6 +61,9 @@ "creditsButton": { "font": "engine:main#0.60" }, + "modulesButton": { + "font": "engine:main#0.55" + }, "menuHeaderText": { "font": "engine:main#1.0" }, diff --git a/engine/src/main/resources/org/destinationsol/assets/ui/mainMenu/modulesScreen.ui b/engine/src/main/resources/org/destinationsol/assets/ui/mainMenu/modulesScreen.ui new file mode 100644 index 000000000..ff3ef21bf --- /dev/null +++ b/engine/src/main/resources/org/destinationsol/assets/ui/mainMenu/modulesScreen.ui @@ -0,0 +1,106 @@ +{ + "type": "ModulesScreen", + "skin": "engine:mainMenu", + "contents": { + "type": "RelativeLayout", + "contents": [ + { + "type": "UILabel", + "id": "headerText", + "family": "menuHeaderText", + "text": "Modules", + "layoutInfo": { + "position-horizontal-center": {}, + "position-top": { + "target": "TOP", + "offset": 32 + }, + "use-content-height": true + } + }, + { + "type": "ColumnLayout", + "id": "moduleSelectLayout", + "columns": 2, + "column-widths": [0.7, 0.3], + "horizontalSpacing": 16, + "contents": [ + { + "type": "ScrollableArea", + "content": { + "type": "UIList", + "id": "modulesList", + "family": "menuButtons" + } + }, + { + "type": "RelativeLayout", + "id": "moduleActionButtons", + "contents": [ + { + "type": "UIButton", + "id": "activateButton", + "text": "Activate Module", + "layoutInfo": { + "position-bottom": { + "target": "MIDDLE", + "offset": 5 + }, + "use-content-height": true + } + }, + { + "type": "UIButton", + "id": "deactivateButton", + "text": "Deactivate Module", + "layoutInfo": { + "position-top": { + "target": "MIDDLE", + "offset": 5 + }, + "use-content-height": true + } + } + ] + } + ], + "layoutInfo": { + "position-horizontal-center": {}, + "position-bottom": { + "widget": "confirmButton", + "target": "TOP", + "offset": 16 + }, + "position-top": { + "widget": "headerText", + "target": "BOTTOM", + "offset": 16 + }, + "position-left": { + "offset": 16 + }, + "position-right": { + "offset": 16 + } + } + }, + { + "type": "UIButton", + "id": "confirmButton", + "text": "Confirm", + "layoutInfo": { + "position-bottom": { + "offset": 32 + }, + "position-left": { + "offset": 32 + }, + "position-right": { + "offset": 32 + }, + "use-content-height": true + } + } + ] + } +} \ No newline at end of file diff --git a/engine/src/main/resources/org/destinationsol/assets/ui/mainMenu/newShipScreen.ui b/engine/src/main/resources/org/destinationsol/assets/ui/mainMenu/newShipScreen.ui index 36e8d2454..eed5dd8d8 100644 --- a/engine/src/main/resources/org/destinationsol/assets/ui/mainMenu/newShipScreen.ui +++ b/engine/src/main/resources/org/destinationsol/assets/ui/mainMenu/newShipScreen.ui @@ -74,6 +74,18 @@ "use-content-height": true, "use-content-width": true } + }, + { + "type": "UIButton", + "id": "modulesButton", + "family": "modulesButton", + "text": "Modules", + "layoutInfo": { + "position-right": {}, + "position-bottom": {}, + "width": 100, + "height": 50 + } } ] } From e0acf17c15d6b6c8d243afda4226bcc6d8bb1207 Mon Sep 17 00:00:00 2001 From: Benjamin Amos Date: Tue, 31 Dec 2024 12:52:25 +0000 Subject: [PATCH 2/2] fix(console): clear registered console commands on game start --- .../main/java/org/destinationsol/game/console/ConsoleImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/src/main/java/org/destinationsol/game/console/ConsoleImpl.java b/engine/src/main/java/org/destinationsol/game/console/ConsoleImpl.java index 9d79a7e6f..133127e8d 100644 --- a/engine/src/main/java/org/destinationsol/game/console/ConsoleImpl.java +++ b/engine/src/main/java/org/destinationsol/game/console/ConsoleImpl.java @@ -89,7 +89,7 @@ private static List splitParameters(String paramStr) { } public void init(SolGame game) { - + commandRegistry.clear(); for (Class commands : context.get(ModuleManager.class).getEnvironment().getTypesAnnotatedWith(RegisterCommands.class)) { try { Object commandsObject = commands.newInstance();