public class ValidatePosition extends L2GameClientPacket {
private int _x, _y, _z, _heading;
private int _data; // vehicle id
@Override
protected void readImpl() {
_x = readD();
_y = readD();
_z = readD();
_heading = readD();
_data = readD();
}
@Override
protected void runImpl() {
final L2PcInstance activeChar = getClient().getActiveChar();
if ((activeChar == null) || activeChar.isTeleporting() || activeChar.inObserverMode()) {
return;
}
final int realX = activeChar.getX();
final int realY = activeChar.getY();
int realZ = activeChar.getZ();
if ((_x == 0) && (_y == 0)) {
if (realX != 0) {
return;
}
}
int dx, dy, dz;
double diffSq;
/*if (activeChar.isInBoat())
{
if (Config.COORD_SYNCHRONIZE == 2)
{
dx = _x - activeChar.getInVehiclePosition().getX();
dy = _y - activeChar.getInVehiclePosition().getY();
// dz = _z - activeChar.getInVehiclePosition().getZ();
diffSq = ((dx * dx) + (dy * dy));
if (diffSq > 250000)
{
sendPacket(new GetOnVehicle(activeChar.getObjectId(), _data, activeChar.getInVehiclePosition()));
}
}
return;
}*/
if (activeChar.isFalling(_z)) {
return; // disable validations during fall to avoid "jumping"
}
dx = _x - realX;
dy = _y - realY;
dz = _z - realZ;
diffSq = ((dx * dx) + (dy * dy));
// Zoey76: TODO: Implement or cleanup.
// L2Party party = activeChar.getParty();
// if ((party != null) && (activeChar.getLastPartyPositionDistance(_x, _y, _z) > 150))
// {
// activeChar.setLastPartyPosition(_x, _y, _z);
// party.broadcastToPartyMembers(activeChar, new PartyMemberPosition(activeChar));
// }
if (activeChar.isFlying() || activeChar.isInWater() || activeChar.isInsideZone(L2Zone.FLAG_WATER)) {
activeChar.getPosition().setXYZ(realX, realY, _z);
if (diffSq > 90000) {
activeChar.sendPacket(new ValidateLocation(activeChar));
}
} else if (diffSq < 360000) // if too large, messes observation
{
if (Config.COORD_SYNCHRONIZE == -1) // Only Z coordinate synched to server,
// mainly used when no geodata but can be used also with geodata
{
activeChar.getPosition().setXYZ(realX, realY, _z);
return;
}
if (Config.COORD_SYNCHRONIZE == 1) // Trusting also client x,y coordinates (should not be used with geodata)
{
if (!activeChar.isMoving() || !activeChar.validateMovementHeading(_heading)) // Heading changed on client = possible obstacle
{
// character is not moving, take coordinates from client
if (diffSq < 2500) {
activeChar.getPosition().setXYZ(realX, realY, _z);
} else {
activeChar.getPosition().setXYZ(_x, _y, _z);
}
} else {
activeChar.getPosition().setXYZ(realX, realY, _z);
}
activeChar.setHeading(_heading);
return;
}
// Sync 2 (or other),
// intended for geodata. Sends a validation packet to client
// when too far from server calculated true coordinate.
// Due to geodata/zone errors, some Z axis checks are made. (maybe a temporary solution)
// Important: this code part must work together with L2Character.updatePosition
if ((diffSq > 250000) || (Math.abs(dz) > 200)) {
// if ((_z - activeChar.getClientZ()) < 200 && Math.abs(activeChar.getLastServerPosition().getZ()-realZ) > 70)
if ((Math.abs(dz) > 200) && (Math.abs(dz) < 1500) && (Math.abs(_z - activeChar.getClientZ()) < 800)) {
activeChar.getPosition().setXYZ(realX, realY, _z);
realZ = _z;
} else {
if (Config.DEVELOPER) {
_log.info(activeChar.getName() + ": Synchronizing position Server --> Client");
}
activeChar.sendPacket(new ValidateLocation(activeChar));
}
}
}
activeChar.setClientX(_x);
activeChar.setClientY(_y);
activeChar.setClientZ(_z);
activeChar.setClientHeading(_heading); // No real need to validate heading.
activeChar.setLastServerPosition(realX, realY, realZ);
/*L2PcInstance player = getClient().getActiveChar();
if (player == null || player.isTeleporting()) {
return;
}
player.checkSummon();
int realX = player.getX();
int realY = player.getY();
int realZ = player.getZ();
if (_x == 0 && _y == 0) {
if (realX != 0) {
return;
}
}
double dx = _x - realX;
double dy = _y - realY;
double dz = _z - realZ;
double diffSq = (dx * dx + dy * dy);
if (player.getParty() != null && player.canSendPartyPos()) {
player.setLastPartyPosition(_x, _y, _z);
player.getParty().broadcastToPartyMembers(player, new PartyMemberPosition(player));
}
if (player.isFlying() || player.isInWater()) {
player.setHeading(_heading);
player.getPosition().setXYZ(realX, realY, _z);
if (diffSq > 90000) {
player.sendPacket(new ValidateLocation(player));
}
} else if (diffSq < 360000) // if too large, messes observation
{
switch (Config.COORD_SYNCHRONIZE) {
case 1:
if (!player.isMoving()
|| !player.validateMovementHeading(_heading)) // Heading changed on client = possible obstacle
{
// character is not moving, take coordinates from client
if (diffSq < 2500) // 50*50 - attack won't work fluently if even small differences are corrected
{
player.getPosition().setXYZ(realX, realY, _z);
} else {
player.getPosition().setXYZ(_x, _y, _z);
}
} else {
player.getPosition().setXYZ(realX, realY, _z);
}
player.setHeading(_heading);
return;
case 2:
if (Config.GEODATA > 0 && (diffSq > 250000 || Math.abs(dz) > 200)) {//player.getTemplate().collisionRadius)) {
//if ((_z - player.getClientZ()) < 200 && Math.abs(player.getLastServerPosition().getZ()-realZ) > 70)
if (Math.abs(dz) > 200
&& Math.abs(dz) < 1500
&& Math.abs(_z - player.getClientZ()) < 800) {
player.getPosition().setXYZ(realX, realY, _z);
realZ = _z;
} else {
player.sendPacket(new ValidateLocation(player));
}
}
break;
default:
player.getPosition().setXYZ(realX, realY, _z);
return;
}
}
player.setClientX(_x);
player.setClientY(_y);
player.setClientZ(_z);
player.setClientHeading(_heading); // No real need to validate heading.
player.setLastServerPosition(realX, realY, realZ);*/
}
/*if (Config.COORD_SYNCHRONIZE == -1) // Only Z coordinate synched to server,
// mainly used when no geodata but can be used also with geodata
{
player.getPosition().setXYZ(realX, realY, _z);
return;
}
if (Config.COORD_SYNCHRONIZE == 1) // Trusting also client x,y coordinates (should not be used with geodata)
{
if (!player.isMoving()
|| !player.validateMovementHeading(_heading)) // Heading changed on client = possible obstacle
{
// character is not moving, take coordinates from client
if (diffSq < 2500) // 50*50 - attack won't work fluently if even small differences are corrected
{
player.getPosition().setXYZ(realX, realY, _z);
} else {
player.getPosition().setXYZ(_x, _y, _z);
}
} else {
player.getPosition().setXYZ(realX, realY, _z);
}
player.setHeading(_heading);
return;
}*/
/*if (Config.GEODATA > 0 && (diffSq > 256 || Math.abs(dz) > 200)) {
player.sendPacket(new ValidateLocation(player));
}*/
// Sync 2 (or other),
// intended for geodata. Sends a validation packet to client
// when too far from server calculated true coordinate.
// Due to geodata/zone errors, some Z axis checks are made. (maybe a temporary solution)
// Important: this code part must work together with L2Character.updatePosition
/*if (Config.GEODATA > 0 && (diffSq > 250000 || Math.abs(dz) > 200)) {//player.getTemplate().collisionRadius)) {
//if ((_z - player.getClientZ()) < 200 && Math.abs(player.getLastServerPosition().getZ()-realZ) > 70)
if (Math.abs(dz) > 200
&& Math.abs(dz) < 1500
&& Math.abs(_z - player.getClientZ()) < 800) {
player.getPosition().setXYZ(realX, realY, _z);
System.out.println("##runImpl###1##" + diffSq);
realZ = _z;
} else {
System.out.println("##runImpl###2##" + diffSq);
player.sendPacket(new ValidateLocation(player));
}
}*/
}