diff --git a/engine/src/main/java/org/destinationsol/SolApplication.java b/engine/src/main/java/org/destinationsol/SolApplication.java index 976376fd8..8d45cdc51 100644 --- a/engine/src/main/java/org/destinationsol/SolApplication.java +++ b/engine/src/main/java/org/destinationsol/SolApplication.java @@ -350,7 +350,7 @@ public void play(boolean tut, String shipName, boolean isNewGame, WorldConfig wo entitySystemManager.initialise(); solGame.createUpdateSystems(); - solGame.startGame(shipName, isNewGame, worldConfig, entitySystemManager); + solGame.startGame(shipName, isNewGame, entitySystemManager); if (!isNewGame) { try { diff --git a/engine/src/main/java/org/destinationsol/game/GalaxyFiller.java b/engine/src/main/java/org/destinationsol/game/GalaxyFiller.java index 59bb6a010..f57fb8df5 100644 --- a/engine/src/main/java/org/destinationsol/game/GalaxyFiller.java +++ b/engine/src/main/java/org/destinationsol/game/GalaxyFiller.java @@ -43,6 +43,7 @@ import javax.inject.Inject; import java.util.ArrayList; +import java.util.List; public class GalaxyFiller { private static final float STATION_CONSUME_SECTOR = 45f; @@ -140,7 +141,7 @@ public void fill(SolGame game, HullConfigManager hullConfigManager, ItemManager return; } createStarPorts(game); - ArrayList systems = game.getGalaxyBuilder().getBuiltSolarSystems(); + List systems = game.getGalaxyBuilder().getBuiltSolarSystems(); JSONObject rootNode = Validator.getValidatedJSON(moduleName + ":startingStation", "engine:schemaStartingStation"); diff --git a/engine/src/main/java/org/destinationsol/game/SaveManager.java b/engine/src/main/java/org/destinationsol/game/SaveManager.java index 516af8173..bc4b34879 100644 --- a/engine/src/main/java/org/destinationsol/game/SaveManager.java +++ b/engine/src/main/java/org/destinationsol/game/SaveManager.java @@ -20,6 +20,8 @@ import com.badlogic.gdx.math.Vector2; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.stream.JsonReader; @@ -232,16 +234,29 @@ public static ShipConfig readShip(HullConfigManager hullConfigs, ItemManager ite } /** - * Saves the world to a file. Currently stores the seed used to generate the world and the number of systems - * @param numberOfSystems + * Saves the world to a file. Currently stores the seed used to generate the world, + * the number of systems and the generators used. + * @param worldConfig the current world configuration. */ - public static void saveWorld(int numberOfSystems) { + public static void saveWorld(WorldConfig worldConfig) { Long seed = SolRandom.getSeed(); String fileName = SaveManager.getResourcePath(Const.WORLD_SAVE_FILE_NAME); JsonObject world = new JsonObject(); world.addProperty("seed", seed); - world.addProperty("systems", numberOfSystems); + world.addProperty("systems", worldConfig.getNumberOfSystems()); + + JsonArray solarSystemGenerators = new JsonArray(); + for (String solarSystemGenerator : worldConfig.getSolarSystemGenerators()) { + solarSystemGenerators.add(solarSystemGenerator); + } + world.add("solarSystemGenerators", solarSystemGenerators); + + JsonArray featureGenerators = new JsonArray(); + for (String featureGenerator : worldConfig.getFeatureGenerators()) { + featureGenerators.add(featureGenerator); + } + world.add("featureGenerators", featureGenerators); Gson gson = new GsonBuilder().setPrettyPrinting().create(); String stringToWrite = gson.toJson(world); @@ -272,6 +287,26 @@ public static Optional loadWorld() { config.setNumberOfSystems(world.get("systems").getAsInt()); } + if (world.has("solarSystemGenerators")) { + List solarSystemGenerators = new ArrayList<>(); + for (JsonElement value : world.getAsJsonArray("solarSystemGenerators")) { + if (value.isJsonPrimitive() && value.getAsJsonPrimitive().isString()) { + solarSystemGenerators.add(value.getAsString()); + } + } + config.setSolarSystemGenerators(solarSystemGenerators); + } + + if (world.has("featureGenerators")) { + List featureGenerators = new ArrayList<>(); + for (JsonElement value : world.getAsJsonArray("featureGenerators")) { + if (value.isJsonPrimitive() && value.getAsJsonPrimitive().isString()) { + featureGenerators.add(value.getAsString()); + } + } + config.setFeatureGenerators(featureGenerators); + } + logger.debug("Successfully loaded the world file"); return Optional.of(config); } catch (FileNotFoundException e) { diff --git a/engine/src/main/java/org/destinationsol/game/SolGame.java b/engine/src/main/java/org/destinationsol/game/SolGame.java index a980d12cd..7fe5d3b95 100644 --- a/engine/src/main/java/org/destinationsol/game/SolGame.java +++ b/engine/src/main/java/org/destinationsol/game/SolGame.java @@ -149,6 +149,8 @@ public class SolGame { protected SolCam solCam; @Inject protected ModuleManager moduleManager; + @Inject + protected WorldConfig worldConfig; protected SolApplication solApplication; private Hero hero; @@ -236,7 +238,7 @@ public void createUpdateSystems() { } } - public void startGame(String shipName, boolean isNewGame, WorldConfig worldConfig, EntitySystemManager entitySystemManager) { + public void startGame(String shipName, boolean isNewGame, EntitySystemManager entitySystemManager) { this.entitySystemManager = entitySystemManager; respawnState = new RespawnState(); @@ -331,7 +333,7 @@ public void onGameEnd(Context context) { if (!hero.isTranscendent()) { saveShip(); } - SaveManager.saveWorld(getPlanetManager().getSystems().size()); + SaveManager.saveWorld(worldConfig); try { context.get(SerialisationManager.class).serialise(); @@ -603,6 +605,10 @@ public DrawableManager getDrawableManager() { return drawableManager; } + public WorldConfig getWorldConfig() { + return worldConfig; + } + public void setRespawnState() { respawnState.setRespawnMoney(.75f * hero.getMoney()); if (hero.isNonTranscendent()) { diff --git a/engine/src/main/java/org/destinationsol/game/StarPort.java b/engine/src/main/java/org/destinationsol/game/StarPort.java index f5017971e..021c05412 100644 --- a/engine/src/main/java/org/destinationsol/game/StarPort.java +++ b/engine/src/main/java/org/destinationsol/game/StarPort.java @@ -125,7 +125,7 @@ public void update(SolGame game) { ship.setMoney(ship.getMoney() - FARE); Transcendent transcendent = new Transcendent(ship, fromPlanet, toPlanet, game); if (transcendent.getShip().getPilot().isPlayer()) { - SaveManager.saveWorld(game.getPlanetManager().getSystems().size()); + SaveManager.saveWorld(game.getWorldConfig()); game.getHero().setTranscendent(transcendent); } ObjectManager objectManager = game.getObjectManager(); @@ -404,7 +404,7 @@ public void update(SolGame game) { SolShip ship = this.ship.toObject(game); if (ship.getPilot().isPlayer()) { game.getHero().setSolShip(ship, game); - SaveManager.saveWorld(game.getPlanetManager().getSystems().size()); + SaveManager.saveWorld(game.getWorldConfig()); } objectManager.addObjDelayed(ship); blip(game, ship); diff --git a/engine/src/main/java/org/destinationsol/game/WorldConfig.java b/engine/src/main/java/org/destinationsol/game/WorldConfig.java index 5a7f2cf39..fcb636b44 100644 --- a/engine/src/main/java/org/destinationsol/game/WorldConfig.java +++ b/engine/src/main/java/org/destinationsol/game/WorldConfig.java @@ -17,18 +17,29 @@ import org.destinationsol.game.planet.SystemsBuilder; +import java.util.ArrayList; +import java.util.List; + public class WorldConfig { protected long seed; protected int numberOfSystems; + private List solarSystemGenerators; + private List featureGenerators; public WorldConfig() { seed = System.currentTimeMillis(); numberOfSystems = SystemsBuilder.DEFAULT_SYSTEM_COUNT; + solarSystemGenerators = new ArrayList<>(); + featureGenerators = new ArrayList<>(); } - public WorldConfig(long seed, int numberOfSystems) { + public WorldConfig(long seed, int numberOfSystems, + List solarSystemGenerators, + List featureGenerators) { this.seed = seed; this.numberOfSystems = numberOfSystems; + this.solarSystemGenerators = solarSystemGenerators; + this.featureGenerators = featureGenerators; } public long getSeed() { @@ -46,4 +57,20 @@ public int getNumberOfSystems() { public void setNumberOfSystems(int numberOfSystems) { this.numberOfSystems = numberOfSystems; } + + public List getSolarSystemGenerators() { + return solarSystemGenerators; + } + + public void setFeatureGenerators(List featureGenerators) { + this.featureGenerators = featureGenerators; + } + + public List getFeatureGenerators() { + return featureGenerators; + } + + public void setSolarSystemGenerators(List solarSystemGenerators) { + this.solarSystemGenerators = solarSystemGenerators; + } } diff --git a/engine/src/main/java/org/destinationsol/world/GalaxyBuilder.java b/engine/src/main/java/org/destinationsol/world/GalaxyBuilder.java index 25af35178..b004d526c 100644 --- a/engine/src/main/java/org/destinationsol/world/GalaxyBuilder.java +++ b/engine/src/main/java/org/destinationsol/world/GalaxyBuilder.java @@ -52,8 +52,8 @@ public class GalaxyBuilder { private ArrayList builtSolarSystems = new ArrayList<>(); private ModuleManager moduleManager; private SolarSystemConfigManager solarSystemConfigManager; - private final int numberOfSystems; private BeanContext beanContext; + private WorldConfig worldConfig; @Inject public GalaxyBuilder(WorldConfig worldConfig, ModuleManager moduleManager, SolarSystemConfigManager solarSystemConfigManager, BeanContext beanContext) { @@ -61,10 +61,41 @@ public GalaxyBuilder(WorldConfig worldConfig, ModuleManager moduleManager, Solar this.solarSystemConfigManager = solarSystemConfigManager; this.beanContext = beanContext; solarSystemConfigManager.loadDefaultSolarSystemConfigs(); - numberOfSystems = worldConfig.getNumberOfSystems(); + this.worldConfig = worldConfig; + + if (worldConfig.getSolarSystemGenerators().isEmpty()) { + populateSolarSystemGeneratorList(); + } else { + for (String typeName : worldConfig.getSolarSystemGenerators()) { + Iterable> generatorTypes = + moduleManager.getEnvironment().getSubtypesOf(SolarSystemGenerator.class, type -> type.getName().equals(typeName)); + if (!generatorTypes.iterator().hasNext()) { + logger.error("Unable to find SolarSystemGenerator type {}! World generation will likely be incorrect.", typeName); + continue; + } + + for (Class generatorType : generatorTypes) { + solarSystemGeneratorTypes.add(generatorType); + } + } + } + + if (worldConfig.getFeatureGenerators().isEmpty()) { + populateFeatureGeneratorList(); + } else { + for (String typeName : worldConfig.getFeatureGenerators()) { + Iterable> generatorTypes = + moduleManager.getEnvironment().getSubtypesOf(FeatureGenerator.class, type -> type.getName().equals(typeName)); + if (!generatorTypes.iterator().hasNext()) { + logger.error("Unable to find FeatureGenerator type {}! World generation will likely be incorrect.", typeName); + continue; + } - populateSolarSystemGeneratorList(); - populateFeatureGeneratorList(); + for (Class generatorType : generatorTypes) { + featureGeneratorTypes.add(generatorType); + } + } + } } /** @@ -72,8 +103,12 @@ public GalaxyBuilder(WorldConfig worldConfig, ModuleManager moduleManager, Solar * of SolarSystemGenerators. */ private void populateSolarSystemGeneratorList() { - //It is necessary to use an iterator as getSubtypesOf() returns an Iterable - moduleManager.getEnvironment().getSubtypesOf(SolarSystemGenerator.class).iterator().forEachRemaining(solarSystemGeneratorTypes::add); + List systemGeneratorTypeNames = new ArrayList<>(); + for (Class systemGeneratorType : moduleManager.getEnvironment().getSubtypesOf(SolarSystemGenerator.class)) { + solarSystemGeneratorTypes.add(systemGeneratorType); + systemGeneratorTypeNames.add(systemGeneratorType.getName()); + } + worldConfig.setSolarSystemGenerators(systemGeneratorTypeNames); } /** @@ -81,12 +116,14 @@ private void populateSolarSystemGeneratorList() { * of FeatureGenerators. */ private void populateFeatureGeneratorList() { - + List featureGeneratorTypeNames = new ArrayList<>(); for (Class generator : moduleManager.getEnvironment().getSubtypesOf(FeatureGenerator.class)) { if (!Modifier.isAbstract(generator.getModifiers())) { featureGeneratorTypes.add(generator); + featureGeneratorTypeNames.add(generator.getName()); } } + worldConfig.setFeatureGenerators(featureGeneratorTypeNames); } /** @@ -112,7 +149,7 @@ public void buildWithRandomSolarSystemGenerators() { */ public ArrayList initializeRandomSolarSystemGenerators() { ArrayList generatorArrayList = new ArrayList<>(); - for (int i = 0; i < numberOfSystems; i++) { + for (int i = 0; i < worldConfig.getNumberOfSystems(); i++) { Class solarSystemGenerator = solarSystemGeneratorTypes.get(SolRandom.seededRandomInt(solarSystemGeneratorTypes.size())); try { SolarSystemGenerator generator = solarSystemGenerator.newInstance(); @@ -199,19 +236,19 @@ private void calculateRandomWorldPositionAtDistance(Vector2 result, float distan SolMath.fromAl(result, angle, distance); } - public ArrayList> getSolarSystemGeneratorTypes() { + public List> getSolarSystemGeneratorTypes() { return solarSystemGeneratorTypes; } - public ArrayList getActiveSolarSystemGenerators() { + public List getActiveSolarSystemGenerators() { return activeSolarSystemGenerators; } - public ArrayList> getFeatureGeneratorTypes() { + public List> getFeatureGeneratorTypes() { return featureGeneratorTypes; } - public ArrayList getBuiltSolarSystems() { + public List getBuiltSolarSystems() { return builtSolarSystems; } } diff --git a/engine/src/main/java/org/destinationsol/world/generators/SolarSystemGenerator.java b/engine/src/main/java/org/destinationsol/world/generators/SolarSystemGenerator.java index 2080c90f0..6951b5130 100644 --- a/engine/src/main/java/org/destinationsol/world/generators/SolarSystemGenerator.java +++ b/engine/src/main/java/org/destinationsol/world/generators/SolarSystemGenerator.java @@ -466,7 +466,7 @@ private boolean isOtherGeneratorType(int index) { && !PlanetGenerator.class.isAssignableFrom(featureGeneratorTypes.get(index)); } - public void setFeatureGeneratorTypes(ArrayList> generators) { + public void setFeatureGeneratorTypes(List> generators) { featureGeneratorTypes.addAll(generators); } diff --git a/engine/src/test/java/org/destinationsol/world/GalaxyBuilderTest.java b/engine/src/test/java/org/destinationsol/world/GalaxyBuilderTest.java index ba14e57c6..1cf89a702 100644 --- a/engine/src/test/java/org/destinationsol/world/GalaxyBuilderTest.java +++ b/engine/src/test/java/org/destinationsol/world/GalaxyBuilderTest.java @@ -22,8 +22,7 @@ import org.destinationsol.files.HullConfigManager; import org.destinationsol.game.AbilityCommonConfigs; import org.destinationsol.game.GameColors; -import org.destinationsol.game.context.Context; -import org.destinationsol.game.context.internal.ContextImpl; +import org.destinationsol.game.WorldConfig; import org.destinationsol.game.item.ItemManager; import org.destinationsol.game.maze.MazeConfigManager; import org.destinationsol.game.particle.EffectTypes; @@ -36,30 +35,37 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mockito; +import org.terasology.context.Lifetime; +import org.terasology.gestalt.di.BeanContext; +import org.terasology.gestalt.di.DefaultBeanContext; +import org.terasology.gestalt.di.ServiceRegistry; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; public class GalaxyBuilderTest implements AssetsHelperInitializer { - private Context context; private ModuleManager moduleManager; GalaxyBuilder galaxyBuilder; private GameColors gameColors; private EffectTypes effectTypes; private OggSoundManager soundManager; private AbilityCommonConfigs abilityCommonConfigs; + private ServiceRegistry registry; + private BeanContext context; @BeforeEach public void setUp() throws Exception { - context = new ContextImpl(); + registry = new ServiceRegistry(); moduleManager = getModuleManager(); - context.put(ModuleManager.class, moduleManager); + registry.with(ModuleManager.class).use(() -> moduleManager).lifetime(Lifetime.Singleton); setupMockGL(); setupConfigManagers(); + + context = new DefaultBeanContext(registry); + galaxyBuilder = new GalaxyBuilder(new WorldConfig(), moduleManager, context.getBean(SolarSystemConfigManager.class), context); } private void setupMockGL() { @@ -69,24 +75,25 @@ private void setupMockGL() { Box2D.init(); } + // TODO: This method is duplicated in most of the world generation tests. Maybe move it into an initialiser interface? private void setupConfigManagers() { ItemManager itemManager = setupItemManager(); HullConfigManager hullConfigManager = setupHullConfigManager(itemManager); PlanetConfigManager planetConfigManager = new PlanetConfigManager(hullConfigManager, gameColors,itemManager); planetConfigManager.loadDefaultPlanetConfigs(); - context.put(PlanetConfigManager.class, planetConfigManager); + registry.with(PlanetConfigManager.class).use(() -> planetConfigManager); MazeConfigManager mazeConfigManager = new MazeConfigManager(hullConfigManager, itemManager); mazeConfigManager.loadDefaultMazeConfigs(); - context.put(MazeConfigManager.class, mazeConfigManager); + registry.with(MazeConfigManager.class).use(() -> mazeConfigManager); BeltConfigManager beltConfigManager = new BeltConfigManager(hullConfigManager, itemManager); beltConfigManager.loadDefaultBeltConfigs(); - context.put(BeltConfigManager.class, beltConfigManager); + registry.with(BeltConfigManager.class).use(() -> beltConfigManager); SolarSystemConfigManager solarSystemConfigManager = new SolarSystemConfigManager(hullConfigManager, itemManager); - context.put(SolarSystemConfigManager.class, solarSystemConfigManager); + registry.with(SolarSystemConfigManager.class).use(() -> solarSystemConfigManager); } private ItemManager setupItemManager() { @@ -103,42 +110,25 @@ private HullConfigManager setupHullConfigManager(ItemManager itemManager) { @Test void populatesSolarSystemsList() { - int testNumberSystems = 2; -// galaxyBuilder = new GalaxyBuilder(context, testNumberSystems); -// galaxyBuilder.buildWithRandomSolarSystemGenerators(); -// assertTrue(galaxyBuilder.getSolarSystemGeneratorTypes().size() > 0); - + galaxyBuilder.buildWithRandomSolarSystemGenerators(); + assertTrue(galaxyBuilder.getSolarSystemGeneratorTypes().size() > 0); } @Test void populatesFeatureGeneratorsList() { - int testNumberSystems = 2; -// galaxyBuilder = new GalaxyBuilder(context, testNumberSystems); -// galaxyBuilder.buildWithRandomSolarSystemGenerators(); -// assertTrue(galaxyBuilder.getFeatureGeneratorTypes().size() > 0); + galaxyBuilder.buildWithRandomSolarSystemGenerators(); + assertTrue(galaxyBuilder.getFeatureGeneratorTypes().size() > 0); } @Test void createsCorrectNumberOfSolarSystemGenerators() { - int testNumberSystems = 2; -// galaxyBuilder = new GalaxyBuilder(context, testNumberSystems); -// galaxyBuilder.buildWithRandomSolarSystemGenerators(); -// assertEquals(galaxyBuilder.getActiveSolarSystemGenerators().size(), 2); + galaxyBuilder.buildWithRandomSolarSystemGenerators(); + assertEquals(galaxyBuilder.getActiveSolarSystemGenerators().size(), 2); } @Test void createsCorrectNumberOfSolarSystems() { - int testNumberSystems = 2; -// galaxyBuilder = new GalaxyBuilder(context, testNumberSystems); -// galaxyBuilder.buildWithRandomSolarSystemGenerators(); -// assertEquals(galaxyBuilder.getBuiltSolarSystems().size(), 2); - } - - @Test - void setsContext() { - int testNumberSystems = 2; -// galaxyBuilder = new GalaxyBuilder(context, testNumberSystems); -// assertNotNull(galaxyBuilder.getContext()); + galaxyBuilder.buildWithRandomSolarSystemGenerators(); + assertEquals(galaxyBuilder.getBuiltSolarSystems().size(), 2); } - } diff --git a/engine/src/test/java/org/destinationsol/world/generators/MazeGeneratorTest.java b/engine/src/test/java/org/destinationsol/world/generators/MazeGeneratorTest.java index 4379e57f6..541e7558d 100644 --- a/engine/src/test/java/org/destinationsol/world/generators/MazeGeneratorTest.java +++ b/engine/src/test/java/org/destinationsol/world/generators/MazeGeneratorTest.java @@ -67,8 +67,10 @@ public void setUp() throws Exception { setupConfigManagers(); + WorldConfig worldConfig = new WorldConfig(); + worldConfig.setNumberOfSystems(1); context = new DefaultBeanContext(registry); - galaxyBuilder = new GalaxyBuilder(new WorldConfig(), moduleManager, context.getBean(SolarSystemConfigManager.class), context); + galaxyBuilder = new GalaxyBuilder(worldConfig, moduleManager, context.getBean(SolarSystemConfigManager.class), context); ArrayList solarSystemGenerators = galaxyBuilder.initializeRandomSolarSystemGenerators(); solarSystemGenerator = solarSystemGenerators.get(0);