Skip to content

Instantly share code, notes, and snippets.

@silvester-pari
Last active February 6, 2024 21:59
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save silvester-pari/763efb2be9748d71a96d74d284604ced to your computer and use it in GitHub Desktop.
Save silvester-pari/763efb2be9748d71a96d74d284604ced to your computer and use it in GitHub Desktop.
[GATHER] Teleport Context Menu

Gather Teleport Context Menu

A simple script to add a "Teleport" context menu entry to the Gather interface.

How to use

Simply load up a Space on https://gather.town/, wait until the interface has loaded (you see the map and other players). Then, open up the browser's DevTools (e.g. by using F12) and copy&paste the following snippet. You should be able to see a "Teleport" entry in the other players' context menu list (same list where you can find "Locate on map", "Follow", "Spotlight"). By clicking it, you are directly teleported to that player.

Instead of copy-pasting it to the console, you could also save the snippet in the DevTools, or create a script in Tampermonkey or other browser plugins.

// Setup
const teleportString = 'Teleport'
const teleportIcon = '<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="people-arrows" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" class="svg-inline--fa fa-people-arrows fa-w-18 fa-lg"><path fill="currentColor" d="M96,128A64,64,0,1,0,32,64,64,64,0,0,0,96,128Zm0,176.08a44.11,44.11,0,0,1,13.64-32L181.77,204c1.65-1.55,3.77-2.31,5.61-3.57A63.91,63.91,0,0,0,128,160H64A64,64,0,0,0,0,224v96a32,32,0,0,0,32,32V480a32,32,0,0,0,32,32h64a32,32,0,0,0,32-32V383.61l-50.36-47.53A44.08,44.08,0,0,1,96,304.08ZM480,128a64,64,0,1,0-64-64A64,64,0,0,0,480,128Zm32,32H448a63.91,63.91,0,0,0-59.38,40.42c1.84,1.27,4,2,5.62,3.59l72.12,68.06a44.37,44.37,0,0,1,0,64L416,383.62V480a32,32,0,0,0,32,32h64a32,32,0,0,0,32-32V352a32,32,0,0,0,32-32V224A64,64,0,0,0,512,160ZM444.4,295.34l-72.12-68.06A12,12,0,0,0,352,236v36H224V236a12,12,0,0,0-20.28-8.73L131.6,295.34a12.4,12.4,0,0,0,0,17.47l72.12,68.07A12,12,0,0,0,224,372.14V336H352v36.14a12,12,0,0,0,20.28,8.74l72.12-68.07A12.4,12.4,0,0,0,444.4,295.34Z" class=""></path></svg>'
const checkInterval = 1000

// Add click listener to all player list divs (if not already present)
const listenToClick = () => {
  const allDivs = document.getElementsByTagName('div')
  for(let i = 0; i < allDivs.length; i++){
    const element = allDivs[i]
    if(element.tabIndex === 0) {
      if (!element.getAttribute('listenerOnClickAdded')) {
        element.setAttribute('listenerOnClickAdded', true)
        // using mousedown event to also capture right click
        element.addEventListener('mousedown', (e) => {
          setTimeout(() => addTeleportItem(e), 100)
        })
      }
    }
  }
}

// Add 'teleport' item (if not already present)
const addTeleportItem = (event) => {
  const playerName = event.target.closest('[tabIndex]').querySelector('span').innerHTML
  const allSpans = document.getElementsByTagName('span')
    
  if (!Array.from(allSpans).find(s => s.innerHTML === teleportString)) {
    for(let i = 0; i < allSpans.length; i++) {
      if (allSpans[i].innerHTML === 'Locate on map') {
          const element = allSpans[i].parentNode
          const container = element.parentNode
          const newElement = element.cloneNode(true)
          newElement.querySelector('div').innerHTML = teleportIcon
          newElement.querySelector('span').innerHTML = teleportString
          newElement.addEventListener('click', (e) => {
            e.preventDefault()
            teleportTo(playerName)
          })
          container.appendChild(newElement)
          break
      }
    }  
  }
}

// The teleport magic
const teleportTo = (playerName) => {
  const playersArr = Object.entries(game.players)
  const foundPlayer = playersArr.find(p => p[1].name === playerName)

  game.teleport(
    foundPlayer[1].map,
    foundPlayer[1].x,
    foundPlayer[1].y
  )
}

// Check every interval to handle new player joins and/or menu navigation
setInterval(() => {
  listenToClick()
}, checkInterval)
listenToClick()
@npfoss
Copy link

npfoss commented Jan 3, 2022

just FYI for anyone using this: we're about to restrict teleporting to moderators-only

I'm all for client-side modding in general though, love this haha

@silvester-pari
Copy link
Author

Seems like a good restriction! 👍

Client-side modding is fun, but would even be more fun if the UI CSS classes could be a bit more descriptive 😉

@ibanaso70
Copy link

I used it and quite helpful, but perhaps it looks it has a threshold usage or distance or time?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment