Skip to content

Commit cfc4956

Browse files
authored
Merge pull request #622 from MovingBlocks/feat/experimental-DI-gestalt-merge
feat: implementation of gestalt-DI
2 parents bc2a7b3 + 660fa7b commit cfc4956

File tree

189 files changed

+1870
-974
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

189 files changed

+1870
-974
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,4 @@ engine/src/main/resources/entity_store.dat
8080

8181
# Ignore donwloaded JREs
8282
jre/**
83+
engine/src/main/generated/

build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ allprojects {
3030
// See https://github.com/libgdx/gdx-controllers/wiki/Compatibility for compatible versions.
3131
gdxControllersVersion = '2.1.0'
3232
roboVMVersion = '2.3.3'
33-
nuiVersion = '3.1.0'
33+
gestaltVersion = '8.0.0-SNAPSHOT'
34+
nuiVersion = '4.0.0-SNAPSHOT'
3435
}
3536
}
3637

3738
repositories {
38-
mavenLocal()
3939

4040
// Good ole Maven central
4141
mavenCentral()

config/gradle/common.gradle

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ sourceCompatibility = 1.8
1717
targetCompatibility = 1.8
1818

1919
repositories {
20-
mavenLocal()
2120

2221
// Good ole Maven central
2322
mavenCentral()
@@ -110,4 +109,4 @@ tasks.withType(Pmd) {
110109
// Make sure our config file for code analytics get extracted (vulnerability: non-IDE execution of single analytic)
111110
ideaModule.dependsOn rootProject.extractConfig
112111
tasks.eclipse.dependsOn rootProject.extractConfig
113-
check.dependsOn rootProject.extractConfig
112+
check.dependsOn rootProject.extractConfig

desktop/src/main/java/org/destinationsol/desktop/SolDesktop.java

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,29 @@
2222
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration;
2323
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Graphics;
2424
import org.destinationsol.GameOptions;
25+
import org.destinationsol.modules.FacadeModuleConfig;
2526
import org.destinationsol.modules.ModuleManager;
2627
import org.destinationsol.SolApplication;
2728
import org.destinationsol.SolFileReader;
2829
import org.destinationsol.game.DebugOptions;
2930
import org.destinationsol.ui.ResizeSubscriber;
3031
import org.slf4j.Logger;
3132
import org.slf4j.LoggerFactory;
33+
import org.terasology.context.Lifetime;
3234
import org.terasology.crashreporter.CrashReporter;
35+
import org.terasology.gestalt.di.ServiceRegistry;
36+
import org.terasology.gestalt.module.Module;
37+
import org.terasology.gestalt.module.ModuleEnvironment;
38+
import org.terasology.gestalt.module.ModuleFactory;
39+
import org.terasology.gestalt.module.ModulePathScanner;
40+
import org.terasology.gestalt.module.sandbox.JavaModuleClassLoader;
3341

3442
import java.awt.Graphics2D;
3543
import java.awt.Color;
3644
import java.awt.SplashScreen;
3745
import java.awt.Rectangle;
3846
import java.io.BufferedReader;
47+
import java.io.File;
3948
import java.io.FileReader;
4049
import java.io.IOException;
4150
import java.io.PrintWriter;
@@ -57,8 +66,6 @@
5766
public final class SolDesktop {
5867

5968
private static Logger logger = LoggerFactory.getLogger(SolDesktop.class);
60-
private static boolean initFinished;
61-
private static ModuleManager moduleManager;
6269

6370
/**
6471
* Specifies the commandline option to pass to the application for it to generate no crash reports.
@@ -119,31 +126,13 @@ public static void main(String[] argv) {
119126
}
120127

121128
handleCrashReporting(argv);
122-
new Thread(new Runnable() {
123-
@Override
124-
public void run() {
125-
try {
126-
moduleManager = new ModuleManager();
127-
moduleManager.init();
128-
} catch (Exception ignore) {
129-
}
130-
initFinished = true;
131-
}
132-
}).start();
133129

134-
while (!initFinished) {
135-
try {
136-
Thread.sleep(100);
137-
} catch (Exception e) {
138-
e.printStackTrace();
139-
}
140-
}
141130

142131
if (useSplash) {
143132
splash.close();
144133
}
145134
// Everything is set up correctly, launch the application
146-
SolApplication application = new SolApplication(moduleManager, 100);
135+
SolApplication application = new SolApplication(100, new DesktopServices());
147136
SolApplication.addResizeSubscriber(new SolDesktop.FullScreenWindowPositionAdjustment(!options.fullscreen));
148137
// Everything is set up correctly, launch the application
149138
new Lwjgl3Application(application, applicationConfig);
@@ -231,6 +220,40 @@ private static void setScreenDimensions(Lwjgl3ApplicationConfiguration applicati
231220
}
232221
}
233222

223+
private static class DesktopServices extends ServiceRegistry {
224+
public DesktopServices() {
225+
this.with(FacadeModuleConfig.class).lifetime(Lifetime.Singleton).use(DesktopModuleConfig::new);
226+
this.with(ModulePathScanner.class).lifetime(Lifetime.Singleton);
227+
}
228+
}
229+
230+
private static class DesktopModuleConfig implements FacadeModuleConfig {
231+
@Override
232+
public File getModulesPath() {
233+
return Paths.get(".").resolve("modules").toFile();
234+
}
235+
236+
@Override
237+
public boolean useSecurityManager() {
238+
return true;
239+
}
240+
241+
@Override
242+
public ModuleEnvironment.ClassLoaderSupplier getClassLoaderSupplier() {
243+
return JavaModuleClassLoader::create;
244+
}
245+
246+
@Override
247+
public Module createEngineModule() {
248+
return new ModuleFactory().createPackageModule("org.destinationsol");
249+
}
250+
251+
@Override
252+
public Class<?>[] getAPIClasses() {
253+
return new Class<?>[0];
254+
}
255+
}
256+
234257
/**
235258
* Provides the implementation of SolFileReader used by this class.
236259
*/

engine/build.gradle

Lines changed: 25 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2,53 +2,46 @@ apply from: '../config/gradle/common.gradle'
22
apply plugin: 'java-library'
33
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
44

5-
import org.reflections.Reflections;
6-
import org.reflections.scanners.SubTypesScanner;
7-
import org.reflections.scanners.TypeAnnotationsScanner;
8-
import org.reflections.util.ConfigurationBuilder;
9-
import org.reflections.util.ClasspathHelper;
10-
115
// Dependencies needed for what our Gradle scripts themselves use. It cannot be included via an external Gradle file :-(
126
buildscript {
137
repositories {
148
mavenCentral()
159

16-
// HACK: Needed for NUI and gestalt entity-component reflections
17-
mavenLocal()
1810
google()
1911
maven { url "http://artifactory.terasology.org/artifactory/virtual-repo-live" }
2012
// Needed for Jsemver, which is a gestalt dependency
2113
maven { url = 'https://heisluft.de/maven/' }
2214
}
2315

2416
dependencies {
25-
// Needed for caching reflected data during builds
26-
classpath 'org.reflections:reflections:0.9.12'
2717
classpath 'dom4j:dom4j:1.6.1'
28-
29-
// HACK: Needed for NUI and gestalt entity-component reflections
30-
classpath group: 'org.terasology.nui', name: 'nui', version: nuiVersion
31-
classpath group: 'javax.servlet', name: 'javax.servlet-api', version: '3.0.1'
32-
classpath group: 'org.terasology.gestalt', name: 'gestalt-entity-system', version: '7.2.0-SNAPSHOT'
3318
}
3419
}
3520

3621
dependencies {
3722
api group: 'org.slf4j', name: 'slf4j-api', version: '1.7.25'
3823
api group: 'com.google.code.gson', name: 'gson', version: '2.6.2'
24+
api group: 'com.google.guava', name: 'guava', version: '30.1-jre'
3925

4026
api "com.badlogicgames.gdx:gdx:$gdxVersion"
4127
api "com.badlogicgames.gdx:gdx-box2d:$gdxVersion"
4228
api "com.badlogicgames.gdx-controllers:gdx-controllers-core:$gdxControllersVersion"
4329

44-
api(group: 'org.terasology.gestalt', name: 'gestalt-asset-core', version: '7.2.0-SNAPSHOT')
45-
api(group: 'org.terasology.gestalt', name: 'gestalt-entity-system', version: '7.2.0-SNAPSHOT')
46-
api(group: 'org.terasology.gestalt', name: 'gestalt-module', version: '7.2.0-SNAPSHOT')
47-
api(group: 'org.terasology.gestalt', name: 'gestalt-util', version: '7.2.0-SNAPSHOT')
30+
api "org.terasology.gestalt:gestalt-asset-core:$gestaltVersion"
31+
api "org.terasology.gestalt:gestalt-entity-system:$gestaltVersion"
32+
api "org.terasology.gestalt:gestalt-module:$gestaltVersion"
33+
api "org.terasology.gestalt:gestalt-util:$gestaltVersion"
34+
35+
api "org.terasology.gestalt:gestalt-di:$gestaltVersion"
36+
api "org.terasology.gestalt:gestalt-inject:$gestaltVersion"
37+
annotationProcessor "org.terasology.gestalt:gestalt-inject-java:$gestaltVersion"
38+
39+
implementation "net.jcip:jcip-annotations:1.0"
4840

49-
api group: 'org.terasology.nui', name: 'nui', version: nuiVersion
50-
api group: 'org.terasology.nui', name: 'nui-libgdx', version: nuiVersion
51-
api group: 'org.terasology.nui', name: 'nui-gestalt7', version: nuiVersion
41+
api "org.terasology.nui:nui:$nuiVersion"
42+
api "org.terasology.nui:nui-libgdx:$nuiVersion"
43+
api "org.terasology.nui:nui-gestalt:$nuiVersion"
44+
api "org.terasology.nui:nui-reflect:$nuiVersion"
5245

5346
implementation group: 'com.google.protobuf', name: 'protobuf-java', version: '3.4.0'
5447

@@ -73,30 +66,19 @@ dependencies {
7366
testCompile group: 'org.assertj', name: 'assertj-core', version: '3.9.0'
7467
}
7568

76-
task cacheReflections {
77-
description = 'Caches reflection output to make regular startup faster. May go stale and need cleanup at times.'
78-
inputs.files sourceSets.main.output.classesDirs,
79-
// getClassesDir from all sourceSets (for any jvm (seems) language)
80-
configurations."${sourceSets.main.runtimeClasspathConfigurationName}"
81-
82-
outputs.upToDateWhen {classes.state.upToDate}
83-
outputs.file("$buildDir/resources/main/org/destinationsol/reflections.cache")
84-
dependsOn classes
85-
86-
doLast {
87-
// Without the .mkdirs() we might hit a scenario where the classes dir doesn't exist yet
88-
Reflections reflections = new Reflections(new ConfigurationBuilder()
89-
.addUrls(inputs.files.collect { it.toURI().toURL() })
90-
.filterInputsBy({ it.startsWith("org.destinationsol") || it.startsWith("org.terasology.nui") })
91-
.setScanners(new TypeAnnotationsScanner(), new SubTypesScanner()))
92-
reflections.save("$buildDir/resources/main/org/destinationsol/reflections.cache")
93-
}
69+
// Adds Resources as parameter for AnnotationProcessor (gather ResourceIndex,
70+
// also add resource as input for compilejava, for re-gathering ResourceIndex, when resource was changed.
71+
compileJava {
72+
inputs.files sourceSets.main.resources.srcDirs
73+
options.compilerArgs = ["-Aresource=${sourceSets.main.resources.srcDirs.join(File.pathSeparator)}"]
74+
}
75+
compileTestJava {
76+
inputs.files sourceSets.test.resources.srcDirs
77+
options.compilerArgs = ["-Aresource=${sourceSets.test.resources.srcDirs.join(File.pathSeparator)}"]
9478
}
9579

96-
jar {
97-
// This prevents the assets from being scanned as code files
98-
dependsOn cacheReflections
9980

81+
jar {
10082
archiveName = "sol.jar"
10183

10284
doFirst {
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package org.destinationsol;
2+
3+
import org.terasology.gestalt.di.BeanContext;
4+
import org.terasology.gestalt.util.reflection.ClassFactory;
5+
6+
import javax.inject.Provider;
7+
import java.util.Optional;
8+
9+
public class BeanClassFactory implements ClassFactory {
10+
private final Provider<BeanContext> beanContext;
11+
12+
public BeanClassFactory(Provider<BeanContext> beanContext) {
13+
this.beanContext = beanContext;
14+
}
15+
16+
@Override
17+
public <T> Optional<T> instantiateClass(Class<? extends T> type) {
18+
return (Optional<T>) beanContext.get().findBean(type);
19+
}
20+
}

engine/src/main/java/org/destinationsol/CommonDrawer.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
import org.destinationsol.ui.ResizeSubscriber;
3535
import org.destinationsol.ui.UiDrawer;
3636

37+
import javax.inject.Inject;
38+
3739
public class CommonDrawer implements ResizeSubscriber {
3840
private final SpriteBatch spriteBatch;
3941
private final BitmapFont font;
@@ -44,8 +46,9 @@ public class CommonDrawer implements ResizeSubscriber {
4446

4547
private DisplayDimensions displayDimensions;
4648

47-
CommonDrawer() {
48-
displayDimensions = SolApplication.displayDimensions;
49+
@Inject
50+
CommonDrawer(DisplayDimensions displayDimensions) {
51+
this.displayDimensions = displayDimensions;
4952

5053
spriteBatch = new SpriteBatch();
5154

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright 2021 The Terasology Foundation
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.destinationsol;
17+
18+
import org.destinationsol.game.context.Context;
19+
import org.slf4j.Logger;
20+
import org.slf4j.LoggerFactory;
21+
import org.terasology.gestalt.di.BeanContext;
22+
import org.terasology.gestalt.di.exceptions.BeanResolutionException;
23+
24+
import javax.inject.Inject;
25+
26+
@Deprecated
27+
public class ContextWrapper implements Context {
28+
29+
private static final Logger logger = LoggerFactory.getLogger(ContextWrapper.class);
30+
protected BeanContext context;
31+
32+
@Inject
33+
public ContextWrapper(BeanContext beanContext) {
34+
this.context = beanContext;
35+
}
36+
37+
@Override
38+
public <T> T get(Class<? extends T> type) {
39+
try {
40+
return (T) context.getBean(type);
41+
} catch (BeanResolutionException e){
42+
logger.warn("Bean [{}] not found",type);
43+
return null;
44+
}
45+
}
46+
47+
@Override
48+
public <T, U extends T> void put(Class<T> type, U object) {
49+
throw new RuntimeException("Cannot insert values into wrapped context: please use the BeanContext directly");
50+
}
51+
52+
@Override
53+
public <T, U extends T> void remove(Class<T> type, U object) {
54+
throw new RuntimeException("Cannot insert values into wrapped context: please use the BeanContext directly");
55+
}
56+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright 2020 The Terasology Foundation
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.destinationsol;
17+
18+
19+
import org.destinationsol.game.context.Context;
20+
import org.terasology.context.Lifetime;
21+
import org.terasology.gestalt.di.ServiceRegistry;
22+
23+
public class ContextWrapperService extends ServiceRegistry {
24+
public ContextWrapperService() {
25+
this.with(Context.class).use(ContextWrapper.class).lifetime(Lifetime.Singleton);
26+
}
27+
}

0 commit comments

Comments
 (0)