Upstream Paper fully
This commit is contained in:
@@ -1,15 +1,18 @@
|
||||
package net.minecraft.server;
|
||||
|
||||
import com.destroystokyo.paper.PaperWorldConfig.DuplicateUUIDMode;
|
||||
import com.destroystokyo.paper.exception.ServerInternalException;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Queues;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import javax.annotation.Nullable;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
@@ -36,6 +39,7 @@ public class Chunk {
|
||||
public final World world;
|
||||
public final int[] heightMap;
|
||||
public Long scheduledForUnload; // Paper - delay chunk unloads
|
||||
private static final Logger logger = LogManager.getLogger(); // Paper
|
||||
public final int locX;
|
||||
public final int locZ;
|
||||
private boolean m;
|
||||
@@ -679,8 +683,34 @@ public class Chunk {
|
||||
entity.ab = this.locX;
|
||||
entity.ac = k;
|
||||
entity.ad = this.locZ;
|
||||
this.entitySlices[k].add(entity);
|
||||
|
||||
// Paper start
|
||||
List<Entity> entitySlice = this.entitySlices[k];
|
||||
boolean inThis = entitySlice.contains(entity);
|
||||
if (entity.entitySlice != null || inThis) {
|
||||
if (entity.entitySlice == entitySlice || inThis) {
|
||||
LogManager.getLogger().warn(entity + " was already in this chunk section! Report this to https://github.com/PaperMC/Paper/issues/1223");
|
||||
new Throwable().printStackTrace();
|
||||
return;
|
||||
} else {
|
||||
LogManager.getLogger().warn(entity + " is still in another ChunkSection! Report this to https://github.com/PaperMC/Paper/issues/1223");
|
||||
|
||||
Chunk chunk = entity.getCurrentChunk();
|
||||
if (chunk != null) {
|
||||
if (chunk != this) {
|
||||
LogManager.getLogger().warn(entity + " was in another chunk at that! " + chunk.locX + "," + chunk.locZ);
|
||||
}
|
||||
chunk.removeEntity(entity);
|
||||
} else {
|
||||
removeEntity(entity);
|
||||
}
|
||||
new Throwable().printStackTrace();
|
||||
}
|
||||
}
|
||||
entity.entitySlice = entitySlice;
|
||||
entitySlice.add(entity);
|
||||
|
||||
this.markDirty();
|
||||
entity.setCurrentChunk(this);
|
||||
entityCounts.increment(entity.entityKeyString);
|
||||
if (entity instanceof EntityItem) {
|
||||
@@ -723,6 +753,13 @@ public class Chunk {
|
||||
|
||||
// Paper start
|
||||
if (!this.entitySlices[i].remove(entity)) { return; }
|
||||
if (entitySlices[i] == entity.entitySlice) {
|
||||
entity.entitySlice = null;
|
||||
} else {
|
||||
LogManager.getLogger().warn(entity + " was removed from a entitySlice we did not expect. Report this to https://github.com/PaperMC/Paper/issues/1223");
|
||||
new Throwable().printStackTrace();
|
||||
}
|
||||
this.markDirty();
|
||||
entity.setCurrentChunk(null);
|
||||
entityCounts.decrement(entity.entityKeyString);
|
||||
if (entity instanceof EntityItem) {
|
||||
@@ -856,6 +893,36 @@ public class Chunk {
|
||||
|
||||
for (int j = 0; j < i; ++j) {
|
||||
List entityslice = aentityslice[j]; // Spigot
|
||||
// Paper start
|
||||
DuplicateUUIDMode mode = world.paperConfig.duplicateUUIDMode;
|
||||
if (mode == DuplicateUUIDMode.DELETE || mode == DuplicateUUIDMode.REGEN) {
|
||||
Map<UUID, Entity> thisChunk = new HashMap<>();
|
||||
for (Iterator<Entity> iterator = ((List<Entity>) entityslice).iterator(); iterator.hasNext(); ) {
|
||||
Entity entity = iterator.next();
|
||||
if (entity.dead) continue;
|
||||
Entity other = ((WorldServer) world).entitiesByUUID.get(entity.uniqueID);
|
||||
if (other == null) {
|
||||
other = thisChunk.get(entity.uniqueID);
|
||||
}
|
||||
if (other != null && !other.dead) {
|
||||
switch (mode) {
|
||||
case REGEN: {
|
||||
entity.setUUID(UUID.randomUUID());
|
||||
logger.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", regenerated UUID for " + entity + ". See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about.");
|
||||
break;
|
||||
}
|
||||
case DELETE: {
|
||||
logger.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", deleted entity " + entity + ". See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about.");
|
||||
entity.die();
|
||||
iterator.remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
thisChunk.put(entity.uniqueID, entity);
|
||||
}
|
||||
}
|
||||
// Paper end
|
||||
|
||||
this.world.a((Collection) entityslice);
|
||||
}
|
||||
|
||||
@@ -50,7 +50,21 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper
|
||||
|
||||
// CraftBukkit start
|
||||
private static final int CURRENT_LEVEL = 2;
|
||||
public static Random SHARED_RANDOM = new io.akarin.api.internal.utils.random.LightRandom(); // Paper // Akarin - LightRNG
|
||||
// Paper start
|
||||
public static Random SHARED_RANDOM = new io.akarin.api.internal.utils.random.LightRandom() { // Akarin - LightRNG
|
||||
private boolean locked = false;
|
||||
@Override
|
||||
public synchronized void setSeed(long seed) {
|
||||
if (locked) {
|
||||
LogManager.getLogger().error("Ignoring setSeed on Entity.SHARED_RANDOM", new Throwable());
|
||||
} else {
|
||||
super.setSeed(seed);
|
||||
locked = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
Object entitySlice = null;
|
||||
// Paper end
|
||||
static boolean isLevelAtLeast(NBTTagCompound tag, int level) {
|
||||
return tag.hasKey("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level;
|
||||
}
|
||||
@@ -64,6 +78,7 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper
|
||||
}
|
||||
return bukkitEntity;
|
||||
}
|
||||
Throwable addedToWorldStack; // Paper - entity debug
|
||||
// CraftBukikt end
|
||||
|
||||
private static final Logger a = LogManager.getLogger();
|
||||
@@ -2352,7 +2367,7 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return String.format("%s[\'%s\'/%d, uuid=\'%s\', l=\'%s\', x=%.2f, y=%.2f, z=%.2f]", new Object[] { this.getClass().getSimpleName(), this.getName(), Integer.valueOf(this.id), this.uniqueID.toString(), this.world == null ? "~NULL~" : this.world.getWorldData().getName(), Double.valueOf(this.locX), Double.valueOf(this.locY), Double.valueOf(this.locZ)}); // Paper - add UUID
|
||||
return String.format("%s[\'%s\'/%d, uuid=\'%s\', l=\'%s\', x=%.2f, y=%.2f, z=%.2f, cx=%d, cd=%d, tl=%d, v=%b, d=%b]", new Object[] { this.getClass().getSimpleName(), this.getName(), Integer.valueOf(this.id), this.uniqueID.toString(), this.world == null ? "~NULL~" : this.world.getWorldData().getName(), Double.valueOf(this.locX), Double.valueOf(this.locY), Double.valueOf(this.locZ), getChunkX(), getChunkZ(), this.ticksLived, this.valid, this.dead}); // Paper - add more information
|
||||
}
|
||||
|
||||
public boolean isInvulnerable(DamageSource damagesource) {
|
||||
@@ -2604,6 +2619,7 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper
|
||||
});
|
||||
}
|
||||
|
||||
public void setUUID(UUID uuid) { a(uuid); } // Paper - OBFHELPER
|
||||
public void a(UUID uuid) {
|
||||
this.uniqueID = uuid;
|
||||
this.ar = this.uniqueID.toString();
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.google.common.util.concurrent.ListenableFuture;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -40,7 +41,7 @@ public class WorldServer extends World implements IAsyncTaskHandler {
|
||||
public final PlayerChunkMap manager; // Akarin - private -> public
|
||||
// private final Set<NextTickListEntry> nextTickListHash = Sets.newHashSet();
|
||||
private final HashTreeSet<NextTickListEntry> nextTickList = new HashTreeSet<NextTickListEntry>(); // CraftBukkit - HashTreeSet
|
||||
private final Map<UUID, Entity> entitiesByUUID = Maps.newHashMap();
|
||||
public final Map<UUID, Entity> entitiesByUUID = Maps.newHashMap(); // Paper
|
||||
public boolean savingDisabled;
|
||||
private boolean Q;
|
||||
private int emptyTime;
|
||||
@@ -52,6 +53,10 @@ public class WorldServer extends World implements IAsyncTaskHandler {
|
||||
private final List<NextTickListEntry> W = Lists.newArrayList();
|
||||
|
||||
// CraftBukkit start
|
||||
private static final boolean DEBUG_ENTITIES = Boolean.getBoolean("debug.entities"); // Paper
|
||||
private static Throwable getAddToWorldStackTrace(Entity entity) {
|
||||
return new Throwable(entity + " Added to world at " + new Date());
|
||||
}
|
||||
public final int dimension;
|
||||
|
||||
// Add env and gen to constructor
|
||||
@@ -1181,6 +1186,7 @@ public class WorldServer extends World implements IAsyncTaskHandler {
|
||||
private boolean j(Entity entity) {
|
||||
if (entity.dead) {
|
||||
WorldServer.a.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.a(entity)); // CraftBukkit // Paper
|
||||
if (DEBUG_ENTITIES) getAddToWorldStackTrace(entity).printStackTrace();
|
||||
return false;
|
||||
} else {
|
||||
UUID uuid = entity.getUniqueID();
|
||||
@@ -1188,12 +1194,21 @@ public class WorldServer extends World implements IAsyncTaskHandler {
|
||||
if (this.entitiesByUUID.containsKey(uuid)) {
|
||||
Entity entity1 = this.entitiesByUUID.get(uuid);
|
||||
|
||||
if (this.f.contains(entity1)) {
|
||||
if (this.f.contains(entity1) || entity1.dead) { // Paper - overwrite the current dead one
|
||||
this.f.remove(entity1);
|
||||
} else {
|
||||
if (!(entity instanceof EntityHuman)) {
|
||||
WorldServer.a.error("Keeping entity {} that already exists with UUID {} - " + entity1, EntityTypes.a(entity1), uuid.toString()); // CraftBukkit // Paper
|
||||
WorldServer.a.error("Deleting duplicate entity {}", entity); // Paper
|
||||
if (entity.world.paperConfig.duplicateUUIDMode != com.destroystokyo.paper.PaperWorldConfig.DuplicateUUIDMode.NOTHING) {
|
||||
WorldServer.a.error("Keeping entity {} that already exists with UUID {}", entity1, uuid.toString()); // CraftBukkit // Paper
|
||||
WorldServer.a.error("Duplicate entity {} will not be added to the world. See paper.yml duplicate-uuid-resolver and set this to either regen, delete or nothing to get rid of this message", entity); // Paper
|
||||
if (DEBUG_ENTITIES) {
|
||||
if (entity1.addedToWorldStack != null) {
|
||||
entity1.addedToWorldStack.printStackTrace();
|
||||
}
|
||||
getAddToWorldStackTrace(entity).printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1211,7 +1226,24 @@ public class WorldServer extends World implements IAsyncTaskHandler {
|
||||
protected void b(Entity entity) {
|
||||
super.b(entity);
|
||||
this.entitiesById.a(entity.getId(), entity);
|
||||
this.entitiesByUUID.put(entity.getUniqueID(), entity);
|
||||
// Paper start
|
||||
if (DEBUG_ENTITIES) {
|
||||
entity.addedToWorldStack = getAddToWorldStackTrace(entity);
|
||||
}
|
||||
Entity old = this.entitiesByUUID.put(entity.getUniqueID(), entity);
|
||||
if (old != null && old.getId() != entity.getId() && old.valid && entity.world.paperConfig.duplicateUUIDMode != com.destroystokyo.paper.PaperWorldConfig.DuplicateUUIDMode.NOTHING) {
|
||||
Logger logger = LogManager.getLogger();
|
||||
logger.error("Overwrote an existing entity " + old + " with " + entity);
|
||||
if (DEBUG_ENTITIES) {
|
||||
if (old.addedToWorldStack != null) {
|
||||
old.addedToWorldStack.printStackTrace();
|
||||
} else {
|
||||
logger.error("Oddly, the old entity was not added to the world in the normal way. Plugins?");
|
||||
}
|
||||
entity.addedToWorldStack.printStackTrace();
|
||||
}
|
||||
}
|
||||
// Paper end
|
||||
Entity[] aentity = entity.bb();
|
||||
|
||||
if (aentity != null) {
|
||||
|
||||
@@ -1179,11 +1179,32 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
for (EntityPlayer player : players) {
|
||||
player.getBukkitEntity().reregisterPlayer(self);
|
||||
}
|
||||
refreshPlayer();
|
||||
}
|
||||
@Override
|
||||
public PlayerProfile getPlayerProfile() {
|
||||
return new CraftPlayerProfile(this).clone();
|
||||
}
|
||||
|
||||
private void refreshPlayer() {
|
||||
EntityPlayer handle = getHandle();
|
||||
|
||||
Location loc = getLocation();
|
||||
|
||||
PlayerConnection connection = handle.playerConnection;
|
||||
reregisterPlayer(handle);
|
||||
|
||||
//Respawn the player then update their position and selected slot
|
||||
connection.sendPacket(new PacketPlayOutRespawn(handle.dimension, handle.world.getDifficulty(), handle.world.getWorldData().getType(), handle.playerInteractManager.getGameMode()));
|
||||
handle.updateAbilities();
|
||||
connection.sendPacket(new PacketPlayOutPosition(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch(), new HashSet<>(), 0));
|
||||
MinecraftServer.getServer().getPlayerList().updateClient(handle);
|
||||
|
||||
if (this.isOp()) {
|
||||
this.setOp(false);
|
||||
this.setOp(true);
|
||||
}
|
||||
}
|
||||
// Paper end
|
||||
|
||||
public void removeDisconnectingPlayer(Player player) {
|
||||
|
||||
Submodule work/Paper updated: ca2209ff20...8b96ee7ea8
Reference in New Issue
Block a user