2424import com .volmit .adapt .api .recipe .AdaptRecipe ;
2525import com .volmit .adapt .content .item .BoundEnderPearl ;
2626import com .volmit .adapt .util .*;
27+ import lombok .EqualsAndHashCode ;
2728import lombok .NoArgsConstructor ;
29+ import manifold .rt .api .util .Pair ;
2830import org .bukkit .*;
2931import org .bukkit .block .Block ;
3032import org .bukkit .entity .Player ;
3840import org .bukkit .inventory .ItemStack ;
3941import us .lynuxcraft .deadsilenceiv .advancedchests .AdvancedChestsAPI ;
4042
43+ import java .lang .ref .WeakReference ;
4144import java .util .ArrayList ;
4245import java .util .Iterator ;
4346import java .util .List ;
4447import java .util .Map ;
4548import java .util .concurrent .ConcurrentHashMap ;
49+ import java .util .concurrent .atomic .AtomicInteger ;
4650
4751import static com .volmit .adapt .api .adaptation .chunk .ChunkLoading .loadChunkAsync ;
4852
4953public class RiftAccess extends SimpleAdaptation <RiftAccess .Config > {
50- private final Map <Location , List <InventoryView >> activeViewsMap = new ConcurrentHashMap <>();
51-
54+ private final Map <Pair < ChunkPos , Location > , List <InventoryView >> activeViewsMap = new ConcurrentHashMap <>();
55+ private final Map < ChunkPos , AtomicInteger > tickets = new ConcurrentHashMap <>();
5256
5357 public RiftAccess () {
5458 super ("rift-access" );
@@ -168,7 +172,7 @@ private void openPearl(Player p) {
168172 } else if (b .getState () instanceof InventoryHolder holder ) {
169173 InventoryView view = p .openInventory (holder .getInventory ());
170174 if (view == null ) return ;
171- activeViewsMap .computeIfAbsent (b .getLocation (), k -> new ArrayList <>()).add (view );
175+ activeViewsMap .computeIfAbsent (Pair . make ( new ChunkPos ( chunk ). add (), b .getLocation () ), k -> new ArrayList <>()).add (view );
172176 }
173177 sp .play (p .getLocation (), Sound .PARTICLE_SOUL_ESCAPE , 1f , 0.10f );
174178 sp .play (p .getLocation (), Sound .BLOCK_ENDER_CHEST_OPEN , 1f , 0.10f );
@@ -181,15 +185,15 @@ public void onTick() {
181185 }
182186
183187 private void checkActiveViews () {
184- Iterator <Map .Entry <Location , List <InventoryView >>> mapIterator = activeViewsMap .entrySet ().iterator ();
188+ Iterator <Map .Entry <Pair < ChunkPos , Location > , List <InventoryView >>> mapIterator = activeViewsMap .entrySet ().iterator ();
185189 while (mapIterator .hasNext ()) {
186- Map .Entry <Location , List <InventoryView >> entry = mapIterator .next ();
190+ Map .Entry <Pair < ChunkPos , Location > , List <InventoryView >> entry = mapIterator .next ();
187191 removeInvalidViews (entry );
188192 removeEntryIfViewsEmpty (mapIterator , entry );
189193 }
190194 }
191195
192- private void removeInvalidViews (Map .Entry <Location , List <InventoryView >> entry ) {
196+ private void removeInvalidViews (Map .Entry <Pair < ChunkPos , Location > , List <InventoryView >> entry ) {
193197 List <InventoryView > views = entry .getValue ();
194198 for (int ii = views .size () - 1 ; ii >= 0 ; ii --) {
195199 InventoryView i = views .get (ii );
@@ -204,10 +208,11 @@ private boolean shouldRemoveView(InventoryView i) {
204208 return !i .getPlayer ().getOpenInventory ().equals (i ) || (location == null || !isStorage (location .getBlock ().getBlockData ()));
205209 }
206210
207- private void removeEntryIfViewsEmpty (Iterator <Map .Entry <Location , List <InventoryView >>> mapIterator , Map .Entry <Location , List <InventoryView >> entry ) {
211+ private void removeEntryIfViewsEmpty (Iterator <Map .Entry <Pair < ChunkPos , Location > , List <InventoryView >>> mapIterator , Map .Entry <Pair < ChunkPos , Location > , List <InventoryView >> entry ) {
208212 List <InventoryView > views = entry .getValue ();
209213 if (views .isEmpty ()) {
210214 mapIterator .remove ();
215+ entry .getKey ().getFirst ().remove ();
211216 }
212217 }
213218
@@ -281,4 +286,40 @@ protected static class Config {
281286 double costFactor = 0.2 ;
282287 int initialCost = 15 ;
283288 }
289+
290+ @ EqualsAndHashCode
291+ private class ChunkPos {
292+ @ EqualsAndHashCode .Exclude
293+ private final WeakReference <World > world ;
294+ private final String name ;
295+ private final int x , z ;
296+
297+ private ChunkPos (Chunk chunk ) {
298+ this .world = new WeakReference <>(chunk .getWorld ());
299+ this .name = chunk .getWorld ().getName ();
300+ this .x = chunk .getX ();
301+ this .z = chunk .getZ ();
302+ }
303+
304+ public ChunkPos add () {
305+ World world = this .world .get ();
306+ if (world == null ) return this ;
307+ if (tickets .computeIfAbsent (this , k -> new AtomicInteger ()).getAndIncrement () == 0 )
308+ world .addPluginChunkTicket (x , z , Adapt .instance );
309+ return this ;
310+ }
311+
312+ public void remove () {
313+ World world = this .world .get ();
314+ if (world == null ) {
315+ tickets .remove (this );
316+ return ;
317+ }
318+ if (tickets .computeIfAbsent (this , k -> new AtomicInteger ()).decrementAndGet () <= 0 ) {
319+ world .removePluginChunkTicket (x , z , Adapt .instance );
320+ world .unloadChunkRequest (x , z );
321+ tickets .remove (this );
322+ }
323+ }
324+ }
284325}
0 commit comments