diff --git a/README.md b/README.md index 3a1b9c6f..6c85ac2c 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ See ch.spacebase.mc.protocol.test.Test. -------- MCProtocolLib uses Maven to manage dependencies. Simply run 'mvn clean install' in the source's directory. -You can also download a build [here](http://build.spacebase.ch/job/MCProtocolLib14w03b/). +You can also download a build [here](http://build.spacebase.ch/job/MCProtocolLib14w04b/). License diff --git a/pom.xml b/pom.xml index 0d3f8f2b..544c0d47 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 ch.spacebase mcprotocollib - 14w03b-SNAPSHOT + 14w04b-SNAPSHOT jar MCProtocolLib @@ -85,6 +85,13 @@ clean install ${basedir}/src/main/java + + + + ${basedir}/src/main/resources + false + + org.apache.maven.plugins diff --git a/src/main/java/ch/spacebase/mc/auth/GameProfile.java b/src/main/java/ch/spacebase/mc/auth/GameProfile.java index 104a8af2..00385c70 100644 --- a/src/main/java/ch/spacebase/mc/auth/GameProfile.java +++ b/src/main/java/ch/spacebase/mc/auth/GameProfile.java @@ -1,9 +1,14 @@ package ch.spacebase.mc.auth; +import java.util.HashMap; +import java.util.Map; + public class GameProfile { private String id; private String name; + private Map properties = new HashMap(); + private boolean legacy; public GameProfile(String id, String name) { if((id == null || id.equals("")) && (name == null || name.equals(""))) { @@ -21,6 +26,14 @@ public class GameProfile { public String getName() { return this.name; } + + public Map getProperties() { + return this.properties; + } + + public boolean isLegacy() { + return this.legacy; + } public boolean isComplete() { return this.id != null && !this.id.equals("") && this.name != null && !this.name.equals(""); diff --git a/src/main/java/ch/spacebase/mc/auth/ProfileProperty.java b/src/main/java/ch/spacebase/mc/auth/ProfileProperty.java new file mode 100644 index 00000000..01c45174 --- /dev/null +++ b/src/main/java/ch/spacebase/mc/auth/ProfileProperty.java @@ -0,0 +1,54 @@ +package ch.spacebase.mc.auth; + +import java.security.PublicKey; +import java.security.Signature; + +import ch.spacebase.mc.util.Base64; + +public class ProfileProperty { + + private String name; + private String value; + private String signature; + + public ProfileProperty(String value, String name) { + this(value, name, null); + } + + public ProfileProperty(String name, String value, String signature) { + this.name = name; + this.value = value; + this.signature = signature; + } + + public String getName() { + return this.name; + } + + public String getValue() { + return this.value; + } + + public String getSignature() { + return this.signature; + } + + public boolean hasSignature() { + return this.signature != null; + } + + public boolean isSignatureValid(PublicKey key) { + try { + Signature sig = Signature.getInstance("SHA1withRSA"); + sig.initVerify(key); + sig.update(this.value.getBytes()); + return sig.verify(Base64.decode(this.signature.getBytes("UTF-8"))); + } catch(Exception e) { + System.err.println("Failed to check profile property signature validity."); + e.printStackTrace(); + } + + return false; + } + +} diff --git a/src/main/java/ch/spacebase/mc/auth/ProfileTexture.java b/src/main/java/ch/spacebase/mc/auth/ProfileTexture.java new file mode 100644 index 00000000..69af60ea --- /dev/null +++ b/src/main/java/ch/spacebase/mc/auth/ProfileTexture.java @@ -0,0 +1,31 @@ +package ch.spacebase.mc.auth; + +public class ProfileTexture { + + private String url; + + public ProfileTexture(String url) { + this.url = url; + } + + public String getUrl() { + return this.url; + } + + public String getHash() { + String url = this.url.endsWith("/") ? this.url.substring(0, this.url.length() - 1) : this.url; + int slash = url.lastIndexOf("/"); + int dot = url.lastIndexOf(".", slash); + return url.substring(slash + 1, dot != -1 ? dot : url.length()); + } + + public String toString() { + return "ProfileTexture{url=" + this.url + ", hash=" + this.getHash() + "}"; + } + + public static enum Type { + SKIN, + CAPE; + } + +} diff --git a/src/main/java/ch/spacebase/mc/auth/SessionService.java b/src/main/java/ch/spacebase/mc/auth/SessionService.java index 054106dd..317d358f 100644 --- a/src/main/java/ch/spacebase/mc/auth/SessionService.java +++ b/src/main/java/ch/spacebase/mc/auth/SessionService.java @@ -4,18 +4,38 @@ import ch.spacebase.mc.auth.exceptions.AuthenticationException; import ch.spacebase.mc.auth.exceptions.AuthenticationUnavailableException; import ch.spacebase.mc.auth.request.JoinServerRequest; import ch.spacebase.mc.auth.response.HasJoinedResponse; +import ch.spacebase.mc.auth.response.MinecraftTexturesPayload; import ch.spacebase.mc.auth.response.Response; +import ch.spacebase.mc.util.Base64; +import ch.spacebase.mc.util.IOUtils; import ch.spacebase.mc.util.URLUtils; import java.net.URL; +import java.security.KeyFactory; +import java.security.PublicKey; +import java.security.spec.X509EncodedKeySpec; import java.util.HashMap; import java.util.Map; +import com.google.gson.Gson; + public class SessionService { private static final String BASE_URL = "https://sessionserver.mojang.com/session/minecraft/"; private static final URL JOIN_URL = URLUtils.constantURL(BASE_URL + "join"); private static final URL CHECK_URL = URLUtils.constantURL(BASE_URL + "hasJoined"); + + private static final PublicKey SIGNATURE_KEY; + + static { + try { + X509EncodedKeySpec spec = new X509EncodedKeySpec(IOUtils.toByteArray(SessionService.class.getResourceAsStream("/yggdrasil_session_pubkey.der"))); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + SIGNATURE_KEY = keyFactory.generatePublic(spec); + } catch(Exception var4) { + throw new ExceptionInInitializerError("Missing/invalid yggdrasil public key."); + } + } public void joinServer(GameProfile profile, String authenticationToken, String serverId) throws AuthenticationException { JoinServerRequest request = new JoinServerRequest(authenticationToken, profile.getId(), serverId); @@ -28,8 +48,19 @@ public class SessionService { arguments.put("serverId", serverId); URL url = URLUtils.concatenateURL(CHECK_URL, URLUtils.buildQuery(arguments)); try { - HasJoinedResponse e = URLUtils.makeRequest(url, null, HasJoinedResponse.class); - return e != null && e.getId() != null ? new GameProfile(e.getId(), user.getName()) : null; + HasJoinedResponse response = URLUtils.makeRequest(url, null, HasJoinedResponse.class); + if(response != null && response.getId() != null) { + GameProfile result = new GameProfile(response.getId(), user.getName()); + if(response.getProperties() != null) { + for(ProfileProperty prop : response.getProperties()) { + result.getProperties().put(prop.getName(), prop); + } + } + + return result; + } else { + return null; + } } catch(AuthenticationUnavailableException var6) { throw var6; } catch(AuthenticationException var7) { @@ -37,6 +68,41 @@ public class SessionService { } } + public Map getTextures(GameProfile profile) { + ProfileProperty textures = profile.getProperties().get("textures"); + if(textures == null) { + return new HashMap(); + } else if(!textures.hasSignature()) { + System.err.println("Signature is missing from textures payload."); + return new HashMap(); + } else if(!textures.isSignatureValid(SIGNATURE_KEY)) { + System.err.println("Textures payload has been tampered with. (signature invalid)"); + return new HashMap(); + } else { + MinecraftTexturesPayload result; + try { + String e = new String(Base64.decode(textures.getValue().getBytes("UTF-8"))); + result = new Gson().fromJson(e, MinecraftTexturesPayload.class); + } catch(Exception e) { + System.err.println("Could not decode textures payload."); + e.printStackTrace(); + return new HashMap(); + } + + if(result.getProfileId() != null && result.getProfileId().equals(profile.getId())) { + if(result.getProfileName() != null && result.getProfileName().equals(profile.getName())) { + return result.getTextures() == null ? new HashMap() : result.getTextures(); + } else { + System.err.println("Decrypted textures payload was for another user. (expected name " + profile.getName() + " but was for " + result.getProfileName() + ")"); + return new HashMap(); + } + } else { + System.err.println("Decrypted textures payload was for another user. (expected id " + profile.getId() + " but was for " + result.getProfileId() + ")"); + return new HashMap(); + } + } + } + @Override public String toString() { return "SessionService{}"; diff --git a/src/main/java/ch/spacebase/mc/auth/UserAuthentication.java b/src/main/java/ch/spacebase/mc/auth/UserAuthentication.java index f8efb69c..372bcd11 100644 --- a/src/main/java/ch/spacebase/mc/auth/UserAuthentication.java +++ b/src/main/java/ch/spacebase/mc/auth/UserAuthentication.java @@ -7,6 +7,7 @@ import ch.spacebase.mc.auth.request.RefreshRequest; import ch.spacebase.mc.auth.response.AuthenticationResponse; import ch.spacebase.mc.auth.response.RefreshResponse; import ch.spacebase.mc.auth.response.User; +import ch.spacebase.mc.auth.response.User.Property; import ch.spacebase.mc.util.URLUtils; import java.net.URL; @@ -14,7 +15,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; @@ -30,7 +30,7 @@ public class UserAuthentication { private static final String STORAGE_KEY_ACCESS_TOKEN = "accessToken"; private String clientToken; - private Map userProperties = new HashMap(); + private Map> userProperties = new HashMap>(); private String userId; private String username; private String password; @@ -38,6 +38,7 @@ public class UserAuthentication { private boolean isOnline; private List profiles = new ArrayList(); private GameProfile selectedProfile; + private UserType userType; public UserAuthentication(String clientToken) { if(clientToken == null) { @@ -67,8 +68,12 @@ public class UserAuthentication { return this.selectedProfile; } - public Map getUserProperties() { - return this.isLoggedIn() ? Collections.unmodifiableMap(this.userProperties) : Collections.unmodifiableMap(new HashMap()); + public UserType getUserType() { + return this.isLoggedIn() ? (this.userType == null ? UserType.LEGACY : this.userType) : null; + } + + public Map> getUserProperties() { + return this.isLoggedIn() ? Collections.unmodifiableMap(this.userProperties) : Collections.unmodifiableMap(new HashMap>()); } public boolean isLoggedIn() { @@ -170,8 +175,14 @@ public class UserAuthentication { AuthenticationRequest request = new AuthenticationRequest(this, this.username, this.password); AuthenticationResponse response = URLUtils.makeRequest(ROUTE_AUTHENTICATE, request, AuthenticationResponse.class); if(!response.getClientToken().equals(this.getClientToken())) { - throw new AuthenticationException("Server requested we change our client token. Don\'t know how to handle this!"); + throw new AuthenticationException("Server requested we change our client token. Don't know how to handle this!"); } else { + if(response.getSelectedProfile() != null) { + this.userType = response.getSelectedProfile().isLegacy() ? UserType.LEGACY : UserType.MOJANG; + } else if(response.getAvailableProfiles() != null && response.getAvailableProfiles().length != 0) { + this.userType = response.getAvailableProfiles()[0].isLegacy() ? UserType.LEGACY : UserType.MOJANG; + } + if(response.getUser() != null && response.getUser().getId() != null) { this.userId = response.getUser().getId(); } else { @@ -182,14 +193,7 @@ public class UserAuthentication { this.accessToken = response.getAccessToken(); this.profiles = Arrays.asList(response.getAvailableProfiles()); this.selectedProfile = response.getSelectedProfile(); - this.userProperties.clear(); - if(response.getUser() != null && response.getUser().getProperties() != null) { - Iterator it = response.getUser().getProperties().iterator(); - while(it.hasNext()) { - User.Property property = it.next(); - this.userProperties.put(property.getKey(), property.getValue()); - } - } + this.updateProperties(response.getUser()); } } } @@ -209,8 +213,14 @@ public class UserAuthentication { RefreshRequest request = new RefreshRequest(this); RefreshResponse response = URLUtils.makeRequest(ROUTE_REFRESH, request, RefreshResponse.class); if(!response.getClientToken().equals(this.getClientToken())) { - throw new AuthenticationException("Server requested we change our client token. Don\'t know how to handle this!"); + throw new AuthenticationException("Server requested we change our client token. Don't know how to handle this!"); } else { + if(response.getSelectedProfile() != null) { + this.userType = response.getSelectedProfile().isLegacy() ? UserType.LEGACY : UserType.MOJANG; + } else if(response.getAvailableProfiles() != null && response.getAvailableProfiles().length != 0) { + this.userType = response.getAvailableProfiles()[0].isLegacy() ? UserType.LEGACY : UserType.MOJANG; + } + if(response.getUser() != null && response.getUser().getId() != null) { this.userId = response.getUser().getId(); } else { @@ -221,15 +231,7 @@ public class UserAuthentication { this.accessToken = response.getAccessToken(); this.profiles = Arrays.asList(response.getAvailableProfiles()); this.selectedProfile = response.getSelectedProfile(); - this.userProperties.clear(); - if(response.getUser() != null && response.getUser().getProperties() != null) { - Iterator it = response.getUser().getProperties().iterator(); - while(it.hasNext()) { - User.Property property = it.next(); - this.userProperties.put(property.getKey(), property.getValue()); - } - } - + this.updateProperties(response.getUser()); } } } @@ -242,6 +244,7 @@ public class UserAuthentication { this.accessToken = null; this.profiles = null; this.isOnline = false; + this.userType = null; } public void selectGameProfile(GameProfile profile) throws AuthenticationException { @@ -253,14 +256,14 @@ public class UserAuthentication { RefreshRequest request = new RefreshRequest(this, profile); RefreshResponse response = URLUtils.makeRequest(ROUTE_REFRESH, request, RefreshResponse.class); if(!response.getClientToken().equals(this.getClientToken())) { - throw new AuthenticationException("Server requested we change our client token. Don\'t know how to handle this!"); + throw new AuthenticationException("Server requested we change our client token. Don't know how to handle this!"); } else { this.isOnline = true; this.accessToken = response.getAccessToken(); this.selectedProfile = response.getSelectedProfile(); } } else { - throw new IllegalArgumentException("Invalid profile \'" + profile + "\'"); + throw new IllegalArgumentException("Invalid profile '" + profile + "'"); } } @@ -268,5 +271,18 @@ public class UserAuthentication { public String toString() { return "UserAuthentication{profiles=" + this.profiles + ", selectedProfile=" + this.getSelectedProfile() + ", username=" + this.username + ", isLoggedIn=" + this.isLoggedIn() + ", canPlayOnline=" + this.canPlayOnline() + ", accessToken=" + this.accessToken + ", clientToken=" + this.getClientToken() + "}"; } + + private void updateProperties(User user) { + this.userProperties.clear(); + if(user != null && user.getProperties() != null) { + for(Property property : user.getProperties()) { + if(this.userProperties.get(property.getKey()) == null) { + this.userProperties.put(property.getKey(), new ArrayList()); + } + + this.userProperties.get(property.getKey()).add(property.getValue()); + } + } + } } diff --git a/src/main/java/ch/spacebase/mc/auth/UserType.java b/src/main/java/ch/spacebase/mc/auth/UserType.java new file mode 100644 index 00000000..31f91740 --- /dev/null +++ b/src/main/java/ch/spacebase/mc/auth/UserType.java @@ -0,0 +1,8 @@ +package ch.spacebase.mc.auth; + +public enum UserType { + + LEGACY, + MOJANG; + +} diff --git a/src/main/java/ch/spacebase/mc/auth/response/HasJoinedResponse.java b/src/main/java/ch/spacebase/mc/auth/response/HasJoinedResponse.java index c749d855..f16eb3db 100644 --- a/src/main/java/ch/spacebase/mc/auth/response/HasJoinedResponse.java +++ b/src/main/java/ch/spacebase/mc/auth/response/HasJoinedResponse.java @@ -1,13 +1,21 @@ package ch.spacebase.mc.auth.response; +import java.util.List; + +import ch.spacebase.mc.auth.ProfileProperty; import ch.spacebase.mc.auth.response.Response; public class HasJoinedResponse extends Response { private String id; + private List properties; public String getId() { return this.id; } + public List getProperties() { + return this.properties; + } + } diff --git a/src/main/java/ch/spacebase/mc/auth/response/MinecraftTexturesPayload.java b/src/main/java/ch/spacebase/mc/auth/response/MinecraftTexturesPayload.java new file mode 100644 index 00000000..9eeb2045 --- /dev/null +++ b/src/main/java/ch/spacebase/mc/auth/response/MinecraftTexturesPayload.java @@ -0,0 +1,30 @@ +package ch.spacebase.mc.auth.response; + +import java.util.Map; + +import ch.spacebase.mc.auth.ProfileTexture; + +public class MinecraftTexturesPayload { + + private long timestamp; + private String profileId; + private String profileName; + private Map textures; + + public long getTimestamp() { + return this.timestamp; + } + + public String getProfileId() { + return this.profileId; + } + + public String getProfileName() { + return this.profileName; + } + + public Map getTextures() { + return this.textures; + } + +} diff --git a/src/main/java/ch/spacebase/mc/protocol/MinecraftProtocol.java b/src/main/java/ch/spacebase/mc/protocol/MinecraftProtocol.java index c26749d8..0f4c5bf1 100644 --- a/src/main/java/ch/spacebase/mc/protocol/MinecraftProtocol.java +++ b/src/main/java/ch/spacebase/mc/protocol/MinecraftProtocol.java @@ -33,6 +33,8 @@ import ch.spacebase.mc.protocol.packet.ingame.client.window.ClientEnchantItemPac import ch.spacebase.mc.protocol.packet.ingame.client.window.ClientWindowActionPacket; import ch.spacebase.mc.protocol.packet.ingame.client.world.ClientUpdateSignPacket; import ch.spacebase.mc.protocol.packet.ingame.server.ServerChatPacket; +import ch.spacebase.mc.protocol.packet.ingame.server.ServerCombatPacket; +import ch.spacebase.mc.protocol.packet.ingame.server.ServerDifficultyPacket; import ch.spacebase.mc.protocol.packet.ingame.server.ServerDisconnectPacket; import ch.spacebase.mc.protocol.packet.ingame.server.ServerJoinGamePacket; import ch.spacebase.mc.protocol.packet.ingame.server.ServerKeepAlivePacket; @@ -326,6 +328,8 @@ public class MinecraftProtocol extends PacketProtocol { this.registerIncoming(62, ServerTeamPacket.class); this.registerIncoming(63, ServerPluginMessagePacket.class); this.registerIncoming(64, ServerDisconnectPacket.class); + this.registerIncoming(65, ServerDifficultyPacket.class); + this.registerIncoming(66, ServerCombatPacket.class); this.registerOutgoing(0, ClientKeepAlivePacket.class); this.registerOutgoing(1, ClientChatPacket.class); @@ -444,6 +448,8 @@ public class MinecraftProtocol extends PacketProtocol { this.registerOutgoing(62, ServerTeamPacket.class); this.registerOutgoing(63, ServerPluginMessagePacket.class); this.registerOutgoing(64, ServerDisconnectPacket.class); + this.registerOutgoing(65, ServerDifficultyPacket.class); + this.registerOutgoing(66, ServerCombatPacket.class); } private void initClientStatus(Session session) { diff --git a/src/main/java/ch/spacebase/mc/protocol/ProtocolConstants.java b/src/main/java/ch/spacebase/mc/protocol/ProtocolConstants.java index f024595b..7b5e8025 100644 --- a/src/main/java/ch/spacebase/mc/protocol/ProtocolConstants.java +++ b/src/main/java/ch/spacebase/mc/protocol/ProtocolConstants.java @@ -3,8 +3,8 @@ package ch.spacebase.mc.protocol; public class ProtocolConstants { // General Constants - public static final String GAME_VERSION = "14w03b"; - public static final int PROTOCOL_VERSION = 6; + public static final String GAME_VERSION = "14w04b"; + public static final int PROTOCOL_VERSION = 8; // General Key Constants public static final String PROFILE_KEY = "profile"; diff --git a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/client/ClientKeepAlivePacket.java b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/client/ClientKeepAlivePacket.java index f2582d48..2f7d2171 100644 --- a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/client/ClientKeepAlivePacket.java +++ b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/client/ClientKeepAlivePacket.java @@ -24,12 +24,12 @@ public class ClientKeepAlivePacket implements Packet { @Override public void read(NetInput in) throws IOException { - this.id = in.readInt(); + this.id = in.readVarInt(); } @Override public void write(NetOutput out) throws IOException { - out.writeInt(this.id); + out.writeVarInt(this.id); } @Override diff --git a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/client/ClientRequestPacket.java b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/client/ClientRequestPacket.java index ee75c373..e4ae8da6 100644 --- a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/client/ClientRequestPacket.java +++ b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/client/ClientRequestPacket.java @@ -24,7 +24,7 @@ public class ClientRequestPacket implements Packet { @Override public void read(NetInput in) throws IOException { - this.request = Request.values()[in.readByte()]; + this.request = Request.values()[in.readUnsignedByte()]; } @Override diff --git a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/client/entity/ClientAnimationPacket.java b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/client/entity/ClientAnimationPacket.java index 9ee01a56..e569a873 100644 --- a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/client/entity/ClientAnimationPacket.java +++ b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/client/entity/ClientAnimationPacket.java @@ -8,45 +8,20 @@ import ch.spacebase.packetlib.packet.Packet; public class ClientAnimationPacket implements Packet { - private int entityId; - private Animation animation; - - @SuppressWarnings("unused") - private ClientAnimationPacket() { - } - - public ClientAnimationPacket(int entityId, Animation animation) { - this.entityId = entityId; - this.animation = animation; - } - - public int getEntityId() { - return this.entityId; - } - - public Animation getAnimation() { - return this.animation; + public ClientAnimationPacket() { } @Override public void read(NetInput in) throws IOException { - this.entityId = in.readInt(); - this.animation = Animation.values()[in.readByte() - 1]; } @Override public void write(NetOutput out) throws IOException { - out.writeInt(this.entityId); - out.writeByte(this.animation.ordinal() + 1); } @Override public boolean isPriority() { return false; } - - public static enum Animation { - SWING_ARM; - } } diff --git a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/client/entity/ClientEntityActionPacket.java b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/client/entity/ClientEntityActionPacket.java index fcfdf011..0f80dd00 100644 --- a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/client/entity/ClientEntityActionPacket.java +++ b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/client/entity/ClientEntityActionPacket.java @@ -40,16 +40,16 @@ public class ClientEntityActionPacket implements Packet { @Override public void read(NetInput in) throws IOException { - this.entityId = in.readInt(); - this.action = Action.values()[in.readByte() - 1]; - this.jumpBoost = in.readInt(); + this.entityId = in.readVarInt(); + this.action = Action.values()[in.readUnsignedByte() - 1]; + this.jumpBoost = in.readVarInt(); } @Override public void write(NetOutput out) throws IOException { - out.writeInt(this.entityId); + out.writeVarInt(this.entityId); out.writeByte(this.action.ordinal() + 1); - out.writeInt(this.jumpBoost); + out.writeVarInt(this.jumpBoost); } @Override diff --git a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/client/entity/ClientEntityInteractPacket.java b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/client/entity/ClientEntityInteractPacket.java index 48255008..cf8286d3 100644 --- a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/client/entity/ClientEntityInteractPacket.java +++ b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/client/entity/ClientEntityInteractPacket.java @@ -30,13 +30,13 @@ public class ClientEntityInteractPacket implements Packet { @Override public void read(NetInput in) throws IOException { - this.entityId = in.readInt(); - this.action = Action.values()[in.readByte()]; + this.entityId = in.readVarInt(); + this.action = Action.values()[in.readUnsignedByte()]; } @Override public void write(NetOutput out) throws IOException { - out.writeInt(this.entityId); + out.writeVarInt(this.entityId); out.writeByte(this.action.ordinal()); } diff --git a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/client/entity/player/ClientSteerVehiclePacket.java b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/client/entity/player/ClientSteerVehiclePacket.java index d6c2b407..b232a34b 100644 --- a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/client/entity/player/ClientSteerVehiclePacket.java +++ b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/client/entity/player/ClientSteerVehiclePacket.java @@ -44,16 +44,25 @@ public class ClientSteerVehiclePacket implements Packet { public void read(NetInput in) throws IOException { this.sideways = in.readFloat(); this.forward = in.readFloat(); - this.jump = in.readBoolean(); - this.dismount = in.readBoolean(); + int flags = in.readUnsignedByte(); + this.jump = (flags & 1) > 0; + this.dismount = (flags & 2) > 0; } @Override public void write(NetOutput out) throws IOException { out.writeFloat(this.sideways); out.writeFloat(this.forward); - out.writeBoolean(this.jump); - out.writeBoolean(this.dismount); + byte flags = 0; + if(this.jump) { + flags = (byte) (flags | 1); + } + + if(this.dismount) { + flags = (byte) (flags | 2); + } + + out.writeByte(flags); } @Override diff --git a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/ServerCombatPacket.java b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/ServerCombatPacket.java new file mode 100644 index 00000000..f7808684 --- /dev/null +++ b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/ServerCombatPacket.java @@ -0,0 +1,91 @@ +package ch.spacebase.mc.protocol.packet.ingame.server; + +import java.io.IOException; + +import ch.spacebase.packetlib.io.NetInput; +import ch.spacebase.packetlib.io.NetOutput; +import ch.spacebase.packetlib.packet.Packet; + +public class ServerCombatPacket implements Packet { + + private CombatState state; + private int entityId; + private int duration; + private int playerId; + private String message; + + public ServerCombatPacket() { + this.state = CombatState.ENTER_COMBAT; + } + + public ServerCombatPacket(int entityId, int duration) { + this.state = CombatState.END_COMBAT; + this.entityId = entityId; + this.duration = duration; + } + + public ServerCombatPacket(int entityId, int playerId, String message) { + this.state = CombatState.ENTITY_DEAD; + this.entityId = entityId; + this.playerId = playerId; + this.message = message; + } + + public CombatState getCombatState() { + return this.state; + } + + public int getEntityId() { + return this.entityId; + } + + public int getDuration() { + return this.duration; + } + + public int getPlayerId() { + return this.playerId; + } + + public String getMessage() { + return this.message; + } + + @Override + public void read(NetInput in) throws IOException { + this.state = CombatState.values()[in.readUnsignedByte()]; + if(this.state == CombatState.END_COMBAT) { + this.duration = in.readVarInt(); + this.entityId = in.readInt(); + } else if(this.state == CombatState.ENTITY_DEAD) { + this.playerId = in.readVarInt(); + this.entityId = in.readInt(); + this.message = in.readString(); + } + } + + @Override + public void write(NetOutput out) throws IOException { + out.writeByte(this.state.ordinal()); + if(this.state == CombatState.END_COMBAT) { + out.writeVarInt(this.duration); + out.writeInt(this.entityId); + } else if(this.state == CombatState.ENTITY_DEAD) { + out.writeVarInt(this.playerId); + out.writeInt(this.entityId); + out.writeString(this.message); + } + } + + @Override + public boolean isPriority() { + return false; + } + + public static enum CombatState { + ENTER_COMBAT, + END_COMBAT, + ENTITY_DEAD; + } + +} diff --git a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/ServerPlayerListEntryPacket.java b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/ServerPlayerListEntryPacket.java index 41290d8d..24f96ff4 100644 --- a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/ServerPlayerListEntryPacket.java +++ b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/ServerPlayerListEntryPacket.java @@ -38,14 +38,14 @@ public class ServerPlayerListEntryPacket implements Packet { public void read(NetInput in) throws IOException { this.name = in.readString(); this.online = in.readBoolean(); - this.ping = in.readShort(); + this.ping = in.readVarInt(); } @Override public void write(NetOutput out) throws IOException { out.writeString(this.name); out.writeBoolean(this.online); - out.writeShort(this.ping); + out.writeVarInt(this.ping); } @Override diff --git a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerCollectItemPacket.java b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerCollectItemPacket.java index 32a72ffb..b9f3676a 100644 --- a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerCollectItemPacket.java +++ b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerCollectItemPacket.java @@ -30,14 +30,14 @@ public class ServerCollectItemPacket implements Packet { @Override public void read(NetInput in) throws IOException { - this.collectedEntityId = in.readInt(); - this.collectorEntityId = in.readInt(); + this.collectedEntityId = in.readVarInt(); + this.collectorEntityId = in.readVarInt(); } @Override public void write(NetOutput out) throws IOException { - out.writeInt(this.collectedEntityId); - out.writeInt(this.collectorEntityId); + out.writeVarInt(this.collectedEntityId); + out.writeVarInt(this.collectorEntityId); } @Override diff --git a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerDestroyEntitiesPacket.java b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerDestroyEntitiesPacket.java index 2091e7a2..af5fdf2e 100644 --- a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerDestroyEntitiesPacket.java +++ b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerDestroyEntitiesPacket.java @@ -24,17 +24,17 @@ public class ServerDestroyEntitiesPacket implements Packet { @Override public void read(NetInput in) throws IOException { - this.entityIds = new int[in.readByte()]; + this.entityIds = new int[in.readVarInt()]; for(int index = 0; index < this.entityIds.length; index++) { - this.entityIds[index] = in.readInt(); + this.entityIds[index] = in.readVarInt(); } } @Override public void write(NetOutput out) throws IOException { - out.writeByte(this.entityIds.length); + out.writeVarInt(this.entityIds.length); for(int entityId : this.entityIds) { - out.writeInt(entityId); + out.writeVarInt(entityId); } } diff --git a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityEffectPacket.java b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityEffectPacket.java index c878f86a..73f348cd 100644 --- a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityEffectPacket.java +++ b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityEffectPacket.java @@ -42,18 +42,18 @@ public class ServerEntityEffectPacket implements Packet { @Override public void read(NetInput in) throws IOException { - this.entityId = in.readInt(); + this.entityId = in.readVarInt(); this.effect = Effect.values()[in.readByte()]; this.amplifier = in.readByte(); - this.duration = in.readShort(); + this.duration = in.readVarInt(); } @Override public void write(NetOutput out) throws IOException { - out.writeInt(this.entityId); + out.writeVarInt(this.entityId); out.writeByte(this.effect.ordinal()); out.writeByte(this.amplifier); - out.writeShort(this.duration); + out.writeVarInt(this.duration); } @Override diff --git a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityEquipmentPacket.java b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityEquipmentPacket.java index 126b036d..40182791 100644 --- a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityEquipmentPacket.java +++ b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityEquipmentPacket.java @@ -38,14 +38,14 @@ public class ServerEntityEquipmentPacket implements Packet { @Override public void read(NetInput in) throws IOException { - this.entityId = in.readInt(); + this.entityId = in.readVarInt(); this.slot = in.readShort(); this.item = NetUtil.readItem(in); } @Override public void write(NetOutput out) throws IOException { - out.writeInt(this.entityId); + out.writeVarInt(this.entityId); out.writeShort(this.slot); NetUtil.writeItem(out, this.item); } diff --git a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityHeadLookPacket.java b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityHeadLookPacket.java index 457a7ced..0a1a454c 100644 --- a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityHeadLookPacket.java +++ b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityHeadLookPacket.java @@ -26,13 +26,13 @@ public class ServerEntityHeadLookPacket implements Packet { @Override public void read(NetInput in) throws IOException { - this.entityId = in.readInt(); + this.entityId = in.readVarInt(); this.headYaw = in.readByte() * 360 / 256f; } @Override public void write(NetOutput out) throws IOException { - out.writeInt(this.entityId); + out.writeVarInt(this.entityId); out.writeByte((byte) (this.headYaw * 256 / 360)); } diff --git a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityMetadataPacket.java b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityMetadataPacket.java index 747116d7..fed065fa 100644 --- a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityMetadataPacket.java +++ b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityMetadataPacket.java @@ -32,13 +32,13 @@ public class ServerEntityMetadataPacket implements Packet { @Override public void read(NetInput in) throws IOException { - this.entityId = in.readInt(); + this.entityId = in.readVarInt(); this.metadata = NetUtil.readEntityMetadata(in); } @Override public void write(NetOutput out) throws IOException { - out.writeInt(this.entityId); + out.writeVarInt(this.entityId); NetUtil.writeEntityMetadata(out, this.metadata); } diff --git a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityMovementPacket.java b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityMovementPacket.java index 40e3875c..5fa11e1a 100644 --- a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityMovementPacket.java +++ b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityMovementPacket.java @@ -51,7 +51,7 @@ public class ServerEntityMovementPacket implements Packet { @Override public void read(NetInput in) throws IOException { - this.entityId = in.readInt(); + this.entityId = in.readVarInt(); if(this.pos) { this.moveX = in.readByte() / 32D; this.moveY = in.readByte() / 32D; @@ -66,7 +66,7 @@ public class ServerEntityMovementPacket implements Packet { @Override public void write(NetOutput out) throws IOException { - out.writeInt(this.entityId); + out.writeVarInt(this.entityId); if(this.pos) { out.writeByte((int) (this.moveX * 32)); out.writeByte((int) (this.moveY * 32)); diff --git a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityPropertiesPacket.java b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityPropertiesPacket.java index bf235e56..fc0d596a 100644 --- a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityPropertiesPacket.java +++ b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityPropertiesPacket.java @@ -35,9 +35,9 @@ public class ServerEntityPropertiesPacket implements Packet { @Override public void read(NetInput in) throws IOException { - this.entityId = in.readInt(); + this.entityId = in.readVarInt(); this.attributes = new ArrayList(); - int length = in.readInt(); + int length = in.readVarInt(); for(int index = 0; index < length; index++) { String key = in.readString(); double value = in.readDouble(); @@ -53,8 +53,8 @@ public class ServerEntityPropertiesPacket implements Packet { @Override public void write(NetOutput out) throws IOException { - out.writeInt(this.entityId); - out.writeInt(this.attributes.size()); + out.writeVarInt(this.entityId); + out.writeVarInt(this.attributes.size()); for(Attribute attribute : this.attributes) { out.writeString(attribute.getKey()); out.writeDouble(attribute.getValue()); diff --git a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityRemoveEffectPacket.java b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityRemoveEffectPacket.java index a42ff155..1a585048 100644 --- a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityRemoveEffectPacket.java +++ b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityRemoveEffectPacket.java @@ -10,18 +10,14 @@ public class ServerEntityRemoveEffectPacket implements Packet { private int entityId; private Effect effect; - private int amplifier; - private int duration; @SuppressWarnings("unused") private ServerEntityRemoveEffectPacket() { } - public ServerEntityRemoveEffectPacket(int entityId, Effect effect, int amplifier, int duration) { + public ServerEntityRemoveEffectPacket(int entityId, Effect effect) { this.entityId = entityId; this.effect = effect; - this.amplifier = amplifier; - this.duration = duration; } public int getEntityId() { @@ -31,29 +27,17 @@ public class ServerEntityRemoveEffectPacket implements Packet { public Effect getEffect() { return this.effect; } - - public int getAmplifier() { - return this.amplifier; - } - - public int getDuration() { - return this.duration; - } @Override public void read(NetInput in) throws IOException { - this.entityId = in.readInt(); + this.entityId = in.readVarInt(); this.effect = Effect.values()[in.readByte()]; - this.amplifier = in.readByte(); - this.duration = in.readShort(); } @Override public void write(NetOutput out) throws IOException { - out.writeInt(this.entityId); + out.writeVarInt(this.entityId); out.writeByte(this.effect.ordinal()); - out.writeByte(this.amplifier); - out.writeShort(this.duration); } @Override diff --git a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityTeleportPacket.java b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityTeleportPacket.java index 9928b999..c3bb93c3 100644 --- a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityTeleportPacket.java +++ b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityTeleportPacket.java @@ -54,7 +54,7 @@ public class ServerEntityTeleportPacket implements Packet { @Override public void read(NetInput in) throws IOException { - this.entityId = in.readInt(); + this.entityId = in.readVarInt(); this.x = in.readInt() / 32D; this.y = in.readInt() / 32D; this.z = in.readInt() / 32D; @@ -64,7 +64,7 @@ public class ServerEntityTeleportPacket implements Packet { @Override public void write(NetOutput out) throws IOException { - out.writeInt(this.entityId); + out.writeVarInt(this.entityId); out.writeInt((int) (this.x * 32)); out.writeInt((int) (this.y * 32)); out.writeInt((int) (this.z * 32)); diff --git a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityVelocityPacket.java b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityVelocityPacket.java index 0e13f186..e0176920 100644 --- a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityVelocityPacket.java +++ b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/ServerEntityVelocityPacket.java @@ -42,7 +42,7 @@ public class ServerEntityVelocityPacket implements Packet { @Override public void read(NetInput in) throws IOException { - this.entityId = in.readInt(); + this.entityId = in.readVarInt(); this.motX = in.readShort() / 8000D; this.motY = in.readShort() / 8000D; this.motZ = in.readShort() / 8000D; @@ -50,7 +50,7 @@ public class ServerEntityVelocityPacket implements Packet { @Override public void write(NetOutput out) throws IOException { - out.writeInt(this.entityId); + out.writeVarInt(this.entityId); out.writeShort((int) (this.motX * 8000)); out.writeShort((int) (this.motY * 8000)); out.writeShort((int) (this.motZ * 8000)); diff --git a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/player/ServerPlayerUseBedPacket.java b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/player/ServerPlayerUseBedPacket.java index 33261509..90a41b31 100644 --- a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/player/ServerPlayerUseBedPacket.java +++ b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/player/ServerPlayerUseBedPacket.java @@ -32,13 +32,13 @@ public class ServerPlayerUseBedPacket implements Packet { @Override public void read(NetInput in) throws IOException { - this.entityId = in.readInt(); + this.entityId = in.readVarInt(); this.position = NetUtil.readPosition(in); } @Override public void write(NetOutput out) throws IOException { - out.writeInt(this.entityId); + out.writeVarInt(this.entityId); NetUtil.writePosition(out, this.position); } diff --git a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/player/ServerSetExperiencePacket.java b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/player/ServerSetExperiencePacket.java index 1df92cfe..a45b828f 100644 --- a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/player/ServerSetExperiencePacket.java +++ b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/player/ServerSetExperiencePacket.java @@ -37,15 +37,15 @@ public class ServerSetExperiencePacket implements Packet { @Override public void read(NetInput in) throws IOException { this.experience = in.readFloat(); - this.level = in.readShort(); - this.totalExperience = in.readShort(); + this.level = in.readVarInt(); + this.totalExperience = in.readVarInt(); } @Override public void write(NetOutput out) throws IOException { out.writeFloat(this.experience); - out.writeShort(this.level); - out.writeShort(this.totalExperience); + out.writeVarInt(this.level); + out.writeVarInt(this.totalExperience); } @Override diff --git a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/player/ServerUpdateHealthPacket.java b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/player/ServerUpdateHealthPacket.java index 362bf1e9..82ff2155 100644 --- a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/player/ServerUpdateHealthPacket.java +++ b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/player/ServerUpdateHealthPacket.java @@ -37,14 +37,14 @@ public class ServerUpdateHealthPacket implements Packet { @Override public void read(NetInput in) throws IOException { this.health = in.readFloat(); - this.food = in.readShort(); + this.food = in.readVarInt(); this.saturation = in.readFloat(); } @Override public void write(NetOutput out) throws IOException { out.writeFloat(this.health); - out.writeShort(this.food); + out.writeVarInt(this.food); out.writeFloat(this.saturation); } diff --git a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/spawn/ServerSpawnPaintingPacket.java b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/spawn/ServerSpawnPaintingPacket.java index b46370d7..68f77baa 100644 --- a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/spawn/ServerSpawnPaintingPacket.java +++ b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/spawn/ServerSpawnPaintingPacket.java @@ -2,6 +2,8 @@ package ch.spacebase.mc.protocol.packet.ingame.server.entity.spawn; import java.io.IOException; +import ch.spacebase.mc.protocol.data.game.Position; +import ch.spacebase.mc.util.NetUtil; import ch.spacebase.packetlib.io.NetInput; import ch.spacebase.packetlib.io.NetOutput; import ch.spacebase.packetlib.packet.Packet; @@ -10,21 +12,17 @@ public class ServerSpawnPaintingPacket implements Packet { private int entityId; private Art art; - private int x; - private int y; - private int z; + private Position position; private Direction direction; @SuppressWarnings("unused") private ServerSpawnPaintingPacket() { } - public ServerSpawnPaintingPacket(int entityId, Art art, int x, int y, int z, Direction direction) { + public ServerSpawnPaintingPacket(int entityId, Art art, Position position, Direction direction) { this.entityId = entityId; this.art = art; - this.x = x; - this.y = y; - this.z = z; + this.position = position; this.direction = direction; } @@ -36,16 +34,8 @@ public class ServerSpawnPaintingPacket implements Packet { return this.art; } - public int getX() { - return this.x; - } - - public int getY() { - return this.y; - } - - public int getZ() { - return this.z; + public Position getPosition() { + return this.position; } public Direction getDirection() { @@ -56,20 +46,16 @@ public class ServerSpawnPaintingPacket implements Packet { public void read(NetInput in) throws IOException { this.entityId = in.readVarInt(); this.art = Art.valueOf(in.readString()); - this.x = in.readInt(); - this.y = in.readInt(); - this.z = in.readInt(); - this.direction = Direction.values()[in.readInt()]; + this.position = NetUtil.readPosition(in); + this.direction = Direction.values()[in.readUnsignedByte()]; } @Override public void write(NetOutput out) throws IOException { out.writeVarInt(this.entityId); out.writeString(this.art.name()); - out.writeInt(this.x); - out.writeInt(this.y); - out.writeInt(this.z); - out.writeInt(this.direction.ordinal()); + NetUtil.writePosition(out, this.position); + out.writeByte(this.direction.ordinal()); } @Override diff --git a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/spawn/ServerSpawnPlayerPacket.java b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/spawn/ServerSpawnPlayerPacket.java index 0cc5dcaf..c4121e1a 100644 --- a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/spawn/ServerSpawnPlayerPacket.java +++ b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/entity/spawn/ServerSpawnPlayerPacket.java @@ -2,6 +2,8 @@ package ch.spacebase.mc.protocol.packet.ingame.server.entity.spawn; import java.io.IOException; +import ch.spacebase.mc.auth.GameProfile; +import ch.spacebase.mc.auth.ProfileProperty; import ch.spacebase.mc.protocol.data.game.EntityMetadata; import ch.spacebase.mc.util.NetUtil; import ch.spacebase.packetlib.io.NetInput; @@ -11,8 +13,7 @@ import ch.spacebase.packetlib.packet.Packet; public class ServerSpawnPlayerPacket implements Packet { private int entityId; - private String uuid; - private String name; + private GameProfile profile; private double x; private double y; private double z; @@ -25,10 +26,9 @@ public class ServerSpawnPlayerPacket implements Packet { private ServerSpawnPlayerPacket() { } - public ServerSpawnPlayerPacket(int entityId, String uuid, String name, double x, double y, double z, float yaw, float pitch, int currentItem, EntityMetadata metadata[]) { + public ServerSpawnPlayerPacket(int entityId, GameProfile profile, double x, double y, double z, float yaw, float pitch, int currentItem, EntityMetadata metadata[]) { this.entityId = entityId; - this.uuid = uuid; - this.name = name; + this.profile = profile; this.x = x; this.y = y; this.z = z; @@ -42,12 +42,8 @@ public class ServerSpawnPlayerPacket implements Packet { return this.entityId; } - public String getUUID() { - return this.uuid; - } - - public String getName() { - return this.name; + public GameProfile getProfile() { + return this.profile; } public double getX() { @@ -81,8 +77,14 @@ public class ServerSpawnPlayerPacket implements Packet { @Override public void read(NetInput in) throws IOException { this.entityId = in.readVarInt(); - this.uuid = in.readString(); - this.name = in.readString(); + this.profile = new GameProfile(in.readString(), in.readString()); + for(int count = 0; count < in.readVarInt(); count++) { + String name = in.readString(); + String value = in.readString(); + String signature = in.readString(); + this.profile.getProperties().put(name, new ProfileProperty(name, value, signature)); + } + this.x = in.readInt() / 32D; this.y = in.readInt() / 32D; this.z = in.readInt() / 32D; @@ -95,8 +97,15 @@ public class ServerSpawnPlayerPacket implements Packet { @Override public void write(NetOutput out) throws IOException { out.writeVarInt(this.entityId); - out.writeString(this.uuid); - out.writeString(this.name); + out.writeString(this.profile.getId()); + out.writeString(this.profile.getName()); + out.writeVarInt(this.profile.getProperties().size()); + for(ProfileProperty property : this.profile.getProperties().values()) { + out.writeString(property.getName()); + out.writeString(property.getValue()); + out.writeString(property.getSignature()); + } + out.writeInt((int) (this.x * 32)); out.writeInt((int) (this.y * 32)); out.writeInt((int) (this.z * 32)); diff --git a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/scoreboard/ServerScoreboardObjectivePacket.java b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/scoreboard/ServerScoreboardObjectivePacket.java index 48c09663..99ff5a46 100644 --- a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/scoreboard/ServerScoreboardObjectivePacket.java +++ b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/scoreboard/ServerScoreboardObjectivePacket.java @@ -9,16 +9,16 @@ import ch.spacebase.packetlib.packet.Packet; public class ServerScoreboardObjectivePacket implements Packet { private String name; - private String value; + private String displayName; private Action action; @SuppressWarnings("unused") private ServerScoreboardObjectivePacket() { } - public ServerScoreboardObjectivePacket(String name, String value, Action action) { + public ServerScoreboardObjectivePacket(String name, String displayName, Action action) { this.name = name; - this.value = value; + this.displayName = displayName; this.action = action; } @@ -26,8 +26,8 @@ public class ServerScoreboardObjectivePacket implements Packet { return this.name; } - public String getValue() { - return this.value; + public String getDisplayName() { + return this.displayName; } public Action getAction() { @@ -37,14 +37,14 @@ public class ServerScoreboardObjectivePacket implements Packet { @Override public void read(NetInput in) throws IOException { this.name = in.readString(); - this.value = in.readString(); + this.displayName = in.readString(); this.action = Action.values()[in.readByte()]; } @Override public void write(NetOutput out) throws IOException { out.writeString(this.name); - out.writeString(this.value); + out.writeString(this.displayName); out.writeByte(this.action.ordinal()); } diff --git a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/scoreboard/ServerTeamPacket.java b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/scoreboard/ServerTeamPacket.java index 4fc72452..33072b95 100644 --- a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/scoreboard/ServerTeamPacket.java +++ b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/scoreboard/ServerTeamPacket.java @@ -95,7 +95,7 @@ public class ServerTeamPacket implements Packet { } if(this.action == Action.CREATE || this.action == Action.ADD_PLAYER || this.action == Action.REMOVE_PLAYER) { - this.players = new String[in.readShort()]; + this.players = new String[in.readVarInt()]; for(int index = 0; index < this.players.length; index++) { this.players[index] = in.readString(); } @@ -114,7 +114,7 @@ public class ServerTeamPacket implements Packet { } if(this.action == Action.CREATE || this.action == Action.ADD_PLAYER || this.action == Action.REMOVE_PLAYER) { - out.writeShort(this.players.length); + out.writeVarInt(this.players.length); for(String player : this.players) { out.writeString(player); } diff --git a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/scoreboard/ServerUpdateScorePacket.java b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/scoreboard/ServerUpdateScorePacket.java index ea7b526c..a3b76c4f 100644 --- a/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/scoreboard/ServerUpdateScorePacket.java +++ b/src/main/java/ch/spacebase/mc/protocol/packet/ingame/server/scoreboard/ServerUpdateScorePacket.java @@ -8,60 +8,60 @@ import ch.spacebase.packetlib.packet.Packet; public class ServerUpdateScorePacket implements Packet { - private String name; + private String entry; private Action action; - private String scoreName; - private int scoreValue; + private String objective; + private int value; @SuppressWarnings("unused") private ServerUpdateScorePacket() { } - public ServerUpdateScorePacket(String name) { - this.name = name; + public ServerUpdateScorePacket(String entry) { + this.entry = entry; this.action = Action.REMOVE; } - public ServerUpdateScorePacket(String name, String scoreName, int scoreValue) { - this.name = name; - this.scoreName = scoreName; - this.scoreValue = scoreValue; + public ServerUpdateScorePacket(String entry, String objective, int value) { + this.entry = entry; + this.objective = objective; + this.value = value; this.action = Action.ADD_OR_UPDATE; } - public String getScoreboardName() { - return this.name; + public String getEntry() { + return this.entry; } public Action getAction() { return this.action; } - public String getScoreName() { - return this.scoreName; + public String getObjective() { + return this.objective; } - public int getScoreValue() { - return this.scoreValue; + public int getValue() { + return this.value; } @Override public void read(NetInput in) throws IOException { - this.name = in.readString(); + this.entry = in.readString(); this.action = Action.values()[in.readByte()]; if(this.action == Action.ADD_OR_UPDATE) { - this.scoreName = in.readString(); - this.scoreValue = in.readInt(); + this.objective = in.readString(); + this.value = in.readVarInt(); } } @Override public void write(NetOutput out) throws IOException { - out.writeString(this.name); + out.writeString(this.entry); out.writeByte(this.action.ordinal()); if(this.action == Action.ADD_OR_UPDATE) { - out.writeString(this.scoreName); - out.writeInt(this.scoreValue); + out.writeString(this.objective); + out.writeVarInt(this.value); } } diff --git a/src/main/java/ch/spacebase/mc/util/IOUtils.java b/src/main/java/ch/spacebase/mc/util/IOUtils.java index 09e246ce..b0550518 100644 --- a/src/main/java/ch/spacebase/mc/util/IOUtils.java +++ b/src/main/java/ch/spacebase/mc/util/IOUtils.java @@ -1,5 +1,6 @@ package ch.spacebase.mc.util; +import java.io.ByteArrayOutputStream; import java.io.Closeable; import java.io.IOException; import java.io.InputStream; @@ -31,5 +32,18 @@ public class IOUtils { in.close(); return writer.toString(); } + + public static byte[] toByteArray(InputStream in) throws IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + byte buffer[] = new byte[DEFAULT_BUFFER_SIZE]; + int n = 0; + while(-1 != (n = in.read(buffer))) { + out.write(buffer, 0, n); + } + + in.close(); + out.close(); + return out.toByteArray(); + } } diff --git a/src/main/java/ch/spacebase/mc/util/NetUtil.java b/src/main/java/ch/spacebase/mc/util/NetUtil.java index f2d894b4..18ba115e 100644 --- a/src/main/java/ch/spacebase/mc/util/NetUtil.java +++ b/src/main/java/ch/spacebase/mc/util/NetUtil.java @@ -22,10 +22,44 @@ import ch.spacebase.packetlib.io.NetOutput; public class NetUtil { + private static final int[] EXPONENTS_OF_TWO = new int[] { 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 }; + + private static final int POSITION_X_SIZE = 1 + lastExponentOfTwo(nextPowerOfTwo(30000000)); + private static final int POSITION_Z_SIZE = POSITION_X_SIZE; + private static final int POSITION_Y_SIZE = 64 - POSITION_X_SIZE - POSITION_Z_SIZE; + private static final int POSITION_Y_SHIFT = POSITION_Z_SIZE; + private static final int POSITION_X_SHIFT = POSITION_Y_SHIFT + POSITION_Y_SIZE; + private static final long POSITION_X_MASK = (1L << POSITION_X_SIZE) - 1; + private static final long POSITION_Y_MASK = (1L << POSITION_Y_SIZE) - 1; + private static final long POSITION_Z_MASK = (1L << POSITION_Z_SIZE) - 1; + /** * An unfortunately necessary hack value for chunk data packet checks as to whether a packet contains skylight values or not. */ public static boolean hasSky = true; + + private static int nextPowerOfTwo(int i) { + int minusOne = i - 1; + minusOne |= minusOne >> 1; + minusOne |= minusOne >> 2; + minusOne |= minusOne >> 4; + minusOne |= minusOne >> 8; + minusOne |= minusOne >> 16; + return minusOne + 1; + } + + private static boolean isPowerOfTwo(int i) { + return i != 0 && (i & i - 1) == 0; + } + + private static int nextExponentOfTwo(int i) { + int power = isPowerOfTwo(i) ? i : nextPowerOfTwo(i); + return EXPONENTS_OF_TWO[(int) (power * 125613361L >> 27) & 31]; + } + + public static int lastExponentOfTwo(int i) { + return nextExponentOfTwo(i) - (isPowerOfTwo(i) ? 0 : 1); + } public static CompoundTag readNBT(NetInput in) throws IOException { short length = in.readShort(); @@ -50,13 +84,15 @@ public class NetUtil { } public static Position readPosition(NetInput in) throws IOException { - return new Position(in.readInt(), in.readUnsignedByte(), in.readInt()); + long val = in.readLong(); + int x = (int) (val << 64 - POSITION_X_SHIFT - POSITION_X_SIZE >> 64 - POSITION_X_SIZE); + int y = (int) (val << 64 - POSITION_Y_SHIFT - POSITION_Y_SIZE >> 64 - POSITION_Y_SIZE); + int z = (int) (val << 64 - POSITION_Z_SIZE >> 64 - POSITION_Z_SIZE); + return new Position(x, y, z); } - + public static void writePosition(NetOutput out, Position pos) throws IOException { - out.writeInt(pos.getX()); - out.writeByte(pos.getY()); - out.writeInt(pos.getZ()); + out.writeLong((pos.getX() & POSITION_X_MASK) << POSITION_X_SHIFT | (pos.getY() & POSITION_Y_MASK) << POSITION_Y_SHIFT | (pos.getZ() & POSITION_Z_MASK)); } public static ItemStack readItem(NetInput in) throws IOException { diff --git a/src/main/resources/yggdrasil_session_pubkey.der b/src/main/resources/yggdrasil_session_pubkey.der new file mode 100644 index 00000000..9c79a3aa Binary files /dev/null and b/src/main/resources/yggdrasil_session_pubkey.der differ