In a networked scenario, you should not try to rely on physics determinism to keep your simulation in sync.
Even if both players are running identical binaries on identical chips, the difference of a single fixed timestep due to network latency, or a single object being spawned in a different order due to any optimizations happening in the engine's internals, is enough to introduce divergence.
Since billiards is a turn-based game, the simplest and most robust approach is to alternate authority over the simulation.
The player who takes the shot simulates the physics locally, and sends position & orientation updates to all other clients, who are for the moment just spectators.
Each spectator maintains a buffer of recent updates from the current player, and uses that buffer to show a state some time in the past. Not far - just enough to be able to absorb the occasional missed or delayed packet without visibly stuttering. This lets them always show an interpolation between two actual positions & orientations that occurred in the current player's simulation - they never need to extrapolate or simulate the behaviour themselves, and the balls always end up exactly where the current player's sim settled.
You may need to adjust the interpolated position slightly, to ensure a ball doesn't sink into the table on its way into a pocket, or to ensure the ball doesn't take a shortcut when changing direction, blunting what should have been a sharp collision, but these are purely visual fix-ups that don't affect the final gameplay state of the table in time for the player's next turn.
Then you switch authority and the next player takes the shot.
Note that this only works if you're willing to trust each client to fairly report their play. If hacking is a concern for your game, then you'll want to use an authoritative server under your control, and let all players see a copy of the simulation from the recent past. You can a wind-up animation of the pool cue to cover the latency before the first results from the server are available.
A more robust, but also more intensive solution is to compute the trajectories yourself, so you're not at the whims of a fully general physics solver, and can control the operation explicitly. I wouldn't do this for most games, but for billiards the problem space is reasonably small and well-studied, so it would be feasible to write a "billiards engine" that solves just this case exactly the way you want it.
Since you're no longer bound to iteratively approximating the outcome frame by frame, you could have one client compute the full future of the table at the moment the ball is struck, and transmit the exact sequence of actions to the other clients like a set of animation keyframes.
You could even use fixed point math to sidestep the complexity of getting floats to agree between binaries / differing hardware. Then the player could simply send their action with the pool cue, and all spectators (or the central server) can independently reproduce the outcome of that action (and check each others' work to spot cheating).