ModPlayerList.java 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. package me.km.overrides;
  2. import com.google.common.collect.Lists;
  3. import com.mojang.authlib.GameProfile;
  4. import io.netty.buffer.Unpooled;
  5. import java.util.List;
  6. import java.util.Map;
  7. import java.util.Optional;
  8. import java.util.UUID;
  9. import me.hammerle.snuviscript.code.ISnuviScheduler;
  10. import me.km.Server;
  11. import me.km.networking.ModPacketHandler;
  12. import me.km.utils.ReflectionUtils;
  13. import net.minecraft.entity.Entity;
  14. import net.minecraft.entity.EntityType;
  15. import net.minecraft.entity.player.PlayerEntity;
  16. import net.minecraft.entity.player.ServerPlayerEntity;
  17. import net.minecraft.nbt.CompoundNBT;
  18. import net.minecraft.network.NetworkManager;
  19. import net.minecraft.network.PacketBuffer;
  20. import net.minecraft.network.play.ServerPlayNetHandler;
  21. import net.minecraft.network.play.server.SChangeGameStatePacket;
  22. import net.minecraft.network.play.server.SCustomPayloadPlayPacket;
  23. import net.minecraft.network.play.server.SHeldItemChangePacket;
  24. import net.minecraft.network.play.server.SJoinGamePacket;
  25. import net.minecraft.network.play.server.SPlayEntityEffectPacket;
  26. import net.minecraft.network.play.server.SPlayerAbilitiesPacket;
  27. import net.minecraft.network.play.server.SPlayerListItemPacket;
  28. import net.minecraft.network.play.server.SRespawnPacket;
  29. import net.minecraft.network.play.server.SServerDifficultyPacket;
  30. import net.minecraft.network.play.server.SSetExperiencePacket;
  31. import net.minecraft.network.play.server.SSpawnPositionPacket;
  32. import net.minecraft.network.play.server.STagsListPacket;
  33. import net.minecraft.network.play.server.SUpdateRecipesPacket;
  34. import net.minecraft.potion.EffectInstance;
  35. import net.minecraft.server.dedicated.DedicatedPlayerList;
  36. import net.minecraft.server.dedicated.DedicatedServer;
  37. import net.minecraft.server.management.DemoPlayerInteractionManager;
  38. import net.minecraft.server.management.PlayerInteractionManager;
  39. import net.minecraft.server.management.PlayerList;
  40. import net.minecraft.server.management.PlayerProfileCache;
  41. import net.minecraft.util.math.BlockPos;
  42. import net.minecraft.util.math.Vec3d;
  43. import net.minecraft.util.text.ITextComponent;
  44. import net.minecraft.util.text.TranslationTextComponent;
  45. import net.minecraft.world.GameRules;
  46. import net.minecraft.world.IWorld;
  47. import net.minecraft.world.server.ServerWorld;
  48. import net.minecraft.world.dimension.DimensionType;
  49. import net.minecraft.world.storage.WorldInfo;
  50. import org.apache.logging.log4j.LogManager;
  51. public class ModPlayerList extends DedicatedPlayerList
  52. {
  53. private final DedicatedServer server;
  54. private final List<ServerPlayerEntity> players;
  55. private final Map<UUID, ServerPlayerEntity> uuidToPlayerMap;
  56. private final ISnuviScheduler scheduler;
  57. public ModPlayerList(DedicatedServer server, ISnuviScheduler scheduler)
  58. {
  59. super(server);
  60. this.server = server;
  61. this.players = getPlayers();
  62. this.uuidToPlayerMap = ReflectionUtils.getFieldValue(Map.class, PlayerList.class, this, "field_177454_f");
  63. this.scheduler = scheduler;
  64. }
  65. @Override
  66. public void initializeConnectionToPlayer(NetworkManager netManager, ServerPlayerEntity p)
  67. {
  68. GameProfile profile = p.getGameProfile();
  69. PlayerProfileCache cache = this.server.getPlayerProfileCache();
  70. GameProfile cachedProfile = cache.getProfileByUUID(profile.getId());
  71. String s = cachedProfile == null ? profile.getName() : cachedProfile.getName();
  72. cache.addEntry(profile);
  73. CompoundNBT compoundnbt = this.readPlayerDataFromFile(p);
  74. //Forge: Make sure the dimension hasn't been deleted, if so stick them in the overworld.
  75. DimensionType type = p.dimension;
  76. boolean noSchedule = true;
  77. if(type == null || !type.isVanilla())
  78. {
  79. ServerWorld overWorld = this.server.getWorld(DimensionType.OVERWORLD);
  80. p.dimension = DimensionType.OVERWORLD;
  81. if(type != null && this.server.getWorld(type) != null)
  82. {
  83. double x = p.posX;
  84. double y = p.posY;
  85. double z = p.posZ;
  86. float yaw = p.rotationYaw;
  87. float pitch = p.rotationPitch;
  88. noSchedule = false;
  89. scheduler.scheduleTask(() ->
  90. {
  91. ServerWorld ws = server.getWorld(type);
  92. if(ws != null)
  93. {
  94. p.teleport(ws, x, y, z, yaw, pitch);
  95. }
  96. net.minecraftforge.fml.hooks.BasicEventHooks.firePlayerLoggedIn(p);
  97. }, 2);
  98. }
  99. WorldInfo wi = overWorld.getWorldInfo();
  100. p.setPosition(wi.getSpawnX(), wi.getSpawnY(), wi.getSpawnZ());
  101. }
  102. ServerWorld sw = this.server.getWorld(p.dimension);
  103. p.setWorld(sw);
  104. p.interactionManager.setWorld((ServerWorld) p.world);
  105. String s1 = "local";
  106. if(netManager.getRemoteAddress() != null)
  107. {
  108. s1 = netManager.getRemoteAddress().toString();
  109. }
  110. LogManager.getLogger().info("{}[{}] logged in with entity id {} at ({}, {}, {})", p.getName().getString(), s1, p.getEntityId(), p.posX, p.posY, p.posZ);
  111. WorldInfo wi = sw.getWorldInfo();
  112. setPlayerGameTypeBasedOnOther(p, null, sw);
  113. ServerPlayNetHandler spnh = new ServerPlayNetHandler(this.server, netManager, p);
  114. ModPacketHandler.syncDimensions(p);
  115. net.minecraftforge.fml.network.NetworkHooks.sendMCRegistryPackets(netManager, "PLAY_TO_CLIENT");
  116. spnh.sendPacket(new SJoinGamePacket(p.getEntityId(), p.interactionManager.getGameType(), wi.isHardcore(), sw.dimension.getType(), this.getMaxPlayers(), wi.getGenerator(), getViewDistance(), sw.getGameRules().getBoolean(GameRules.REDUCED_DEBUG_INFO)));
  117. spnh.sendPacket(new SCustomPayloadPlayPacket(SCustomPayloadPlayPacket.BRAND, (new PacketBuffer(Unpooled.buffer())).writeString(this.getServer().getServerModName())));
  118. spnh.sendPacket(new SServerDifficultyPacket(wi.getDifficulty(), wi.isDifficultyLocked()));
  119. spnh.sendPacket(new SPlayerAbilitiesPacket(p.abilities));
  120. spnh.sendPacket(new SHeldItemChangePacket(p.inventory.currentItem));
  121. spnh.sendPacket(new SUpdateRecipesPacket(this.server.getRecipeManager().getRecipes()));
  122. spnh.sendPacket(new STagsListPacket(this.server.getNetworkTagManager()));
  123. this.updatePermissionLevel(p);
  124. p.getStats().markAllDirty();
  125. p.getRecipeBook().init(p);
  126. this.sendScoreboard(sw.getScoreboard(), p);
  127. this.server.refreshStatusNextTick();
  128. spnh.setPlayerLocation(p.posX, p.posY, p.posZ, p.rotationYaw, p.rotationPitch);
  129. this.addPlayer(p);
  130. this.uuidToPlayerMap.put(p.getUniqueID(), p);
  131. this.sendPacketToAllPlayers(new SPlayerListItemPacket(SPlayerListItemPacket.Action.ADD_PLAYER, p));
  132. for(int i = 0; i < this.players.size(); ++i)
  133. {
  134. p.connection.sendPacket(new SPlayerListItemPacket(SPlayerListItemPacket.Action.ADD_PLAYER, this.players.get(i)));
  135. }
  136. sw.addNewPlayer(p);
  137. this.server.getCustomBossEvents().onPlayerLogin(p);
  138. this.sendWorldInfo(p, sw);
  139. if(!this.server.getResourcePackUrl().isEmpty())
  140. {
  141. p.loadResourcePack(this.server.getResourcePackUrl(), this.server.getResourcePackHash());
  142. }
  143. for(EffectInstance effectinstance : p.getActivePotionEffects())
  144. {
  145. spnh.sendPacket(new SPlayEntityEffectPacket(p.getEntityId(), effectinstance));
  146. }
  147. if(compoundnbt != null && compoundnbt.contains("RootVehicle", 10))
  148. {
  149. CompoundNBT compoundnbt1 = compoundnbt.getCompound("RootVehicle");
  150. final ServerWorld worldf = sw;
  151. Entity entity1 = EntityType.func_220335_a(compoundnbt1.getCompound("Entity"), sw, (p_217885_1_) ->
  152. {
  153. return !worldf.summonEntity(p_217885_1_) ? null : p_217885_1_;
  154. });
  155. if(entity1 != null)
  156. {
  157. UUID uuid = compoundnbt1.getUniqueId("Attach");
  158. if(entity1.getUniqueID().equals(uuid))
  159. {
  160. p.startRiding(entity1, true);
  161. }
  162. else
  163. {
  164. for(Entity entity : entity1.getRecursivePassengers())
  165. {
  166. if(entity.getUniqueID().equals(uuid))
  167. {
  168. p.startRiding(entity, true);
  169. break;
  170. }
  171. }
  172. }
  173. if(!p.isPassenger())
  174. {
  175. LogManager.getLogger().warn("Couldn't reattach entity to player");
  176. sw.removeEntity(entity1);
  177. for(Entity entity2 : entity1.getRecursivePassengers())
  178. {
  179. sw.removeEntity(entity2);
  180. }
  181. }
  182. }
  183. }
  184. p.addSelfToInternalCraftingInventory();
  185. if(noSchedule)
  186. {
  187. net.minecraftforge.fml.hooks.BasicEventHooks.firePlayerLoggedIn(p);
  188. }
  189. }
  190. @Override
  191. public ServerPlayerEntity createPlayerForUser(GameProfile profile)
  192. {
  193. UUID uuid = PlayerEntity.getUUID(profile);
  194. List<ServerPlayerEntity> list = Lists.newArrayList();
  195. for(int i = 0; i < this.players.size(); ++i)
  196. {
  197. ServerPlayerEntity serverplayerentity = this.players.get(i);
  198. if(serverplayerentity.getUniqueID().equals(uuid))
  199. {
  200. list.add(serverplayerentity);
  201. }
  202. }
  203. ServerPlayerEntity serverplayerentity2 = this.uuidToPlayerMap.get(profile.getId());
  204. if(serverplayerentity2 != null && !list.contains(serverplayerentity2))
  205. {
  206. list.add(serverplayerentity2);
  207. }
  208. for(ServerPlayerEntity serverplayerentity1 : list)
  209. {
  210. serverplayerentity1.connection.disconnect(new TranslationTextComponent("multiplayer.disconnect.duplicate_login"));
  211. }
  212. PlayerInteractionManager playerinteractionmanager;
  213. if(this.server.isDemo())
  214. {
  215. playerinteractionmanager = new DemoPlayerInteractionManager(this.server.getWorld(DimensionType.OVERWORLD));
  216. }
  217. else
  218. {
  219. playerinteractionmanager = new PlayerInteractionManager(this.server.getWorld(DimensionType.OVERWORLD));
  220. }
  221. return new ModEntityPlayerMP(this.server, this.server.getWorld(DimensionType.OVERWORLD), profile, playerinteractionmanager);
  222. }
  223. @Override
  224. public ServerPlayerEntity recreatePlayerEntity(ServerPlayerEntity pIn, DimensionType dim, boolean conqueredEnd)
  225. {
  226. Server.scriptEvents.onPlayerPreRespawn(pIn);
  227. ServerWorld world = server.getWorld(dim);
  228. if(world == null)
  229. {
  230. dim = pIn.getSpawnDimension();
  231. }
  232. else if(!world.getDimension().canRespawnHere())
  233. {
  234. dim = world.getDimension().getRespawnDimension(pIn);
  235. }
  236. if(server.getWorld(dim) == null)
  237. {
  238. dim = DimensionType.OVERWORLD;
  239. }
  240. this.removePlayer(pIn);
  241. pIn.getServerWorld().removePlayer(pIn, true); // Forge: keep data until copyFrom called
  242. BlockPos blockpos = pIn.getBedLocation(dim);
  243. boolean flag = pIn.isSpawnForced(dim);
  244. pIn.dimension = dim;
  245. PlayerInteractionManager playerinteractionmanager;
  246. if(this.server.isDemo())
  247. {
  248. playerinteractionmanager = new DemoPlayerInteractionManager(this.server.getWorld(pIn.dimension));
  249. }
  250. else
  251. {
  252. playerinteractionmanager = new PlayerInteractionManager(this.server.getWorld(pIn.dimension));
  253. }
  254. ServerPlayerEntity p = new ModEntityPlayerMP(this.server, this.server.getWorld(pIn.dimension), pIn.getGameProfile(), playerinteractionmanager, (ModEntityPlayerMP) pIn);
  255. p.connection = pIn.connection;
  256. p.copyFrom(pIn, conqueredEnd);
  257. pIn.remove(false); // Forge: clone event had a chance to see old data, now discard it
  258. p.dimension = dim;
  259. p.setEntityId(pIn.getEntityId());
  260. p.setPrimaryHand(pIn.getPrimaryHand());
  261. for(String s : pIn.getTags())
  262. {
  263. p.addTag(s);
  264. }
  265. ServerWorld serverworld = this.server.getWorld(pIn.dimension);
  266. this.setPlayerGameTypeBasedOnOther(p, pIn, serverworld);
  267. if(blockpos != null)
  268. {
  269. Optional<Vec3d> optional = PlayerEntity.func_213822_a(this.server.getWorld(pIn.dimension), blockpos, flag);
  270. if(optional.isPresent())
  271. {
  272. Vec3d vec3d = optional.get();
  273. p.setLocationAndAngles(vec3d.x, vec3d.y, vec3d.z, 0.0F, 0.0F);
  274. p.setSpawnPoint(blockpos, flag, dim);
  275. }
  276. else
  277. {
  278. p.connection.sendPacket(new SChangeGameStatePacket(0, 0.0F));
  279. }
  280. }
  281. while(!serverworld.areCollisionShapesEmpty(p) && p.posY < 256.0D)
  282. {
  283. p.setPosition(p.posX, p.posY + 1.0D, p.posZ);
  284. }
  285. WorldInfo wi = p.world.getWorldInfo();
  286. p.connection.sendPacket(new SRespawnPacket(p.dimension, wi.getGenerator(), p.interactionManager.getGameType()));
  287. BlockPos pos = serverworld.getSpawnPoint();
  288. p.connection.setPlayerLocation(p.posX, p.posY, p.posZ, p.rotationYaw, p.rotationPitch);
  289. p.connection.sendPacket(new SSpawnPositionPacket(pos));
  290. p.connection.sendPacket(new SServerDifficultyPacket(wi.getDifficulty(), wi.isDifficultyLocked()));
  291. p.connection.sendPacket(new SSetExperiencePacket(p.experience, p.experienceTotal, p.experienceLevel));
  292. this.sendWorldInfo(p, serverworld);
  293. this.updatePermissionLevel(p);
  294. serverworld.addRespawnedPlayer(p);
  295. this.addPlayer(p);
  296. this.uuidToPlayerMap.put(p.getUniqueID(), p);
  297. p.addSelfToInternalCraftingInventory();
  298. p.setHealth(p.getHealth());
  299. net.minecraftforge.fml.hooks.BasicEventHooks.firePlayerRespawnEvent(p, conqueredEnd);
  300. return p;
  301. }
  302. private void setPlayerGameTypeBasedOnOther(ServerPlayerEntity target, ServerPlayerEntity source, IWorld w)
  303. {
  304. ReflectionUtils.setPlayerGameTypeBasedOnOther(this, target, source, w);
  305. }
  306. @Override
  307. public void sendMessage(ITextComponent component)
  308. {
  309. // filter multiplayer leave text
  310. if(component instanceof TranslationTextComponent && ((TranslationTextComponent) component).getKey().equals("multiplayer.player.left"))
  311. {
  312. return;
  313. }
  314. super.sendMessage(component);
  315. }
  316. }