fix(items): charge rentable space purchases

Deduct the computed rent cost when a user rents an InteractionRentableSpace. The previous flow only checked that the user had enough credits, then marked the space as rented without charging them, allowing free weekly rentals.

Honor ACC_INFINITE_CREDITS for staff accounts and add a contract test that keeps the charge before the rented state is assigned.
This commit is contained in:
simoleo89
2026-06-13 17:34:55 +02:00
parent 60ccc8c80b
commit 82c6f3f9ff
2 changed files with 39 additions and 1 deletions
@@ -3,6 +3,7 @@ package com.eu.habbo.habbohotel.items.interactions;
import com.eu.habbo.Emulator;
import com.eu.habbo.habbohotel.gameclients.GameClient;
import com.eu.habbo.habbohotel.items.Item;
import com.eu.habbo.habbohotel.permissions.Permission;
import com.eu.habbo.habbohotel.rooms.Room;
import com.eu.habbo.habbohotel.rooms.RoomLayout;
import com.eu.habbo.habbohotel.rooms.RoomUnit;
@@ -133,12 +134,18 @@ public class InteractionRentableSpace extends HabboItem {
if (habbo.getHabboStats().isRentingSpace())
return;
if (habbo.getHabboInfo().getCredits() < this.rentCost())
int cost = this.rentCost();
boolean hasInfiniteCredits = habbo.hasPermission(Permission.ACC_INFINITE_CREDITS);
if (!hasInfiniteCredits && habbo.getHabboInfo().getCredits() < cost)
return;
if (habbo.getHabboStats().getClubExpireTimestamp() < Emulator.getIntUnixTimestamp())
return;
if (!hasInfiniteCredits) {
habbo.giveCredits(-cost);
}
this.setRenterId(habbo.getHabboInfo().getId());
this.setRenterName(habbo.getHabboInfo().getUsername());
this.setEndTimestamp(Emulator.getIntUnixTimestamp() + (7 * 86400));
@@ -0,0 +1,31 @@
package com.eu.habbo.habbohotel.items.interactions;
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 RentableSpaceChargeContractTest {
@Test
void rentingSpaceChargesCreditsBeforeMarkingSpaceRented() throws Exception {
String source = Files.readString(Path.of("src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionRentableSpace.java"));
int rentMethod = source.indexOf("public void rent(Habbo habbo)");
assertTrue(rentMethod >= 0, "InteractionRentableSpace must keep explicit rent handling");
String rentHandling = source.substring(rentMethod, Math.min(source.length(), rentMethod + 1400));
assertTrue(rentHandling.contains("int cost = this.rentCost();"),
"Rent cost must be computed once before charging");
assertTrue(rentHandling.contains("boolean hasInfiniteCredits = habbo.hasPermission(Permission.ACC_INFINITE_CREDITS);"),
"Renting must honor infinite-credit staff permission before charging");
assertTrue(rentHandling.contains("!hasInfiniteCredits && habbo.getHabboInfo().getCredits() < cost"),
"Renting must reject non-staff users without enough credits for the computed cost");
assertTrue(rentHandling.contains("habbo.giveCredits(-cost);"),
"Renting must deduct the computed credit cost");
assertTrue(rentHandling.indexOf("habbo.giveCredits(-cost);") < rentHandling.indexOf("this.setRenterId"),
"Credits must be charged before the rentable space is marked as rented");
}
}