diff --git a/src/components/event-repeater.js b/src/components/event-repeater.js
index d6f396766cd82cf42548d93f0808256a1e4891cd..e58c2f912d902329659bffc3e57083a82ceb754d 100644
--- a/src/components/event-repeater.js
+++ b/src/components/event-repeater.js
@@ -1,16 +1,15 @@
 AFRAME.registerComponent("event-repeater", {
   schema: {
-    target: {type: "selector"},
-    events: {type: "array"}
+    target: { type: "selector" },
+    events: { type: "array" }
   },
 
   init: function() {
-  	let events = this.data.events;
-  	for (let i = 0; i < events.length; i++) {
-  		this.data.target.addEventListener(events[i], e => {
-  			this.el.emit(events[i], e.details);
-  		});
-  	}
+    const events = this.data.events;
+    for (let i = 0; i < events.length; i++) {
+      this.data.target.addEventListener(events[i], e => {
+        this.el.emit(events[i], e.details);
+      });
+    }
   }
-
-});
\ No newline at end of file
+});
diff --git a/src/components/networked-counter.js b/src/components/networked-counter.js
index 9845bca6e9d644a5287a51fc864b9449b365b9e0..1a144561eb609814d86a948d3d7eee62a4c46942 100644
--- a/src/components/networked-counter.js
+++ b/src/components/networked-counter.js
@@ -1,7 +1,9 @@
 AFRAME.registerComponent("networked-counter", {
   schema: {
     max: { default: 3 },
-    ttl: { default: 120 }
+    ttl: { default: 120 },
+    grab_event: { type: "string", default: "grab-start" },
+    release_event: { type: "string", default: "grab-end" }
   },
 
   init: function() {
@@ -10,18 +12,6 @@ AFRAME.registerComponent("networked-counter", {
     this.timeouts = {};
   },
 
-  getCount: function() {
-    return queue.length;
-  },
-
-  getMax: function() {
-    return this.data.max;
-  },
-
-  getTtl: function() {
-    return this.data.ttl;
-  },
-
   register: function(networkedEl) {
     if (this.data.max <= 0) {
       return;
@@ -42,8 +32,8 @@ AFRAME.registerComponent("networked-counter", {
       onReleaseHandler: onReleaseHandler
     };
 
-    networkedEl.addEventListener("grab-start", onGrabHandler);
-    networkedEl.addEventListener("grab-end", onReleaseHandler);
+    networkedEl.addEventListener(this.data.grab_event, onGrabHandler);
+    networkedEl.addEventListener(this.data.release_event, onReleaseHandler);
 
     this.count++;
 
@@ -51,15 +41,15 @@ AFRAME.registerComponent("networked-counter", {
       this._addTimeout(id);
     }
 
-    this._removeOldest();
+    this._destroyOldest();
   },
 
   deregister: function(networkedEl) {
     const id = NAF.utils.getNetworkId(networkedEl);
     if (this.queue.hasOwnProperty(id)) {
       const item = this.queue[id];
-      networkedEl.removeEventListener("grab-start", item.onGrabHandler);
-      networkedEl.removeEventListener("grab-end", item.onReleaseHandler);
+      networkedEl.removeEventListener(this.data.grab_event, item.onGrabHandler);
+      networkedEl.removeEventListener(this.data.release_event, item.onReleaseHandler);
 
       delete this.queue[id];
 
@@ -80,9 +70,10 @@ AFRAME.registerComponent("networked-counter", {
     this.queue[id].ts = Date.now();
   },
 
-  _removeOldest: function() {
+  _destroyOldest: function() {
     if (this.count > this.data.max) {
-      let oldest = null, ts = Number.MAX_VALUE;
+      let oldest = null,
+        ts = Number.MAX_VALUE;
       Object.keys(this.queue).forEach(function(id) {
         const expiration = this.queue[id].ts + this.data.ttl * 1000;
         if (this.queue[id].ts < ts && !this._isCurrentlyGrabbed(id)) {
@@ -105,7 +96,6 @@ AFRAME.registerComponent("networked-counter", {
   _addTimeout: function(id) {
     const timeout = this.data.ttl * 1000;
     this.timeouts[id] = setTimeout(() => {
-
       const el = this.queue[id].el;
       this.deregister(el);
       this._destroy(el);
diff --git a/src/components/remote-dynamic-body.js b/src/components/remote-dynamic-body.js
deleted file mode 100644
index 3d2a1dc7e525554e39430d140e931a29ef747427..0000000000000000000000000000000000000000
--- a/src/components/remote-dynamic-body.js
+++ /dev/null
@@ -1,50 +0,0 @@
-AFRAME.registerComponent("remote-dynamic-body", {
-  schema: {
-    mass: { default: 1 },
-    counter: { type: "selector" },
-    grabbable: {type: "boolean", default: true},
-    stretchable: {type: "boolean", default: true}
-  },
-
-  init: function() {
-    this.counter = this.data.counter.components["networked-counter"];
-    this.hand = null;
-
-    NAF.utils.getNetworkedEntity(this.el).then(networkedEl => {
-      this.networkedEl = networkedEl;
-      if (!NAF.utils.isMine(networkedEl)) {
-        this.el.setAttribute("body", "type: dynamic; mass: 0");
-        this.el.setAttribute("material", "color: white")
-      } else {
-        this.counter.register(networkedEl);
-      }
-    });
-
-    this.el.addEventListener("grab-start", e => {
-      this._onGrabStart(e);
-    });
-
-    this.el.addEventListener("ownership-lost", e => {
-      this.el.setAttribute("body", "mass: 0");
-      this.el.emit("grab-end", {hand: this.hand});
-      this.hand = null;
-      this.counter.deregister(this.el);
-      this.el.setAttribute("material", "color: white")
-    });
-  },
-
-  _onGrabStart: function(e) {
-    this.hand = e.detail.hand;
-    if (this.networkedEl && !NAF.utils.isMine(this.networkedEl)) {
-      if (NAF.utils.takeOwnership(this.networkedEl)) {
-        this.el.setAttribute("body", `mass: ${this.data.mass};`);
-        this.counter.register(this.networkedEl);
-        this.el.setAttribute("material", "color: green")
-      } else {
-        this.el.emit("grab-end", {hand: this.hand});
-        this.hand = null;
-        this.el.setAttribute("material", "color: red")
-      }
-    }
-  }
-});
diff --git a/src/components/cursor-hand.js b/src/components/super-cursor.js
similarity index 62%
rename from src/components/cursor-hand.js
rename to src/components/super-cursor.js
index 758d5ac14d91c9256ee7406eab48a1905ddf74d1..47269cecea6c70adc1f9b161e76acf1b3c4bfe0e 100644
--- a/src/components/cursor-hand.js
+++ b/src/components/super-cursor.js
@@ -1,9 +1,9 @@
-AFRAME.registerComponent("cursor-hand", {
-  dependencies: ['raycaster'],
+AFRAME.registerComponent("super-cursor", {
+  dependencies: ["raycaster"],
   schema: {
-    cursor: {type: "selector"},
-    maxDistance: {type: "number", default: 3},
-    minDistance: {type: "number", default: 0.5}
+    cursor: { type: "selector" },
+    maxDistance: { type: "number", default: 3 },
+    minDistance: { type: "number", default: 0.5 }
   },
 
   init: function() {
@@ -14,27 +14,26 @@ AFRAME.registerComponent("cursor-hand", {
     this.enabled = true;
     this.isGrabbing = false;
 
-    document.addEventListener("mousedown", (e) => {
+    document.addEventListener("mousedown", e => {
       this.data.cursor.emit("action_grab", {});
     });
 
-    document.addEventListener("mouseup", (e) => {
+    document.addEventListener("mouseup", e => {
       this.data.cursor.emit("action_release", {});
     });
 
-    document.addEventListener("wheel", (e) => {
-      if (this.isGrabbing)
-        this.currentDistanceMod += e.deltaY/10;
+    document.addEventListener("wheel", e => {
+      if (this.isGrabbing) this.currentDistanceMod += e.deltaY / 10;
     });
 
-    window.addEventListener('enter-vr', e => {
+    window.addEventListener("enter-vr", e => {
       if (AFRAME.utils.device.checkHeadsetConnected() || AFRAME.utils.device.isMobile()) {
         this.enabled = false;
         this.data.cursor.setAttribute("visible", false);
       }
     });
 
-    window.addEventListener('exit-vr', e => {
+    window.addEventListener("exit-vr", e => {
       this.enabled = true;
       this.data.cursor.setAttribute("visible", true);
     });
@@ -49,10 +48,10 @@ AFRAME.registerComponent("cursor-hand", {
 
     if (!this.isGrabbing) {
       const intersections = this.el.components.raycaster.intersections;
-      if(intersections.length > 0 && intersections[0].distance <= this.data.maxDistance) {
+      if (intersections.length > 0 && intersections[0].distance <= this.data.maxDistance) {
         isIntersecting = true;
         const point = intersections[0].point;
-        this.data.cursor.setAttribute('position', point);
+        this.data.cursor.setAttribute("position", point);
         this.currentDistance = intersections[0].distance;
         this.currentDistanceMod = 0;
       } else {
@@ -63,19 +62,22 @@ AFRAME.registerComponent("cursor-hand", {
     if (this.isGrabbing || !isIntersecting) {
       const head = this.el.object3D;
       const origin = head.getWorldPosition();
-      let direction = head.getWorldDirection();
-      const distance = Math.min(Math.max(this.data.minDistance, this.currentDistance - this.currentDistanceMod), this.data.maxDistance);
+      const direction = head.getWorldDirection();
+      const distance = Math.min(
+        Math.max(this.data.minDistance, this.currentDistance - this.currentDistanceMod),
+        this.data.maxDistance
+      );
       this.currentDistanceMod = this.currentDistance - distance;
       direction.multiplyScalar(-distance);
-      let point = new THREE.Vector3();
+      const point = new THREE.Vector3();
       point.addVectors(origin, direction);
-      this.data.cursor.setAttribute("position", {x: point.x, y: point.y, z: point.z});
+      this.data.cursor.setAttribute("position", { x: point.x, y: point.y, z: point.z });
     }
 
     if ((this.isGrabbing || isIntersecting) && !this.wasIntersecting) {
       this.wasIntersecting = true;
       this.data.cursor.setAttribute("material", "color: #00FF00");
-    } else if ((!this.isGrabbing && !isIntersecting) && this.wasIntersecting) {
+    } else if (!this.isGrabbing && !isIntersecting && this.wasIntersecting) {
       this.wasIntersecting = false;
       this.data.cursor.setAttribute("material", "color: #00EFFF");
     }
diff --git a/src/components/super-networked-interactable.js b/src/components/super-networked-interactable.js
new file mode 100644
index 0000000000000000000000000000000000000000..c5546ec87e35d7aa4648d15536f20b9815dff14d
--- /dev/null
+++ b/src/components/super-networked-interactable.js
@@ -0,0 +1,53 @@
+AFRAME.registerComponent("super-networked-interactable", {
+  schema: {
+    mass: { default: 1 },
+    counter: { type: "selector" }
+  },
+
+  init: function() {
+    this.counter = this.data.counter.components["networked-counter"];
+    this.hand = null;
+
+    NAF.utils.getNetworkedEntity(this.el).then(networkedEl => {
+      this.networkedEl = networkedEl;
+      if (!NAF.utils.isMine(networkedEl)) {
+        this.el.setAttribute("body", "type: dynamic; mass: 0");
+      } else {
+        this.counter.register(networkedEl);
+      }
+    });
+
+    this.grabStartListener = this._onGrabStart.bind(this);
+    this.ownershipLostListener = this._onOwnershipLost.bind(this);
+    this.el.addEventListener("grab-start", this.grabStartListener);
+    this.el.addEventListener("ownership-lost", this.ownershipLostListener);
+  },
+
+  remove: function() {
+    this.counter.deregister(this.el);
+    this.el.removeEventListener("grab-start", this.grabStartListener);
+    this.el.removeEventListener("ownership-lost", this.ownershipLostListener);
+  },
+
+  _onGrabStart: function(e) {
+    this.hand = e.detail.hand;
+    if (this.networkedEl && !NAF.utils.isMine(this.networkedEl)) {
+      if (NAF.utils.takeOwnership(this.networkedEl)) {
+        console.log("1");
+        this.el.setAttribute("body", `mass: ${this.data.mass};`);
+        this.counter.register(this.networkedEl);
+      } else {
+        console.log("2");
+        this.el.emit("grab-end", { hand: this.hand });
+        this.hand = null;
+      }
+    }
+  },
+
+  _onOwnershipLost: function(e) {
+    this.el.setAttribute("body", "mass: 0");
+    this.el.emit("grab-end", { hand: this.hand });
+    this.hand = null;
+    this.counter.deregister(this.el);
+  }
+});
diff --git a/src/components/super-spawner.js b/src/components/super-spawner.js
index 0b8a0354dbede1113858b11eaeeac00869240d1a..efff5e9c871e458069466646bf5a2aacb762a68a 100644
--- a/src/components/super-spawner.js
+++ b/src/components/super-spawner.js
@@ -1,7 +1,7 @@
 AFRAME.registerComponent("super-spawner", {
   schema: {
-    template: { default: '' },
-    spawn_position: {type: "vec3"}
+    template: { default: "" },
+    spawn_position: { type: "vec3" }
   },
 
   init: function() {
@@ -13,25 +13,25 @@ AFRAME.registerComponent("super-spawner", {
   _spawn: function(hand) {
     const entity = document.createElement("a-entity");
 
-    entity.setAttribute('networked', 'template:' + this.data.template);
+    entity.setAttribute("networked", "template:" + this.data.template);
 
     const componentinitialized = new Promise((resolve, reject) => {
-        entity.addEventListener("componentinitialized", (e) => {
-        if(e.detail.name == "grabbable") {
+      entity.addEventListener("componentinitialized", e => {
+        if (e.detail.name == "grabbable") {
           resolve();
         }
       });
     });
 
     const bodyloaded = new Promise((resolve, reject) => {
-        entity.addEventListener("body-loaded", (e) => {
-          resolve();
+      entity.addEventListener("body-loaded", e => {
+        resolve();
       });
     });
 
     Promise.all([componentinitialized, bodyloaded]).then(() => {
-      hand.emit("action_grab", {targetEntity: entity});
-      entity.emit('grab-start', {hand: hand});
+      hand.emit("action_grab", { targetEntity: entity });
+      entity.emit("grab-start", { hand: hand });
     });
 
     entity.setAttribute("position", this.data.spawn_position || this.el.getAttribute("position"));
diff --git a/src/room.html b/src/room.html
index eef387bc25ea88f937d6e951d8b9e697de17567e..5826cfbf9a781f06f2fbd16078927426fab7673d 100644
--- a/src/room.html
+++ b/src/room.html
@@ -92,7 +92,7 @@
                     gltf-model="#interactable-duck"
                     scale="2 2 2"
                     class="collidable" 
-                    remote-dynamic-body="counter: #counter; mass: 5;"
+                    super-networked-interactable="counter: #counter; mass: 5;"
                     body="type: dynamic; mass: 5; shape: box;"
                     grabbable
                     stretchable
@@ -105,7 +105,7 @@
                     colliderEndEvent: collisions; colliderEndEventProperty: clearedEls;
                     grabStartButtons: action_grab; grabEndButtons: action_release;
                     stretchStartButtons: action_grab; stretchEndButtons: action_release;
-                    dargDropStartButtons: action_grab; dragDropEndButtons: action_release;
+                    dragDropStartButtons: action_grab; dragDropEndButtons: action_release;
                     "
                 collision-filter="collisionForces: false"
                 physics-collider
@@ -152,8 +152,8 @@
                 look-controls="pointerLockEnabled: true;"
             >
                 <a-entity
-                    id="cursor-hand"
-                    cursor-hand="cursor: #3d-cursor"
+                    id="super-cursor"
+                    super-cursor="cursor: #3d-cursor"
                     position="0 0 0"
                     raycaster="objects: .collidable; direction: 0 0 -1;"
                 ></a-entity>
diff --git a/src/room.js b/src/room.js
index 4e6a569b1aaaf1df73c4f3b7d2b2197c71d63fff..dea6a536fd6c49c312a20a4262dd9b6e3f2c80df 100644
--- a/src/room.js
+++ b/src/room.js
@@ -46,10 +46,10 @@ import "./elements/a-gltf-entity";
 import "aframe-physics-system";
 import "aframe-physics-extras";
 import "super-hands";
-import "./components/remote-dynamic-body";
+import "./components/super-networked-interactable";
 import "./components/networked-counter";
 import "./components/super-spawner";
-import "./components/cursor-hand";
+import "./components/super-cursor";
 import "./components/event-repeater";
 
 import { promptForName, getCookie, parseJwt } from "./utils/identity";