Skip to content

Commit 050fd8d

Browse files
authored
fix: resolve issue when loading a world a second time (#4829)
This contains two major changes: - wipe all the prefabs and let the engine re-resolve them when the world loads, and - unload any assets that are not loaded in by core As gestalt loads a whole new environment for every game, any assets from a previous session are not compatible for another session. List of changes: * fix: resolved loading issue when attempting to start a world twice * chore: add InitialiseRendering * chore: add rendering to client and only how with a local client * chore: remove caching from DefaultColorSource
1 parent b3a959f commit 050fd8d

File tree

8 files changed

+77
-86
lines changed

8 files changed

+77
-86
lines changed

engine/src/main/java/org/terasology/engine/core/TerasologyEngine.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
import org.terasology.engine.core.subsystem.common.ThreadManagerSubsystem;
3030
import org.terasology.engine.core.subsystem.common.TimeSubsystem;
3131
import org.terasology.engine.core.subsystem.common.WorldGenerationSubsystem;
32-
import org.terasology.engine.core.subsystem.rendering.ModuleRenderingSubsystem;
3332
import org.terasology.engine.entitySystem.prefab.Prefab;
3433
import org.terasology.engine.entitySystem.prefab.internal.PojoPrefab;
3534
import org.terasology.engine.i18n.I18nSubsystem;
@@ -175,7 +174,6 @@ public TerasologyEngine(TimeSubsystem timeSubsystem, Collection<EngineSubsystem>
175174
this.allSubsystems.add(new GameSubsystem());
176175
this.allSubsystems.add(new I18nSubsystem());
177176
this.allSubsystems.add(new TelemetrySubSystem());
178-
this.allSubsystems.add(new ModuleRenderingSubsystem());
179177

180178
// add all subsystem as engine module part. (needs for ECS classes loaded from external subsystems)
181179
allSubsystems.stream().map(Object::getClass).forEach(this::addToClassesOnClasspathsToAddToEngine);
@@ -489,7 +487,6 @@ public boolean tick() {
489487
}
490488

491489
Iterator<Float> updateCycles = timeSubsystem.getEngineTime().tick();
492-
CoreRegistry.setContext(currentState.getContext());
493490
rootContext.get(NetworkSystem.class).setContext(currentState.getContext());
494491

495492
for (EngineSubsystem subsystem : allSubsystems) {
@@ -586,6 +583,7 @@ private void switchState(GameState newState) {
586583
if (currentState != null) {
587584
currentState.dispose();
588585
}
586+
CoreRegistry.setContext(newState.getContext());
589587
currentState = newState;
590588
LoggingContext.setGameState(newState);
591589
newState.init(this);

engine/src/main/java/org/terasology/engine/core/bootstrap/EnvironmentSwitchHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,6 @@ public void handleSwitchToGameEnvironment(Context context) {
107107
autoConfigManager.loadConfigsIn(context);
108108

109109
ModuleAwareAssetTypeManager assetTypeManager = context.get(ModuleAwareAssetTypeManager.class);
110-
111110
/*
112111
* The registering of the prefab formats is done in this method, because it needs to be done before
113112
* the environment of the asset manager gets changed.
@@ -116,6 +115,7 @@ public void handleSwitchToGameEnvironment(Context context) {
116115
* existing then yet.
117116
*/
118117
unregisterPrefabFormats(assetTypeManager);
118+
119119
registeredPrefabFormat = new PrefabFormat(componentLibrary, typeHandlerLibrary);
120120
assetTypeManager.getAssetFileDataProducer(assetTypeManager
121121
.getAssetType(Prefab.class)

engine/src/main/java/org/terasology/engine/core/modes/StateIngame.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@
88
import org.terasology.engine.core.ComponentSystemManager;
99
import org.terasology.engine.core.GameEngine;
1010
import org.terasology.engine.core.GameThread;
11+
import org.terasology.engine.core.TerasologyConstants;
1112
import org.terasology.engine.core.bootstrap.EnvironmentSwitchHandler;
1213
import org.terasology.engine.core.module.ModuleManager;
1314
import org.terasology.engine.core.subsystem.DisplayDevice;
1415
import org.terasology.engine.entitySystem.entity.internal.EngineEntityManager;
1516
import org.terasology.engine.entitySystem.event.internal.EventSystem;
17+
import org.terasology.engine.entitySystem.prefab.Prefab;
1618
import org.terasology.engine.entitySystem.systems.UpdateSubscriberSystem;
1719
import org.terasology.engine.game.GameManifest;
1820
import org.terasology.engine.identity.storageServiceClient.StorageServiceWorker;
@@ -28,7 +30,13 @@
2830
import org.terasology.engine.rendering.nui.layers.mainMenu.MessagePopup;
2931
import org.terasology.engine.rendering.world.WorldRenderer;
3032
import org.terasology.engine.rendering.world.WorldRenderer.RenderingStage;
33+
import org.terasology.engine.world.block.loader.BlockFamilyDefinition;
3134
import org.terasology.engine.world.chunks.ChunkProvider;
35+
import org.terasology.gestalt.assets.Asset;
36+
import org.terasology.gestalt.assets.AssetType;
37+
import org.terasology.gestalt.assets.ResourceUrn;
38+
import org.terasology.gestalt.assets.management.AssetTypeManager;
39+
import org.terasology.gestalt.assets.module.ModuleAwareAssetTypeManager;
3240
import org.terasology.gestalt.module.Module;
3341
import org.terasology.gestalt.module.ModuleEnvironment;
3442
import org.terasology.nui.databinding.ReadOnlyBinding;
@@ -103,6 +111,19 @@ public void dispose(boolean shuttingDown) {
103111
ChunkProvider chunkProvider = context.get(ChunkProvider.class);
104112
chunkProvider.dispose();
105113

114+
AssetTypeManager assetTypeManager = context.get(ModuleAwareAssetTypeManager.class);
115+
// dispose all module assets
116+
assetTypeManager.getAssetTypes().forEach(assetType -> {
117+
for (ResourceUrn urn : assetType.getLoadedAssetUrns()) {
118+
if (!urn.getModuleName().equals(TerasologyConstants.ENGINE_MODULE)) {
119+
assetType.getAsset(urn).ifPresent(Asset::dispose);
120+
}
121+
}
122+
});
123+
// dispose engine assets that should not be kept when switching game states
124+
assetTypeManager.getAssetType(BlockFamilyDefinition.class).ifPresent(AssetType::disposeAll);
125+
assetTypeManager.getAssetType(Prefab.class).ifPresent(AssetType::disposeAll);
126+
106127
boolean save = networkSystem.getMode().isAuthority();
107128
if (save) {
108129
storageManager.waitForCompletionOfPreviousSaveAndStartSaving();

engine/src/main/java/org/terasology/engine/core/modes/StateLoading.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.terasology.engine.core.modes.loadProcesses.InitialiseSystems;
3030
import org.terasology.engine.core.modes.loadProcesses.InitialiseWorld;
3131
import org.terasology.engine.core.modes.loadProcesses.InitialiseWorldGenerator;
32+
import org.terasology.engine.core.modes.loadProcesses.InitialiseRendering;
3233
import org.terasology.engine.core.modes.loadProcesses.JoinServer;
3334
import org.terasology.engine.core.modes.loadProcesses.LoadEntities;
3435
import org.terasology.engine.core.modes.loadProcesses.LoadExtraBlockData;
@@ -141,6 +142,7 @@ public void init(GameEngine engine) {
141142

142143
private void initClient() {
143144
loadProcesses.add(new JoinServer(context, gameManifest, joinStatus));
145+
loadProcesses.add(new InitialiseRendering(context));
144146
loadProcesses.add(new InitialiseEntitySystem(context));
145147
loadProcesses.add(new RegisterBlocks(context, gameManifest));
146148
loadProcesses.add(new InitialiseGraphics(context));
@@ -165,6 +167,9 @@ private void initClient() {
165167

166168
private void initHost() {
167169
loadProcesses.add(new RegisterMods(context, gameManifest));
170+
if(netMode.hasLocalClient()) {
171+
loadProcesses.add(new InitialiseRendering(context));
172+
}
168173
loadProcesses.add(new InitialiseEntitySystem(context));
169174
loadProcesses.add(new RegisterBlocks(context, gameManifest));
170175
loadProcesses.add(new InitialiseGraphics(context));
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright 2021 The Terasology Foundation
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package org.terasology.engine.core.modes.loadProcesses;
5+
6+
import org.terasology.engine.context.Context;
7+
import org.terasology.engine.core.modes.SingleStepLoadProcess;
8+
import org.terasology.engine.core.module.rendering.RenderingModuleRegistry;
9+
10+
/**
11+
* Add {@link RenderingModuleRegistry} to the game {@link Context}.
12+
*
13+
* The rendering system is required whenever a client starts or joins a game. As rendering may fail to re-initialise
14+
* correctly when it has previously been constructed, this loading process will populate the {@link Context} with a
15+
* freshly created rendering system.
16+
*
17+
* When switching the game state, the rendering system can just be disposed with the old state.
18+
*/
19+
public class InitialiseRendering extends SingleStepLoadProcess {
20+
private final Context context;
21+
22+
public InitialiseRendering(Context context) {
23+
this.context = context;
24+
}
25+
26+
27+
@Override
28+
public String getMessage() {
29+
return "Initialising Rendering System...";
30+
}
31+
32+
@Override
33+
public boolean step() {
34+
context.put(RenderingModuleRegistry.class, new RenderingModuleRegistry());
35+
return true;
36+
}
37+
38+
@Override
39+
public int getExpectedCost() {
40+
return 1;
41+
}
42+
}

engine/src/main/java/org/terasology/engine/core/subsystem/rendering/ModuleRenderingSubsystem.java

Lines changed: 0 additions & 70 deletions
This file was deleted.

engine/src/main/java/org/terasology/engine/rendering/opengl/GLSLMaterial.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ public void bindTextures() {
103103
for (int slot : textureMap.keys()) {
104104
Texture texture = textureMap.get(slot);
105105
if (texture.isDisposed()) {
106+
textureMap.remove(slot);
106107
logger.error("Attempted to bind disposed texture {}", texture);
107108
} else {
108109
shaderManager.bindTexture(slot, texture);

engine/src/main/java/org/terasology/engine/world/block/DefaultColorSource.java

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,29 +17,23 @@ public Colorc calcColor(int x, int y, int z) {
1717
COLOR_LUT {
1818
@Override
1919
public Colorc calcColor(int x, int y, int z) {
20+
ColorProvider colorProvider = CoreRegistry.get(ColorProvider.class);
21+
// Return white as default if there aren't any color providers
2022
if (colorProvider == null) {
21-
colorProvider = CoreRegistry.get(ColorProvider.class);
22-
// Return white as default if there aren't any color providers
23-
if (colorProvider == null) {
24-
return Color.white;
25-
}
23+
return Color.white;
2624
}
2725
return colorProvider.colorLut(x, y, z);
2826
}
2927
},
3028
FOLIAGE_LUT {
3129
@Override
3230
public Colorc calcColor(int x, int y, int z) {
31+
ColorProvider colorProvider = CoreRegistry.get(ColorProvider.class);
32+
// Return white as default if there aren't any color providers
3333
if (colorProvider == null) {
34-
colorProvider = CoreRegistry.get(ColorProvider.class);
35-
// Return white as default if there aren't any color providers
36-
if (colorProvider == null) {
37-
return Color.white;
38-
}
34+
return Color.white;
3935
}
4036
return colorProvider.foliageLut(x, y, z);
4137
}
4238
};
43-
44-
private static ColorProvider colorProvider;
4539
}

0 commit comments

Comments
 (0)