Files
CatServer/patches/net/minecraft/server/management/PlayerList.java.patch

1262 lines
64 KiB
Diff

--- ../src-base/minecraft/net/minecraft/server/management/PlayerList.java
+++ ../src-work/minecraft/net/minecraft/server/management/PlayerList.java
@@ -1,5 +1,7 @@
package net.minecraft.server.management;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
@@ -8,6 +10,8 @@
import java.io.File;
import java.net.SocketAddress;
import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -27,6 +31,7 @@
import net.minecraft.network.play.server.SPacketChat;
import net.minecraft.network.play.server.SPacketCustomPayload;
import net.minecraft.network.play.server.SPacketEntityEffect;
+import net.minecraft.network.play.server.SPacketEntityMetadata;
import net.minecraft.network.play.server.SPacketEntityStatus;
import net.minecraft.network.play.server.SPacketHeldItemChange;
import net.minecraft.network.play.server.SPacketJoinGame;
@@ -45,6 +50,7 @@
import net.minecraft.scoreboard.ServerScoreboard;
import net.minecraft.scoreboard.Team;
import net.minecraft.server.MinecraftServer;
+import net.minecraft.server.network.NetHandlerLoginServer;
import net.minecraft.stats.StatList;
import net.minecraft.stats.StatisticsManagerServer;
import net.minecraft.util.math.BlockPos;
@@ -52,7 +58,7 @@
import net.minecraft.util.text.ChatType;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentTranslation;
-import net.minecraft.util.text.TextFormatting;
+import net.minecraft.util.text.translation.I18n;
import net.minecraft.world.DimensionType;
import net.minecraft.world.GameType;
import net.minecraft.world.World;
@@ -66,6 +72,23 @@
import net.minecraftforge.fml.relauncher.SideOnly;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.TravelAgent;
+import org.bukkit.craftbukkit.CraftServer;
+import org.bukkit.craftbukkit.CraftWorld;
+import org.bukkit.craftbukkit.chunkio.ChunkIOExecutor;
+import org.bukkit.craftbukkit.util.CraftChatMessage;
+import org.bukkit.entity.Player;
+import org.bukkit.event.player.PlayerChangedWorldEvent;
+import org.bukkit.event.player.PlayerJoinEvent;
+import org.bukkit.event.player.PlayerLoginEvent;
+import org.bukkit.event.player.PlayerPortalEvent;
+import org.bukkit.event.player.PlayerQuitEvent;
+import org.bukkit.event.player.PlayerRespawnEvent;
+import org.bukkit.event.player.PlayerTeleportEvent;
+import org.bukkit.util.Vector;
+import org.spigotmc.event.player.PlayerSpawnLocationEvent;
public abstract class PlayerList
{
@@ -76,7 +99,7 @@
private static final Logger LOGGER = LogManager.getLogger();
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss z");
private final MinecraftServer mcServer;
- private final List<EntityPlayerMP> playerEntityList = Lists.<EntityPlayerMP>newArrayList();
+ public final List<EntityPlayerMP> playerEntityList = new java.util.concurrent.CopyOnWriteArrayList<>(); // CraftBukkit - ArrayList -> CopyOnWriteArrayList: Iterator safety
private final Map<UUID, EntityPlayerMP> uuidToPlayerMap = Maps.<UUID, EntityPlayerMP>newHashMap();
private final UserListBans bannedPlayers;
private final UserListIPBans bannedIPs;
@@ -84,7 +107,7 @@
private final UserListWhitelist whiteListedPlayers;
private final Map<UUID, StatisticsManagerServer> playerStatFiles;
private final Map<UUID, PlayerAdvancements> advancements;
- private IPlayerFileData playerDataManager;
+ public IPlayerFileData playerDataManager;
private boolean whiteListEnforced;
protected int maxPlayers;
private int viewDistance;
@@ -92,6 +115,8 @@
private boolean commandsAllowedForAll;
private int playerPingIndex;
+ private CraftServer cserver;
+
public PlayerList(MinecraftServer server)
{
this.bannedPlayers = new UserListBans(FILE_PLAYERBANS);
@@ -106,8 +131,22 @@
this.maxPlayers = 8;
}
- public void initializeConnectionToPlayer(NetworkManager netManager, EntityPlayerMP playerIn)
+ // CatServer start
+ public PlayerList initCraftServer() {
+ this.cserver = mcServer.server = new CraftServer(mcServer, this);
+ mcServer.console = org.bukkit.craftbukkit.command.ColouredConsoleSender.getInstance();
+ return this;
+ }
+ // CatServer end
+
+ public void initializeConnectionToPlayer(NetworkManager netManager, EntityPlayerMP playerIn, NetHandlerPlayServer nethandlerplayserver)
{
+ // CatServer start
+ if (this.playerEntityList.stream().anyMatch(p -> p.getName().toLowerCase(java.util.Locale.ROOT).equals(playerIn.getName().toLowerCase(java.util.Locale.ROOT)) || p.getUniqueID().equals(playerIn.getUniqueID()))) {
+ nethandlerplayserver.disconnect(new TextComponentTranslation("multiplayer.disconnect.duplicate_login", new Object[0]));
+ return;
+ }
+ // CatServer end
GameProfile gameprofile = playerIn.getGameProfile();
PlayerProfileCache playerprofilecache = this.mcServer.getPlayerProfileCache();
GameProfile gameprofile1 = playerprofilecache.getProfileByUUID(gameprofile.getId());
@@ -115,6 +154,24 @@
playerprofilecache.addEntry(gameprofile);
NBTTagCompound nbttagcompound = this.readPlayerDataFromFile(playerIn);
playerIn.setWorld(this.mcServer.getWorld(playerIn.dimension));
+
+ World playerWorld = this.mcServer.getWorld(playerIn.dimension);
+ if (playerWorld == null)
+ {
+ playerIn.dimension = 0;
+ playerWorld = this.mcServer.getWorld(0);
+ BlockPos spawnPoint = playerWorld.provider.getRandomizedSpawnPoint();
+ playerIn.setPosition(spawnPoint.getX(), spawnPoint.getY(), spawnPoint.getZ());
+ }
+
+ // CraftBukkit start - Better rename detection
+ if (nbttagcompound != null && nbttagcompound.hasKey("bukkit")) {
+ NBTTagCompound bukkit = nbttagcompound.getCompoundTag("bukkit");
+ s = bukkit.hasKey("lastKnownName", 8) ? bukkit.getString("lastKnownName") : s;
+ }
+ // CraftBukkit end
+
+ playerIn.setWorld(playerWorld);
playerIn.interactionManager.setWorld((WorldServer)playerIn.world);
String s1 = "local";
@@ -123,12 +180,33 @@
s1 = netManager.getRemoteAddress().toString();
}
- LOGGER.info("{}[{}] logged in with entity id {} at ({}, {}, {})", playerIn.getName(), s1, Integer.valueOf(playerIn.getEntityId()), Double.valueOf(playerIn.posX), Double.valueOf(playerIn.posY), Double.valueOf(playerIn.posZ));
+ catserver.server.PlayerDataFixer.checkLocation(playerIn); // CatServer - fix invalid location
+ catserver.server.PlayerDataFixer.checkHealth(playerIn); // CatServer - fix invalid health
+
+ // Spigot start - spawn location event
+ Player bukkitPlayer = playerIn.getBukkitEntity();
+ PlayerSpawnLocationEvent ev = new PlayerSpawnLocationEvent(bukkitPlayer, bukkitPlayer.getLocation());
+ Bukkit.getPluginManager().callEvent(ev);
+
+ Location loc = ev.getSpawnLocation();
+ WorldServer world = ((CraftWorld) loc.getWorld()).getHandle();
+
+ playerIn.setWorld(world);
+ playerIn.setPosition(loc.getX(), loc.getY(), loc.getZ());
+ playerIn.setRotation(loc.getYaw(), loc.getPitch());
+ // Spigot end
+
+
+ // CraftBukkit - Moved message to after join
+ // LOGGER.info("{}[{}] logged in with entity id {} at ({}, {}, {})", playerIn.getName(), s1, Integer.valueOf(playerIn.getEntityId()), Double.valueOf(playerIn.posX), Double.valueOf(playerIn.posY), Double.valueOf(playerIn.posZ));
WorldServer worldserver = this.mcServer.getWorld(playerIn.dimension);
WorldInfo worldinfo = worldserver.getWorldInfo();
this.setPlayerGameTypeBasedOnOther(playerIn, (EntityPlayerMP)null, worldserver);
- NetHandlerPlayServer nethandlerplayserver = new NetHandlerPlayServer(this.mcServer, netManager, playerIn);
- nethandlerplayserver.sendPacket(new SPacketJoinGame(playerIn.getEntityId(), playerIn.interactionManager.getGameType(), worldinfo.isHardcoreModeEnabled(), worldserver.provider.getDimensionType().getId(), worldserver.getDifficulty(), this.getMaxPlayers(), worldinfo.getTerrainType(), worldserver.getGameRules().getBoolean("reducedDebugInfo")));
+ playerIn.connection = nethandlerplayserver;
+ catserver.server.CatServerNetwork.registerBukkitWorldToClient(playerIn, playerIn.dimension); // send DimensionRegisterMessage to client before attempting to login to a Bukkit dimension
+ net.minecraftforge.fml.common.FMLCommonHandler.instance().fireServerConnectionEvent(netManager);
+ nethandlerplayserver.sendPacket(new SPacketJoinGame(playerIn.getEntityId(), playerIn.interactionManager.getGameType(), worldinfo.isHardcoreModeEnabled(), worldserver.provider.getDimension(), worldserver.getDifficulty(), this.getMaxPlayers(), worldinfo.getTerrainType(), worldserver.getGameRules().getBoolean("reducedDebugInfo")));
+ playerIn.getBukkitEntity().sendSupportedChannels(); // CraftBukkit
nethandlerplayserver.sendPacket(new SPacketCustomPayload("MC|Brand", (new PacketBuffer(Unpooled.buffer())).writeString(this.getServerInstance().getServerModName())));
nethandlerplayserver.sendPacket(new SPacketServerDifficulty(worldinfo.getDifficulty(), worldinfo.isDifficultyLocked()));
nethandlerplayserver.sendPacket(new SPacketPlayerAbilities(playerIn.capabilities));
@@ -138,20 +216,23 @@
playerIn.getRecipeBook().init(playerIn);
this.sendScoreboard((ServerScoreboard)worldserver.getScoreboard(), playerIn);
this.mcServer.refreshStatusNextTick();
- TextComponentTranslation textcomponenttranslation;
-
+ // CraftBukkit start - login message is handled in the event
+ // TextComponentTranslation textcomponenttranslation;
+ String joinMessage;
if (playerIn.getName().equalsIgnoreCase(s))
{
- textcomponenttranslation = new TextComponentTranslation("multiplayer.player.joined", new Object[] {playerIn.getDisplayName()});
+ // textcomponenttranslation = new TextComponentTranslation("multiplayer.player.joined", new Object[] {playerIn.getDisplayName()});
+ joinMessage = "\u00A7e" + I18n.translateToLocalFormatted("multiplayer.player.joined", playerIn.getName());
}
else
{
- textcomponenttranslation = new TextComponentTranslation("multiplayer.player.joined.renamed", new Object[] {playerIn.getDisplayName(), s});
+ // textcomponenttranslation = new TextComponentTranslation("multiplayer.player.joined.renamed", new Object[] {playerIn.getDisplayName(), s});
+ joinMessage = "\u00A7e" + I18n.translateToLocalFormatted("multiplayer.player.joined.renamed", playerIn.getName(), s);
}
- textcomponenttranslation.getStyle().setColor(TextFormatting.YELLOW);
- this.sendMessage(textcomponenttranslation);
- this.playerLoggedIn(playerIn);
+ // textcomponenttranslation.getStyle().setColor(TextFormatting.YELLOW);
+ // this.sendMessage(textcomponenttranslation);
+ this.playerLoggedIn(playerIn, joinMessage);
nethandlerplayserver.setPlayerLocation(playerIn.posX, playerIn.posY, playerIn.posZ, playerIn.rotationYaw, playerIn.rotationPitch);
this.updateTimeAndWeatherForPlayer(playerIn, worldserver);
@@ -204,9 +285,12 @@
}
playerIn.addSelfToInternalCraftingInventory();
+ net.minecraftforge.fml.common.FMLCommonHandler.instance().firePlayerLoggedIn(playerIn);
+ // CraftBukkit - Moved from above, added world
+ PlayerList.LOGGER.info(playerIn.getName() + "[" + s1 + "] logged in with entity id " + playerIn.getEntityId() + " at ([" + playerIn.world.worldInfo.getWorldName() + "]" + playerIn.posX + ", " + playerIn.posY + ", " + playerIn.posZ + ")");
}
- protected void sendScoreboard(ServerScoreboard scoreboardIn, EntityPlayerMP playerIn)
+ public void sendScoreboard(ServerScoreboard scoreboardIn, EntityPlayerMP playerIn)
{
Set<ScoreObjective> set = Sets.<ScoreObjective>newHashSet();
@@ -233,28 +317,29 @@
public void setPlayerManager(WorldServer[] worldServers)
{
+ if (playerDataManager != null) return;
this.playerDataManager = worldServers[0].getSaveHandler().getPlayerNBTManager();
worldServers[0].getWorldBorder().addListener(new IBorderListener()
{
public void onSizeChanged(WorldBorder border, double newSize)
{
- PlayerList.this.sendPacketToAllPlayers(new SPacketWorldBorder(border, SPacketWorldBorder.Action.SET_SIZE));
+ PlayerList.this.sendAll(new SPacketWorldBorder(border, SPacketWorldBorder.Action.SET_SIZE), border.world);
}
public void onTransitionStarted(WorldBorder border, double oldSize, double newSize, long time)
{
- PlayerList.this.sendPacketToAllPlayers(new SPacketWorldBorder(border, SPacketWorldBorder.Action.LERP_SIZE));
+ PlayerList.this.sendAll(new SPacketWorldBorder(border, SPacketWorldBorder.Action.LERP_SIZE), border.world);
}
public void onCenterChanged(WorldBorder border, double x, double z)
{
- PlayerList.this.sendPacketToAllPlayers(new SPacketWorldBorder(border, SPacketWorldBorder.Action.SET_CENTER));
+ PlayerList.this.sendAll(new SPacketWorldBorder(border, SPacketWorldBorder.Action.SET_CENTER), border.world);
}
public void onWarningTimeChanged(WorldBorder border, int newTime)
{
- PlayerList.this.sendPacketToAllPlayers(new SPacketWorldBorder(border, SPacketWorldBorder.Action.SET_WARNING_TIME));
+ PlayerList.this.sendAll(new SPacketWorldBorder(border, SPacketWorldBorder.Action.SET_WARNING_TIME), border.world);
}
public void onWarningDistanceChanged(WorldBorder border, int newDistance)
{
- PlayerList.this.sendPacketToAllPlayers(new SPacketWorldBorder(border, SPacketWorldBorder.Action.SET_WARNING_BLOCKS));
+ PlayerList.this.sendAll(new SPacketWorldBorder(border, SPacketWorldBorder.Action.SET_WARNING_BLOCKS), border.world);
}
public void onDamageAmountChanged(WorldBorder border, double newAmount)
{
@@ -296,7 +381,7 @@
@Nullable
public NBTTagCompound readPlayerDataFromFile(EntityPlayerMP playerIn)
{
- NBTTagCompound nbttagcompound = this.mcServer.worlds[0].getWorldInfo().getPlayerNBTTagCompound();
+ NBTTagCompound nbttagcompound = this.mcServer.worldServerList.get(0).getWorldInfo().getPlayerNBTTagCompound();
NBTTagCompound nbttagcompound1;
if (playerIn.getName().equals(this.mcServer.getServerOwner()) && nbttagcompound != null)
@@ -304,6 +389,7 @@
nbttagcompound1 = nbttagcompound;
playerIn.readFromNBT(nbttagcompound);
LOGGER.debug("loading single player");
+ net.minecraftforge.event.ForgeEventFactory.firePlayerLoadingEvent(playerIn, this.playerDataManager, playerIn.getUniqueID().toString());
}
else
{
@@ -313,8 +399,24 @@
return nbttagcompound1;
}
+ public NBTTagCompound getPlayerNBT(EntityPlayerMP player)
+ {
+ // Hacky method to allow loading the NBT for a player prior to login
+ NBTTagCompound nbttagcompound = this.mcServer.worldServerList.get(0).getWorldInfo().getPlayerNBTTagCompound();
+ if (player.getName().equals(this.mcServer.getServerOwner()) && nbttagcompound != null)
+ {
+ return nbttagcompound;
+ }
+ else
+ {
+ return ((net.minecraft.world.storage.SaveHandler)this.playerDataManager).getPlayerNBT(player);
+ }
+ }
+
protected void writePlayerData(EntityPlayerMP playerIn)
{
+ if (playerIn.connection == null) return;
+
this.playerDataManager.writePlayerData(playerIn);
StatisticsManagerServer statisticsmanagerserver = this.playerStatFiles.get(playerIn.getUniqueID());
@@ -343,19 +445,90 @@
playerIn.connection.sendPacket(new SPacketPlayerListItem(SPacketPlayerListItem.Action.ADD_PLAYER, new EntityPlayerMP[] {this.playerEntityList.get(i)}));
}
+ net.minecraftforge.common.chunkio.ChunkIOExecutor.adjustPoolSize(this.getCurrentPlayerCount());
worldserver.spawnEntity(playerIn);
this.preparePlayer(playerIn, (WorldServer)null);
}
+ public void playerLoggedIn(EntityPlayerMP playerIn, String joinMessage)
+ {
+ this.playerEntityList.add(playerIn);
+ this.uuidToPlayerMap.put(playerIn.getUniqueID(), playerIn);
+ // this.sendPacketToAllPlayers(new SPacketPlayerListItem(SPacketPlayerListItem.Action.ADD_PLAYER, new EntityPlayerMP[] {playerIn})); // CraftBukkit - replaced with loop below
+ WorldServer worldserver = this.mcServer.getWorld(playerIn.dimension);
+
+ PlayerJoinEvent playerJoinEvent = new PlayerJoinEvent(cserver.getPlayer(playerIn), joinMessage);
+ cserver.getPluginManager().callEvent(playerJoinEvent);
+
+ if (!playerIn.connection.netManager.isChannelOpen()) {
+ return;
+ }
+
+ joinMessage = playerJoinEvent.getJoinMessage();
+
+ if (joinMessage != null && joinMessage.length() > 0) {
+ for (ITextComponent line : org.bukkit.craftbukkit.util.CraftChatMessage.fromString(joinMessage)) {
+ mcServer.getPlayerList().sendPacketToAllPlayers(new SPacketChat(line));
+ }
+ }
+
+ ChunkIOExecutor.adjustPoolSize(getCurrentPlayerCount());
+
+ // CraftBukkit start - sendAll above replaced with this loop
+ SPacketPlayerListItem packet = new SPacketPlayerListItem(SPacketPlayerListItem.Action.ADD_PLAYER, playerIn);
+ for (int i = 0; i < this.playerEntityList.size(); ++i)
+ {
+ // playerIn.connection.sendPacket(new SPacketPlayerListItem(SPacketPlayerListItem.Action.ADD_PLAYER, new EntityPlayerMP[] {this.playerEntityList.get(i)}));
+ EntityPlayerMP entityplayer1 = this.playerEntityList.get(i);
+
+ if (entityplayer1.getBukkitEntity().canSee(playerIn.getBukkitEntity())) {
+ entityplayer1.connection.sendPacket(packet);
+ }
+
+ if (!playerIn.getBukkitEntity().canSee(entityplayer1.getBukkitEntity())) {
+ continue;
+ }
+
+ playerIn.connection.sendPacket(new SPacketPlayerListItem(SPacketPlayerListItem.Action.ADD_PLAYER, new EntityPlayerMP[] { entityplayer1}));
+ }
+ playerIn.sentListPacket = true;
+ // CraftBukkit end
+
+ playerIn.connection.sendPacket(new SPacketEntityMetadata(playerIn.getEntityId(), playerIn.getDataManager(), true)); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn
+ net.minecraftforge.common.chunkio.ChunkIOExecutor.adjustPoolSize(this.getCurrentPlayerCount());
+ // CraftBukkit start - Only add if the player wasn't moved in the event
+ if (playerIn.world == worldserver && !worldserver.playerEntities.contains(playerIn)) {
+ worldserver.spawnEntity(playerIn);
+ this.preparePlayer(playerIn, null);
+ }
+ // CraftBukkit end
+ }
+
public void serverUpdateMovingPlayer(EntityPlayerMP playerIn)
{
playerIn.getServerWorld().getPlayerChunkMap().updateMovingPlayer(playerIn);
}
- public void playerLoggedOut(EntityPlayerMP playerIn)
+ public String playerLoggedOut(EntityPlayerMP playerIn)
{
+ if (catserver.server.AsyncCatcher.checkAsync("kick player")) return catserver.server.AsyncCatcher.ensureExecuteOnPrimaryThread(() -> playerLoggedOut(playerIn)); // CatServer
+ String quitMessage = null;
+ net.minecraftforge.fml.common.FMLCommonHandler.instance().firePlayerLoggedOut(playerIn);
WorldServer worldserver = playerIn.getServerWorld();
playerIn.addStat(StatList.LEAVE_GAME);
+
+ // CraftBukkit start - Quitting must be before we do final save of data, in case plugins need to modify it
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleInventoryCloseEvent(playerIn);
+ if(playerIn.connection != null) { // CatServer - fix crash when player is Forge Handshake
+ PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(playerIn), "\u00A7e" + playerIn.getName() + " left the game");
+ cserver.getPluginManager().callEvent(playerQuitEvent);
+ playerIn.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage());
+
+ playerIn.onUpdateEntity();// SPIGOT-924
+ quitMessage = playerQuitEvent.getQuitMessage();
+ }
+ // CraftBukkit end
+
this.writePlayerData(playerIn);
if (playerIn.isRiding())
@@ -376,6 +549,7 @@
worldserver.getChunkFromChunkCoords(playerIn.chunkCoordX, playerIn.chunkCoordZ).markDirty();
}
}
+ net.minecraftforge.common.chunkio.ChunkIOExecutor.adjustPoolSize(this.getCurrentPlayerCount());
worldserver.removeEntity(playerIn);
worldserver.getPlayerChunkMap().removePlayer(playerIn);
@@ -391,7 +565,23 @@
this.advancements.remove(uuid);
}
- this.sendPacketToAllPlayers(new SPacketPlayerListItem(SPacketPlayerListItem.Action.REMOVE_PLAYER, new EntityPlayerMP[] {playerIn}));
+ // this.sendPacketToAllPlayers(new SPacketPlayerListItem(SPacketPlayerListItem.Action.REMOVE_PLAYER, new EntityPlayerMP[] {playerIn}));
+ SPacketPlayerListItem packet = new SPacketPlayerListItem(SPacketPlayerListItem.Action.REMOVE_PLAYER, playerIn);
+ for (int i = 0; i < playerEntityList.size(); i++) {
+ EntityPlayerMP entityplayer2 = (EntityPlayerMP) this.playerEntityList.get(i);
+
+ if (entityplayer2.getBukkitEntity().canSee(playerIn.getBukkitEntity())) {
+ entityplayer2.connection.sendPacket(packet);
+ } else {
+ entityplayer2.getBukkitEntity().removeDisconnectingPlayer(playerIn.getBukkitEntity());
+ }
+ }
+ // This removes the scoreboard (and player reference) for the specific player in the manager
+ cserver.getScoreboardManager().removePlayer(playerIn.getBukkitEntity());
+
+ ChunkIOExecutor.adjustPoolSize(this.getCurrentPlayerCount());
+
+ return quitMessage;
}
public String allowUserToConnect(SocketAddress address, GameProfile profile)
@@ -430,6 +620,87 @@
}
}
+ @Nullable
+ public EntityPlayerMP allowUserToConnect(NetHandlerLoginServer loginServer, GameProfile profile, String hostname)
+ {
+ // Moved from processLogin
+ UUID uuid = EntityPlayer.getUUID(profile);
+ ArrayList<EntityPlayerMP> arraylist = Lists.newArrayList();
+
+ EntityPlayerMP entityplayer;
+
+ for (int i = 0; i < this.playerEntityList.size(); ++i) {
+ entityplayer = (EntityPlayerMP) this.playerEntityList.get(i);
+ if (entityplayer.getUniqueID().equals(uuid)) {
+ arraylist.add(entityplayer);
+ }
+ }
+
+ Iterator<EntityPlayerMP> iterator = arraylist.iterator();
+
+ while (iterator.hasNext()) {
+ entityplayer = (EntityPlayerMP) iterator.next();
+ writePlayerData(entityplayer); // CraftBukkit - Force the player's inventory to be saved
+ entityplayer.connection.disconnect(new TextComponentTranslation("multiplayer.disconnect.duplicate_login", new Object[0]));
+ }
+
+ // Instead of kicking then returning, we need to store the kick reason
+ // in the event, check with plugins to see if it's ok, and THEN kick
+ // depending on the outcome.
+ SocketAddress socketaddress = loginServer.networkManager.getRemoteAddress();
+
+ EntityPlayerMP entity = new EntityPlayerMP(mcServer, mcServer.getWorldServer(0), profile, new PlayerInteractionManager(mcServer.getWorldServer(0)));
+ Player player = entity.getBukkitEntity();
+ //Spigot Start
+ PlayerLoginEvent event = new PlayerLoginEvent(player, hostname, ((java.net.InetSocketAddress) socketaddress).getAddress(), ((java.net.InetSocketAddress) loginServer.networkManager.getRawAddress()).getAddress());
+ //Spigot End
+ if (getBannedPlayers().isBanned(profile) && !getBannedPlayers().getEntry(profile).hasBanExpired())
+ {
+ UserListBansEntry userlistbansentry = (UserListBansEntry)this.bannedPlayers.getEntry(profile);
+ String s1 = "You are banned from this server!\nReason: " + userlistbansentry.getBanReason();
+
+ if (userlistbansentry.getBanEndDate() != null)
+ {
+ s1 = s1 + "\nYour ban will be removed on " + DATE_FORMAT.format(userlistbansentry.getBanEndDate());
+ }
+
+ // return s1;
+ event.disallow(PlayerLoginEvent.Result.KICK_BANNED, s1);
+ }
+ else if (!this.canJoin(profile))
+ {
+ // return "You are not white-listed on this server!";
+ event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot
+ }
+ else if (getBannedIPs().isBanned(socketaddress) && !getBannedIPs().getBanEntry(socketaddress).hasBanExpired())
+ {
+ UserListIPBansEntry userlistipbansentry = this.bannedIPs.getBanEntry(socketaddress);
+ String s = "Your IP address is banned from this server!\nReason: " + userlistipbansentry.getBanReason();
+
+ if (userlistipbansentry.getBanEndDate() != null)
+ {
+ s = s + "\nYour ban will be removed on " + DATE_FORMAT.format(userlistipbansentry.getBanEndDate());
+ }
+
+ // return s;
+ if (!userlistipbansentry.hasBanExpired()) event.disallow(PlayerLoginEvent.Result.KICK_BANNED, s);
+ }
+ else
+ {
+ // return this.playerEntityList.size() >= this.maxPlayers && !this.bypassesPlayerLimit(profile) ? "The server is full!" : null;
+ if (this.playerEntityList.size() >= this.maxPlayers && !this.bypassesPlayerLimit(profile)) {
+ event.disallow(PlayerLoginEvent.Result.KICK_FULL, org.spigotmc.SpigotConfig.serverFullMessage); // Spigot
+ }
+ }
+
+ cserver.getPluginManager().callEvent(event);
+ if (event.getResult() != PlayerLoginEvent.Result.ALLOWED) {
+ loginServer.disconnect(event.getKickMessage());
+ return null;
+ }
+ return entity;
+ }
+
public EntityPlayerMP createPlayerForUser(GameProfile profile)
{
UUID uuid = EntityPlayer.getUUID(profile);
@@ -471,15 +742,99 @@
return new EntityPlayerMP(this.mcServer, this.mcServer.getWorld(0), profile, playerinteractionmanager);
}
+ public EntityPlayerMP createPlayerForUser(GameProfile profile, EntityPlayerMP entityPlayerMP)
+ {
+ /* CraftBukkit - Moved up
+ UUID uuid = EntityPlayer.getUUID(profile);
+ List<EntityPlayerMP> list = Lists.<EntityPlayerMP>newArrayList();
+
+ for (int i = 0; i < this.playerEntityList.size(); ++i)
+ {
+ EntityPlayerMP entityplayermp = this.playerEntityList.get(i);
+
+ if (entityplayermp.getUniqueID().equals(uuid))
+ {
+ list.add(entityplayermp);
+ }
+ }
+
+ EntityPlayerMP entityplayermp2 = this.uuidToPlayerMap.get(profile.getId());
+
+ if (entityplayermp2 != null && !list.contains(entityplayermp2))
+ {
+ list.add(entityplayermp2);
+ }
+
+ for (EntityPlayerMP entityplayermp1 : list)
+ {
+ entityplayermp1.connection.disconnect(new TextComponentTranslation("multiplayer.disconnect.duplicate_login", new Object[0]));
+ }
+
+ PlayerInteractionManager playerinteractionmanager;
+
+ if (this.mcServer.isDemo())
+ {
+ playerinteractionmanager = new DemoPlayerInteractionManager(this.mcServer.getWorld(0));
+ }
+ else
+ {
+ playerinteractionmanager = new PlayerInteractionManager(this.mcServer.getWorld(0));
+ }
+
+ return new EntityPlayerMP(this.mcServer, this.mcServer.getWorld(0), profile, playerinteractionmanager);
+ */
+ return entityPlayerMP;
+ }
+
public EntityPlayerMP recreatePlayerEntity(EntityPlayerMP playerIn, int dimension, boolean conqueredEnd)
{
+ return this.moveToWorld(playerIn, dimension, conqueredEnd, null, true);
+ }
+
+ public EntityPlayerMP moveToWorld(EntityPlayerMP playerIn, int dimension, boolean conqueredEnd, Location location, boolean avoidSuffocation) {
+ playerIn.dismountRidingEntity(); // CraftBukkit
+ World world = mcServer.getWorld(dimension);
+ if (world == null)
+ {
+ dimension = playerIn.getSpawnDimension();
+ }
+ else if (location == null && !world.provider.canRespawnHere())
+ {
+ dimension = world.provider.getRespawnDimension(playerIn);
+ }
+ if (mcServer.getWorld(dimension) == null) dimension = 0;
+
+ // handle return from End
+ if (conqueredEnd && location == null)
+ {
+ WorldServer exitWorld = this.mcServer.getWorld(dimension);
+ Location enter = playerIn.getBukkitEntity().getLocation();
+ Location exit = null;
+ // THE_END -> NORMAL; use bed if available, otherwise default spawn
+ exit = playerIn.getBukkitEntity().getBedSpawnLocation();
+
+ if (exit == null || ((CraftWorld) exit.getWorld()).getHandle().dimension != 0)
+ {
+ exit = exitWorld.getWorld().getSpawnLocation();
+ }
+ PlayerPortalEvent event = new PlayerPortalEvent(playerIn.getBukkitEntity(), enter, exit, org.bukkit.craftbukkit.CraftTravelAgent.DEFAULT, PlayerPortalEvent.TeleportCause.END_PORTAL);
+ event.useTravelAgent(false);
+ Bukkit.getServer().getPluginManager().callEvent(event);
+ if (event.isCancelled() || event.getTo() == null)
+ {
+ return null;
+ }
+ location = event.getTo();
+ }
+
playerIn.getServerWorld().getEntityTracker().removePlayerFromTrackers(playerIn);
- playerIn.getServerWorld().getEntityTracker().untrack(playerIn);
+ // playerIn.getServerWorld().getEntityTracker().untrack(playerIn);
playerIn.getServerWorld().getPlayerChunkMap().removePlayer(playerIn);
this.playerEntityList.remove(playerIn);
this.mcServer.getWorld(playerIn.dimension).removeEntityDangerously(playerIn);
- BlockPos blockpos = playerIn.getBedLocation();
- boolean flag = playerIn.isSpawnForced();
+ BlockPos blockpos = playerIn.getBedLocation(dimension);
+ boolean flag1 = playerIn.isSpawnForced(dimension);
+ /* CraftBukkit start
playerIn.dimension = dimension;
PlayerInteractionManager playerinteractionmanager;
@@ -493,8 +848,14 @@
}
EntityPlayerMP entityplayermp = new EntityPlayerMP(this.mcServer, this.mcServer.getWorld(playerIn.dimension), playerIn.getGameProfile(), playerinteractionmanager);
+ */
+ EntityPlayerMP entityplayermp = playerIn;
+ org.bukkit.World fromWorld = playerIn.getBukkitEntity().getWorld();
+ playerIn.queuedEndExit = false;
+
entityplayermp.connection = playerIn.connection;
entityplayermp.copyFrom(playerIn, conqueredEnd);
+ entityplayermp.dimension = dimension;
entityplayermp.setEntityId(playerIn.getEntityId());
entityplayermp.setCommandStats(playerIn);
entityplayermp.setPrimaryHand(playerIn.getPrimaryHand());
@@ -504,44 +865,103 @@
entityplayermp.addTag(s);
}
- WorldServer worldserver = this.mcServer.getWorld(playerIn.dimension);
- this.setPlayerGameTypeBasedOnOther(entityplayermp, playerIn, worldserver);
+ // WorldServer worldserver = this.mcServer.getWorld(playerIn.dimension); // CraftBukkit - handled later
+ // this.setPlayerGameTypeBasedOnOther(entityplayermp, playerIn, worldserver);
+ BlockPos blockposition1;
+ // CraftBukkit start - fire PlayerRespawnEvent
+ if (location == null) {
+ boolean isBedSpawn = false;
+ CraftWorld cworld = (CraftWorld) this.mcServer.server.getWorld(playerIn.spawnWorld);
+ if (cworld != null && blockpos != null) {
+ blockposition1 = EntityPlayer.getBedSpawnLocation(cworld.getHandle(), blockpos, flag1);
+ if (blockposition1 != null) {
+ isBedSpawn = true;
+ location = new Location(cworld, (double) ((float) blockposition1.getX() + 0.5F), (double) ((float) blockposition1.getY() + 0.1F), (double) ((float) blockposition1.getZ() + 0.5F));
+ } else {
+ entityplayermp.setSpawnPoint(null, true);
+ entityplayermp.connection.sendPacket(new SPacketChangeGameState(0, 0.0F));
+ }
+ }
- if (blockpos != null)
- {
- BlockPos blockpos1 = EntityPlayer.getBedSpawnLocation(this.mcServer.getWorld(playerIn.dimension), blockpos, flag);
-
- if (blockpos1 != null)
- {
- entityplayermp.setLocationAndAngles((double)((float)blockpos1.getX() + 0.5F), (double)((float)blockpos1.getY() + 0.1F), (double)((float)blockpos1.getZ() + 0.5F), 0.0F, 0.0F);
- entityplayermp.setSpawnPoint(blockpos, flag);
+ if (location == null) {
+ cworld = (CraftWorld) this.mcServer.server.getWorlds().get(0);
+ blockpos = entityplayermp.getSpawnPoint(this.mcServer, cworld.getHandle());
+ location = new Location(cworld, (double) ((float) blockpos.getX() + 0.5F), (double) ((float) blockpos.getY() + 0.1F), (double) ((float) blockpos.getZ() + 0.5F));
}
- else
- {
- entityplayermp.connection.sendPacket(new SPacketChangeGameState(0, 0.0F));
+ Player respawnPlayer = cserver.getPlayer(entityplayermp);
+ PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn);
+ cserver.getPluginManager().callEvent(respawnEvent);
+ // Spigot Start
+ if (playerIn.connection.isDisconnected()) {
+ return playerIn;
}
+ // Spigot End
+
+
+ location = respawnEvent.getRespawnLocation();
+ playerIn.reset();
+ } else {
+ location.setWorld(mcServer.getWorld(dimension).getWorld());
}
+ WorldServer worldserver = ((CraftWorld) location.getWorld()).getHandle();
+ entityplayermp.forceSetPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
+
worldserver.getChunkProvider().provideChunk((int)entityplayermp.posX >> 4, (int)entityplayermp.posZ >> 4);
- while (!worldserver.getCollisionBoxes(entityplayermp, entityplayermp.getEntityBoundingBox()).isEmpty() && entityplayermp.posY < 256.0D)
+ while (avoidSuffocation && !worldserver.getCollisionBoxes(entityplayermp, entityplayermp.getEntityBoundingBox()).isEmpty() && entityplayermp.posY < 256.0D)
{
entityplayermp.setPosition(entityplayermp.posX, entityplayermp.posY + 1.0D, entityplayermp.posZ);
}
- entityplayermp.connection.sendPacket(new SPacketRespawn(entityplayermp.dimension, entityplayermp.world.getDifficulty(), entityplayermp.world.getWorldInfo().getTerrainType(), entityplayermp.interactionManager.getGameType()));
+ int actualDimension = worldserver.provider.getDimension();
+ catserver.server.CatServerNetwork.registerBukkitWorldToClient(entityplayermp, actualDimension); // CatServer - change dim for bukkit added dimensions
+ // entityplayermp.connection.sendPacket(new SPacketRespawn(entityplayermp.dimension, entityplayermp.world.getDifficulty(), entityplayermp.world.getWorldInfo().getTerrainType(), entityplayermp.interactionManager.getGameType()));
+ entityplayermp.connection.sendPacket(new SPacketRespawn(actualDimension, worldserver.getDifficulty(), worldserver.getWorldInfo().getTerrainType(), entityplayermp.interactionManager.getGameType()));
+ entityplayermp.setWorld(worldserver);
+ entityplayermp.isDead = false;
+ entityplayermp.connection.teleport(new Location(worldserver.getWorld(), entityplayermp.posX, entityplayermp.posY, entityplayermp.posZ, entityplayermp.rotationYaw, entityplayermp.rotationPitch));
+ entityplayermp.setSneaking(false);
BlockPos blockpos2 = worldserver.getSpawnPoint();
- entityplayermp.connection.setPlayerLocation(entityplayermp.posX, entityplayermp.posY, entityplayermp.posZ, entityplayermp.rotationYaw, entityplayermp.rotationPitch);
+ // entityplayermp.connection.setPlayerLocation(entityplayermp.posX, entityplayermp.posY, entityplayermp.posZ, entityplayermp.rotationYaw, entityplayermp.rotationPitch);
entityplayermp.connection.sendPacket(new SPacketSpawnPosition(blockpos2));
entityplayermp.connection.sendPacket(new SPacketSetExperience(entityplayermp.experience, entityplayermp.experienceTotal, entityplayermp.experienceLevel));
this.updateTimeAndWeatherForPlayer(entityplayermp, worldserver);
this.updatePermissionLevel(entityplayermp);
- worldserver.getPlayerChunkMap().addPlayer(entityplayermp);
- worldserver.spawnEntity(entityplayermp);
- this.playerEntityList.add(entityplayermp);
- this.uuidToPlayerMap.put(entityplayermp.getUniqueID(), entityplayermp);
- entityplayermp.addSelfToInternalCraftingInventory();
+ if (!playerIn.connection.isDisconnected()) {
+ worldserver.getPlayerChunkMap().addPlayer(entityplayermp);
+ worldserver.spawnEntity(entityplayermp);
+ this.playerEntityList.add(entityplayermp);
+ this.uuidToPlayerMap.put(entityplayermp.getUniqueID(), entityplayermp);
+ }
+ // entityplayermp.addSelfToInternalCraftingInventory();
entityplayermp.setHealth(entityplayermp.getHealth());
+ // Added from changeDimension
+ syncPlayerInventory(playerIn); // Update health, etc...
+ playerIn.sendPlayerAbilities();
+ for (Object o1 : playerIn.getActivePotionEffects()) {
+ PotionEffect mobEffect = (PotionEffect) o1;
+ playerIn.connection.sendPacket(new SPacketEntityEffect(playerIn.getEntityId(), mobEffect));
+ }
+
+ // Fire advancement trigger
+ CriteriaTriggers.CHANGED_DIMENSION.trigger(playerIn, ((CraftWorld) fromWorld).getHandle().provider.getDimensionType(), worldserver.provider.getDimensionType());
+ if (((CraftWorld) fromWorld).getHandle().provider.getDimensionType() == DimensionType.NETHER && worldserver.provider.getDimensionType() == DimensionType.OVERWORLD && playerIn.getEnteredNetherPosition() != null) {
+ CriteriaTriggers.NETHER_TRAVEL.trigger(playerIn, playerIn.getEnteredNetherPosition());
+ }
+
+ // Don't fire on respawn
+ if (fromWorld != location.getWorld()) {
+ PlayerChangedWorldEvent event = new PlayerChangedWorldEvent(playerIn.getBukkitEntity(), fromWorld);
+ mcServer.server.getPluginManager().callEvent(event);
+ }
+
+ // Save player file again if they were disconnected
+ if (playerIn.connection.isDisconnected()) {
+ this.writePlayerData(playerIn);
+ }
+ // CraftBukkit end
+ net.minecraftforge.fml.common.FMLCommonHandler.instance().firePlayerRespawnEvent(entityplayermp, conqueredEnd);
return entityplayermp;
}
@@ -549,44 +969,125 @@
{
GameProfile gameprofile = player.getGameProfile();
int i = this.canSendCommands(gameprofile) ? this.ops.getPermissionLevel(gameprofile) : 0;
- i = this.mcServer.isSinglePlayer() && this.mcServer.worlds[0].getWorldInfo().areCommandsAllowed() ? 4 : i;
+ i = this.mcServer.isSinglePlayer() && this.mcServer.worldServerList.get(0).getWorldInfo().areCommandsAllowed() ? 4 : i;
i = this.commandsAllowedForAll ? 4 : i;
this.sendPlayerPermissionLevel(player, i);
}
public void changePlayerDimension(EntityPlayerMP player, int dimensionIn)
{
- int i = player.dimension;
- WorldServer worldserver = this.mcServer.getWorld(player.dimension);
+ transferPlayerToDimension(player, dimensionIn, mcServer.getWorld(dimensionIn).getDefaultTeleporter());
+ }
+
+ // TODO: Remove (1.13)
+ public void transferPlayerToDimension(EntityPlayerMP player, int dimensionIn, net.minecraft.world.Teleporter teleporter)
+ {
+ transferPlayerToDimension(player, dimensionIn, (net.minecraftforge.common.util.ITeleporter) teleporter);
+ }
+
+ // CatServer start - Replaced the standard handling of portals with a more customised method.
+ public void transferPlayerToDimension(EntityPlayerMP player, int dimensionIn, net.minecraftforge.common.util.ITeleporter teleporter) {
+ transferPlayerToDimension(player, dimensionIn, (net.minecraftforge.common.util.ITeleporter) teleporter, PlayerTeleportEvent.TeleportCause.MOD);
+ }
+
+ public void transferPlayerToDimension(EntityPlayerMP player, int dimensionIn, net.minecraftforge.common.util.ITeleporter teleporter, PlayerTeleportEvent.TeleportCause cause)
+ {
+ WorldServer fromWorld = this.mcServer.getWorld(player.dimension);
+ WorldServer exitWorld = this.mcServer.getWorld(dimensionIn);
+
+ Location enter = player.getBukkitEntity().getLocation();
+ Location exit = null;
+ boolean useTravelAgent = false;
+ if (exitWorld != null) {
+ exit = this.calculateTarget(enter, exitWorld);
+ if (cause != cause.MOD) // don't use travel agent for custom dimensions
+ {
+ useTravelAgent = true;
+ }
+ }
+
+ TravelAgent agent = teleporter instanceof TravelAgent ? (TravelAgent)teleporter : org.bukkit.craftbukkit.CraftTravelAgent.DEFAULT; // return arbitrary TA to compensate for implementation dependent plugins
+
+ PlayerPortalEvent event = new PlayerPortalEvent(player.getBukkitEntity(), enter, exit, agent, cause);
+ event.useTravelAgent(useTravelAgent);
+ Bukkit.getServer().getPluginManager().callEvent(event);
+ if (event.isCancelled() || event.getTo() == null) {
+ return;
+ }
+
+ exit = event.useTravelAgent() && cause != cause.MOD ? event.getPortalTravelAgent().findOrCreate(event.getTo()) : event.getTo();
+ if (exit == null) {
+ return;
+ }
+ exitWorld = ((CraftWorld) exit.getWorld()).getHandle();
+
+ org.bukkit.event.player.PlayerTeleportEvent tpEvent = new org.bukkit.event.player.PlayerTeleportEvent(player.getBukkitEntity(), enter, exit, cause);
+ Bukkit.getServer().getPluginManager().callEvent(tpEvent);
+ if (tpEvent.isCancelled() || tpEvent.getTo() == null) {
+ return;
+ }
+
+ Vector velocity = player.getBukkitEntity().getVelocity();
+ exitWorld.getDefaultTeleporter().adjustExit(player, exit, velocity);
+
+ player.invulnerableDimensionChange = true; // CraftBukkit - Set teleport invulnerability only if player changing worlds
+
+ int fromDimension = player.dimension;
player.dimension = dimensionIn;
- WorldServer worldserver1 = this.mcServer.getWorld(player.dimension);
- player.connection.sendPacket(new SPacketRespawn(player.dimension, player.world.getDifficulty(), player.world.getWorldInfo().getTerrainType(), player.interactionManager.getGameType()));
+
+ catserver.server.CatServerNetwork.registerBukkitWorldToClient(player, player.dimension); // CatServer - change dim for bukkit added dimensions
+ player.connection.sendPacket(new SPacketRespawn(player.dimension, exitWorld.getDifficulty(), exitWorld.getWorldInfo().getTerrainType(), player.interactionManager.getGameType()));
this.updatePermissionLevel(player);
- worldserver.removeEntityDangerously(player);
+ fromWorld.removeEntityDangerously(player);
player.isDead = false;
- this.transferEntityToWorld(player, i, worldserver, worldserver1);
- this.preparePlayer(player, worldserver);
+ this.transferEntityToWorld(player, fromDimension, fromWorld, exitWorld, teleporter);
+ this.preparePlayer(player, fromWorld);
player.connection.setPlayerLocation(player.posX, player.posY, player.posZ, player.rotationYaw, player.rotationPitch);
- player.interactionManager.setWorld(worldserver1);
+ player.interactionManager.setWorld(exitWorld);
player.connection.sendPacket(new SPacketPlayerAbilities(player.capabilities));
- this.updateTimeAndWeatherForPlayer(player, worldserver1);
+ this.updateTimeAndWeatherForPlayer(player, exitWorld);
this.syncPlayerInventory(player);
for (PotionEffect potioneffect : player.getActivePotionEffects())
{
player.connection.sendPacket(new SPacketEntityEffect(player.getEntityId(), potioneffect));
}
+ // Fix MC-88179: on non-death SPacketRespawn, also resend attributes
+ net.minecraft.entity.ai.attributes.AttributeMap attributemap = (net.minecraft.entity.ai.attributes.AttributeMap) player.getAttributeMap();
+ java.util.Collection<net.minecraft.entity.ai.attributes.IAttributeInstance> watchedAttribs = attributemap.getWatchedAttributes();
+ if (!watchedAttribs.isEmpty()) player.connection.sendPacket(new net.minecraft.network.play.server.SPacketEntityProperties(player.getEntityId(), watchedAttribs));
+
+ net.minecraftforge.fml.common.FMLCommonHandler.instance().firePlayerChangedDimensionEvent(player, fromDimension, dimensionIn);
}
+ public void changeDimension(EntityPlayerMP player, int dimensionIn, PlayerTeleportEvent.TeleportCause cause) {
+ transferPlayerToDimension(player, dimensionIn, mcServer.getWorld(dimensionIn).getDefaultTeleporter(), cause);
+ }
+ // CatServer end
+
public void transferEntityToWorld(Entity entityIn, int lastDimension, WorldServer oldWorldIn, WorldServer toWorldIn)
{
- double d0 = entityIn.posX;
- double d1 = entityIn.posZ;
+ // transferEntityToWorld(entityIn, lastDimension, oldWorldIn, toWorldIn, toWorldIn.getDefaultTeleporter());
+ Location exit = this.calculateTarget(entityIn.getBukkitEntity().getLocation(), toWorldIn);
+ this.repositionEntity(entityIn, exit, true);
+ }
+
+ // TODO: Remove (1.13)
+ public void transferEntityToWorld(Entity entityIn, int lastDimension, WorldServer oldWorldIn, WorldServer toWorldIn, net.minecraft.world.Teleporter teleporter)
+ {
+ transferEntityToWorld(entityIn, lastDimension, oldWorldIn, toWorldIn, (net.minecraftforge.common.util.ITeleporter) teleporter);
+ }
+
+ public void transferEntityToWorld(Entity entityIn, int lastDimension, WorldServer oldWorldIn, WorldServer toWorldIn, net.minecraftforge.common.util.ITeleporter teleporter)
+ {
+ double moveFactor = oldWorldIn.provider.getMovementFactor() / toWorldIn.provider.getMovementFactor();
+ double d0 = MathHelper.clamp(entityIn.posX * moveFactor, toWorldIn.getWorldBorder().minX() + 16.0D, toWorldIn.getWorldBorder().maxX() - 16.0D);
+ double d1 = MathHelper.clamp(entityIn.posZ * moveFactor, toWorldIn.getWorldBorder().minZ() + 16.0D, toWorldIn.getWorldBorder().maxZ() - 16.0D);
double d2 = 8.0D;
float f = entityIn.rotationYaw;
oldWorldIn.profiler.startSection("moving");
- if (entityIn.dimension == -1)
+ if (false && entityIn.dimension == -1)
{
d0 = MathHelper.clamp(d0 / 8.0D, toWorldIn.getWorldBorder().minX() + 16.0D, toWorldIn.getWorldBorder().maxX() - 16.0D);
d1 = MathHelper.clamp(d1 / 8.0D, toWorldIn.getWorldBorder().minZ() + 16.0D, toWorldIn.getWorldBorder().maxZ() - 16.0D);
@@ -597,7 +1098,7 @@
oldWorldIn.updateEntityWithOptionalForce(entityIn, false);
}
}
- else if (entityIn.dimension == 0)
+ else if (false && entityIn.dimension == 0)
{
d0 = MathHelper.clamp(d0 * 8.0D, toWorldIn.getWorldBorder().minX() + 16.0D, toWorldIn.getWorldBorder().maxX() - 16.0D);
d1 = MathHelper.clamp(d1 * 8.0D, toWorldIn.getWorldBorder().minZ() + 16.0D, toWorldIn.getWorldBorder().maxZ() - 16.0D);
@@ -608,7 +1109,7 @@
oldWorldIn.updateEntityWithOptionalForce(entityIn, false);
}
}
- else
+ if (entityIn.dimension == 1 && teleporter.isVanilla())
{
BlockPos blockpos;
@@ -634,7 +1135,7 @@
oldWorldIn.profiler.endSection();
- if (lastDimension != 1)
+ if (lastDimension != 1 || !teleporter.isVanilla())
{
oldWorldIn.profiler.startSection("placing");
d0 = (double)MathHelper.clamp((int)d0, -29999872, 29999872);
@@ -643,7 +1144,8 @@
if (entityIn.isEntityAlive())
{
entityIn.setLocationAndAngles(d0, entityIn.posY, d1, entityIn.rotationYaw, entityIn.rotationPitch);
- toWorldIn.getDefaultTeleporter().placeInPortal(entityIn, f);
+ oldWorldIn.updateEntityWithOptionalForce(entityIn, false);
+ teleporter.placeEntity(toWorldIn, entityIn, f);
toWorldIn.spawnEntity(entityIn);
toWorldIn.updateEntityWithOptionalForce(entityIn, false);
}
@@ -654,11 +1156,155 @@
entityIn.setWorld(toWorldIn);
}
+ // Copy of original transferEntityToWorld(Entity, int, WorldServer, WorldServer) method with only location calculation logic
+ public Location calculateTarget(Location enter, World target) {
+ WorldServer worldserver = ((CraftWorld) enter.getWorld()).getHandle();
+ WorldServer worldserver1 = ((CraftWorld) target.getWorld()).getHandle();
+ int i = worldserver.dimension;
+
+ double y = enter.getY();
+ float yaw = enter.getYaw();
+ float pitch = enter.getPitch();
+ double d0 = enter.getX();
+ double d1 = enter.getZ();
+ double d2 = 8.0D;
+
+ worldserver.profiler.startSection("moving");
+ if (worldserver1.dimension == -1) {
+ d0 = MathHelper.clamp(d0 / d2, worldserver1.getWorldBorder().minX()+ 16.0D, worldserver1.getWorldBorder().maxX() - 16.0D);
+ d1 = MathHelper.clamp(d1 / d2, worldserver1.getWorldBorder().minZ() + 16.0D, worldserver1.getWorldBorder().maxZ() - 16.0D);
+ } else if (worldserver1.dimension == 0) {
+ d0 = MathHelper.clamp(d0 * d2, worldserver1.getWorldBorder().minX() + 16.0D, worldserver1.getWorldBorder().maxX() - 16.0D);
+ d1 = MathHelper.clamp(d1 * d2, worldserver1.getWorldBorder().minZ() + 16.0D, worldserver1.getWorldBorder().maxZ() - 16.0D);
+ } else {
+ BlockPos blockposition;
+
+ if (i == 1) {
+ // use default NORMAL world spawn instead of target
+ worldserver1 = this.mcServer.worldServerList.get(0);
+ blockposition = worldserver1.getSpawnPoint();
+ } else {
+ blockposition = worldserver1.getSpawnCoordinate();
+ }
+
+ // CatServer start - check null
+ if (blockposition != null)
+ {
+ d0 = (double) blockposition.getX();
+ y = (double) blockposition.getY();
+ d1 = (double) blockposition.getZ();
+ }
+ // CatServer end
+ }
+
+ worldserver.profiler.endSection();
+ if (i != 1) {
+ worldserver.profiler.startSection("placing");
+ d0 = (double) MathHelper.clamp((int) d0, -29999872, 29999872);
+ d1 = (double) MathHelper.clamp((int) d1, -29999872, 29999872);
+ worldserver.profiler.endSection();
+ }
+
+ return new Location(worldserver1.getWorld(), d0, y, d1, yaw, pitch);
+ }
+
+ // copy of original transferEntityToWorld(Entity, int, WorldServer, WorldServer) method with only entity repositioning logic
+ public void repositionEntity(Entity entity, Location exit, boolean portal) {
+ WorldServer worldserver = (WorldServer) entity.world;
+ WorldServer worldserver1 = ((CraftWorld) exit.getWorld()).getHandle();
+ int i = worldserver.dimension;
+
+ /*
+ double d0 = entity.locX;
+ double d1 = entity.locZ;
+ double d2 = 8.0D;
+ float f = entity.yaw;
+ */
+
+ worldserver.profiler.startSection("moving");
+ entity.setLocationAndAngles(exit.getX(), exit.getY(), exit.getZ(), exit.getYaw(), exit.getPitch());
+ if (entity.isEntityAlive()) {
+ worldserver.updateEntityWithOptionalForce(entity, false);
+ }
+ /*
+ if (entity.dimension == -1) {
+ d0 = MathHelper.a(d0 / 8.0D, worldserver1.getWorldBorder().b() + 16.0D, worldserver1.getWorldBorder().d() - 16.0D);
+ d1 = MathHelper.a(d1 / 8.0D, worldserver1.getWorldBorder().c() + 16.0D, worldserver1.getWorldBorder().e() - 16.0D);
+ entity.setPositionRotation(d0, entity.locY, d1, entity.yaw, entity.pitch);
+ if (entity.isAlive()) {
+ worldserver.entityJoinedWorld(entity, false);
+ }
+ } else if (entity.dimension == 0) {
+ d0 = MathHelper.a(d0 * 8.0D, worldserver1.getWorldBorder().b() + 16.0D, worldserver1.getWorldBorder().d() - 16.0D);
+ d1 = MathHelper.a(d1 * 8.0D, worldserver1.getWorldBorder().c() + 16.0D, worldserver1.getWorldBorder().e() - 16.0D);
+ entity.setPositionRotation(d0, entity.locY, d1, entity.yaw, entity.pitch);
+ if (entity.isAlive()) {
+ worldserver.entityJoinedWorld(entity, false);
+ }
+ } else {
+ BlockPosition blockposition;
+
+ if (i == 1) {
+ // use default NORMAL world spawn instead of target
+ worldserver1 = this.server.worlds.get(0);
+ blockposition = worldserver1.getSpawn();
+ } else {
+ blockposition = worldserver1.getDimensionSpawn();
+ }
+
+ d0 = (double) blockposition.getX();
+ entity.locY = (double) blockposition.getY();
+ d1 = (double) blockposition.getZ();
+ entity.setPositionRotation(d0, entity.locY, d1, 90.0F, 0.0F);
+ if (entity.isAlive()) {
+ worldserver.entityJoinedWorld(entity, false);
+ }
+ }
+ */
+
+ worldserver.profiler.endSection();
+ if (i != 1) {
+ worldserver.profiler.startSection("placing");
+ /*
+ d0 = (double) MathHelper.clamp((int) d0, -29999872, 29999872);
+ d1 = (double) MathHelper.clamp((int) d1, -29999872, 29999872);
+ */
+ if (entity.isEntityAlive()) {
+ // entity.setPositionRotation(d0, entity.locY, d1, entity.yaw, entity.pitch);
+ // worldserver1.getTravelAgent().a(entity, f);
+ if (portal) {
+ Vector velocity = entity.getBukkitEntity().getVelocity();
+ worldserver1.getDefaultTeleporter().adjustExit(entity, exit, velocity);
+ entity.setLocationAndAngles(exit.getX(), exit.getY(), exit.getZ(), exit.getYaw(), exit.getPitch());
+ if (entity.motionX != velocity.getX() || entity.motionY != velocity.getY() || entity.motionZ != velocity.getZ()) {
+ entity.getBukkitEntity().setVelocity(velocity);
+ }
+ }
+ // worldserver1.addEntity(entity);
+ worldserver1.updateEntityWithOptionalForce(entity, false);
+ }
+
+ worldserver.profiler.endSection();
+ }
+
+ entity.setWorld(worldserver1);
+ }
+
public void onTick()
{
if (++this.playerPingIndex > 600)
{
- this.sendPacketToAllPlayers(new SPacketPlayerListItem(SPacketPlayerListItem.Action.UPDATE_LATENCY, this.playerEntityList));
+ // this.sendPacketToAllPlayers(new SPacketPlayerListItem(SPacketPlayerListItem.Action.UPDATE_LATENCY, this.playerEntityList));
+ for (int i = 0; i < this.playerEntityList.size(); ++i) {
+ final EntityPlayerMP target = this.playerEntityList.get(i);
+
+ target.connection.sendPacket(new SPacketPlayerListItem(SPacketPlayerListItem.Action.UPDATE_LATENCY, Iterables.filter(this.playerEntityList, new Predicate<EntityPlayerMP>() {
+ @Override
+ public boolean apply(EntityPlayerMP input) {
+ return target.getBukkitEntity().canSee(input.getBukkitEntity());
+ }
+ })));
+ }
this.playerPingIndex = 0;
}
}
@@ -671,6 +1317,24 @@
}
}
+ // CraftBukkit start - add a world/entity limited version
+ public void sendAll(Packet packet, EntityPlayer entityhuman) {
+ for (int i = 0; i < this.playerEntityList.size(); ++i) {
+ EntityPlayerMP entityplayer = this.playerEntityList.get(i);
+ if (entityhuman != null && entityhuman instanceof EntityPlayerMP && !entityplayer.getBukkitEntity().canSee(((EntityPlayerMP) entityhuman).getBukkitEntity())) {
+ continue;
+ }
+ ((EntityPlayerMP) this.playerEntityList.get(i)).connection.sendPacket(packet);
+ }
+ }
+
+ public void sendAll(Packet packet, World world) {
+ for (int i = 0; i < world.playerEntities.size(); ++i) {
+ ((EntityPlayerMP) world.playerEntities.get(i)).connection.sendPacket(packet);
+ }
+ }
+ // CraftBukkit end
+
public void sendPacketToAllPlayersInDimension(Packet<?> packetIn, int dimension)
{
for (int i = 0; i < this.playerEntityList.size(); ++i)
@@ -786,12 +1450,20 @@
int i = this.mcServer.getOpPermissionLevel();
this.ops.addEntry(new UserListOpsEntry(profile, this.mcServer.getOpPermissionLevel(), this.ops.bypassesPlayerLimit(profile)));
this.sendPlayerPermissionLevel(this.getPlayerByUUID(profile.getId()), i);
+ Player player = mcServer.server.getPlayer(profile.getId());
+ if (player != null) {
+ player.recalculatePermissions();
+ }
}
public void removeOp(GameProfile profile)
{
this.ops.removeEntry(profile);
this.sendPlayerPermissionLevel(this.getPlayerByUUID(profile.getId()), 0);
+ Player player = mcServer.server.getPlayer(profile.getId());
+ if (player != null) {
+ player.recalculatePermissions();
+ }
}
private void sendPlayerPermissionLevel(EntityPlayerMP player, int permLevel)
@@ -824,7 +1496,7 @@
public boolean canSendCommands(GameProfile profile)
{
- return this.ops.hasEntry(profile) || this.mcServer.isSinglePlayer() && this.mcServer.worlds[0].getWorldInfo().areCommandsAllowed() && this.mcServer.getServerOwner().equalsIgnoreCase(profile.getName()) || this.commandsAllowedForAll;
+ return this.ops.hasEntry(profile) || this.mcServer.isSinglePlayer() && this.mcServer.worldServerList.get(0).getWorldInfo().areCommandsAllowed() && this.mcServer.getServerOwner().equalsIgnoreCase(profile.getName()) || this.commandsAllowedForAll;
}
@Nullable
@@ -847,6 +1519,12 @@
{
EntityPlayerMP entityplayermp = this.playerEntityList.get(i);
+ // CraftBukkit start - Test if player receiving packet can see the source of the packet
+ if (except != null && except instanceof EntityPlayerMP && !entityplayermp.getBukkitEntity().canSee(((EntityPlayerMP) except).getBukkitEntity())) {
+ continue;
+ }
+ // CraftBukkit end
+
if (entityplayermp != except && entityplayermp.dimension == dimension)
{
double d0 = x - entityplayermp.posX;
@@ -905,7 +1583,7 @@
public void updateTimeAndWeatherForPlayer(EntityPlayerMP playerIn, WorldServer worldIn)
{
- WorldBorder worldborder = this.mcServer.worlds[0].getWorldBorder();
+ WorldBorder worldborder = this.mcServer.worldServerList.get(0).getWorldBorder();
playerIn.connection.sendPacket(new SPacketWorldBorder(worldborder, SPacketWorldBorder.Action.INITIALIZE));
playerIn.connection.sendPacket(new SPacketTimeUpdate(worldIn.getTotalWorldTime(), worldIn.getWorldTime(), worldIn.getGameRules().getBoolean("doDaylightCycle")));
BlockPos blockpos = worldIn.getSpawnPoint();
@@ -913,16 +1591,21 @@
if (worldIn.isRaining())
{
- playerIn.connection.sendPacket(new SPacketChangeGameState(1, 0.0F));
- playerIn.connection.sendPacket(new SPacketChangeGameState(7, worldIn.getRainStrength(1.0F)));
- playerIn.connection.sendPacket(new SPacketChangeGameState(8, worldIn.getThunderStrength(1.0F)));
+ // CraftBukkit start - handle player weather
+ // playerIn.connection.sendPacket(new SPacketChangeGameState(1, 0.0F));
+ // playerIn.connection.sendPacket(new SPacketChangeGameState(7, worldIn.getRainStrength(1.0F)));
+ // playerIn.connection.sendPacket(new SPacketChangeGameState(8, worldIn.getThunderStrength(1.0F)));
+ playerIn.setPlayerWeather(org.bukkit.WeatherType.DOWNFALL, false);
+ playerIn.updateWeather(-worldIn.rainingStrength, worldIn.rainingStrength, -worldIn.thunderingStrength, worldIn.thunderingStrength);
+ // CraftBukkit end
}
}
public void syncPlayerInventory(EntityPlayerMP playerIn)
{
playerIn.sendContainerToPlayer(playerIn.inventoryContainer);
- playerIn.setPlayerHealthUpdated();
+ // playerIn.setPlayerHealthUpdated();
+ playerIn.getBukkitEntity().updateScaledHealth(); // CraftBukkit - Update scaled health on respawn and worldchange
playerIn.connection.sendPacket(new SPacketHeldItemChange(playerIn.inventory.currentItem));
}
@@ -938,7 +1621,7 @@
public String[] getAvailablePlayerDat()
{
- return this.mcServer.worlds[0].getSaveHandler().getPlayerNBTManager().getAvailablePlayerDat();
+ return this.mcServer.worldServerList.get(0).getSaveHandler().getPlayerNBTManager().getAvailablePlayerDat();
}
public void setWhiteListEnabled(boolean whitelistEnabled)
@@ -1004,17 +1687,26 @@
public void removeAllPlayers()
{
- for (int i = 0; i < this.playerEntityList.size(); ++i)
- {
- (this.playerEntityList.get(i)).connection.disconnect(new TextComponentTranslation("multiplayer.disconnect.server_shutdown", new Object[0]));
+ // CraftBukkit start - disconnect safely
+ for (EntityPlayerMP player : this.playerEntityList) {
+ player.connection.disconnect(this.mcServer.server.getShutdownMessage()); // CraftBukkit - add custom shutdown message
}
}
+ public void sendMessage(ITextComponent[] iChatBaseComponents) {
+ for (ITextComponent component : iChatBaseComponents) {
+ sendMessage(component, true);
+ }
+ }
+
public void sendMessage(ITextComponent component, boolean isSystem)
{
this.mcServer.sendMessage(component);
ChatType chattype = isSystem ? ChatType.SYSTEM : ChatType.CHAT;
- this.sendPacketToAllPlayers(new SPacketChat(component, chattype));
+ // this.sendPacketToAllPlayers(new SPacketChat(component, chattype));
+ // CraftBukkit start - we run this through our processor first so we can get web links etc
+ this.sendPacketToAllPlayers(new SPacketChat(CraftChatMessage.fixComponent(component), chattype));
+ // CraftBukkit end
}
public void sendMessage(ITextComponent component)
@@ -1022,6 +1714,7 @@
this.sendMessage(component, true);
}
+ @Nullable
public StatisticsManagerServer getPlayerStatsFile(EntityPlayer playerIn)
{
UUID uuid = playerIn.getUniqueID();
@@ -1050,6 +1743,8 @@
return statisticsmanagerserver;
}
+ public StatisticsManagerServer getStatisticManager(EntityPlayerMP playerIn) { return getPlayerStatsFile(playerIn); } // CatServer - Add CraftBukkit method
+
public PlayerAdvancements getPlayerAdvancements(EntityPlayerMP p_192054_1_)
{
UUID uuid = p_192054_1_.getUniqueID();
@@ -1073,7 +1768,7 @@
if (this.mcServer.worlds != null)
{
- for (WorldServer worldserver : this.mcServer.worlds)
+ for (WorldServer worldserver : this.mcServer.worldServerList)
{
if (worldserver != null)
{