1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
--- a/net/minecraft/server/level/DistanceManager.java
+++ b/net/minecraft/server/level/DistanceManager.java
@@ -117,8 +117,17 @@
ChunkHolder playerchunk;
+ // CraftBukkit start - SPIGOT-7780: Call chunk unload events before updateHighestAllowedStatus
while (iterator.hasNext()) {
playerchunk = (ChunkHolder) iterator.next();
+ playerchunk.callEventIfUnloading(chunkLoadingManager);
+ }
+
+ iterator = this.chunksToUpdateFutures.iterator();
+ // CraftBukkit end
+
+ while (iterator.hasNext()) {
+ playerchunk = (ChunkHolder) iterator.next();
playerchunk.updateHighestAllowedStatus(chunkLoadingManager);
}
@@ -165,30 +174,33 @@
}
}
- void addTicket(long position, Ticket<?> ticket) {
- SortedArraySet<Ticket<?>> arraysetsorted = this.getTickets(position);
+ boolean addTicket(long i, Ticket<?> ticket) { // CraftBukkit - void -> boolean
+ SortedArraySet<Ticket<?>> arraysetsorted = this.getTickets(i);
int j = DistanceManager.getTicketLevelAt(arraysetsorted);
Ticket<?> ticket1 = (Ticket) arraysetsorted.addOrGet(ticket);
ticket1.setCreatedTick(this.ticketTickCounter);
if (ticket.getTicketLevel() < j) {
- this.ticketTracker.update(position, ticket.getTicketLevel(), true);
+ this.ticketTracker.update(i, ticket.getTicketLevel(), true);
}
+ return ticket == ticket1; // CraftBukkit
}
- void removeTicket(long pos, Ticket<?> ticket) {
- SortedArraySet<Ticket<?>> arraysetsorted = this.getTickets(pos);
+ boolean removeTicket(long i, Ticket<?> ticket) { // CraftBukkit - void -> boolean
+ SortedArraySet<Ticket<?>> arraysetsorted = this.getTickets(i);
+ boolean removed = false; // CraftBukkit
if (arraysetsorted.remove(ticket)) {
- ;
+ removed = true; // CraftBukkit
}
if (arraysetsorted.isEmpty()) {
- this.tickets.remove(pos);
+ this.tickets.remove(i);
}
- this.ticketTracker.update(pos, DistanceManager.getTicketLevelAt(arraysetsorted), false);
+ this.ticketTracker.update(i, DistanceManager.getTicketLevelAt(arraysetsorted), false);
+ return removed; // CraftBukkit
}
public <T> void addTicket(TicketType<T> type, ChunkPos pos, int level, T argument) {
@@ -202,19 +214,33 @@
}
public <T> void addRegionTicket(TicketType<T> type, ChunkPos pos, int radius, T argument) {
- Ticket<T> ticket = new Ticket<>(type, ChunkLevel.byStatus(FullChunkStatus.FULL) - radius, argument);
- long j = pos.toLong();
+ // CraftBukkit start
+ this.addRegionTicketAtDistance(type, pos, radius, argument);
+ }
- this.addTicket(j, ticket);
+ public <T> boolean addRegionTicketAtDistance(TicketType<T> tickettype, ChunkPos chunkcoordintpair, int i, T t0) {
+ // CraftBukkit end
+ Ticket<T> ticket = new Ticket<>(tickettype, ChunkLevel.byStatus(FullChunkStatus.FULL) - i, t0);
+ long j = chunkcoordintpair.toLong();
+
+ boolean added = this.addTicket(j, ticket); // CraftBukkit
this.tickingTicketsTracker.addTicket(j, ticket);
+ return added; // CraftBukkit
}
public <T> void removeRegionTicket(TicketType<T> type, ChunkPos pos, int radius, T argument) {
- Ticket<T> ticket = new Ticket<>(type, ChunkLevel.byStatus(FullChunkStatus.FULL) - radius, argument);
- long j = pos.toLong();
+ // CraftBukkit start
+ this.removeRegionTicketAtDistance(type, pos, radius, argument);
+ }
- this.removeTicket(j, ticket);
+ public <T> boolean removeRegionTicketAtDistance(TicketType<T> tickettype, ChunkPos chunkcoordintpair, int i, T t0) {
+ // CraftBukkit end
+ Ticket<T> ticket = new Ticket<>(tickettype, ChunkLevel.byStatus(FullChunkStatus.FULL) - i, t0);
+ long j = chunkcoordintpair.toLong();
+
+ boolean removed = this.removeTicket(j, ticket); // CraftBukkit
this.tickingTicketsTracker.removeTicket(j, ticket);
+ return removed; // CraftBukkit
}
private SortedArraySet<Ticket<?>> getTickets(long position) {
@@ -253,9 +279,10 @@
ChunkPos chunkcoordintpair = pos.chunk();
long i = chunkcoordintpair.toLong();
ObjectSet<ServerPlayer> objectset = (ObjectSet) this.playersPerChunk.get(i);
+ if (objectset == null) return; // CraftBukkit - SPIGOT-6208
- objectset.remove(player);
- if (objectset.isEmpty()) {
+ if (objectset != null) objectset.remove(player); // Paper - some state corruption happens here, don't crash, clean up gracefully
+ if (objectset == null || objectset.isEmpty()) { // Paper
this.playersPerChunk.remove(i);
this.naturalSpawnChunkCounter.update(i, Integer.MAX_VALUE, false);
this.playerTicketManager.update(i, Integer.MAX_VALUE, false);
@@ -358,7 +385,7 @@
}
public void removeTicketsOnClosing() {
- ImmutableSet<TicketType<?>> immutableset = ImmutableSet.of(TicketType.UNKNOWN);
+ ImmutableSet<TicketType<?>> immutableset = ImmutableSet.of(TicketType.UNKNOWN, TicketType.POST_TELEPORT, TicketType.FUTURE_AWAIT); // Paper - add additional tickets to preserve
ObjectIterator<Entry<SortedArraySet<Ticket<?>>>> objectiterator = this.tickets.long2ObjectEntrySet().fastIterator();
while (objectiterator.hasNext()) {
@@ -389,7 +416,27 @@
public boolean hasTickets() {
return !this.tickets.isEmpty();
+ }
+
+ // CraftBukkit start
+ public <T> void removeAllTicketsFor(TicketType<T> ticketType, int ticketLevel, T ticketIdentifier) {
+ Ticket<T> target = new Ticket<>(ticketType, ticketLevel, ticketIdentifier);
+
+ for (java.util.Iterator<Entry<SortedArraySet<Ticket<?>>>> iterator = this.tickets.long2ObjectEntrySet().fastIterator(); iterator.hasNext();) {
+ Entry<SortedArraySet<Ticket<?>>> entry = iterator.next();
+ SortedArraySet<Ticket<?>> tickets = entry.getValue();
+ if (tickets.remove(target)) {
+ // copied from removeTicket
+ this.ticketTracker.update(entry.getLongKey(), DistanceManager.getTicketLevelAt(tickets), false);
+
+ // can't use entry after it's removed
+ if (tickets.isEmpty()) {
+ iterator.remove();
+ }
+ }
+ }
}
+ // CraftBukkit end
private class ChunkTicketTracker extends ChunkTracker {
|