@@ -71,60 +71,85 @@ private void execute(@NotNull CommandContext<CommandSourceStack> ctx) {
7171 Placeholder .unparsed ("region" , regionId )));
7272 return ;
7373 }
74+ // Step 1: preview (DB read, no mutation)
7475 CompletableFuture .supplyAsync (() -> {
7576 try {
76- RealtyLogicImpl .UnrentResult result = logic .unrentRegion (
77- regionId , region .world ().getUID (), sender .getUniqueId ());
78- return switch (result ) {
79- case RealtyLogicImpl .UnrentResult .Success success -> {
80- Map <String , String > placeholders = logic .getRegionPlaceholders (regionId , region .world ().getUID ());
81- yield Map .entry (success , placeholders );
82- }
83- case RealtyLogicImpl .UnrentResult .NoLeaseholdContract ignored -> {
84- sender .sendMessage (messages .messageFor (MessageKeys .UNRENT_NO_LEASEHOLD_CONTRACT ,
85- Placeholder .unparsed ("region" , regionId )));
86- yield null ;
87- }
88- case RealtyLogicImpl .UnrentResult .UpdateFailed ignored -> {
89- sender .sendMessage (messages .messageFor (MessageKeys .UNRENT_UPDATE_FAILED ,
90- Placeholder .unparsed ("region" , regionId )));
91- yield null ;
92- }
93- };
77+ return logic .previewUnrent (regionId , region .world ().getUID ());
9478 } catch (Exception ex ) {
9579 sender .sendMessage (messages .messageFor (MessageKeys .UNRENT_ERROR ,
9680 Placeholder .unparsed ("error" , ex .getMessage ())));
9781 return null ;
9882 }
99- }, executorState .dbExec ()).thenAcceptAsync (entry -> {
100- if (entry == null ) {
83+ }, executorState .dbExec ()).thenAcceptAsync (preview -> {
84+ if (preview == null ) {
10185 return ;
10286 }
103- RealtyLogicImpl .UnrentResult .Success success = entry .getKey ();
104- double refund = success .refund ();
105- if (refund > 0 ) {
106- EconomyResponse response = economy .depositPlayer (sender , refund );
107- if (!response .transactionSuccess ()) {
108- sender .sendMessage (messages .messageFor (MessageKeys .UNRENT_REFUND_FAILED ,
109- Placeholder .unparsed ("error" , response .errorMessage )));
110- return ;
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+ }
137+ ProtectedRegion protectedRegion = region .region ();
138+ protectedRegion .getOwners ().clear ();
139+ protectedRegion .getMembers ().clear ();
140+ regionProfileService .applyFlags (region , RegionState .FOR_LEASE , placeholders );
141+ signTextApplicator .updateLoadedSigns (region .world (), regionId , RegionState .FOR_LEASE , placeholders );
142+ sender .sendMessage (messages .messageFor (MessageKeys .UNRENT_SUCCESS ,
143+ Placeholder .unparsed ("region" , regionId ),
144+ Placeholder .unparsed ("refund" , CurrencyFormatter .format (refund ))));
145+ notificationService .queueNotification (success .landlordId (),
146+ messages .messageFor (MessageKeys .NOTIFICATION_REGION_UNRENTED ,
147+ Placeholder .unparsed ("player" , sender .getName ()),
148+ Placeholder .unparsed ("region" , regionId ),
149+ Placeholder .unparsed ("refund" , CurrencyFormatter .format (refund ))));
150+ }, executorState .mainThreadExec ());
111151 }
112- OfflinePlayer landlord = Bukkit .getOfflinePlayer (success .landlordId ());
113- economy .withdrawPlayer (landlord , refund );
114152 }
115- ProtectedRegion protectedRegion = region .region ();
116- protectedRegion .getOwners ().clear ();
117- protectedRegion .getMembers ().clear ();
118- regionProfileService .applyFlags (region , RegionState .FOR_LEASE , entry .getValue ());
119- signTextApplicator .updateLoadedSigns (region .world (), regionId , RegionState .FOR_LEASE , entry .getValue ());
120- sender .sendMessage (messages .messageFor (MessageKeys .UNRENT_SUCCESS ,
121- Placeholder .unparsed ("region" , regionId ),
122- Placeholder .unparsed ("refund" , CurrencyFormatter .format (refund ))));
123- notificationService .queueNotification (success .landlordId (),
124- messages .messageFor (MessageKeys .NOTIFICATION_REGION_UNRENTED ,
125- Placeholder .unparsed ("player" , sender .getName ()),
126- Placeholder .unparsed ("region" , regionId ),
127- Placeholder .unparsed ("refund" , CurrencyFormatter .format (refund ))));
128153 }, executorState .mainThreadExec ());
129154 }
130155
0 commit comments