From 55fc9e3672a4b78d1ce12dc96a99bfeeaecd93b2 Mon Sep 17 00:00:00 2001 From: duckietm Date: Wed, 14 Jan 2026 12:45:21 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=86=99=20Updated=20move=20furni=20for=20t?= =?UTF-8?q?he=20buildtool?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/eu/habbo/habbohotel/rooms/Room.java | 12 ++ .../habbohotel/rooms/RoomItemManager.java | 158 ++++++++++++++++++ .../messages/incoming/MessageHandler.java | 7 + .../rooms/items/RotateMoveItemEvent.java | 12 +- .../items/UpdateFurniturePositionEvent.java | 21 ++- 5 files changed, 196 insertions(+), 14 deletions(-) diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/Room.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/Room.java index 6c7c5a5a..e47431ed 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/Room.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/Room.java @@ -2434,6 +2434,18 @@ public class Room implements Comparable, ISerialize, Runnable { return this.itemManager.moveFurniTo(item, tile, rotation, actor, sendUpdates, checkForUnits); } + public FurnitureMovementError moveFurniTo(HabboItem item, RoomTile tile, int rotation, double z, Habbo actor) { + return this.itemManager.moveFurniTo(item, tile, rotation, z, actor, true, true); + } + + public FurnitureMovementError moveFurniTo(HabboItem item, RoomTile tile, int rotation, double z, Habbo actor, boolean sendUpdates) { + return this.itemManager.moveFurniTo(item, tile, rotation, z, actor, sendUpdates, true); + } + + public FurnitureMovementError moveFurniTo(HabboItem item, RoomTile tile, int rotation, double z, Habbo actor, boolean sendUpdates, boolean checkForUnits) { + return this.itemManager.moveFurniTo(item, tile, rotation, z, actor, sendUpdates, checkForUnits); + } + public FurnitureMovementError slideFurniTo(HabboItem item, RoomTile tile, int rotation) { return this.itemManager.slideFurniTo(item, tile, rotation); } diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/RoomItemManager.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/RoomItemManager.java index 5b83b94d..d6d36d6f 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/RoomItemManager.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/RoomItemManager.java @@ -1357,6 +1357,164 @@ public class RoomItemManager { return FurnitureMovementError.NONE; } + /** + * Moves furniture to a new position with an explicit Z height. + */ + public FurnitureMovementError moveFurniTo(HabboItem item, RoomTile tile, int rotation, double z, Habbo actor, boolean sendUpdates, boolean checkForUnits) { + if (item == null || tile == null) { + return FurnitureMovementError.INVALID_MOVE; + } + + RoomLayout layout = this.room.getLayout(); + RoomTile oldLocation = layout.getTile(item.getX(), item.getY()); + + boolean pluginHelper = false; + + if (Emulator.getPluginManager().isRegistered(FurnitureMovedEvent.class, true)) { + FurnitureMovedEvent event = Emulator.getPluginManager() + .fireEvent(new FurnitureMovedEvent(item, actor, oldLocation, tile)); + + if (event.isCancelled()) { + return FurnitureMovementError.CANCEL_PLUGIN_MOVE; + } + + pluginHelper = event.hasPluginHelper(); + } + + rotation %= 8; + + boolean magicTile = + item instanceof InteractionStackHelper || + item instanceof InteractionTileWalkMagic; + + THashSet occupiedTiles = layout.getTilesAt( + tile, + item.getBaseItem().getWidth(), + item.getBaseItem().getLength(), + rotation + ); + + THashSet oldOccupiedTiles = layout.getTilesAt( + layout.getTile(item.getX(), item.getY()), + item.getBaseItem().getWidth(), + item.getBaseItem().getLength(), + item.getRotation() + ); + + if (!pluginHelper) { + FurnitureMovementError fits = furnitureFitsAt(tile, item, rotation, checkForUnits); + if (fits != FurnitureMovementError.NONE) { + return fits; + } + } + + int oldRotation = item.getRotation(); + + if (oldRotation != rotation) { + item.setRotation(rotation); + + if (Emulator.getPluginManager().isRegistered(FurnitureRotatedEvent.class, true)) { + Event rotatedEvent = new FurnitureRotatedEvent(item, actor, oldRotation); + Emulator.getPluginManager().fireEvent(rotatedEvent); + + if (rotatedEvent.isCancelled()) { + item.setRotation(oldRotation); + return FurnitureMovementError.CANCEL_PLUGIN_ROTATE; + } + } + } + + // Height sanity checks + if (z > Room.MAXIMUM_FURNI_HEIGHT) { + return FurnitureMovementError.CANT_STACK; + } + + // Prevent furni going under the floor + if (z < layout.getHeightAtSquare(tile.x, tile.y)) { + return FurnitureMovementError.CANT_STACK; + } + + // Plugin height override (match your NEW behavior: base + updatedHeight) + if (Emulator.getPluginManager().isRegistered(FurnitureBuildheightEvent.class, true)) { + FurnitureBuildheightEvent event = Emulator.getPluginManager() + .fireEvent(new FurnitureBuildheightEvent(item, actor, 0.00, z)); + + if (event.hasChangedHeight()) { + z = layout.getHeightAtSquare(tile.x, tile.y) + event.getUpdatedHeight(); + } + } + + item.setX(tile.x); + item.setY(tile.y); + item.setZ(z); + + if (magicTile) { + item.setZ(tile.z); + item.setExtradata("" + (item.getZ() * 100)); + } + + if (item.getZ() > Room.MAXIMUM_FURNI_HEIGHT) { + item.setZ(Room.MAXIMUM_FURNI_HEIGHT); + } + + // Update wired spatial index + invalidate cache + if (oldLocation != null) { + if (item instanceof InteractionWiredTrigger) { + this.room.getRoomSpecialTypes().updateTriggerLocation((InteractionWiredTrigger) item, oldLocation.x, oldLocation.y); + WiredManager.invalidateRoom(this.room); + } else if (item instanceof InteractionWiredEffect) { + this.room.getRoomSpecialTypes().updateEffectLocation((InteractionWiredEffect) item, oldLocation.x, oldLocation.y); + WiredManager.invalidateRoom(this.room); + } else if (item instanceof InteractionWiredCondition) { + this.room.getRoomSpecialTypes().updateConditionLocation((InteractionWiredCondition) item, oldLocation.x, oldLocation.y); + WiredManager.invalidateRoom(this.room); + } else if (item instanceof InteractionWiredExtra) { + this.room.getRoomSpecialTypes().updateExtraLocation((InteractionWiredExtra) item, oldLocation.x, oldLocation.y); + WiredManager.invalidateRoom(this.room); + } + } + + // Update furniture + item.onMove(this.room, oldLocation, tile); + item.needsUpdate(true); + Emulator.getThreading().run(item); + + if (sendUpdates) { + this.room.sendComposer(new FloorItemUpdateComposer(item).compose()); + } + + // Update old & new tiles + occupiedTiles.removeAll(oldOccupiedTiles); + occupiedTiles.addAll(oldOccupiedTiles); + this.room.updateTiles(occupiedTiles); + + // Update Habbos/Bots + for (RoomTile t : occupiedTiles) { + this.room.updateHabbosAt(t.x, t.y, this.room.getHabbosAt(t.x, t.y)); + this.room.updateBotsAt(t.x, t.y); + } + + // Preserve your newer "place under" behavior if enabled + if (Emulator.getConfig().getBoolean("wired.place.under", false)) { + THashSet newOccupiedTiles = layout.getTilesAt( + tile, + item.getBaseItem().getWidth(), + item.getBaseItem().getLength(), + rotation + ); + + for (RoomTile t : newOccupiedTiles) { + for (Habbo h : this.room.getHabbosAt(t.x, t.y)) { + try { + item.onWalkOn(h.getRoomUnit(), this.room, null); + } catch (Exception ignored) { } + } + } + } + + return FurnitureMovementError.NONE; + } + /** * Moves furniture to a new position. */ diff --git a/Emulator/src/main/java/com/eu/habbo/messages/incoming/MessageHandler.java b/Emulator/src/main/java/com/eu/habbo/messages/incoming/MessageHandler.java index 38920afe..ccc214bd 100644 --- a/Emulator/src/main/java/com/eu/habbo/messages/incoming/MessageHandler.java +++ b/Emulator/src/main/java/com/eu/habbo/messages/incoming/MessageHandler.java @@ -1,6 +1,7 @@ package com.eu.habbo.messages.incoming; import com.eu.habbo.habbohotel.gameclients.GameClient; +import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.messages.ClientMessage; public abstract class MessageHandler { @@ -13,4 +14,10 @@ public abstract class MessageHandler { public int getRatelimit() { return 0; } + + protected final Room currentRoom() { + if (this.client == null || this.client.getHabbo() == null) return null; + if (this.client.getHabbo().getHabboInfo() == null) return null; + return this.client.getHabbo().getHabboInfo().getCurrentRoom(); + } } \ No newline at end of file diff --git a/Emulator/src/main/java/com/eu/habbo/messages/incoming/rooms/items/RotateMoveItemEvent.java b/Emulator/src/main/java/com/eu/habbo/messages/incoming/rooms/items/RotateMoveItemEvent.java index 22a6b1ec..812fb6b2 100644 --- a/Emulator/src/main/java/com/eu/habbo/messages/incoming/rooms/items/RotateMoveItemEvent.java +++ b/Emulator/src/main/java/com/eu/habbo/messages/incoming/rooms/items/RotateMoveItemEvent.java @@ -12,10 +12,8 @@ import com.eu.habbo.messages.outgoing.rooms.items.FloorItemUpdateComposer; public class RotateMoveItemEvent extends MessageHandler { @Override public void handle() throws Exception { - Room room = this.client.getHabbo().getHabboInfo().getCurrentRoom(); - - if (room == null) - return; + Room room = currentRoom(); + if (room == null) return; int furniId = this.packet.readInt(); HabboItem item = room.getHabboItem(furniId); @@ -24,17 +22,19 @@ public class RotateMoveItemEvent extends MessageHandler { int x = this.packet.readInt(); int y = this.packet.readInt(); int rotation = this.packet.readInt(); + RoomTile tile = room.getLayout().getTile((short) x, (short) y); + if (tile == null) return; FurnitureMovementError error = room.canPlaceFurnitureAt(item, this.client.getHabbo(), tile, rotation); - if (!error.equals(FurnitureMovementError.NONE)) { + if (error != FurnitureMovementError.NONE) { this.client.sendResponse(new BubbleAlertComposer(BubbleAlertKeys.FURNITURE_PLACEMENT_ERROR.key, error.errorCode)); this.client.sendResponse(new FloorItemUpdateComposer(item)); return; } error = room.moveFurniTo(item, tile, rotation, this.client.getHabbo()); - if (!error.equals(FurnitureMovementError.NONE)) { + if (error != FurnitureMovementError.NONE) { this.client.sendResponse(new BubbleAlertComposer(BubbleAlertKeys.FURNITURE_PLACEMENT_ERROR.key, error.errorCode)); this.client.sendResponse(new FloorItemUpdateComposer(item)); } diff --git a/Emulator/src/main/java/com/eu/habbo/messages/incoming/rooms/items/UpdateFurniturePositionEvent.java b/Emulator/src/main/java/com/eu/habbo/messages/incoming/rooms/items/UpdateFurniturePositionEvent.java index abc30221..2a29f28e 100644 --- a/Emulator/src/main/java/com/eu/habbo/messages/incoming/rooms/items/UpdateFurniturePositionEvent.java +++ b/Emulator/src/main/java/com/eu/habbo/messages/incoming/rooms/items/UpdateFurniturePositionEvent.java @@ -1,16 +1,15 @@ package com.eu.habbo.messages.incoming.rooms.items; +import com.eu.habbo.habbohotel.rooms.FurnitureMovementError; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomTile; import com.eu.habbo.habbohotel.users.HabboItem; import com.eu.habbo.messages.incoming.MessageHandler; -import com.eu.habbo.messages.outgoing.rooms.items.FloorItemUpdateComposer; public class UpdateFurniturePositionEvent extends MessageHandler { @Override public void handle() throws Exception { - Room room = this.client.getHabbo().getHabboInfo().getCurrentRoom(); - + Room room = currentRoom(); if (room == null) return; int furniId = this.packet.readInt(); @@ -19,11 +18,17 @@ public class UpdateFurniturePositionEvent extends MessageHandler { int x = this.packet.readInt(); int y = this.packet.readInt(); - double z = (double) this.packet.readInt() / 10000; + double z = this.packet.readInt() / 10000.0; int rotation = this.packet.readInt(); - RoomTile tile = room.getLayout().getTile((short) x, (short) y); - room.moveFurniTo(item, tile, rotation, this.client.getHabbo(), true, true); - this.client.sendResponse(new FloorItemUpdateComposer(item)); + RoomTile tile = room.getLayout().getTile((short) x, (short) y); + if (tile == null) return; + + FurnitureMovementError result = + room.moveFurniTo(item, tile, rotation, z, this.client.getHabbo(), true, true); + + if (result != FurnitureMovementError.NONE) { + return; + } } -} \ No newline at end of file +}