#include <bits/stdc++.h>
using namespace std;
const int N_DEL = 0, N_VAL = 0;
inline int mOp(int x, int y) { return x + y; }
inline int qOp(int lval, int rval) { return lval ^ rval; }
inline int dOnSeg(int d, int len) { return d == N_DEL ? N_DEL : d * len; }
inline int joinD(int d1, int d2) {
  if (d1 == N_DEL) return d2;
  if (d2 == N_DEL) return d1;
  return mOp(d1, d2);
}
inline int joinVD(int v, int d) { return d == N_DEL ? v : mOp(v, d); }
struct Node_t {
  int sz, nVal, tVal, d;
  bool rev;
  Node_t *c[2], *p;
  Node_t(int v) : sz(1), nVal(v), tVal(v), d(N_DEL), rev(0), p(0) {
    c[0] = c[1] = 0;
  }
  bool isRoot() { return !p || (p->c[0] != this && p->c[1] != this); }
  void push() {
    if (rev) {
      rev = 0;
      swap(c[0], c[1]);
      for (int x = 0, ThxDem = 2; x < ThxDem; ++x)
        if (c[x]) c[x]->rev ^= 1;
    }
    nVal = joinVD(nVal, d);
    tVal = joinVD(tVal, dOnSeg(d, sz));
    for (int x = 0, ThxDem = 2; x < ThxDem; ++x)
      if (c[x]) c[x]->d = joinD(c[x]->d, d);
    d = N_DEL;
  }
  void upd();
};
typedef Node_t* Node;
int getSize(Node r) { return r ? r->sz : 0; }
int getPV(Node r) { return r ? joinVD(r->tVal, dOnSeg(r->d, r->sz)) : N_VAL; }
void Node_t::upd() {
  tVal = qOp(qOp(getPV(c[0]), joinVD(nVal, d)), getPV(c[1]));
  sz = 1 + getSize(c[0]) + getSize(c[1]);
}
void conn(Node c, Node p, int il) {
  if (c) c->p = p;
  if (il >= 0) p->c[!il] = c;
}
void rotate(Node x) {
  Node p = x->p, g = p->p;
  bool gCh = p->isRoot(), isl = x == p->c[0];
  conn(x->c[isl], p, isl);
  conn(p, x, !isl);
  conn(x, g, gCh ? -1 : (p == g->c[0]));
  p->upd();
}
void spa(Node x) {
  while (!x->isRoot()) {
    Node p = x->p, g = p->p;
    if (!p->isRoot()) g->push();
    p->push();
    x->push();
    if (!p->isRoot()) rotate((x == p->c[0]) == (p == g->c[0]) ? p : x);
    rotate(x);
  }
  x->push();
  x->upd();
}
Node exv(Node x) {
  Node last = 0;
  for (Node y = x; y; y = y->p) spa(y), y->c[0] = last, y->upd(), last = y;
  spa(x);
  return last;
}
void mkR(Node x) {
  exv(x);
  x->rev ^= 1;
}
Node getR(Node x) {
  exv(x);
  while (x->c[1]) x = x->c[1];
  spa(x);
  return x;
}
Node lca(Node x, Node y) {
  exv(x);
  return exv(y);
}
bool connected(Node x, Node y) {
  exv(x);
  exv(y);
  return x == y ? 1 : x->p != 0;
}
void link(Node x, Node y) {
  mkR(x);
  x->p = y;
}
void cut(Node x, Node y) {
  mkR(x);
  exv(y);
  y->c[1]->p = 0;
  y->c[1] = 0;
}
int query(Node x, Node y) {
  mkR(x);
  exv(y);
  return getPV(y);
}
void modify(Node x, Node y, int d) {
  mkR(x);
  exv(y);
  y->d = joinD(y->d, d);
}
map<int, Node> mp;
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int q, last = 0, l, r, x, idx = 0, t;
  cin >> q;
  while (q--) {
    if (last < 0) last = 1;
    cin >> t;
    if (t == 1) {
      cin >> l >> r >> x;
      l ^= last;
      r ^= last;
      x ^= last;
      if (l > r) swap(l, r);
      r++;
      if (!mp.count(l)) mp[l] = new Node_t(0);
      if (!mp.count(r)) mp[r] = new Node_t(0);
      auto le = mp[l], rr = mp[r];
      if (connected(le, rr)) continue;
      auto xx = new Node_t(x);
      link(le, xx);
      link(rr, xx);
    } else {
      cin >> l >> r;
      l ^= last;
      r ^= last;
      if (l > r) swap(l, r);
      r++;
      int ans = -1;
      if (mp.count(l) && mp.count(r)) {
        auto le = mp[l], rr = mp[r];
        if (connected(le, rr)) {
          ans = query(le, rr);
        }
      }
      cout << ans << "\n";
      last = ans;
    }
  }
}
