Skip to content

Commit 32924a3

Browse files
committed
Refactor unrent command again
1 parent 332ee16 commit 32924a3

2 files changed

Lines changed: 81 additions & 75 deletions

File tree

realty-common/src/main/java/io/github/md5sha256/realty/database/RealtyLogicImpl.java

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -700,22 +700,6 @@ record NoLeaseholdContract() implements UnrentResult {}
700700
record UpdateFailed() implements UnrentResult {}
701701
}
702702

703-
public @NotNull UnrentResult previewUnrent(@NotNull String worldGuardRegionId,
704-
@NotNull UUID worldId) {
705-
try (SqlSessionWrapper wrapper = database.openSession()) {
706-
LeaseholdContractMapper leaseholdMapper = wrapper.leaseholdContractMapper();
707-
LeaseholdContractEntity lease = leaseholdMapper.selectByRegion(worldGuardRegionId, worldId);
708-
if (lease == null) {
709-
return new UnrentResult.NoLeaseholdContract();
710-
}
711-
long totalSeconds = lease.durationSeconds();
712-
long remainingSeconds = lease.endDate() == null ? 0
713-
: Math.max(0, java.time.Duration.between(java.time.LocalDateTime.now(), lease.endDate()).getSeconds());
714-
double refund = totalSeconds > 0 ? lease.price() * remainingSeconds / totalSeconds : 0;
715-
return new UnrentResult.Success(refund, lease.tenantId(), lease.landlordId());
716-
}
717-
}
718-
719703
public @NotNull UnrentResult unrentRegion(@NotNull String worldGuardRegionId,
720704
@NotNull UUID worldId,
721705
@NotNull UUID tenantId) {
@@ -819,6 +803,13 @@ public record RegionInfo(
819803
}
820804
}
821805

806+
public @Nullable LeaseholdContractEntity getLeaseholdContract(@NotNull String worldGuardRegionId,
807+
@NotNull UUID worldId) {
808+
try (SqlSessionWrapper wrapper = database.openSession()) {
809+
return wrapper.leaseholdContractMapper().selectByRegion(worldGuardRegionId, worldId);
810+
}
811+
}
812+
822813
public @NotNull RegionInfo getRegionInfo(@NotNull String worldGuardRegionId, @NotNull UUID worldId) {
823814
try (SqlSessionWrapper wrapper = database.openSession()) {
824815
FreeholdContractEntity freehold = wrapper.freeholdContractMapper().selectByRegion(worldGuardRegionId, worldId);

realty-paper/src/main/java/io/github/md5sha256/realty/command/UnrentCommand.java

Lines changed: 74 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import io.github.md5sha256.realty.api.SignTextApplicator;
99
import io.github.md5sha256.realty.command.util.WorldGuardRegion;
1010
import io.github.md5sha256.realty.command.util.WorldGuardRegionResolver;
11+
import io.github.md5sha256.realty.database.entity.LeaseholdContractEntity;
1112
import io.github.md5sha256.realty.database.RealtyLogicImpl;
1213
import io.github.md5sha256.realty.localisation.MessageContainer;
1314
import io.github.md5sha256.realty.localisation.MessageKeys;
@@ -71,86 +72,100 @@ private void execute(@NotNull CommandContext<CommandSourceStack> ctx) {
7172
Placeholder.unparsed("region", regionId)));
7273
return;
7374
}
74-
// Step 1: preview (DB read, no mutation)
75+
// Step 1: query lease to compute refund (DB read, no mutation)
7576
CompletableFuture.supplyAsync(() -> {
7677
try {
77-
return logic.previewUnrent(regionId, region.world().getUID());
78+
return logic.getLeaseholdContract(regionId, region.world().getUID());
7879
} catch (Exception ex) {
7980
sender.sendMessage(messages.messageFor(MessageKeys.UNRENT_ERROR,
8081
Placeholder.unparsed("error", ex.getMessage())));
8182
return null;
8283
}
83-
}, executorState.dbExec()).thenAcceptAsync(preview -> {
84-
if (preview == null) {
84+
}, executorState.dbExec()).thenAcceptAsync(lease -> {
85+
if (lease == null) {
86+
sender.sendMessage(messages.messageFor(MessageKeys.UNRENT_NO_LEASEHOLD_CONTRACT,
87+
Placeholder.unparsed("region", regionId)));
8588
return;
8689
}
87-
switch (preview) {
88-
case RealtyLogicImpl.UnrentResult.NoLeaseholdContract ignored ->
89-
sender.sendMessage(messages.messageFor(MessageKeys.UNRENT_NO_LEASEHOLD_CONTRACT,
90-
Placeholder.unparsed("region", regionId)));
91-
case RealtyLogicImpl.UnrentResult.UpdateFailed ignored ->
92-
sender.sendMessage(messages.messageFor(MessageKeys.UNRENT_UPDATE_FAILED,
93-
Placeholder.unparsed("region", regionId)));
94-
case RealtyLogicImpl.UnrentResult.Success success -> {
95-
double refund = success.refund();
96-
// Step 2: economy — withdraw from landlord, deposit to tenant (main thread)
97-
if (refund > 0) {
98-
OfflinePlayer landlord = Bukkit.getOfflinePlayer(success.landlordId());
99-
EconomyResponse withdrawResponse = economy.withdrawPlayer(landlord, refund);
100-
if (!withdrawResponse.transactionSuccess()) {
101-
sender.sendMessage(messages.messageFor(MessageKeys.UNRENT_REFUND_FAILED,
102-
Placeholder.unparsed("error", withdrawResponse.errorMessage)));
103-
return;
104-
}
105-
EconomyResponse depositResponse = economy.depositPlayer(sender, refund);
106-
if (!depositResponse.transactionSuccess()) {
107-
economy.depositPlayer(landlord, refund);
108-
sender.sendMessage(messages.messageFor(MessageKeys.UNRENT_REFUND_FAILED,
109-
Placeholder.unparsed("error", depositResponse.errorMessage)));
110-
return;
111-
}
112-
}
113-
// Step 3: DB mutation
114-
CompletableFuture.supplyAsync(() -> {
115-
try {
116-
RealtyLogicImpl.UnrentResult result = logic.unrentRegion(
117-
regionId, region.world().getUID(), sender.getUniqueId());
118-
if (result instanceof RealtyLogicImpl.UnrentResult.Success) {
119-
return logic.getRegionPlaceholders(regionId, region.world().getUID());
120-
}
121-
return null;
122-
} catch (Exception ex) {
123-
return null;
124-
}
125-
}, executorState.dbExec()).thenAcceptAsync(placeholders -> {
126-
// Step 4: finalize or revert
127-
if (placeholders == null) {
128-
if (refund > 0) {
129-
economy.withdrawPlayer(sender, refund);
130-
OfflinePlayer landlord = Bukkit.getOfflinePlayer(success.landlordId());
131-
economy.depositPlayer(landlord, refund);
132-
}
133-
sender.sendMessage(messages.messageFor(MessageKeys.UNRENT_UPDATE_FAILED,
134-
Placeholder.unparsed("region", regionId)));
135-
return;
136-
}
90+
long totalSeconds = lease.durationSeconds();
91+
long remainingSeconds = lease.endDate() == null ? 0
92+
: Math.max(0, java.time.Duration.between(java.time.LocalDateTime.now(), lease.endDate()).getSeconds());
93+
double refund = totalSeconds > 0 ? lease.price() * remainingSeconds / totalSeconds : 0;
94+
// Step 2: economy — withdraw from landlord, deposit to tenant (main thread)
95+
if (refund > 0) {
96+
OfflinePlayer landlord = Bukkit.getOfflinePlayer(lease.landlordId());
97+
EconomyResponse withdrawResponse = economy.withdrawPlayer(landlord, refund);
98+
if (!withdrawResponse.transactionSuccess()) {
99+
sender.sendMessage(messages.messageFor(MessageKeys.UNRENT_REFUND_FAILED,
100+
Placeholder.unparsed("error", withdrawResponse.errorMessage)));
101+
return;
102+
}
103+
EconomyResponse depositResponse = economy.depositPlayer(sender, refund);
104+
if (!depositResponse.transactionSuccess()) {
105+
economy.depositPlayer(landlord, refund);
106+
sender.sendMessage(messages.messageFor(MessageKeys.UNRENT_REFUND_FAILED,
107+
Placeholder.unparsed("error", depositResponse.errorMessage)));
108+
return;
109+
}
110+
}
111+
// Step 3: DB mutation
112+
CompletableFuture.supplyAsync(() -> {
113+
RealtyLogicImpl.UnrentResult result = logic.unrentRegion(
114+
regionId, region.world().getUID(), sender.getUniqueId());
115+
if (result instanceof RealtyLogicImpl.UnrentResult.Success) {
116+
Map<String, String> placeholders = logic.getRegionPlaceholders(regionId, region.world().getUID());
117+
return Map.entry(result, placeholders);
118+
}
119+
return Map.<RealtyLogicImpl.UnrentResult, Map<String, String>>entry(result, Map.of());
120+
}, executorState.dbExec()).thenAcceptAsync(entry -> {
121+
// Step 4: finalize or revert economy
122+
switch (entry.getKey()) {
123+
case RealtyLogicImpl.UnrentResult.Success ignored -> {
137124
ProtectedRegion protectedRegion = region.region();
138125
protectedRegion.getOwners().clear();
139126
protectedRegion.getMembers().clear();
140-
regionProfileService.applyFlags(region, RegionState.FOR_LEASE, placeholders);
141-
signTextApplicator.updateLoadedSigns(region.world(), regionId, RegionState.FOR_LEASE, placeholders);
127+
regionProfileService.applyFlags(region, RegionState.FOR_LEASE, entry.getValue());
128+
signTextApplicator.updateLoadedSigns(region.world(), regionId, RegionState.FOR_LEASE, entry.getValue());
142129
sender.sendMessage(messages.messageFor(MessageKeys.UNRENT_SUCCESS,
143130
Placeholder.unparsed("region", regionId),
144131
Placeholder.unparsed("refund", CurrencyFormatter.format(refund))));
145-
notificationService.queueNotification(success.landlordId(),
132+
notificationService.queueNotification(lease.landlordId(),
146133
messages.messageFor(MessageKeys.NOTIFICATION_REGION_UNRENTED,
147134
Placeholder.unparsed("player", sender.getName()),
148135
Placeholder.unparsed("region", regionId),
149136
Placeholder.unparsed("refund", CurrencyFormatter.format(refund))));
150-
}, executorState.mainThreadExec());
137+
}
138+
case RealtyLogicImpl.UnrentResult.NoLeaseholdContract ignored -> {
139+
revertEconomy(sender, lease, refund);
140+
sender.sendMessage(messages.messageFor(MessageKeys.UNRENT_NO_LEASEHOLD_CONTRACT,
141+
Placeholder.unparsed("region", regionId)));
142+
}
143+
case RealtyLogicImpl.UnrentResult.UpdateFailed ignored -> {
144+
revertEconomy(sender, lease, refund);
145+
sender.sendMessage(messages.messageFor(MessageKeys.UNRENT_UPDATE_FAILED,
146+
Placeholder.unparsed("region", regionId)));
147+
}
151148
}
152-
}
149+
}, executorState.mainThreadExec()).exceptionally(ex -> {
150+
executorState.mainThreadExec().execute(() -> {
151+
revertEconomy(sender, lease, refund);
152+
Throwable cause = ex.getCause() != null ? ex.getCause() : ex;
153+
sender.sendMessage(messages.messageFor(MessageKeys.UNRENT_ERROR,
154+
Placeholder.unparsed("error", cause.getMessage())));
155+
});
156+
return null;
157+
});
153158
}, executorState.mainThreadExec());
154159
}
155160

161+
private void revertEconomy(@NotNull Player tenant,
162+
@NotNull LeaseholdContractEntity lease,
163+
double refund) {
164+
if (refund > 0) {
165+
economy.withdrawPlayer(tenant, refund);
166+
OfflinePlayer landlord = Bukkit.getOfflinePlayer(lease.landlordId());
167+
economy.depositPlayer(landlord, refund);
168+
}
169+
}
170+
156171
}

0 commit comments

Comments
 (0)