Skip to content

Commit a29fba8

Browse files
committed
chore: restructure Platform
1 parent 0b12f8a commit a29fba8

File tree

10 files changed

+202
-107
lines changed

10 files changed

+202
-107
lines changed

src/main/java/org/terasology/launcher/LauncherInitTask.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.slf4j.LoggerFactory;
1313
import org.terasology.launcher.game.GameManager;
1414
import org.terasology.launcher.model.LauncherVersion;
15+
import org.terasology.launcher.platform.UnsupportedPlatformException;
1516
import org.terasology.launcher.repositories.CombinedRepository;
1617
import org.terasology.launcher.settings.LauncherSettingsValidator;
1718
import org.terasology.launcher.settings.Settings;
@@ -24,7 +25,7 @@
2425
import org.terasology.launcher.util.LauncherDirectoryUtils;
2526
import org.terasology.launcher.util.LauncherManagedDirectory;
2627
import org.terasology.launcher.util.LauncherStartFailedException;
27-
import org.terasology.launcher.util.Platform;
28+
import org.terasology.launcher.platform.Platform;
2829

2930
import java.io.IOException;
3031
import java.net.URI;
@@ -114,18 +115,17 @@ protected LauncherConfiguration call() {
114115
releaseRepository);
115116
} catch (LauncherStartFailedException e) {
116117
logger.warn("Could not configure launcher.");
118+
} catch (UnsupportedPlatformException e) {
119+
logger.error("Unsupported OS or architecture: {}", e.getMessage());
117120
}
118121

119122
return null;
120123
}
121124

122-
private Platform getPlatform() {
125+
private Platform getPlatform() throws UnsupportedPlatformException {
123126
logger.trace("Init Platform...");
124127
updateMessage(I18N.getLabel("splash_checkOS"));
125128
final Platform platform = Platform.getPlatform();
126-
if (!platform.isLinux() && !platform.isMac() && !platform.isWindows()) {
127-
logger.warn("Detected unexpected platform: {}", platform);
128-
}
129129
logger.debug("Platform: {}", platform);
130130
return platform;
131131
}

src/main/java/org/terasology/launcher/game/GameService.java

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import javafx.concurrent.Worker;
99
import org.slf4j.Logger;
1010
import org.slf4j.LoggerFactory;
11+
import org.terasology.launcher.platform.UnsupportedPlatformException;
1112
import org.terasology.launcher.settings.Settings;
1213

1314
import java.io.IOException;
@@ -49,19 +50,20 @@ public class GameService extends Service<Boolean> {
4950

5051
public GameService() {
5152
setExecutor(Executors.newSingleThreadExecutor(
52-
new ThreadFactoryBuilder()
53-
.setNameFormat("GameService-%d")
54-
.setDaemon(true)
55-
.setUncaughtExceptionHandler(this::exceptionHandler)
56-
.build()
53+
new ThreadFactoryBuilder()
54+
.setNameFormat("GameService-%d")
55+
.setDaemon(true)
56+
.setUncaughtExceptionHandler(this::exceptionHandler)
57+
.build()
5758
));
5859
}
5960

6061
/**
6162
* Start a new game process with these settings.
63+
*
6264
* @param gameInstallation the directory under which we will find libs/Terasology.jar, also used as the process's
63-
* working directory
64-
* @param settings supplies other settings relevant to configuring a process
65+
* working directory
66+
* @param settings supplies other settings relevant to configuring a process
6567
*/
6668
@SuppressWarnings("checkstyle:HiddenField")
6769
public void start(GameInstallation gameInstallation, Settings settings) {
@@ -115,7 +117,7 @@ public void restart() {
115117
* This class's configuration fields <em>must</em> be set before this is called.
116118
*
117119
* @throws com.google.common.base.VerifyException when fields are unset
118-
* @throws RuntimeException when required files in the game directory are missing or inaccessible
120+
* @throws RuntimeException when required files in the game directory are missing or inaccessible
119121
*/
120122
@Override
121123
protected RunGameTask createTask() throws GameVersionNotSupportedException {
@@ -128,19 +130,23 @@ protected RunGameTask createTask() throws GameVersionNotSupportedException {
128130
settings.userJavaParameters.get(),
129131
settings.userGameParameters.get(),
130132
settings.logLevel.get());
131-
} catch (IOException e) {
133+
} catch (IOException | UnsupportedPlatformException e) {
132134
throw new RuntimeException("Error using this as a game directory: " + gamePath, e);
133135
}
134136
return new RunGameTask(starter);
135137
}
136138

137-
/** After a task completes, reset to ready for the next. */
139+
/**
140+
* After a task completes, reset to ready for the next.
141+
*/
138142
@Override
139143
protected void succeeded() {
140144
reset(); // Ready to go again!
141145
}
142146

143-
/** Checks to see if the failure left any exceptions behind, then resets to ready. */
147+
/**
148+
* Checks to see if the failure left any exceptions behind, then resets to ready.
149+
*/
144150
@Override
145151
protected void failed() {
146152
// "Uncaught" exceptions from javafx's Task are actually caught and kept in a property,

src/main/java/org/terasology/launcher/game/GameStarter.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77
import org.slf4j.Logger;
88
import org.slf4j.LoggerFactory;
99
import org.slf4j.event.Level;
10+
import org.terasology.launcher.platform.UnsupportedPlatformException;
1011
import org.terasology.launcher.util.JavaHeapSize;
11-
import org.terasology.launcher.util.Platform;
12+
import org.terasology.launcher.platform.Platform;
1213

1314
import java.io.IOException;
1415
import java.nio.file.Path;
@@ -38,7 +39,8 @@ final class GameStarter implements Callable<Process> {
3839
* @param logLevel the minimum level of log events Terasology will include on its output stream to us
3940
*/
4041
GameStarter(GameInstallation gameInstallation, Path gameDataDirectory, JavaHeapSize heapMin, JavaHeapSize heapMax,
41-
List<String> javaParams, List<String> gameParams, Level logLevel) throws IOException, GameVersionNotSupportedException {
42+
List<String> javaParams, List<String> gameParams, Level logLevel)
43+
throws IOException, GameVersionNotSupportedException, UnsupportedPlatformException {
4244
Semver engineVersion = gameInstallation.getEngineVersion();
4345
var gamePath = gameInstallation.getPath();
4446

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Copyright 2023 The Terasology Foundation
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package org.terasology.launcher.platform;
5+
6+
public enum Arch {
7+
X64,
8+
X86,
9+
ARM64
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Copyright 2023 The Terasology Foundation
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package org.terasology.launcher.platform;
5+
6+
public enum OS {
7+
WINDOWS,
8+
MAC,
9+
LINUX
10+
}
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
// Copyright 2023 The Terasology Foundation
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package org.terasology.launcher.platform;
5+
6+
import com.google.common.base.Objects;
7+
import com.google.common.collect.Sets;
8+
9+
import java.util.Locale;
10+
import java.util.Set;
11+
12+
/**
13+
* A simplified representation of a computer platform as `os` and `arch`
14+
*/
15+
public final class Platform {
16+
17+
final private OS os;
18+
final private Arch arch;
19+
20+
//TODO(skaldarnar): I'm not fully settled on how to model the Platform. I thought splitting this up into two enums
21+
// for OS and Architecture would help with more type-safe construction of these values, simplify comparison to
22+
// select the right JRE for a game, etc.
23+
//
24+
// On the other hand, the set of supported platforms is so limited, and continuing on a non-supported platform
25+
// does not make much sense. So, maybe it is better to have a rather restrictive and explicit enum in the form of
26+
// WINDOWS_X64
27+
// LINUX_X64
28+
// I'm adding the architecture to this list, as I hope that we'll be able to support old Intel and new M1 Macs at
29+
// some point in the future, adding the following to the list:
30+
// MAC_X64
31+
// MAC_AARCH64
32+
// The biggest drawback of being super-strict here is that development on non-supported platforms becomes
33+
// impossible where it was just "not ideal" before.
34+
public static final Set<Platform> SUPPORTED_PLATFORMS = Sets.newHashSet(
35+
new Platform(OS.WINDOWS, Arch.X64),
36+
new Platform(OS.LINUX, Arch.X64),
37+
new Platform(OS.MAC, Arch.X64)
38+
);
39+
40+
public Platform(OS os, Arch arch) {
41+
this.os = os;
42+
this.arch = arch;
43+
}
44+
45+
/**
46+
* @return the simplified operating system name as platform os
47+
*/
48+
public String getOs() {
49+
//TODO: change return type to OS
50+
return os.name().toLowerCase(Locale.ENGLISH);
51+
}
52+
53+
/**
54+
* @return the simplified operating system architecture as platform arch
55+
*/
56+
public Arch getArch() {
57+
return arch;
58+
}
59+
60+
public boolean isLinux() {
61+
return os == OS.LINUX;
62+
}
63+
64+
public boolean isMac() {
65+
return os == OS.MAC;
66+
}
67+
68+
public boolean isWindows() {
69+
return os == OS.WINDOWS;
70+
}
71+
72+
public String toString() {
73+
return "OS '" + os + "', arch '" + arch + "'";
74+
}
75+
76+
@Override
77+
public boolean equals(Object o) {
78+
if (this == o) {
79+
return true;
80+
}
81+
if (o == null || getClass() != o.getClass()) {
82+
return false;
83+
}
84+
Platform platform = (Platform) o;
85+
return os == platform.os && arch == platform.arch;
86+
}
87+
88+
@Override
89+
public int hashCode() {
90+
return Objects.hashCode(os, arch);
91+
}
92+
93+
/**
94+
* Get information on the host platform the launcher is currently running on.
95+
*
96+
* @return the platform
97+
*/
98+
public static Platform getPlatform() throws UnsupportedPlatformException {
99+
final String platformOs = System.getProperty("os.name").toLowerCase();
100+
final OS os;
101+
if (platformOs.startsWith("linux")) {
102+
os = OS.LINUX;
103+
} else if (platformOs.startsWith("mac os")) {
104+
os = OS.MAC;
105+
} else if (platformOs.startsWith("windows")) {
106+
os = OS.WINDOWS;
107+
} else {
108+
throw new UnsupportedPlatformException("Unsupported OS: " + platformOs);
109+
}
110+
111+
final String platformArch = System.getProperty("os.arch");
112+
final Arch arch;
113+
switch (platformArch) {
114+
case "x86_64":
115+
case "amd64":
116+
arch = Arch.X64;
117+
break;
118+
case "x86":
119+
case "i386":
120+
arch = Arch.X86;
121+
break;
122+
case "aarch64":
123+
case "arm64":
124+
arch = Arch.ARM64;
125+
break;
126+
default:
127+
throw new UnsupportedPlatformException("Architecture not supported: " + platformArch);
128+
}
129+
130+
return new Platform(os, arch);
131+
}
132+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2023 The Terasology Foundation
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package org.terasology.launcher.platform;
5+
6+
public class UnsupportedPlatformException extends Exception {
7+
8+
public UnsupportedPlatformException() {
9+
super();
10+
}
11+
12+
public UnsupportedPlatformException(String message) {
13+
super(message);
14+
}
15+
}

src/main/java/org/terasology/launcher/util/LauncherDirectoryUtils.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import org.slf4j.Logger;
77
import org.slf4j.LoggerFactory;
8+
import org.terasology.launcher.platform.Platform;
89

910
import java.io.IOException;
1011
import java.net.URISyntaxException;

src/main/java/org/terasology/launcher/util/Platform.java

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

0 commit comments

Comments
 (0)