forked from MagicBane/Server
Project cleanup pre merge.
This commit is contained in:
@@ -32,474 +32,469 @@ import static engine.math.FastMath.sqr;
|
||||
|
||||
public enum MovementManager {
|
||||
|
||||
MOVEMENTMANAGER;
|
||||
MOVEMENTMANAGER;
|
||||
|
||||
private static final String changeAltitudeTimerJobName = "ChangeHeight";
|
||||
private static final String flightTimerJobName = "Flight";
|
||||
private static final String changeAltitudeTimerJobName = "ChangeHeight";
|
||||
private static final String flightTimerJobName = "Flight";
|
||||
|
||||
public static void sendOOS(PlayerCharacter pc) {
|
||||
pc.setWalkMode(true);
|
||||
MovementManager.sendRWSSMsg(pc);
|
||||
}
|
||||
public static void sendOOS(PlayerCharacter pc) {
|
||||
pc.setWalkMode(true);
|
||||
MovementManager.sendRWSSMsg(pc);
|
||||
}
|
||||
|
||||
public static void sendRWSSMsg(AbstractCharacter ac) {
|
||||
public static void sendRWSSMsg(AbstractCharacter ac) {
|
||||
|
||||
if (!ac.isAlive())
|
||||
return;
|
||||
UpdateStateMsg rssm = new UpdateStateMsg();
|
||||
rssm.setPlayer(ac);
|
||||
if (ac.getObjectType() == GameObjectType.PlayerCharacter)
|
||||
DispatchMessage.dispatchMsgToInterestArea(ac, rssm, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false);
|
||||
else
|
||||
DispatchMessage.sendToAllInRange(ac, rssm);
|
||||
}
|
||||
if (!ac.isAlive())
|
||||
return;
|
||||
UpdateStateMsg rssm = new UpdateStateMsg();
|
||||
rssm.setPlayer(ac);
|
||||
if (ac.getObjectType() == GameObjectType.PlayerCharacter)
|
||||
DispatchMessage.dispatchMsgToInterestArea(ac, rssm, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false);
|
||||
else
|
||||
DispatchMessage.sendToAllInRange(ac, rssm);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the first combat target for the AbstractCharacter. Used to clear the
|
||||
* combat
|
||||
* target upon each move, unless something has set the firstHitCombatTarget
|
||||
* Also used to determine the size of a monster's hitbox
|
||||
*/
|
||||
public static void movement(MoveToPointMsg msg, AbstractCharacter toMove) throws MsgSendException {
|
||||
/*
|
||||
* Sets the first combat target for the AbstractCharacter. Used to clear the
|
||||
* combat
|
||||
* target upon each move, unless something has set the firstHitCombatTarget
|
||||
* Also used to determine the size of a monster's hitbox
|
||||
*/
|
||||
public static void movement(MoveToPointMsg msg, AbstractCharacter toMove) throws MsgSendException {
|
||||
|
||||
// check for stun/root
|
||||
if (!toMove.isAlive())
|
||||
return;
|
||||
// check for stun/root
|
||||
if (!toMove.isAlive())
|
||||
return;
|
||||
|
||||
if (toMove.getObjectType().equals(GameObjectType.PlayerCharacter)){
|
||||
if (((PlayerCharacter)toMove).isCasting())
|
||||
((PlayerCharacter)toMove).update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
toMove.setIsCasting(false);
|
||||
toMove.setItemCasting(false);
|
||||
if (toMove.getObjectType().equals(GameObjectType.PlayerCharacter)) {
|
||||
if (((PlayerCharacter) toMove).isCasting())
|
||||
((PlayerCharacter) toMove).update();
|
||||
}
|
||||
|
||||
|
||||
toMove.setIsCasting(false);
|
||||
toMove.setItemCasting(false);
|
||||
|
||||
if (toMove.getBonuses().getBool(ModType.Stunned, SourceType.None) || toMove.getBonuses().getBool(ModType.CannotMove, SourceType.None)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg.getEndLat() > MBServerStatics.MAX_WORLD_WIDTH)
|
||||
msg.setEndLat((float) MBServerStatics.MAX_WORLD_WIDTH);
|
||||
|
||||
if (msg.getEndLon() < MBServerStatics.MAX_WORLD_HEIGHT) {
|
||||
msg.setEndLon((float) MBServerStatics.MAX_WORLD_HEIGHT);
|
||||
}
|
||||
|
||||
if (toMove.getBonuses().getBool(ModType.Stunned, SourceType.None) || toMove.getBonuses().getBool(ModType.CannotMove, SourceType.None)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg.getEndLat() > MBServerStatics.MAX_WORLD_WIDTH)
|
||||
msg.setEndLat((float) MBServerStatics.MAX_WORLD_WIDTH);
|
||||
|
||||
if (msg.getEndLon() < MBServerStatics.MAX_WORLD_HEIGHT){
|
||||
msg.setEndLon((float) MBServerStatics.MAX_WORLD_HEIGHT);
|
||||
}
|
||||
|
||||
// if (msg.getEndLat() < 0)
|
||||
// msg.setEndLat(0);
|
||||
//
|
||||
// if (msg.getEndLon() > 0)
|
||||
// msg.setEndLon(0);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (!toMove.isMoving())
|
||||
toMove.resetLastSetLocUpdate();
|
||||
else
|
||||
toMove.update();
|
||||
|
||||
// Update movement for the player
|
||||
|
||||
|
||||
// else if (toMove.getObjectType() == GameObjectType.Mob)
|
||||
// ((Mob)toMove).updateLocation();
|
||||
// get start and end locations for the move
|
||||
Vector3fImmutable startLocation = new Vector3fImmutable(msg.getStartLat(), msg.getStartAlt(), msg.getStartLon());
|
||||
Vector3fImmutable endLocation = new Vector3fImmutable(msg.getEndLat(), msg.getEndAlt(), msg.getEndLon());
|
||||
|
||||
// if (toMove.getObjectType() == GameObjectType.PlayerCharacter)
|
||||
// if (msg.getEndAlt() == 0 && msg.getTargetID() == 0){
|
||||
// MovementManager.sendRWSSMsg(toMove);
|
||||
// }
|
||||
|
||||
//If in Building, let's see if we need to Fix
|
||||
|
||||
// if inside a building, convert both locations from the building local reference frame to the world reference frame
|
||||
|
||||
if (msg.getTargetID() > 0) {
|
||||
Building building = BuildingManager.getBuildingFromCache(msg.getTargetID());
|
||||
if (building != null) {
|
||||
|
||||
Vector3fImmutable convertLocEnd = new Vector3fImmutable(ZoneManager.convertLocalToWorld(building, endLocation));
|
||||
// if (!Bounds.collide(convertLocEnd, b) || !b.loadObjectsInside()) {
|
||||
// toMove.setInBuilding(-1);
|
||||
// toMove.setInFloorID(-1);
|
||||
// toMove.setInBuildingID(0);
|
||||
// }
|
||||
// else {
|
||||
toMove.setInBuilding(msg.getInBuilding());
|
||||
toMove.setInFloorID(msg.getUnknown01());
|
||||
toMove.setInBuildingID(msg.getTargetID());
|
||||
msg.setStartCoord(ZoneManager.convertWorldToLocal(building, toMove.getLoc()));
|
||||
|
||||
if (toMove.getObjectType() == GameObjectType.PlayerCharacter) {
|
||||
if (convertLocEnd.distanceSquared2D(toMove.getLoc()) > 6000 * 6000) {
|
||||
|
||||
Logger.info( "ENDLOC:" + convertLocEnd.x + ',' + convertLocEnd.y + ',' + convertLocEnd.z +
|
||||
',' + "GETLOC:" + toMove.getLoc().x + ',' + toMove.getLoc().y + ',' + toMove.getLoc().z + " Name " + ((PlayerCharacter) toMove).getCombinedName());
|
||||
toMove.teleport(toMove.getLoc());
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
startLocation = toMove.getLoc();
|
||||
endLocation = convertLocEnd;
|
||||
|
||||
} else {
|
||||
|
||||
toMove.setInBuilding(-1);
|
||||
toMove.setInFloorID(-1);
|
||||
toMove.setInBuildingID(0);
|
||||
//SYNC PLAYER
|
||||
toMove.teleport(toMove.getLoc());
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
toMove.setInBuildingID(0);
|
||||
toMove.setInFloorID(-1);
|
||||
toMove.setInBuilding(-1);
|
||||
msg.setStartCoord(toMove.getLoc());
|
||||
}
|
||||
|
||||
//make sure we set the correct player.
|
||||
msg.setSourceType(toMove.getObjectType().ordinal());
|
||||
msg.setSourceID(toMove.getObjectUUID());
|
||||
|
||||
//if player in region, modify location to local location of building. set target to building.
|
||||
if (toMove.region != null) {
|
||||
Building regionBuilding = Regions.GetBuildingForRegion(toMove.region);
|
||||
if (regionBuilding != null) {
|
||||
msg.setStartCoord(ZoneManager.convertWorldToLocal(Regions.GetBuildingForRegion(toMove.region), toMove.getLoc()));
|
||||
msg.setEndCoord(ZoneManager.convertWorldToLocal(regionBuilding, endLocation));
|
||||
msg.setInBuilding(toMove.region.level);
|
||||
msg.setUnknown01(toMove.region.room);
|
||||
msg.setTargetType(GameObjectType.Building.ordinal());
|
||||
msg.setTargetID(regionBuilding.getObjectUUID());
|
||||
}
|
||||
|
||||
} else {
|
||||
toMove.setInBuildingID(0);
|
||||
toMove.setInFloorID(-1);
|
||||
toMove.setInBuilding(-1);
|
||||
msg.setStartCoord(toMove.getLoc());
|
||||
msg.setEndCoord(endLocation);
|
||||
msg.setTargetType(0);
|
||||
msg.setTargetID(0);
|
||||
}
|
||||
|
||||
//checks sync between character and server, if out of sync, teleport player to original position and return.
|
||||
if (toMove.getObjectType() == GameObjectType.PlayerCharacter) {
|
||||
boolean startLocInSync = checkSync(toMove, startLocation, toMove.getLoc());
|
||||
|
||||
if (!startLocInSync){
|
||||
syncLoc(toMove, toMove.getLoc(), startLocInSync);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// set direction, based on the current location which has just been sync'd
|
||||
// with the client and the calc'd destination
|
||||
toMove.setFaceDir(endLocation.subtract2D(toMove.getLoc()).normalize());
|
||||
|
||||
boolean collide = false;
|
||||
if (toMove.getObjectType().equals(GameObjectType.PlayerCharacter)) {
|
||||
Vector3fImmutable collidePoint = Bounds.PlayerBuildingCollisionPoint((PlayerCharacter)toMove, toMove.getLoc(), endLocation);
|
||||
|
||||
if (collidePoint != null) {
|
||||
msg.setEndCoord(collidePoint);
|
||||
endLocation = collidePoint;
|
||||
collide = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (toMove.getObjectType() == GameObjectType.PlayerCharacter && ((PlayerCharacter) toMove).isTeleportMode()) {
|
||||
toMove.teleport(endLocation);
|
||||
return;
|
||||
}
|
||||
|
||||
// move to end location, this can interrupt the current move
|
||||
toMove.setEndLoc(endLocation);
|
||||
|
||||
// ChatManager.chatSystemInfo((PlayerCharacter)toMove, "Moving to " + Vector3fImmutable.toString(endLocation));
|
||||
|
||||
// make sure server knows player is not sitting
|
||||
toMove.setSit(false);
|
||||
|
||||
// cancel any effects that break upon movement
|
||||
toMove.cancelOnMove();
|
||||
|
||||
//cancel any attacks for manual move.
|
||||
if ((toMove.getObjectType() == GameObjectType.PlayerCharacter) && msg.getUnknown02() == 0)
|
||||
toMove.setCombatTarget(null);
|
||||
|
||||
|
||||
// If it's not a player moving just send the message
|
||||
|
||||
if ((toMove.getObjectType() == GameObjectType.PlayerCharacter) == false) {
|
||||
DispatchMessage.sendToAllInRange(toMove, msg);
|
||||
return;
|
||||
}
|
||||
|
||||
// If it's a player who is moving then we need to handle characters
|
||||
// who should see the message via group follow
|
||||
|
||||
PlayerCharacter player = (PlayerCharacter) toMove;
|
||||
|
||||
player.setTimeStamp("lastMoveGate", System.currentTimeMillis());
|
||||
|
||||
if (collide)
|
||||
DispatchMessage.dispatchMsgToInterestArea(player, msg, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false);
|
||||
else
|
||||
DispatchMessage.dispatchMsgToInterestArea(player, msg, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, false, false);
|
||||
|
||||
|
||||
// Handle formation movement if needed
|
||||
|
||||
if (player.getFollow() == false)
|
||||
return;
|
||||
|
||||
|
||||
City cityObject = null;
|
||||
Zone serverZone = null;
|
||||
|
||||
serverZone = ZoneManager.findSmallestZone(player.getLoc());
|
||||
cityObject = (City) DbManager.getFromCache(GameObjectType.City, serverZone.getPlayerCityUUID());
|
||||
|
||||
// Do not send group messages if player is on grid
|
||||
|
||||
if (cityObject != null)
|
||||
return;
|
||||
|
||||
// If player is not in a group we can exit here
|
||||
|
||||
Group group = GroupManager.getGroup(player);
|
||||
|
||||
if (group == null)
|
||||
return;
|
||||
|
||||
// Echo group movement messages
|
||||
|
||||
if (group.getGroupLead().getObjectUUID() == player.getObjectUUID())
|
||||
moveGroup(player, player.getClientConnection(), msg);
|
||||
|
||||
}
|
||||
if (!toMove.isMoving())
|
||||
toMove.resetLastSetLocUpdate();
|
||||
else
|
||||
toMove.update();
|
||||
|
||||
// Update movement for the player
|
||||
|
||||
|
||||
// else if (toMove.getObjectType() == GameObjectType.Mob)
|
||||
// ((Mob)toMove).updateLocation();
|
||||
// get start and end locations for the move
|
||||
Vector3fImmutable startLocation = new Vector3fImmutable(msg.getStartLat(), msg.getStartAlt(), msg.getStartLon());
|
||||
Vector3fImmutable endLocation = new Vector3fImmutable(msg.getEndLat(), msg.getEndAlt(), msg.getEndLon());
|
||||
|
||||
// if (toMove.getObjectType() == GameObjectType.PlayerCharacter)
|
||||
// if (msg.getEndAlt() == 0 && msg.getTargetID() == 0){
|
||||
// MovementManager.sendRWSSMsg(toMove);
|
||||
// }
|
||||
|
||||
//If in Building, let's see if we need to Fix
|
||||
|
||||
// if inside a building, convert both locations from the building local reference frame to the world reference frame
|
||||
|
||||
if (msg.getTargetID() > 0) {
|
||||
Building building = BuildingManager.getBuildingFromCache(msg.getTargetID());
|
||||
if (building != null) {
|
||||
|
||||
Vector3fImmutable convertLocEnd = new Vector3fImmutable(ZoneManager.convertLocalToWorld(building, endLocation));
|
||||
// if (!Bounds.collide(convertLocEnd, b) || !b.loadObjectsInside()) {
|
||||
// toMove.setInBuilding(-1);
|
||||
// toMove.setInFloorID(-1);
|
||||
// toMove.setInBuildingID(0);
|
||||
// }
|
||||
// else {
|
||||
toMove.setInBuilding(msg.getInBuilding());
|
||||
toMove.setInFloorID(msg.getUnknown01());
|
||||
toMove.setInBuildingID(msg.getTargetID());
|
||||
msg.setStartCoord(ZoneManager.convertWorldToLocal(building, toMove.getLoc()));
|
||||
|
||||
if (toMove.getObjectType() == GameObjectType.PlayerCharacter) {
|
||||
if (convertLocEnd.distanceSquared2D(toMove.getLoc()) > 6000 * 6000) {
|
||||
|
||||
Logger.info("ENDLOC:" + convertLocEnd.x + ',' + convertLocEnd.y + ',' + convertLocEnd.z +
|
||||
',' + "GETLOC:" + toMove.getLoc().x + ',' + toMove.getLoc().y + ',' + toMove.getLoc().z + " Name " + ((PlayerCharacter) toMove).getCombinedName());
|
||||
toMove.teleport(toMove.getLoc());
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
startLocation = toMove.getLoc();
|
||||
endLocation = convertLocEnd;
|
||||
|
||||
} else {
|
||||
|
||||
toMove.setInBuilding(-1);
|
||||
toMove.setInFloorID(-1);
|
||||
toMove.setInBuildingID(0);
|
||||
//SYNC PLAYER
|
||||
toMove.teleport(toMove.getLoc());
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* compare client and server location to verify that the two are in sync
|
||||
*
|
||||
* @param ac the player character
|
||||
* @param clientLoc location as reported by the client
|
||||
* @param serverLoc location known to the server
|
||||
* @return true if the two are in sync
|
||||
*/
|
||||
private static boolean checkSync(AbstractCharacter ac, Vector3fImmutable clientLoc, Vector3fImmutable serverLoc) {
|
||||
} else {
|
||||
toMove.setInBuildingID(0);
|
||||
toMove.setInFloorID(-1);
|
||||
toMove.setInBuilding(-1);
|
||||
msg.setStartCoord(toMove.getLoc());
|
||||
}
|
||||
|
||||
float desyncDist = clientLoc.distanceSquared2D(serverLoc);
|
||||
//make sure we set the correct player.
|
||||
msg.setSourceType(toMove.getObjectType().ordinal());
|
||||
msg.setSourceID(toMove.getObjectUUID());
|
||||
|
||||
// desync logging
|
||||
if (MBServerStatics.MOVEMENT_SYNC_DEBUG)
|
||||
if (desyncDist > MBServerStatics.MOVEMENT_DESYNC_TOLERANCE * MBServerStatics.MOVEMENT_DESYNC_TOLERANCE)
|
||||
// our current location server side is a calc of last known loc + direction + speed and known time of last update
|
||||
Logger.debug("Movement out of sync for " + ac.getFirstName()
|
||||
+ ", Server Loc: " + serverLoc.getX() + ' ' + serverLoc.getZ()
|
||||
+ " , Client loc: " + clientLoc.getX() + ' ' + clientLoc.getZ()
|
||||
+ " desync distance " + desyncDist
|
||||
+ " moving=" + ac.isMoving());
|
||||
else
|
||||
Logger.debug( "Movement sync is good - desyncDist = " + desyncDist);
|
||||
//if player in region, modify location to local location of building. set target to building.
|
||||
if (toMove.region != null) {
|
||||
Building regionBuilding = Regions.GetBuildingForRegion(toMove.region);
|
||||
if (regionBuilding != null) {
|
||||
msg.setStartCoord(ZoneManager.convertWorldToLocal(Regions.GetBuildingForRegion(toMove.region), toMove.getLoc()));
|
||||
msg.setEndCoord(ZoneManager.convertWorldToLocal(regionBuilding, endLocation));
|
||||
msg.setInBuilding(toMove.region.level);
|
||||
msg.setUnknown01(toMove.region.room);
|
||||
msg.setTargetType(GameObjectType.Building.ordinal());
|
||||
msg.setTargetID(regionBuilding.getObjectUUID());
|
||||
}
|
||||
|
||||
if (ac.getDebug(1) && ac.getObjectType().equals(GameObjectType.PlayerCharacter))
|
||||
if (desyncDist > MBServerStatics.MOVEMENT_DESYNC_TOLERANCE * MBServerStatics.MOVEMENT_DESYNC_TOLERANCE) {
|
||||
PlayerCharacter pc = (PlayerCharacter) ac;
|
||||
ChatManager.chatSystemInfo(pc,
|
||||
"Movement out of sync for " + ac.getFirstName()
|
||||
+ ", Server Loc: " + serverLoc.getX() + ' ' + serverLoc.getZ()
|
||||
+ " , Client loc: " + clientLoc.getX() + ' ' + clientLoc.getZ()
|
||||
+ " desync distance " + desyncDist
|
||||
+ " moving=" + ac.isMoving());
|
||||
}
|
||||
} else {
|
||||
toMove.setInBuildingID(0);
|
||||
toMove.setInFloorID(-1);
|
||||
toMove.setInBuilding(-1);
|
||||
msg.setStartCoord(toMove.getLoc());
|
||||
msg.setEndCoord(endLocation);
|
||||
msg.setTargetType(0);
|
||||
msg.setTargetID(0);
|
||||
}
|
||||
|
||||
// return indicator that the two are in sync or not
|
||||
return (desyncDist < 100f * 100f);
|
||||
//checks sync between character and server, if out of sync, teleport player to original position and return.
|
||||
if (toMove.getObjectType() == GameObjectType.PlayerCharacter) {
|
||||
boolean startLocInSync = checkSync(toMove, startLocation, toMove.getLoc());
|
||||
|
||||
}
|
||||
if (!startLocInSync) {
|
||||
syncLoc(toMove, toMove.getLoc(), startLocInSync);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// set direction, based on the current location which has just been sync'd
|
||||
// with the client and the calc'd destination
|
||||
toMove.setFaceDir(endLocation.subtract2D(toMove.getLoc()).normalize());
|
||||
|
||||
public static void finishChangeAltitude(AbstractCharacter ac, float targetAlt) {
|
||||
boolean collide = false;
|
||||
if (toMove.getObjectType().equals(GameObjectType.PlayerCharacter)) {
|
||||
Vector3fImmutable collidePoint = Bounds.PlayerBuildingCollisionPoint((PlayerCharacter) toMove, toMove.getLoc(), endLocation);
|
||||
|
||||
if (ac.getObjectType().equals(GameObjectType.PlayerCharacter) == false)
|
||||
return;
|
||||
if (collidePoint != null) {
|
||||
msg.setEndCoord(collidePoint);
|
||||
endLocation = collidePoint;
|
||||
collide = true;
|
||||
}
|
||||
|
||||
//reset the getLoc timer before we clear other timers
|
||||
// otherwise the next call to getLoc will not be correct
|
||||
ac.resetLastSetLocUpdate();
|
||||
}
|
||||
|
||||
// call getLoc once as it processes loc to the ms
|
||||
Vector3fImmutable curLoc = ac.getLoc();
|
||||
if (toMove.getObjectType() == GameObjectType.PlayerCharacter && ((PlayerCharacter) toMove).isTeleportMode()) {
|
||||
toMove.teleport(endLocation);
|
||||
return;
|
||||
}
|
||||
|
||||
// move to end location, this can interrupt the current move
|
||||
toMove.setEndLoc(endLocation);
|
||||
|
||||
// ChatManager.chatSystemInfo((PlayerCharacter)toMove, "Moving to " + Vector3fImmutable.toString(endLocation));
|
||||
|
||||
if (MBServerStatics.MOVEMENT_SYNC_DEBUG)
|
||||
Logger.info("Finished Alt change, setting the end location to "
|
||||
+ ac.getEndLoc().getX() + ' ' + ac.getEndLoc().getZ()
|
||||
+ " moving=" + ac.isMoving()
|
||||
+ " and current location is " + curLoc.getX() + ' ' + curLoc.getZ());
|
||||
|
||||
if (ac.getDebug(1) && ac.getObjectType().equals(GameObjectType.PlayerCharacter))
|
||||
ChatManager.chatSystemInfo((PlayerCharacter) ac, "Finished Alt change, setting the end location to " + ac.getEndLoc().getX() + ' ' + ac.getEndLoc().getZ() + " moving=" + ac.isMoving() + " and current location is " + curLoc.getX() + ' ' + curLoc.getZ());
|
||||
|
||||
//Send run/walk/sit/stand to tell the client we are flying / landing etc
|
||||
ac.update();
|
||||
ac.stopMovement(ac.getLoc());
|
||||
if (ac.isAlive())
|
||||
MovementManager.sendRWSSMsg(ac);
|
||||
|
||||
//Check collision again
|
||||
}
|
||||
|
||||
|
||||
// Handle formation movement in group
|
||||
|
||||
public static void moveGroup(PlayerCharacter pc, ClientConnection origin, MoveToPointMsg msg) throws MsgSendException {
|
||||
// get forward vector
|
||||
Vector3f faceDir = new Vector3f(pc.getFaceDir().x, 0, pc.getFaceDir().z).normalize();
|
||||
// get perpendicular vector
|
||||
Vector3f crossDir = new Vector3f(faceDir.z, 0, -faceDir.x);
|
||||
|
||||
//get source loc with altitude
|
||||
Vector3f sLoc = new Vector3f(pc.getLoc().x, pc.getAltitude(), pc.getLoc().z);
|
||||
|
||||
Group group = GroupManager.getGroup(pc);
|
||||
Set<PlayerCharacter> members = group.getMembers();
|
||||
int pos = 0;
|
||||
for (PlayerCharacter member : members) {
|
||||
|
||||
if (member == null)
|
||||
continue;
|
||||
if (member.getObjectUUID() == pc.getObjectUUID())
|
||||
continue;
|
||||
|
||||
MoveToPointMsg groupMsg = new MoveToPointMsg(msg);
|
||||
|
||||
// Verify group member should be moved
|
||||
|
||||
pos++;
|
||||
if (member.getFollow() != true)
|
||||
continue;
|
||||
|
||||
//get member loc with altitude, then range against source loc
|
||||
Vector3f mLoc = new Vector3f(member.getLoc().x, member.getAltitude(), member.getLoc().z);
|
||||
|
||||
if (sLoc.distanceSquared2D(mLoc) > sqr(MBServerStatics.FORMATION_RANGE))
|
||||
continue;
|
||||
|
||||
//don't move if player has taken damage from another player in last 60 seconds
|
||||
long lastAttacked = System.currentTimeMillis() - pc.getLastPlayerAttackTime();
|
||||
if (lastAttacked < 60000)
|
||||
continue;
|
||||
|
||||
if (!member.isAlive())
|
||||
continue;
|
||||
|
||||
//don't move if player is stunned or rooted
|
||||
PlayerBonuses bonus = member.getBonuses();
|
||||
if (bonus.getBool(ModType.Stunned, SourceType.None) || bonus.getBool(ModType.CannotMove, SourceType.None))
|
||||
continue;
|
||||
|
||||
member.update();
|
||||
|
||||
|
||||
// All checks passed, let's move the player
|
||||
// First get the offset position
|
||||
Vector3f offset = Formation.getOffset(group.getFormation(), pos);
|
||||
Vector3fImmutable destination = pc.getEndLoc();
|
||||
// offset forwards or backwards
|
||||
destination = destination.add(faceDir.mult(offset.z));
|
||||
// offset left or right
|
||||
destination = destination.add(crossDir.mult(offset.x));
|
||||
// ArrayList<AbstractWorldObject> awoList = WorldGrid.INSTANCE.getObjectsInRangePartial(member, member.getLoc().distance2D(destination) +1000, MBServerStatics.MASK_BUILDING);
|
||||
//
|
||||
// boolean skip = false;
|
||||
//
|
||||
// for (AbstractWorldObject awo: awoList){
|
||||
// Building building = (Building)awo;
|
||||
//
|
||||
// if (building.getBounds() != null){
|
||||
// if (Bounds.collide(building, member.getLoc(), destination)){
|
||||
// skip = true;
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// if (skip)
|
||||
// continue;
|
||||
// if (member.isMoving())
|
||||
// member.stopMovement();
|
||||
|
||||
// Update player speed to match group lead speed and make standing
|
||||
if (member.isSit() || (member.isWalk() != pc.isWalk())) {
|
||||
member.setSit(false);
|
||||
member.setWalkMode(pc.isWalk());
|
||||
MovementManager.sendRWSSMsg(member);
|
||||
}
|
||||
|
||||
//cancel any effects that break upon movement
|
||||
member.cancelOnMove();
|
||||
|
||||
// send movement for other players to see
|
||||
groupMsg.setSourceID(member.getObjectUUID());
|
||||
groupMsg.setStartCoord(member.getLoc());
|
||||
groupMsg.setEndCoord(destination);
|
||||
groupMsg.clearTarget();
|
||||
DispatchMessage.sendToAllInRange(member, groupMsg);
|
||||
|
||||
// update group member
|
||||
member.setFaceDir(destination.subtract2D(member.getLoc()).normalize());
|
||||
member.setEndLoc(destination);
|
||||
}
|
||||
}
|
||||
|
||||
public static void translocate(AbstractCharacter teleporter, Vector3fImmutable targetLoc, Regions region) {
|
||||
|
||||
|
||||
if (targetLoc == null)
|
||||
return;
|
||||
|
||||
Vector3fImmutable oldLoc = new Vector3fImmutable(teleporter.getLoc());
|
||||
|
||||
teleporter.stopMovement(targetLoc);
|
||||
teleporter.setRegion(region);
|
||||
|
||||
//mobs ignore region sets for now.
|
||||
if (teleporter.getObjectType().equals(GameObjectType.Mob)){
|
||||
teleporter.setInBuildingID(0);
|
||||
teleporter.setInBuilding(-1);
|
||||
teleporter.setInFloorID(-1);
|
||||
TeleportToPointMsg msg = new TeleportToPointMsg(teleporter, targetLoc.getX(), targetLoc.getY(), targetLoc.getZ(), 0, -1, -1);
|
||||
DispatchMessage.dispatchMsgToInterestArea(oldLoc, teleporter, msg, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, false, false);
|
||||
return;
|
||||
}
|
||||
TeleportToPointMsg msg = new TeleportToPointMsg(teleporter, targetLoc.getX(), targetLoc.getY(), targetLoc.getZ(), 0, -1, -1);
|
||||
//we shouldnt need to send teleport message to new area, as loadjob should pick it up.
|
||||
// DispatchMessage.dispatchMsgToInterestArea(teleporter, msg, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false);
|
||||
DispatchMessage.dispatchMsgToInterestArea(oldLoc, teleporter, msg, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false);
|
||||
|
||||
if (teleporter.getObjectType().equals(GameObjectType.PlayerCharacter))
|
||||
InterestManager.INTERESTMANAGER.HandleLoadForTeleport((PlayerCharacter)teleporter);
|
||||
|
||||
}
|
||||
|
||||
private static void syncLoc(AbstractCharacter ac, Vector3fImmutable clientLoc, boolean useClientLoc) {
|
||||
ac.teleport(ac.getLoc());
|
||||
}
|
||||
// make sure server knows player is not sitting
|
||||
toMove.setSit(false);
|
||||
|
||||
// cancel any effects that break upon movement
|
||||
toMove.cancelOnMove();
|
||||
|
||||
//cancel any attacks for manual move.
|
||||
if ((toMove.getObjectType() == GameObjectType.PlayerCharacter) && msg.getUnknown02() == 0)
|
||||
toMove.setCombatTarget(null);
|
||||
|
||||
|
||||
// If it's not a player moving just send the message
|
||||
|
||||
if ((toMove.getObjectType() == GameObjectType.PlayerCharacter) == false) {
|
||||
DispatchMessage.sendToAllInRange(toMove, msg);
|
||||
return;
|
||||
}
|
||||
|
||||
// If it's a player who is moving then we need to handle characters
|
||||
// who should see the message via group follow
|
||||
|
||||
PlayerCharacter player = (PlayerCharacter) toMove;
|
||||
|
||||
player.setTimeStamp("lastMoveGate", System.currentTimeMillis());
|
||||
|
||||
if (collide)
|
||||
DispatchMessage.dispatchMsgToInterestArea(player, msg, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false);
|
||||
else
|
||||
DispatchMessage.dispatchMsgToInterestArea(player, msg, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, false, false);
|
||||
|
||||
|
||||
// Handle formation movement if needed
|
||||
|
||||
if (player.getFollow() == false)
|
||||
return;
|
||||
|
||||
|
||||
City cityObject = null;
|
||||
Zone serverZone = null;
|
||||
|
||||
serverZone = ZoneManager.findSmallestZone(player.getLoc());
|
||||
cityObject = (City) DbManager.getFromCache(GameObjectType.City, serverZone.getPlayerCityUUID());
|
||||
|
||||
// Do not send group messages if player is on grid
|
||||
|
||||
if (cityObject != null)
|
||||
return;
|
||||
|
||||
// If player is not in a group we can exit here
|
||||
|
||||
Group group = GroupManager.getGroup(player);
|
||||
|
||||
if (group == null)
|
||||
return;
|
||||
|
||||
// Echo group movement messages
|
||||
|
||||
if (group.getGroupLead().getObjectUUID() == player.getObjectUUID())
|
||||
moveGroup(player, player.getClientConnection(), msg);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* compare client and server location to verify that the two are in sync
|
||||
*
|
||||
* @param ac the player character
|
||||
* @param clientLoc location as reported by the client
|
||||
* @param serverLoc location known to the server
|
||||
* @return true if the two are in sync
|
||||
*/
|
||||
private static boolean checkSync(AbstractCharacter ac, Vector3fImmutable clientLoc, Vector3fImmutable serverLoc) {
|
||||
|
||||
float desyncDist = clientLoc.distanceSquared2D(serverLoc);
|
||||
|
||||
// desync logging
|
||||
if (MBServerStatics.MOVEMENT_SYNC_DEBUG)
|
||||
if (desyncDist > MBServerStatics.MOVEMENT_DESYNC_TOLERANCE * MBServerStatics.MOVEMENT_DESYNC_TOLERANCE)
|
||||
// our current location server side is a calc of last known loc + direction + speed and known time of last update
|
||||
Logger.debug("Movement out of sync for " + ac.getFirstName()
|
||||
+ ", Server Loc: " + serverLoc.getX() + ' ' + serverLoc.getZ()
|
||||
+ " , Client loc: " + clientLoc.getX() + ' ' + clientLoc.getZ()
|
||||
+ " desync distance " + desyncDist
|
||||
+ " moving=" + ac.isMoving());
|
||||
else
|
||||
Logger.debug("Movement sync is good - desyncDist = " + desyncDist);
|
||||
|
||||
if (ac.getDebug(1) && ac.getObjectType().equals(GameObjectType.PlayerCharacter))
|
||||
if (desyncDist > MBServerStatics.MOVEMENT_DESYNC_TOLERANCE * MBServerStatics.MOVEMENT_DESYNC_TOLERANCE) {
|
||||
PlayerCharacter pc = (PlayerCharacter) ac;
|
||||
ChatManager.chatSystemInfo(pc,
|
||||
"Movement out of sync for " + ac.getFirstName()
|
||||
+ ", Server Loc: " + serverLoc.getX() + ' ' + serverLoc.getZ()
|
||||
+ " , Client loc: " + clientLoc.getX() + ' ' + clientLoc.getZ()
|
||||
+ " desync distance " + desyncDist
|
||||
+ " moving=" + ac.isMoving());
|
||||
}
|
||||
|
||||
// return indicator that the two are in sync or not
|
||||
return (desyncDist < 100f * 100f);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static void finishChangeAltitude(AbstractCharacter ac, float targetAlt) {
|
||||
|
||||
if (ac.getObjectType().equals(GameObjectType.PlayerCharacter) == false)
|
||||
return;
|
||||
|
||||
//reset the getLoc timer before we clear other timers
|
||||
// otherwise the next call to getLoc will not be correct
|
||||
ac.resetLastSetLocUpdate();
|
||||
|
||||
// call getLoc once as it processes loc to the ms
|
||||
Vector3fImmutable curLoc = ac.getLoc();
|
||||
|
||||
if (MBServerStatics.MOVEMENT_SYNC_DEBUG)
|
||||
Logger.info("Finished Alt change, setting the end location to "
|
||||
+ ac.getEndLoc().getX() + ' ' + ac.getEndLoc().getZ()
|
||||
+ " moving=" + ac.isMoving()
|
||||
+ " and current location is " + curLoc.getX() + ' ' + curLoc.getZ());
|
||||
|
||||
if (ac.getDebug(1) && ac.getObjectType().equals(GameObjectType.PlayerCharacter))
|
||||
ChatManager.chatSystemInfo((PlayerCharacter) ac, "Finished Alt change, setting the end location to " + ac.getEndLoc().getX() + ' ' + ac.getEndLoc().getZ() + " moving=" + ac.isMoving() + " and current location is " + curLoc.getX() + ' ' + curLoc.getZ());
|
||||
|
||||
//Send run/walk/sit/stand to tell the client we are flying / landing etc
|
||||
ac.update();
|
||||
ac.stopMovement(ac.getLoc());
|
||||
if (ac.isAlive())
|
||||
MovementManager.sendRWSSMsg(ac);
|
||||
|
||||
//Check collision again
|
||||
}
|
||||
|
||||
|
||||
// Handle formation movement in group
|
||||
|
||||
public static void moveGroup(PlayerCharacter pc, ClientConnection origin, MoveToPointMsg msg) throws MsgSendException {
|
||||
// get forward vector
|
||||
Vector3f faceDir = new Vector3f(pc.getFaceDir().x, 0, pc.getFaceDir().z).normalize();
|
||||
// get perpendicular vector
|
||||
Vector3f crossDir = new Vector3f(faceDir.z, 0, -faceDir.x);
|
||||
|
||||
//get source loc with altitude
|
||||
Vector3f sLoc = new Vector3f(pc.getLoc().x, pc.getAltitude(), pc.getLoc().z);
|
||||
|
||||
Group group = GroupManager.getGroup(pc);
|
||||
Set<PlayerCharacter> members = group.getMembers();
|
||||
int pos = 0;
|
||||
for (PlayerCharacter member : members) {
|
||||
|
||||
if (member == null)
|
||||
continue;
|
||||
if (member.getObjectUUID() == pc.getObjectUUID())
|
||||
continue;
|
||||
|
||||
MoveToPointMsg groupMsg = new MoveToPointMsg(msg);
|
||||
|
||||
// Verify group member should be moved
|
||||
|
||||
pos++;
|
||||
if (member.getFollow() != true)
|
||||
continue;
|
||||
|
||||
//get member loc with altitude, then range against source loc
|
||||
Vector3f mLoc = new Vector3f(member.getLoc().x, member.getAltitude(), member.getLoc().z);
|
||||
|
||||
if (sLoc.distanceSquared2D(mLoc) > sqr(MBServerStatics.FORMATION_RANGE))
|
||||
continue;
|
||||
|
||||
//don't move if player has taken damage from another player in last 60 seconds
|
||||
long lastAttacked = System.currentTimeMillis() - pc.getLastPlayerAttackTime();
|
||||
if (lastAttacked < 60000)
|
||||
continue;
|
||||
|
||||
if (!member.isAlive())
|
||||
continue;
|
||||
|
||||
//don't move if player is stunned or rooted
|
||||
PlayerBonuses bonus = member.getBonuses();
|
||||
if (bonus.getBool(ModType.Stunned, SourceType.None) || bonus.getBool(ModType.CannotMove, SourceType.None))
|
||||
continue;
|
||||
|
||||
member.update();
|
||||
|
||||
|
||||
// All checks passed, let's move the player
|
||||
// First get the offset position
|
||||
Vector3f offset = Formation.getOffset(group.getFormation(), pos);
|
||||
Vector3fImmutable destination = pc.getEndLoc();
|
||||
// offset forwards or backwards
|
||||
destination = destination.add(faceDir.mult(offset.z));
|
||||
// offset left or right
|
||||
destination = destination.add(crossDir.mult(offset.x));
|
||||
// ArrayList<AbstractWorldObject> awoList = WorldGrid.INSTANCE.getObjectsInRangePartial(member, member.getLoc().distance2D(destination) +1000, MBServerStatics.MASK_BUILDING);
|
||||
//
|
||||
// boolean skip = false;
|
||||
//
|
||||
// for (AbstractWorldObject awo: awoList){
|
||||
// Building building = (Building)awo;
|
||||
//
|
||||
// if (building.getBounds() != null){
|
||||
// if (Bounds.collide(building, member.getLoc(), destination)){
|
||||
// skip = true;
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// if (skip)
|
||||
// continue;
|
||||
// if (member.isMoving())
|
||||
// member.stopMovement();
|
||||
|
||||
// Update player speed to match group lead speed and make standing
|
||||
if (member.isSit() || (member.isWalk() != pc.isWalk())) {
|
||||
member.setSit(false);
|
||||
member.setWalkMode(pc.isWalk());
|
||||
MovementManager.sendRWSSMsg(member);
|
||||
}
|
||||
|
||||
//cancel any effects that break upon movement
|
||||
member.cancelOnMove();
|
||||
|
||||
// send movement for other players to see
|
||||
groupMsg.setSourceID(member.getObjectUUID());
|
||||
groupMsg.setStartCoord(member.getLoc());
|
||||
groupMsg.setEndCoord(destination);
|
||||
groupMsg.clearTarget();
|
||||
DispatchMessage.sendToAllInRange(member, groupMsg);
|
||||
|
||||
// update group member
|
||||
member.setFaceDir(destination.subtract2D(member.getLoc()).normalize());
|
||||
member.setEndLoc(destination);
|
||||
}
|
||||
}
|
||||
|
||||
public static void translocate(AbstractCharacter teleporter, Vector3fImmutable targetLoc, Regions region) {
|
||||
|
||||
|
||||
if (targetLoc == null)
|
||||
return;
|
||||
|
||||
Vector3fImmutable oldLoc = new Vector3fImmutable(teleporter.getLoc());
|
||||
|
||||
teleporter.stopMovement(targetLoc);
|
||||
teleporter.setRegion(region);
|
||||
|
||||
//mobs ignore region sets for now.
|
||||
if (teleporter.getObjectType().equals(GameObjectType.Mob)) {
|
||||
teleporter.setInBuildingID(0);
|
||||
teleporter.setInBuilding(-1);
|
||||
teleporter.setInFloorID(-1);
|
||||
TeleportToPointMsg msg = new TeleportToPointMsg(teleporter, targetLoc.getX(), targetLoc.getY(), targetLoc.getZ(), 0, -1, -1);
|
||||
DispatchMessage.dispatchMsgToInterestArea(oldLoc, teleporter, msg, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, false, false);
|
||||
return;
|
||||
}
|
||||
TeleportToPointMsg msg = new TeleportToPointMsg(teleporter, targetLoc.getX(), targetLoc.getY(), targetLoc.getZ(), 0, -1, -1);
|
||||
//we shouldnt need to send teleport message to new area, as loadjob should pick it up.
|
||||
// DispatchMessage.dispatchMsgToInterestArea(teleporter, msg, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false);
|
||||
DispatchMessage.dispatchMsgToInterestArea(oldLoc, teleporter, msg, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false);
|
||||
|
||||
if (teleporter.getObjectType().equals(GameObjectType.PlayerCharacter))
|
||||
InterestManager.INTERESTMANAGER.HandleLoadForTeleport((PlayerCharacter) teleporter);
|
||||
|
||||
}
|
||||
|
||||
private static void syncLoc(AbstractCharacter ac, Vector3fImmutable clientLoc, boolean useClientLoc) {
|
||||
ac.teleport(ac.getLoc());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user