🆙 Updated the LoopTracker for rollers
This commit is contained in:
parent
3332bc7f9c
commit
d1ff6687d6
@ -700,6 +700,7 @@ public class Room implements Comparable<Room>, ISerialize, Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.sendComposer(new UpdateStackHeightComposer(this, updatedTiles).compose());
|
this.sendComposer(new UpdateStackHeightComposer(this, updatedTiles).compose());
|
||||||
this.updateTiles(updatedTiles);
|
this.updateTiles(updatedTiles);
|
||||||
for (RoomTile tile : updatedTiles) {
|
for (RoomTile tile : updatedTiles) {
|
||||||
@ -1188,6 +1189,47 @@ public class Room implements Comparable<Room>, ISerialize, Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isOnRoller(RoomUnit unit) {
|
||||||
|
RoomTile currentTile = unit.getCurrentLocation();
|
||||||
|
// Iterate over all rollers in the room.
|
||||||
|
for (HabboItem roller : this.roomSpecialTypes.getRollers().values()) {
|
||||||
|
if (roller.getX() == currentTile.x && roller.getY() == currentTile.y) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Map<RoomUnit, LoopTracker> loopTrackers = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private static class LoopTracker {
|
||||||
|
double x, y, z;
|
||||||
|
int counter;
|
||||||
|
RoomTile nextTile;
|
||||||
|
|
||||||
|
public LoopTracker(double x, double y, double z, RoomTile nextTile) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.z = z;
|
||||||
|
this.counter = 0;
|
||||||
|
this.nextTile = nextTile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSamePosition(double newX, double newY, double newZ) {
|
||||||
|
// Use an epsilon for double comparison if necessary.
|
||||||
|
final double EPSILON = 0.001;
|
||||||
|
return Math.abs(newX - x) < EPSILON && Math.abs(newY - y) < EPSILON && Math.abs(newZ - z) < EPSILON;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update(double newX, double newY, double newZ, RoomTile nextTile) {
|
||||||
|
this.x = newX;
|
||||||
|
this.y = newY;
|
||||||
|
this.z = newZ;
|
||||||
|
this.counter = 0;
|
||||||
|
this.nextTile = nextTile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void cycle() {
|
private void cycle() {
|
||||||
this.cycleOdd = !this.cycleOdd;
|
this.cycleOdd = !this.cycleOdd;
|
||||||
this.cycleTimestamp = System.currentTimeMillis();
|
this.cycleTimestamp = System.currentTimeMillis();
|
||||||
@ -1238,31 +1280,97 @@ public class Room implements Comparable<Room>, ISerialize, Runnable {
|
|||||||
|
|
||||||
for (Habbo habbo : this.currentHabbos.values()) {
|
for (Habbo habbo : this.currentHabbos.values()) {
|
||||||
RoomUnit unit = habbo.getRoomUnit();
|
RoomUnit unit = habbo.getRoomUnit();
|
||||||
// Only run loop detection if the unit is on a roller.
|
|
||||||
if (!unit.hasStatus(RoomUnitStatus.MOVE) && isOnRoller(unit)) {
|
if (!unit.hasStatus(RoomUnitStatus.MOVE) && isOnRoller(unit)) {
|
||||||
double curX = unit.getX();
|
double curX = unit.getX();
|
||||||
double curY = unit.getY();
|
double curY = unit.getY();
|
||||||
double curZ = unit.getZ();
|
double curZ = unit.getZ();
|
||||||
|
|
||||||
// Get or create a loop tracker for this unit.
|
LoopTracker tracker = loopTrackers.computeIfAbsent(unit, u -> {
|
||||||
LoopTracker tracker = loopTrackers.computeIfAbsent(unit, u -> new LoopTracker(curX, curY, curZ));
|
RoomTile nextTile = null;
|
||||||
|
for (InteractionRoller roller : this.roomSpecialTypes.getRollers().values()) {
|
||||||
|
RoomTile rollerTile = this.getLayout().getTile((short) roller.getX(), (short) roller.getY());
|
||||||
|
RoomTile potentialNextTile = this.getLayout().getTileInFront(rollerTile, roller.getRotation());
|
||||||
|
if (potentialNextTile != null) {
|
||||||
|
nextTile = potentialNextTile;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new LoopTracker(curX, curY, curZ, nextTile);
|
||||||
|
});
|
||||||
|
|
||||||
if (tracker.isSamePosition(curX, curY, curZ)) {
|
if (tracker.isSamePosition(curX, curY, curZ)) {
|
||||||
tracker.counter++;
|
InteractionRoller currentRoller = null;
|
||||||
// Compute threshold based on roller speed (max speed = 10).
|
RoomTile currentTile = this.getLayout().getTile((short) curX, (short) curY);
|
||||||
int loopThreshold = Math.max(10, 3 + this.getRollerSpeed());
|
for (InteractionRoller roller : this.roomSpecialTypes.getRollers().values()) {
|
||||||
if (tracker.counter >= loopThreshold) {
|
if (roller.getX() == currentTile.x && roller.getY() == currentTile.y) {
|
||||||
LOGGER.warn("Loop detected for unit id " + unit.getId() +
|
currentRoller = roller;
|
||||||
" at position: x=" + curX + ", y=" + curY + ", z=" + curZ);
|
break;
|
||||||
// Teleport unit back to the door tile.
|
}
|
||||||
RoomTile doorTile = this.getLayout().getDoorTile();
|
}
|
||||||
this.teleportRoomUnitToLocation(unit, doorTile.x, doorTile.y, doorTile.z);
|
|
||||||
|
RoomTile currentCalculatedNextTile = null;
|
||||||
|
if (currentRoller != null) {
|
||||||
|
RoomTile rollerTile = this.getLayout().getTile((short) currentRoller.getX(), (short) currentRoller.getY());
|
||||||
|
currentCalculatedNextTile = this.getLayout().getTileInFront(rollerTile, currentRoller.getRotation());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentTile != null && unit.getGoal() != null) {
|
||||||
|
double distanceToGoal = Math.hypot(unit.getGoal().x - currentTile.x, unit.getGoal().y - currentTile.y);
|
||||||
|
final double ACCEPTABLE_DISTANCE = 0.5; // adjust as needed
|
||||||
|
if (distanceToGoal <= ACCEPTABLE_DISTANCE) {
|
||||||
|
tracker.update(curX, curY, curZ, currentCalculatedNextTile);
|
||||||
|
tracker.counter = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean nextTileHasRoller = false;
|
||||||
|
if (currentCalculatedNextTile != null) {
|
||||||
|
for (InteractionRoller roller : this.roomSpecialTypes.getRollers().values()) {
|
||||||
|
if (roller.getX() == currentCalculatedNextTile.x && roller.getY() == currentCalculatedNextTile.y) {
|
||||||
|
nextTileHasRoller = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentCalculatedNextTile != null && !nextTileHasRoller) {
|
||||||
|
tracker.update(curX, curY, curZ, currentCalculatedNextTile);
|
||||||
tracker.counter = 0;
|
tracker.counter = 0;
|
||||||
|
} else {
|
||||||
|
if (unit.getGoal() != null && tracker.nextTile != null &&
|
||||||
|
unit.getGoal().x == tracker.nextTile.x && unit.getGoal().y == tracker.nextTile.y) {
|
||||||
|
tracker.counter = 0;
|
||||||
|
} else {
|
||||||
|
tracker.counter++;
|
||||||
|
int loopThreshold = Math.max(10, 3 + this.getRollerSpeed());
|
||||||
|
if (tracker.counter >= loopThreshold) {
|
||||||
|
RoomTile doorTile = this.getLayout().getDoorTile();
|
||||||
|
unit.setBodyRotation(RoomUserRotation.values()[this.getLayout().getDoorDirection()]);
|
||||||
|
unit.setHeadRotation(RoomUserRotation.values()[this.getLayout().getDoorDirection()]);
|
||||||
|
this.teleportRoomUnitToLocation(unit, doorTile.x, doorTile.y, doorTile.z);
|
||||||
|
tracker.counter = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tracker.update(curX, curY, curZ);
|
InteractionRoller currentRoller = null;
|
||||||
|
RoomTile currentTile = this.getLayout().getTile((short) curX, (short) curY);
|
||||||
|
for (InteractionRoller roller : this.roomSpecialTypes.getRollers().values()) {
|
||||||
|
if (roller.getX() == currentTile.x && roller.getY() == currentTile.y) {
|
||||||
|
currentRoller = roller;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RoomTile nextTile = null;
|
||||||
|
if (currentRoller != null) {
|
||||||
|
RoomTile rollerTile = this.getLayout().getTile((short) currentRoller.getX(), (short) currentRoller.getY());
|
||||||
|
nextTile = this.getLayout().getTileInFront(rollerTile, currentRoller.getRotation());
|
||||||
|
}
|
||||||
|
tracker.update(curX, curY, curZ, nextTile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!foundRightHolder[0]) {
|
if (!foundRightHolder[0]) {
|
||||||
foundRightHolder[0] = habbo.getRoomUnit().getRightsLevel() != RoomRightLevels.NONE;
|
foundRightHolder[0] = habbo.getRoomUnit().getRightsLevel() != RoomRightLevels.NONE;
|
||||||
}
|
}
|
||||||
@ -1314,7 +1422,6 @@ public class Room implements Comparable<Room>, ISerialize, Runnable {
|
|||||||
this.sendComposer(new RoomUserIgnoredComposer(habbo, RoomUserIgnoredComposer.UNIGNORED).compose());
|
this.sendComposer(new RoomUserIgnoredComposer(habbo, RoomUserIgnoredComposer.UNIGNORED).compose());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Substract 1 from the chatCounter every odd cycle, which is every (500ms * 2).
|
|
||||||
if (this.cycleOdd && habbo.getHabboStats().chatCounter.get() > 0) {
|
if (this.cycleOdd && habbo.getHabboStats().chatCounter.get() > 0) {
|
||||||
habbo.getHabboStats().chatCounter.decrementAndGet();
|
habbo.getHabboStats().chatCounter.decrementAndGet();
|
||||||
}
|
}
|
||||||
@ -1396,19 +1503,15 @@ public class Room implements Comparable<Room>, ISerialize, Runnable {
|
|||||||
|
|
||||||
List<InteractionRoller> rollers = new ArrayList<>(this.roomSpecialTypes.getRollers().values());
|
List<InteractionRoller> rollers = new ArrayList<>(this.roomSpecialTypes.getRollers().values());
|
||||||
|
|
||||||
// Sort rollers using a custom comparator that uses a projection of the roller's position
|
|
||||||
rollers.sort((r1, r2) -> {
|
rollers.sort((r1, r2) -> {
|
||||||
// Convert the roller's rotation into an angle in radians.
|
|
||||||
double angle1 = Math.toRadians(r1.getRotation() * 45);
|
double angle1 = Math.toRadians(r1.getRotation() * 45);
|
||||||
double angle2 = Math.toRadians(r2.getRotation() * 45);
|
double angle2 = Math.toRadians(r2.getRotation() * 45);
|
||||||
|
|
||||||
// Compute the movement vector for each roller (a unit vector in its direction)
|
|
||||||
double vx1 = Math.cos(angle1);
|
double vx1 = Math.cos(angle1);
|
||||||
double vy1 = Math.sin(angle1);
|
double vy1 = Math.sin(angle1);
|
||||||
double vx2 = Math.cos(angle2);
|
double vx2 = Math.cos(angle2);
|
||||||
double vy2 = Math.sin(angle2);
|
double vy2 = Math.sin(angle2);
|
||||||
|
|
||||||
// Calculate the projection of the roller's position along its movement vector
|
|
||||||
double proj1 = r1.getX() * vx1 + r1.getY() * vy1;
|
double proj1 = r1.getX() * vx1 + r1.getY() * vy1;
|
||||||
double proj2 = r2.getX() * vx2 + r2.getY() * vy2;
|
double proj2 = r2.getX() * vx2 + r2.getY() * vy2;
|
||||||
|
|
||||||
@ -1442,7 +1545,6 @@ public class Room implements Comparable<Room>, ISerialize, Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// itemsOnRoller.addAll(this.getItemsAt(rollerTile));
|
|
||||||
itemsOnRoller.remove(roller);
|
itemsOnRoller.remove(roller);
|
||||||
|
|
||||||
if (!rollerTile.hasUnits() && itemsOnRoller.isEmpty())
|
if (!rollerTile.hasUnits() && itemsOnRoller.isEmpty())
|
||||||
@ -1707,7 +1809,6 @@ public class Room implements Comparable<Room>, ISerialize, Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private boolean cycleRoomUnit(RoomUnit unit, RoomUnitType type) {
|
private boolean cycleRoomUnit(RoomUnit unit, RoomUnitType type) {
|
||||||
boolean update = unit.needsStatusUpdate();
|
boolean update = unit.needsStatusUpdate();
|
||||||
if (unit.hasStatus(RoomUnitStatus.SIGN)) {
|
if (unit.hasStatus(RoomUnitStatus.SIGN)) {
|
||||||
@ -3049,6 +3150,7 @@ public class Room implements Comparable<Room>, ISerialize, Runnable {
|
|||||||
|
|
||||||
return pets;
|
return pets;
|
||||||
}
|
}
|
||||||
|
|
||||||
public THashSet<Habbo> getHabbosAt(short x, short y) {
|
public THashSet<Habbo> getHabbosAt(short x, short y) {
|
||||||
return this.getHabbosAt(this.layout.getTile(x, y));
|
return this.getHabbosAt(this.layout.getTile(x, y));
|
||||||
}
|
}
|
||||||
@ -3133,8 +3235,7 @@ public class Room implements Comparable<Room>, ISerialize, Runnable {
|
|||||||
roomUnit.setZ(z);
|
roomUnit.setZ(z);
|
||||||
roomUnit.setPreviousLocationZ(z);
|
roomUnit.setPreviousLocationZ(z);
|
||||||
this.updateRoomUnit(roomUnit);
|
this.updateRoomUnit(roomUnit);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4953,6 +5054,7 @@ public class Room implements Comparable<Room>, ISerialize, Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public FurnitureMovementError slideFurniTo(HabboItem item, RoomTile tile, int rotation) {
|
public FurnitureMovementError slideFurniTo(HabboItem item, RoomTile tile, int rotation) {
|
||||||
|
|
||||||
RoomTile oldLocation = this.layout.getTile(item.getX(), item.getY());
|
RoomTile oldLocation = this.layout.getTile(item.getX(), item.getY());
|
||||||
|
|
||||||
HabboItem topItem = this.getTopItemAt(tile.x, tile.y);
|
HabboItem topItem = this.getTopItemAt(tile.x, tile.y);
|
||||||
@ -4976,6 +5078,7 @@ public class Room implements Comparable<Room>, ISerialize, Runnable {
|
|||||||
item.setRotation(rotation);
|
item.setRotation(rotation);
|
||||||
|
|
||||||
//Place at new position
|
//Place at new position
|
||||||
|
|
||||||
if (magicTile) {
|
if (magicTile) {
|
||||||
item.setZ(tile.z);
|
item.setZ(tile.z);
|
||||||
item.setExtradata("" + item.getZ() * 100);
|
item.setExtradata("" + item.getZ() * 100);
|
||||||
@ -5026,42 +5129,4 @@ public class Room implements Comparable<Room>, ISerialize, Runnable {
|
|||||||
THashSet<RoomUnit> roomUnits = getRoomUnits();
|
THashSet<RoomUnit> roomUnits = getRoomUnits();
|
||||||
return roomUnits.stream().filter(unit -> unit.getCurrentLocation() == tile).collect(Collectors.toSet());
|
return roomUnits.stream().filter(unit -> unit.getCurrentLocation() == tile).collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private static class LoopTracker {
|
|
||||||
double x, y, z;
|
|
||||||
int counter;
|
|
||||||
|
|
||||||
public LoopTracker(double x, double y, double z) {
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.z = z;
|
|
||||||
this.counter = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSamePosition(double newX, double newY, double newZ) {
|
|
||||||
// Use an epsilon for double comparison if necessary.
|
|
||||||
final double EPSILON = 0.001;
|
|
||||||
return Math.abs(newX - x) < EPSILON && Math.abs(newY - y) < EPSILON && Math.abs(newZ - z) < EPSILON;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void update(double newX, double newY, double newZ) {
|
|
||||||
this.x = newX;
|
|
||||||
this.y = newY;
|
|
||||||
this.z = newZ;
|
|
||||||
this.counter = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isOnRoller(RoomUnit unit) {
|
|
||||||
RoomTile currentTile = unit.getCurrentLocation();
|
|
||||||
// Iterate over all rollers in the room.
|
|
||||||
for (HabboItem roller : this.roomSpecialTypes.getRollers().values()) {
|
|
||||||
if (roller.getX() == currentTile.x && roller.getY() == currentTile.y) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Map<RoomUnit, LoopTracker> loopTrackers = new ConcurrentHashMap<>();
|
|
||||||
}
|
|
||||||
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user