Merge branch 'develop' into record_replay_release

develop
iaronaraujo 2018-06-06 17:11:12 -03:00 committed by GitHub
commit 1a2837dc00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 271 additions and 72 deletions

4
.gitignore vendored
View File

@ -99,4 +99,8 @@ config/metrics/
API_file.txt
New_API_file.txt
# Ignore Whitelist and Blacklist files
whitelist.json
blacklist.json
# Ignore weird stuff that might be obsolete

View File

@ -232,7 +232,8 @@ Contributors
[Inei1](https://github.com/Inei1),
[dorasun](https://github.com/dorasun),
[oekonomi](https://github.com/oekonomi),
[Chris 'cwgreene' Greene](https://github.com/cwgreene)
[Chris 'cwgreene' Greene](https://github.com/cwgreene),
[AdamAboudi](https://github.com/AdamAboudi)
* GUI Team:
[Anton "small-jeeper" Kireev](https://github.com/small-jeeper),
[miniME89](https://github.com/miniME89),

View File

@ -8,6 +8,77 @@ You can run the game with `-homedir` to instead store all game data in the direc
Report issues in the [support forum](http://forum.terasology.org/forum/support.20) or ask on [IRC](https://github.com/MovingBlocks/Terasology/wiki/Using-IRC) (`#terasology` on Freenode)
## Controls
Note: Keys between the latest stable and latest develop build may differ.
* [W,A,S,D] - Movement
* [E] - Activate / Use (while pointing at a chest, TNT blocks, etc)
* [Q] - Throw held (block) item (hold down to charge for a longer throw!)
* [R] - Keep moving forward (like W) until [R] is pressed again
* [Space] - Jump / Ascend
* [Ctrl] - Crouch / Descend
* [Shift] - Hold to run (or walk when run is toggled to default)
* [Caps lock] - Toggle default between run or walk (starts on run)
* [Left click] - Trigger left click action (default = remove block)
* [Right click] - Trigger right click action (default = place block)
* [Mouse wheel up/down] - Cycle through toolbar slots OR pick up / deposit items into stacks in an inventory one at a time
* [1..0] - Change the active toolbar slot
* [I] - Toggle inventory screen
* [B] - Show infinite block inventory (requires "BlockPicker" module active)
* [C] - Show character screen for stats and equipment (requires "Equipment" module active)
* [H] - Hide user interface
* [T] - Toggle chat interface (effectively a mini-console that only does chat)
* [Tab] - Auto-completion in the console
* [Home] - Increase viewing distance
* [End] - Decrease viewing distance
* [Escape] - Show/hide the game menu screen
* [F1] OR [`] - Toggle full developer console (the "grave" key, usually above tab)
* [F2] - Toggle window focus and reveals a debug pane (only contains stuff if module(s) using it is enabled)
* [F3] - Toggle debug mode and information
* [F5] - Show behavior tree editor
* [F10] - Show NUI editor
* [F12] - Take screenshot (goes to /screenshots in game data dir)
## Debug Features
Only works when the F3 debug mode is enabled (and may come and go)
* [Arrow up/down] - Adjust the current time in small steps
* [Arrow left/right] - Adjust the current time in larger steps
* [F4] - Cycle advanced debug metrics
* [F6] - Debug rendering enabled
* [F7] - Cycle debug rendering stage
* [F8] - Debug render chunk bounding boxes
* [F9] - Debug render wire-frame
## Game console
Press the `F1` or `grave` key (usually the \` key immediately above `tab`) to show the in-game console. Mostly everything is case insensitive. Copy paste is supported and up/down arrow will cycle through commands you've used before. Hitting `tab` with a partially typed command will auto-complete it (including abbreviated camel case like lS for listShapes). For partial commands with multiple completion candidates you can `tab` again to cycle through them.
* `help` - Show in-game help (more thorough)
* `search [something]` - searches for any command, prefab, or asset with "something" in its name, help text, etc
* `flight` - just what it sounds like :)
* `ghost` - no-clip mode (fly through anything)
* `hspeed` - greatly increase your movement speed
* `hjump` - jump really high. Almost like flying - but it isn't. Just jump good.
* `restoreSpeed` - normalizes speed (both horizontal and vertical)
* `help give` - Shows detailed help on the "give" command
* `give Water` - Gives 16 water blocks (default quantity when not specified)
* `give Stone 99 Stair` - Gives you 99 stone stair blocks
* `give Chest` - Gives you a Chest block you can place, activate ('E'), put stuff in, break, pick up, place elsewhere, find same stuff in it!
* `give TNT` - Gives you 16 TNT blocks you can place and activate ('E') to blow up
* `bulkGiveBlock cake` - Gives you a stack of blocks for every block with the name "cake" in it! Find good block series with `search`
* `listBlocks` - Lists all actively used blocks (have been loaded for the world)
* `listFreeShapeBlocks` - Lists all blocks that can be requested in any known shape
* `listShapes` - Lists the available shapes
* `healthMax` - Fully restores the player's health
* `showHealth` - Shows the player's health
* `teleport 42 42 42` - Warps the player to x = 42, y = 42, z = 42
* `toggleSunHalting X` - Stops the sun's movement at X position, denoted in days.
## Multiplayer
To name yourself for a multiplayer game use Settings / Player. You can also pick a color, which will affect your placeholder monkey head player avatar, name in chat, and floating name tag.
@ -68,6 +139,16 @@ Alternatively you can run from source and supply parameters for game configurati
This will all become easier as the project and especially the launcher mature further :-)
### Server Whitelist and Blacklist
Hosting a server will create a whitelist and a blacklist that can be used to manage who is able to connect to that server.
If the whitelist contains at least one client ID, only the ID(s) on the list will be allowed to connect to the server. All IDs not on the whitelist are effectively blacklisted.
If the whitelist is empty, any ID not on the blacklist will be able to connect.
Client IDs are added to the lists in JSON format, for example: ["6a5f11f7-4038-4ef0-91ac-86cb957588b1","01264d12-27cf-4699-b8e2-bdc92ac8ef73"]
### Server via Docker
If you're into Docker you can launch a container with a Terasology server already hooked up.
@ -80,72 +161,4 @@ Example: `docker pull qwick/terasology:latest`
The Docker server starts with no extra modules configured, you would have to go update the game server's config accordingly if desired.
## Controls
Note: Keys between the latest stable and latest develop build may differ.
* [W,A,S,D] - Movement
* [E] - Activate / Use (while pointing at a chest, TNT blocks, etc)
* [Q] - Throw held (block) item (hold down to charge for a longer throw!)
* [R] - Keep moving forward (like W) until [R] is pressed again
* [Space] - Jump / Ascend
* [Ctrl] - Crouch / Descend
* [Shift] - Hold to run (or walk when run is toggled to default)
* [Caps lock] - Toggle default between run or walk (starts on run)
* [Left click] - Trigger left click action (default = remove block)
* [Right click] - Trigger right click action (default = place block)
* [Mouse wheel up/down] - Cycle through toolbar slots OR pick up / deposit items into stacks in an inventory one at a time
* [1..0] - Change the active toolbar slot
* [I] - Toggle inventory screen
* [B] - Show infinite block inventory (requires "BlockPicker" module active)
* [C] - Show character screen for stats and equipment (requires "Equipment" module active)
* [H] - Hide user interface
* [T] - Toggle chat interface (effectively a mini-console that only does chat)
* [Tab] - Auto-completion in the console
* [Home] - Increase viewing distance
* [End] - Decrease viewing distance
* [Escape] - Show/hide the game menu screen
* [F1] OR [`] - Toggle full developer console (the "grave" key, usually above tab)
* [F2] - Toggle window focus and reveals a debug pane (only contains stuff if module(s) using it is enabled)
* [F3] - Toggle debug mode and information
* [F5] - Show behavior tree editor
* [F10] - Show NUI editor
* [F12] - Take screenshot (goes to /screenshots in game data dir)
## Debug Features
Only works when the F3 debug mode is enabled (and may come and go)
* [Arrow up/down] - Adjust the current time in small steps
* [Arrow left/right] - Adjust the current time in larger steps
* [F4] - Cycle advanced debug metrics
* [F6] - Debug rendering enabled
* [F7] - Cycle debug rendering stage
* [F8] - Debug render chunk bounding boxes
* [F9] - Debug render wire-frame
## Game console
Press the `F1` or `grave` key (usually the \` key immediately above `tab`) to show the in-game console. Mostly everything is case insensitive. Copy paste is supported and up/down arrow will cycle through commands you've used before. Hitting `tab` with a partially typed command will auto-complete it (including abbreviated camel case like lS for listShapes). For partial commands with multiple completion candidates you can `tab` again to cycle through them.
* `help` - Show in-game help (more thorough)
* `search [something]` - searches for any command, prefab, or asset with "something" in its name, help text, etc
* `flight` - just what it sounds like :)
* `ghost` - no-clip mode (fly through anything)
* `hspeed` - greatly increase your movement speed
* `hjump` - jump really high. Almost like flying - but it isn't. Just jump good.
* `restoreSpeed` - normalizes speed (both horizontal and vertical)
* `help give` - Shows detailed help on the "give" command
* `give Water` - Gives 16 water blocks (default quantity when not specified)
* `give Stone 99 Stair` - Gives you 99 stone stair blocks
* `give Chest` - Gives you a Chest block you can place, activate ('E'), put stuff in, break, pick up, place elsewhere, find same stuff in it!
* `give TNT` - Gives you 16 TNT blocks you can place and activate ('E') to blow up
* `bulkGiveBlock cake` - Gives you a stack of blocks for every block with the name "cake" in it! Find good block series with `search`
* `listBlocks` - Lists all actively used blocks (have been loaded for the world)
* `listFreeShapeBlocks` - Lists all blocks that can be requested in any known shape
* `listShapes` - Lists the available shapes
* `healthMax` - Fully restores the player's health
* `showHealth` - Shows the player's health
* `teleport 42 42 42` - Warps the player to x = 42, y = 42, z = 42

View File

@ -121,11 +121,15 @@ public class StateIngame implements GameState {
screenGrabber.takeGamePreview(PathManager.getInstance().getSavePath(gameManifest.getTitle()));
}
ChunkProvider chunkProvider = context.get(ChunkProvider.class);
chunkProvider.dispose();
boolean save = networkSystem.getMode().isAuthority();
if (save) {
ScreenGrabber screenGrabber = context.get(ScreenGrabber.class);
screenGrabber.takeGamePreview(PathManager.getInstance().getSavePath(gameManifest.getTitle()));
storageManager.waitForCompletionOfPreviousSaveAndStartSaving();
}

View File

@ -50,6 +50,11 @@ public abstract class AbstractClient implements Client {
clientEntity.destroy();
}
/**
* Function to find the clients entity reference and return it.
* @param entityManager - Passes the entity manager for looping through all entities to find ones with client components
* @return the entity reference of the client playerID
*/
private EntityRef findClientEntityRef(EntityManager entityManager) {
for (EntityRef entityRef: entityManager.getEntitiesWith(ClientInfoComponent.class)) {
ClientInfoComponent clientInfoComponent = entityRef.getComponent(ClientInfoComponent.class);
@ -60,6 +65,12 @@ public abstract class AbstractClient implements Client {
return EntityRef.NULL;
}
/**
* Creates an entity for the client connection, checking if name and color options can be used.
* @param preferredName Passes players preferred name to check availability, giving a best alternative if it is used already.
* @param color Creates or changes the player's color component to match argument
* @param entityManager
*/
protected void createEntity(String preferredName, Color color, EntityManager entityManager) {
// Create player entity
clientEntity = entityManager.create("engine:client");
@ -87,6 +98,11 @@ public abstract class AbstractClient implements Client {
}
}
/**
* Used to change or add a color to the client entity.
* @param clientInfo
* @param color Used to change the clients color to this
*/
private void addOrSetColorComponent(EntityRef clientInfo, Color color) {
ColorComponent colorComp = clientInfo.getComponent(ColorComponent.class);
if (colorComp != null) {
@ -99,6 +115,11 @@ public abstract class AbstractClient implements Client {
}
}
/**
* Used to change or add a display name to the client entity.
* @param clientInfo
* @param name Function will set the client entities name to this.
*/
private void addOrSetDisplayNameComponent(EntityRef clientInfo, String name) {
DisplayNameComponent component = clientInfo.getComponent(DisplayNameComponent.class);
if (component != null) {
@ -111,6 +132,13 @@ public abstract class AbstractClient implements Client {
}
}
/**
* Provides an alternative name to the client when the preferred name is taken or unavailable, appending a suffix to the end.
* @param preferredName Used to build new name based on preferred option.
* @param entityManager
* @param player Used to mark client name as not to be checked, ensuring the client doesn't block its own name.
* @return Returns the new name to the client.
*/
protected String findUniquePlayerName(String preferredName, EntityManager entityManager, EntityRef player) {
Set<String> usedNames = findNamesOfOtherPlayers(entityManager, player);
@ -123,6 +151,13 @@ public abstract class AbstractClient implements Client {
return name;
}
/**
* Creates a HashSet<String> of all connected player names.
* @param entityManager
* @param player Client name to make sure it doesn't put its own name in the list.
* @return Returns all connected player names.
*/
private Set<String> findNamesOfOtherPlayers(EntityManager entityManager, EntityRef player) {
Set<String> otherNames = new HashSet<>();
for (EntityRef clientInfo: entityManager.getEntitiesWith(ClientInfoComponent.class)) {
@ -135,6 +170,11 @@ public abstract class AbstractClient implements Client {
return otherNames;
}
/**
* Creates a client information entity on the current entity.
* @param entityManager
* @return Returns the client information.
*/
private EntityRef createClientInfoEntity(EntityManager entityManager) {
EntityRef clientInfo;
clientInfo = entityManager.create("engine:clientInfo");

View File

@ -63,6 +63,11 @@ public class ClientConnectionHandler extends SimpleChannelUpstreamHandler {
private final long timeoutThreshold = 10000;
private Channel channel;
/**
* Initialises: network system, join status, and module manager.
* @param joinStatus
* @param networkSystem
*/
public ClientConnectionHandler(JoinStatusImpl joinStatus, NetworkSystemImpl networkSystem) {
this.networkSystem = networkSystem;
this.joinStatus = joinStatus;
@ -71,6 +76,10 @@ public class ClientConnectionHandler extends SimpleChannelUpstreamHandler {
this.moduleManager = CoreRegistry.get(ModuleManager.class);
}
/**
* Sets timeout threshold, if client exceeds this time during connection it will automatically close the channel.
* @param inputChannel Socket for connections to allow I/O.
*/
private void scheduleTimeout(Channel inputChannel) {
channel = inputChannel;
timeoutPoint = System.currentTimeMillis() + timeoutThreshold;
@ -129,6 +138,11 @@ public class ClientConnectionHandler extends SimpleChannelUpstreamHandler {
}
}
/**
* Attempts to receive a module from the server and push it to the client. Creates a file on the target machine and begins preparation to write to it.
* @param channelHandlerContext
* @param moduleDataHeader
*/
private void receiveModuleStart(ChannelHandlerContext channelHandlerContext,
NetData.ModuleDataHeader moduleDataHeader) {
if (receivingModule != null) {
@ -169,6 +183,12 @@ public class ClientConnectionHandler extends SimpleChannelUpstreamHandler {
}
}
/**
* Converts file size to a string in either bytes, KB, or MB. Dependant on the files size.
* @param size Size of the file.
* @return String of the file size in either bytes or KB or MB.
*/
private String getSizeString(long size) {
if (size < 1024) {
return size + " bytes";
@ -179,6 +199,11 @@ public class ClientConnectionHandler extends SimpleChannelUpstreamHandler {
}
}
/**
* Converts the modules data to a byte array and writes it to a file, which then is copied from the temp directory to the correct directory.
* @param channelHandlerContext
* @param moduleData The data of the module.
*/
private void receiveModule(ChannelHandlerContext channelHandlerContext, NetData.ModuleData moduleData) {
if (receivingModule == null) {
joinStatus.setErrorMessage("Module download error");
@ -226,6 +251,11 @@ public class ClientConnectionHandler extends SimpleChannelUpstreamHandler {
}
}
/**
* Passes the join complete message to the client, and marks the entities joining as successful.
* @param channelHandlerContext
* @param joinComplete
*/
private void completeJoin(ChannelHandlerContext channelHandlerContext, NetData.JoinCompleteMessage joinComplete) {
logger.info("Join complete received");
server.setClientId(joinComplete.getClientId());
@ -235,6 +265,11 @@ public class ClientConnectionHandler extends SimpleChannelUpstreamHandler {
joinStatus.setComplete();
}
/**
* Gets the server information and passes it to the client, while also checking if all required modules have been downloaded.
* @param channelHandlerContext
* @param message Passes the server information message to the function.
*/
private void receivedServerInfo(ChannelHandlerContext channelHandlerContext, NetData.ServerInfoMessage message) {
logger.info("Received server info");
((EngineTime) CoreRegistry.get(Time.class)).setGameTime(message.getTime());
@ -262,6 +297,10 @@ public class ClientConnectionHandler extends SimpleChannelUpstreamHandler {
}
}
/**
* Sends a join request from the client upstream to the server.
* @param channelHandlerContext
*/
private void sendJoin(ChannelHandlerContext channelHandlerContext) {
Config config = CoreRegistry.get(Config.class);
NetData.JoinMessage.Builder bldr = NetData.JoinMessage.newBuilder();
@ -274,6 +313,10 @@ public class ClientConnectionHandler extends SimpleChannelUpstreamHandler {
channelHandlerContext.getChannel().write(NetData.NetMessage.newBuilder().setJoin(bldr).build());
}
/**
* Gets the clients Join Status
* @return Returns join status.
*/
public JoinStatus getJoinStatus() {
synchronized (joinStatus) {
return joinStatus;

View File

@ -87,6 +87,11 @@ public class ClientHandshakeHandler extends SimpleChannelUpstreamHandler {
}
}
/**
* Process the handshake verification, checking that both the server and client have attempted it. If successful marks the channel as Authenticated.
* @param handshakeVerification
* @param ctx Channel Handler Context.
*/
private void processHandshakeVerification(NetData.HandshakeVerification handshakeVerification, ChannelHandlerContext ctx) {
logger.info("Received server verification");
if (serverHello == null || clientHello == null) {
@ -108,6 +113,11 @@ public class ClientHandshakeHandler extends SimpleChannelUpstreamHandler {
channelAuthenticated(ctx);
}
/**
* Generates a new secret key for a user and then decrypts the certificate into a byte array. Storing the certificate to the user ID.
* @param provisionIdentity
* @param ctx Channel Handler Context.
*/
private void processNewIdentity(NetData.ProvisionIdentity provisionIdentity, ChannelHandlerContext ctx) {
logger.info("Received identity from server");
if (!requestedCertificate) {
@ -167,12 +177,21 @@ public class ClientHandshakeHandler extends SimpleChannelUpstreamHandler {
}
}
/**
* Creates a new builder on the channel and sets join status.
* @param ctx Channel Handler Context.
*/
private void channelAuthenticated(ChannelHandlerContext ctx) {
ctx.getChannel().write(NetData.NetMessage.newBuilder()
.setServerInfoRequest(NetData.ServerInfoRequest.newBuilder()).build());
joinStatus.setCurrentActivity("Requesting server info");
}
/**
* Client checks to see if it received the server hello message, if so it processes it into a random key and the certificate.
* @param helloMessage Message from server to client.
* @param ctx Channel Handler Context.
*/
private void processServerHello(NetData.HandshakeHello helloMessage, ChannelHandlerContext ctx) {
if (serverHello == null) {
logger.info("Received Server Hello");
@ -205,6 +224,11 @@ public class ClientHandshakeHandler extends SimpleChannelUpstreamHandler {
}
/**
* Generates a client hello from clientRandom file, time, and the public client certificate. Sends the clients hello and certificate back to the server via network channel.
* @param helloMessage Message from server to client.
* @param ctx Channel Handler Context.
*/
private void sendCertificate(NetData.HandshakeHello helloMessage, ChannelHandlerContext ctx) {
logger.info("Sending client certificate");
PublicIdentityCertificate pubClientCert = identity.getPlayerPublicCertificate();
@ -225,6 +249,10 @@ public class ClientHandshakeHandler extends SimpleChannelUpstreamHandler {
.build());
}
/**
* Requests a new identity for a client if one doesn't already exist. Generated from the master secret key and server certificate.
* @param ctx Channel Handler Context.
*/
private void requestIdentity(ChannelHandlerContext ctx) {
logger.info("No existing identity, requesting one");

View File

@ -29,6 +29,10 @@ public class JoinStatusImpl implements JoinStatus {
public JoinStatusImpl() {
}
/**
* Function sets the Join status error message and sets the status to FAILED.
* @param errorMessage
*/
public JoinStatusImpl(String errorMessage) {
this.errorMessage = errorMessage;
status = Status.FAILED;
@ -44,6 +48,10 @@ public class JoinStatusImpl implements JoinStatus {
return currentActivity;
}
/**
* Sets the current activity.
* @param currentActivity
*/
public synchronized void setCurrentActivity(String currentActivity) {
this.currentActivity = currentActivity;
currentProgress.set(0);
@ -63,11 +71,18 @@ public class JoinStatusImpl implements JoinStatus {
return errorMessage;
}
/**
* Sets the current error message.
* @param errorMessage
*/
public synchronized void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
status = Status.FAILED;
}
/**
* Sets the Join Status as complete.
*/
public synchronized void setComplete() {
status = Status.COMPLETE;
}

View File

@ -37,6 +37,12 @@ public class LocalClient extends AbstractClient {
private Config config = CoreRegistry.get(Config.class);
/**
* Creates an entity for the new local client.
* @param preferredName Clients preferred name.
* @param color Clients preferred color.
* @param entityManager Entity manager for the clients entity creation.
*/
public LocalClient(String preferredName, Color color, EntityManager entityManager) {
createEntity(preferredName, color, entityManager);
}

View File

@ -136,6 +136,12 @@ public class NetClient extends AbstractClient implements WorldChangeListener {
private AtomicInteger sentBytes = new AtomicInteger();
private Color color;
/**
* Sets up a new net client with metrics, time, identity, and a world provider.
* @param channel
* @param networkSystem
* @param identity Publice certificate for the client.
*/
public NetClient(Channel channel, NetworkSystemImpl networkSystem, PublicIdentityCertificate identity) {
this.channel = channel;
metricSource = (NetMetricSource) channel.getPipeline().get(MetricRecordingHandler.NAME);

View File

@ -30,6 +30,7 @@ import org.terasology.engine.module.ModuleManager;
import org.terasology.engine.module.StandardModuleExtension;
import org.terasology.game.GameManifest;
import org.terasology.i18n.TranslationSystem;
import org.terasology.input.Keyboard;
import org.terasology.module.DependencyInfo;
import org.terasology.module.DependencyResolver;
import org.terasology.module.Module;
@ -45,6 +46,7 @@ import org.terasology.rendering.nui.animation.MenuAnimationSystems;
import org.terasology.rendering.nui.databinding.BindHelper;
import org.terasology.rendering.nui.databinding.Binding;
import org.terasology.rendering.nui.databinding.ReadOnlyBinding;
import org.terasology.rendering.nui.events.NUIKeyEvent;
import org.terasology.rendering.nui.itemRendering.StringTextRenderer;
import org.terasology.rendering.nui.layers.mainMenu.savedGames.GameInfo;
import org.terasology.rendering.nui.layers.mainMenu.savedGames.GameProvider;
@ -236,7 +238,7 @@ public class CreateGameScreen extends CoreScreenLayer {
WidgetUtil.trySubscribe(this, "close", button -> {
triggerBackAnimation();
// get back to main screen if no saved games
if (GameProvider.getSavedGames().isEmpty()) {
if (!isSavedGamesExist()) {
triggerBackAnimation();
}
});
@ -445,4 +447,21 @@ public class CreateGameScreen extends CoreScreenLayer {
public boolean isLowerLayerVisible() {
return false;
}
private boolean isSavedGamesExist() {
return !GameProvider.getSavedGames().isEmpty();
}
@Override
public boolean onKeyEvent(NUIKeyEvent event) {
if (event.isDown() && event.getKey() == Keyboard.Key.ESCAPE && isEscapeToCloseAllowed()) {
triggerBackAnimation();
if (!isSavedGamesExist()) {
// get back to main screen
triggerBackAnimation();
}
return true;
}
return false;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016 MovingBlocks
* Copyright 2018 MovingBlocks
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -46,6 +46,7 @@ import org.terasology.rendering.nui.widgets.UIList;
import org.terasology.utilities.Assets;
import org.terasology.utilities.FilesUtil;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.stream.Collectors;
@ -199,8 +200,27 @@ public class SelectGameScreen extends CoreScreenLayer {
}
private void loadGame(GameInfo item) {
if (loadingAsServer) {
Path blacklistPath = PathManager.getInstance().getHomePath().resolve("blacklist.json");
Path whitelistPath = PathManager.getInstance().getHomePath().resolve("whitelist.json");
if (!Files.exists(blacklistPath)) {
try {
Files.createFile(blacklistPath);
} catch (IOException e) {
logger.error("IO Exception on blacklist generation", e);
}
}
if (!Files.exists(whitelistPath)) {
try {
Files.createFile(whitelistPath);
} catch (IOException e) {
logger.error("IO Exception on whitelist generation", e);
}
}
}
try {
GameManifest manifest = item.getManifest();
config.getWorldGeneration().setDefaultSeed(manifest.getSeed());
config.getWorldGeneration().setWorldTitle(manifest.getTitle());
CoreRegistry.get(GameEngine.class).changeState(new StateLoading(manifest, (loadingAsServer) ? NetworkMode.DEDICATED_SERVER : NetworkMode.NONE));
@ -228,7 +248,7 @@ public class SelectGameScreen extends CoreScreenLayer {
TextureData textureData = null;
try {
textureData = AWTTextureFormat.convertToTextureData(item.getPreviewImage(), Texture.FilterMode.LINEAR);
} catch( IOException e ) {
} catch (IOException e) {
logger.error("Converting preview image to texture data {} failed", e);
}
texture = Assets.generateAsset(PREVIEW_IMAGE_URI, textureData, Texture.class);