From c2376603aef847b2d680d722e31d5b9d7bd1224d Mon Sep 17 00:00:00 2001 From: jdrueckert Date: Mon, 13 Nov 2023 13:05:15 +0100 Subject: [PATCH] refactor: merge universe setup into world pregen screen (#5122) Merging UniverseSetupScreen and WorldPreGenerationScreen incl. * merging .ui representations * merging .java classes * merge widget bindings and screen logic * merge WorldSetupWrapper into UniverseWrapper * using UniverseWrapper instead of local copies of target world and seed for persisting state * binding UI widgets to persisted state * use universe seed and properly randomize seed on re-roll * remove worlds element in lower right screen section * update preview on changing seed field content and when opening screen * memorize modified (manually or via re-roll) seed field content (currently reset always to initial seed) Co-authored-by: Tobias Nett --- .../headless/mode/StateHeadlessSetup.java | 2 +- .../layers/mainMenu/GameManifestProvider.java | 34 +-- .../nui/layers/mainMenu/NewGameScreen.java | 12 +- .../layers/mainMenu/UniverseSetupScreen.java | 279 ++++++++++++----- .../nui/layers/mainMenu/UniverseWrapper.java | 26 +- .../mainMenu/WorldPreGenerationScreen.java | 281 ------------------ .../nui/layers/mainMenu/WorldSetupScreen.java | 68 +---- .../AdvancedGameSetupScreen.java | 41 ++- .../gameDetailsScreen/GameDetailsScreen.java | 15 +- .../rendering/world/WorldSetupWrapper.java | 58 ---- .../engine/world/internal/WorldInfo.java | 10 - .../world/internal/WorldProviderCoreImpl.java | 8 +- .../assets/ui/menu/universeSetupScreen.ui | 243 +++++++++++---- .../ui/menu/worldPreGenerationScreen.ui | 247 --------------- .../engine/assets/ui/worldSetupScreen.ui | 26 +- 15 files changed, 476 insertions(+), 874 deletions(-) delete mode 100644 engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/WorldPreGenerationScreen.java delete mode 100644 engine/src/main/java/org/terasology/engine/rendering/world/WorldSetupWrapper.java delete mode 100644 engine/src/main/resources/org/terasology/engine/assets/ui/menu/worldPreGenerationScreen.ui diff --git a/engine/src/main/java/org/terasology/engine/core/subsystem/headless/mode/StateHeadlessSetup.java b/engine/src/main/java/org/terasology/engine/core/subsystem/headless/mode/StateHeadlessSetup.java index 050278b74c4..f52891e5063 100644 --- a/engine/src/main/java/org/terasology/engine/core/subsystem/headless/mode/StateHeadlessSetup.java +++ b/engine/src/main/java/org/terasology/engine/core/subsystem/headless/mode/StateHeadlessSetup.java @@ -103,7 +103,7 @@ public GameManifest createGameManifest() { gameManifest.setTitle(worldGenConfig.getWorldTitle()); gameManifest.setSeed(worldGenConfig.getDefaultSeed()); - WorldInfo worldInfo = new WorldInfo(TerasologyConstants.MAIN_WORLD, worldGenConfig.getWorldTitle(), gameManifest.getSeed(), + WorldInfo worldInfo = new WorldInfo(TerasologyConstants.MAIN_WORLD, gameManifest.getSeed(), (long) (WorldTime.DAY_LENGTH * WorldTime.NOON_OFFSET), worldGeneratorUri); gameManifest.addWorld(worldInfo); return gameManifest; diff --git a/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/GameManifestProvider.java b/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/GameManifestProvider.java index 6ea129a913c..c865467121e 100644 --- a/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/GameManifestProvider.java +++ b/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/GameManifestProvider.java @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 package org.terasology.engine.rendering.nui.layers.mainMenu; -import com.google.common.collect.Maps; import org.codehaus.plexus.util.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -13,16 +12,14 @@ import org.terasology.engine.game.GameManifest; import org.terasology.engine.registry.In; import org.terasology.engine.rendering.nui.layers.mainMenu.savedGames.GameProvider; -import org.terasology.engine.rendering.world.WorldSetupWrapper; +import org.terasology.engine.world.generator.WorldConfigurator; +import org.terasology.engine.world.generator.WorldGenerator; import org.terasology.engine.world.internal.WorldInfo; import org.terasology.engine.world.time.WorldTime; -import org.terasology.gestalt.entitysystem.component.Component; import org.terasology.gestalt.module.Module; import org.terasology.gestalt.module.dependencyresolution.DependencyResolver; import org.terasology.gestalt.module.dependencyresolution.ResolutionResult; -import java.util.Map; - /** * Generates new games manifest according to input data. */ @@ -67,30 +64,25 @@ public static GameManifest createGameManifest(final UniverseWrapper universeWrap SimpleUri uri; String seed; - WorldSetupWrapper worldSetup = universeWrapper.getTargetWorld(); - if (worldSetup != null) { - uri = worldSetup.getWorldGenerator().getUri(); - seed = worldSetup.getWorldGenerator().getWorldSeed(); + WorldGenerator worldGenerator = universeWrapper.getWorldGenerator(); + if (worldGenerator != null) { + uri = worldGenerator.getUri(); + seed = worldGenerator.getWorldSeed(); } else { uri = config.getWorldGeneration().getDefaultGenerator(); seed = universeWrapper.getSeed(); } gameManifest.setSeed(seed); - String targetWorldName = ""; - Map worldConfig = Maps.newHashMap(); - if (worldSetup != null) { - targetWorldName = worldSetup.getWorldName().toString(); - if (worldSetup.getWorldConfigurator() != null) { - - // horrible hack to get configs into manifest. - // config driven by CreateWorldEntity. - // world config set somewhere else as well no clear drive from config --> world - gameManifest.setModuleConfigs(uri, worldSetup.getWorldConfigurator().getProperties()); - } + WorldConfigurator worldConfigurator = universeWrapper.getWorldConfigurator(); + if (worldConfigurator != null) { + // horrible hack to get configs into manifest. + // config driven by CreateWorldEntity. + // world config set somewhere else as well no clear drive from config --> world + gameManifest.setModuleConfigs(uri, worldConfigurator.getProperties()); } // This is multiplied by the number of seconds in a day (86400000) to determine the exact millisecond at which the game will start. - WorldInfo worldInfo = new WorldInfo(TerasologyConstants.MAIN_WORLD, targetWorldName, seed, + WorldInfo worldInfo = new WorldInfo(TerasologyConstants.MAIN_WORLD, seed, (long) (WorldTime.DAY_LENGTH * WorldTime.SUNRISE_OFFSET), uri); gameManifest.addWorld(worldInfo); diff --git a/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/NewGameScreen.java b/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/NewGameScreen.java index 50e019a1db0..521e6544187 100644 --- a/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/NewGameScreen.java +++ b/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/NewGameScreen.java @@ -134,7 +134,7 @@ public String get() { AdvancedGameSetupScreen advancedSetupGameScreen = getManager().createScreen(AdvancedGameSetupScreen.ASSET_URI, AdvancedGameSetupScreen.class); WidgetUtil.trySubscribe(this, "advancedSetup", button -> { universeWrapper.setGameName(gameName.getText()); - advancedSetupGameScreen.setUniverseWrapper(universeWrapper); + advancedSetupGameScreen.setEnvironment(universeWrapper); triggerForwardAnimation(advancedSetupGameScreen); }); @@ -281,12 +281,10 @@ public void setUniverseWrapper(UniverseWrapper wrapper) { @Override public boolean onKeyEvent(NUIKeyEvent event) { - if (event.isDown() && event.getKey() == Keyboard.Key.ESCAPE) { - if (GameProvider.isSavesFolderEmpty()) { - // skip selectGameScreen and get back directly to main screen - getManager().pushScreen("engine:mainMenuScreen"); - return true; - } + if (event.isDown() && event.getKey() == Keyboard.Key.ESCAPE && GameProvider.isSavesFolderEmpty()) { + // skip selectGameScreen and get back directly to main screen + getManager().pushScreen("engine:mainMenuScreen"); + return true; } return super.onKeyEvent(event); } diff --git a/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/UniverseSetupScreen.java b/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/UniverseSetupScreen.java index 9ff3983524b..43ff9c91930 100644 --- a/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/UniverseSetupScreen.java +++ b/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/UniverseSetupScreen.java @@ -8,20 +8,27 @@ import org.slf4j.LoggerFactory; import org.terasology.engine.config.Config; import org.terasology.engine.context.Context; -import org.terasology.engine.context.internal.ContextImpl; +import org.terasology.engine.core.GameEngine; +import org.terasology.engine.core.Time; import org.terasology.engine.core.bootstrap.EnvironmentSwitchHandler; +import org.terasology.engine.core.modes.StateLoading; import org.terasology.engine.core.module.ModuleManager; import org.terasology.engine.entitySystem.prefab.Prefab; import org.terasology.engine.entitySystem.prefab.internal.PojoPrefab; +import org.terasology.engine.game.GameManifest; import org.terasology.engine.logic.behavior.asset.BehaviorTree; +import org.terasology.engine.network.NetworkMode; import org.terasology.engine.registry.CoreRegistry; import org.terasology.engine.registry.In; +import org.terasology.engine.rendering.assets.texture.Texture; +import org.terasology.engine.rendering.assets.texture.TextureData; import org.terasology.engine.rendering.nui.CoreScreenLayer; import org.terasology.engine.rendering.nui.NUIManager; import org.terasology.engine.rendering.nui.animation.MenuAnimationSystems; -import org.terasology.engine.rendering.nui.layers.mainMenu.advancedGameSetupScreen.AdvancedGameSetupScreen; -import org.terasology.engine.rendering.world.WorldSetupWrapper; -import org.terasology.engine.world.block.family.BlockFamilyLibrary; +import org.terasology.engine.rendering.nui.layers.mainMenu.preview.FacetLayerPreview; +import org.terasology.engine.rendering.nui.layers.mainMenu.preview.PreviewGenerator; +import org.terasology.engine.utilities.Assets; +import org.terasology.engine.utilities.random.FastRandom; import org.terasology.engine.world.block.loader.BlockFamilyDefinition; import org.terasology.engine.world.block.loader.BlockFamilyDefinitionData; import org.terasology.engine.world.block.loader.BlockFamilyDefinitionFormat; @@ -35,6 +42,7 @@ import org.terasology.engine.world.generator.internal.WorldGeneratorManager; import org.terasology.engine.world.generator.plugin.TempWorldGeneratorPluginLibrary; import org.terasology.engine.world.generator.plugin.WorldGeneratorPluginLibrary; +import org.terasology.engine.world.zones.Zone; import org.terasology.gestalt.assets.AssetType; import org.terasology.gestalt.assets.ResourceUrn; import org.terasology.gestalt.assets.management.AssetManager; @@ -46,6 +54,7 @@ import org.terasology.gestalt.module.dependencyresolution.DependencyResolver; import org.terasology.gestalt.module.dependencyresolution.ResolutionResult; import org.terasology.gestalt.naming.Name; +import org.terasology.math.TeraMath; import org.terasology.nui.WidgetUtil; import org.terasology.nui.asset.UIElement; import org.terasology.nui.databinding.Binding; @@ -53,19 +62,26 @@ import org.terasology.nui.itemRendering.StringTextRenderer; import org.terasology.nui.skin.UISkinAsset; import org.terasology.nui.widgets.UIDropdownScrollable; +import org.terasology.nui.widgets.UIImage; +import org.terasology.nui.widgets.UISlider; +import org.terasology.nui.widgets.UISliderOnChangeTriggeredListener; +import org.terasology.nui.widgets.UIText; import org.terasology.reflection.copy.CopyStrategyLibrary; import org.terasology.reflection.reflect.ReflectFactory; import org.terasology.reflection.reflect.ReflectionReflectFactory; +import java.nio.ByteBuffer; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.concurrent.Callable; +import java.util.stream.Collectors; /** * Sets up the Universe for a user. Displays a list of {@link WorldGenerator} * for a particular game template. */ -public class UniverseSetupScreen extends CoreScreenLayer { +public class UniverseSetupScreen extends CoreScreenLayer implements UISliderOnChangeTriggeredListener { public static final ResourceUrn ASSET_URI = new ResourceUrn("engine:universeSetupScreen"); private static final Logger logger = LoggerFactory.getLogger(UniverseSetupScreen.class); @@ -79,10 +95,22 @@ public class UniverseSetupScreen extends CoreScreenLayer { @In private Config config; + @In + private GameEngine gameEngine; + + @In + private Context context; + + @In + private Time time; + private ModuleEnvironment environment; private ModuleAwareAssetTypeManager assetTypeManager; - private Context context; - private WorldSetupWrapper selectedWorld; + private UISlider zoomSlider; + private Texture texture; + private PreviewGenerator previewGen; + private UIImage previewImage; + private long previewUpdateRequiredSince = Long.MAX_VALUE; @Override public void initialise() { @@ -109,13 +137,14 @@ public List get() { return result; } }); - worldGenerators.setVisibleOptions(3); + worldGenerators.setVisibleOptions(worldGenerators.getOptions().size()); worldGenerators.bindSelection(new Binding() { @Override public WorldGeneratorInfo get() { // get the default generator from the config. This is likely to have a user triggered selection. WorldGeneratorInfo info = worldGeneratorManager.getWorldGeneratorInfo(config.getWorldGeneration().getDefaultGenerator()); if (info != null && getAllEnabledModuleNames().contains(info.getUri().getModuleName())) { + set(info); return info; } @@ -131,9 +160,13 @@ public WorldGeneratorInfo get() { } @Override - public void set(WorldGeneratorInfo value) { - if (value != null) { - config.getWorldGeneration().setDefaultGenerator(value.getUri()); + public void set(WorldGeneratorInfo worldGeneratorInfo) { + if (worldGeneratorInfo != null) { + if (context.get(UniverseWrapper.class).getWorldGenerator() == null + || !worldGeneratorInfo.getUri().equals(context.get(UniverseWrapper.class).getWorldGenerator().getUri())) { + config.getWorldGeneration().setDefaultGenerator(worldGeneratorInfo.getUri()); + addNewWorld(worldGeneratorInfo); + } } } }); @@ -148,36 +181,64 @@ public String getString(WorldGeneratorInfo value) { }); } - WidgetUtil.trySubscribe(this, "close", button -> - triggerBackAnimation() - ); - - WidgetUtil.trySubscribe(this, "continue", button -> { - final WorldPreGenerationScreen worldPreGenerationScreen = - getManager().createScreen(WorldPreGenerationScreen.ASSET_URI, WorldPreGenerationScreen.class); - addNewWorld(worldGenerators.getSelection()); - if (selectedWorld != null) { - final WaitPopup loadPopup = getManager().pushScreen(WaitPopup.ASSET_URI, WaitPopup.class); - loadPopup.setMessage("Loading", "please wait ..."); - loadPopup.onSuccess(result -> { - if (result != null && result) { - triggerForwardAnimation(worldPreGenerationScreen); - } else { - getManager().pushScreen(MessagePopup.ASSET_URI, MessagePopup.class) - .setMessage("Error", "Can't load world pre generation screen! Please, try again!"); - } - }); - loadPopup.startOperation(() -> { - try { - worldPreGenerationScreen.setEnvironment(context); - } catch (UnresolvedWorldGeneratorException e) { - return false; - } - return true; - }, true); + final UIText seedField = find("seed", UIText.class); + seedField.bindText(new Binding() { + @Override + public String get() { + return context.get(UniverseWrapper.class).getSeed(); + } + + @Override + public void set(String value) { + setSeed(value); + } + }); + + zoomSlider = find("zoomSlider", UISlider.class); + if (zoomSlider != null) { + zoomSlider.setValue(2f); + zoomSlider.setUiSliderOnChangeTriggeredListener(this); + } + + WidgetUtil.trySubscribe(this, "reRoll", button -> { + if (context.get(UniverseWrapper.class).getWorldGenerator() != null) { + setSeed(createRandomSeed()); + } else { + getManager().pushScreen(MessagePopup.ASSET_URI, MessagePopup.class) + .setMessage("No world generator selected!", "Please select a world generator first!"); + } + }); + + WorldSetupScreen worldSetupScreen = getManager().createScreen(WorldSetupScreen.ASSET_URI, WorldSetupScreen.class); + WidgetUtil.trySubscribe(this, "config", button -> { + if (context.get(UniverseWrapper.class).getWorldGenerator() != null) { + worldSetupScreen.setWorld(context, context.get(UniverseWrapper.class)); + triggerForwardAnimation(worldSetupScreen); } else { getManager().pushScreen(MessagePopup.ASSET_URI, MessagePopup.class) - .setMessage("Worlds List Empty!", "Please select a world generator and add words to the dropdown!"); + .setMessage("No world generator selected!", "Please select a world generator first!"); + } + }); + + WidgetUtil.trySubscribe(this, "close", button -> { + CoreRegistry.put(UniverseWrapper.class, context.get(UniverseWrapper.class)); + triggerBackAnimation(); + }); + + WidgetUtil.trySubscribe(this, "play", button -> { + if (context.get(UniverseWrapper.class).getWorldGenerator() == null) { + getManager().pushScreen(MessagePopup.ASSET_URI, MessagePopup.class) + .setMessage("No world generator selected!", "Please select a world generator first!"); + return; + } + + final GameManifest gameManifest = GameManifestProvider.createGameManifest(context.get(UniverseWrapper.class), moduleManager, config); + if (gameManifest != null) { + gameEngine.changeState(new StateLoading(gameManifest, (context.get(UniverseWrapper.class).getLoadingAsServer()) + ? NetworkMode.DEDICATED_SERVER + : NetworkMode.NONE)); + } else { + getManager().createScreen(MessagePopup.ASSET_URI, MessagePopup.class).setMessage("Error", "Can't create new game!"); } }); @@ -187,10 +248,29 @@ public String getString(WorldGeneratorInfo value) { } @Override - public void onOpened() { - super.onOpened(); + public void onScreenOpened() { + super.onScreenOpened(); + + if (texture != null) { + updatePreview(); + } + } + + @Override + public void update(float delta) { + super.update(delta); + + if (previewUpdateRequiredSince < time.getRealTimeInMs() - 1000) { + UniverseWrapper universeWrapper = context.get(UniverseWrapper.class); + universeWrapper.getWorldGenerator().setWorldSeed(universeWrapper.getSeed()); + updatePreview(); + previewUpdateRequiredSince = Long.MAX_VALUE; + } + } - selectedWorld = null; + private void setSeed(String value) { + context.get(UniverseWrapper.class).setSeed(value); + previewUpdateRequiredSince = time.getRealTimeInMs(); } private Set getAllEnabledModuleNames() { @@ -203,7 +283,6 @@ private Set getAllEnabledModuleNames() { return enabledModules; } - private void recursivelyAddModuleDependencies(Set modules, Name moduleName) { Module module = moduleManager.getRegistry().getLatestModuleVersion(moduleName); if (module != null) { @@ -215,44 +294,51 @@ private void recursivelyAddModuleDependencies(Set modules, Name moduleName } /** - * Called whenever the user decides to add a new world. + * Called whenever the user chooses a world generator. * @param worldGeneratorInfo The {@link WorldGeneratorInfo} object for the new world. */ private void addNewWorld(WorldGeneratorInfo worldGeneratorInfo) { - String selectedWorldName = worldGeneratorInfo.getDisplayName(); + UniverseWrapper universeWrapper = context.get(UniverseWrapper.class); + try { + WorldGenerator worldGenerator = WorldGeneratorManager.createWorldGenerator(worldGeneratorInfo.getUri(), context, environment); + worldGenerator.setWorldSeed(universeWrapper.getSeed()); + universeWrapper.setWorldGenerator(worldGenerator); + } catch (UnresolvedWorldGeneratorException e) { + //TODO: this will likely fail at game creation time later-on due to lack of world generator - don't just ignore this + e.printStackTrace(); + } - selectedWorld = new WorldSetupWrapper(new Name(selectedWorldName), worldGeneratorInfo); + texture = generateTexture(); + previewImage = find("preview", UIImage.class); + previewImage.setImage(texture); + List previewZones = Lists.newArrayList(universeWrapper.getWorldGenerator().getZones()) + .stream() + .filter(z -> !z.getPreviewLayers().isEmpty()) + .collect(Collectors.toList()); + if (previewZones.isEmpty()) { + previewGen = new FacetLayerPreview(environment, universeWrapper.getWorldGenerator()); + } + + updatePreview(); } /** * This method switches the environment of the game to a temporary one needed for * creating a game. It creates a new {@link Context} and only puts the minimum classes * needed for successful game creation. - * @param wrapper takes the {@link AdvancedGameSetupScreen} and pushes it into the new context. */ - public void setEnvironment(UniverseWrapper wrapper) { - context = new ContextImpl(); - CoreRegistry.setContext(context); - ReflectFactory reflectFactory = new ReflectionReflectFactory(); - context.put(ReflectFactory.class, reflectFactory); - CopyStrategyLibrary copyStrategyLibrary = new CopyStrategyLibrary(reflectFactory); - context.put(CopyStrategyLibrary.class, copyStrategyLibrary); - context.put(NUIManager.class, getManager()); - context.put(UniverseSetupScreen.class, this); - assetTypeManager = new AutoReloadAssetTypeManager(); - context.put(AssetManager.class, assetTypeManager.getAssetManager()); - context.put(ModuleAwareAssetTypeManager.class, assetTypeManager); - context.put(ModuleManager.class, moduleManager); - context.put(UniverseWrapper.class, wrapper); + public void setEnvironment() { + prepareContext(); DependencyResolver resolver = new DependencyResolver(moduleManager.getRegistry()); ResolutionResult result = resolver.resolve(config.getDefaultModSelection().listModules()); if (result.isSuccess()) { environment = moduleManager.loadEnvironment(result.getModules(), false); + //BlockFamilyLibrary library = new BlockFamilyLibrary(environment, context); + initializeAssets(); + context.put(ModuleEnvironment.class, environment); context.put(WorldGeneratorPluginLibrary.class, new TempWorldGeneratorPluginLibrary(environment, context)); - initAssets(); - EnvironmentSwitchHandler environmentSwitcher = new EnvironmentSwitchHandler(); context.put(EnvironmentSwitchHandler.class, environmentSwitcher); @@ -260,11 +346,20 @@ public void setEnvironment(UniverseWrapper wrapper) { } } - private void initAssets() { - - ModuleEnvironment environment = context.get(ModuleManager.class).getEnvironment(); - BlockFamilyLibrary library = new BlockFamilyLibrary(environment, context); + private void prepareContext() { + ReflectFactory reflectFactory = new ReflectionReflectFactory(); + context.put(ReflectFactory.class, reflectFactory); + CopyStrategyLibrary copyStrategyLibrary = new CopyStrategyLibrary(reflectFactory); + context.put(CopyStrategyLibrary.class, copyStrategyLibrary); + context.put(NUIManager.class, getManager()); + context.put(UniverseSetupScreen.class, this); + assetTypeManager = new AutoReloadAssetTypeManager(); + context.put(AssetManager.class, assetTypeManager.getAssetManager()); + context.put(ModuleAwareAssetTypeManager.class, assetTypeManager); + context.put(ModuleManager.class, moduleManager); + } + private void initializeAssets() { // cast lambdas explicitly to avoid inconsistent compiler behavior wrt. type inference assetTypeManager.createAssetType(Prefab.class, PojoPrefab::new, "prefabs"); assetTypeManager.createAssetType(BlockShape.class, BlockShapeImpl::new, "shapes"); @@ -281,15 +376,59 @@ private void initAssets() { } /** - * @return the selected world in the drop-down. + * Generates a texture and sets it to the image view, thus previewing the world. */ - public WorldSetupWrapper getSelectedWorld() { - return selectedWorld; + private Texture generateTexture() { + int imgWidth = 384; + int imgHeight = 384; + ByteBuffer buffer = ByteBuffer.allocateDirect(imgWidth * imgHeight * Integer.BYTES); + ByteBuffer[] data = new ByteBuffer[]{buffer}; + ResourceUrn uri = new ResourceUrn("engine:terrainPreview"); + TextureData texData = new TextureData(imgWidth, imgHeight, data, Texture.WrapMode.CLAMP, Texture.FilterMode.LINEAR); + return Assets.generateAsset(uri, texData, Texture.class); + } + + /** + * Updates the preview according to any changes made to the configurator. + * Also pops up a message and keeps track of percentage world preview prepared. + */ + private void updatePreview() { + + final NUIManager manager = context.get(NUIManager.class); + final WaitPopup popup = manager.pushScreen(WaitPopup.ASSET_URI, WaitPopup.class); + popup.setMessage("Updating Preview", "Please wait ..."); + + ProgressListener progressListener = progress -> + popup.setMessage("Updating Preview", String.format("Please wait ... %d%%", (int) (progress * 100f))); + + Callable operation = () -> { + int zoom = TeraMath.floorToInt(zoomSlider.getValue()); + TextureData data = texture.getData(); + + previewGen.render(data, zoom, progressListener); + + return data; + }; + + popup.onSuccess(texture::reload); + popup.startOperation(operation, true); + } + + private String createRandomSeed() { + String seed = new FastRandom().nextString(32); + return seed; } @Override public boolean isLowerLayerVisible() { return false; } + + @Override + public void onSliderValueChanged(float val) { + if (context.get(UniverseWrapper.class).getWorldGenerator() != null) { + previewUpdateRequiredSince = time.getRealTimeInMs(); + } + } } diff --git a/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/UniverseWrapper.java b/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/UniverseWrapper.java index f50239aba84..a776e236666 100644 --- a/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/UniverseWrapper.java +++ b/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/UniverseWrapper.java @@ -2,7 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 package org.terasology.engine.rendering.nui.layers.mainMenu; -import org.terasology.engine.rendering.world.WorldSetupWrapper; +import org.terasology.engine.world.generator.WorldConfigurator; +import org.terasology.engine.world.generator.WorldGenerator; /** * A class which stores the universe level properties for a game like whether @@ -10,13 +11,14 @@ */ public class UniverseWrapper { - private String seed; + private String seed = ""; private boolean loadingAsServer; private String gameName; - private WorldSetupWrapper targetWorld; + private WorldConfigurator worldConfigurator; + private WorldGenerator worldGenerator; public void setSeed(String seed) { - this.seed = seed; + this.seed = seed == null ? "" : seed; } public String getSeed() { @@ -39,11 +41,19 @@ public String getGameName() { return gameName; } - public void setTargetWorld(WorldSetupWrapper targetWorld) { - this.targetWorld = targetWorld; + public void setWorldConfigurator(WorldConfigurator worldConfigurator) { + this.worldConfigurator = worldConfigurator; } - public WorldSetupWrapper getTargetWorld() { - return targetWorld; + public WorldConfigurator getWorldConfigurator() { + return worldConfigurator; + } + + public void setWorldGenerator(WorldGenerator worldGenerator) { + this.worldGenerator = worldGenerator; + } + + public WorldGenerator getWorldGenerator() { + return worldGenerator; } } diff --git a/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/WorldPreGenerationScreen.java b/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/WorldPreGenerationScreen.java deleted file mode 100644 index 1a09cc29585..00000000000 --- a/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/WorldPreGenerationScreen.java +++ /dev/null @@ -1,281 +0,0 @@ -// Copyright 2021 The Terasology Foundation -// SPDX-License-Identifier: Apache-2.0 -package org.terasology.engine.rendering.nui.layers.mainMenu; - -import com.google.common.collect.Lists; -import org.joml.Vector2i; -import org.terasology.engine.config.Config; -import org.terasology.engine.context.Context; -import org.terasology.engine.core.GameEngine; -import org.terasology.engine.core.modes.StateLoading; -import org.terasology.engine.core.module.ModuleManager; -import org.terasology.engine.game.GameManifest; -import org.terasology.engine.network.NetworkMode; -import org.terasology.engine.registry.In; -import org.terasology.engine.rendering.assets.texture.Texture; -import org.terasology.engine.rendering.assets.texture.TextureData; -import org.terasology.engine.rendering.nui.CoreScreenLayer; -import org.terasology.engine.rendering.nui.NUIManager; -import org.terasology.engine.rendering.nui.animation.MenuAnimationSystems; -import org.terasology.engine.rendering.nui.layers.mainMenu.preview.FacetLayerPreview; -import org.terasology.engine.rendering.nui.layers.mainMenu.preview.PreviewGenerator; -import org.terasology.engine.rendering.world.WorldSetupWrapper; -import org.terasology.engine.utilities.Assets; -import org.terasology.engine.world.generator.UnresolvedWorldGeneratorException; -import org.terasology.engine.world.generator.WorldGenerator; -import org.terasology.engine.world.generator.internal.WorldGeneratorManager; -import org.terasology.engine.world.generator.plugin.TempWorldGeneratorPluginLibrary; -import org.terasology.engine.world.generator.plugin.WorldGeneratorPluginLibrary; -import org.terasology.engine.world.zones.Zone; -import org.terasology.gestalt.assets.ResourceUrn; -import org.terasology.gestalt.module.ModuleEnvironment; -import org.terasology.gestalt.naming.Name; -import org.terasology.math.TeraMath; -import org.terasology.nui.Canvas; -import org.terasology.nui.WidgetUtil; -import org.terasology.nui.databinding.Binding; -import org.terasology.nui.widgets.UIImage; -import org.terasology.nui.widgets.UISlider; -import org.terasology.nui.widgets.UISliderOnChangeTriggeredListener; -import org.terasology.nui.widgets.UIText; - -import java.nio.ByteBuffer; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.stream.Collectors; - -/** - * This class lets the user preview different worlds added in the - * {@link UniverseSetupScreen}. Each world is still configurable and its seed - * can be changed by the re-roll button. Note that each world has a unique seed. - */ -public class WorldPreGenerationScreen extends CoreScreenLayer implements UISliderOnChangeTriggeredListener { - - public static final ResourceUrn ASSET_URI = new ResourceUrn("engine:worldPreGenerationScreen"); - - @In - private ModuleManager moduleManager; - - @In - private Config config; - - @In - private GameEngine gameEngine; - - private ModuleEnvironment environment; - private WorldGenerator worldGenerator; - private Texture texture; - private UIImage previewImage; - private Context context; - private PreviewGenerator previewGen; - private UniverseWrapper universeWrapper; - private WorldSetupWrapper selectedWorld; - private int seedNumber; - private UISlider zoomSlider; - - /** - * A function called before the screen comes to the forefront to setup the environment - * and extract necessary objects from the new Context. - * - * @param subContext The new environment created in {@link UniverseSetupScreen} - * @throws UnresolvedWorldGeneratorException The creation of a world generator can throw this Exception - */ - public void setEnvironment(Context subContext) throws UnresolvedWorldGeneratorException { - - context = subContext; - environment = context.get(ModuleEnvironment.class); - context.put(WorldGeneratorPluginLibrary.class, new TempWorldGeneratorPluginLibrary(environment, context)); - selectedWorld = context.get(UniverseSetupScreen.class).getSelectedWorld(); - universeWrapper = context.get(UniverseWrapper.class); - - ensureWorldGeneratorIsSet(); - selectedWorld.getWorldGenerator().setWorldSeed(createSeed(selectedWorld.getWorldName().toString())); - - worldGenerator = selectedWorld.getWorldGenerator(); - genTexture(); - - List previewZones = Lists.newArrayList(worldGenerator.getZones()) - .stream() - .filter(z -> !z.getPreviewLayers().isEmpty()) - .collect(Collectors.toList()); - if (previewZones.isEmpty()) { - previewGen = new FacetLayerPreview(environment, worldGenerator); - } - } - - @Override - public void initialise() { - setAnimationSystem(MenuAnimationSystems.createDefaultSwipeAnimation()); - - zoomSlider = find("zoomSlider", UISlider.class); - if (zoomSlider != null) { - zoomSlider.setValue(2f); - zoomSlider.setUiSliderOnChangeTriggeredListener(this); - } - - final UIText worldName = find("worldName", UIText.class); - worldName.bindText(new Binding() { - @Override - public String get() { - return selectedWorld.getWorldName().toString(); - } - - @Override - public void set(String value) { - // no-op - // field should be read-only - } - }); - - WidgetUtil.trySubscribe(this, "reRoll", button -> { - worldGenerator.setWorldSeed(createSeed(selectedWorld.getWorldName().toString())); - updatePreview(); - }); - - WorldSetupScreen worldSetupScreen = getManager().createScreen(WorldSetupScreen.ASSET_URI, WorldSetupScreen.class); - WidgetUtil.trySubscribe(this, "config", button -> { - try { - if (!selectedWorld.getWorldName().isEmpty()) { - worldSetupScreen.setWorld(context, selectedWorld); - triggerForwardAnimation(worldSetupScreen); - } else { - getManager().pushScreen(MessagePopup.ASSET_URI, MessagePopup.class) - .setMessage("Worlds List Empty!", "No world found to configure."); - } - } catch (UnresolvedWorldGeneratorException e) { - e.printStackTrace(); - } - }); - - WidgetUtil.trySubscribe(this, "close", button -> { - triggerBackAnimation(); - }); - - WidgetUtil.trySubscribe(this, "play", button -> { - universeWrapper.setTargetWorld(selectedWorld); - final GameManifest gameManifest = GameManifestProvider.createGameManifest(universeWrapper, moduleManager, config); - if (gameManifest != null) { - gameEngine.changeState(new StateLoading(gameManifest, (universeWrapper.getLoadingAsServer()) - ? NetworkMode.DEDICATED_SERVER - : NetworkMode.NONE)); - } else { - getManager().createScreen(MessagePopup.ASSET_URI, MessagePopup.class).setMessage("Error", "Can't create new game!"); - } - }); - - WidgetUtil.trySubscribe(this, "mainMenu", button -> { - getManager().pushScreen("engine:mainMenuScreen"); - }); - } - - @Override - public void onOpened() { - super.onOpened(); - - try { - if (selectedWorld.getWorldGenerator() == null) { - worldGenerator = WorldGeneratorManager.createWorldGenerator(selectedWorld - .getWorldGeneratorInfo().getUri(), context, environment); - selectedWorld.setWorldGenerator(worldGenerator); - } else { - worldGenerator = selectedWorld.getWorldGenerator(); - } - if (worldGenerator.getWorldSeed().isEmpty()) { - worldGenerator.setWorldSeed(createSeed(selectedWorld.getWorldName().toString())); - } - previewGen = new FacetLayerPreview(environment, worldGenerator); - updatePreview(); - } catch (UnresolvedWorldGeneratorException e) { - e.printStackTrace(); - } - } - - //TODO: this does not actually only set it when configure is called from WorldPreGenerationScreen, but also if called from UniverseSetupScreen - /** - * Set seletedWorld when configure from WorldPreGenerationScreen - * @param newNameToSet - */ - public void setName(Name newNameToSet) { - selectedWorld.setWorldName(newNameToSet); - } - - /** - * Generates a texture and sets it to the image view, thus previewing the world. - */ - private void genTexture() { - int imgWidth = 384; - int imgHeight = 384; - ByteBuffer buffer = ByteBuffer.allocateDirect(imgWidth * imgHeight * Integer.BYTES); - ByteBuffer[] data = new ByteBuffer[]{buffer}; - ResourceUrn uri = new ResourceUrn("engine:terrainPreview"); - TextureData texData = new TextureData(imgWidth, imgHeight, data, Texture.WrapMode.CLAMP, Texture.FilterMode.LINEAR); - texture = Assets.generateAsset(uri, texData, Texture.class); - - previewImage = find("preview", UIImage.class); - previewImage.setImage(texture); - } - - /** - * Updates the preview according to any changes made to the configurator. - * Also pops up a message and keeps track of percentage world preview prepared. - */ - private void updatePreview() { - - final NUIManager manager = context.get(NUIManager.class); - final WaitPopup popup = manager.pushScreen(WaitPopup.ASSET_URI, WaitPopup.class); - popup.setMessage("Updating Preview", "Please wait ..."); - - ProgressListener progressListener = progress -> - popup.setMessage("Updating Preview", String.format("Please wait ... %d%%", (int) (progress * 100f))); - - Callable operation = () -> { - int zoom = TeraMath.floorToInt(zoomSlider.getValue()); - TextureData data = texture.getData(); - - previewGen.render(data, zoom, progressListener); - - return data; - }; - - popup.onSuccess(texture::reload); - popup.startOperation(operation, true); - } - - /** - * Creates a unique world seed by appending the world name with an incrementing number, on top of the universe seed. - * - * @param world {@link WorldSetupWrapper} object whose seed is to be set. - * @return The seed as a string. - */ - private String createSeed(String world) { - String seed = context.get(UniverseWrapper.class).getSeed(); - return seed + world + seedNumber++; - } - - private void ensureWorldGeneratorIsSet() { - if (selectedWorld.getWorldGenerator() == null) { - try { - selectedWorld.setWorldGenerator(WorldGeneratorManager.createWorldGenerator( - selectedWorld.getWorldGeneratorInfo().getUri(), context, environment)); - } catch (UnresolvedWorldGeneratorException e) { - //TODO: this will likely fail at game creation time later-on due to lack of world generator - don't just ignore this - e.printStackTrace(); - } - } - } - - @Override - public void onSliderValueChanged(float val) { - updatePreview(); - } - - @Override - public boolean isLowerLayerVisible() { - return false; - } - - @Override - public Vector2i getPreferredContentSize(Canvas canvas, Vector2i vector2i) { - return vector2i; - } -} diff --git a/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/WorldSetupScreen.java b/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/WorldSetupScreen.java index bdf90f8ff82..cf9ae162b93 100644 --- a/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/WorldSetupScreen.java +++ b/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/WorldSetupScreen.java @@ -4,13 +4,11 @@ import org.terasology.engine.config.Config; import org.terasology.engine.context.Context; -import org.terasology.engine.core.SimpleUri; import org.terasology.engine.entitySystem.metadata.ComponentLibrary; import org.terasology.engine.i18n.TranslationSystem; import org.terasology.engine.registry.In; import org.terasology.engine.rendering.nui.CoreScreenLayer; import org.terasology.engine.rendering.nui.animation.MenuAnimationSystems; -import org.terasology.engine.rendering.world.WorldSetupWrapper; import org.terasology.engine.world.generator.UnresolvedWorldGeneratorException; import org.terasology.engine.world.generator.WorldConfigurator; import org.terasology.engine.world.generator.WorldGenerator; @@ -20,7 +18,6 @@ import org.terasology.gestalt.assets.ResourceUrn; import org.terasology.gestalt.entitysystem.component.Component; import org.terasology.gestalt.module.ModuleEnvironment; -import org.terasology.gestalt.naming.Name; import org.terasology.nui.WidgetUtil; import org.terasology.nui.databinding.Binding; import org.terasology.nui.layouts.PropertyLayout; @@ -29,7 +26,6 @@ import org.terasology.nui.properties.PropertyOrdering; import org.terasology.nui.properties.PropertyProvider; import org.terasology.nui.widgets.UILabel; -import org.terasology.nui.widgets.UIText; import org.terasology.reflection.metadata.FieldMetadata; import org.terasology.reflection.reflect.ReflectFactory; @@ -54,59 +50,26 @@ public class WorldSetupScreen extends CoreScreenLayer { private TranslationSystem translationSystem; private WorldGenerator worldGenerator; - private WorldSetupWrapper world; + private UniverseWrapper universe; private ModuleEnvironment environment; private Context context; private WorldConfigurator oldWorldConfig; - private Name newWorldName; @Override public void initialise() { setAnimationSystem(MenuAnimationSystems.createDefaultSwipeAnimation()); - WidgetUtil.trySubscribe(this, "close", button -> { - UIText customWorldName = find("customisedWorldName", UIText.class); - - boolean goBack = false; - - //sanity checks on world name - if (customWorldName.getText().isEmpty()) { - //name empty: display a popup, stay on the same screen - getManager().pushScreen(MessagePopup.ASSET_URI, MessagePopup.class) - .setMessage("Name Cannot Be Empty!", "Please add a name for the world"); - } else if (customWorldName.getText().equalsIgnoreCase(world.getWorldName().toString())) { - //same name as before: go back to universe setup - goBack = true; - } else { - //no match found: go back to universe setup - goBack = true; - } + WidgetUtil.trySubscribe(this, "close", button -> { - if (goBack) { - newWorldName = new Name(customWorldName.getText()); - world.setWorldName(newWorldName); - triggerBackAnimation(); - } + triggerBackAnimation(); }); } - - /** - * This method sets the world name in title as well as in UITextBox - * - * @param customWorldName - */ - private void setCustomWorldName(UIText customWorldName) { - customWorldName.setText(world.getWorldName().toString()); - } - @Override public void onOpened() { super.onOpened(); - UILabel subitle = find("subtitle", UILabel.class); - subitle.setText(translationSystem.translate("${engine:menu#world-setup}") + " for " + world.getWorldName().toString()); - UIText customWorldName = find("customisedWorldName", UIText.class); - setCustomWorldName(customWorldName); + UILabel subtitle = find("subtitle", UILabel.class); + subtitle.setText(translationSystem.translate("${engine:menu#world-setup}") + " for " + universe.getGameName().toString()); } /** @@ -114,22 +77,15 @@ public void onOpened() { * to the forefront. * * @param subContext the new environment created in {@link UniverseSetupScreen} - * @param worldSelected the world whose configurations are to be changed. + * @param universe the universe whose world's configurations are to be changed. * @throws UnresolvedWorldGeneratorException */ - public void setWorld(Context subContext, WorldSetupWrapper worldSelected) - throws UnresolvedWorldGeneratorException { - world = worldSelected; + public void setWorld(Context subContext, UniverseWrapper universe) { + this.universe = universe; context = subContext; - SimpleUri worldGenUri = worldSelected.getWorldGeneratorInfo().getUri(); environment = context.get(ModuleEnvironment.class); context.put(WorldGeneratorPluginLibrary.class, new TempWorldGeneratorPluginLibrary(environment, context)); - if (world.getWorldGenerator() == null) { - worldGenerator = WorldGeneratorManager.createWorldGenerator(worldGenUri, context, environment); - world.setWorldGenerator(worldGenerator); - } else { - worldGenerator = world.getWorldGenerator(); - } + worldGenerator = universe.getWorldGenerator(); configureProperties(); } @@ -143,11 +99,11 @@ private void configureProperties() { propLayout.setOrdering(PropertyOrdering.byLabel()); propLayout.clear(); WorldConfigurator worldConfig; - if (world.getWorldConfigurator() != null) { - worldConfig = world.getWorldConfigurator(); + if (universe.getWorldConfigurator() != null) { + worldConfig = universe.getWorldConfigurator(); } else { worldConfig = worldGenerator.getConfigurator(); - world.setWorldConfigurator(worldConfig); + universe.setWorldConfigurator(worldConfig); } oldWorldConfig = worldConfig; diff --git a/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/advancedGameSetupScreen/AdvancedGameSetupScreen.java b/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/advancedGameSetupScreen/AdvancedGameSetupScreen.java index e7b58fcbb95..5b9b1f505d3 100644 --- a/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/advancedGameSetupScreen/AdvancedGameSetupScreen.java +++ b/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/advancedGameSetupScreen/AdvancedGameSetupScreen.java @@ -14,6 +14,7 @@ import org.terasology.engine.config.Config; import org.terasology.engine.config.ModuleConfig; import org.terasology.engine.config.SelectModulesConfig; +import org.terasology.engine.context.Context; import org.terasology.engine.core.GameEngine; import org.terasology.engine.core.SimpleUri; import org.terasology.engine.core.TerasologyConstants; @@ -25,6 +26,7 @@ import org.terasology.engine.game.GameManifest; import org.terasology.engine.i18n.TranslationSystem; import org.terasology.engine.network.NetworkMode; +import org.terasology.engine.registry.CoreRegistry; import org.terasology.engine.registry.In; import org.terasology.engine.rendering.nui.CoreScreenLayer; import org.terasology.engine.rendering.nui.animation.MenuAnimationSystems; @@ -94,6 +96,8 @@ public class AdvancedGameSetupScreen extends CoreScreenLayer { private TranslationSystem translationSystem; @In private GameEngine gameEngine; + @In + private Context context; private Map modulesLookup; private List sortedModules; @@ -103,7 +107,6 @@ public class AdvancedGameSetupScreen extends CoreScreenLayer { private boolean needsUpdate = true; private ResettableUIText moduleSearch; private SelectModulesConfig selectModulesConfig; - private UniverseWrapper universeWrapper; @Override public void onOpened() { @@ -117,6 +120,17 @@ public void onOpened() { filterModules(); } + @Override + public void onScreenOpened() { + super.onScreenOpened(); + + final UIText seed = find("seed", UIText.class); + UniverseWrapper universeWrapper = CoreRegistry.get(UniverseWrapper.class); + if (universeWrapper != null && !universeWrapper.getSeed().isEmpty()) { + seed.setText(universeWrapper.getSeed()); + } + } + @Override public void initialise() { setAnimationSystem(MenuAnimationSystems.createDefaultSwipeAnimation()); @@ -127,9 +141,7 @@ public void initialise() { .build()).submit(moduleManager.getInstallManager().updateRemoteRegistry()); final UIText seed = find("seed", UIText.class); - if (seed != null) { - seed.setText(new FastRandom().nextString(32)); - } + seed.setText(createRandomSeed()); // skip loading module configs, limit shown modules to locally present ones selectModulesConfig = new SelectModulesConfig(); @@ -496,11 +508,11 @@ public Boolean get() { } WidgetUtil.trySubscribe(this, "createWorld", button -> { + context.get(UniverseWrapper.class).setSeed(seed.getText()); final UniverseSetupScreen universeSetupScreen = getManager() .createScreen(UniverseSetupScreen.ASSET_URI, UniverseSetupScreen.class); - universeWrapper.setSeed(seed.getText()); saveConfiguration(); - universeSetupScreen.setEnvironment(universeWrapper); + universeSetupScreen.setEnvironment(); triggerForwardAnimation(universeSetupScreen); }); @@ -509,6 +521,7 @@ public Boolean get() { getManager().createScreen(MessagePopup.ASSET_URI, MessagePopup.class). setMessage("Error", "Game seed cannot be empty!"); } else { + UniverseWrapper universeWrapper = context.get(UniverseWrapper.class); universeWrapper.setSeed(seed.getText()); saveConfiguration(); final GameManifest gameManifest = GameManifestProvider.createGameManifest(universeWrapper, moduleManager, config); @@ -743,7 +756,6 @@ public boolean isLowerLayerVisible() { private void select(ModuleSelectionInfo target) { if (target.isValidToSelect() && !target.isExplicitSelection()) { - boolean previouslySelected = target.isSelected(); target.setExplicitSelection(true); refreshSelection(); } @@ -779,7 +791,18 @@ private void refreshSelection() { updateValidToSelect(); } - public void setUniverseWrapper(UniverseWrapper wrapper) { - universeWrapper = wrapper; + private String createRandomSeed() { + return new FastRandom().nextString(32); + } + + public void setEnvironment(UniverseWrapper wrapper) { + // Theoretically, the idea was to do the following: + // context.put(UniverseWrapper.class, wrapper); + // CoreRegistry.setContext(context); + // However, this does not work and leads to an NPE in UniverseSetupScreen.java:182 + // when attempting to access UniverseWrapper from a context that it's not in. + // At this moment, it's unclear, why this does not work. + // TODO: Investigate the inconsistencies between context and core registry usage + CoreRegistry.put(UniverseWrapper.class, wrapper); } } diff --git a/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/gameDetailsScreen/GameDetailsScreen.java b/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/gameDetailsScreen/GameDetailsScreen.java index af6690c865d..dc06e16d0f4 100644 --- a/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/gameDetailsScreen/GameDetailsScreen.java +++ b/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/gameDetailsScreen/GameDetailsScreen.java @@ -219,16 +219,12 @@ private void setUpGameWorlds() { gameWorlds.setItemRenderer(new AbstractItemRenderer() { @Override public void draw(WorldInfo value, Canvas canvas) { - if (value.getCustomTitle().isEmpty()) { - canvas.drawText(value.getTitle()); - } else { - canvas.drawText(value.getCustomTitle()); - } + canvas.drawText(value.getTitle()); } @Override public Vector2i getPreferredSize(WorldInfo value, Canvas canvas) { - String text = value.getCustomTitle(); + String text = value.getTitle(); return new Vector2i( canvas.getCurrentStyle().getFont().getWidth(text), canvas.getCurrentStyle().getFont().getLineHeight()); @@ -237,12 +233,7 @@ public Vector2i getPreferredSize(WorldInfo value, Canvas canvas) { } private String getWorldDescription(final WorldInfo worldInfo) { - String gameTitle; - if (worldInfo.getCustomTitle().isEmpty()) { - gameTitle = worldInfo.getTitle(); - } else { - gameTitle = worldInfo.getCustomTitle(); - } + String gameTitle = worldInfo.getTitle(); return translationSystem.translate("${engine:menu#game-details-game-title} ") + gameTitle + '\n' + '\n' + translationSystem.translate("${engine:menu#game-details-game-seed} ") + worldInfo.getSeed() diff --git a/engine/src/main/java/org/terasology/engine/rendering/world/WorldSetupWrapper.java b/engine/src/main/java/org/terasology/engine/rendering/world/WorldSetupWrapper.java deleted file mode 100644 index 144d7285029..00000000000 --- a/engine/src/main/java/org/terasology/engine/rendering/world/WorldSetupWrapper.java +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2021 The Terasology Foundation -// SPDX-License-Identifier: Apache-2.0 -package org.terasology.engine.rendering.world; - -import org.terasology.gestalt.naming.Name; -import org.terasology.engine.world.generator.WorldConfigurator; -import org.terasology.engine.world.generator.WorldGenerator; -import org.terasology.engine.world.generator.internal.WorldGeneratorInfo; - -/** - * This class only has significance during the create game phase. - * Every world is an object of this class. - */ -public class WorldSetupWrapper { - - private Name worldName; - private WorldGeneratorInfo worldGeneratorInfo; - private WorldConfigurator worldConfigurator; - private WorldGenerator worldGenerator; - - /** - * A constructor to initialise a world object. - * @param worldName The World Name which is displayed in the drop-downs. - * @param worldGeneratorInfo Contains the {@link WorldGeneratorInfo} object for that world. - */ - public WorldSetupWrapper(Name worldName, WorldGeneratorInfo worldGeneratorInfo) { - this.worldName = worldName; - this.worldGeneratorInfo = worldGeneratorInfo; - } - - public WorldGeneratorInfo getWorldGeneratorInfo() { - return this.worldGeneratorInfo; - } - - public Name getWorldName() { - return this.worldName; - } - - public void setWorldName(Name newName) { - this.worldName = newName; - } - - public void setWorldConfigurator(WorldConfigurator worldConfigurator) { - this.worldConfigurator = worldConfigurator; - } - - public WorldConfigurator getWorldConfigurator() { - return worldConfigurator; - } - - public void setWorldGenerator(WorldGenerator worldGenerator) { - this.worldGenerator = worldGenerator; - } - - public WorldGenerator getWorldGenerator() { - return worldGenerator; - } -} diff --git a/engine/src/main/java/org/terasology/engine/world/internal/WorldInfo.java b/engine/src/main/java/org/terasology/engine/world/internal/WorldInfo.java index 0687830ec3b..26bd3405e1f 100644 --- a/engine/src/main/java/org/terasology/engine/world/internal/WorldInfo.java +++ b/engine/src/main/java/org/terasology/engine/world/internal/WorldInfo.java @@ -12,7 +12,6 @@ public class WorldInfo { private String title = ""; - private String customTitle = ""; private String seed = ""; private long time; private SimpleUri worldGenerator = new SimpleUri(); @@ -21,14 +20,9 @@ public WorldInfo() { } public WorldInfo(String title, String seed, long time, SimpleUri worldGenerator) { - this(title, "", seed, time, worldGenerator); - } - - public WorldInfo(String title, String customTitle, String seed, long time, SimpleUri worldGenerator) { if (title != null) { this.title = title; } - this.customTitle = customTitle; if (seed != null) { this.seed = seed; } @@ -48,10 +42,6 @@ public void setTitle(String title) { } } - public String getCustomTitle() { - return customTitle; - } - public String getSeed() { return seed; } diff --git a/engine/src/main/java/org/terasology/engine/world/internal/WorldProviderCoreImpl.java b/engine/src/main/java/org/terasology/engine/world/internal/WorldProviderCoreImpl.java index 0db21115845..f4514cb9965 100644 --- a/engine/src/main/java/org/terasology/engine/world/internal/WorldProviderCoreImpl.java +++ b/engine/src/main/java/org/terasology/engine/world/internal/WorldProviderCoreImpl.java @@ -48,7 +48,6 @@ public class WorldProviderCoreImpl implements WorldProviderCore { private String title; - private String customTitle; private String seed = ""; private SimpleUri worldGenerator; @@ -63,10 +62,9 @@ public class WorldProviderCoreImpl implements WorldProviderCore { private Block unloadedBlock; - public WorldProviderCoreImpl(String title, String customTitle, String seed, long time, SimpleUri worldGenerator, + public WorldProviderCoreImpl(String title, String seed, long time, SimpleUri worldGenerator, ChunkProvider chunkProvider, Block unloadedBlock, Context context) { this.title = (title == null) ? seed : title; - this.customTitle = customTitle; this.seed = seed; this.worldGenerator = worldGenerator; this.chunkProvider = chunkProvider; @@ -89,7 +87,7 @@ public WorldProviderCoreImpl(String title, String customTitle, String seed, long public WorldProviderCoreImpl(WorldInfo info, ChunkProvider chunkProvider, Block unloadedBlock, Context context) { - this(info.getTitle(), info.getCustomTitle(), info.getSeed(), info.getTime(), info.getWorldGenerator(), + this(info.getTitle(), info.getSeed(), info.getTime(), info.getWorldGenerator(), chunkProvider, unloadedBlock, context); } @@ -115,7 +113,7 @@ public String getSeed() { @Override public WorldInfo getWorldInfo() { - return new WorldInfo(title, customTitle, seed, worldTime.getMilliseconds(), worldGenerator); + return new WorldInfo(title, seed, worldTime.getMilliseconds(), worldGenerator); } @Override diff --git a/engine/src/main/resources/org/terasology/engine/assets/ui/menu/universeSetupScreen.ui b/engine/src/main/resources/org/terasology/engine/assets/ui/menu/universeSetupScreen.ui index c4290c916a7..2e5600eed76 100644 --- a/engine/src/main/resources/org/terasology/engine/assets/ui/menu/universeSetupScreen.ui +++ b/engine/src/main/resources/org/terasology/engine/assets/ui/menu/universeSetupScreen.ui @@ -1,5 +1,5 @@ { - "type": "UniverseSetupScreen", + "type": "engine:UniverseSetupScreen", "skin": "engine:mainMenu", "contents": { "type": "relativeLayout", @@ -8,7 +8,7 @@ "type": "UILabel", "id": "title", "family": "title", - "text": "${engine:menu#universe-setup}", + "text": "${engine:menu#world-pre-generation}", "layoutInfo": { "height": 48, "position-horizontal-center": {}, @@ -20,51 +20,185 @@ }, { "type": "UIBox", - "id": "mainBox", - "content": { - "type": "ColumnLayout", - "columns": 1, - "verticalSpacing": 4, - "horizontalSpacing": 4, - "contents": [ - { - "type": "UILabel", - "text": "${engine:menu#universe-setup-description}" - }, - { - "type": "UILabel", - "text": "${engine:menu#game-world-generators}:", - "family": "left-label" - }, - { - "type": "RowLayout", - "horizontalSpacing": 4, - "contents": [ - { - "type": "UIDropdownScrollable", - "id": "worldGenerators", - "layoutInfo": { - "relativeWidth": 1.00 - } + "id": "container", + "layoutInfo": { + "width": 720, + "position-horizontal-center": {}, + "position-top": { + "target": "TOP", + "offset": -16, + "widget": "generator" + }, + "position-bottom": { + "target": "BOTTOM", + "offset": -16, + "widget": "coreLayout" + } + } + }, + { + "type": "ColumnLayout", + "id": "generator", + "columns": 1, + "verticalSpacing": 4, + "horizontalSpacing": 4, + "contents": [ + { + "type": "UILabel", + "text": "${engine:menu#universe-setup-description}" + }, + { + "type": "UILabel", + "text": "${engine:menu#game-world-generators}:", + "family": "left-label" + }, + { + "type": "RowLayout", + "horizontalSpacing": 4, + "contents": [ + { + "type": "UIDropdownScrollable", + "id": "worldGenerators", + "layoutInfo": { + "relativeWidth": 1.00 } - ] - }, - { - "type": "UISpace", - "size": [ - 1, - 8 - ] - } - ] - }, + } + ] + }, + { + "type": "UILabel", + "text": "${engine:menu#world-seed}:", + "family": "left-label" + }, + { + "type": "UIText", + "id": "seed" + }, + { + "type": "UISpace", + "size": [ + 1, + 8 + ] + } + ], "layoutInfo": { "width": 500, "use-content-height": true, "position-horizontal-center": {}, - "position-vertical-center": {} + "position-bottom": { + "target": "TOP", + "offset": 16, + "widget": "coreLayout" + } } }, + { + "type": "ColumnLayout", + "id": "coreLayout", + "columns": 2, + "horizontalSpacing": 8, + "column-widths": [ + 0.53, + 0.47 + ], + "layoutInfo": { + "width": 704, + "use-content-height": true, + "position-horizontal-center": {}, + "position-vertical-center": {} + }, + "contents": [ + { + "type": "UIImage", + "skin": "framed_image", + "id": "preview" + }, + { + "type": "ColumnLayout", + "columns": 1, + "verticalSpacing": 4, + "contents": [ + { + "type": "UILabel", + "text": "${engine:menu#pregeneration-description}" + }, + { + "type": "UILabel", + "text": "${engine:menu#time-progression-during-pre-generation}:", + "id": "timeLabel", + "family": "left-label", + "enabled": false + }, + { + "type": "UISlider", + "id": "timeSlider", + "minimum": 0.0, + "range": 9.0, + "increment": 1.0, + "precision": 0, + "value": 0.0, + "enabled": false, + "layoutInfo": { + "position-horizontal-center": {}, + "position-top": { + "target": "BOTTOM", + "widget": "timeLabel", + "offset": 0 + } + } + }, + { + "type": "UILabel", + "text": "${engine:menu#preview-zoom-factor}:", + "id": "zoomLabel", + "family": "left-label", + "layoutInfo": { + "position-horizontal-center": {}, + "position-top": { + "target": "BOTTOM", + "widget": "timeSlider", + "offset": 0 + } + } + }, + { + "type": "UISlider", + "id": "zoomSlider", + "minimum": 1.0, + "range": 7.0, + "increment": 1.0, + "precision": 0, + "layoutInfo": { + "use-content-height": true, + "position-horizontal-center": {}, + "position-top": { + "target": "BOTTOM", + "widget": "zoomLabel" + } + } + }, + { + "type": "RowLayout", + "id": "worldGenActions", + "horizontalSpacing": 4, + "contents": [ + { + "type": "UIButton", + "text": "${engine:menu#re-roll}", + "id": "reRoll" + }, + { + "type": "UIButton", + "text": "${engine:menu#config}", + "id": "config" + } + ] + } + ] + } + ] + }, { "type": "RowLayout", "id": "actionsRow", @@ -78,8 +212,7 @@ { "type": "UIButton", "text": "${engine:menu#start-playing}", - "id": "play", - "enabled": false + "id": "play" } ], "layoutInfo": { @@ -88,43 +221,25 @@ "position-horizontal-center": {}, "position-top": { "target": "BOTTOM", - "widget": "mainBox", + "widget": "container", "offset": 16 } } }, { "type": "UIButton", - "text": "${engine:menu#return-advanced-setup}", + "text": "${engine:menu#return-universe-setup}", "id": "close", "layoutInfo": { "width": 120, "height": 80, "position-vertical-center": { "target": "CENTER", - "widget": "mainBox" + "widget": "container" }, "position-right": { "target": "LEFT", - "offset": 16, - "widget": "mainBox" - } - } - }, - { - "type": "UIButton", - "text": "${engine:menu#continue-pregeneration}", - "id": "continue", - "layoutInfo": { - "width": 120, - "height": 80, - "position-vertical-center": { - "target": "CENTER", - "widget": "mainBox" - }, - "position-left": { - "target": "RIGHT", - "widget": "mainBox", + "widget": "container", "offset": 16 } } diff --git a/engine/src/main/resources/org/terasology/engine/assets/ui/menu/worldPreGenerationScreen.ui b/engine/src/main/resources/org/terasology/engine/assets/ui/menu/worldPreGenerationScreen.ui deleted file mode 100644 index 4fb56d6823e..00000000000 --- a/engine/src/main/resources/org/terasology/engine/assets/ui/menu/worldPreGenerationScreen.ui +++ /dev/null @@ -1,247 +0,0 @@ -{ - "type": "engine:WorldPreGenerationScreen", - "skin": "engine:mainMenu", - "contents": { - "type": "relativeLayout", - "contents": [ - { - "type": "UILabel", - "id": "title", - "family": "title", - "text": "${engine:menu#world-pre-generation}", - "layoutInfo": { - "height": 48, - "position-horizontal-center": {}, - "position-top": { - "target": "TOP", - "offset": 48 - } - } - }, - { - "type": "UIBox", - "id": "container", - "layoutInfo": { - "width": 720, - "position-horizontal-center": {}, - "position-top": { - "target": "TOP", - "offset": -16, - "widget": "coreLayout" - }, - "position-bottom": { - "target": "BOTTOM", - "offset": -16, - "widget": "coreLayout" - } - } - }, - { - "type": "ColumnLayout", - "id": "coreLayout", - "columns": 2, - "horizontalSpacing": 8, - "column-widths": [ - 0.53, - 0.47 - ], - "layoutInfo": { - "width": 704, - "use-content-height": true, - "position-horizontal-center": {}, - "position-vertical-center": {} - }, - "contents": [ - { - "type": "UIImage", - "skin": "framed_image", - "id": "preview" - }, - { - "type": "ColumnLayout", - "columns": 1, - "verticalSpacing": 4, - "contents": [ - { - "type": "UILabel", - "text": "${engine:menu#pregeneration-description}" - }, - { - "type": "UILabel", - "text": "${engine:menu#time-progression-during-pre-generation}:", - "id": "timeLabel", - "family": "left-label", - "enabled": false - }, - { - "type": "UISlider", - "id": "timeSlider", - "minimum": 0.0, - "range": 9.0, - "increment": 1.0, - "precision": 0, - "value": 0.0, - "enabled": false, - "layoutInfo": { - "position-horizontal-center": {}, - "position-top": { - "target": "BOTTOM", - "widget": "timeLabel", - "offset": 0 - } - } - }, - { - "type": "UILabel", - "text": "${engine:menu#preview-zoom-factor}:", - "id": "zoomLabel", - "family": "left-label", - "layoutInfo": { - "position-horizontal-center": {}, - "position-top": { - "target": "BOTTOM", - "widget": "timeSlider", - "offset": 0 - } - } - }, - { - "type": "UISlider", - "id": "zoomSlider", - "minimum": 1.0, - "range": 7.0, - "increment": 1.0, - "precision": 0, - "layoutInfo": { - "use-content-height": true, - "position-horizontal-center": {}, - "position-top": { - "target": "BOTTOM", - "widget": "zoomLabel" - } - } - }, - { - "type": "UILabel", - "text": "${engine:menu#game-worlds}:", - "id": "worldLabel", - "family": "left-label", - "layoutInfo": { - "position-horizontal-center": {}, - "position-top": { - "target": "BOTTOM", - "widget": "zoomSlider", - "offset": 0 - } - } - }, - { - "type": "engine:UIText", - "id": "worldName", - "readOnly": true, - "enabled": false, - "layoutInfo": {} - }, - { - "type": "RowLayout", - "id": "worldGenActions", - "horizontalSpacing": 4, - "contents": [ - { - "type": "UIButton", - "text": "${engine:menu#re-roll}", - "id": "reRoll" - }, - { - "type": "UIButton", - "text": "${engine:menu#config}", - "id": "config" - } - ] - } - ] - } - ] - }, - { - "type": "RowLayout", - "id": "actionsRow", - "horizontalSpacing": 32, - "contents": [ - { - "type": "UIButton", - "text": "${engine:menu#return-main-menu}", - "id": "mainMenu" - }, - { - "type": "UIButton", - "text": "${engine:menu#start-playing}", - "id": "play" - } - ], - "layoutInfo": { - "width": 272, - "height": 80, - "position-horizontal-center": {}, - "position-top": { - "target": "BOTTOM", - "widget": "container", - "offset": 16 - } - } - }, - { - "type": "UIButton", - "text": "${engine:menu#return-universe-setup}", - "id": "close", - "layoutInfo": { - "width": 120, - "height": 80, - "position-vertical-center": { - "target": "CENTER", - "widget": "container" - }, - "position-right": { - "target": "LEFT", - "widget": "container", - "offset": 16 - } - } - }, - { - "type": "UIImage", - "image": "engine:happyGooey", - "layoutInfo": { - "width": 87, - "height": 40, - "position-left": { - "target": "RIGHT", - "widget": "actionsRow", - "offset": 8 - }, - "position-vertical-center": { - "target": "CENTER", - "widget": "actionsRow" - } - } - }, - { - "type": "UIImage", - "image": "engine:angryGooey", - "layoutInfo": { - "width": 87, - "height": 40, - "position-right": { - "target": "LEFT", - "widget": "actionsRow", - "offset": 8 - }, - "position-vertical-center": { - "target": "CENTER", - "widget": "actionsRow" - } - } - } - ] - } -} diff --git a/engine/src/main/resources/org/terasology/engine/assets/ui/worldSetupScreen.ui b/engine/src/main/resources/org/terasology/engine/assets/ui/worldSetupScreen.ui index 0260c70e9e3..c01291885fa 100644 --- a/engine/src/main/resources/org/terasology/engine/assets/ui/worldSetupScreen.ui +++ b/engine/src/main/resources/org/terasology/engine/assets/ui/worldSetupScreen.ui @@ -60,28 +60,6 @@ "type": "RelativeLayout", "family": "description", "contents": [ - { - "type": "RowLayout", - "id": "customNameWorld", - "layoutInfo": { - "use-content-height": true, - "position-horizontal-center": {}, - "position-top": { - "target": "TOP" - } - }, - "contents": [ - { - "type": "UILabel", - "text": "${engine:menu#world-name}" - }, - { - "type": "UIText", - "text": "", - "id": "customisedWorldName" - } - ] - }, { "type": "ScrollableArea", "content": { @@ -92,9 +70,7 @@ "layoutInfo": { "position-horizontal-center": {}, "position-top": { - "target": "BOTTOM", - "offset": 8, - "widget": "customNameWorld" + "target": "TOP" }, "position-bottom": { "target": "TOP",