Repository: movingblocks/terasology
Issue: Module details when a module exists with unresolved dependencies causes crash

### What you were trying to do

View module details for GooeyDefence to figure out its dependencies and what might be missing

### What actually happened

Game crashed when I clicked "FlexiblePathfinding" (the missing dependency)

### How to reproduce

* Grab Omega zip 977 or comparable source dir. Or just remove any dependency
* Run the game and go to module details under advanced game setup
* Click a button representing a module that isn't present

### Log details and game version

Omega 977

```
12:23:21.566 [main] WARN  o.t.engine.internal.TimeBase - Delta too great (10474), capping to 1000
12:23:21.572 [main] INFO  o.t.logic.console.ConsoleImpl - [NOTIFICATION] Identity storage service: No configuration data is present, staying logged out.
12:24:08.604 [main] ERROR o.terasology.engine.TerasologyEngine - Uncaught exception, attempting clean game shutdown
java.lang.NullPointerException: null
	at org.terasology.rendering.nui.layers.mainMenu.moduleDetailsScreen.ModuleDetailsScreen$6.get(ModuleDetailsScreen.java:229)
	at org.terasology.rendering.nui.layers.mainMenu.moduleDetailsScreen.ModuleDetailsScreen$6.get(ModuleDetailsScreen.java:225)
	at org.terasology.rendering.nui.widgets.UILabel.getText(UILabel.java:68)
	at org.terasology.rendering.nui.widgets.UILabel.getPreferredContentSize(UILabel.java:101)
	at org.terasology.rendering.nui.internal.CanvasImpl.calculateRestrictedSize(CanvasImpl.java:347)
	at org.terasology.rendering.nui.layouts.ColumnLayout.calculateRowSize(ColumnLayout.java:212)
	at org.terasology.rendering.nui.layouts.ColumnLayout.lambda$onDraw$0(ColumnLayout.java:133)
	at java.util.stream.ReferencePipeline$3$1.accept(Unknown Source)
	at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(Unknown Source)
	at java.util.stream.AbstractPipeline.copyInto(Unknown Source)
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source)
	at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(Unknown Source)
	at java.util.stream.AbstractPipeline.evaluate(Unknown Source)
	at java.util.stream.ReferencePipeline.collect(Unknown Source)
	at org.terasology.rendering.nui.layouts.ColumnLayout.onDraw(ColumnLayout.java:133)
	at org.terasology.rendering.nui.internal.CanvasImpl.drawStyledWidget(CanvasImpl.java:406)
	at org.terasology.rendering.nui.internal.CanvasImpl.drawWidget(CanvasImpl.java:392)
	at org.terasology.rendering.nui.layouts.relative.RelativeLayout.onDraw(RelativeLayout.java:85)
	at org.terasology.rendering.nui.internal.CanvasImpl.drawStyledWidget(CanvasImpl.java:406)
	at org.terasology.rendering.nui.internal.CanvasImpl.drawWidget(CanvasImpl.java:392)
	at org.terasology.rendering.nui.layouts.ColumnLayout.onDraw(ColumnLayout.java:191)
	at org.terasology.rendering.nui.internal.CanvasImpl.drawStyledWidget(CanvasImpl.java:406)
	at org.terasology.rendering.nui.internal.CanvasImpl.drawWidget(CanvasImpl.java:392)
	at org.terasology.rendering.nui.layouts.relative.RelativeLayout.onDraw(RelativeLayout.java:85)
	at org.terasology.rendering.nui.internal.CanvasImpl.drawStyledWidget(CanvasImpl.java:406)
	at org.terasology.rendering.nui.internal.CanvasImpl.drawWidget(CanvasImpl.java:392)
	at org.terasology.rendering.nui.layouts.relative.RelativeLayout.onDraw(RelativeLayout.java:85)
	at org.terasology.rendering.nui.internal.CanvasImpl.drawStyledWidget(CanvasImpl.java:406)
	at org.terasology.rendering.nui.internal.CanvasImpl.drawWidget(CanvasImpl.java:392)
	at org.terasology.rendering.nui.layouts.ColumnLayout.onDraw(ColumnLayout.java:191)
	at org.terasology.rendering.nui.internal.CanvasImpl.drawStyledWidget(CanvasImpl.java:406)
	at org.terasology.rendering.nui.internal.CanvasImpl.drawWidget(CanvasImpl.java:392)
	at org.terasology.rendering.nui.layouts.relative.RelativeLayout.onDraw(RelativeLayout.java:85)
	at org.terasology.rendering.nui.internal.CanvasImpl.drawStyledWidget(CanvasImpl.java:406)
	at org.terasology.rendering.nui.internal.CanvasImpl.drawWidget(CanvasImpl.java:392)
	at org.terasology.rendering.nui.layouts.relative.RelativeLayout.onDraw(RelativeLayout.java:85)
	at org.terasology.rendering.nui.internal.CanvasImpl.drawStyledWidget(CanvasImpl.java:406)
	at org.terasology.rendering.nui.internal.CanvasImpl.drawWidget(CanvasImpl.java:392)
	at org.terasology.rendering.nui.CoreScreenLayer.onDraw(CoreScreenLayer.java:115)
	at org.terasology.rendering.nui.internal.CanvasImpl.drawStyledWidget(CanvasImpl.java:406)
	at org.terasology.rendering.nui.internal.CanvasImpl.drawWidget(CanvasImpl.java:392)
	at org.terasology.rendering.nui.internal.NUIManagerInternal.render(NUIManagerInternal.java:475)
	at org.terasology.engine.modes.StateMainMenu.render(StateMainMenu.java:210)
	at org.terasology.engine.subsystem.lwjgl.LwjglGraphics.postUpdate(LwjglGraphics.java:166)
	at org.terasology.engine.TerasologyEngine.tick(TerasologyEngine.java:467)
	at org.terasology.engine.TerasologyEngine.mainLoop(TerasologyEngine.java:421)
	at org.terasology.engine.TerasologyEngine.run(TerasologyEngine.java:397)
	at org.terasology.engine.Terasology.main(Terasology.java:154)
12:24:08.610 [main] INFO  o.terasology.engine.TerasologyEngine - Shutting down Terasology...
12:24:08.972 [main] WARN  o.t.w.g.i.WorldGeneratorManager - Could not resolve dependencies for module: GooeyDefence-0.1.0-SNAPSHOT
```

Maybe of interest to @ar0ne. Probably not a very difficult bug.

Changed files:
engine/src/main/java/org/terasology/rendering/nui/layers/mainMenu/moduleDetailsScreen/ModuleDetailsScreen.java

diff --git a/engine/src/main/java/org/terasology/rendering/nui/layers/mainMenu/moduleDetailsScreen/ModuleDetailsScreen.java b/engine/src/main/java/org/terasology/rendering/nui/layers/mainMenu/moduleDetailsScreen/ModuleDetailsScreen.java
index 95a637ce6..8b4818f9c 100644
--- a/engine/src/main/java/org/terasology/rendering/nui/layers/mainMenu/moduleDetailsScreen/ModuleDetailsScreen.java
+++ b/engine/src/main/java/org/terasology/rendering/nui/layers/mainMenu/moduleDetailsScreen/ModuleDetailsScreen.java
@@ -228,7 +228,7 @@ public String get() {
         installedVersion.bindText(new ReadOnlyBinding<String>() {
             @Override
             public String get() {
-                if (dependencyInfoBinding.get() != null) {
+                if (dependencyInfoBinding.get() != null && moduleManager.getRegistry().getLatestModuleVersion(dependencyInfoBinding.get().getId()) != null) {
                     return String.valueOf(moduleManager.getRegistry().getLatestModuleVersion(dependencyInfoBinding.get().getId()).getVersion());
                 }
                 return "";
@@ -288,6 +288,11 @@ private String getString(DependencyInfo value) {
 
             @Override
             public void draw(DependencyInfo value, Canvas canvas) {
+                if (moduleManager.getRegistry().getLatestModuleVersion(value.getId()) == null) {
+                    canvas.setMode("invalid");
+                } else {
+                    canvas.setMode("available");
+                }
                 canvas.drawText(getString(value), canvas.getRegion());
             }
 
@@ -316,7 +321,7 @@ private void setUpUpdateModuleButton() {
             public Boolean get() {
                 final String online = onlineVersion.getText();
                 final String installed = installedVersion.getText();
-                if (StringUtils.isNotBlank(online)) {
+                if (StringUtils.isNotBlank(online) && StringUtils.isNotBlank(installed)) {
                     return new Version(online).compareTo(new Version(installed)) > 0;
                 }
                 return false;