diff --git a/h2_playermanager/src/main/java/mc/core/h2db/H2PlayerSerializer.java b/h2_playermanager/src/main/java/mc/core/h2db/H2PlayerSerializer.java index 80102cd..af5d4c8 100644 --- a/h2_playermanager/src/main/java/mc/core/h2db/H2PlayerSerializer.java +++ b/h2_playermanager/src/main/java/mc/core/h2db/H2PlayerSerializer.java @@ -1,19 +1,33 @@ package mc.core.h2db; +import lombok.extern.slf4j.Slf4j; +import mc.core.EntityLocation; +import mc.core.world.World; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.support.GeneratedKeyHolder; import org.springframework.jdbc.support.KeyHolder; +import org.springframework.stereotype.Component; import java.sql.PreparedStatement; +import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import java.util.UUID; +@Slf4j +@Component public class H2PlayerSerializer { + @Autowired + private World world; + @Autowired + private JdbcTemplate jdbcTemplate; + private static final String SQL_INSERT = "INSERT INTO players " + "(uuid, name, location_x, location_y, location_z, location_yaw, location_pitch, location_world) " + "VALUES (?, ?, ?, ?, ?, ?, ?, ?)"; - public static void serialize(final H2Player player, final JdbcTemplate jdbcTemplate) throws SQLException { + public void serialize(final H2Player player) throws SQLException { KeyHolder keyHolder = new GeneratedKeyHolder(); int affectedRows = jdbcTemplate.update(connection -> { PreparedStatement stmt = connection.prepareStatement(SQL_INSERT, Statement.RETURN_GENERATED_KEYS); @@ -36,4 +50,65 @@ public class H2PlayerSerializer { player.setId(keyHolder.getKey().intValue()); } + + public void deserialize(H2Player player) { + if (player.getId() > 0) { + selectById(player); + } else if (player.getUuid() != null) { + selectByUuid(player); + } else if (player.getName() != null && !player.getName().isEmpty()) { + selectByName(player); + } + } + + + private void selectById(final H2Player player) { + final String sql = "SELECT * FROM players WHERE id = ? LIMIT 1;"; + jdbcTemplate.query(sql, + ps -> ps.setInt(1, player.getId()), + rs -> { + player.setUuid(UUID.fromString(rs.getString("uuid"))); + player.setName(rs.getString("name")); + deserializeLocation(player, rs); + }); + } + + private void selectByUuid(H2Player player) { + final String sql = "SELECT * FROM players WHERE uuid LIKE ? LIMIT 1;"; + jdbcTemplate.query(sql, + ps -> ps.setString(1, player.getUuid().toString()), + rs -> { + player.setId(rs.getInt("id")); + player.setName(rs.getString("name")); + deserializeLocation(player, rs); + }); + } + + private void selectByName(H2Player player) { + final String sql = "SELECT * FROM players WHERE name LIKE ? LIMIT 1;"; + jdbcTemplate.query(sql, + ps -> ps.setString(1, player.getName()), + rs -> { + player.setId(rs.getInt("id")); + player.setUuid(UUID.fromString(rs.getString("uuid"))); + deserializeLocation(player, rs); + }); + } + + private void deserializeLocation(H2Player player, ResultSet resultSet) throws SQLException { + if (!world.getName().equals(resultSet.getString("location_world"))) { + log.warn("Unknown world \"{}\"", resultSet.getString("location_world")); + log.warn("Using default (spawn) location for user \"{}\"", player.getName()); + player.setLocation(world.getSpawn().clone()); + } else { + player.setLocation(new EntityLocation( + resultSet.getDouble("location_x"), + resultSet.getDouble("location_y"), + resultSet.getDouble("location_z"), + resultSet.getFloat("location_yaw"), + resultSet.getFloat("location_pitch"), + world + )); + } + } } diff --git a/h2_playermanager/src/test/java/mc/core/h2db/SpringConfig.java b/h2_playermanager/src/test/java/mc/core/h2db/SpringConfig.java index 4e18747..e4417e3 100644 --- a/h2_playermanager/src/test/java/mc/core/h2db/SpringConfig.java +++ b/h2_playermanager/src/test/java/mc/core/h2db/SpringConfig.java @@ -2,6 +2,7 @@ package mc.core.h2db; import mc.core.world.World; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DriverManagerDataSource; @@ -12,6 +13,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @Configuration +@ComponentScan("mc.core.h2db") public class SpringConfig { @Bean public World mockWorld() { diff --git a/h2_playermanager/src/test/java/mc/core/h2db/TestH2Database.java b/h2_playermanager/src/test/java/mc/core/h2db/TestH2Database.java index 77a2292..f194431 100644 --- a/h2_playermanager/src/test/java/mc/core/h2db/TestH2Database.java +++ b/h2_playermanager/src/test/java/mc/core/h2db/TestH2Database.java @@ -15,6 +15,7 @@ import java.io.IOException; import java.nio.charset.StandardCharsets; import java.sql.SQLException; import java.util.UUID; +import java.util.concurrent.ThreadLocalRandom; import static org.junit.Assert.assertEquals; @@ -25,18 +26,32 @@ public class TestH2Database { private JdbcTemplate jdbcTemplate; @Autowired private World mockWorld; + @Autowired + private H2PlayerSerializer h2PlayerSerializer; + private H2Player player; @PostConstruct public void init() throws IOException { jdbcTemplate.execute(IOUtils.resourceToString("/sqls/create_tables.sql", StandardCharsets.UTF_8)); } - private H2Player buildPlayer(final String name, final EntityLocation location) { - H2Player player = new H2Player(); + private void createPlayer() { + final ThreadLocalRandom rnd = ThreadLocalRandom.current(); + final double minD = 0.0d, maxD = 10.0d; + final float minF = 0.0f, maxF = 359.9f; + final int minI = 1000, maxI = 9999; + + player = new H2Player(); player.setUuid(UUID.randomUUID()); - player.setName(name); - player.setLocation(location.clone()); - return player; + player.setName("player" + rnd.nextInt(minI, maxI)); + player.setLocation(new EntityLocation( + rnd.nextDouble(minD, maxD), + rnd.nextDouble(minD, maxD), + rnd.nextDouble(minD, maxD), + rnd.nextFloat() * (maxF - minF) + minF, + rnd.nextFloat() * (maxF - minF) + minF, + mockWorld + )); } @Test @@ -52,8 +67,8 @@ public class TestH2Database { @Test public void testSerialize() throws SQLException { - final H2Player player = buildPlayer("player1", new EntityLocation(1.5d, 6.8d, 0.01d, 0f, 36.9f, mockWorld)); - H2PlayerSerializer.serialize(player, jdbcTemplate); + createPlayer(); + h2PlayerSerializer.serialize(player); assertEquals(1, player.getId()); @@ -69,4 +84,39 @@ public class TestH2Database { assertEquals(player.getLocation().getWorld().getName(), resultSet.getString("location_world")); }); } + + @Test + public void testDeserialize() { + createPlayer(); + player.setId(2); + + final String sql = "INSERT INTO players VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);"; + int affectedRows = jdbcTemplate.update(sql, ps -> { + ps.setInt(1, player.getId()); + ps.setString(2, player.getUuid().toString()); + ps.setString(3, player.getName()); + ps.setDouble(4, player.getLocation().getX()); + ps.setDouble(5, player.getLocation().getY()); + ps.setDouble(6, player.getLocation().getZ()); + ps.setFloat(7, player.getLocation().getYaw()); + ps.setFloat(8, player.getLocation().getPitch()); + ps.setString(9, player.getLocation().getWorld().getName()); + }); + assertEquals(1, affectedRows); + + H2Player queryPlayer = new H2Player(); + queryPlayer.setId(2); + h2PlayerSerializer.deserialize(queryPlayer); + assertEquals("Search by id", this.player, queryPlayer); + + queryPlayer = new H2Player(); + queryPlayer.setUuid(player.getUuid()); + h2PlayerSerializer.deserialize(queryPlayer); + assertEquals("Search by UUID", this.player, queryPlayer); + + queryPlayer = new H2Player(); + queryPlayer.setName(player.getName()); + h2PlayerSerializer.deserialize(queryPlayer); + assertEquals("Search by name", this.player, queryPlayer); + } }