Upstream Paper fully
This commit is contained in:
@@ -1,15 +1,18 @@
|
|||||||
package net.minecraft.server;
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import com.destroystokyo.paper.PaperWorldConfig.DuplicateUUIDMode;
|
||||||
import com.destroystokyo.paper.exception.ServerInternalException;
|
import com.destroystokyo.paper.exception.ServerInternalException;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.Queues;
|
import com.google.common.collect.Queues;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
@@ -36,6 +39,7 @@ public class Chunk {
|
|||||||
public final World world;
|
public final World world;
|
||||||
public final int[] heightMap;
|
public final int[] heightMap;
|
||||||
public Long scheduledForUnload; // Paper - delay chunk unloads
|
public Long scheduledForUnload; // Paper - delay chunk unloads
|
||||||
|
private static final Logger logger = LogManager.getLogger(); // Paper
|
||||||
public final int locX;
|
public final int locX;
|
||||||
public final int locZ;
|
public final int locZ;
|
||||||
private boolean m;
|
private boolean m;
|
||||||
@@ -679,8 +683,34 @@ public class Chunk {
|
|||||||
entity.ab = this.locX;
|
entity.ab = this.locX;
|
||||||
entity.ac = k;
|
entity.ac = k;
|
||||||
entity.ad = this.locZ;
|
entity.ad = this.locZ;
|
||||||
this.entitySlices[k].add(entity);
|
|
||||||
// Paper start
|
// 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);
|
entity.setCurrentChunk(this);
|
||||||
entityCounts.increment(entity.entityKeyString);
|
entityCounts.increment(entity.entityKeyString);
|
||||||
if (entity instanceof EntityItem) {
|
if (entity instanceof EntityItem) {
|
||||||
@@ -723,6 +753,13 @@ public class Chunk {
|
|||||||
|
|
||||||
// Paper start
|
// Paper start
|
||||||
if (!this.entitySlices[i].remove(entity)) { return; }
|
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);
|
entity.setCurrentChunk(null);
|
||||||
entityCounts.decrement(entity.entityKeyString);
|
entityCounts.decrement(entity.entityKeyString);
|
||||||
if (entity instanceof EntityItem) {
|
if (entity instanceof EntityItem) {
|
||||||
@@ -856,6 +893,36 @@ public class Chunk {
|
|||||||
|
|
||||||
for (int j = 0; j < i; ++j) {
|
for (int j = 0; j < i; ++j) {
|
||||||
List entityslice = aentityslice[j]; // Spigot
|
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);
|
this.world.a((Collection) entityslice);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,21 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper
|
|||||||
|
|
||||||
// CraftBukkit start
|
// CraftBukkit start
|
||||||
private static final int CURRENT_LEVEL = 2;
|
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) {
|
static boolean isLevelAtLeast(NBTTagCompound tag, int level) {
|
||||||
return tag.hasKey("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= 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;
|
return bukkitEntity;
|
||||||
}
|
}
|
||||||
|
Throwable addedToWorldStack; // Paper - entity debug
|
||||||
// CraftBukikt end
|
// CraftBukikt end
|
||||||
|
|
||||||
private static final Logger a = LogManager.getLogger();
|
private static final Logger a = LogManager.getLogger();
|
||||||
@@ -2352,7 +2367,7 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
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) {
|
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) {
|
public void a(UUID uuid) {
|
||||||
this.uniqueID = uuid;
|
this.uniqueID = uuid;
|
||||||
this.ar = this.uniqueID.toString();
|
this.ar = this.uniqueID.toString();
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import com.google.common.util.concurrent.ListenableFuture;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -40,7 +41,7 @@ public class WorldServer extends World implements IAsyncTaskHandler {
|
|||||||
public final PlayerChunkMap manager; // Akarin - private -> public
|
public final PlayerChunkMap manager; // Akarin - private -> public
|
||||||
// private final Set<NextTickListEntry> nextTickListHash = Sets.newHashSet();
|
// private final Set<NextTickListEntry> nextTickListHash = Sets.newHashSet();
|
||||||
private final HashTreeSet<NextTickListEntry> nextTickList = new HashTreeSet<NextTickListEntry>(); // CraftBukkit - HashTreeSet
|
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;
|
public boolean savingDisabled;
|
||||||
private boolean Q;
|
private boolean Q;
|
||||||
private int emptyTime;
|
private int emptyTime;
|
||||||
@@ -52,6 +53,10 @@ public class WorldServer extends World implements IAsyncTaskHandler {
|
|||||||
private final List<NextTickListEntry> W = Lists.newArrayList();
|
private final List<NextTickListEntry> W = Lists.newArrayList();
|
||||||
|
|
||||||
// CraftBukkit start
|
// 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;
|
public final int dimension;
|
||||||
|
|
||||||
// Add env and gen to constructor
|
// Add env and gen to constructor
|
||||||
@@ -1181,6 +1186,7 @@ public class WorldServer extends World implements IAsyncTaskHandler {
|
|||||||
private boolean j(Entity entity) {
|
private boolean j(Entity entity) {
|
||||||
if (entity.dead) {
|
if (entity.dead) {
|
||||||
WorldServer.a.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.a(entity)); // CraftBukkit // Paper
|
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;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
UUID uuid = entity.getUniqueID();
|
UUID uuid = entity.getUniqueID();
|
||||||
@@ -1188,12 +1194,21 @@ public class WorldServer extends World implements IAsyncTaskHandler {
|
|||||||
if (this.entitiesByUUID.containsKey(uuid)) {
|
if (this.entitiesByUUID.containsKey(uuid)) {
|
||||||
Entity entity1 = this.entitiesByUUID.get(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);
|
this.f.remove(entity1);
|
||||||
} else {
|
} else {
|
||||||
if (!(entity instanceof EntityHuman)) {
|
if (!(entity instanceof EntityHuman)) {
|
||||||
WorldServer.a.error("Keeping entity {} that already exists with UUID {} - " + entity1, EntityTypes.a(entity1), uuid.toString()); // CraftBukkit // Paper
|
if (entity.world.paperConfig.duplicateUUIDMode != com.destroystokyo.paper.PaperWorldConfig.DuplicateUUIDMode.NOTHING) {
|
||||||
WorldServer.a.error("Deleting duplicate entity {}", entity); // Paper
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1211,7 +1226,24 @@ public class WorldServer extends World implements IAsyncTaskHandler {
|
|||||||
protected void b(Entity entity) {
|
protected void b(Entity entity) {
|
||||||
super.b(entity);
|
super.b(entity);
|
||||||
this.entitiesById.a(entity.getId(), 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();
|
Entity[] aentity = entity.bb();
|
||||||
|
|
||||||
if (aentity != null) {
|
if (aentity != null) {
|
||||||
|
|||||||
@@ -1179,11 +1179,32 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
|||||||
for (EntityPlayer player : players) {
|
for (EntityPlayer player : players) {
|
||||||
player.getBukkitEntity().reregisterPlayer(self);
|
player.getBukkitEntity().reregisterPlayer(self);
|
||||||
}
|
}
|
||||||
|
refreshPlayer();
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public PlayerProfile getPlayerProfile() {
|
public PlayerProfile getPlayerProfile() {
|
||||||
return new CraftPlayerProfile(this).clone();
|
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
|
// Paper end
|
||||||
|
|
||||||
public void removeDisconnectingPlayer(Player player) {
|
public void removeDisconnectingPlayer(Player player) {
|
||||||
|
|||||||
Submodule work/Paper updated: ca2209ff20...8b96ee7ea8
Reference in New Issue
Block a user