Added player saving and loading from disk
This commit is contained in:
		| @@ -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()); | ||||
|   | ||||
| @@ -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(); | ||||
| 	} | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -18,18 +18,18 @@ | ||||
|  | ||||
| package ru.windcorp.progressia.server; | ||||
|  | ||||
| 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.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; | ||||
|  | ||||
| public class PlayerManager { | ||||
|  | ||||
| 	private final Server server; | ||||
| @@ -50,21 +50,25 @@ public class PlayerManager { | ||||
| 	} | ||||
|  | ||||
| 	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); | ||||
| @@ -73,8 +77,6 @@ public class PlayerManager { | ||||
| 		player.setUpVector(new Vec3(0, 0, 1)); | ||||
| 		player.setLookingAt(new Vec3(2, 1, 0)); | ||||
|  | ||||
| 		getServer().getWorld().getData().addEntity(player); | ||||
|  | ||||
| 		return player; | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -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<Server, WorldGenerator> generator = new TestGenerationConfig().getGenerator(); | ||||
| 		WorldContainer container = new RegionFormat("Test:Region").create(Paths.get("tmp_world")); | ||||
|   | ||||
| @@ -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); | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -17,12 +17,14 @@ | ||||
|  */ | ||||
| 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 { | ||||
|  | ||||
| @@ -32,6 +34,10 @@ public interface WorldContainer { | ||||
|  | ||||
| 	void save(DefaultChunkData chunk, DefaultWorldData world, Server server); | ||||
|  | ||||
| 	Player loadPlayer(String login, ClientPlayer clientPlayer, Server server); | ||||
|  | ||||
| 	void savePlayer(Player player, Server server); | ||||
|  | ||||
| 	void close(); | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -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; | ||||
| 	 | ||||
| } | ||||
|   | ||||
| @@ -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"); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -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); | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -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<Region> 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); | ||||
| @@ -155,7 +207,7 @@ public class TestWorldDiskIO implements WorldContainer { | ||||
| 	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,7 +231,7 @@ 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"); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user