diff --git a/src/main/java/org/terasology/moduletestingenvironment/ModuleTestingEnvironment.java b/src/main/java/org/terasology/moduletestingenvironment/ModuleTestingEnvironment.java index 964cfaa..145ac98 100644 --- a/src/main/java/org/terasology/moduletestingenvironment/ModuleTestingEnvironment.java +++ b/src/main/java/org/terasology/moduletestingenvironment/ModuleTestingEnvironment.java @@ -21,6 +21,7 @@ import org.terasology.engine.core.TerasologyEngine; import org.terasology.engine.core.TerasologyEngineBuilder; import org.terasology.engine.core.Time; +import org.terasology.engine.core.modes.GameState; import org.terasology.engine.core.modes.StateIngame; import org.terasology.engine.core.modes.StateLoading; import org.terasology.engine.core.modes.StateMainMenu; @@ -39,10 +40,6 @@ import org.terasology.engine.core.subsystem.openvr.OpenVRInput; import org.terasology.engine.entitySystem.entity.EntityManager; import org.terasology.engine.logic.location.LocationComponent; -import org.terasology.module.Module; -import org.terasology.module.ModuleLoader; -import org.terasology.module.ModuleMetadataJsonAdapter; -import org.terasology.module.ModuleRegistry; import org.terasology.engine.network.JoinStatus; import org.terasology.engine.network.NetworkSystem; import org.terasology.engine.registry.CoreRegistry; @@ -50,6 +47,10 @@ import org.terasology.engine.rendering.world.viewDistance.ViewDistance; import org.terasology.engine.world.RelevanceRegionComponent; import org.terasology.engine.world.WorldProvider; +import org.terasology.module.Module; +import org.terasology.module.ModuleLoader; +import org.terasology.module.ModuleMetadataJsonAdapter; +import org.terasology.module.ModuleRegistry; import java.io.IOException; import java.nio.file.Files; @@ -313,7 +314,7 @@ public boolean runWhile(long gameTimeTimeoutMs, Supplier f) { * * @return the created client's context object */ - public Context createClient() { + public Context createClient() throws IOException { TerasologyEngine terasologyEngine = createHeadlessEngine(); terasologyEngine.getFromEngineContext(Config.class).getRendering().setViewDistance(ViewDistance.LEGALLY_BLIND); @@ -371,7 +372,7 @@ public void setSafetyTimeoutMs(long safetyTimeoutMs) { this.safetyTimeoutMs = safetyTimeoutMs; } - private TerasologyEngine createHeadlessEngine() { + private TerasologyEngine createHeadlessEngine() throws IOException { TerasologyEngineBuilder terasologyEngineBuilder = new TerasologyEngineBuilder(); terasologyEngineBuilder .add(new HeadlessGraphics()) @@ -382,7 +383,7 @@ private TerasologyEngine createHeadlessEngine() { return createEngine(terasologyEngineBuilder); } - private TerasologyEngine createHeadedEngine() { + private TerasologyEngine createHeadedEngine() throws IOException { EngineSubsystem audio = new LwjglAudio(); TerasologyEngineBuilder terasologyEngineBuilder = new TerasologyEngineBuilder() .add(audio) @@ -394,19 +395,15 @@ private TerasologyEngine createHeadedEngine() { return createEngine(terasologyEngineBuilder); } - private TerasologyEngine createEngine(TerasologyEngineBuilder terasologyEngineBuilder) { + private TerasologyEngine createEngine(TerasologyEngineBuilder terasologyEngineBuilder) throws IOException { // create temporary home paths so the MTE engines don't overwrite config/save files in your real home path - try { - Path path = Files.createTempDirectory("terasology-mte-engine"); - PathManager.getInstance().useOverrideHomePath(path); - logger.info("Created temporary engine home path"); - - // JVM will delete these on normal termination but not exceptions. - path.toFile().deleteOnExit(); - } catch (Exception e) { - logger.warn("Exception creating temporary home path for engine: ", e); - return null; - } + Path path = Files.createTempDirectory("terasology-mte-engine"); + PathManager pathManager = PathManager.getInstance(); + pathManager.useOverrideHomePath(path); + logger.info("Created temporary engine home path: {}", path); + + // JVM will delete these on normal termination but not exceptions. + path.toFile().deleteOnExit(); TerasologyEngine terasologyEngine = terasologyEngineBuilder.build(); terasologyEngine.initialize(); @@ -449,7 +446,7 @@ private void registerCurrentDirectoryIfModule(TerasologyEngine terasologyEngine) } } - private TerasologyEngine createHost() { + private TerasologyEngine createHost() throws IOException { TerasologyEngine terasologyEngine = createHeadlessEngine(); terasologyEngine.getFromEngineContext(SystemConfig.class).writeSaveGamesEnabled.set(false); terasologyEngine.subscribeToStateChange(new HeadlessStateChangeListener(terasologyEngine)); @@ -457,15 +454,29 @@ private TerasologyEngine createHost() { doneLoading = false; terasologyEngine.subscribeToStateChange(() -> { - if (terasologyEngine.getState() instanceof org.terasology.engine.core.modes.StateIngame) { - hostContext = terasologyEngine.getState().getContext(); + GameState newState = terasologyEngine.getState(); + logger.debug("New engine state is {}", terasologyEngine.getState()); + if (newState instanceof org.terasology.engine.core.modes.StateIngame) { + hostContext = newState.getContext(); + if (hostContext == null) { + logger.warn("hostContext is NULL in engine state {}", newState); + } doneLoading = true; - } else if (terasologyEngine.getState() instanceof org.terasology.engine.core.modes.StateLoading) { + } else if (newState instanceof org.terasology.engine.core.modes.StateLoading) { org.terasology.engine.registry.CoreRegistry.put(GameEngine.class, terasologyEngine); } }); - while (!doneLoading && terasologyEngine.tick()) { /* do nothing */ } + boolean keepTicking; + while (!doneLoading) { + keepTicking = terasologyEngine.tick(); + if (!keepTicking) { + throw new RuntimeException(String.format( + "Engine stopped ticking before we got in game. Current state: %s", + terasologyEngine.getState() + )); + } + } return terasologyEngine; } diff --git a/src/main/java/org/terasology/moduletestingenvironment/TestingStateHeadlessSetup.java b/src/main/java/org/terasology/moduletestingenvironment/TestingStateHeadlessSetup.java index 947c968..add5e7b 100644 --- a/src/main/java/org/terasology/moduletestingenvironment/TestingStateHeadlessSetup.java +++ b/src/main/java/org/terasology/moduletestingenvironment/TestingStateHeadlessSetup.java @@ -9,13 +9,13 @@ import org.terasology.engine.core.module.ModuleManager; import org.terasology.engine.core.subsystem.headless.mode.StateHeadlessSetup; import org.terasology.engine.game.GameManifest; +import org.terasology.engine.registry.CoreRegistry; +import org.terasology.engine.world.internal.WorldInfo; +import org.terasology.engine.world.time.WorldTime; import org.terasology.module.DependencyResolver; import org.terasology.module.Module; import org.terasology.module.ResolutionResult; import org.terasology.naming.Name; -import org.terasology.engine.registry.CoreRegistry; -import org.terasology.engine.world.internal.WorldInfo; -import org.terasology.engine.world.time.WorldTime; import java.util.Collection; import java.util.Set; @@ -41,6 +41,9 @@ public GameManifest createGameManifest() { Set dependencyNames = dependencies.stream().map(Name::new).collect(Collectors.toSet()); logger.info("Building manifest for module dependencies: {}", dependencyNames); + // Include the MTE module to provide world generators and suchlike. + dependencyNames.add(new Name("ModuleTestingEnvironment")); + ResolutionResult result = resolver.resolve(dependencyNames); if (!result.isSuccess()) { logger.error("Unable to resolve modules: {}", dependencyNames); diff --git a/src/test/java/org/terasology/moduletestingenvironment/ClientConnectionTest.java b/src/test/java/org/terasology/moduletestingenvironment/ClientConnectionTest.java index 5220834..980a8de 100644 --- a/src/test/java/org/terasology/moduletestingenvironment/ClientConnectionTest.java +++ b/src/test/java/org/terasology/moduletestingenvironment/ClientConnectionTest.java @@ -1,18 +1,5 @@ -/* - * Copyright 2020 MovingBlocks - * - * 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. - */ +// Copyright 2021 The Terasology Foundation +// SPDX-License-Identifier: Apache-2.0 package org.terasology.moduletestingenvironment; import org.junit.jupiter.api.Assertions; @@ -23,6 +10,7 @@ import org.terasology.engine.core.modes.StateIngame; import org.terasology.moduletestingenvironment.extension.Dependencies; +import java.io.IOException; import java.util.List; @ExtendWith(MTEExtension.class) @@ -30,7 +18,7 @@ public class ClientConnectionTest { @Test - public void testClientConnection(ModuleTestingHelper helper) { + public void testClientConnection(ModuleTestingHelper helper) throws IOException { Context clientContext = helper.createClient(); List engines = helper.getEngines(); Assertions.assertEquals(2, engines.size()); diff --git a/src/test/java/org/terasology/moduletestingenvironment/DeprecationTest.java b/src/test/java/org/terasology/moduletestingenvironment/DeprecationTest.java index 430c1a1..7efe285 100644 --- a/src/test/java/org/terasology/moduletestingenvironment/DeprecationTest.java +++ b/src/test/java/org/terasology/moduletestingenvironment/DeprecationTest.java @@ -1,18 +1,5 @@ -/* - * Copyright 2020 MovingBlocks - * - * 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. - */ +// Copyright 2021 The Terasology Foundation +// SPDX-License-Identifier: Apache-2.0 package org.terasology.moduletestingenvironment; import com.google.common.collect.Lists; @@ -31,6 +18,8 @@ import org.terasology.engine.world.WorldProvider; import org.terasology.engine.world.block.BlockManager; +import java.io.IOException; + /** * The ExampleTest but using the old (deprecated) API @@ -49,7 +38,7 @@ public class DeprecationTest { private ModuleTestingEnvironment helper; @Test - public void testExample() { + public void testExample() throws IOException { // create some clients (the library connects them automatically) Context clientContext1 = helper.createClient(); Context clientContext2 = helper.createClient(); diff --git a/src/test/java/org/terasology/moduletestingenvironment/ExampleTest.java b/src/test/java/org/terasology/moduletestingenvironment/ExampleTest.java index 2ac5086..b0ac74e 100644 --- a/src/test/java/org/terasology/moduletestingenvironment/ExampleTest.java +++ b/src/test/java/org/terasology/moduletestingenvironment/ExampleTest.java @@ -1,4 +1,4 @@ -// Copyright 2020 The Terasology Foundation +// Copyright 2021 The Terasology Foundation // SPDX-License-Identifier: Apache-2.0 package org.terasology.moduletestingenvironment; @@ -18,6 +18,8 @@ import org.terasology.engine.world.WorldProvider; import org.terasology.engine.world.block.BlockManager; +import java.io.IOException; + @ExtendWith(MTEExtension.class) @Dependencies({"engine", "ModuleTestingEnvironment"}) @@ -35,7 +37,7 @@ public class ExampleTest { private ModuleTestingHelper helper; @Test - public void testClientConnection() { + public void testClientConnection() throws IOException { int currentClients = Lists.newArrayList(entityManager.getEntitiesWith(ClientComponent.class)).size(); // create some clients (the library connects them automatically) @@ -61,7 +63,7 @@ public void testRunWhileTimeout() { } @Test - public void testSendEvent() { + public void testSendEvent() throws IOException { Context clientContext = helper.createClient(); // send an event to a client's local player just for fun diff --git a/src/test/java/org/terasology/moduletestingenvironment/delay/DelayManagerTest.java b/src/test/java/org/terasology/moduletestingenvironment/delay/DelayManagerTest.java index bcd00aa..39dd17d 100644 --- a/src/test/java/org/terasology/moduletestingenvironment/delay/DelayManagerTest.java +++ b/src/test/java/org/terasology/moduletestingenvironment/delay/DelayManagerTest.java @@ -1,4 +1,4 @@ -// Copyright 2020 The Terasology Foundation +// Copyright 2021 The Terasology Foundation // SPDX-License-Identifier: Apache-2.0 package org.terasology.moduletestingenvironment.delay; @@ -21,6 +21,8 @@ import org.terasology.engine.network.ClientComponent; import org.terasology.engine.registry.In; +import java.io.IOException; + @ExtendWith(MTEExtension.class) @Dependencies({"engine", "ModuleTestingEnvironment"}) public class DelayManagerTest { @@ -36,7 +38,7 @@ public class DelayManagerTest { Time time; @Test - public void delayedActionIsTriggeredTest(ModuleTestingHelper helper) { + public void delayedActionIsTriggeredTest(ModuleTestingHelper helper) throws IOException { helper.createClient(); helper.runWhile(() -> Lists.newArrayList(entityManager.getEntitiesWith(ClientComponent.class)).isEmpty());