diff --git a/Emulator/src/main/java/com/eu/habbo/messages/incoming/rooms/pets/PetUseItemEvent.java b/Emulator/src/main/java/com/eu/habbo/messages/incoming/rooms/pets/PetUseItemEvent.java index 5a8a3847..ed0db1c9 100644 --- a/Emulator/src/main/java/com/eu/habbo/messages/incoming/rooms/pets/PetUseItemEvent.java +++ b/Emulator/src/main/java/com/eu/habbo/messages/incoming/rooms/pets/PetUseItemEvent.java @@ -32,6 +32,12 @@ public class PetUseItemEvent extends MessageHandler { int petId = this.packet.readInt(); Pet pet = this.client.getHabbo().getHabboInfo().getCurrentRoom().getPet(petId); + if (pet == null + || item.getUserId() != this.client.getHabbo().getHabboInfo().getId() + || pet.getUserId() != this.client.getHabbo().getHabboInfo().getId()) { + return; + } + if (pet instanceof HorsePet) { if (item.getBaseItem().getName().toLowerCase().startsWith("horse_dye")) { int race = Integer.parseInt(item.getBaseItem().getName().split("_")[2]); @@ -89,11 +95,6 @@ public class PetUseItemEvent extends MessageHandler { Emulator.getGameEnvironment().getItemManager().deleteItem(item); } } else if (pet instanceof MonsterplantPet) { - // Validate ownership - only owner can use items on their plant - if (pet.getUserId() != this.client.getHabbo().getHabboInfo().getId()) { - return; - } - MonsterplantPet monsterplant = (MonsterplantPet) pet; if (item.getBaseItem().getName().equalsIgnoreCase("mnstr_revival")) { @@ -165,4 +166,4 @@ public class PetUseItemEvent extends MessageHandler { } } } -} \ No newline at end of file +} diff --git a/Emulator/src/test/java/com/eu/habbo/messages/incoming/rooms/pets/PetUseItemOwnershipContractTest.java b/Emulator/src/test/java/com/eu/habbo/messages/incoming/rooms/pets/PetUseItemOwnershipContractTest.java new file mode 100644 index 00000000..ef6ea5c1 --- /dev/null +++ b/Emulator/src/test/java/com/eu/habbo/messages/incoming/rooms/pets/PetUseItemOwnershipContractTest.java @@ -0,0 +1,25 @@ +package com.eu.habbo.messages.incoming.rooms.pets; + +import org.junit.jupiter.api.Test; + +import java.nio.file.Files; +import java.nio.file.Path; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +class PetUseItemOwnershipContractTest { + @Test + void validatesItemAndPetOwnershipBeforeHorseMutations() throws Exception { + String source = Files.readString(Path.of("src/main/java/com/eu/habbo/messages/incoming/rooms/pets/PetUseItemEvent.java")); + + int petLookup = source.indexOf("Pet pet = this.client.getHabbo().getHabboInfo().getCurrentRoom().getPet(petId)"); + int ownershipGuard = source.indexOf("item.getUserId() != this.client.getHabbo().getHabboInfo().getId()", petLookup); + int petGuard = source.indexOf("pet.getUserId() != this.client.getHabbo().getHabboInfo().getId()", ownershipGuard); + int horseBranch = source.indexOf("if (pet instanceof HorsePet)", petGuard); + + assertTrue(petLookup > -1, "PetUseItemEvent should resolve the target pet"); + assertTrue(ownershipGuard > petLookup, "PetUseItemEvent must require ownership of the consumable item"); + assertTrue(petGuard > ownershipGuard, "PetUseItemEvent must require ownership of the target pet"); + assertTrue(horseBranch > petGuard, "Ownership checks must run before horse item mutations"); + } +}