--- a/net/minecraft/server/management/PlayerList.java
+++ b/net/minecraft/server/management/PlayerList.java
@@ -107,6 +107,7 @@
    private GameType field_72410_m;
    private boolean field_72407_n;
    private int field_72408_o;
+   private final List<ServerPlayerEntity> playersView = java.util.Collections.unmodifiableList(field_72404_b);
 
    public PlayerList(MinecraftServer p_i231425_1_, IDynamicRegistries.Impl p_i231425_2_, PlayerData p_i231425_3_, int p_i231425_4_) {
       this.field_72400_f = p_i231425_1_;
@@ -143,6 +144,7 @@
       IWorldInfo iworldinfo = serverworld1.func_72912_H();
       this.func_72381_a(p_72355_2_, (ServerPlayerEntity)null, serverworld1);
       ServerPlayNetHandler serverplaynethandler = new ServerPlayNetHandler(this.field_72400_f, p_72355_1_, p_72355_2_);
+      net.minecraftforge.fml.network.NetworkHooks.sendMCRegistryPackets(p_72355_1_, "PLAY_TO_CLIENT");
       GameRules gamerules = serverworld1.func_82736_K();
       boolean flag = gamerules.func_223586_b(GameRules.field_226683_z_);
       boolean flag1 = gamerules.func_223586_b(GameRules.field_223612_o);
@@ -167,7 +169,7 @@
 
       this.func_232641_a_(iformattabletextcomponent.func_240699_a_(TextFormatting.YELLOW), ChatType.SYSTEM, Util.field_240973_b_);
       serverplaynethandler.func_147364_a(p_72355_2_.func_226277_ct_(), p_72355_2_.func_226278_cu_(), p_72355_2_.func_226281_cx_(), p_72355_2_.field_70177_z, p_72355_2_.field_70125_A);
-      this.field_72404_b.add(p_72355_2_);
+      this.addPlayer(p_72355_2_);
       this.field_177454_f.put(p_72355_2_.func_110124_au(), p_72355_2_);
       this.func_148540_a(new SPlayerListItemPacket(SPlayerListItemPacket.Action.ADD_PLAYER, p_72355_2_));
 
@@ -222,6 +224,7 @@
       }
 
       p_72355_2_.func_71116_b();
+      net.minecraftforge.fml.hooks.BasicEventHooks.firePlayerLoggedIn( p_72355_2_ );
    }
 
    protected void func_96456_a(ServerScoreboard p_96456_1_, ServerPlayerEntity p_96456_2_) {
@@ -282,6 +285,7 @@
          compoundnbt1 = compoundnbt;
          p_72380_1_.func_70020_e(compoundnbt);
          field_148546_d.debug("loading single player");
+         net.minecraftforge.event.ForgeEventFactory.firePlayerLoadingEvent(p_72380_1_, this.field_72412_k, p_72380_1_.func_110124_au().toString());
       } else {
          compoundnbt1 = this.field_72412_k.func_237336_b_(p_72380_1_);
       }
@@ -290,6 +294,7 @@
    }
 
    protected void func_72391_b(ServerPlayerEntity p_72391_1_) {
+      if (p_72391_1_.field_71135_a == null) return;
       this.field_72412_k.func_237335_a_(p_72391_1_);
       ServerStatisticsManager serverstatisticsmanager = this.field_148547_k.get(p_72391_1_.func_110124_au());
       if (serverstatisticsmanager != null) {
@@ -304,6 +309,7 @@
    }
 
    public void func_72367_e(ServerPlayerEntity p_72367_1_) {
+      net.minecraftforge.fml.hooks.BasicEventHooks.firePlayerLoggedOut(p_72367_1_);
       ServerWorld serverworld = p_72367_1_.func_71121_q();
       p_72367_1_.func_195066_a(Stats.field_75947_j);
       this.func_72391_b(p_72367_1_);
@@ -327,7 +333,7 @@
       p_72367_1_.func_213319_R();
       serverworld.func_217434_e(p_72367_1_);
       p_72367_1_.func_192039_O().func_192745_a();
-      this.field_72404_b.remove(p_72367_1_);
+      this.removePlayer(p_72367_1_);
       this.field_72400_f.func_201300_aS().func_201382_b(p_72367_1_);
       UUID uuid = p_72367_1_.func_110124_au();
       ServerPlayerEntity serverplayerentity = this.field_177454_f.get(uuid);
@@ -397,8 +403,8 @@
    }
 
    public ServerPlayerEntity func_232644_a_(ServerPlayerEntity p_232644_1_, boolean p_232644_2_) {
-      this.field_72404_b.remove(p_232644_1_);
-      p_232644_1_.func_71121_q().func_217434_e(p_232644_1_);
+      this.removePlayer(p_232644_1_);
+      p_232644_1_.func_71121_q().removePlayer(p_232644_1_, true); // Forge: keep data until copyFrom called
       BlockPos blockpos = p_232644_1_.func_241140_K_();
       boolean flag = p_232644_1_.func_241142_M_();
       ServerWorld serverworld = this.field_72400_f.func_71218_a(p_232644_1_.func_241141_L_());
@@ -420,6 +426,7 @@
       ServerPlayerEntity serverplayerentity = new ServerPlayerEntity(this.field_72400_f, serverworld1, p_232644_1_.func_146103_bH(), playerinteractionmanager);
       serverplayerentity.field_71135_a = p_232644_1_.field_71135_a;
       serverplayerentity.func_193104_a(p_232644_1_, p_232644_2_);
+      p_232644_1_.remove(false); // Forge: clone event had a chance to see old data, now discard it
       serverplayerentity.func_145769_d(p_232644_1_.func_145782_y());
       serverplayerentity.func_184819_a(p_232644_1_.func_184591_cq());
 
@@ -451,10 +458,11 @@
       this.func_72354_b(serverplayerentity, serverworld1);
       this.func_187243_f(serverplayerentity);
       serverworld1.func_217433_d(serverplayerentity);
-      this.field_72404_b.add(serverplayerentity);
+      this.addPlayer(serverplayerentity);
       this.field_177454_f.put(serverplayerentity.func_110124_au(), serverplayerentity);
       serverplayerentity.func_71116_b();
       serverplayerentity.func_70606_j(serverplayerentity.func_110143_aJ());
+      net.minecraftforge.fml.hooks.BasicEventHooks.firePlayerRespawnEvent(serverplayerentity, p_232644_2_);
       if (flag1) {
          serverplayerentity.field_71135_a.func_147359_a(new SPlaySoundEffectPacket(SoundEvents.field_232818_ms_, SoundCategory.BLOCKS, (double)blockpos.func_177958_n(), (double)blockpos.func_177956_o(), (double)blockpos.func_177952_p(), 1.0F, 1.0F));
       }
@@ -772,7 +780,7 @@
    }
 
    public List<ServerPlayerEntity> func_181057_v() {
-      return this.field_72404_b;
+      return this.playersView; //Unmodifiable view, we don't want people removing things without us knowing.
    }
 
    @Nullable
@@ -802,4 +810,12 @@
    public boolean func_206257_x() {
       return this.field_72407_n;
    }
+
+   public boolean addPlayer(ServerPlayerEntity player) {
+      return field_72404_b.add(player);
+   }
+
+   public boolean removePlayer(ServerPlayerEntity player) {
+       return this.field_72404_b.remove(player);
+   }
 }
