package me.km.overrides; import com.google.common.collect.Lists; import com.mojang.authlib.GameProfile; import io.netty.buffer.Unpooled; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.UUID; import me.hammerle.snuviscript.code.ISnuviScheduler; import me.km.Server; import me.km.networking.ModPacketHandler; import me.km.utils.ReflectionUtils; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.nbt.CompoundNBT; import net.minecraft.network.NetworkManager; import net.minecraft.network.PacketBuffer; import net.minecraft.network.play.ServerPlayNetHandler; import net.minecraft.network.play.server.SChangeGameStatePacket; import net.minecraft.network.play.server.SCustomPayloadPlayPacket; import net.minecraft.network.play.server.SHeldItemChangePacket; import net.minecraft.network.play.server.SJoinGamePacket; import net.minecraft.network.play.server.SPlayEntityEffectPacket; import net.minecraft.network.play.server.SPlayerAbilitiesPacket; import net.minecraft.network.play.server.SPlayerListItemPacket; import net.minecraft.network.play.server.SRespawnPacket; import net.minecraft.network.play.server.SServerDifficultyPacket; import net.minecraft.network.play.server.SSetExperiencePacket; import net.minecraft.network.play.server.SSpawnPositionPacket; import net.minecraft.network.play.server.STagsListPacket; import net.minecraft.network.play.server.SUpdateRecipesPacket; import net.minecraft.potion.EffectInstance; import net.minecraft.server.dedicated.DedicatedPlayerList; import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.server.management.DemoPlayerInteractionManager; import net.minecraft.server.management.PlayerInteractionManager; import net.minecraft.server.management.PlayerList; import net.minecraft.server.management.PlayerProfileCache; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TranslationTextComponent; import net.minecraft.world.GameRules; import net.minecraft.world.IWorld; import net.minecraft.world.server.ServerWorld; import net.minecraft.world.dimension.DimensionType; import net.minecraft.world.storage.WorldInfo; import org.apache.logging.log4j.LogManager; public class ModPlayerList extends DedicatedPlayerList { private final DedicatedServer server; private final List players; private final Map uuidToPlayerMap; private final ISnuviScheduler scheduler; public ModPlayerList(DedicatedServer server, ISnuviScheduler scheduler) { super(server); this.server = server; this.players = getPlayers(); this.uuidToPlayerMap = ReflectionUtils.getFieldValue(Map.class, PlayerList.class, this, "field_177454_f"); this.scheduler = scheduler; } @Override public void initializeConnectionToPlayer(NetworkManager netManager, ServerPlayerEntity p) { GameProfile profile = p.getGameProfile(); PlayerProfileCache cache = this.server.getPlayerProfileCache(); GameProfile cachedProfile = cache.getProfileByUUID(profile.getId()); String s = cachedProfile == null ? profile.getName() : cachedProfile.getName(); cache.addEntry(profile); CompoundNBT compoundnbt = this.readPlayerDataFromFile(p); //Forge: Make sure the dimension hasn't been deleted, if so stick them in the overworld. DimensionType type = p.dimension; boolean noSchedule = true; if(type == null || !type.isVanilla()) { ServerWorld overWorld = this.server.getWorld(DimensionType.OVERWORLD); p.dimension = DimensionType.OVERWORLD; if(type != null && this.server.getWorld(type) != null) { double x = p.posX; double y = p.posY; double z = p.posZ; float yaw = p.rotationYaw; float pitch = p.rotationPitch; noSchedule = false; scheduler.scheduleTask(() -> { ServerWorld ws = server.getWorld(type); if(ws != null) { p.teleport(ws, x, y, z, yaw, pitch); } net.minecraftforge.fml.hooks.BasicEventHooks.firePlayerLoggedIn(p); }, 2); } WorldInfo wi = overWorld.getWorldInfo(); p.setPosition(wi.getSpawnX(), wi.getSpawnY(), wi.getSpawnZ()); } ServerWorld sw = this.server.getWorld(p.dimension); p.setWorld(sw); p.interactionManager.setWorld((ServerWorld) p.world); String s1 = "local"; if(netManager.getRemoteAddress() != null) { s1 = netManager.getRemoteAddress().toString(); } LogManager.getLogger().info("{}[{}] logged in with entity id {} at ({}, {}, {})", p.getName().getString(), s1, p.getEntityId(), p.posX, p.posY, p.posZ); WorldInfo wi = sw.getWorldInfo(); setPlayerGameTypeBasedOnOther(p, null, sw); ServerPlayNetHandler spnh = new ServerPlayNetHandler(this.server, netManager, p); ModPacketHandler.syncDimensions(p); net.minecraftforge.fml.network.NetworkHooks.sendMCRegistryPackets(netManager, "PLAY_TO_CLIENT"); 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))); spnh.sendPacket(new SCustomPayloadPlayPacket(SCustomPayloadPlayPacket.BRAND, (new PacketBuffer(Unpooled.buffer())).writeString(this.getServer().getServerModName()))); spnh.sendPacket(new SServerDifficultyPacket(wi.getDifficulty(), wi.isDifficultyLocked())); spnh.sendPacket(new SPlayerAbilitiesPacket(p.abilities)); spnh.sendPacket(new SHeldItemChangePacket(p.inventory.currentItem)); spnh.sendPacket(new SUpdateRecipesPacket(this.server.getRecipeManager().getRecipes())); spnh.sendPacket(new STagsListPacket(this.server.getNetworkTagManager())); this.updatePermissionLevel(p); p.getStats().markAllDirty(); p.getRecipeBook().init(p); this.sendScoreboard(sw.getScoreboard(), p); this.server.refreshStatusNextTick(); spnh.setPlayerLocation(p.posX, p.posY, p.posZ, p.rotationYaw, p.rotationPitch); this.addPlayer(p); this.uuidToPlayerMap.put(p.getUniqueID(), p); this.sendPacketToAllPlayers(new SPlayerListItemPacket(SPlayerListItemPacket.Action.ADD_PLAYER, p)); for(int i = 0; i < this.players.size(); ++i) { p.connection.sendPacket(new SPlayerListItemPacket(SPlayerListItemPacket.Action.ADD_PLAYER, this.players.get(i))); } sw.addNewPlayer(p); this.server.getCustomBossEvents().onPlayerLogin(p); this.sendWorldInfo(p, sw); if(!this.server.getResourcePackUrl().isEmpty()) { p.loadResourcePack(this.server.getResourcePackUrl(), this.server.getResourcePackHash()); } for(EffectInstance effectinstance : p.getActivePotionEffects()) { spnh.sendPacket(new SPlayEntityEffectPacket(p.getEntityId(), effectinstance)); } if(compoundnbt != null && compoundnbt.contains("RootVehicle", 10)) { CompoundNBT compoundnbt1 = compoundnbt.getCompound("RootVehicle"); final ServerWorld worldf = sw; Entity entity1 = EntityType.func_220335_a(compoundnbt1.getCompound("Entity"), sw, (p_217885_1_) -> { return !worldf.summonEntity(p_217885_1_) ? null : p_217885_1_; }); if(entity1 != null) { UUID uuid = compoundnbt1.getUniqueId("Attach"); if(entity1.getUniqueID().equals(uuid)) { p.startRiding(entity1, true); } else { for(Entity entity : entity1.getRecursivePassengers()) { if(entity.getUniqueID().equals(uuid)) { p.startRiding(entity, true); break; } } } if(!p.isPassenger()) { LogManager.getLogger().warn("Couldn't reattach entity to player"); sw.removeEntity(entity1); for(Entity entity2 : entity1.getRecursivePassengers()) { sw.removeEntity(entity2); } } } } p.addSelfToInternalCraftingInventory(); if(noSchedule) { net.minecraftforge.fml.hooks.BasicEventHooks.firePlayerLoggedIn(p); } } @Override public ServerPlayerEntity createPlayerForUser(GameProfile profile) { UUID uuid = PlayerEntity.getUUID(profile); List list = Lists.newArrayList(); for(int i = 0; i < this.players.size(); ++i) { ServerPlayerEntity serverplayerentity = this.players.get(i); if(serverplayerentity.getUniqueID().equals(uuid)) { list.add(serverplayerentity); } } ServerPlayerEntity serverplayerentity2 = this.uuidToPlayerMap.get(profile.getId()); if(serverplayerentity2 != null && !list.contains(serverplayerentity2)) { list.add(serverplayerentity2); } for(ServerPlayerEntity serverplayerentity1 : list) { serverplayerentity1.connection.disconnect(new TranslationTextComponent("multiplayer.disconnect.duplicate_login")); } PlayerInteractionManager playerinteractionmanager; if(this.server.isDemo()) { playerinteractionmanager = new DemoPlayerInteractionManager(this.server.getWorld(DimensionType.OVERWORLD)); } else { playerinteractionmanager = new PlayerInteractionManager(this.server.getWorld(DimensionType.OVERWORLD)); } return new ModEntityPlayerMP(this.server, this.server.getWorld(DimensionType.OVERWORLD), profile, playerinteractionmanager); } @Override public ServerPlayerEntity recreatePlayerEntity(ServerPlayerEntity pIn, DimensionType dim, boolean conqueredEnd) { Server.scriptEvents.onPlayerPreRespawn(pIn); ServerWorld world = server.getWorld(dim); if(world == null) { dim = pIn.getSpawnDimension(); } else if(!world.getDimension().canRespawnHere()) { dim = world.getDimension().getRespawnDimension(pIn); } if(server.getWorld(dim) == null) { dim = DimensionType.OVERWORLD; } this.removePlayer(pIn); pIn.getServerWorld().removePlayer(pIn, true); // Forge: keep data until copyFrom called BlockPos blockpos = pIn.getBedLocation(dim); boolean flag = pIn.isSpawnForced(dim); pIn.dimension = dim; PlayerInteractionManager playerinteractionmanager; if(this.server.isDemo()) { playerinteractionmanager = new DemoPlayerInteractionManager(this.server.getWorld(pIn.dimension)); } else { playerinteractionmanager = new PlayerInteractionManager(this.server.getWorld(pIn.dimension)); } ServerPlayerEntity p = new ModEntityPlayerMP(this.server, this.server.getWorld(pIn.dimension), pIn.getGameProfile(), playerinteractionmanager, (ModEntityPlayerMP) pIn); p.connection = pIn.connection; p.copyFrom(pIn, conqueredEnd); pIn.remove(false); // Forge: clone event had a chance to see old data, now discard it p.dimension = dim; p.setEntityId(pIn.getEntityId()); p.setPrimaryHand(pIn.getPrimaryHand()); for(String s : pIn.getTags()) { p.addTag(s); } ServerWorld serverworld = this.server.getWorld(pIn.dimension); this.setPlayerGameTypeBasedOnOther(p, pIn, serverworld); if(blockpos != null) { Optional optional = PlayerEntity.func_213822_a(this.server.getWorld(pIn.dimension), blockpos, flag); if(optional.isPresent()) { Vec3d vec3d = optional.get(); p.setLocationAndAngles(vec3d.x, vec3d.y, vec3d.z, 0.0F, 0.0F); p.setSpawnPoint(blockpos, flag, dim); } else { p.connection.sendPacket(new SChangeGameStatePacket(0, 0.0F)); } } while(!serverworld.areCollisionShapesEmpty(p) && p.posY < 256.0D) { p.setPosition(p.posX, p.posY + 1.0D, p.posZ); } WorldInfo wi = p.world.getWorldInfo(); p.connection.sendPacket(new SRespawnPacket(p.dimension, wi.getGenerator(), p.interactionManager.getGameType())); BlockPos pos = serverworld.getSpawnPoint(); p.connection.setPlayerLocation(p.posX, p.posY, p.posZ, p.rotationYaw, p.rotationPitch); p.connection.sendPacket(new SSpawnPositionPacket(pos)); p.connection.sendPacket(new SServerDifficultyPacket(wi.getDifficulty(), wi.isDifficultyLocked())); p.connection.sendPacket(new SSetExperiencePacket(p.experience, p.experienceTotal, p.experienceLevel)); this.sendWorldInfo(p, serverworld); this.updatePermissionLevel(p); serverworld.addRespawnedPlayer(p); this.addPlayer(p); this.uuidToPlayerMap.put(p.getUniqueID(), p); p.addSelfToInternalCraftingInventory(); p.setHealth(p.getHealth()); net.minecraftforge.fml.hooks.BasicEventHooks.firePlayerRespawnEvent(p, conqueredEnd); return p; } private void setPlayerGameTypeBasedOnOther(ServerPlayerEntity target, ServerPlayerEntity source, IWorld w) { ReflectionUtils.setPlayerGameTypeBasedOnOther(this, target, source, w); } @Override public void sendMessage(ITextComponent component) { // filter multiplayer leave text if(component instanceof TranslationTextComponent && ((TranslationTextComponent) component).getKey().equals("multiplayer.player.left")) { return; } super.sendMessage(component); } }