Alright, so this is the release of a request presented to me by Rookie. Credits to him for making me aware of how the packets are presently handled in Matrix, and also motivating me to get off my ass and actually do something. After I found out that all the packets were handled with if-statements, I couldn't help but feel sick. So, I rewrote them as per Rookie's request.
You'll need some things to get you started. You'll need to create a packets package. This will contain two interfaces. One for handling the game logic packets, the other for just the world packets, and also the "Packet Manager", which we will use to assign the opcodes their appropriate handlers. Please excuse the packet sizes, writing this now I just realised that I never got around to making that more concise. Oh well. This is just so that everything is more clean and organised.
Code:
package org.murlock.net.packets;
import org.murlock.game.player.LogicPacket;
import org.murlock.game.player.Player;
import org.murlock.io.InputStream;
/**
* @author Belzebu <http://www.rune-server.ee/members/Belzebu>
*/
public interface LogicPacketHandler {
/**
* Abstract void that will be implemented into
* our logic packet handlers
*
* @param packet
* The packet to handle
*
* @param player
* The player sending the packet
*
* @param stream
* The input stream of the player
*/
public void handleLogic(LogicPacket packet, Player player, InputStream stream);
}
Code:
package org.murlock.net.packets;
import org.murlock.game.player.Player;
import org.murlock.io.InputStream;
/**
* @author Belzebu <http://www.rune-server.ee/members/Belzebu>
*/
public interface PacketHandler {
/**
* Abstract void that will be implemented into
* our logic packet handlers
*
* @param packetId
* The id of the packet to handle
*
* @param player
* The player sending the packet
*
* @param stream
* The input stream of the player
*/
public void handle(int packetId, Player player, InputStream stream, int length);
}
Code:
package org.murlock.net.packets;
import org.murlock.game.player.LogicPacket;
import org.murlock.game.player.Player;
import org.murlock.io.InputStream;
import org.murlock.net.packets.impl.*;
import org.murlock.net.packets.impl.chat.*;
import org.murlock.net.packets.impl.clan.*;
import org.murlock.net.packets.impl.dialogue.*;
import org.murlock.net.packets.impl.fc.*;
import org.murlock.net.packets.impl.friends.*;
import org.murlock.net.packets.impl.logic.*;
import org.murlock.net.packets.impl.misc.*;
import org.murlock.net.packets.impl.region.DoneLoadingRegionPacketHandler;
/**
* @author Belzebu <http://www.rune-server.ee/members/Belzebu>
*/
public class PacketManager {
/**
* A byte array containing the sizes
* of the different packet types
*/
public static final byte[] PACKET_SIZES = new byte[256];
/**
* The array of logic packet handlers
*/
private static final LogicPacketHandler[] logicHandler = new LogicPacketHandler[256];
/**
* The array of packet handlers
*/
private static final PacketHandler[] handler = new PacketHandler[256];
/**
* The constructor for the packet manager,
* which also sets the packet sizes
*/
public PacketManager() {
for (int id = 0; id < 256; id++)
PACKET_SIZES[id] = -4;
PACKET_SIZES[64] = 8;
PACKET_SIZES[18] = 8;
PACKET_SIZES[25] = 8;
PACKET_SIZES[41] = -1;
PACKET_SIZES[14] = 3;
PACKET_SIZES[46] = 3;
PACKET_SIZES[87] = 6;
PACKET_SIZES[47] = 9;
PACKET_SIZES[57] = 3;
PACKET_SIZES[67] = 3;
PACKET_SIZES[91] = 8;
PACKET_SIZES[24] = 7;
PACKET_SIZES[73] = 16;
PACKET_SIZES[40] = 11;
PACKET_SIZES[36] = -1;
PACKET_SIZES[74] = -1;
PACKET_SIZES[31] = 3;
PACKET_SIZES[54] = 6;
PACKET_SIZES[12] = -1;
PACKET_SIZES[23] = 1;
PACKET_SIZES[9] = 3;
PACKET_SIZES[17] = -1;
PACKET_SIZES[44] = -1;
PACKET_SIZES[88] = -1;
PACKET_SIZES[42] = 17;
PACKET_SIZES[49] = 3;
PACKET_SIZES[21] = 15;
PACKET_SIZES[59] = -1;
PACKET_SIZES[37] = -1;
PACKET_SIZES[6] = 8;
PACKET_SIZES[55] = 7;
PACKET_SIZES[69] = 9;
PACKET_SIZES[26] = 16;
PACKET_SIZES[39] = 12;
PACKET_SIZES[71] = 4;
PACKET_SIZES[22] = 2;
PACKET_SIZES[32] = -1;
PACKET_SIZES[79] = -1;
PACKET_SIZES[89] = 4;
PACKET_SIZES[90] = -1;
PACKET_SIZES[15] = 4;
PACKET_SIZES[72] = -2;
PACKET_SIZES[20] = 8;
PACKET_SIZES[92] = 3;
PACKET_SIZES[82] = 3;
PACKET_SIZES[28] = 3;
PACKET_SIZES[81] = 8;
PACKET_SIZES[7] = -1;
PACKET_SIZES[4] = 8;
PACKET_SIZES[60] = -1;
PACKET_SIZES[13] = 2;
PACKET_SIZES[52] = 8;
PACKET_SIZES[65] = 11;
PACKET_SIZES[85] = 2;
PACKET_SIZES[86] = 7;
PACKET_SIZES[78] = -1;
PACKET_SIZES[83] = -1;
PACKET_SIZES[27] = 7;
PACKET_SIZES[2] = 9;
PACKET_SIZES[93] = 1;
PACKET_SIZES[70] = -1;
PACKET_SIZES[1] = -1;
PACKET_SIZES[8] = -1;
PACKET_SIZES[11] = 9;
PACKET_SIZES[0] = 9;
PACKET_SIZES[51] = -1;
PACKET_SIZES[5] = 4;
PACKET_SIZES[45] = 7;
PACKET_SIZES[75] = 4;
PACKET_SIZES[53] = 3;
PACKET_SIZES[33] = 0;
PACKET_SIZES[50] = 3;
PACKET_SIZES[76] = 9;
PACKET_SIZES[80] = -1;
PACKET_SIZES[77] = 3;
PACKET_SIZES[68] = -1;
PACKET_SIZES[43] = 3;
PACKET_SIZES[30] = -1;
PACKET_SIZES[19] = 3;
PACKET_SIZES[16] = 0;
PACKET_SIZES[34] = 4;
PACKET_SIZES[48] = 0;
PACKET_SIZES[56] = 0;
PACKET_SIZES[58] = 2;
PACKET_SIZES[10] = 8;
PACKET_SIZES[35] = 7;
PACKET_SIZES[84] = 6;
PACKET_SIZES[66] = 3;
PACKET_SIZES[61] = 8;
PACKET_SIZES[29] = -1;
PACKET_SIZES[62] = 3;
PACKET_SIZES[3] = 4;
PACKET_SIZES[63] = 4;
PACKET_SIZES[73] = 16;
PACKET_SIZES[38] = -1;
}
/**
* Default method for handling logic packets
*
* @param packet
* The packet to handle
*
* @param player
* The player sending the packet
*
* @param stream
* The input stream of the player
*/
public static void handleLogic(LogicPacket packet, Player player, InputStream stream) {
if (logicHandler[packet.getId()] != null) {
logicHandler[packet.getId()].handleLogic(packet, player, stream);
return;
}
logicHandler[0].handleLogic(packet, player, stream);
}
/**
* Default method for handling packets
*
* @param packetId
* The id of the packet
*
* @param player
* The player sending the packet
*
* @param stream
* The input stream of the player
*/
public static void handle(int packetId, Player player, InputStream stream, int length) {
if (handler[packetId] != null) {
handler[packetId].handle(packetId, player, stream, length);
return;
}
handler[0].handle(packetId, player, stream, length);
}
/**
* A static constructor, which will assign
* the packet id their appropriate handler
*/
static {
/* Default */
logicHandler[0] = new DefaultLogicPacketHandler();
handler[0] = new DefaultPacketHandler();
/* Miscelleneous */
handler[5] = new MoveCameraPacketHandler();
handler[75] = new InOutScreenPacketHandler();
handler[87] = new ScreenPacketHandler();
handler[84] = new ClickPacketHandler();
handler[4] = new SwitchDetailPacketHandler();
handler[22] = new SkillcapeColourIdPacketHandler();
handler[16] = new PingPacketHandler();
handler[29] = new MoveMousePacketHandler();
handler[68] = new KeyTypedPacketHandler();
handler[15] = new ReceivePacketCountPacketHandler();
/* Regions */
handler[33] = new DoneLoadingRegionPacketHandler();
/* Dialogues */
handler[54] = new ContinueDialoguePacketHandler();
handler[59] = new EnterStringPacketHandler();
handler[3] = new EnterIntegerPacketHandler();
/* Chat */
handler[30] = new PublicQuickChatPacketHandler();
handler[23] = new ChatTypePacketHandler();
handler[36] = new ChatPacketHandler();
handler[70] = new CommandPacketHandler();
/* Action buttons */
handler[61] = new ActionButtonPacketHandler(); //Action Button 1
handler[64] = new ActionButtonPacketHandler(); //Action Button 2
handler[4] = new ActionButtonPacketHandler(); //Action Button 3
handler[52] = new ActionButtonPacketHandler(); //Action Button 4
handler[81] = new ActionButtonPacketHandler(); //Action Button 5
handler[18] = new ActionButtonPacketHandler(); //Action Button 6
handler[10] = new ActionButtonPacketHandler(); //Action Button 7
handler[25] = new ActionButtonPacketHandler(); //Action Button 8
handler[91] = new ActionButtonPacketHandler(); //Action Button 9
handler[20] = new ActionButtonPacketHandler(); //Action Button 10
/* Friends */
handler[51] = new AddFriendPacketHandler();
handler[8] = new RemoveFriendPacketHandler();
handler[72] = new SendFriendPrivateMessagePacketHandler();
handler[79] = new SendFriendQuickChatMessagePacketHandler();
/* Friends Chat */
handler[1] = new JoinFriendChatPacketHandler();
handler[32] = new KickFriendChatPacketHandler();
handler[41] = new ChangeFriendChatPacketHandler();
/* Clans */
handler[7] = new ClanNamePacketHandler();
handler[74] = new ClanForumThreadPacket();
/* Walking packets */
logicHandler[12] = new WalkingPacketHandler();
logicHandler[83] = new WalkingPacketHandler();
/* Item packets */
handler[73] = new ItemOnItemPacketHandler();
handler[27] = new ItemExaminePacketHandler();
logicHandler[24] = new TakeItemPacketHandler();
/* Player options */
logicHandler[14] = new FirstPlayerOptionPacketHandler();
logicHandler[53] = new SecondPlayerOptionPacketHandler();
handler[77] = new PlayerTradeOptionPacketHandler();
handler[46] = new AcceptTradePacketHandler();
/* NPC Options */
logicHandler[66] = new AttackNpcPacketHandler();
logicHandler[9] = new FirstClickNpcPacketHandler();
logicHandler[31] = new SecondClickNpcPacketHandler();
handler[92] = new NpcExaminePacketHandler();
/* Interfaces */
logicHandler[40] = new InterfaceOnPlayerPacketHandler();
logicHandler[65] = new InterfaceOnNpcPacketHandler();
handler[56] = new CloseInterfacePacketHandler();
handler[26] = new SwitchInterfaceItemPacketHandler();
/* Object */
logicHandler[11] = new FirstClickObjectPacketHandler();
logicHandler[2] = new SecondClickObjectPacketHandler();
logicHandler[76] = new ThirdClickObjectPacketHandler();
logicHandler[42] = new ItemOnObjectPacketHandler();
handler[47] = new ObjectExaminePacketHandler();
}
}
After that's been added, replace your WorldPacketsDecoder with the following:
Code:
package org.murlock.net.decoders;
import java.util.logging.Logger;
import org.murlock.game.player.LogicPacket;
import org.murlock.game.player.Player;
import org.murlock.io.InputStream;
import org.murlock.net.Session;
import org.murlock.net.packets.PacketManager;
import org.murlock.utils.Utils;
public final class WorldPacketsDecoder extends Decoder {
/**
* The logger instance
*/
private static final Logger logger = Logger.getLogger(WorldPacketsDecoder.class.getName());
public final static int ACTION_BUTTON1_PACKET = 61;
public final static int ACTION_BUTTON2_PACKET = 64;
public final static int ACTION_BUTTON3_PACKET = 4;
public final static int ACTION_BUTTON4_PACKET = 52;
public final static int ACTION_BUTTON5_PACKET = 81;
public final static int ACTION_BUTTON6_PACKET = 18;
public final static int ACTION_BUTTON7_PACKET = 10;
public final static int ACTION_BUTTON8_PACKET = 25;
public final static int ACTION_BUTTON9_PACKET = 91;
public final static int ACTION_BUTTON10_PACKET = 20;
private final static int WALKING_PACKET = 12;
private final static int MINI_WALKING_PACKET = 83;
public final static int RECEIVE_PACKET_COUNT_PACKET = 15;
private final static int OBJECT_CLICK1_PACKET = 11;
private final static int OBJECT_CLICK2_PACKET = 2;
private final static int OBJECT_CLICK3_PACKET = 76;
private final static int NPC_CLICK1_PACKET = 9;
private final static int NPC_CLICK2_PACKET = 31;
private final static int ATTACK_NPC = 66;
private final static int PLAYER_OPTION_1_PACKET = 14;
private final static int PLAYER_OPTION_2_PACKET = 53;
private final static int ITEM_TAKE_PACKET = 24;
private final static int SWITCH_INTERFACE_ITEM_PACKET = 26;
private final static int INTERFACE_ON_PLAYER = 40;
private final static int INTERFACE_ON_NPC = 65;
private final static int ITEM_ON_OBJECT_PACKET = 42;
private Player player;
public WorldPacketsDecoder(Session session, Player player) {
super(session);
this.player = player;
}
@Override
public void decode(InputStream stream) {
while (stream.getRemaining() > 0 && session.getChannel().isConnected()
&& !player.hasFinished()) {
int packetId = stream.readUnsignedByte();
if (packetId >= PacketManager.PACKET_SIZES.length) {
System.out.println("PacketId " + packetId
+ " has fake packet id.");
break;
}
int length = PacketManager.PACKET_SIZES[packetId];
if (length == -1)
length = stream.readUnsignedByte();
else if (length == -2)
length = stream.readUnsignedShort();
else if (length == -3)
length = stream.readInt();
else if (length == -4) {
length = stream.getRemaining();
System.out.println("Invalid size for PacketId " + packetId
+ ". Size guessed to be " + length);
}
if (length > stream.getRemaining()) {
length = stream.getRemaining();
System.out.println("PacketId " + packetId
+ " has fake size. - expected size " + length);
break;
}
int startOffset = stream.getOffset();
processPackets(packetId, stream, length);
stream.setOffset(startOffset + length);
}
}
public void processPackets(final int packetId, InputStream stream,
int length) {
player.setPacketsDecoderPing(Utils.currentTimeMillis());
if (packetId == WALKING_PACKET
|| packetId == MINI_WALKING_PACKET
|| packetId == ITEM_TAKE_PACKET
|| packetId == PLAYER_OPTION_2_PACKET
|| packetId == PLAYER_OPTION_1_PACKET || packetId == ATTACK_NPC
|| packetId == INTERFACE_ON_PLAYER
|| packetId == INTERFACE_ON_NPC
|| packetId == NPC_CLICK1_PACKET
|| packetId == NPC_CLICK2_PACKET
|| packetId == OBJECT_CLICK1_PACKET
|| packetId == SWITCH_INTERFACE_ITEM_PACKET
|| packetId == OBJECT_CLICK2_PACKET
|| packetId == OBJECT_CLICK3_PACKET
|| packetId == ITEM_ON_OBJECT_PACKET)
player.addLogicPacketToQueue(new LogicPacket(packetId, length,
stream));
else {
PacketManager.handle(packetId, player, stream, length);
logger.info("Unhandled packet " + packetId + ", expected size: "
+ length + ", actual size: " + PacketManager.PACKET_SIZES[packetId]);
}
}
public Player getPlayer() {
return player;
}
}
In your player class, you'll need to replace the processLogicPackets method (as the previous way is now redundant):
Code:
public void processLogicPackets() {
LogicPacket packet;
while ((packet = logicPackets.poll()) != null) {
InputStream stream = new InputStream(packet.getData());
PacketManager.handleLogic(packet, this, stream);
}
}
Also, add the following while you're at it:
Code:
/**
* The player's chat type
*/
private int chatType = 0;
/**
* Sets the chat type of the player
*
* @param chatType
* The chat type
*/
public void setChatType(int chatType) {
this.chatType = chatType;
}
/**
* Gets the chat type of the player
*
* @return
* The player's chat type
*/
public int getChatType() {
return chatType;
}
Due to the sheer amount of packets, obviously I can't post all the code here. Instead, I've archived them for you. You can download them here: [Only registered and activated users can see links. ]
This was written for the Feather 667 release, so I don't know if you'll have to change anything to match your server. Obviously the packaging. Also, you'll need to instantiate the PacketManager class. You could, for example, just add the following to your launcher:
Code:
private static PacketManager packetManager = new PacketManager();
If I've forgotten anything (which is quite possible), just let me know
Your naming is wrong. The interface you call 'LogicPacketHandler' is just a 'LogicPacket'.
The class you call 'LogicPacketManager' should be the 'LogicPacketHandler'.
I wouldn't call it a 'LogicPacket' in the first place.
Originally Posted by Nando
why would I care about trying to get you to care about me homosexual?
back to coding shit revisions
Your naming is wrong. The interface you call 'LogicPacketHandler' is just a 'LogicPacket'.
The class you call 'LogicPacketManager' should be the 'LogicPacketHandler'.
I wouldn't call it a 'LogicPacket' in the first place.
He wanted to name it that so he did other people can change it, not that big of a deal but thanks I guess for pointing it out.
Your naming is wrong. The interface you call 'LogicPacketHandler' is just a 'LogicPacket'.
The class you call 'LogicPacketManager' should be the 'LogicPacketHandler'.
I wouldn't call it a 'LogicPacket' in the first place.
I don't see the need to. As we've already established, they are both processed the same, and I had wanted to keep the naming conventions similar to that as was already implemented. No need for arguing on this thread, if you don't like it, don't use it.
wasnt arguing and there is no need to correct me on my spelling i dont give 2 shits.
was giving you a tip saying there is no point having 2 classes that do exactly the same thing, talk about bloated code lmao