code: public synchronized WorldState next() throws Exception {
      if (this.error != null) {
        throw this.error;
      }
  
      // In case next() is called after completed with no states remaining
      if (this.complete && this.states.isEmpty()) {
        throw new IllegalStateException("No world states remaining.");
      }
      try {
        // Will block until something is available
        WorldState ws = this.states.take();
        if (ws != RESPONSE_COMPLETE) {
          return ws;
        }
      } catch (InterruptedException e) {
        // This should only happen once the request is complete
      }
  
      // If we were interrupted because of an exception, be sure to throw it
      if (this.error != null) {
        throw this.error;
      }
  
      // At this point, we should have an empty queue
      throw new IllegalStateException("Called next() on an empty StepResponse.");
    }
docs: Returns the next {@code WorldState} provided by the world model, blocking
  until data is available, if necessary. If an error has already occurred,
  the {@code Exception} that was generated is thrown. If this response is
  already completed (either normally or by a cancel request), then an
  {@code IllegalStateException} is thrown.
  
  @return the next {@code WorldState} returned by the world model.
  @throws IllegalStateException
  if this method is invoked after a request completes and
  has no more world states.
  @throws Exception
  if an exception is generated by the request