99import org .slf4j .Logger ;
1010import org .slf4j .LoggerFactory ;
1111import org .terasology .engine .config .Config ;
12- import org .terasology .engine .config .SystemConfig ;
1312import org .terasology .engine .context .Context ;
1413import org .terasology .engine .core .GameEngine ;
1514import org .terasology .engine .core .PathManager ;
1615import org .terasology .engine .core .PathManagerProvider ;
17- import org .terasology .engine .core .TerasologyConstants ;
1816import org .terasology .engine .core .TerasologyEngine ;
1917import org .terasology .engine .core .TerasologyEngineBuilder ;
2018import org .terasology .engine .core .modes .GameState ;
4038import org .terasology .engine .network .NetworkSystem ;
4139import org .terasology .engine .registry .CoreRegistry ;
4240import org .terasology .engine .rendering .opengl .ScreenGrabber ;
43- import org .terasology .engine .rendering .world .viewDistance .ViewDistance ;
44- import org .terasology .engine .testUtil .WithUnittestModule ;
45- import org .terasology .gestalt .module .Module ;
46- import org .terasology .gestalt .module .ModuleMetadataJsonAdapter ;
47- import org .terasology .gestalt .module .ModuleRegistry ;
4841
4942import java .io .IOException ;
5043import java .io .UncheckedIOException ;
5144import java .nio .file .Files ;
5245import java .nio .file .Path ;
46+ import java .util .ArrayList ;
5347import java .util .Collections ;
5448import java .util .List ;
5549import java .util .Set ;
5650
51+ import static org .junit .platform .commons .support .ReflectionSupport .newInstance ;
52+
5753/**
5854 * Manages game engines for tests.
5955 * <p>
@@ -78,15 +74,18 @@ public class Engines {
7874 protected boolean doneLoading ;
7975 protected Context hostContext ;
8076 protected final List <TerasologyEngine > engines = Lists .newArrayList ();
77+ protected final List <Class <? extends EngineSubsystem >> subsystems = Lists .newArrayList ();
8178
8279 PathManager pathManager ;
8380 PathManagerProvider .Cleaner pathManagerCleaner ;
8481 TerasologyEngine host ;
8582 private final NetworkMode networkMode ;
8683
87- public Engines (List <String > dependencies , String worldGeneratorUri , NetworkMode networkMode ) {
84+ public Engines (List <String > dependencies , String worldGeneratorUri , NetworkMode networkMode ,
85+ List <Class <? extends EngineSubsystem >> subsystems ) {
8886 this .networkMode = networkMode ;
8987 this .dependencies .addAll (dependencies );
88+ this .subsystems .addAll (subsystems );
9089
9190 if (worldGeneratorUri != null ) {
9291 this .worldGeneratorUri = worldGeneratorUri ;
@@ -142,7 +141,6 @@ public void tearDown() {
142141 */
143142 public Context createClient (MainLoop mainLoop ) throws IOException {
144143 TerasologyEngine client = createHeadlessEngine ();
145- client .getFromEngineContext (Config .class ).getRendering ().setViewDistance (ViewDistance .LEGALLY_BLIND );
146144
147145 client .changeState (new StateMainMenu ());
148146 if (!connectToHost (client , mainLoop )) {
@@ -182,11 +180,12 @@ public Context getHostContext() {
182180 TerasologyEngine createHeadlessEngine () throws IOException {
183181 TerasologyEngineBuilder terasologyEngineBuilder = new TerasologyEngineBuilder ();
184182 terasologyEngineBuilder
185- .add (new WithUnittestModule ())
183+ .add (new IntegrationEnvironmentSubsystem ())
186184 .add (new HeadlessGraphics ())
187185 .add (new HeadlessTimer ())
188186 .add (new HeadlessAudio ())
189187 .add (new HeadlessInput ());
188+ createExtraSubsystems ().forEach (terasologyEngineBuilder ::add );
190189
191190 return createEngine (terasologyEngineBuilder );
192191 }
@@ -195,16 +194,31 @@ TerasologyEngine createHeadlessEngine() throws IOException {
195194 TerasologyEngine createHeadedEngine () throws IOException {
196195 EngineSubsystem audio = new LwjglAudio ();
197196 TerasologyEngineBuilder terasologyEngineBuilder = new TerasologyEngineBuilder ()
198- .add (new WithUnittestModule ())
197+ .add (new IntegrationEnvironmentSubsystem ())
199198 .add (audio )
200199 .add (new LwjglGraphics ())
201200 .add (new LwjglTimer ())
202201 .add (new LwjglInput ())
203202 .add (new OpenVRInput ());
203+ createExtraSubsystems ().forEach (terasologyEngineBuilder ::add );
204204
205205 return createEngine (terasologyEngineBuilder );
206206 }
207207
208+ List <EngineSubsystem > createExtraSubsystems () {
209+ List <EngineSubsystem > instances = new ArrayList <>();
210+ for (Class <? extends EngineSubsystem > clazz : subsystems ) {
211+ try {
212+ EngineSubsystem subsystem = newInstance (clazz );
213+ instances .add (subsystem );
214+ logger .debug ("Created new {}" , subsystem );
215+ } catch (RuntimeException e ) {
216+ throw new RuntimeException ("Failed creating new " + clazz .getName (), e );
217+ }
218+ }
219+ return instances ;
220+ }
221+
208222 TerasologyEngine createEngine (TerasologyEngineBuilder terasologyEngineBuilder ) throws IOException {
209223 System .setProperty (ModuleManager .LOAD_CLASSPATH_MODULES_PROPERTY , "true" );
210224
@@ -220,43 +234,11 @@ TerasologyEngine createEngine(TerasologyEngineBuilder terasologyEngineBuilder) t
220234
221235 TerasologyEngine terasologyEngine = terasologyEngineBuilder .build ();
222236 terasologyEngine .initialize ();
223- registerCurrentDirectoryIfModule (terasologyEngine );
224237
225238 engines .add (terasologyEngine );
226239 return terasologyEngine ;
227240 }
228241
229- /**
230- * In standalone module environments (i.e. Jenkins CI builds) the CWD is the module under test. When it uses MTE it very likely needs to
231- * load itself as a module, but it won't be loadable from the typical path such as ./modules. This means that modules using MTE would
232- * always fail CI tests due to failing to load themselves.
233- * <p>
234- * For these cases we try to load the CWD (via the installPath) as a module and put it in the global module registry.
235- * <p>
236- * This process is based on how ModuleManagerImpl uses ModulePathScanner to scan for available modules.
237- */
238- protected void registerCurrentDirectoryIfModule (TerasologyEngine terasologyEngine ) {
239- Path installPath = PathManager .getInstance ().getInstallPath ();
240- ModuleManager moduleManager = terasologyEngine .getFromEngineContext (ModuleManager .class );
241- ModuleRegistry registry = moduleManager .getRegistry ();
242- ModuleMetadataJsonAdapter metadataReader = moduleManager .getModuleMetadataReader ();
243- moduleManager .getModuleFactory ().getModuleMetadataLoaderMap ()
244- .put (TerasologyConstants .MODULE_INFO_FILENAME .toString (), metadataReader );
245-
246-
247- try {
248- Module module = moduleManager .getModuleFactory ().createModule (installPath .toFile ());
249- if (module != null ) {
250- registry .add (module );
251- logger .info ("Added install path as module: {}" , installPath );
252- } else {
253- logger .info ("Install path does not appear to be a module: {}" , installPath );
254- }
255- } catch (IOException e ) {
256- logger .warn ("Could not read install path as module at " + installPath );
257- }
258- }
259-
260242 protected void mockPathManager () {
261243 PathManager originalPathManager = PathManager .getInstance ();
262244 pathManager = Mockito .spy (originalPathManager );
@@ -265,11 +247,10 @@ protected void mockPathManager() {
265247 PathManagerProvider .setPathManager (pathManager );
266248 }
267249
268- TerasologyEngine createHost (NetworkMode networkMode ) throws IOException {
250+ TerasologyEngine createHost (NetworkMode hostNetworkMode ) throws IOException {
269251 TerasologyEngine host = createHeadlessEngine ();
270- host .getFromEngineContext (SystemConfig .class ).writeSaveGamesEnabled .set (false );
271252 host .subscribeToStateChange (new HeadlessStateChangeListener (host ));
272- host .changeState (new TestingStateHeadlessSetup (dependencies , worldGeneratorUri , networkMode ));
253+ host .changeState (new TestingStateHeadlessSetup (dependencies , worldGeneratorUri , hostNetworkMode ));
273254
274255 doneLoading = false ;
275256 host .subscribeToStateChange (() -> {
0 commit comments