diff --git a/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java b/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java index 630f9c6..e85e2f0 100644 --- a/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java +++ b/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java @@ -39,10 +39,6 @@ public class ProgressiaLauncher { GUI.addTopLayer(new LayerTitle("Title")); } - public static void play() { - proxy.setupServer(); - } - private static void setupCrashReports() { // Context providers CrashReports.registerProvider(new OSContextProvider()); diff --git a/src/main/java/ru/windcorp/progressia/client/ClientProxy.java b/src/main/java/ru/windcorp/progressia/client/ClientProxy.java index ffb9bd7..ac9d61f 100644 --- a/src/main/java/ru/windcorp/progressia/client/ClientProxy.java +++ b/src/main/java/ru/windcorp/progressia/client/ClientProxy.java @@ -30,7 +30,6 @@ import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram; import ru.windcorp.progressia.client.localization.Localizer; import ru.windcorp.progressia.common.resource.ResourceManager; import ru.windcorp.progressia.common.util.crash.CrashReports; -import ru.windcorp.progressia.server.ServerState; import ru.windcorp.progressia.test.TestContent; import ru.windcorp.progressia.test.TestMusicPlayer; @@ -62,10 +61,4 @@ public class ClientProxy implements Proxy { TestMusicPlayer.start(); } - - public void setupServer() { - ServerState.startServer(); - ClientState.connectToLocalServer(); - } - } diff --git a/src/main/java/ru/windcorp/progressia/server/PlayerManager.java b/src/main/java/ru/windcorp/progressia/server/PlayerManager.java index a7184e9..5e94784 100644 --- a/src/main/java/ru/windcorp/progressia/server/PlayerManager.java +++ b/src/main/java/ru/windcorp/progressia/server/PlayerManager.java @@ -15,21 +15,21 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server; +import glm.vec._3.Vec3; +import ru.windcorp.progressia.common.world.entity.EntityData; +import ru.windcorp.progressia.common.world.entity.EntityDataRegistry; +import ru.windcorp.progressia.server.comms.ClientPlayer; +import ru.windcorp.progressia.server.events.PlayerJoinedEvent; +import ru.windcorp.progressia.server.events.PlayerLeftEvent; +import ru.windcorp.progressia.test.TestContent; + import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import glm.vec._3.Vec3; -import ru.windcorp.progressia.common.util.crash.CrashReports; -import ru.windcorp.progressia.common.world.entity.EntityData; -import ru.windcorp.progressia.common.world.entity.EntityDataRegistry; -import ru.windcorp.progressia.server.events.PlayerJoinedEvent; -import ru.windcorp.progressia.server.events.PlayerLeftEvent; -import ru.windcorp.progressia.test.TestContent; - public class PlayerManager { private final Server server; @@ -48,36 +48,38 @@ public class PlayerManager { this.players.add(player); getServer().postEvent(new PlayerJoinedEvent.Immutable(getServer(), player)); } - + public void removePlayer(Player player) { + server.getWorld().getContainer().savePlayer(player, server); this.players.remove(player); getServer().postEvent(new PlayerLeftEvent.Immutable(getServer(), player)); } - public EntityData conjurePlayerEntity(String login) { - // TODO Live up to the name - if (TestContent.PLAYER_LOGIN.equals(login)) { - EntityData entity = spawnPlayerEntity(login); - return entity; - } else { - throw CrashReports.report(null, "Unknown login %s, javahorse stupid", login); + public Player conjurePlayer(ClientPlayer clientPlayer, String login) { + + Player player = getServer().getWorld().getContainer().loadPlayer(login, clientPlayer, getServer()); + if (player == null) { // create new player + EntityData entity = spawnPlayerEntity(clientPlayer, login); + player = new Player(entity, getServer(), clientPlayer); } + + getServer().getWorld().getData().addEntity(player.getEntity()); + + return player; } - private EntityData spawnPlayerEntity(String login) { + private EntityData spawnPlayerEntity(ClientPlayer clientPlayer, String login) { EntityData player = EntityDataRegistry.getInstance().create("Test:Player"); player.setEntityId(TestContent.PLAYER_ENTITY_ID); player.setPosition(getServer().getWorld().getGenerator().suggestSpawnLocation()); - + player.setUpVector(new Vec3(0, 0, 1)); player.setLookingAt(new Vec3(2, 1, 0)); - getServer().getWorld().getData().addEntity(player); - return player; } - + public Object getMutex() { return players; } diff --git a/src/main/java/ru/windcorp/progressia/server/ServerState.java b/src/main/java/ru/windcorp/progressia/server/ServerState.java index c38f21b..79844cb 100644 --- a/src/main/java/ru/windcorp/progressia/server/ServerState.java +++ b/src/main/java/ru/windcorp/progressia/server/ServerState.java @@ -18,6 +18,7 @@ package ru.windcorp.progressia.server; +import java.io.IOException; import java.nio.file.Paths; import java.util.function.Function; @@ -39,7 +40,7 @@ public class ServerState { ServerState.instance = instance; } - public static void startServer() { + public static void startServer() throws IOException { Function generator = new TestGenerationConfig().getGenerator(); WorldContainer container = new RegionFormat("Test:Region").create(Paths.get("tmp_world")); diff --git a/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java b/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java index fc55cbb..095c403 100644 --- a/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java +++ b/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java @@ -80,12 +80,11 @@ public class ClientManager { setGravityModelPacket.set(getServer().getWorld().getData().getGravityModel()); client.sendPacket(setGravityModelPacket); - EntityData entity = getServer().getPlayerManager().conjurePlayerEntity(login); - Player player = new Player(entity, getServer(), client); + Player player = getServer().getPlayerManager().conjurePlayer(client, login); getServer().getPlayerManager().addPlayer(player); PacketSetLocalPlayer packet = new PacketSetLocalPlayer(); - packet.set(entity.getEntityId()); + packet.set(player.getEntity().getEntityId()); client.sendPacket(packet); } diff --git a/src/main/java/ru/windcorp/progressia/server/world/io/WorldContainer.java b/src/main/java/ru/windcorp/progressia/server/world/io/WorldContainer.java index 07aa7b5..42451ad 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/io/WorldContainer.java +++ b/src/main/java/ru/windcorp/progressia/server/world/io/WorldContainer.java @@ -17,21 +17,27 @@ */ package ru.windcorp.progressia.server.world.io; -import java.nio.file.Path; - import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.common.world.DefaultChunkData; import ru.windcorp.progressia.common.world.DefaultWorldData; +import ru.windcorp.progressia.server.Player; import ru.windcorp.progressia.server.Server; +import ru.windcorp.progressia.server.comms.ClientPlayer; + +import java.nio.file.Path; public interface WorldContainer { - + Path getPath(); - + DefaultChunkData load(Vec3i position, DefaultWorldData world, Server server); - + void save(DefaultChunkData chunk, DefaultWorldData world, Server server); - + + Player loadPlayer(String login, ClientPlayer clientPlayer, Server server); + + void savePlayer(Player player, Server server); + void close(); } diff --git a/src/main/java/ru/windcorp/progressia/server/world/io/WorldContainerFormat.java b/src/main/java/ru/windcorp/progressia/server/world/io/WorldContainerFormat.java index 9c8e0c8..4c89621 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/io/WorldContainerFormat.java +++ b/src/main/java/ru/windcorp/progressia/server/world/io/WorldContainerFormat.java @@ -17,6 +17,7 @@ */ package ru.windcorp.progressia.server.world.io; +import java.io.IOException; import java.nio.file.Path; import ru.windcorp.progressia.common.util.namespaces.Namespaced; @@ -27,6 +28,6 @@ public abstract class WorldContainerFormat extends Namespaced { super(id); } - public abstract WorldContainer create(Path directory); + public abstract WorldContainer create(Path directory) throws IOException; } diff --git a/src/main/java/ru/windcorp/progressia/test/LayerTitle.java b/src/main/java/ru/windcorp/progressia/test/LayerTitle.java index d2ba139..e497252 100644 --- a/src/main/java/ru/windcorp/progressia/test/LayerTitle.java +++ b/src/main/java/ru/windcorp/progressia/test/LayerTitle.java @@ -1,15 +1,20 @@ package ru.windcorp.progressia.test; -import ru.windcorp.progressia.ProgressiaLauncher; +import ru.windcorp.progressia.client.ClientState; import ru.windcorp.progressia.client.graphics.Colors; import ru.windcorp.progressia.client.graphics.GUI; import ru.windcorp.progressia.client.graphics.font.Font; +import ru.windcorp.progressia.client.graphics.gui.BasicButton; import ru.windcorp.progressia.client.graphics.gui.Button; import ru.windcorp.progressia.client.graphics.gui.GUILayer; import ru.windcorp.progressia.client.graphics.gui.Label; import ru.windcorp.progressia.client.graphics.gui.layout.LayoutVertical; import ru.windcorp.progressia.client.localization.MutableString; import ru.windcorp.progressia.client.localization.MutableStringLocalized; +import ru.windcorp.progressia.common.util.crash.CrashReports; +import ru.windcorp.progressia.server.ServerState; + +import java.io.IOException; public class LayerTitle extends GUILayer { @@ -22,11 +27,7 @@ public class LayerTitle extends GUILayer { Font buttonFont = titleFont; MutableString playText = new MutableStringLocalized("Layer" + name + ".Play"); - getRoot().addChild(new Button(name + ".Play", new Label(name + ".Play", buttonFont, playText)).addAction(b -> { - GUI.removeLayer(this); - - ProgressiaLauncher.play(); - })); + getRoot().addChild(new Button(name + ".Play", new Label(name + ".Play", buttonFont, playText)).addAction(this::startGame)); MutableString quitText = new MutableStringLocalized("Layer" + name + ".Quit"); getRoot().addChild(new Button(name + "Quit", new Label(name + ".Quit", buttonFont, quitText)).addAction(b -> { @@ -34,4 +35,14 @@ public class LayerTitle extends GUILayer { })); } + private void startGame(BasicButton basicButton) { + GUI.removeLayer(this); + try { + ServerState.startServer(); + ClientState.connectToLocalServer(); + } catch (IOException e) { + throw CrashReports.report(e, "Problem with loading server"); + } + } + } diff --git a/src/main/java/ru/windcorp/progressia/test/region/RegionFormat.java b/src/main/java/ru/windcorp/progressia/test/region/RegionFormat.java index 85d1bbe..ad67074 100644 --- a/src/main/java/ru/windcorp/progressia/test/region/RegionFormat.java +++ b/src/main/java/ru/windcorp/progressia/test/region/RegionFormat.java @@ -17,6 +17,7 @@ */ package ru.windcorp.progressia.test.region; +import java.io.IOException; import java.nio.file.Path; import ru.windcorp.progressia.server.world.io.WorldContainer; @@ -29,7 +30,7 @@ public class RegionFormat extends WorldContainerFormat { } @Override - public WorldContainer create(Path directory) { + public WorldContainer create(Path directory) throws IOException { return new TestWorldDiskIO(directory); } diff --git a/src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java b/src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java index f8b015f..2bc3f50 100644 --- a/src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java +++ b/src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java @@ -18,31 +18,37 @@ package ru.windcorp.progressia.test.region; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.file.Files; -import java.nio.file.Path; +import glm.vec._3.i.Vec3i; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; - -import glm.vec._3.i.Vec3i; +import ru.windcorp.progressia.common.state.IOContext; import ru.windcorp.progressia.common.util.crash.CrashReports; -import ru.windcorp.progressia.common.world.DefaultChunkData; import ru.windcorp.progressia.common.world.Coordinates; import ru.windcorp.progressia.common.world.DecodingException; +import ru.windcorp.progressia.common.world.DefaultChunkData; import ru.windcorp.progressia.common.world.DefaultWorldData; +import ru.windcorp.progressia.common.world.entity.EntityData; +import ru.windcorp.progressia.common.world.entity.EntityDataRegistry; import ru.windcorp.progressia.common.world.generic.ChunkMap; import ru.windcorp.progressia.common.world.generic.ChunkMaps; +import ru.windcorp.progressia.server.Player; import ru.windcorp.progressia.server.Server; +import ru.windcorp.progressia.server.comms.ClientPlayer; import ru.windcorp.progressia.server.world.io.WorldContainer; +import ru.windcorp.progressia.test.TestContent; + +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Path; public class TestWorldDiskIO implements WorldContainer { private static final boolean ENABLE = true; - private static final String FILE_NAME_FORMAT = "region_%d_%d_%d.progressia_region"; + private static final String REGION_FOLDER_NAME = "regions"; + private static final String PLAYERS_FOLDER_NAME = "players"; + private static final String REGION_NAME_FORMAT = REGION_FOLDER_NAME + "/" + "region_%d_%d_%d.progressia_region"; + private static final String PLAYER_NAME_FORMAT = PLAYERS_FOLDER_NAME + "/" + "%s.progressia_player"; private static final int BITS_IN_CHUNK_COORDS = 4; public static final int REGION_DIAMETER = 1 << BITS_IN_CHUNK_COORDS; @@ -60,8 +66,12 @@ public class TestWorldDiskIO implements WorldContainer { private final Path path; private final ChunkMap regions = ChunkMaps.newHashMap(); - public TestWorldDiskIO(Path path) { + public TestWorldDiskIO(Path path) throws IOException { this.path = path; + + Files.createDirectories(getPath()); + Files.createDirectories(getPath().resolve(REGION_FOLDER_NAME)); + Files.createDirectories(getPath().resolve(PLAYERS_FOLDER_NAME)); } @Override @@ -104,11 +114,53 @@ public class TestWorldDiskIO implements WorldContainer { } } - private Region getRegion(Vec3i position, boolean createIfMissing) throws IOException { - if (regions.isEmpty()) { - Files.createDirectories(getPath()); + @Override + public Player loadPlayer(String login, ClientPlayer clientPlayer, Server server) { + + Path path = getPlayerPath(login); + if (!Files.exists(path)) { + LOG.debug("Could not load player {} because file {} does not exist", login, path); + return null; } + EntityData player = EntityDataRegistry.getInstance().create("Test:Player"); + try ( + DataInputStream dataInputStream = new DataInputStream( + new BufferedInputStream( + Files.newInputStream( + getPlayerPath(login) + ) + ) + ) + ) { + player.read(dataInputStream, IOContext.SAVE); + player.setEntityId(TestContent.PLAYER_ENTITY_ID); + return new Player(player, server, clientPlayer); + } catch (IOException ioException) { + throw CrashReports.report(ioException, "Could not load player data: " + login); + } + } + + @Override + public void savePlayer(Player player, Server server) { + Path path = getPlayerPath(player.getLogin()); + try ( + DataOutputStream dataOutputStream = new DataOutputStream( + new BufferedOutputStream( + Files.newOutputStream(path) + ) + ) + ) { + player.getEntity(). + + write(dataOutputStream, IOContext.SAVE); + } catch (IOException ioException) { + throw CrashReports.report(ioException, "Could not save player %s data in file ", player.getLogin(), path); + } + } + + private Region getRegion(Vec3i position, boolean createIfMissing) throws IOException { + Vec3i regionCoords = getRegionCoords(position); Region region = regions.get(regionCoords); @@ -151,11 +203,11 @@ public class TestWorldDiskIO implements WorldContainer { public Path getPath() { return path; } - + private Path getRegionPath(Vec3i regionPos) { return getPath().resolve( String.format( - FILE_NAME_FORMAT, + REGION_NAME_FORMAT, regionPos.x, regionPos.y, regionPos.z @@ -163,6 +215,15 @@ public class TestWorldDiskIO implements WorldContainer { ); } + private Path getPlayerPath(String login) { + return getPath().resolve( + String.format( + PLAYER_NAME_FORMAT, + login + ) + ); + } + @Override public void close() { try { @@ -170,16 +231,16 @@ public class TestWorldDiskIO implements WorldContainer { region.close(); } } catch (IOException e) { - CrashReports.report(e, "Could not close region files"); + throw CrashReports.report(e, "Could not close region files"); } } - + private static void debug(String message, Vec3i vector) { if (LOG.isDebugEnabled()) { LOG.debug(message, vector.x, vector.y, vector.z); } } - + private static void warn(String message, Vec3i vector) { LOG.warn(message, vector.x, vector.y, vector.z); }