You are on the right track, and I agree that the vanilla respawn code is complex. Here is how I solved it: (Make sure to put this after a !world.isRemote check to avoid reaching across sides)
ServerPlayerEntity player = (ServerPlayerEntity) event.player; // Get the player somehow (from a parameter or similar)
ServerWorld respawnWorld = player.server.getWorld(player.func_241141_L_());
BlockPos spawn = player.func_241140_K_();
float spawnAngle = player.func_242109_L();
boolean forcedSpawn = false;
boolean preserveAnchorCharges = true;
Optional<Vector3d> maybeSpawn = PlayerEntity.func_242374_a(respawnWorld, spawn, spawnAngle,
forcedSpawn, preserveAnchorCharges);
Then the maybeSpawn will contain the respawn position of the player, and the respawnWorld will be the world in which the player will respawn. Of course, the maybeSpawn can be empty, and then you have to get the respawn position from the world.