diff --git a/core/src/main/java/mc/core/Location.java b/core/src/main/java/mc/core/Location.java index 959f141..fa1e00b 100644 --- a/core/src/main/java/mc/core/Location.java +++ b/core/src/main/java/mc/core/Location.java @@ -12,6 +12,14 @@ import lombok.Data; public class Location { private double x, y, z; + public static Location copyOf(Location location) { + return new Location( + location.x, + location.y, + location.z + ); + } + public void set(Location location) { this.x = location.x; this.y = location.y; diff --git a/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/TeleportManager.java b/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/TeleportManager.java new file mode 100644 index 0000000..31424bd --- /dev/null +++ b/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/TeleportManager.java @@ -0,0 +1,55 @@ +/* + * DmitriyMX + * 2018-06-23 + */ +package mc.core.network.proto_1_12_2; + +import lombok.AllArgsConstructor; +import mc.core.Location; +import mc.core.player.Player; + +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +public class TeleportManager { + private static TeleportManager instance = new TeleportManager(); + + public static TeleportManager getInstance() { + return instance; + } + + @AllArgsConstructor + private class TpData { + public Player player; + public Location newLocation; + // TODO необходимо добавить TimeStamp, что бы понимать, когда клиент отвергнул телепортацию + // т.е. идея такова: долгое молчание клиента знак отвержения телепортации. + } + + private final Random RAND = new Random(); + private final Map teleportMap = new HashMap<>(); + + private TeleportManager() {} + + public int append(Player player, Location location) { + int teleportId; + do { + teleportId = RAND.nextInt(9999); + } while (teleportMap.containsKey(teleportId)); + + teleportMap.put(teleportId, new TpData(player, Location.copyOf(location))); + return teleportId; + } + + public void apply(int teleportId) { + if (teleportMap.containsKey(teleportId)) { + TpData data = teleportMap.remove(teleportId); + data.player.getLocation().set(data.newLocation); + } + } + + public void removeDataPlayer(Player player) { + teleportMap.entrySet().removeIf(entry -> entry.getValue().player.equals(player)); + } +} diff --git a/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/packets/PlayerPositionAndLookPacket.java b/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/packets/PlayerPositionAndLookPacket.java index 6eb30b6..05a3e60 100644 --- a/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/packets/PlayerPositionAndLookPacket.java +++ b/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/packets/PlayerPositionAndLookPacket.java @@ -11,17 +11,16 @@ import mc.core.Location; import mc.core.network.CSPacket; import mc.core.network.NetStream; import mc.core.network.SCPacket; +import mc.core.network.proto_1_12_2.TeleportManager; import mc.core.player.Look; -import java.util.Random; - @NoArgsConstructor @Getter @Setter public class PlayerPositionAndLookPacket implements SCPacket, CSPacket { - private static Random RANDOM = new Random(); private Location location; private Look look; + private int teleportId; private boolean onGround = false; @Override @@ -38,8 +37,7 @@ public class PlayerPositionAndLookPacket implements SCPacket, CSPacket { * Y_ROT - 0x08 * X_ROT - 0x10 */ - //FIXME teleport id - netStream.writeVarInt(RANDOM.nextInt()); // Client should confirm this packet with Teleport Confirm containing the same Teleport ID + netStream.writeVarInt(teleportId); // Client should confirm this packet with Teleport Confirm containing the same Teleport ID } @Override diff --git a/proto_1.12.2_netty/src/main/java/mc/core/network/proto_1_12_2/netty/handlers/LoginHandler.java b/proto_1.12.2_netty/src/main/java/mc/core/network/proto_1_12_2/netty/handlers/LoginHandler.java index 62ca419..e66a6b3 100644 --- a/proto_1.12.2_netty/src/main/java/mc/core/network/proto_1_12_2/netty/handlers/LoginHandler.java +++ b/proto_1.12.2_netty/src/main/java/mc/core/network/proto_1_12_2/netty/handlers/LoginHandler.java @@ -7,6 +7,7 @@ package mc.core.network.proto_1_12_2.netty.handlers; import io.netty.channel.Channel; import io.netty.channel.ChannelFutureListener; import mc.core.network.proto_1_12_2.State; +import mc.core.network.proto_1_12_2.TeleportManager; import mc.core.network.proto_1_12_2.packets.*; import mc.core.player.Look; import mc.core.player.Player; @@ -80,6 +81,7 @@ public class LoginHandler extends AbstractStateHandler implements LoginStateHand PlayerPositionAndLookPacket pkt4 = new PlayerPositionAndLookPacket(); pkt4.setLocation(player.getLocation()); pkt4.setLook(player.getLook()); + pkt4.setTeleportId(TeleportManager.getInstance().append(player, player.getLocation())); channel.writeAndFlush(pkt4); } } diff --git a/proto_1.12.2_netty/src/main/java/mc/core/network/proto_1_12_2/netty/handlers/PlayHandler.java b/proto_1.12.2_netty/src/main/java/mc/core/network/proto_1_12_2/netty/handlers/PlayHandler.java index 9f6963e..4544496 100644 --- a/proto_1.12.2_netty/src/main/java/mc/core/network/proto_1_12_2/netty/handlers/PlayHandler.java +++ b/proto_1.12.2_netty/src/main/java/mc/core/network/proto_1_12_2/netty/handlers/PlayHandler.java @@ -5,7 +5,9 @@ package mc.core.network.proto_1_12_2.netty.handlers; import io.netty.channel.Channel; +import mc.core.network.proto_1_12_2.TeleportManager; import mc.core.network.proto_1_12_2.packets.ClientSettingsPacket; +import mc.core.network.proto_1_12_2.packets.TeleportConfirmPacket; import mc.core.player.Player; import org.springframework.stereotype.Component; @@ -13,6 +15,8 @@ import static mc.core.network.proto_1_12_2.netty.NettyServer.ATTR_PLAYER; @Component public class PlayHandler extends AbstractStateHandler implements PlayStateHandler { + private TeleportManager teleport = TeleportManager.getInstance(); + @Handler public void onClientSettings(Channel channel, ClientSettingsPacket packet) { Player player = channel.attr(ATTR_PLAYER).get(); @@ -32,4 +36,9 @@ public class PlayHandler extends AbstractStateHandler implements PlayStateHandle player.getSettings().setMainHand(packet.getMainHand()); } + + @Handler + public void onTeleportConfirm(Channel channel, TeleportConfirmPacket packet) { + this.teleport.apply(packet.getTeleportId()); + } }