Guide Teleporter-Weighted Pressure Plate Glitch

putianyi888

Terrarian
It is (well?) known that developers have had 'fixed' the infinite-loop caused by teleporters connected to weighted pressure plates. However, the way the developers used is too naive so that another glitch arises. Let me show the glitch before explaining it.

379.png
380.png

The schematic is quite simple.

If the player stands on the left one and switches the switch on the middle teleporter, then the player will be teleported to the middle teleporter and trigger the weighted pressure plate. Although the blue wire wants to teleport the player to the right, the developers say "No" and leave the player on the middle teleporter. This is what has been described by the developers.

However, if the player switches the left switch at the begining, it will be teleported twice between the left two teleporters and end up on the left teleporter. This result is confusing and I didn't know why until I read the source code.

This thread is to explain why this glitch happens so that we can predict or even utilize this glitch. I think this is a new discovery since the pinned thread agrees that we didn't know this issue very well.

I would be happy if the pinned thread can add a reference to this thread.

When a wire is activated

A traversing process is called, running a BFS algorithm from the source of activation to traverse all tiles connected by the wire. FYI, the order of searching directions of the BFS algorithm is down-up-right-left.

Throughout this process, the game takes down the locations of the first teleporter tile and the last teleporter tile that are traversed. Then the game calls the teleportation process.

The teleportation process

Let's assume that the game has decided to teleport between teleporters A and B. Normally we believe that A and B are the same and hence interchangable, but they are not. Let A denote the first teleporter tile and B denote the last teleporter tile.

A teleporter tile is 1/3 of a teleporter. It can be either the left, middle or right tile. different tile has different teleportation zone highlighted below:
216.png

If the tile is (rectangular) halfbrick, then the teleportation zone will be half a tile lower. For triangular halfbricks, the zones remain the same.

The teleportation fails in the first place if the teleportation zones of A and B overlap and the position of A is not lower than B. This prevents teleportation between two tiles of the same teleporter but also allows it when one of the tiles is halfbrick.

The teleportation has 4 steps:
Step 1: all players on A are teleported to B.
Step 2: all NPCs on A are teleported to B.
Step 3: all players on B are teleported to A.
Step 4: all NPCs on B are teleported to A.

You must have a bunch of questions now. Let me add some notes.
Note 1: every time a player or an NPC is teleported, the property field teleporting of the player or NPC is set to true. As long as a player or an NPC has true teleporting, it will not be teleported.
Note 2: after all 4 steps of a teleportation (not including the failed case), the teleporting of all players and NPCs are set to false.
Note 3: every time a player is teleported, the game checks if this teleportation triggers any weighted pressure plate(s). If so, a public static variable blockPlayerTeleportationForOneIteration is set to true before the activation of the pressure plate.
Note 4: as long as blockPlayerTeleportationForOneIteration is true, Step 1 and/or Step 3 will be skipped.
Note 5: blockPlayerTeleportationForOneIteration is set to false at the end of each iteration. the concept of iteration

Now everything should be clear. BTW, all players and NPCs are teleported in the same order as how they stay in the player array and NPC array, if you are curious.

Let's check the glitch at the beginning. Assume that the player stands on the left teleporter and triggers the left switch.
  • The left teleporter is regarded as A and the middle teleporter is regarded as B, because the left teleporter is traversed first.
  • Step 1 teleports the player to B and set the player's teleporting to true.
  • The player triggers the weighted pressure plate and set blockPlayerTeleportationForOneIteration to true.
  • Since the blue wire is activated, the associated wiring process is inserted.
    • A teleportation between the middle teleporter and the right teleporter happens, but the player is not teleported because blockPlayerTeleportationForOneIteration is true.
    • At the end of the teleportation, the player's teleporting is set to false.
    • At the end of the blue wire iteration, blockPlayerTeleportationForOneIteration is set to false.
  • Return to the A-B teleportation.
  • Nothing happens in Step 2 since there is no NPC involved.
  • In Step 3, the player is teleported back to A because both blockPlayerTeleportationForOneIteration and teleporting are false.
  • The player triggers the weighted pressure plate again, but it does't matter. (It does matter if an NPC is with the player at the beginning.)
  • Nothing happens in Step 4 since there is no NPC involved.
For the case when the switch on the middle is triggered:
  • The left teleporter is regarded as B and the middle teleporter is regarded as A, because the middle teleporter is traversed first.
  • Step 1 does nothing because there is no player on A.
  • Nothing happens in Step 2 since there is no NPC involved.
  • Step 3 teleports the player to A and set the player's teleporting to true.
  • The player triggers the weighted pressure plate and set blockPlayerTeleportationForOneIteration to true.
  • Since the blue wire is activated, the associated wiring process is inserted.
    • A teleportation between the middle teleporter and the right teleporter happens, but the player is not teleported because blockPlayerTeleportationForOneIteration is true.
    • At the end of the teleportation, the player's teleporting is set to false.
    • At the end of the blue wire iteration, blockPlayerTeleportationForOneIteration is set to false.
  • Return to the A-B teleportation.
  • Nothing happens in Step 4 since there is no NPC involved.
See the difference?

So this glitch is a common issue for programmers, when different process share the same variable. In this case, the shared variables are blockPlayerTeleportationForOneIteration and teleporting.

That's it. Hope you enjoy.

Applications

Now we can teleport NPCs on different teleporters together, which was impossible before. Showcase
 
Last edited:
Ok, so to summarize the new things that were discovered here:
  • When a player is teleported onto a weighted pressure plate, the plate triggers immediately. (Unlike regular pessure plates, which don't do anything.)
Due to this you can do other stuff between the forward and backward steps of a teleportation. For instance:
  • You can trigger another set of teleporters, which will reset the teleporting flag of every npc and player.
And you can actually do this with a completely unrelated set of teleporters. As long as you have at least two teleporters connected to the weighted pressure plate, and their zones don't overlap, this will always work.

1572096056040.png


Which means:
  • You can make things teleport back to the pad they came from.
Which is not normally something you can do directly.
Another side effect of using weighted plates, is that they also set the blockPlayerTeleportationForOneIteration flag. In case of this setup that does not matter though, since the flag gets reset in Wiring.LogicGatePass.
Though you can also use this mechanic to your advantage. Since npc are unaffected by the flag, you can use this sort them out.

One more thing to add:
Note 3: every time a player is teleported, the game checks if this teleportation triggers any weighted pressure plate(s). If so, a public static variable blockPlayerTeleportationForOneIteration is set to true before the activation of the pressure plate.
blockPlayerTeleportationForOneIteration actually gets set every time a weighted plate or player above logic sensor is triggered by any means. Which why you can't use them trigger teleporters for players.

So yeah, that's pretty interesting, definitely not something I would have ever noticed. :p
However, I'm not entirely sure how useful it is. It's kinda similar how you can double triggers doors due to the game resetting Wiring.runnig too early. Which is also very interesting, but not incredibly practical.
This might be handy for building teleporter hubs though.

So this glitch is a common issue for programmers, when different process share the same variable. In this case, the shared variables are blockPlayerTeleportationForOneIteration and teleporting.
And this is one of the many reasons why you shouldn't use global variables to begin with. :)
 
Last edited:
I suppose that the inserted wiring process would take over all variables in the parent process (e.g. logic gates to be activated) and mess up the parent process. I haven't done any experiment. To make it safe, don't place weighted pressure plates on teleporters unless you are ready for unexpected results.
 
Back
Top Bottom