diff --git a/src/main/java/org/runejs/client/cache/media/AnimationSequence.java b/src/main/java/org/runejs/client/cache/media/AnimationSequence.java index e05c04b8d..455f7991d 100644 --- a/src/main/java/org/runejs/client/cache/media/AnimationSequence.java +++ b/src/main/java/org/runejs/client/cache/media/AnimationSequence.java @@ -63,10 +63,8 @@ public static void loadTerrainBlock(CollisionMap[] collisions, int regionX_maybe } } - public static boolean method596(int arg0, int arg1, byte arg2, int arg3) { + public static boolean method596(int arg0, int arg1, byte junk, int arg3) { int i = 0x7fff & arg1 >> 14; - if(arg2 > -9) - method596(-4, -74, (byte) -44, -62); int i_14_ = Npc.currentScene.getArrangement(Player.worldLevel, arg0, arg3, arg1); if(i_14_ == -1) return false; diff --git a/src/main/java/org/runejs/client/cache/media/gameInterface/GameInterface.java b/src/main/java/org/runejs/client/cache/media/gameInterface/GameInterface.java index 7d3eec022..4fd9f5ca1 100644 --- a/src/main/java/org/runejs/client/cache/media/gameInterface/GameInterface.java +++ b/src/main/java/org/runejs/client/cache/media/gameInterface/GameInterface.java @@ -17,7 +17,9 @@ import org.runejs.client.media.renderable.actor.Pathfinding; import org.runejs.client.media.renderable.actor.Player; import org.runejs.client.media.renderable.actor.PlayerAppearance; +import org.runejs.client.message.outbound.interactions.ObjectInteractionOutboundMessage; import org.runejs.client.net.ISAAC; +import org.runejs.client.net.OutgoingPackets; import org.runejs.client.net.PacketBuffer; import org.runejs.client.node.CachedNode; import org.runejs.client.scene.InteractiveObject; @@ -584,10 +586,19 @@ public static void processMenuActions(int arg1) { } if(action == ActionRowType.INTERACT_WITH_OBJECT_OPTION_4.getId()) { AnimationSequence.method596(i, npcIdx, (byte) -79, i_10_); - SceneCluster.packetBuffer.putPacket(229); - SceneCluster.packetBuffer.putShortLE(MovedStatics.baseX + i); - SceneCluster.packetBuffer.putShortLE((0x1ffffd20 & npcIdx) >> 14); - SceneCluster.packetBuffer.putShortLE(Class26.baseY + i_10_); + + int objectX = MovedStatics.baseX + i; + int objectId = (0x1ffffd20 & npcIdx) >> 14; + int objectY = Class26.baseY + i_10_; + + OutgoingPackets.sendMessage( + new ObjectInteractionOutboundMessage( + 4, + objectId, + objectX, + objectY + ) + ); } if(action == ActionRowType.CAST_MAGIC_ON_PLAYER.getId()) { Player class40_sub5_sub17_sub4_sub1 = Player.trackedPlayers[npcIdx]; @@ -835,10 +846,19 @@ public static void processMenuActions(int arg1) { } if(action == ActionRowType.INTERACT_WITH_OBJECT_OPTION_5.getId()) { AnimationSequence.method596(i, npcIdx, (byte) -11, i_10_); - SceneCluster.packetBuffer.putPacket(62); - SceneCluster.packetBuffer.putShortBE((0x1fffd05d & npcIdx) >> 14); - SceneCluster.packetBuffer.putShortLE(i_10_ + Class26.baseY); - SceneCluster.packetBuffer.putShortLE(i + MovedStatics.baseX); + + int objectId = (0x1ffffd20 & npcIdx) >> 14; + int objectY = i_10_ + Class26.baseY; + int objectX = i + MovedStatics.baseX; + + OutgoingPackets.sendMessage( + new ObjectInteractionOutboundMessage( + 5, + objectId, + objectX, + objectY + ) + ); } if(action == ActionRowType.INTERACT_WITH_NPC_OPTION_2.getId()) { Npc class40_sub5_sub17_sub4_sub2 = Player.npcs[npcIdx]; @@ -869,10 +889,19 @@ public static void processMenuActions(int arg1) { } if(action == ActionRowType.INTERACT_WITH_OBJECT_OPTION_2.getId()) { AnimationSequence.method596(i, npcIdx, (byte) -77, i_10_); - SceneCluster.packetBuffer.putPacket(164); - SceneCluster.packetBuffer.putShortLE(MovedStatics.baseX + i); - SceneCluster.packetBuffer.putShortLE(Class26.baseY + i_10_); - SceneCluster.packetBuffer.putShortLE(npcIdx >> 14 & 0x7fff); + + int objectX = i + MovedStatics.baseX; + int objectY = i_10_ + Class26.baseY; + int objectId = npcIdx >> 14 & 0x7fff; + + OutgoingPackets.sendMessage( + new ObjectInteractionOutboundMessage( + 2, + objectId, + objectX, + objectY + ) + ); } if(action == ActionRowType.USE_ITEM_ON_OBJECT.getId() && AnimationSequence.method596(i, npcIdx, (byte) -104, i_10_)) { SceneCluster.packetBuffer.putPacket(24); @@ -1080,10 +1109,19 @@ public static void processMenuActions(int arg1) { } if(action == ActionRowType.INTERACT_WITH_OBJECT_OPTION_3.getId()) { AnimationSequence.method596(i, npcIdx, (byte) -104, i_10_); - SceneCluster.packetBuffer.putPacket(183); - SceneCluster.packetBuffer.putShortBE(i_10_ + Class26.baseY); - SceneCluster.packetBuffer.putShortBE(npcIdx >> 14 & 0x7fff); - SceneCluster.packetBuffer.putShortBE(i + MovedStatics.baseX); + + int objectY = i_10_ + Class26.baseY; + int objectId = npcIdx >> 14 & 0x7fff; + int objectX = i + MovedStatics.baseX; + + OutgoingPackets.sendMessage( + new ObjectInteractionOutboundMessage( + 3, + objectId, + objectX, + objectY + ) + ); } if(action == 50) { Class33.method406(i, npcIdx, i_10_); @@ -1241,10 +1279,18 @@ public static void processMenuActions(int arg1) { } if(action == ActionRowType.INTERACT_WITH_OBJECT_OPTION_1.getId()) { AnimationSequence.method596(i, npcIdx, (byte) -47, i_10_); - SceneCluster.packetBuffer.putPacket(30); - SceneCluster.packetBuffer.putShortBE(0x7fff & npcIdx >> 14); - SceneCluster.packetBuffer.putShortBE(Class26.baseY + i_10_); - SceneCluster.packetBuffer.putShortLE(i + MovedStatics.baseX); + int objectId = 0x7fff & npcIdx >> 14; + int objectX = i + MovedStatics.baseX; + int objectY = i_10_ + Class26.baseY; + + OutgoingPackets.sendMessage( + new ObjectInteractionOutboundMessage( + 1, + objectId, + objectX, + objectY + ) + ); } if(action == ActionRowType.INTERACT_WITH_NPC_OPTION_5.getId()) { Npc class40_sub5_sub17_sub4_sub2 = Player.npcs[npcIdx]; diff --git a/src/main/java/org/runejs/client/message/outbound/interactions/ObjectInteractionOutboundMessage.java b/src/main/java/org/runejs/client/message/outbound/interactions/ObjectInteractionOutboundMessage.java new file mode 100644 index 000000000..9447c234e --- /dev/null +++ b/src/main/java/org/runejs/client/message/outbound/interactions/ObjectInteractionOutboundMessage.java @@ -0,0 +1,39 @@ +package org.runejs.client.message.outbound.interactions; + +import org.runejs.client.message.OutboundMessage; + +/** + * Represents a message sent to the server when a player interacts with an object. + * + * e.g. clicking on a tree to chop it down + */ +public class ObjectInteractionOutboundMessage implements OutboundMessage { + /** + * Which option on the object was clicked + * + * i.e. 1 = first option, 2 = second option, etc. + */ + public final int option; + + /** + * The id of the object + */ + public final int objectId; + + /** + * The x coordinate of the object + */ + public final int x; + + /** + * The y coordinate of the object + */ + public final int y; + + public ObjectInteractionOutboundMessage(int option, int objectId, int x, int y) { + this.option = option; + this.objectId = objectId; + this.x = x; + this.y = y; + } +} diff --git a/src/main/java/org/runejs/client/net/OutgoingPackets.java b/src/main/java/org/runejs/client/net/OutgoingPackets.java index 786b3d72f..9a855f097 100644 --- a/src/main/java/org/runejs/client/net/OutgoingPackets.java +++ b/src/main/java/org/runejs/client/net/OutgoingPackets.java @@ -17,6 +17,8 @@ public static void init(ISAAC outCipher) { /** * Opens a fixed-size packet with the specified opcode. + * + * @param size The size of the packet in bytes, not including the opcode. */ public static PacketBuffer openFixedSizePacket(int size, int opcode) { // data + 1 byte for opcode diff --git a/src/main/java/org/runejs/client/net/codec/runejs435/RuneJS435PacketCodec.java b/src/main/java/org/runejs/client/net/codec/runejs435/RuneJS435PacketCodec.java index facfeed95..8335d69ab 100644 --- a/src/main/java/org/runejs/client/net/codec/runejs435/RuneJS435PacketCodec.java +++ b/src/main/java/org/runejs/client/net/codec/runejs435/RuneJS435PacketCodec.java @@ -1,10 +1,10 @@ package org.runejs.client.net.codec.runejs435; +import org.runejs.client.message.outbound.interactions.ObjectInteractionOutboundMessage; import org.runejs.client.net.PacketType; import org.runejs.client.net.codec.MessagePacketCodec; -import org.runejs.client.net.codec.runejs435.decoder.audio.PlayQuickSongMessageDecoder; -import org.runejs.client.net.codec.runejs435.decoder.audio.PlaySongMessageDecoder; -import org.runejs.client.net.codec.runejs435.decoder.audio.PlaySoundMessageDecoder; +import org.runejs.client.net.codec.runejs435.encoder.*; +import org.runejs.client.net.codec.runejs435.decoder.*; /** * A {@link MessagePacketCodec} for the RuneJS customised 435 protocol. @@ -18,6 +18,7 @@ public RuneJS435PacketCodec() { } private void registerEncoders() { + register(ObjectInteractionOutboundMessage.class, new ObjectInteractionMessageEncoder()); } private void registerDecoders() { diff --git a/src/main/java/org/runejs/client/net/codec/runejs435/encoder/interactions/ObjectInteractionMessageEncoder.java b/src/main/java/org/runejs/client/net/codec/runejs435/encoder/interactions/ObjectInteractionMessageEncoder.java new file mode 100644 index 000000000..59e34a6c0 --- /dev/null +++ b/src/main/java/org/runejs/client/net/codec/runejs435/encoder/interactions/ObjectInteractionMessageEncoder.java @@ -0,0 +1,78 @@ +package org.runejs.client.net.codec.runejs435.encoder.interactions; + +import org.runejs.client.message.outbound.interactions.ObjectInteractionOutboundMessage; +import org.runejs.client.net.OutgoingPackets; +import org.runejs.client.net.PacketBuffer; +import org.runejs.client.net.codec.MessageEncoder; + +public class ObjectInteractionMessageEncoder implements MessageEncoder { + + @Override + public PacketBuffer encode(ObjectInteractionOutboundMessage message) { + switch (message.option) { + case 1: + return encodeOption1Interaction(message); + case 2: + return encodeOption2Interaction(message); + case 3: + return encodeOption3Interaction(message); + case 4: + return encodeOption4Interaction(message); + case 5: + return encodeOption5Interaction(message); + default: + throw new RuntimeException("Invalid option: " + message.option); + } + } + + private PacketBuffer encodeOption1Interaction(ObjectInteractionOutboundMessage message) { + PacketBuffer buffer = OutgoingPackets.openFixedSizePacket(6, 30); + + buffer.putShortBE(message.objectId); + buffer.putShortBE(message.y); + buffer.putShortLE(message.x); + + return buffer; + } + + private PacketBuffer encodeOption2Interaction(ObjectInteractionOutboundMessage message) { + PacketBuffer buffer = OutgoingPackets.openFixedSizePacket(6, 164); + + buffer.putShortLE(message.x); + buffer.putShortLE(message.y); + buffer.putShortLE(message.objectId); + + return buffer; + } + + private PacketBuffer encodeOption3Interaction(ObjectInteractionOutboundMessage message) { + PacketBuffer buffer = OutgoingPackets.openFixedSizePacket(6, 183); + + buffer.putShortBE(message.y); + buffer.putShortBE(message.objectId); + buffer.putShortBE(message.x); + + return buffer; + } + + private PacketBuffer encodeOption4Interaction(ObjectInteractionOutboundMessage message) { + PacketBuffer buffer = OutgoingPackets.openFixedSizePacket(6, 229); + + buffer.putShortLE(message.x); + buffer.putShortLE(message.objectId); + buffer.putShortLE(message.y); + + return buffer; + } + + private PacketBuffer encodeOption5Interaction(ObjectInteractionOutboundMessage message) { + PacketBuffer buffer = OutgoingPackets.openFixedSizePacket(6, 62); + + buffer.putShortBE(message.objectId); + buffer.putShortLE(message.y); + buffer.putShortLE(message.x); + + return buffer; + } + +}