3

My goal is to rotate an entity around a fixed point by 180 degrees. The following is what I have tried so far:

Rotating an entity by x degrees around a point a known distance away is easy enough:

execute positioned ~ ~ ~10 facing entity @s feet rotated ~x ~ positioned ^ ^ ^10 run teleport @s ~ ~ ~

If, as in my case, you want to teleport by exactly 180 degrees it is even easier:

teleport @s ~ ~ ~20

However, I haven't been able to come up with a simple method to rotate an entity around a fixed point in space. The above methods rely on knowing how far away the point around which to rotate is from the entity (in this case exactly 10 blocks down z, relative to the entity). To keep things simple, I stuck with just the xz plane.

The only working method I have found employs a systematic approach using AECs (again around the point 30.5 ~ 30.5):

#> the following is not optimized, purely for clarity's sake
summon area_effect_cloud 30.5 ~ 30.5 {Duration:2,Tags:["rot.origin"]}

# Calculate offset on each axis from Entity E to the AEC (looking down from above): 
#  E-------------
#  |            |
#  |-----------AEC------------|
#               |             |
#               |-------------E*
# Then move the AEC by the offset amount on each axis so it ends up at E*
# Finally, teleport E to E*

# get the offset from the entity to the AEC
execute store result score @s pos.x run data get entity @s Pos[0] 1000
execute store result score @s pos.z run data get entity @s Pos[2] 1000
scoreboard players set @e[tag=rot.origin] pos.x 30500
scoreboard players set @e[tag=rot.origin] pos.z 30500
scoreboard players set @e[tag=rot.origin] offset.x 30500
scoreboard players set @e[tag=rot.origin] offset.z 30500
scoreboard players operation @e[tag=rot.origin] offset.x -= @s pos.x
scoreboard players operation @e[tag=rot.origin] offset.z -= @s pos.z

# move AEC and teleport
scoreboard players operation @e[tag=rot.origin] pos.x += @s offset.x
scoreboard players operation @e[tag=rot.origin] pos.z += @s offset.z
execute as @e[tag=rot.origin] store result entity @s Pos[0] 0.001 run scoreboard players get @s pos.x
execute as @e[tag=rot.origin] store result entity @s Pos[2] 0.001 run scoreboard players get @s pos.z

teleport @s @e[tag=rot.origin,limit=1]
kill @e[tag=rot.origin]

This approach is undoubtedly slow, even after optimizing the selectors into separate functions.

The closest simple solution I found was the following: the entity rotates around the point 30.5 ~ 30.5; but it again relies on knowing the distance to the player (note the 10 block offset):

execute positioned 30.5 ~ 30.5 facing entity @s feet run teleport @s ^10 ^ ^

This is a bit of a mess of a post, I did my best to share everything I've tried so far. If anyone has any ideas on how to this in a simpler fashion I'd love to hear your thoughts. Here is a brief summary of my intentions: Rotate the entity...

  • ...around a fixed, known point; like 30.5 ~ 30.5
  • ...when the entity is an arbitrary distance away, be it 5, 10 or 1412.2222 blocks, from that point.
  • Can you specify what version you're using? – Andrew Jul 10 at 22:34
  • @Andrew The commands are for 1.13+, so that's what I'd suspect. – ExpertCoder14 Jul 11 at 3:21
  • @Andrew I am on 1.16.1, so anything outside of the very latest snapshots goes. – Camp bell Jul 11 at 9:26
1

If I understand it right, you want to mirror E on P to get E'. That's basically just the same as moving E to P and then moving the same distance again in the same direction.

To also change the viewing direction, you can simply add 180°. Minecraft will already handle the cases over 360° properly for you. Unlike the movement, this would get more complicated in 3D.

Actually figuring out the distance between E and P and getting that to be usable in commands is the difficult part. Luckily I did something similar already here.
The steps are:
(0. Preparation)

  1. Get coordinates of the entity at E and the location P into scoreboards.
  2. Subtract the E scores from the P scores to get the difference/distance. I'll actually do this by multiplying the E scores with -1, then adding P to them, that way I can do it for multiple entities at once.
  3. Add that to the P scores to get E'.
  4. Write that back into the entity to move it.
  5. Rotate it.

The commands for that, in this example rotating every armour stand around x=12 z=34 (with 0.02 blocks precision):

/scoreboard objectives add const dummy
/scoreboard objectives add x dummy
/scoreboard objectives add z dummy
/scoreboard players set -1 const -1

/scoreboard players set P x 600
/scoreboard players set P z 1700
/execute as @e[type=armor_stand] store result score @s x run data get entity @s Pos[0] 50
/execute as @e[type=armor_stand] store result score @s z run data get entity @s Pos[2] 50

/scoreboard players operation @e[type=armor_stand] x *= -1 const
/scoreboard players operation @e[type=armor_stand] z *= -1 const
/scoreboard players operation @e[type=armor_stand] x += P x
/scoreboard players operation @e[type=armor_stand] z += P z

/scoreboard players operation @e[type=armor_stand] x += P x
/scoreboard players operation @e[type=armor_stand] z += P z

/execute as @e[type=armor_stand] store result entity @s Pos[0] double 0.02 run scoreboard players get @s x
/execute as @e[type=armor_stand] store result entity @s Pos[2] double 0.02 run scoreboard players get @s z

/execute as @e[type=armor_stand] at @s run tp @s ~ ~ ~ ~180 ~

Some more explanation:

  • Using a scoreboard named const for numbers is somewhat of a coding standard in Minecraft commands.
  • Scoreboards only hold integers, so you need to multiply the coordinates by 50 and later by 0.02 to get higher precision. That gives you 12*50=600 and 34*50=1700.
  • Pos is an array with the X, Y and Z coordinate in it. If the entity is not a player, you can write into it to teleport the entity. If it is a player, you'll need to use a dummy entity and teleport the player to it afterwards (in the same tick if it goes into unloaded chunks).
  • I've used the name "E" from your post. You would probably want to choose a better fake player name. "E" could in theory be a very old player name, I think. You can start it with e.g. $ to prevent such collisions or with #, which also hides it from scoreboard displays.
| improve this answer | |
  • I don't know how closely you read my example code, but your solution is actually identical to the one I posted with my question! Unfortunately, all those entity look-ups (@e) are really, really slow; which is why I was looking for a simpler, faster solution. Thanks for your description all the same, you explained it much better than I did! – Camp bell Sep 21 at 14:57
  • I think you have some more complications in your version, for example a dummy entity in the middle is not needed. And tag lookups are extremely efficient. This system should have no measurable performance impact at all (because if you move enough entities at once to have an impact, you already have a LOT of entities). But in general, yes, I read and answered this question during one of my quick rounds recently, so I might have missed some things. – Fabian Röling Sep 21 at 18:04
-1

I'm definitely not an expert in stuff like this so forgive me if this doesn't work, but you could potentially make the entity have an invisible armor stand with a tag riding it or on a /setblock and teleport the entity relative to the armor stand.

| improve this answer | |
  • I'm not sure I completely understand. Do you think you could provide a simple example, maybe some commands, to show what you mean? – Camp bell Jul 11 at 12:05
  • What does /setblock have to do with the question? – Fabian Röling Sep 20 at 15:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.