From 65ecd1b5fc527822636931bc84e03fca379e5b15 Mon Sep 17 00:00:00 2001 From: Major- Date: Tue, 3 Mar 2015 07:25:20 +0000 Subject: [PATCH] Merge PlayerSaver and PlayerLoader into PlayerSerializer. --- data/login.xml | 3 +- src/org/apollo/io/player/BinaryFileUtils.java | 56 ++++++ ...oader.java => BinaryPlayerSerializer.java} | 170 +++++++++++++++--- ...Loader.java => DummyPlayerSerializer.java} | 22 ++- .../io/player/JdbcPlayerSerializer.java | 23 +++ src/org/apollo/io/player/PlayerLoader.java | 22 --- .../io/player/PlayerLoaderResponse.java | 9 +- src/org/apollo/io/player/PlayerSaver.java | 21 --- .../apollo/io/player/PlayerSerializer.java | 38 ++++ .../io/player/impl/BinaryPlayerSaver.java | 126 ------------- .../io/player/impl/BinaryPlayerUtil.java | 46 ----- .../io/player/impl/DiscardPlayerSaver.java | 18 -- .../io/player/impl/JdbcPlayerLoader.java | 19 -- .../io/player/impl/JdbcPlayerSaver.java | 18 -- .../apollo/io/player/impl/package-info.java | 4 - src/org/apollo/login/LoginService.java | 39 ++-- src/org/apollo/login/PlayerLoaderWorker.java | 10 +- src/org/apollo/login/PlayerSaverWorker.java | 6 +- 18 files changed, 300 insertions(+), 350 deletions(-) create mode 100644 src/org/apollo/io/player/BinaryFileUtils.java rename src/org/apollo/io/player/{impl/BinaryPlayerLoader.java => BinaryPlayerSerializer.java} (52%) rename src/org/apollo/io/player/{impl/DummyPlayerLoader.java => DummyPlayerSerializer.java} (52%) create mode 100644 src/org/apollo/io/player/JdbcPlayerSerializer.java delete mode 100644 src/org/apollo/io/player/PlayerLoader.java delete mode 100644 src/org/apollo/io/player/PlayerSaver.java create mode 100644 src/org/apollo/io/player/PlayerSerializer.java delete mode 100644 src/org/apollo/io/player/impl/BinaryPlayerSaver.java delete mode 100644 src/org/apollo/io/player/impl/BinaryPlayerUtil.java delete mode 100644 src/org/apollo/io/player/impl/DiscardPlayerSaver.java delete mode 100644 src/org/apollo/io/player/impl/JdbcPlayerLoader.java delete mode 100644 src/org/apollo/io/player/impl/JdbcPlayerSaver.java delete mode 100644 src/org/apollo/io/player/impl/package-info.java diff --git a/data/login.xml b/data/login.xml index 27f2d6fa..c7f0371a 100644 --- a/data/login.xml +++ b/data/login.xml @@ -1,4 +1,3 @@ - org.apollo.io.player.impl.DummyPlayerLoader - org.apollo.io.player.impl.DiscardPlayerSaver + org.apollo.io.player.DummyPlayerSerializer \ No newline at end of file diff --git a/src/org/apollo/io/player/BinaryFileUtils.java b/src/org/apollo/io/player/BinaryFileUtils.java new file mode 100644 index 00000000..00c747a4 --- /dev/null +++ b/src/org/apollo/io/player/BinaryFileUtils.java @@ -0,0 +1,56 @@ +package org.apollo.io.player; + +import java.io.File; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.apollo.util.NameUtil; + +/** + * A utility class with common functionality used by the binary player loader/ savers. + * + * @author Graham + * @author Major + */ +public final class BinaryFileUtils { + + /** + * The Path to the saved games directory. + */ + private static final Path SAVED_GAMES_DIRECTORY = Paths.get("data/savedGames"); + + /** + * Creates the saved games directory if it does not exist. + */ + static { + try { + if (!Files.exists(SAVED_GAMES_DIRECTORY)) { + Files.createDirectory(SAVED_GAMES_DIRECTORY); + } + } catch (IOException e) { + throw new UncheckedIOException("Error creating saved games directory.", e); + } + } + + /** + * Gets the save {@link File} for the specified player. + * + * @param username The username of the player. + * @return The file. + */ + public static Path getFile(String username) { + String filtered = NameUtil.decodeBase37(NameUtil.encodeBase37(username)); + return SAVED_GAMES_DIRECTORY.resolve(filtered + ".dat"); + } + + /** + * Sole private constructor to prevent instantiation. + */ + private BinaryFileUtils() { + + } + +} \ No newline at end of file diff --git a/src/org/apollo/io/player/impl/BinaryPlayerLoader.java b/src/org/apollo/io/player/BinaryPlayerSerializer.java similarity index 52% rename from src/org/apollo/io/player/impl/BinaryPlayerLoader.java rename to src/org/apollo/io/player/BinaryPlayerSerializer.java index 19d77500..6ae08b98 100644 --- a/src/org/apollo/io/player/impl/BinaryPlayerLoader.java +++ b/src/org/apollo/io/player/BinaryPlayerSerializer.java @@ -1,13 +1,20 @@ -package org.apollo.io.player.impl; +package org.apollo.io.player; +import java.io.BufferedInputStream; import java.io.DataInputStream; +import java.io.DataOutputStream; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; import org.apollo.game.model.Appearance; import org.apollo.game.model.Item; @@ -16,6 +23,8 @@ import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Skill; import org.apollo.game.model.entity.SkillSet; import org.apollo.game.model.entity.attr.Attribute; +import org.apollo.game.model.entity.attr.AttributeMap; +import org.apollo.game.model.entity.attr.AttributePersistence; import org.apollo.game.model.entity.attr.AttributeType; import org.apollo.game.model.entity.attr.BooleanAttribute; import org.apollo.game.model.entity.attr.NumericalAttribute; @@ -26,8 +35,6 @@ import org.apollo.game.model.entity.setting.PrivacyState; import org.apollo.game.model.entity.setting.PrivilegeLevel; import org.apollo.game.model.entity.setting.ScreenBrightness; import org.apollo.game.model.inv.Inventory; -import org.apollo.io.player.PlayerLoader; -import org.apollo.io.player.PlayerLoaderResponse; import org.apollo.net.codec.login.LoginConstants; import org.apollo.security.PlayerCredentials; import org.apollo.util.NameUtil; @@ -36,28 +43,39 @@ import org.apollo.util.StreamUtil; import com.lambdaworks.crypto.SCryptUtil; /** - * A {@link PlayerLoader} implementation that loads data from a binary file. + * A {@link PlayerSerializer} implementation that uses a binary file to store player data. * * @author Graham + * @author Major */ -public final class BinaryPlayerLoader implements PlayerLoader { +public final class BinaryPlayerSerializer implements PlayerSerializer { /** - * The default spawn position. + * The Path to the saved games directory. */ - private static final Position SPAWN_POSITION = new Position(3093, 3104); + private static final Path SAVED_GAMES_DIRECTORY = Paths.get("data/savedGames"); + + static { + try { + if (!Files.exists(SAVED_GAMES_DIRECTORY)) { + Files.createDirectory(SAVED_GAMES_DIRECTORY); + } + } catch (IOException e) { + throw new UncheckedIOException("Error creating saved games directory.", e); + } + } @Override public PlayerLoaderResponse loadPlayer(PlayerCredentials credentials) throws IOException { - File file = BinaryPlayerUtil.getFile(credentials.getUsername()); - if (!file.exists()) { - Player player = new Player(credentials, SPAWN_POSITION); - player.getBank().add(995, 25); // 25 coins + Path path = getFile(credentials.getUsername()); + if (!Files.exists(path)) { + Player player = new Player(credentials, TUTORIAL_ISLAND_SPAWN); + credentials.setPassword(SCryptUtil.scrypt(credentials.getPassword(), 16384, 8, 1)); return new PlayerLoaderResponse(LoginConstants.STATUS_OK, player); } - try (DataInputStream in = new DataInputStream(new FileInputStream(file))) { + try (DataInputStream in = new DataInputStream(new BufferedInputStream(Files.newInputStream(path)))) { String name = StreamUtil.readString(in); String password = StreamUtil.readString(in); @@ -67,37 +85,35 @@ public final class BinaryPlayerLoader implements PlayerLoader { credentials.setPassword(password); // Update password to the hashed one. - PrivilegeLevel privilegeLevel = PrivilegeLevel.valueOf(in.readByte()); + PrivilegeLevel privilege = PrivilegeLevel.valueOf(in.readByte()); MembershipStatus members = MembershipStatus.valueOf(in.readByte()); PrivacyState chatPrivacy = PrivacyState.valueOf(in.readByte(), true); PrivacyState friendPrivacy = PrivacyState.valueOf(in.readByte(), false); PrivacyState tradePrivacy = PrivacyState.valueOf(in.readByte(), false); - int runEnergy = in.readByte(); ScreenBrightness brightness = ScreenBrightness.valueOf(in.readByte()); int x = in.readUnsignedShort(); int y = in.readUnsignedShort(); int height = in.readUnsignedByte(); - int genderIntValue = in.readUnsignedByte(); - Gender gender = genderIntValue == Gender.MALE.toInteger() ? Gender.MALE : Gender.FEMALE; + Gender gender = (in.readUnsignedByte() == Gender.MALE.toInteger()) ? Gender.MALE : Gender.FEMALE; int[] style = new int[7]; - for (int i = 0; i < style.length; i++) { - style[i] = in.readUnsignedByte(); + for (int slot = 0; slot < style.length; slot++) { + style[slot] = in.readUnsignedByte(); } + int[] colors = new int[5]; - for (int i = 0; i < colors.length; i++) { - colors[i] = in.readUnsignedByte(); + for (int slot = 0; slot < colors.length; slot++) { + colors[slot] = in.readUnsignedByte(); } Player player = new Player(credentials, new Position(x, y, height)); - player.setPrivilegeLevel(privilegeLevel); + player.setPrivilegeLevel(privilege); player.setMembers(members); player.setChatPrivacy(chatPrivacy); player.setFriendPrivacy(friendPrivacy); player.setTradePrivacy(tradePrivacy); - player.setRunEnergy(runEnergy); player.setScreenBrightness(brightness); player.setAppearance(new Appearance(gender, style, colors)); @@ -141,6 +157,87 @@ public final class BinaryPlayerLoader implements PlayerLoader { } } + @Override + public void savePlayer(Player player) throws IOException { + Path file = getFile(player.getUsername()); + + try (DataOutputStream out = new DataOutputStream(Files.newOutputStream(file))) { + StreamUtil.writeString(out, player.getUsername()); + StreamUtil.writeString(out, player.getCredentials().getPassword()); + out.writeByte(player.getPrivilegeLevel().toInteger()); + out.writeByte(player.getMembershipStatus().getValue()); + + out.writeByte(player.getChatPrivacy().toInteger(true)); + out.writeByte(player.getFriendPrivacy().toInteger(false)); + out.writeByte(player.getTradePrivacy().toInteger(false)); + out.writeByte(player.getScreenBrightness().toInteger()); + + Position position = player.getPosition(); + out.writeShort(position.getX()); + out.writeShort(position.getY()); + out.writeByte(position.getHeight()); + + Appearance appearance = player.getAppearance(); + out.writeByte(appearance.getGender().toInteger()); + int[] style = appearance.getStyle(); + for (int element : style) { + out.writeByte(element); + } + int[] colors = appearance.getColors(); + for (int color : colors) { + out.writeByte(color); + } + + writeInventory(out, player.getInventory()); + writeInventory(out, player.getEquipment()); + writeInventory(out, player.getBank()); + + SkillSet skills = player.getSkillSet(); + out.writeByte(skills.size()); + for (int id = 0; id < skills.size(); id++) { + Skill skill = skills.getSkill(id); + out.writeByte(skill.getCurrentLevel()); + out.writeDouble(skill.getExperience()); + } + + List usernames = player.getFriendUsernames(); + out.writeByte(usernames.size()); + for (String username : usernames) { + out.writeLong(NameUtil.encodeBase37(username)); + } + + usernames = player.getIgnoredUsernames(); + out.writeByte(usernames.size()); + for (String username : usernames) { + out.writeLong(NameUtil.encodeBase37(username)); + } + + Set>> attributes = player.getAttributes().entrySet(); + attributes.removeIf(e -> AttributeMap.getDefinition(e.getKey()).getPersistence() != AttributePersistence.PERSISTENT); + out.writeInt(attributes.size()); + + for (Entry> entry : attributes) { + String name = entry.getKey(); + StreamUtil.writeString(out, name); + + Attribute attribute = entry.getValue(); + out.writeByte(attribute.getType().getValue()); + out.write(attribute.encode()); + } + } + } + + /** + * Gets the save {@link File} for the specified player. + * + * @param username The username of the player. + * @return The file. + */ + private Path getFile(String username) { + String filtered = NameUtil.decodeBase37(NameUtil.encodeBase37(username)); + return SAVED_GAMES_DIRECTORY.resolve(filtered + ".dat"); + } + /** * Reads the player's {@link Attribute}s. * @@ -148,7 +245,7 @@ public final class BinaryPlayerLoader implements PlayerLoader { * @return The {@link Map} of attribute names to attributes. * @throws IOException If there is an error reading from the stream. */ - private static Map> readAttributes(DataInputStream in) throws IOException { + private Map> readAttributes(DataInputStream in) throws IOException { int count = in.readInt(); Map> attributes = new HashMap<>(count); @@ -187,7 +284,7 @@ public final class BinaryPlayerLoader implements PlayerLoader { * @param inventory The inventory. * @throws IOException If an I/O error occurs. */ - private static void readInventory(DataInputStream in, Inventory inventory) throws IOException { + private void readInventory(DataInputStream in, Inventory inventory) throws IOException { int capacity = in.readUnsignedShort(); inventory.stopFiringEvents(); @@ -206,4 +303,27 @@ public final class BinaryPlayerLoader implements PlayerLoader { } } + /** + * Writes an inventory to the specified output stream. + * + * @param out The output stream. + * @param inventory The inventory. + * @throws IOException If an I/O error occurs. + */ + private void writeInventory(DataOutputStream out, Inventory inventory) throws IOException { + int capacity = inventory.capacity(); + out.writeShort(capacity); + + for (int slot = 0; slot < capacity; slot++) { + Item item = inventory.get(slot); + if (item != null) { + out.writeShort(item.getId() + 1); + out.writeInt(item.getAmount()); + } else { + out.writeShort(0); + out.writeInt(0); + } + } + } + } \ No newline at end of file diff --git a/src/org/apollo/io/player/impl/DummyPlayerLoader.java b/src/org/apollo/io/player/DummyPlayerSerializer.java similarity index 52% rename from src/org/apollo/io/player/impl/DummyPlayerLoader.java rename to src/org/apollo/io/player/DummyPlayerSerializer.java index 83b0aedf..5466f385 100644 --- a/src/org/apollo/io/player/impl/DummyPlayerLoader.java +++ b/src/org/apollo/io/player/DummyPlayerSerializer.java @@ -1,35 +1,33 @@ -package org.apollo.io.player.impl; +package org.apollo.io.player; -import org.apollo.game.model.Position; import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.setting.MembershipStatus; import org.apollo.game.model.entity.setting.PrivilegeLevel; -import org.apollo.io.player.PlayerLoader; -import org.apollo.io.player.PlayerLoaderResponse; import org.apollo.net.codec.login.LoginConstants; import org.apollo.security.PlayerCredentials; /** - * A dummy {@link PlayerLoader} implementation used for testing purposes. + * A {@link PlayerSerializer} that saves no data and returns an administrator member account, ideal for debugging. * * @author Graham + * @author Major */ -public final class DummyPlayerLoader implements PlayerLoader { - - /** - * The default spawn position for players loaded by this loader. - */ - private static final Position DEFAULT_POSITION = new Position(3093, 3104); +public final class DummyPlayerSerializer implements PlayerSerializer { @Override public PlayerLoaderResponse loadPlayer(PlayerCredentials credentials) { int status = LoginConstants.STATUS_OK; - Player player = new Player(credentials, DEFAULT_POSITION); + Player player = new Player(credentials, TUTORIAL_ISLAND_SPAWN); player.setPrivilegeLevel(PrivilegeLevel.ADMINISTRATOR); player.setMembers(MembershipStatus.PAID); return new PlayerLoaderResponse(status, player); } + @Override + public void savePlayer(Player player) { + /* discard player */ + } + } \ No newline at end of file diff --git a/src/org/apollo/io/player/JdbcPlayerSerializer.java b/src/org/apollo/io/player/JdbcPlayerSerializer.java new file mode 100644 index 00000000..c8e48cf0 --- /dev/null +++ b/src/org/apollo/io/player/JdbcPlayerSerializer.java @@ -0,0 +1,23 @@ +package org.apollo.io.player; + +import org.apollo.game.model.entity.Player; +import org.apollo.security.PlayerCredentials; + +/** + * A {@link PlayerSerializer} that utilises {@code JDBC} to communicate with an SQL database containing player data. + * + * @author Major + */ +public final class JdbcPlayerSerializer implements PlayerSerializer { + + @Override + public void savePlayer(Player player) throws Exception { + throw new UnsupportedOperationException("JDBC saving is not supported at this time."); + } + + @Override + public PlayerLoaderResponse loadPlayer(PlayerCredentials credentials) throws Exception { + throw new UnsupportedOperationException("JDBC loading is not supported at this time."); + } + +} \ No newline at end of file diff --git a/src/org/apollo/io/player/PlayerLoader.java b/src/org/apollo/io/player/PlayerLoader.java deleted file mode 100644 index ff14e622..00000000 --- a/src/org/apollo/io/player/PlayerLoader.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.apollo.io.player; - -import org.apollo.security.PlayerCredentials; - -/** - * An interface which may be extended by others which are capable of loading players. For example, implementations might - * include text-based, binary and SQL loaders. - * - * @author Graham - */ -public interface PlayerLoader { - - /** - * Loads a player. - * - * @param credentials The player's credentials. - * @return The {@link PlayerLoaderResponse}. - * @throws Exception If an error occurs. - */ - public PlayerLoaderResponse loadPlayer(PlayerCredentials credentials) throws Exception; - -} \ No newline at end of file diff --git a/src/org/apollo/io/player/PlayerLoaderResponse.java b/src/org/apollo/io/player/PlayerLoaderResponse.java index 69e6541b..6f6bc2b6 100644 --- a/src/org/apollo/io/player/PlayerLoaderResponse.java +++ b/src/org/apollo/io/player/PlayerLoaderResponse.java @@ -8,9 +8,10 @@ import org.apollo.net.codec.login.LoginConstants; import com.google.common.base.Preconditions; /** - * A response for the {@link PlayerLoader#loadPlayer(org.apollo.security.PlayerCredentials)} call. + * A response for the {@link PlayerSerializer#loadPlayer} call. * * @author Graham + * @author Major */ public final class PlayerLoaderResponse { @@ -32,7 +33,8 @@ public final class PlayerLoaderResponse { * {@link LoginConstants#STATUS_RECONNECTION_OK}. */ public PlayerLoaderResponse(int status) { - Preconditions.checkArgument(status != LoginConstants.STATUS_OK && status != LoginConstants.STATUS_RECONNECTION_OK, "Player required for this status code."); + Preconditions.checkArgument(status != LoginConstants.STATUS_OK && status != LoginConstants.STATUS_RECONNECTION_OK, + "Player required for this status code."); this.status = status; player = Optional.empty(); } @@ -46,7 +48,8 @@ public final class PlayerLoaderResponse { * @throws NullPointerException If the specified player is null. */ public PlayerLoaderResponse(int status, Player player) { - Preconditions.checkArgument(status == LoginConstants.STATUS_OK || status == LoginConstants.STATUS_RECONNECTION_OK, "Player not required for this status code."); + Preconditions.checkArgument(status == LoginConstants.STATUS_OK || status == LoginConstants.STATUS_RECONNECTION_OK, + "Player not required for this status code."); this.status = status; this.player = Optional.of(player); } diff --git a/src/org/apollo/io/player/PlayerSaver.java b/src/org/apollo/io/player/PlayerSaver.java deleted file mode 100644 index 1a2def5d..00000000 --- a/src/org/apollo/io/player/PlayerSaver.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.apollo.io.player; - -import org.apollo.game.model.entity.Player; - -/** - * An interface which may be implemented by others which are capable of saving players. For example, implementations - * might include text-based, binary and SQL savers. - * - * @author Graham - */ -public interface PlayerSaver { - - /** - * Saves a player. - * - * @param player The player to save. - * @throws Exception If an error occurs. - */ - public void savePlayer(Player player) throws Exception; - -} \ No newline at end of file diff --git a/src/org/apollo/io/player/PlayerSerializer.java b/src/org/apollo/io/player/PlayerSerializer.java new file mode 100644 index 00000000..4d246a74 --- /dev/null +++ b/src/org/apollo/io/player/PlayerSerializer.java @@ -0,0 +1,38 @@ +package org.apollo.io.player; + +import org.apollo.game.model.Position; +import org.apollo.game.model.entity.Player; +import org.apollo.security.PlayerCredentials; + +/** + * An interface which may be implemented by others which are capable of serializing and deserializing players. For + * example, implementations might include text-based, binary and SQL serializers. + * + * @author Graham + * @author Major + */ +public interface PlayerSerializer { + + /** + * The spawn point for Players, on Tutorial Island. + */ + Position TUTORIAL_ISLAND_SPAWN = new Position(3093, 3104); + + /** + * Loads a {@link Player}. + * + * @param credentials The {@link PlayerCredentials}. + * @return The {@link PlayerLoaderResponse}. + * @throws Exception If an error occurs. + */ + public PlayerLoaderResponse loadPlayer(PlayerCredentials credentials) throws Exception; + + /** + * Saves a {@link Player}. + * + * @param player The Player to save. + * @throws Exception If an error occurs. + */ + public void savePlayer(Player player) throws Exception; + +} \ No newline at end of file diff --git a/src/org/apollo/io/player/impl/BinaryPlayerSaver.java b/src/org/apollo/io/player/impl/BinaryPlayerSaver.java deleted file mode 100644 index 5fca15a2..00000000 --- a/src/org/apollo/io/player/impl/BinaryPlayerSaver.java +++ /dev/null @@ -1,126 +0,0 @@ -package org.apollo.io.player.impl; - -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.List; -import java.util.Map.Entry; -import java.util.Set; - -import org.apollo.game.model.Appearance; -import org.apollo.game.model.Item; -import org.apollo.game.model.Position; -import org.apollo.game.model.entity.Player; -import org.apollo.game.model.entity.Skill; -import org.apollo.game.model.entity.SkillSet; -import org.apollo.game.model.entity.attr.Attribute; -import org.apollo.game.model.entity.attr.AttributeMap; -import org.apollo.game.model.entity.attr.AttributePersistence; -import org.apollo.game.model.inv.Inventory; -import org.apollo.io.player.PlayerSaver; -import org.apollo.util.NameUtil; -import org.apollo.util.StreamUtil; - -/** - * A {@link PlayerSaver} implementation that saves player data to a binary file. - * - * @author Graham - */ -public final class BinaryPlayerSaver implements PlayerSaver { - - @Override - public void savePlayer(Player player) throws IOException { - File file = BinaryPlayerUtil.getFile(player.getUsername()); - - try (DataOutputStream out = new DataOutputStream(new FileOutputStream(file))) { - StreamUtil.writeString(out, player.getUsername()); - StreamUtil.writeString(out, player.getCredentials().getPassword()); - out.writeByte(player.getPrivilegeLevel().toInteger()); - out.writeByte(player.getMembershipStatus().getValue()); - - out.writeByte(player.getChatPrivacy().toInteger(true)); - out.writeByte(player.getFriendPrivacy().toInteger(false)); - out.writeByte(player.getTradePrivacy().toInteger(false)); - out.writeByte(player.getRunEnergy()); - out.writeByte(player.getScreenBrightness().toInteger()); - - Position position = player.getPosition(); - out.writeShort(position.getX()); - out.writeShort(position.getY()); - out.writeByte(position.getHeight()); - - Appearance appearance = player.getAppearance(); - out.writeByte(appearance.getGender().toInteger()); - int[] style = appearance.getStyle(); - for (int element : style) { - out.writeByte(element); - } - int[] colors = appearance.getColors(); - for (int color : colors) { - out.writeByte(color); - } - - writeInventory(out, player.getInventory()); - writeInventory(out, player.getEquipment()); - writeInventory(out, player.getBank()); - - SkillSet skills = player.getSkillSet(); - out.writeByte(skills.size()); - for (int id = 0; id < skills.size(); id++) { - Skill skill = skills.getSkill(id); - out.writeByte(skill.getCurrentLevel()); - out.writeDouble(skill.getExperience()); - } - - List usernames = player.getFriendUsernames(); - out.writeByte(usernames.size()); - for (String username : usernames) { - out.writeLong(NameUtil.encodeBase37(username)); - } - - usernames = player.getIgnoredUsernames(); - out.writeByte(usernames.size()); - for (String username : usernames) { - out.writeLong(NameUtil.encodeBase37(username)); - } - - Set>> attributes = player.getAttributes().entrySet(); - attributes.removeIf(e -> AttributeMap.getDefinition(e.getKey()).getPersistence() != AttributePersistence.PERSISTENT); - out.writeInt(attributes.size()); - - for (Entry> entry : attributes) { - String name = entry.getKey(); - StreamUtil.writeString(out, name); - - Attribute attribute = entry.getValue(); - out.writeByte(attribute.getType().getValue()); - out.write(attribute.encode()); - } - } - } - - /** - * Writes an inventory to the specified output stream. - * - * @param out The output stream. - * @param inventory The inventory. - * @throws IOException If an I/O error occurs. - */ - private static void writeInventory(DataOutputStream out, Inventory inventory) throws IOException { - int capacity = inventory.capacity(); - out.writeShort(capacity); - - for (int slot = 0; slot < capacity; slot++) { - Item item = inventory.get(slot); - if (item != null) { - out.writeShort(item.getId() + 1); - out.writeInt(item.getAmount()); - } else { - out.writeShort(0); - out.writeInt(0); - } - } - } - -} \ No newline at end of file diff --git a/src/org/apollo/io/player/impl/BinaryPlayerUtil.java b/src/org/apollo/io/player/impl/BinaryPlayerUtil.java deleted file mode 100644 index 9c4ca633..00000000 --- a/src/org/apollo/io/player/impl/BinaryPlayerUtil.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.apollo.io.player.impl; - -import java.io.File; - -import org.apollo.util.NameUtil; - -/** - * A utility class with common functionality used by the binary player loader/ savers. - * - * @author Graham - */ -public final class BinaryPlayerUtil { - - /** - * The saved games directory. - */ - private static final File SAVED_GAMES_DIRECTORY = new File("data/savedGames"); - - /** - * Creates the saved games directory if it does not exist. - */ - static { - if (!SAVED_GAMES_DIRECTORY.exists()) { - SAVED_GAMES_DIRECTORY.mkdir(); - } - } - - /** - * Gets the save {@link File} for the specified player. - * - * @param username The username of the player. - * @return The file. - */ - public static File getFile(String username) { - String filtered = NameUtil.decodeBase37(NameUtil.encodeBase37(username)); - return new File(SAVED_GAMES_DIRECTORY, filtered + ".dat"); - } - - /** - * Default private constructor to prevent instantiation. - */ - private BinaryPlayerUtil() { - - } - -} \ No newline at end of file diff --git a/src/org/apollo/io/player/impl/DiscardPlayerSaver.java b/src/org/apollo/io/player/impl/DiscardPlayerSaver.java deleted file mode 100644 index cc00e839..00000000 --- a/src/org/apollo/io/player/impl/DiscardPlayerSaver.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.apollo.io.player.impl; - -import org.apollo.game.model.entity.Player; -import org.apollo.io.player.PlayerSaver; - -/** - * A {@link PlayerSaver} implementation that discards player data. - * - * @author Graham - */ -public final class DiscardPlayerSaver implements PlayerSaver { - - @Override - public void savePlayer(Player player) { - /* discard player */ - } - -} \ No newline at end of file diff --git a/src/org/apollo/io/player/impl/JdbcPlayerLoader.java b/src/org/apollo/io/player/impl/JdbcPlayerLoader.java deleted file mode 100644 index 9be78090..00000000 --- a/src/org/apollo/io/player/impl/JdbcPlayerLoader.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.apollo.io.player.impl; - -import org.apollo.io.player.PlayerLoader; -import org.apollo.io.player.PlayerLoaderResponse; -import org.apollo.security.PlayerCredentials; - -/** - * A {@link PlayerLoader} that utilises {@code JDBC} to load player files. - * - * @author Major - */ -public final class JdbcPlayerLoader implements PlayerLoader { - - @Override - public PlayerLoaderResponse loadPlayer(PlayerCredentials credentials) throws Exception { - throw new UnsupportedOperationException("JDBC loading is not supported at this time."); - } - -} \ No newline at end of file diff --git a/src/org/apollo/io/player/impl/JdbcPlayerSaver.java b/src/org/apollo/io/player/impl/JdbcPlayerSaver.java deleted file mode 100644 index bbdc7d3d..00000000 --- a/src/org/apollo/io/player/impl/JdbcPlayerSaver.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.apollo.io.player.impl; - -import org.apollo.game.model.entity.Player; -import org.apollo.io.player.PlayerSaver; - -/** - * A {@link PlayerSaver} that utilises {@code JDBC} to save the player. - * - * @author Major - */ -public final class JdbcPlayerSaver implements PlayerSaver { - - @Override - public void savePlayer(Player player) throws Exception { - throw new UnsupportedOperationException("JDBC saving is not supported at this time."); - } - -} \ No newline at end of file diff --git a/src/org/apollo/io/player/impl/package-info.java b/src/org/apollo/io/player/impl/package-info.java deleted file mode 100644 index a56ca9ca..00000000 --- a/src/org/apollo/io/player/impl/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Contains various player loader/saver implementations. - */ -package org.apollo.io.player.impl; \ No newline at end of file diff --git a/src/org/apollo/login/LoginService.java b/src/org/apollo/login/LoginService.java index fc45797f..d5664526 100644 --- a/src/org/apollo/login/LoginService.java +++ b/src/org/apollo/login/LoginService.java @@ -8,9 +8,8 @@ import java.util.concurrent.Executors; import org.apollo.Service; import org.apollo.game.model.entity.Player; -import org.apollo.io.player.PlayerLoader; import org.apollo.io.player.PlayerLoaderResponse; -import org.apollo.io.player.PlayerSaver; +import org.apollo.io.player.PlayerSerializer; import org.apollo.net.codec.login.LoginConstants; import org.apollo.net.codec.login.LoginRequest; import org.apollo.net.release.Release; @@ -25,6 +24,7 @@ import org.xml.sax.SAXException; * The {@link LoginService} manages {@link LoginRequest}s. * * @author Graham + * @author Major */ public final class LoginService extends Service { @@ -34,14 +34,9 @@ public final class LoginService extends Service { private final ExecutorService executor = Executors.newCachedThreadPool(new NamedThreadFactory("LoginService")); /** - * The current {@link PlayerLoader}. + * The current {@link PlayerSerializer}. */ - private PlayerLoader loader; - - /** - * The current {@link PlayerSaver}. - */ - private PlayerSaver saver; + private PlayerSerializer serializer; /** * Creates the login service. @@ -70,24 +65,16 @@ public final class LoginService extends Service { } if (!rootNode.getName().equals("login")) { - throw new IOException("Unexpected root node name."); + throw new IOException("Unexpected root node name, expected 'login'."); } - XmlNode loaderNode = rootNode.getChild("loader"); - if (loaderNode == null || !loaderNode.hasValue()) { - throw new IOException("No loader child node or value."); + XmlNode serializer = rootNode.getChild("serializer"); + if (serializer == null || !serializer.hasValue()) { + throw new IOException("No serializer child node or value."); } - XmlNode saverNode = rootNode.getChild("saver"); - if (saverNode == null || !saverNode.hasValue()) { - throw new IOException("No saver child node or value."); - } - - Class loaderClazz = Class.forName(loaderNode.getValue()); - Class saverClazz = Class.forName(saverNode.getValue()); - - loader = (PlayerLoader) loaderClazz.newInstance(); - saver = (PlayerSaver) saverClazz.newInstance(); + Class clazz = Class.forName(serializer.getValue()); + this.serializer = (PlayerSerializer) clazz.newInstance(); } /** @@ -95,7 +82,7 @@ public final class LoginService extends Service { */ @Override public void start() { - /* empty - here for consistency with other services */ + } /** @@ -110,7 +97,7 @@ public final class LoginService extends Service { // TODO check archive 0 CRCs session.handlePlayerLoaderResponse(request, new PlayerLoaderResponse(LoginConstants.STATUS_GAME_UPDATED)); } else { - executor.submit(new PlayerLoaderWorker(loader, session, request)); + executor.submit(new PlayerLoaderWorker(serializer, session, request)); } } @@ -121,7 +108,7 @@ public final class LoginService extends Service { * @param player The player to save. */ public void submitSaveRequest(GameSession session, Player player) { - executor.submit(new PlayerSaverWorker(saver, session, player)); + executor.submit(new PlayerSaverWorker(serializer, session, player)); } } \ No newline at end of file diff --git a/src/org/apollo/login/PlayerLoaderWorker.java b/src/org/apollo/login/PlayerLoaderWorker.java index 9c9bfabe..0553fe77 100644 --- a/src/org/apollo/login/PlayerLoaderWorker.java +++ b/src/org/apollo/login/PlayerLoaderWorker.java @@ -3,8 +3,8 @@ package org.apollo.login; import java.util.logging.Level; import java.util.logging.Logger; -import org.apollo.io.player.PlayerLoader; import org.apollo.io.player.PlayerLoaderResponse; +import org.apollo.io.player.PlayerSerializer; import org.apollo.net.codec.login.LoginConstants; import org.apollo.net.codec.login.LoginRequest; import org.apollo.net.session.LoginSession; @@ -22,9 +22,9 @@ public final class PlayerLoaderWorker implements Runnable { private static final Logger logger = Logger.getLogger(PlayerLoaderWorker.class.getName()); /** - * The player loader. + * The PlayerSerializer. */ - private final PlayerLoader loader; + private final PlayerSerializer loader; /** * The request. @@ -39,11 +39,11 @@ public final class PlayerLoaderWorker implements Runnable { /** * Creates a {@link PlayerLoaderWorker} which will do the work for a single player load request. * - * @param loader The current player loader. + * @param loader The {@link PlayerSerializer}. * @param session The {@link LoginSession} which initiated the request. * @param request The {@link LoginRequest} object. */ - public PlayerLoaderWorker(PlayerLoader loader, LoginSession session, LoginRequest request) { + public PlayerLoaderWorker(PlayerSerializer loader, LoginSession session, LoginRequest request) { this.loader = loader; this.session = session; this.request = request; diff --git a/src/org/apollo/login/PlayerSaverWorker.java b/src/org/apollo/login/PlayerSaverWorker.java index 2a0e369a..6ea2495c 100644 --- a/src/org/apollo/login/PlayerSaverWorker.java +++ b/src/org/apollo/login/PlayerSaverWorker.java @@ -4,7 +4,7 @@ import java.util.logging.Level; import java.util.logging.Logger; import org.apollo.game.model.entity.Player; -import org.apollo.io.player.PlayerSaver; +import org.apollo.io.player.PlayerSerializer; import org.apollo.net.session.GameSession; /** @@ -27,7 +27,7 @@ public final class PlayerSaverWorker implements Runnable { /** * The player saver. */ - private final PlayerSaver saver; + private final PlayerSerializer saver; /** * The game session. @@ -41,7 +41,7 @@ public final class PlayerSaverWorker implements Runnable { * @param session The game session. * @param player The player to save. */ - public PlayerSaverWorker(PlayerSaver saver, GameSession session, Player player) { + public PlayerSaverWorker(PlayerSerializer saver, GameSession session, Player player) { this.saver = saver; this.session = session; this.player = player;