diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/games/GamePlayer.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/games/GamePlayer.java index 608bb448..a76f01dd 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/games/GamePlayer.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/games/GamePlayer.java @@ -40,7 +40,7 @@ public class GamePlayer { this.wiredScore += amount; } - WiredManager.triggerScoreAchieved(this.habbo.getHabboInfo().getCurrentRoom(), this.habbo.getRoomUnit(), this.score); + WiredManager.triggerScoreAchieved(this.habbo.getHabboInfo().getCurrentRoom(), this.habbo.getRoomUnit(), this.score, amount); } } diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionDice.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionDice.java index c127a85f..aa938ee0 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionDice.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionDice.java @@ -48,7 +48,7 @@ public class InteractionDice extends HabboItem { if (client != null) { if (RoomLayout.tilesAdjecent(room.getLayout().getTile(this.getX(), this.getY()), client.getHabbo().getRoomUnit().getCurrentLocation())) { if (!this.getExtradata().equalsIgnoreCase("-1")) { - FurnitureDiceRolledEvent event = Emulator.getPluginManager().fireEvent(new FurnitureDiceRolledEvent(this, client.getHabbo(), -1)); + FurnitureDiceRolledEvent event = (FurnitureDiceRolledEvent) Emulator.getPluginManager().fireEvent(new FurnitureDiceRolledEvent(this, client.getHabbo(), -1)); if (event.isCancelled()) return; @@ -58,9 +58,9 @@ public class InteractionDice extends HabboItem { Emulator.getThreading().run(this); if (event.result > 0) { - Emulator.getThreading().run(new RandomDiceNumber(room, this, event.result), 2000); + Emulator.getThreading().run(new RandomDiceNumber(room, this, event.result), 1500); } else { - Emulator.getThreading().run(new RandomDiceNumber(this, room, this.getBaseItem().getStateCount()), 2000); + Emulator.getThreading().run(new RandomDiceNumber(this, room, this.getBaseItem().getStateCount()), 1500); } } } diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionFXBox.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionFXBox.java index e7f4f94b..1da31022 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionFXBox.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionFXBox.java @@ -15,12 +15,12 @@ import java.sql.SQLException; public class InteractionFXBox extends InteractionDefault { public InteractionFXBox(ResultSet set, Item baseItem) throws SQLException { super(set, baseItem); - // this.setExtradata("0"); + // this.setExtradata("0"); } public InteractionFXBox(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) { super(id, userId, item, extradata, limitedStack, limitedSells); - // this.setExtradata("0"); + // this.setExtradata("0"); } @Override diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionObstacle.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionObstacle.java index a63dcad8..a6c139af 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionObstacle.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionObstacle.java @@ -1,14 +1,18 @@ package com.eu.habbo.habbohotel.items.interactions; +import com.eu.habbo.Emulator; +import com.eu.habbo.habbohotel.achievements.AchievementManager; import com.eu.habbo.habbohotel.gameclients.GameClient; import com.eu.habbo.habbohotel.items.ICycleable; import com.eu.habbo.habbohotel.items.Item; import com.eu.habbo.habbohotel.pets.HorsePet; import com.eu.habbo.habbohotel.pets.Pet; +import com.eu.habbo.habbohotel.pets.PetTasks; import com.eu.habbo.habbohotel.rooms.*; import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.users.HabboItem; import com.eu.habbo.messages.ServerMessage; +import com.eu.habbo.threading.runnables.HabboItemNewState; import gnu.trove.set.hash.THashSet; import java.sql.ResultSet; @@ -56,9 +60,10 @@ public class InteractionObstacle extends HabboItem implements ICycleable { @Override public void onWalk(RoomUnit roomUnit, Room room, Object[] objects) throws Exception { - /*Pet pet = room.getPet(roomUnit); + Pet pet = room.getPet(roomUnit); if (pet instanceof HorsePet && ((HorsePet) pet).getRider() != null) { + Habbo rider = ((HorsePet) pet).getRider(); if (pet.getTask() != null && pet.getTask().equals(PetTasks.RIDE)) { if (pet.getRoomUnit().hasStatus(RoomUnitStatus.JUMP)) { pet.getRoomUnit().removeStatus(RoomUnitStatus.JUMP); @@ -75,13 +80,13 @@ public class InteractionObstacle extends HabboItem implements ICycleable { this.setExtradata(state + ""); pet.getRoomUnit().setStatus(RoomUnitStatus.JUMP, "0"); - AchievementManager.progressAchievement(habbo, Emulator.getGameEnvironment().getAchievementManager().getAchievement("HorseConsecutiveJumpsCount")); - AchievementManager.progressAchievement(habbo, Emulator.getGameEnvironment().getAchievementManager().getAchievement("HorseJumping")); + AchievementManager.progressAchievement(rider, Emulator.getGameEnvironment().getAchievementManager().getAchievement("HorseConsecutiveJumpsCount")); + AchievementManager.progressAchievement(rider, Emulator.getGameEnvironment().getAchievementManager().getAchievement("HorseJumping")); } room.updateItemState(this); } - }*/ + } } @Override diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionVendingMachine.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionVendingMachine.java index cbe4e8c2..efb8fbf3 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionVendingMachine.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionVendingMachine.java @@ -27,7 +27,7 @@ public class InteractionVendingMachine extends HabboItem { super(id, userId, item, extradata, limitedStack, limitedSells); this.setExtradata("0"); } - + public THashSet getActivatorTiles(Room room) { THashSet tiles = new THashSet<>(); RoomTile tileInFront = getSquareInFront(room.getLayout(), this); diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/pets/InteractionPetBreedingNest.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/pets/InteractionPetBreedingNest.java index 9ec50ff9..ee598d8d 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/pets/InteractionPetBreedingNest.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/pets/InteractionPetBreedingNest.java @@ -6,6 +6,7 @@ import com.eu.habbo.habbohotel.items.Item; import com.eu.habbo.habbohotel.pets.Pet; import com.eu.habbo.habbohotel.pets.PetManager; import com.eu.habbo.habbohotel.pets.PetTasks; +import com.eu.habbo.habbohotel.pets.RideablePet; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.users.Habbo; @@ -33,7 +34,11 @@ public class InteractionPetBreedingNest extends HabboItem { @Override public boolean canWalkOn(RoomUnit roomUnit, Room room, Object[] objects) { - return room.getPet(roomUnit) != null && !this.boxFull(); + Pet pet = room.getPet(roomUnit); + if (pet == null) return false; + // Don't let ridden pets enter breeding nest + if (pet instanceof RideablePet && ((RideablePet) pet).getRider() != null) return false; + return !this.boxFull(); } @Override diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/pets/InteractionPetDrink.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/pets/InteractionPetDrink.java index a18ada6b..178e73e5 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/pets/InteractionPetDrink.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/pets/InteractionPetDrink.java @@ -6,6 +6,7 @@ import com.eu.habbo.habbohotel.items.Item; import com.eu.habbo.habbohotel.items.interactions.InteractionDefault; import com.eu.habbo.habbohotel.pets.Pet; import com.eu.habbo.habbohotel.pets.PetTasks; +import com.eu.habbo.habbohotel.pets.RideablePet; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.rooms.RoomUnitStatus; @@ -32,6 +33,10 @@ public class InteractionPetDrink extends InteractionDefault { Pet pet = room.getPet(roomUnit); if (pet != null) { + // Don't let ridden pets drink + if (pet instanceof RideablePet && ((RideablePet) pet).getRider() != null) + return; + if (pet.getPetData().haveDrinkItem(this)) { if (pet.levelThirst >= 35) { pet.setTask(PetTasks.EAT); diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/pets/InteractionPetFood.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/pets/InteractionPetFood.java index 8f2dd02c..aec5233f 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/pets/InteractionPetFood.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/pets/InteractionPetFood.java @@ -5,6 +5,7 @@ import com.eu.habbo.habbohotel.items.Item; import com.eu.habbo.habbohotel.items.interactions.InteractionDefault; import com.eu.habbo.habbohotel.pets.Pet; import com.eu.habbo.habbohotel.pets.PetTasks; +import com.eu.habbo.habbohotel.pets.RideablePet; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.rooms.RoomUnitStatus; @@ -34,6 +35,10 @@ public class InteractionPetFood extends InteractionDefault { Pet pet = room.getPet(roomUnit); if (pet != null) { + // Don't let ridden pets eat + if (pet instanceof RideablePet && ((RideablePet) pet).getRider() != null) + return; + if (pet.getPetData().haveFoodItem(this)) { if (pet.levelHunger >= 35) { pet.setTask(PetTasks.EAT); diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/pets/InteractionPetToy.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/pets/InteractionPetToy.java index 9c21cbe0..ef0a829f 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/pets/InteractionPetToy.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/pets/InteractionPetToy.java @@ -5,6 +5,7 @@ import com.eu.habbo.habbohotel.items.Item; import com.eu.habbo.habbohotel.items.interactions.InteractionDefault; import com.eu.habbo.habbohotel.pets.Pet; import com.eu.habbo.habbohotel.pets.PetTasks; +import com.eu.habbo.habbohotel.pets.RideablePet; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.rooms.RoomUnitStatus; @@ -33,6 +34,10 @@ public class InteractionPetToy extends InteractionDefault { Pet pet = room.getPet(roomUnit); if (pet != null) { + // Don't let ridden pets play with toys + if (pet instanceof RideablePet && ((RideablePet) pet).getRider() != null) + return; + if (pet.getEnergy() <= 35) { return; } diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectTeleport.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectTeleport.java index 7e1ba81d..eef82e51 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectTeleport.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectTeleport.java @@ -6,10 +6,14 @@ import com.eu.habbo.habbohotel.items.Item; import com.eu.habbo.habbohotel.items.interactions.InteractionWiredEffect; import com.eu.habbo.habbohotel.items.interactions.InteractionWiredTrigger; import com.eu.habbo.habbohotel.items.interactions.wired.WiredSettings; +import com.eu.habbo.habbohotel.pets.RideablePet; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomTile; import com.eu.habbo.habbohotel.rooms.RoomTileState; import com.eu.habbo.habbohotel.rooms.RoomUnit; +import com.eu.habbo.habbohotel.rooms.RoomUnitStatus; +import com.eu.habbo.habbohotel.rooms.RoomUnitType; +import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.wired.core.WiredContext; import com.eu.habbo.habbohotel.users.HabboItem; import com.eu.habbo.habbohotel.wired.WiredEffectType; @@ -17,6 +21,7 @@ import com.eu.habbo.habbohotel.wired.core.WiredManager; import com.eu.habbo.messages.ServerMessage; import com.eu.habbo.messages.incoming.wired.WiredSaveException; import com.eu.habbo.messages.outgoing.rooms.users.RoomUserEffectComposer; +import com.eu.habbo.messages.outgoing.rooms.users.RoomUserStatusComposer; import com.eu.habbo.threading.runnables.RoomUnitTeleport; import com.eu.habbo.threading.runnables.SendRoomUnitEffectComposer; import gnu.trove.procedure.TObjectProcedure; @@ -54,6 +59,27 @@ public class WiredEffectTeleport extends InteractionWiredEffect { return; } + // If this is a rider, sync the riding pet to the rider's current position immediately + // Both will teleport together when the delay fires + if (roomUnit.getRoomUnitType() == RoomUnitType.USER) { + Habbo habbo = room.getHabbo(roomUnit); + if (habbo != null && habbo.getHabboInfo() != null && habbo.getHabboInfo().getRiding() != null) { + RideablePet ridingPet = habbo.getHabboInfo().getRiding(); + RoomUnit petUnit = ridingPet.getRoomUnit(); + if (petUnit != null) { + // Sync pet to rider's current position + RoomTile riderTile = roomUnit.getCurrentLocation(); + petUnit.setLocation(riderTile); + petUnit.setZ(roomUnit.getZ() - 1.0); + petUnit.setPreviousLocation(riderTile); + petUnit.setGoalLocation(riderTile); + petUnit.removeStatus(RoomUnitStatus.MOVE); + petUnit.setCanWalk(false); + room.sendComposer(new RoomUserStatusComposer(petUnit).compose()); + } + } + } + // makes a temporary effect roomUnit.getRoom().unIdle(roomUnit.getRoom().getHabbo(roomUnit)); diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectTriggerStacks.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectTriggerStacks.java index 3a14c42c..d5dec492 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectTriggerStacks.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectTriggerStacks.java @@ -126,25 +126,12 @@ public class WiredEffectTriggerStacks extends InteractionWiredEffect { public void execute(WiredContext ctx) { Room room = ctx.room(); RoomUnit roomUnit = ctx.actor().orElse(null); - Object[] stuff = ctx.legacyStuff(); - // Prevent infinite recursion by checking for WiredEffectTriggerStacks in the call chain - // and limiting the recursion depth - int stackDepth = 0; - if (stuff != null) { - for (Object obj : stuff) { - if (obj instanceof WiredEffectTriggerStacks) { - stackDepth++; - // If this specific stack is already in the chain, prevent infinite loop - if (obj == this) { - return; - } - } - } - } + // Get the current call stack depth from the event + int currentDepth = ctx.event().getCallStackDepth(); // Prevent excessive recursion depth - if (stackDepth >= MAX_STACK_DEPTH) { + if (currentDepth >= MAX_STACK_DEPTH) { return; } @@ -169,17 +156,8 @@ public class WiredEffectTriggerStacks extends InteractionWiredEffect { } } - // Create new stuff array with this trigger stack added for recursion tracking - Object[] newStuff; - if (stuff != null) { - newStuff = new Object[stuff.length + 1]; - System.arraycopy(stuff, 0, newStuff, 0, stuff.length); - newStuff[newStuff.length - 1] = this; - } else { - newStuff = new Object[] { this }; - } - - WiredManager.executeEffectsAtTiles(usedTiles, roomUnit, room, newStuff); + // Execute effects at tiles with incremented call stack depth + WiredManager.executeEffectsAtTiles(usedTiles, roomUnit, room, currentDepth + 1); } @Deprecated diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerBotReachedFurni.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerBotReachedFurni.java index 462d4b0e..f42bba2b 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerBotReachedFurni.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerBotReachedFurni.java @@ -120,14 +120,16 @@ public class WiredTriggerBotReachedFurni extends InteractionWiredTrigger { public boolean matches(HabboItem triggerItem, WiredEvent event) { RoomUnit roomUnit = event.getActor().orElse(null); Room room = event.getRoom(); - Object[] stuff = event.getLegacyStuff(); - if (stuff.length >= 1) { - if (stuff[0] instanceof HabboItem) { - return this.items.contains(stuff[0]) && room.getBots(this.botName).stream().anyMatch(bot -> bot.getRoomUnit() == roomUnit); - } + // Get the furniture item the bot walked onto + HabboItem sourceItem = event.getSourceItem().orElse(null); + if (sourceItem == null || roomUnit == null) { + return false; } - return false; + + // Check if this furniture is in our monitored list AND the actor is the correct bot + return this.items.contains(sourceItem) && + room.getBots(this.botName).stream().anyMatch(bot -> bot.getRoomUnit() == roomUnit); } @Deprecated diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerFurniStateToggled.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerFurniStateToggled.java index 5db6591a..4f4a82f4 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerFurniStateToggled.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerFurniStateToggled.java @@ -6,9 +6,7 @@ import com.eu.habbo.habbohotel.items.interactions.InteractionWiredTrigger; import com.eu.habbo.habbohotel.items.interactions.wired.WiredSettings; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; -import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.users.HabboItem; -import com.eu.habbo.habbohotel.wired.WiredEffectType; import com.eu.habbo.habbohotel.wired.core.WiredManager; import com.eu.habbo.habbohotel.wired.WiredTriggerType; import com.eu.habbo.habbohotel.wired.core.WiredEvent; @@ -37,25 +35,14 @@ public class WiredTriggerFurniStateToggled extends InteractionWiredTrigger { @Override public boolean matches(HabboItem triggerItem, WiredEvent event) { - RoomUnit roomUnit = event.getActor().orElse(null); - Room room = event.getRoom(); - Object[] stuff = event.getLegacyStuff(); + // Reject if this was triggered by a wired effect (to prevent loops) + if (event.isTriggeredByEffect()) { + return false; + } - if (stuff.length >= 1) { - Habbo habbo = room.getHabbo(roomUnit); - - if (habbo != null) { - for (Object object : stuff) { - if (object instanceof WiredEffectType) { - return false; - } - } - - HabboItem sourceItem = event.getSourceItem().orElse(null); - if (sourceItem != null) { - return this.items.contains(sourceItem); - } - } + HabboItem sourceItem = event.getSourceItem().orElse(null); + if (sourceItem != null) { + return this.items.contains(sourceItem); } return false; } diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerScoreAchieved.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerScoreAchieved.java index fb3f1be0..179e9597 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerScoreAchieved.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerScoreAchieved.java @@ -28,15 +28,11 @@ public class WiredTriggerScoreAchieved extends InteractionWiredTrigger { @Override public boolean matches(HabboItem triggerItem, WiredEvent event) { - Object[] stuff = event.getLegacyStuff(); - if (stuff.length >= 2) { - int points = (Integer) stuff[0]; - int amountAdded = (Integer) stuff[1]; + int points = event.getScore(); + int amountAdded = event.getScoreAdded(); - return points - amountAdded < this.score && points >= this.score; - } - - return false; + // Check if this score addition crossed the threshold + return points - amountAdded < this.score && points >= this.score; } @Deprecated 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 aa485c59..ab734e44 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 @@ -556,6 +556,10 @@ public class Room implements Comparable, ISerialize, Runnable { this.cycleManager.resetIdleCycles(); + if (this.roomCycleTask != null) { + this.roomCycleTask.cancel(false); + } + this.roomCycleTask = Emulator.getThreading().getService() .scheduleAtFixedRate(this, 500, 500, TimeUnit.MILLISECONDS); } catch (Exception e) { @@ -868,16 +872,20 @@ public class Room implements Comparable, ISerialize, Runnable { } if (this.loaded) { - try { + // Set loaded to false FIRST to prevent re-entry and ensure cycle stops + this.loaded = false; + try { if (this.traxManager != null && !this.traxManager.disposed()) { this.traxManager.dispose(); } - this.roomCycleTask.cancel(false); + if (this.roomCycleTask != null) { + this.roomCycleTask.cancel(false); + this.roomCycleTask = null; + } this.scheduledTasks.clear(); this.scheduledComposers.clear(); - this.loaded = false; this.tileCache.clear(); @@ -901,10 +909,10 @@ public class Room implements Comparable, ISerialize, Runnable { if (this.roomSpecialTypes != null) { this.roomSpecialTypes.dispose(); } - + // Unregister all wired tickables for this room from the tick service com.eu.habbo.habbohotel.wired.core.WiredManager.unregisterRoomTickables(this); - + // Clear wired engine caches for this room if (com.eu.habbo.habbohotel.wired.core.WiredManager.getStackIndex() != null) { com.eu.habbo.habbohotel.wired.core.WiredManager.getStackIndex().invalidateAll(this); diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/RoomRollerManager.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/RoomRollerManager.java index 9306333c..df76d3a6 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/RoomRollerManager.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/RoomRollerManager.java @@ -279,14 +279,23 @@ public class RoomRollerManager { Habbo rollingHabbo = this.room.getHabbo(unit); if (rollingHabbo != null && rollingHabbo.getHabboInfo() != null) { RideablePet riding = rollingHabbo.getHabboInfo().getRiding(); - if (riding != null) { + if (riding != null && riding.getRoomUnit() != null) { RoomUnit ridingUnit = riding.getRoomUnit(); - newZ = ridingUnit.getZ() + zOffset; + double petOldZ = ridingUnit.getZ(); + double petNewZ = tileInFront.getStackHeight(); + + // Update pet position immediately before composing messages to prevent desync rolledUnitIds.add(ridingUnit.getId()); updatedUnit.remove(ridingUnit); - messages.add(new RoomUnitOnRollerComposer(ridingUnit, roller, - ridingUnit.getCurrentLocation(), ridingUnit.getZ(), tileInFront, newZ, - this.room)); + + // Compose and send pet roller message first + RoomUnitOnRollerComposer petRollerComposer = new RoomUnitOnRollerComposer( + ridingUnit, roller, ridingUnit.getCurrentLocation(), petOldZ, + tileInFront, petNewZ, this.room); + messages.add(petRollerComposer); + + // Update newZ for the rider (1 unit above pet) + newZ = petNewZ + 1.0; isRiding = true; } } @@ -295,9 +304,12 @@ public class RoomRollerManager { usersRolledThisTile.add(unit.getId()); rolledUnitIds.add(unit.getId()); updatedUnit.remove(unit); + + // For riding users, use pet-relative Z values + double riderOldZ = isRiding ? unit.getZ() : unit.getZ(); + double riderNewZ = isRiding ? newZ : (unit.getZ() + zOffset); messages.add(new RoomUnitOnRollerComposer(unit, roller, unit.getCurrentLocation(), - unit.getZ() + (isRiding ? 1 : 0), tileInFront, newZ + (isRiding ? 1 : 0), - this.room)); + riderOldZ, tileInFront, riderNewZ, this.room)); if (itemsOnRoller.isEmpty()) { HabboItem item = this.room.getTopItemAt(tileInFront.x, tileInFront.y); diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/RoomUnit.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/RoomUnit.java index a58debc5..2f88edb7 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/RoomUnit.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/RoomUnit.java @@ -23,18 +23,13 @@ import com.eu.habbo.util.pathfinding.Rotation; import gnu.trove.map.TMap; import gnu.trove.map.hash.THashMap; import gnu.trove.set.hash.THashSet; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.Deque; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ScheduledFuture; import java.util.stream.Collectors; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; public class RoomUnit { @@ -155,9 +150,11 @@ public class RoomUnit { if (!this.isWalking() && !this.isKicked) { if (this.status.remove(RoomUnitStatus.MOVE) == null) { Habbo habboT = room.getHabbo(this); - if (habboT != null) { - habboT.getHabboInfo().getRiding().getRoomUnit().status.remove(RoomUnitStatus.MOVE); - + if (habboT != null && habboT.getHabboInfo() != null && habboT.getHabboInfo().getRiding() != null) { + RoomUnit ridingRoomUnit = habboT.getHabboInfo().getRiding().getRoomUnit(); + if (ridingRoomUnit != null) { + ridingRoomUnit.status.remove(RoomUnitStatus.MOVE); + } } return true; } diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/users/HabboInfo.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/users/HabboInfo.java index bee2dfca..c0524b9e 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/users/HabboInfo.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/users/HabboInfo.java @@ -480,6 +480,10 @@ public class HabboInfo implements Runnable { roomUnit.setZ(riding.getRoomUnit().getZ()); roomUnit.setPreviousLocationZ(riding.getRoomUnit().getZ()); roomUnit.stopWalking(); + if (riding.getRoomUnit() != null) { + riding.getRoomUnit().setCanWalk(true); + room.sendComposer(new RoomUserStatusComposer(riding.getRoomUnit()).compose()); + } room.sendComposer(new RoomUserStatusComposer(roomUnit).compose()); List availableTiles = isRemoving ? new ArrayList<>() : this.getCurrentRoom().getLayout().getWalkableTilesAround(roomUnit.getCurrentLocation()); diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/core/WiredContext.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/core/WiredContext.java index 4a84cb01..142528e7 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/core/WiredContext.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/core/WiredContext.java @@ -256,14 +256,6 @@ public final class WiredContext { return legacySettings != null ? legacySettings : new Object[0]; } - /** - * Get the legacy stuff array from the event. - * @return the legacy stuff array - */ - public Object[] legacyStuff() { - return event.getLegacyStuff(); - } - // ========== Utility Methods ========== /** diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/core/WiredEvent.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/core/WiredEvent.java index 56a92cda..8ddc2215 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/core/WiredEvent.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/core/WiredEvent.java @@ -128,11 +128,15 @@ public final class WiredEvent { private final Type type; private final Room room; - private final RoomUnit actor; // nullable - private final HabboItem sourceItem; // nullable - private final RoomTile tile; // nullable - private final String text; // nullable - private final Object[] legacyStuff; // for adapter compatibility + private final RoomUnit actor; // nullable - the user/bot that caused the event + private final HabboItem sourceItem; // nullable - the furniture involved + private final RoomTile tile; // nullable - the tile where event occurred + private final String text; // nullable - text for say triggers + private final RoomUnit targetUnit; // nullable - target user (e.g., for bot reached habbo) + private final int score; // score value for score achieved events + private final int scoreAdded; // amount added for score achieved events + private final boolean triggeredByEffect; // true if triggered by a wired effect (to prevent loops) + private final int callStackDepth; // recursion depth for trigger stacks effect private final long createdAtMs; private WiredEvent(Builder builder) { @@ -142,7 +146,11 @@ public final class WiredEvent { this.sourceItem = builder.sourceItem; this.tile = builder.tile; this.text = builder.text; - this.legacyStuff = builder.legacyStuff; + this.targetUnit = builder.targetUnit; + this.score = builder.score; + this.scoreAdded = builder.scoreAdded; + this.triggeredByEffect = builder.triggeredByEffect; + this.callStackDepth = builder.callStackDepth; this.createdAtMs = builder.createdAtMs; } @@ -199,12 +207,46 @@ public final class WiredEvent { } /** - * Get the legacy stuff array for adapter compatibility. - * This allows legacy triggers/conditions/effects to work with the new system. - * @return the legacy stuff array, or empty array if not set + * Get the target unit for this event. + * Used for events like BOT_REACHED_HABBO where we need to track the target user. + * @return optional containing the target unit */ - public Object[] getLegacyStuff() { - return legacyStuff != null ? legacyStuff : new Object[0]; + public Optional getTargetUnit() { + return Optional.ofNullable(targetUnit); + } + + /** + * Get the score value for score achieved events. + * @return the current score + */ + public int getScore() { + return score; + } + + /** + * Get the amount of score added for score achieved events. + * @return the amount added + */ + public int getScoreAdded() { + return scoreAdded; + } + + /** + * Check if this event was triggered by a wired effect. + * Used to prevent infinite loops (e.g., effect toggles furni -> triggers state changed -> triggers effect). + * @return true if triggered by a wired effect + */ + public boolean isTriggeredByEffect() { + return triggeredByEffect; + } + + /** + * Get the call stack depth for recursion tracking. + * Used by WiredEffectTriggerStacks to prevent infinite recursion. + * @return the current recursion depth + */ + public int getCallStackDepth() { + return callStackDepth; } /** @@ -256,7 +298,11 @@ public final class WiredEvent { private HabboItem sourceItem; private RoomTile tile; private String text; - private Object[] legacyStuff; + private RoomUnit targetUnit; + private int score; + private int scoreAdded; + private boolean triggeredByEffect; + private int callStackDepth; private long createdAtMs = System.currentTimeMillis(); private Builder(Type type, Room room) { @@ -307,12 +353,52 @@ public final class WiredEvent { } /** - * Set the legacy stuff array for adapter compatibility. - * @param stuff the legacy object array + * Set the target unit for this event. + * @param targetUnit the target room unit * @return this builder */ - public Builder legacyStuff(Object[] stuff) { - this.legacyStuff = stuff; + public Builder targetUnit(RoomUnit targetUnit) { + this.targetUnit = targetUnit; + return this; + } + + /** + * Set the score value for score achieved events. + * @param score the current score + * @return this builder + */ + public Builder score(int score) { + this.score = score; + return this; + } + + /** + * Set the amount of score added for score achieved events. + * @param scoreAdded the amount added + * @return this builder + */ + public Builder scoreAdded(int scoreAdded) { + this.scoreAdded = scoreAdded; + return this; + } + + /** + * Mark this event as triggered by a wired effect. + * @param triggeredByEffect true if triggered by effect + * @return this builder + */ + public Builder triggeredByEffect(boolean triggeredByEffect) { + this.triggeredByEffect = triggeredByEffect; + return this; + } + + /** + * Set the call stack depth for recursion tracking. + * @param callStackDepth the recursion depth + * @return this builder + */ + public Builder callStackDepth(int callStackDepth) { + this.callStackDepth = callStackDepth; return this; } diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/core/WiredManager.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/core/WiredManager.java index b73680a7..e31b948c 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/core/WiredManager.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/core/WiredManager.java @@ -357,13 +357,17 @@ public final class WiredManager { /** * Trigger when score is achieved. + * @param room the room + * @param user the user who scored + * @param score the current total score + * @param scoreAdded the amount of score just added */ - public static boolean triggerScoreAchieved(Room room, RoomUnit user, int score) { + public static boolean triggerScoreAchieved(Room room, RoomUnit user, int score, int scoreAdded) { if (!isEnabled() || room == null || user == null) { return false; } - WiredEvent event = WiredEvents.scoreAchieved(room, user, score); + WiredEvent event = WiredEvents.scoreAchieved(room, user, score, scoreAdded); return handleEvent(event); } @@ -631,7 +635,15 @@ public final class WiredManager { // ========== Effect Execution ========== - public static boolean executeEffectsAtTiles(THashSet tiles, final RoomUnit roomUnit, final Room room, final Object[] stuff) { + /** + * Execute all wired effects at the specified tiles. + * @param tiles the tiles to execute effects at + * @param roomUnit the triggering room unit (may be null) + * @param room the room + * @param callStackDepth current recursion depth for trigger stacks + * @return true if any effects were executed + */ + public static boolean executeEffectsAtTiles(THashSet tiles, final RoomUnit roomUnit, final Room room, final int callStackDepth) { for (RoomTile tile : tiles) { if (room != null) { THashSet items = room.getItemsAt(tile); @@ -642,7 +654,7 @@ public final class WiredManager { InteractionWiredEffect effect = (InteractionWiredEffect) item; WiredEvent event = WiredEvent.builder(WiredEvent.Type.CUSTOM, room) .actor(roomUnit) - .legacyStuff(stuff) + .callStackDepth(callStackDepth) .build(); WiredContext ctx = new WiredContext(event, effect, DefaultWiredServices.getInstance(), new WiredState(100)); effect.execute(ctx); diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/migrate/WiredEvents.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/migrate/WiredEvents.java index a6df356a..91bba744 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/migrate/WiredEvents.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/migrate/WiredEvents.java @@ -199,19 +199,19 @@ public final class WiredEvents { .build(); } - /** - * Create an event for when a score is achieved. /** * Create an event for when a score threshold is achieved. * @param room the room * @param user the user who achieved the score - * @param score the score achieved + * @param score the current total score + * @param scoreAdded the amount of score just added * @return the event */ - public static WiredEvent scoreAchieved(Room room, RoomUnit user, int score) { + public static WiredEvent scoreAchieved(Room room, RoomUnit user, int score, int scoreAdded) { return WiredEvent.builder(WiredEvent.Type.SCORE_ACHIEVED, room) .actor(user) - .legacyStuff(new Object[]{score}) + .score(score) + .scoreAdded(scoreAdded) .build(); } @@ -257,7 +257,7 @@ public final class WiredEvents { return WiredEvent.builder(WiredEvent.Type.BOT_REACHED_HABBO, room) .actor(botUnit) .tile(targetUser.getCurrentLocation()) - .legacyStuff(new Object[]{targetUser}) + .targetUnit(targetUser) .build(); } @@ -324,15 +324,14 @@ public final class WiredEvents { * @param triggerType the legacy trigger type * @param room the room * @param roomUnit the triggering unit (may be null) - * @param stuff legacy stuff array + * @param stuff legacy stuff array (now only used to extract typed data) * @return the event */ public static WiredEvent fromLegacy(WiredTriggerType triggerType, Room room, RoomUnit roomUnit, Object[] stuff) { WiredEvent.Type eventType = WiredEvent.Type.fromLegacyType(triggerType); WiredEvent.Builder builder = WiredEvent.builder(eventType, room) - .actor(roomUnit) - .legacyStuff(stuff); + .actor(roomUnit); // Try to extract common data from stuff array if (stuff != null) { diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/tick/WiredTickService.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/tick/WiredTickService.java index 45ca8de0..144f73d7 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/tick/WiredTickService.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/tick/WiredTickService.java @@ -252,7 +252,6 @@ public final class WiredTickService { if (tickables.add(tickable)) { tickable.onRegistered(room, System.currentTimeMillis()); - LOGGER.debug("Registered tickable {} in room {}", tickable.getId(), roomId); } } @@ -273,7 +272,6 @@ public final class WiredTickService { if (tickables != null) { if (tickables.remove(tickable)) { tickable.onUnregistered(room); - LOGGER.debug("Unregistered tickable {} from room {}", tickable.getId(), roomId); } // Clean up empty sets diff --git a/Emulator/src/main/java/com/eu/habbo/messages/outgoing/rooms/pets/PetInformationComposer.java b/Emulator/src/main/java/com/eu/habbo/messages/outgoing/rooms/pets/PetInformationComposer.java index 78cb57e4..70150740 100644 --- a/Emulator/src/main/java/com/eu/habbo/messages/outgoing/rooms/pets/PetInformationComposer.java +++ b/Emulator/src/main/java/com/eu/habbo/messages/outgoing/rooms/pets/PetInformationComposer.java @@ -43,7 +43,7 @@ public class PetInformationComposer extends MessageComposer { } this.response.appendInt(this.pet.getEnergy()); this.response.appendInt(this.pet.getMaxEnergy()); //Max energy - this.response.appendInt(this.pet.getHappiness()); //this.pet.getHappiness() + this.response.appendInt(this.pet.getHappiness()); this.response.appendInt(100); this.response.appendInt(this.pet.getRespect()); this.response.appendInt(this.pet.getUserId()); @@ -51,7 +51,19 @@ public class PetInformationComposer extends MessageComposer { this.response.appendString(this.room.getFurniOwnerName(this.pet.getUserId())); //Owner name this.response.appendInt(this.pet instanceof MonsterplantPet ? ((MonsterplantPet) this.pet).getRarity() : 0); - this.response.appendBoolean(this.pet instanceof RideablePet && this.requestingHabbo != null && (((RideablePet) this.pet).getRider() == null || this.pet.getUserId() == this.requestingHabbo.getHabboInfo().getId()) && ((RideablePet) this.pet).hasSaddle()); // can ride + + // Can ride: pet has saddle, no one riding or user owns pet, and (user owns pet or anyone can ride) + boolean canRide = false; + if (this.pet instanceof RideablePet && this.requestingHabbo != null) { + RideablePet rideablePet = (RideablePet) this.pet; + boolean hasSaddle = rideablePet.hasSaddle(); + boolean noRider = rideablePet.getRider() == null; + boolean isOwner = this.pet.getUserId() == this.requestingHabbo.getHabboInfo().getId(); + boolean canRidePermission = isOwner || rideablePet.anyoneCanRide(); + canRide = hasSaddle && (noRider || isOwner) && canRidePermission; + } + this.response.appendBoolean(canRide); + this.response.appendBoolean(this.pet instanceof RideablePet && ((RideablePet) this.pet).getRider() != null && this.requestingHabbo != null && ((RideablePet) this.pet).getRider().getHabboInfo().getId() == this.requestingHabbo.getHabboInfo().getId()); // is current user riding this.response.appendInt(0); this.response.appendInt(this.pet instanceof RideablePet && ((RideablePet) this.pet).anyoneCanRide() ? 1 : 0); // anyone can ride diff --git a/Emulator/src/main/java/com/eu/habbo/messages/outgoing/rooms/pets/RoomPetHorseFigureComposer.java b/Emulator/src/main/java/com/eu/habbo/messages/outgoing/rooms/pets/RoomPetHorseFigureComposer.java index 3c7cd570..702b1d2e 100644 --- a/Emulator/src/main/java/com/eu/habbo/messages/outgoing/rooms/pets/RoomPetHorseFigureComposer.java +++ b/Emulator/src/main/java/com/eu/habbo/messages/outgoing/rooms/pets/RoomPetHorseFigureComposer.java @@ -45,7 +45,7 @@ public class RoomPetHorseFigureComposer extends MessageComposer { this.response.appendInt(this.pet.getHairColor()); } this.response.appendBoolean(this.pet.hasSaddle()); - this.response.appendBoolean(false); // this.pet.anyoneCanRide() + this.response.appendBoolean(this.pet.anyoneCanRide()); return this.response; } diff --git a/Emulator/src/main/java/com/eu/habbo/messages/outgoing/rooms/users/RoomUnitOnRollerComposer.java b/Emulator/src/main/java/com/eu/habbo/messages/outgoing/rooms/users/RoomUnitOnRollerComposer.java index f2f54bfd..0628a478 100644 --- a/Emulator/src/main/java/com/eu/habbo/messages/outgoing/rooms/users/RoomUnitOnRollerComposer.java +++ b/Emulator/src/main/java/com/eu/habbo/messages/outgoing/rooms/users/RoomUnitOnRollerComposer.java @@ -4,10 +4,12 @@ import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.bots.Bot; import com.eu.habbo.habbohotel.items.interactions.InteractionRoller; import com.eu.habbo.habbohotel.pets.Pet; +import com.eu.habbo.habbohotel.pets.RideablePet; 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.RoomUnitType; +import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.users.HabboItem; import com.eu.habbo.messages.ServerMessage; import com.eu.habbo.messages.outgoing.MessageComposer; @@ -58,7 +60,21 @@ public class RoomUnitOnRollerComposer extends MessageComposer { // Early validation: Check if the roller movement is still valid before composing the packet if (this.roller != null && room.getLayout() != null) { // Check if the destination tile is blocked by another unit that moved there - if (this.newLocation.hasUnits() && !this.newLocation.getUnits().contains(this.roomUnit)) { + // Skip this check for pets with riders or users riding pets (they share the tile) + boolean isRidingPetOrRider = false; + if (this.roomUnit.getRoomUnitType() == RoomUnitType.PET) { + Pet pet = this.room.getPet(this.roomUnit); + if (pet instanceof RideablePet && ((RideablePet) pet).getRider() != null) { + isRidingPetOrRider = true; + } + } else if (this.roomUnit.getRoomUnitType() == RoomUnitType.USER) { + Habbo habbo = this.room.getHabbo(this.roomUnit); + if (habbo != null && habbo.getHabboInfo() != null && habbo.getHabboInfo().getRiding() != null) { + isRidingPetOrRider = true; + } + } + + if (!isRidingPetOrRider && this.newLocation.hasUnits() && !this.newLocation.getUnits().contains(this.roomUnit)) { return null; } @@ -106,6 +122,15 @@ public class RoomUnitOnRollerComposer extends MessageComposer { Pet pet = this.room.getPet(this.roomUnit); if (pet != null) { pet.needsUpdate = true; + + // If this pet has a rider, sync the rider's position with the pet + if (pet instanceof RideablePet) { + RideablePet rideablePet = (RideablePet) pet; + Habbo rider = rideablePet.getRider(); + if (rider != null && rider.getRoomUnit() != null) { + rider.getRoomUnit().setLastRollerTime(System.currentTimeMillis()); + } + } } } } diff --git a/Emulator/src/main/java/com/eu/habbo/threading/runnables/RoomUnitRidePet.java b/Emulator/src/main/java/com/eu/habbo/threading/runnables/RoomUnitRidePet.java index bcfd8ef2..b6227a06 100644 --- a/Emulator/src/main/java/com/eu/habbo/threading/runnables/RoomUnitRidePet.java +++ b/Emulator/src/main/java/com/eu/habbo/threading/runnables/RoomUnitRidePet.java @@ -21,7 +21,10 @@ public class RoomUnitRidePet implements Runnable { @Override public void run() { - if (this.habbo.getRoomUnit() == null || this.pet.getRoomUnit() == null || this.pet.getRoom() != this.habbo.getHabboInfo().getCurrentRoom() || this.goalTile == null || this.habbo.getRoomUnit().getGoal() != this.goalTile) + if (this.habbo == null || this.habbo.getRoomUnit() == null || this.pet == null || + this.pet.getRoomUnit() == null || this.habbo.getHabboInfo() == null || + this.pet.getRoom() != this.habbo.getHabboInfo().getCurrentRoom() || + this.goalTile == null || this.habbo.getRoomUnit().getGoal() != this.goalTile) return; if (habbo.getRoomUnit().getCurrentLocation().distance(pet.getRoomUnit().getCurrentLocation()) <= 1) { @@ -34,10 +37,16 @@ public class RoomUnitRidePet implements Runnable { habbo.getRoomUnit().setPreviousLocationZ(this.pet.getRoomUnit().getZ() + 1); habbo.getRoomUnit().setRotation(this.pet.getRoomUnit().getBodyRotation()); habbo.getRoomUnit().statusUpdate(true); + + // Set up the pet for riding pet.setRider(habbo); + pet.setTask(PetTasks.RIDE); + pet.getRoomUnit().stopWalking(); + pet.getRoomUnit().setGoalLocation(habbo.getRoomUnit().getCurrentLocation()); + habbo.getHabboInfo().getCurrentRoom().sendComposer(new RoomUserStatusComposer(habbo.getRoomUnit()).compose()); habbo.getHabboInfo().getCurrentRoom().sendComposer(new RoomUserEffectComposer(habbo.getRoomUnit()).compose()); - pet.setTask(PetTasks.RIDE); + habbo.getHabboInfo().getCurrentRoom().sendComposer(new RoomUserStatusComposer(pet.getRoomUnit()).compose()); } else { pet.getRoomUnit().setWalkTimeOut(3 + Emulator.getIntUnixTimestamp()); pet.getRoomUnit().stopWalking(); diff --git a/Latest_Compiled_Version/Habbo-4.0.1-jar-with-dependencies.jar b/Latest_Compiled_Version/Habbo-4.0.1-jar-with-dependencies.jar index 94104c3a..f40dcb4c 100644 Binary files a/Latest_Compiled_Version/Habbo-4.0.1-jar-with-dependencies.jar and b/Latest_Compiled_Version/Habbo-4.0.1-jar-with-dependencies.jar differ