Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,8 @@ public void time() {
leader.sendMessage("§cGet more prestige or unclaim provinces to counteract this!");
}
}
SimpleFactions.getInstance().getVehicleUpkeepService()
.warnBankShortfalls(Bukkit.getOnlinePlayers(), getSecondsUntilNewDay());
}
if (timer >= DAY_LENGTH_SECONDS) {
runDailyStep("player ledgers", () -> PlayerEconomyManager.get().clearAllDaily());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package net.tfminecraft.simplefactions.vehicles.maintenance;

import net.tfminecraft.simplefactions.utils.Formatter;
import net.tfminecraft.simplefactions.vehicles.maintenance.VehicleMaintenancePayService.PaymentSource;

public final class VehicleMaintenanceMessages {
Expand All @@ -18,6 +19,15 @@ public static String payArmed(PaymentSource source) {
+ (source == PaymentSource.BANK ? "bank" : "pouch") + ".";
}

public static String bankShortfall(double shortfall, int secondsUntilCharge) {
// Round up so the final partial minute does not read as already due.
int minutes = (secondsUntilCharge + 59) / 60;
return "§cYou lack " + Formatter.formatMoney(shortfall)
+ " denars in your personal bank to pay vehicle maintenance in "
+ minutes / 60 + "h " + minutes % 60 + "m"
+ " §7(/deco deposit for the bank, it does not count the pouch)";
}

public static String paySuccess() {
return "§aPaid vehicle maintenance.";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import net.tfminecraft.simplefactions.vehicles.maintenance.DenarEconomyPlayerBank.PlayerBank;
import net.tfminecraft.simplefactions.vehicles.registry.PlayerVehicleRegistry;
import net.tfminecraft.simplefactions.vehicles.registry.VehicleOwnershipQueries;
import java.util.Collection;
import java.util.UUID;

import org.bukkit.Bukkit;
Expand All @@ -13,6 +14,7 @@
import net.tfminecraft.simplefactions.SimpleFactions;
import net.tfminecraft.simplefactions.player.PlayerEconomyManager;
import net.tfminecraft.simplefactions.player.income.PlayerCashflow;
import net.tfminecraft.simplefactions.utils.Formatter;
import net.tfminecraft.vehicleframework.data.OwnedVehicleSummary;

public final class VehicleUpkeepService {
Expand Down Expand Up @@ -63,6 +65,28 @@ public void processDailyUpkeep() {
}
}

/** Warns each player whose bank cannot cover their vehicle upkeep at the next new day. */
public void warnBankShortfalls(Collection<? extends Player> players, int secondsUntilCharge) {
if (secondsUntilCharge <= 0) {
return;
}
for (Player player : players) {
double upkeep = VehicleUpkeepProjection.projectedDailyUpkeep(player.getName(), registry);
if (upkeep <= 0.0) {
continue;
}
UUID playerUuid = playerBank.resolve(player.getName());
if (playerUuid == null) {
continue;
}
// Round to cents so a float residue never reads as "lack 0.00".
double shortfall = Formatter.formatDouble(upkeep - playerBank.getBankBalance(playerUuid));
if (shortfall > 0.0) {
player.sendMessage(VehicleMaintenanceMessages.bankShortfall(shortfall, secondsUntilCharge));
}
}
}

public void tickHourlyDecay() {
double fraction = VehiclesConfigLoader.getMaintenanceHourlyDamageFraction();
double minHealth = VehiclesConfigLoader.getMaintenanceMinHealthFraction();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.io.IOException;
Expand All @@ -30,6 +32,7 @@
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.Server;
import org.bukkit.entity.Player;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -168,6 +171,53 @@ void successfulUpkeepClearsExistingUnpaid() {
assertFalse(store.isUnpaid("vehicle-1"));
}

@Test
void warnsPlayerWhoseBankCannotCoverUpkeep() {
UUID playerUuid = UUID.randomUUID();
bank.setBalance(playerUuid, 5.0);
bank.remember("Alice", playerUuid);
VehicleOwnershipQueries.setSourceForTests(
new FakeOwnedInventory().add("vehicle-1", "ironclad", "player_Alice"));
Player alice = onlinePlayer("Alice", playerUuid);

service.warnBankShortfalls(List.of(alice), 3 * 3600 + 12 * 60);

verify(alice).sendMessage("§cYou lack 15.00 denars in your personal bank to pay vehicle maintenance"
+ " in 3h 12m §7(/deco deposit for the bank, it does not count the pouch)");
}

@Test
void doesNotWarnWhenBankCoversUpkeep() {
UUID playerUuid = UUID.randomUUID();
bank.setBalance(playerUuid, 20.0);
bank.remember("Alice", playerUuid);
VehicleOwnershipQueries.setSourceForTests(
new FakeOwnedInventory().add("vehicle-1", "ironclad", "player_Alice"));
Player alice = onlinePlayer("Alice", playerUuid);

service.warnBankShortfalls(List.of(alice), 600);

verify(alice, never()).sendMessage(org.mockito.ArgumentMatchers.anyString());
}

@Test
void doesNotWarnPlayersWithoutVehicles() {
UUID playerUuid = UUID.randomUUID();
bank.remember("Alice", playerUuid);
Player alice = onlinePlayer("Alice", playerUuid);

service.warnBankShortfalls(List.of(alice), 600);

verify(alice, never()).sendMessage(org.mockito.ArgumentMatchers.anyString());
}

private static Player onlinePlayer(String name, UUID uuid) {
Player player = mock(Player.class);
when(player.getName()).thenReturn(name);
when(player.getUniqueId()).thenReturn(uuid);
return player;
}

@Test
void hourlyDecayDamagesUnpaidVehicles() {
store.markUnpaid("vehicle-1", 1L);
Expand Down