diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/BedProfile.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/BedProfile.java new file mode 100644 index 00000000..1786979b --- /dev/null +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/BedProfile.java @@ -0,0 +1,138 @@ +package com.eu.habbo.habbohotel.rooms; + +import com.eu.habbo.habbohotel.users.HabboItem; + +/** + * Bed Profile Configuration + * ┌──────────────────────────────────────────────────────────────────────────┐ + * │ EDIT THESE VALUES TO ADJUST BED POSITIONING │ + * ├──────────────────┬──────────┬────────────┬────────────┬────────────────┤ + * │ Bed Type │ Width │ Lay X │ Lay Y │ Lay Z │ + * ├──────────────────┼──────────┼────────────┼────────────┼────────────────┤ + * │ Flat single │ single │ 0 │ 0 │ -0.5 │ + * │ Flat double │ double │ 0 │ 0 │ -0.5 │ + * │ Raised single │ single │ 0 │ 0 │ -0.5 │ + * │ Raised double │ double │ 0 │ 0 │ -0.5 │ + * └──────────────────┴──────────┴────────────┴────────────┴────────────────┘ + */ +public class BedProfile { + + // ===== HEIGHT THRESHOLD ===== + private static final double FLAT_BED_HEIGHT_THRESHOLD = 1.0; + + // ===== FLAT BED OFFSETS (sleeping bags, mats, etc.) ===== + private static final double FLAT_SINGLE_LAY_X_OFFSET = 0; + private static final double FLAT_SINGLE_LAY_Y_OFFSET = 15; + private static final double FLAT_SINGLE_LAY_Z_OFFSET = -0.5; + + private static final double FLAT_DOUBLE_LAY_X_OFFSET = 0; + private static final double FLAT_DOUBLE_LAY_Y_OFFSET = 0; + private static final double FLAT_DOUBLE_LAY_Z_OFFSET = -0.5; + + // ===== RAISED BED OFFSETS (normal beds with frames) ===== + private static final double RAISED_SINGLE_LAY_X_OFFSET = 5; + private static final double RAISED_SINGLE_LAY_Y_OFFSET = 0; + private static final double RAISED_SINGLE_LAY_Z_OFFSET = 0; + + private static final double RAISED_DOUBLE_LAY_X_OFFSET = 0; + private static final double RAISED_DOUBLE_LAY_Y_OFFSET = 0; + private static final double RAISED_DOUBLE_LAY_Z_OFFSET = -0; + + private final boolean isDouble; + private final boolean isFlat; + private final int rotation; + private final double layXOffset; + private final double layYOffset; + private final double layZOffset; + + public BedProfile(HabboItem bed) { + this.rotation = bed.getRotation(); + + this.isDouble = bed.getBaseItem().getWidth() >= 2; + this.isFlat = bed.getBaseItem().getHeight() < FLAT_BED_HEIGHT_THRESHOLD; + + if (this.isFlat) { + if (this.isDouble) { + this.layXOffset = FLAT_DOUBLE_LAY_X_OFFSET; + this.layYOffset = FLAT_DOUBLE_LAY_Y_OFFSET; + this.layZOffset = FLAT_DOUBLE_LAY_Z_OFFSET; + } else { + this.layXOffset = FLAT_SINGLE_LAY_X_OFFSET; + this.layYOffset = FLAT_SINGLE_LAY_Y_OFFSET; + this.layZOffset = FLAT_SINGLE_LAY_Z_OFFSET; + } + } else { + if (this.isDouble) { + this.layXOffset = RAISED_DOUBLE_LAY_X_OFFSET; + this.layYOffset = RAISED_DOUBLE_LAY_Y_OFFSET; + this.layZOffset = RAISED_DOUBLE_LAY_Z_OFFSET; + } else { + this.layXOffset = RAISED_SINGLE_LAY_X_OFFSET; + this.layYOffset = RAISED_SINGLE_LAY_Y_OFFSET; + this.layZOffset = RAISED_SINGLE_LAY_Z_OFFSET; + } + } + } + + public double getLayXOffset() { + return this.layXOffset; + } + + public double getLayYOffset() { + return this.layYOffset; + } + + public double getLayZOffset() { + return this.layZOffset; + } + + public boolean isDouble() { + return this.isDouble; + } + + public boolean isFlat() { + return this.isFlat; + } + + public boolean isLengthAlongY() { + return this.rotation == 0 || this.rotation == 4; + } + + public RoomTile getPillow(Room room, short clickX, short clickY, HabboItem bed) { + if (isLengthAlongY()) { + return room.getLayout().getTile(clickX, bed.getY()); + } else { + return room.getLayout().getTile(bed.getX(), clickY); + } + } + + public RoomTile snapToLay(Room room, HabboItem bed, short unitX, short unitY) { + if (isLengthAlongY()) { + return room.getLayout().getTile(unitX, bed.getY()); + } else { + return room.getLayout().getTile(bed.getX(), unitY); + } + } + + public RoomTile getOtherSide(Room room, HabboItem bed, RoomTile currentPillow) { + if (!this.isDouble) return null; + + short otherX = currentPillow.x; + short otherY = currentPillow.y; + + if (isLengthAlongY()) { + otherX = (short) (bed.getX() + (currentPillow.x == bed.getX() ? 1 : -1)); + } else { + otherY = (short) (bed.getY() + (currentPillow.y == bed.getY() ? 1 : -1)); + } + + RoomTile otherTile = room.getLayout().getTile(otherX, otherY); + if (otherTile == null) return null; + + HabboItem itemAtOther = room.getTopItemAt(otherX, otherY); + if (itemAtOther != null && itemAtOther.getId() == bed.getId()) { + return otherTile; + } + return null; + } +} diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/RoomCycleManager.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/RoomCycleManager.java index 281e24ad..49e1639a 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/RoomCycleManager.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/RoomCycleManager.java @@ -75,7 +75,6 @@ public class RoomCycleManager { boolean loaded = this.room.isLoaded(); this.room.tileCache.clear(); - this.room.getItemManager().tileCache.clear(); if (loaded) { processScheduledTasks(); @@ -471,14 +470,15 @@ public class RoomCycleManager { } } else { if (!unit.hasStatus(RoomUnitStatus.LAY)) { - unit.setStatus(RoomUnitStatus.LAY, Item.getCurrentHeight(topItem) * 1.0D + ""); + BedProfile bedProfile = new BedProfile(topItem); + double layHeight = Item.getCurrentHeight(topItem) * 1.0D + bedProfile.getLayZOffset(); + LOGGER.info("[BedProfile] item={} stackHeight={} isFlat={} isDouble={} X={} Y={} Z={}", + topItem.getBaseItem().getName(), topItem.getBaseItem().getHeight(), + bedProfile.isFlat(), bedProfile.isDouble(), + bedProfile.getLayXOffset(), bedProfile.getLayYOffset(), bedProfile.getLayZOffset()); + unit.setStatus(RoomUnitStatus.LAY, layHeight + ";" + bedProfile.getLayXOffset() + ";" + bedProfile.getLayYOffset()); unit.setRotation(RoomUserRotation.values()[topItem.getRotation() % 4]); - - if (topItem.getRotation() == 0 || topItem.getRotation() == 4) { - unit.setLocation(this.room.getLayout().getTile(unit.getX(), topItem.getY())); - } else { - unit.setLocation(this.room.getLayout().getTile(topItem.getX(), unit.getY())); - } + unit.setLocation(bedProfile.snapToLay(this.room, topItem, unit.getX(), unit.getY())); update = true; } } diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/RoomLayout.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/RoomLayout.java index f555eaa4..576ebf2e 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/RoomLayout.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/RoomLayout.java @@ -238,22 +238,6 @@ public class RoomLayout { return this.roomTiles[x][y].relativeHeight(); } - public double getFloorAltitude(int x, int y) { - short baseHeight = this.getHeightAtSquare(x, y); - int target = baseHeight + 1; - - for (int dy = -1; dy <= 1; dy++) { - for (int dx = -1; dx <= 1; dx++) { - if (dx == 0 && dy == 0) continue; - if (this.getHeightAtSquare(x + dx, y + dy) == target) { - return baseHeight + 0.5; - } - } - } - - return baseHeight; - } - public RoomTile getTile(short x, short y) { if (this.tileExists(x, y)) { return this.roomTiles[x][y]; diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/RoomUnitManager.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/RoomUnitManager.java index bfaa427a..260af739 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/RoomUnitManager.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/RoomUnitManager.java @@ -380,8 +380,9 @@ public class RoomUnitManager { habbo.getRoomUnit().setZ(topItem.getZ()); habbo.getRoomUnit().setPreviousLocationZ(topItem.getZ()); habbo.getRoomUnit().setRotation(RoomUserRotation.fromValue(topItem.getRotation() % 4)); - habbo.getRoomUnit().setStatus(RoomUnitStatus.LAY, - String.valueOf(Item.getCurrentHeight(topItem))); + BedProfile bedProfile = new BedProfile(topItem); + double layHeight = Item.getCurrentHeight(topItem) + bedProfile.getLayZOffset(); + habbo.getRoomUnit().setStatus(RoomUnitStatus.LAY, layHeight + ";" + bedProfile.getLayXOffset() + ";" + bedProfile.getLayYOffset()); } else { if (habbo.getRoomUnit().hasStatus(RoomUnitStatus.SIT)) { habbo.getRoomUnit().removeStatus(RoomUnitStatus.SIT); @@ -697,8 +698,9 @@ public class RoomUnitManager { } else if (topItem != null && topItem.getBaseItem().allowLay()) { bot.getRoomUnit().setZ(topItem.getZ()); bot.getRoomUnit().setPreviousLocationZ(topItem.getZ()); - bot.getRoomUnit().setStatus(RoomUnitStatus.LAY, - String.valueOf(Item.getCurrentHeight(topItem))); + BedProfile botBedProfile = new BedProfile(topItem); + double botLayHeight = Item.getCurrentHeight(topItem) + botBedProfile.getLayZOffset(); + bot.getRoomUnit().setStatus(RoomUnitStatus.LAY, botLayHeight + ";" + botBedProfile.getLayXOffset() + ";" + botBedProfile.getLayYOffset()); } else { if (bot.getRoomUnit().hasStatus(RoomUnitStatus.SIT)) { bot.getRoomUnit().removeStatus(RoomUnitStatus.SIT); diff --git a/Emulator/src/main/java/com/eu/habbo/messages/incoming/rooms/users/RoomUserWalkEvent.java b/Emulator/src/main/java/com/eu/habbo/messages/incoming/rooms/users/RoomUserWalkEvent.java index a83a418d..2b5d5a5e 100644 --- a/Emulator/src/main/java/com/eu/habbo/messages/incoming/rooms/users/RoomUserWalkEvent.java +++ b/Emulator/src/main/java/com/eu/habbo/messages/incoming/rooms/users/RoomUserWalkEvent.java @@ -6,6 +6,7 @@ import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomTile; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.rooms.RoomUnitStatus; +import com.eu.habbo.habbohotel.rooms.BedProfile; import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.users.HabboInfo; import com.eu.habbo.habbohotel.users.HabboItem; @@ -123,7 +124,13 @@ public class RoomUserWalkEvent extends MessageHandler { HabboItem bed = room.getTopItemAt(tile.x, tile.y); if (bed != null && bed.getBaseItem().allowLay()) { - RoomTile pillow = getPillow(room, x, y, bed); + BedProfile profile = new BedProfile(bed); + RoomTile pillow = profile.getPillow(room, x, y, bed); + + // If pillow position is occupied, try the other side (double beds only) + if (pillow != null && !room.canLayAt(pillow.x, pillow.y)) { + pillow = profile.getOtherSide(room, bed, pillow); + } if (pillow != null && room.canLayAt(pillow.x, pillow.y)) { roomUnit.setGoalLocation(pillow); @@ -133,21 +140,6 @@ public class RoomUserWalkEvent extends MessageHandler { return false; } - private static RoomTile getPillow(Room room, short x, short y, HabboItem bed) { - RoomTile pillow = room.getLayout().getTile(bed.getX(), bed.getY()); - switch (bed.getRotation()) { - case 0: - case 4: - pillow = room.getLayout().getTile(x, bed.getY()); - break; - case 2: - case 8: - pillow = room.getLayout().getTile(bed.getX(), y); - break; - } - return pillow; - } - private static void fireIdleEvent(Habbo habbo, RoomUnit roomUnit) { UserIdleEvent event = new UserIdleEvent(habbo, UserIdleEvent.IdleReason.WALKED, false); Emulator.getPluginManager().fireEvent(event);