package carpet.patches; import carpet.CarpetSettings; import com.mojang.authlib.GameProfile; import net.minecraft.block.entity.SkullBlockEntity; import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.network.packet.s2c.play.EntityPositionS2CPacket; import net.minecraft.network.packet.s2c.play.EntitySetHeadYawS2CPacket; import net.minecraft.network.packet.s2c.play.PlayerListS2CPacket; import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.player.HungerManager; import net.minecraft.network.NetworkSide; import net.minecraft.text.Text; import net.minecraft.text.TranslatableText; import net.minecraft.server.MinecraftServer; import net.minecraft.server.ServerTask; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerInteractionManager; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.UserCache; import net.minecraft.util.registry.RegistryKey; import net.minecraft.world.GameMode; import net.minecraft.world.World; import carpet.fakes.ServerPlayerEntityInterface; import carpet.utils.Messenger; @SuppressWarnings("EntityConstructor") public class EntityPlayerMPFake extends ServerPlayerEntity { public Runnable fixStartingPosition = () -> {}; public boolean isAShadow; public static EntityPlayerMPFake createFake(String username, MinecraftServer server, double d0, double d1, double d2, double yaw, double pitch, RegistryKey dimensionId, GameMode gamemode) { //prolly half of that crap is not necessary, but it works ServerWorld worldIn = server.getWorld(dimensionId); ServerPlayerInteractionManager interactionManagerIn = new ServerPlayerInteractionManager(worldIn); UserCache.setUseRemote(false); GameProfile gameprofile; try { gameprofile = server.getUserCache().findByName(username); } finally { UserCache.setUseRemote(server.isDedicated() && server.isOnlineMode()); } if (gameprofile == null) { if (!CarpetSettings.allowSpawningOfflinePlayers) { return null; } else { gameprofile = new GameProfile(PlayerEntity.getOfflinePlayerUuid(username), username); } } if (gameprofile.getProperties().containsKey("textures")) { gameprofile = SkullBlockEntity.loadProperties(gameprofile); } EntityPlayerMPFake instance = new EntityPlayerMPFake(server, worldIn, gameprofile, interactionManagerIn, false); instance.fixStartingPosition = () -> instance.refreshPositionAndAngles(d0, d1, d2, (float) yaw, (float) pitch); server.getPlayerManager().onPlayerConnect(new NetworkManagerFake(NetworkSide.SERVERBOUND), instance); instance.teleport(worldIn, d0, d1, d2, (float)yaw, (float)pitch); instance.setHealth(20.0F); instance.removed = false; instance.stepHeight = 0.6F; interactionManagerIn.setGameMode(gamemode); server.getPlayerManager().sendToDimension(new EntitySetHeadYawS2CPacket(instance, (byte) (instance.headYaw * 256 / 360)), dimensionId);//instance.dimension); server.getPlayerManager().sendToDimension(new EntityPositionS2CPacket(instance), dimensionId);//instance.dimension); instance.getServerWorld().getChunkManager().updateCameraPosition(instance); instance.dataTracker.set(PLAYER_MODEL_PARTS, (byte) 0x7f); // show all model layers (incl. capes) return instance; } public static EntityPlayerMPFake createShadow(MinecraftServer server, ServerPlayerEntity player) { player.getServer().getPlayerManager().remove(player); player.networkHandler.disconnect(new TranslatableText("multiplayer.disconnect.duplicate_login")); ServerWorld worldIn = player.getServerWorld();//.getWorld(player.dimension); ServerPlayerInteractionManager interactionManagerIn = new ServerPlayerInteractionManager(worldIn); GameProfile gameprofile = player.getGameProfile(); EntityPlayerMPFake playerShadow = new EntityPlayerMPFake(server, worldIn, gameprofile, interactionManagerIn, true); server.getPlayerManager().onPlayerConnect(new NetworkManagerFake(NetworkSide.SERVERBOUND), playerShadow); playerShadow.setHealth(player.getHealth()); playerShadow.networkHandler.requestTeleport(player.getX(), player.getY(), player.getZ(), player.yaw, player.pitch); interactionManagerIn.setGameMode(player.interactionManager.getGameMode()); ((ServerPlayerEntityInterface) playerShadow).getActionPack().copyFrom(((ServerPlayerEntityInterface) player).getActionPack()); playerShadow.stepHeight = 0.6F; playerShadow.dataTracker.set(PLAYER_MODEL_PARTS, player.getDataTracker().get(PLAYER_MODEL_PARTS)); server.getPlayerManager().sendToDimension(new EntitySetHeadYawS2CPacket(playerShadow, (byte) (player.headYaw * 256 / 360)), playerShadow.world.getRegistryKey()); server.getPlayerManager().sendToAll(new PlayerListS2CPacket(PlayerListS2CPacket.Action.ADD_PLAYER, playerShadow)); player.getServerWorld().getChunkManager().updateCameraPosition(playerShadow); return playerShadow; } private EntityPlayerMPFake(MinecraftServer server, ServerWorld worldIn, GameProfile profile, ServerPlayerInteractionManager interactionManagerIn, boolean shadow) { super(server, worldIn, profile, interactionManagerIn); isAShadow = shadow; } @Override protected void onEquipStack(ItemStack stack) { if (!isUsingItem()) super.onEquipStack(stack); } @Override public void kill() { kill(Messenger.s("Killed")); } public void kill(Text reason) { shakeOff(); this.server.send(new ServerTask(this.server.getTicks(), () -> { this.networkHandler.onDisconnected(reason); })); } @Override public void tick() { if (this.getServer().getTicks() % 10 == 0) { this.networkHandler.syncWithPlayerPosition(); this.getServerWorld().getChunkManager().updateCameraPosition(this); //if (netherPortalCooldown==10) onTeleportationDone(); <- causes hard crash but would need to be done to enable portals } super.tick(); this.playerTick(); } private void shakeOff() { if (getVehicle() instanceof PlayerEntity) stopRiding(); for (Entity passenger : getPassengersDeep()) { if (passenger instanceof PlayerEntity) passenger.stopRiding(); } } @Override public void onDeath(DamageSource cause) { shakeOff(); super.onDeath(cause); setHealth(20); this.hungerManager = new HungerManager(); kill(this.getDamageTracker().getDeathMessage()); } @Override public String getIp() { return "127.0.0.1"; } }