Hello people, the current thing that I am working on is getting to ForceMovement mask to work on my 803 server. I've spent enough time trying to solve this issue myself that I warrant asking for help on the forums. The RuneLove 3 base did not come with Force Movement already installed, so I took liberty to trying to add it as I managed to find the Mask Hex in the code. I created the classes for force movement as well as the Update block, which sends to my client with no major errors (IE crashing), however the mask does not do what it is supposed to and locks me from any other movement. The one thing that does work, however, is it faces the player character in the proper direction. If I click an NPC, the player faces the NPC, meaning the face entity code overrides the broken, but when I click away, it once again faces the direction sent by the force movement when it was called.
ForceMovement Class:
Code:
public class ForceMovement {
public static final int NORTH = 0, EAST = 1, SOUTH = 2, WEST = 3;
private Tile toFirstTile;
private Tile toSecondTile;
private int firstTileTicketDelay;
private int secondTileTicketDelay;
protected int direction;
public ForceMovement(Tile toFirstTile, int firstTileTicketDelay,
int direction) {
this(toFirstTile, firstTileTicketDelay, null, 0, direction);
}
public ForceMovement(Tile toFirstTile, int firstTileTicketDelay,
Tile toSecondTile, int secondTileTicketDelay, int direction) {
this.toFirstTile = toFirstTile;
this.firstTileTicketDelay = firstTileTicketDelay;
this.toSecondTile = toSecondTile;
this.secondTileTicketDelay = secondTileTicketDelay;
this.direction = direction;
}
public int getDirection() {
switch(direction) {
case NORTH:
return Utils.getFaceDirection(0, 1);
case EAST:
return Utils.getFaceDirection(1, 0);
case SOUTH:
return Utils.getFaceDirection(0, -1);
case WEST:
default:
return Utils.getFaceDirection(-1, 0);
}
}
public Tile getToFirstTile() {
return toFirstTile;
}
public Tile getToSecondTile() {
return toSecondTile;
}
public int getFirstTileTicketDelay() {
return firstTileTicketDelay;
}
public int getSecondTileTicketDelay() {
return secondTileTicketDelay;
}
}
ForceMovementBlock Class:
Code:
public class ForceMovementBlock extends UpdateBlock {
@Override
public int getMask() {
return UpdateMasks.FORCE_MOVE;
}
@Override
public int getBlockPosition() {
return 20;
}
@Override
public int appendToUpdateBlock(RS3PacketBuilder buffer, Entity player) {
int start = buffer.getPosition();
System.out.println ("Start: "+start);
buffer.putByteA(player.getNextForceMovement().getToFirstTile().getLocalX()
- player.getTile().getLocalX());
//System.out.println("TileX"+player.getNextForceMovement().getToFirstTile().getX());
//System.out.println("ThepTileX"+player.getTile().getX());
buffer.putByteS(player.getNextForceMovement().getToFirstTile().getLocalY()
- player.getTile().getLocalY());
//System.out.println("TileY"+player.getNextForceMovement().getToFirstTile().getY());
//System.out.println("ThepTileY"+player.getTile().getY());
buffer.putByteS(player.getNextForceMovement().getToSecondTile() == null ? 0
: player.getNextForceMovement().getToSecondTile().getLocalX() - player.getTile().getLocalX());
buffer.putByteS(player.getNextForceMovement().getToSecondTile() == null ? 0
: player.getNextForceMovement().getToSecondTile().getLocalY() - player.getTile().getLocalY());
buffer.putShortA(player.getNextForceMovement().getFirstTileTicketDelay() * 30);
//System.out.println("1st Tick Delay"+player.getNextForceMovement().getFirstTileTicketDelay() * 30);
buffer.putShortA(player.getNextForceMovement().getToSecondTile() == null ? 0
: player.getNextForceMovement().getSecondTileTicketDelay() * 30);
//System.out.println("2nd Tick Delay"+player.getNextForceMovement().getSecondTileTicketDelay() * 30);
buffer.putShort(player.getNextForceMovement().getDirection());
//System.out.println("Direction"+player.getNextForceMovement().getDirection());
System.out.println (buffer.getPosition() - start);
return buffer.getPosition() - start;
}
}
Client Side Decode Player Updates (Class 480):
Code:
if ((mask & 0x40) != 0) {//Force movement (20)
player.anInt11401 = stream.readByteA(582493488) * 2045684417;
player.anInt11403 = stream.readByteS((byte) 1) * -182768233;
player.anInt11402 = stream.readByteS((byte) 1) * -9202803;
player.anInt11428 = stream.getByteC(537746309) * -1841438277;
player.anInt11386 = (stream.readUnsignedLEShort((short) 32483) + client.anInt8296) * 1486211439;
player.anInt11422 = (stream.readUnsignedShortA((byte) 82) + client.anInt8296) * -2087589789;
player.anInt11407 = stream.readUnsignedShortA((byte) 33) * 364183757;
player.anInt11401 += (player.scenePositionXQueue[0] * 2045684417);
player.anInt11403 += (-182768233 * player.scenePositionYQueue[0]);
player.anInt11402 += player.scenePositionXQueue[0] * -9202803;
player.anInt11428 += (-1841438277 * player.scenePositionYQueue[0]);
player.queuedStepCount = 1631398045;
player.anInt11430 = 0;
}
}
If anyone with a higher understanding of this code can help, it would be really appreciated. I've done a lot of work trying to make sense of this, but the clientside's use of random numbers makes it hard to see whats going on. I did some trial and error to see what was being sent to the client, and found that by messing with player.anInt11386, it affected the facing of the player by making it no longer face the proper way.
I have a hunch on to what might be the cause of some of the errors, which might be do to how in the update block the start and return value might not be correct. With the animationblock, it ends up returning 9, which is the blockposition in the clientside, while the return value of the forcemovement returns 10 when the position is 20. I'm not entirely sure on that, so I felt the need to ask for assistance. I hope somebody is able to help me.