--- a/net/minecraft/server/ChunkMapDistance.java +++ b/net/minecraft/server/ChunkMapDistance.java @@ -59,7 +59,7 @@ while (objectiterator.hasNext()) { Entry>> entry = (Entry) objectiterator.next(); - if (((ArraySetSorted) entry.getValue()).removeIf((ticket) -> { + if ((entry.getValue()).removeIf((ticket) -> { // CraftBukkit - decompile error return ticket.b(this.currentTick); })) { this.e.b(entry.getLongKey(), a((ArraySetSorted) entry.getValue()), false); @@ -95,10 +95,25 @@ } if (!this.pendingChunkUpdates.isEmpty()) { - this.pendingChunkUpdates.forEach((playerchunk) -> { + // CraftBukkit start + // Iterate pending chunk updates with protection against concurrent modification exceptions + java.util.Iterator iter = this.pendingChunkUpdates.iterator(); + int expectedSize = this.pendingChunkUpdates.size(); + do { + PlayerChunk playerchunk = iter.next(); + iter.remove(); + expectedSize--; + playerchunk.a(playerchunkmap); - }); - this.pendingChunkUpdates.clear(); + + // Reset iterator if set was modified using add() + if (this.pendingChunkUpdates.size() != expectedSize) { + expectedSize = this.pendingChunkUpdates.size(); + iter = this.pendingChunkUpdates.iterator(); + } + } while (iter.hasNext()); + // CraftBukkit end + return true; } else { if (!this.l.isEmpty()) { @@ -120,7 +135,7 @@ completablefuture.thenAccept((either) -> { this.m.execute(() -> { - this.k.a((Object) ChunkTaskQueueSorter.a(() -> { + this.k.a(ChunkTaskQueueSorter.a(() -> { // CraftBukkit - decompile error }, j, false)); }); }); @@ -134,23 +149,25 @@ } } - private void addTicket(long i, Ticket ticket) { + private boolean addTicket(long i, Ticket ticket) { // CraftBukkit - void -> boolean ArraySetSorted> arraysetsorted = this.e(i); int j = a(arraysetsorted); - Ticket ticket1 = (Ticket) arraysetsorted.a((Object) ticket); + Ticket ticket1 = (Ticket) arraysetsorted.a(ticket); // CraftBukkit - decompile error ticket1.a(this.currentTick); if (ticket.b() < j) { this.e.b(i, ticket.b(), true); } + return ticket == ticket1; // CraftBukkit } - private void removeTicket(long i, Ticket ticket) { + private boolean removeTicket(long i, Ticket ticket) { // CraftBukkit - void -> boolean ArraySetSorted> arraysetsorted = this.e(i); + boolean removed = false; // CraftBukkit if (arraysetsorted.remove(ticket)) { - ; + removed = true; // CraftBukkit } if (arraysetsorted.isEmpty()) { @@ -158,16 +175,29 @@ } this.e.b(i, a(arraysetsorted), false); + return removed; // CraftBukkit } public void a(TicketType tickettype, ChunkCoordIntPair chunkcoordintpair, int i, T t0) { - this.addTicket(chunkcoordintpair.pair(), new Ticket<>(tickettype, i, t0)); + // CraftBukkit start + this.addTicketAtLevel(tickettype, chunkcoordintpair, i, t0); + } + + public boolean addTicketAtLevel(TicketType ticketType, ChunkCoordIntPair chunkcoordintpair, int level, T identifier) { + return this.addTicket(chunkcoordintpair.pair(), new Ticket<>(ticketType, level, identifier)); + // CraftBukkit end } public void b(TicketType tickettype, ChunkCoordIntPair chunkcoordintpair, int i, T t0) { - Ticket ticket = new Ticket<>(tickettype, i, t0); + // CraftBukkit start + this.removeTicketAtLevel(tickettype, chunkcoordintpair, i, t0); + } - this.removeTicket(chunkcoordintpair.pair(), ticket); + public boolean removeTicketAtLevel(TicketType ticketType, ChunkCoordIntPair chunkcoordintpair, int level, T identifier) { + Ticket ticket = new Ticket<>(ticketType, level, identifier); + + return this.removeTicket(chunkcoordintpair.pair(), ticket); + // CraftBukkit end } public void addTicket(TicketType tickettype, ChunkCoordIntPair chunkcoordintpair, int i, T t0) { @@ -251,6 +281,21 @@ return this.i.a(); } + // CraftBukkit start + public void removeAllTicketsFor(TicketType ticketType, int ticketLevel, T ticketIdentifier) { + Ticket target = new Ticket<>(ticketType, ticketLevel, ticketIdentifier); + + for (java.util.Iterator>> iterator = this.tickets.values().iterator(); iterator.hasNext();) { + ArraySetSorted> tickets = iterator.next(); + tickets.remove(target); + + if (tickets.isEmpty()) { + iterator.remove(); + } + } + } + // CraftBukkit end + class a extends ChunkMap { public a() { @@ -331,13 +376,13 @@ Ticket ticket = new Ticket<>(TicketType.PLAYER, ChunkMapDistance.b, new ChunkCoordIntPair(i)); if (flag1) { - ChunkMapDistance.this.j.a((Object) ChunkTaskQueueSorter.a(() -> { + ChunkMapDistance.this.j.a(ChunkTaskQueueSorter.a(() -> { // CraftBukkit - decompile error ChunkMapDistance.this.m.execute(() -> { if (this.c(this.c(i))) { ChunkMapDistance.this.addTicket(i, ticket); ChunkMapDistance.this.l.add(i); } else { - ChunkMapDistance.this.k.a((Object) ChunkTaskQueueSorter.a(() -> { + ChunkMapDistance.this.k.a(ChunkTaskQueueSorter.a(() -> { // CraftBukkit - decompile error }, i, false)); } @@ -346,7 +391,7 @@ return j; })); } else { - ChunkMapDistance.this.k.a((Object) ChunkTaskQueueSorter.a(() -> { + ChunkMapDistance.this.k.a(ChunkTaskQueueSorter.a(() -> { // CraftBukkit - decompile error ChunkMapDistance.this.m.execute(() -> { ChunkMapDistance.this.removeTicket(i, ticket); });