Updates
This thread will be updated with optimizations, stabilizations, removing all kind of memory issues and all kind of dupes.
NOTE
I know there are mixed opinions about my thread, which I accept and you got to accept, but this thread is just a purpose to help other people and will help on future PI development. Moving on to other frameworks is an owner's own decision. Therefore people may decide themselves which framework is being used. In this case, I'm helping out PI servers.
Thanks,
MrClassic
UPDATES
Updates:
UPDATED 14-07-2014:
- Added more checks
UPDATED 15-07-2014:
- Fixed packet abusing 208 and 135.
- Fixed packet 97 abusing @ Walking.java. Re-do these packets.
- Added simple methods to prevent opening interfaces for smelting, smithing, cooking etc while actually not doing the skill.
- Added explaination about packet 121 abusing. 100% credits to
akZu.
UPDATED 16-07-2014:
- Fixed the part: Prevent opening smithing, smelting and cooking etc interfaces. Thanks to
Poesy700 for pointing out the fix.
UPDATED 02-08-2016:
- Prevent noclipping by cheat engine. Thanks to
Idiot Bird.
NOTE
Notes:
- This snippet is created because SilabSoft is abusing packets on several servers.
- Almost all packets which can be abused have been patched.
- This will be updated when I add more checks server sided.
- This is just created to give you a clear view of all the packets which can easily be abused to dupe items or to get advantages in-game.
- This snippet will lead you to other snippet(s) if possible, which 100% credits will be given.
- At last, if you have something to contribute or have critisism, post it here. If you have something to contribute, 100% credits will be given.
Avoid usage of oversized packets or incorrect packets:
http://www.rune-server.org/runescape...t-abusers.html - credits to Genesis
Packet 85, 101, 151, 132, 252 and 70 abusing (object handling and clicking):
http://www.rune-server.org/runescape...t-clients.html - credits to Thock321
Packet 208 and 135 abusing (X amount packet):
BankX2.java
Under this:
Code:
int Xamount = c.getInStream().readDWord();
add this:
Code:
if (Xamount < 0)// this should work fine
{
Xamount = c.getItems().getItemAmount(c.xRemoveId);
}
if (Xamount == 0) {
Xamount = 1;
}
In cases 5064 and 3322 add on top:
Code:
if(!c.getItems().playerHasItem(c.xRemoveId, Xamount))
return;
Packet 97 abusing (open interface EG: bank, trade, duel or shop):
Bank
Player.java add this int:
Code:
c.isBanking = false;
PlayerAssistant.java openUpBank method:
Code:
c.isBanking = true;
ItemAssistant.java fromBank and bankItem methods add this:
Code:
if(!c.isBanking)
return false;
Shop
Player.java:
Code:
public boolean isShopping = false;
ShopAssistant.java openShop method:
Code:
c.isShopping = true;
buyItem & sellItem method:
Code:
if(!c.isShopping)
return false;
Trade
Player.java:
Code:
public boolean inTrade = false;
TradeAndDuel.java in openTrade method add:
tradeItem method add:
Code:
if (!c.inTrade) {
declineTrade();
return false;
}
Code:
if(!c.getItems().playerHasItem(itemID, amount))
return false;
fromTrade method:
Code:
if (!c.inTrade || !c.canOffer) {
declineTrade();
return false;
}
declineTrade method(boolean tellOther):
confirmScreen method:
Code:
if(!c.inTrade) {
declineTrade();
return;
}
Dueling
Player.java:
Code:
public boolean openDuel = false;
TradeAndDuel.java openDuel method:
Code:
c.openDuel = true;
o.openDuel = true;
refreshDuelScreen method:
Code:
if(!c.openDuel && !o.openDuel) {
declineDuel();
return;
}
stakeItem method under Client o = ...:
Code:
if(!c.openDuel && !o.openDuel) {
declineDuel();
return false;
}
if(!c.getItems().playerHasItem(itemID, amount))
return false;
if (amount <= 0)
return false;
fromDuel method:
Code:
if(!c.openDuel && !o.openDuel) {
declineDuel();
return false;
}
ABOVE every, except for requestDuel() method, add:
Code:
c.openDuel = false;
o.openDuel = false;
if "o" is not initialized add this:
Code:
Client o = (Client) PlayerHandler.players[c.duelingWith];
Now for resetting shopping, banking, trading and dueling when walking or closing button:
ClickingStuff.java:
Code:
if (c.isBanking)
c.isBanking = false;
if(c.isShopping)
c.isShopping = false;
if(c.openDuel && c.duelStatus >= 1 && c.duelStatus <= 4) {
Client o = (Client) PlayerHandler.players[c.duelingWith];
if(o != null)
o.getTradeAndDuel().declineDuel();
c.getTradeAndDuel().declineDuel();
}
if(c.duelStatus == 6)
c.getTradeAndDuel().claimStakedItems();
if (c.inTrade) {
if(!c.acceptedTrade) {
c.getTradeAndDuel().declineTrade();
}
}
Walking.java:
Code:
if(c.openDuel && c.duelStatus != 5) {
Client o = (Client) PlayerHandler.players[c.duelingWith];
if(o != null)
o.getTradeAndDuel().declineDuel();
c.getTradeAndDuel().declineDuel();
}
if((c.duelStatus >= 1 && c.duelStatus <= 4) || c.duelStatus == 6) {
if(c.duelStatus == 6) {
c.getTradeAndDuel().claimStakedItems();
}
return;
}
if(c.isBanking || c.isShopping || c.inTrade)
c.isBanking = c.isShopping = c.inTrade = false;
EXTRA: This will come in handy to prevent 3 player dupes etc etc:
- Player is busy at the moment
Player.java:
Code:
public boolean playerIsBusy() {
if(isShopping || inTrade || openDuel || isBanking || duelStatus == 1)
return true;
return false;
}
TradeAndDuel.java requestTrade method:
Code:
if(c.playerIsBusy())
return;
if(o.playerIsBusy()) {
c.sendMessage("Other player is busy at the moment.");
return;
}
requestDuel method:
Code:
if(c.playerIsBusy())
return;
if(o.playerIsBusy()) {
c.sendMessage("Other player is busy at the moment.");
return;
}
Player appearance abusing (invisible etc):
http://www.rune-server.org/runescape...sign-flaw.html - credits to Stuart
Packet 41 abusing (wearing an item):
WearItem.java:
Code:
if(!c.getItems().playerHasItem(c.wearId, 1, c.wearSlot)) {
return;
}
Packet 53 abusing (Item on item):
ItemOnItem.java:
Code:
if(!c.getItems().playerHasItem(useWith, 1, usedWithSlot) || !c.getItems().playerHasItem(itemUsed, 1, itemUsedSlot)) {
return;
}
Packet 192 abusing (Item on object):
ItemOnObject.java:
Code:
if(!c.getItems().playerHasItem(itemId, 1)) {
return;
}
Packet 25 abusing (Item on grounditem):
ItemOnGroundItem.java:
Code:
if(!c.getItems().playerHasItem(itemUsed, 1, itemUsedSlot)) {
return;
}
if(!Server.itemHandler.itemExists(groundItem, gItemX, gItemY)) {
return;
}
Packet 101 abusing (changing appearance):
ChangeAppearance.java:
Code:
if(!client.canChangeAppearance)
return;
Packet 129, 43 and 117 abusing (Bank all from 1 item, like 100 trouts..., bank 10 and bank 5. Also uncludes shopping):
BankAll.java:
under case 3823:
Code:
if(!c.getItems().playerHasItem(removeId))
return;
under case 5064:
Code:
if(!c.getItems().playerHasItem(removeId))
return;
Bank10.java:
under case 3823:
Code:
if(!c.getItems().playerHasItem(removeId))
return;
under case 5064:
Code:
if(!c.getItems().playerHasItem(removeId))
return;
Bank5.java:
under case 3823:
Code:
if(!c.getItems().playerHasItem(removeId))
return;
under case 5064:
Code:
if(!c.getItems().playerHasItem(removeId))
return;
Packet 39 abusing (Trade request):
Trade.java:
Code:
if(tradeId < 1)
return;
if (tradeId != c.playerId)
c.getTradeAndDuel().requestTrade(tradeId);
Packet 128 abusing (duel request):
ChallengePlayer.java:
Code:
if(PlayerHandler.players[answerPlayer] == null || answerPlayer == c.playerId)
return;
Packet 202 abusing (IdleLogout):
IdleLogout.java (could prevent duping):
Code:
if(c.underAttackBy > 0 || c.underAttackBy2 > 0)
return;
Packet 181 abusing (Magic on flooritems):
MagicOnFloorItems.java:
Code:
if(!Server.itemHandler.itemExists(itemId, itemX, itemY)) {
c.stopMovement();
return;
}
Packet 236 abusing (Pickup an item):
PickupItem.java:
Code:
if(!Server.itemHandler.itemExists(c.pItemId, c.pItemX, c.pItemY)) {
c.stopMovement();
return;
}
Packet 237 abusing (Magic on item):
MagicOnItems.java:
Code:
if(!c.getItems().playerHasItem(itemId, 1, slot))
return;
Packet 87 abusing (Dropping item):
DropItem.java:
Code:
if(!c.getItems().playerHasItem(itemId)) {
return;
}
Packet 122, 75 and 16 abusing (click item):
ClickItem.java, ClickItem3.java and ClickItem2.java:
Code:
if(!c.getItems().playerHasItem(itemId, 1)) { //, itemSlot
return;
}
Packet 57 abusing (Item on npc):
ItemOnNpc.java:
Code:
if(!c.getItems().playerHasItem(itemId, 1, slot)) {
return;
}
Useful methods by Arithium:
100% credits to Arithium

Originally Posted by
Arithium
Code:
public boolean playerHasOfferedItem(int id) {
for (GameItem item : player.getTradeAndDuel().offeredItems) {
if ((item != null) && (item.id == id)) {
return true;
}
}
return false;
}
public boolean playerHasStakedItem(int id) {
for (GameItem item : player.stakedItems) {
if ((item != null) && (item.id == id)) {
return true;
}
}
return false;
}
Prevent opening smithing, smelting, cooking interfaces:
Player.java:
Code:
public boolean[] checkSkilling = new boolean[5]; //herblore, smithing, smelting, cooking, fletching, crafting
Usage:
Let's say we have have the booleans like this:
c.checkSkilling[
0] = Smithing
c.checkSkilling[
1] = Smelting
c.checkSkilling[
2] = Fletching
c.checkSkilling[
3] = Crafting
c.checkSkilling[
4] = Herblore
c.checkSkilling[
5] = Cooking
when you start smelting do this:
Code:
c.checkSkilling[1] = true;
When clicking buttons on the smelting interface do this:
- Thanks for pointing out the fix Poesy700
Code:
if(!c.checkSkilling[1])
return;
and resetting smelting add this:
Code:
c.checkSkilling[1] = false;
This is how you prevent opening the skilling interface while not doing the skill actually.
packet 121 abusing (region changing):
- 100% credits to akZu
- The check won't be released until akZu confirms it. (could take up to... lifetime)

Originally Posted by
AkZu
Haven't tested but in theory how awful ground item and global object systems pi's had (never looked at pi at further glance..)..
You could lag any server anyhow for any vulnerable code, for example.
If I were to make attacks to servers I would choose to use the Region has finished loading packet (121?) which is sent from client, most servers (99%) do not check anything in that packet (or any for that matter....), they just trust the client blindfolded that the region is changed, must sent ground entities and loop through huge lists..
Do that times 5000 under minute and you can bloody lag server, if it has alot of ground items to check for.
What you can do about it, when you as the server tell client that it's time for a map region update (sending a packet to construct new map region based on your coordinates), you store a flag for that player that a map region update packet has been shipped, then when client, legit or not, sends region has loaded packet back, you nullify the flag and load global ground items/objects.
Prevent noclipping by cheat engine:
Player class search for:
Code:
int getNextWalkingDirection()
Under this
Code:
currentY += Misc.directionDeltaY[dir];
put:
Code:
if (!Region.canMove(absX, absY, (absX + Misc.directionDeltaX[dir]), (absY + Misc.directionDeltaY[dir]), heightLevel, 1, 1))
return -1;
canMove method:
Code:
public static boolean canMove(int startX, int startY, int endX, int endY, int height, int xLength, int yLength) {
int diffX = endX - startX;
int diffY = endY - startY;
int max = Math.max(Math.abs(diffX), Math.abs(diffY));
for (int ii = 0; ii < max; ii++) {
int currentX = endX - diffX;
int currentY = endY - diffY;
for (int i = 0; i < xLength; i++) {
for (int i2 = 0; i2 < yLength; i2++) {
if (diffX < 0 && diffY < 0) {
if ((getClipping(currentX + i - 1, currentY + i2 - 1, height) & 0x128010e) != 0 || (getClipping(currentX + i - 1, currentY + i2, height) & 0x1280108) != 0
|| (getClipping(currentX + i, currentY + i2 - 1, height) & 0x1280102) != 0) {
return false;
}
} else if (diffX > 0 && diffY > 0) {
if ((getClipping(currentX + i + 1, currentY + i2 + 1, height) & 0x12801e0) != 0 || (getClipping(currentX + i + 1, currentY + i2, height) & 0x1280180) != 0
|| (getClipping(currentX + i, currentY + i2 + 1, height) & 0x1280120) != 0) {
return false;
}
} else if (diffX < 0 && diffY > 0) {
if ((getClipping(currentX + i - 1, currentY + i2 + 1, height) & 0x1280138) != 0 || (getClipping(currentX + i - 1, currentY + i2, height) & 0x1280108) != 0
|| (getClipping(currentX + i, currentY + i2 + 1, height) & 0x1280120) != 0) {
return false;
}
} else if (diffX > 0 && diffY < 0) {
if ((getClipping(currentX + i + 1, currentY + i2 - 1, height) & 0x1280183) != 0 || (getClipping(currentX + i + 1, currentY + i2, height) & 0x1280180) != 0
|| (getClipping(currentX + i, currentY + i2 - 1, height) & 0x1280102) != 0) {
return false;
}
} else if (diffX > 0 && diffY == 0) {
if ((getClipping(currentX + i + 1, currentY + i2, height) & 0x1280180) != 0) {
return false;
}
} else if (diffX < 0 && diffY == 0) {
if ((getClipping(currentX + i - 1, currentY + i2, height) & 0x1280108) != 0) {
return false;
}
} else if (diffX == 0 && diffY > 0) {
if ((getClipping(currentX + i, currentY + i2 + 1, height) & 0x1280120) != 0) {
return false;
}
} else if (diffX == 0 && diffY < 0) {
if ((getClipping(currentX + i, currentY + i2 - 1, height) & 0x1280102) != 0) {
return false;
}
}
}
}
if (diffX < 0) {
diffX++;
} else if (diffX > 0) {
diffX--;
}
if (diffY < 0) {
diffY++;
} else if (diffY > 0) {
diffY--;
}
}
return true;
}
Will update when I find more.