Skip to content

Commit

Permalink
Fixes #5004: Prevent AEBaseTileEntity#saveChanges() leaking client TEs
Browse files Browse the repository at this point in the history
There was a chance that it would leak the clientside `TileEntity` into
the serverside callback queue.
  • Loading branch information
yueh committed Feb 25, 2021
1 parent 7c3f64e commit 03195df
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 1 deletion.
14 changes: 14 additions & 0 deletions src/main/java/appeng/hooks/TickHandler.java
Expand Up @@ -31,6 +31,7 @@
import java.util.WeakHashMap;
import java.util.concurrent.TimeUnit;

import com.google.common.base.Preconditions;
import com.google.common.base.Stopwatch;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.Multimap;
Expand Down Expand Up @@ -104,7 +105,20 @@ public Map<Integer, PlayerColor> getPlayerColors() {
return this.cliPlayerColors;
}

/**
* Add a server or world callback which gets called the next time the queue is ticked.
*
* Callbacks on the client are not support.
* <p>
* Using null as world will queue it into the global {@link ServerTickEvent}, otherwise it will be ticked with the
* corresponding {@link WorldTickEvent}.
*
* @param w null or the specific {@link World}
* @param c the callback
*/
public void addCallable(final IWorld w, final IWorldCallable<?> c) {
Preconditions.checkArgument(w == null || !w.isRemote(), "Can only register serverside callbacks");

if (w == null) {
this.serverQueue.add(c);
} else {
Expand Down
11 changes: 10 additions & 1 deletion src/main/java/appeng/tile/AEBaseTileEntity.java
Expand Up @@ -450,7 +450,16 @@ public void disableDrops() {
}

public void saveChanges() {
if (this.world != null) {
if (this.world == null) {
return;
}

// Clientside is marked immediately as dirty as there is no queue processing
// Serverside is only queued once per tick to avoid costly operations
// TODO: Evaluate if this is still necessary
if (this.world.isRemote) {
this.markDirty();
} else {
this.world.markChunkDirty(this.pos, this);
if (!this.markDirtyQueued) {
TickHandler.instance().addCallable(null, this::markDirtyAtEndOfTick);
Expand Down

0 comments on commit 03195df

Please sign in to comment.