Skip to content

Instantly share code, notes, and snippets.

@GrantGryczan
Last active April 1, 2023 11:04
Show Gist options
  • Save GrantGryczan/f0a51fc195f76da570d67826974bf2de to your computer and use it in GitHub Desktop.
Save GrantGryczan/f0a51fc195f76da570d67826974bf2de to your computer and use it in GitHub Desktop.
Guide to Working Around MC-227930

Grant's Guide to Working Around MC-227930 Being Resolved as "Works As Intended"

As of Minecraft 1.17, we can't forceload a chunk, summon an entity into the chunk, and immediately select that entity, all in the same tick. In fact, we can't select any entities in newly loaded chunks until an arbitrary amount of ticks have passed while the chunk fully loads. I've come up with a few ways to work around this, depending on your use case, but none of these solutions are flawless. I may edit this post to include more or make revisions in the future. If you have feedback or suggestions on any of this, feel free to post a comment or message me on Discord @Grant#2604.

1. Wait for the chunk to be loaded.

  • Because chunks now take an arbitrary, unknown amount of ticks to fully load, we can't just schedule a constant time ahead. So there's not really any way to do this other than running a function that tries to select your entity, and schedules itself to run again every tick it doesn't find it. Once it does find it, do whatever you need to do.
  • This isn't a viable solution if the information needed to do something with the entity is time-sensitive and may have changed or became unavailable while the chunk was loading. For example, if you need to copy data from a player to an entity in a newly loaded chunk, you can't be certain the player is still online by the time the chunk finishes loading.

2. Summon the entity in a chunk you know is loaded, execute as it, tp @s into the newly loaded chunk, and select it with @s.

  • This solution works because @s is selectable regardless of whether it's in a fully loaded chunk.
  • It's not always possible to be sure an area is loaded unless you additionally use solution #1. Spawn chunks can move. Force-loaded chunks require a delay. Even chunks loaded by the player don't load synchronously, and so they can't be guaranteed to be selectable unless you test it. So if you do this, be careful not to assume a chunk is loaded.
  • This isn't a viable solution if you can't guarantee any chunks to be loaded, and you can't afford solution #1 to wait for any chunks to be loaded.
  • This also isn't a viable solution if you need to select the entity in the ticks immediately following it being summoned, because after the function being run from execute as finishes, the context which allows selecting the entity via @s no longer exists.

3. Summon an entity with a custom UUID tag.

  • If an entity with a custom UUID is in memory (i.e. if it was summoned or has ever been loaded before during the current session), you can select it directly by its UUID. For example, summon minecraft:marker ~ ~ ~ {UUID:[I;1,2,3,4]} will create an entity that is immediately selectable via 00000001-0000-0002-0000-000300000004 for as long as the entity is in memory. If you forceload the chunk the entity is in, this guarantees the entity will (almost, see next point) always be selectable by its UUID, starting as soon as it is summoned.
  • The entity will not be immediately selectable if the server (or singleplayer world) restarts. After a restart, it will only be selectable after a few ticks have passed for the chunk to fully load and the entity to be in memory again. If that's a problem for you, this isn't a viable solution.
  • This also isn't a viable solution if you don't have a constant set of known, static entities, and you can't guarantee there to be no UUID conflicts in your pack. Only one entity should have a particular UUID at a time.
  • Do not kill and re-summon an entity with the same UUID! Killed entities are not always completely removed from memory, so summoning a new one with the same UUID as a previously killed one may create a UUID conflict.

4. loot spawn an item into the newly loaded chunk, and replace the item entity with your entity once it is selectable.

  • To solve the issue with solution #1 where necessary information may be time-sensitive, use loot table functions (item modifiers) to perform the NBT modifications as soon as the entity is summoned, rather than having a wait a few ticks for the modifications to be performed.
  • If you want to use the data command to perform your NBT modifications rather than being restricted to any limitations of loot table functions or item modifiers, just perform your data operations in storage beforehand, and then use an item modifier on the loot table to copy the NBT from storage to the item.
  • This still has the issue of the entity not being immediately selectable, and it requires detecting the item after it is summoned (ideally by running a function that schedules itself with 1t append until it finds the item entity) and replacing the item entity with your desired entity.
  • For example, if you want to summon a minecraft:marker, you will need to wait for your minecraft:item to be selectable, and then summon minecraft:marker in its place, copying the item's Item.tag to the marker's data and killing the item.
@maybenotconnor
Copy link

Hi, so as the reporter of the bug, like many I'm trying to work around this in my datapack. I have been using a simple delay but have been experimenting with the @s method (#2). I have discovered that while it will execute the commands, it will not execute them in the new chunk the entity was moved to. For example:

summon armor stand ~ ~ ~
execute as @e[type=armor_stand] run function debug:stand

(debug:stand):
execute as @s in the_nether run tp ~ ~ ~
forceload add ~ ~
tp @p @s
kill @s

In the second function the lower 3 commands are run in the overworld at the previous location of the armor stand, which means that it cannot even 'kill @s' since it is not there. The player is teleported to where the stand was summoned.

Just pointing it out. Any ideas on alternatives?
Really hoping for that sync forceload option to be added because our datapacks are practically broken until then.

@GrantGryczan
Copy link
Author

GrantGryczan commented Jun 15, 2021

I have discovered that while it will execute the commands, it will not execute them in the new chunk the entity was moved to.

@maybenotconnor After tping, you must execute at @s run another function with the rest of the commands you want to run at the new location. A function's execution position never changes without an execute command to change it.

Also, worth noting that as @s never does anything under any circumstance. You can just remove that. Additionally, the forceload command you have there doesn't seem to have any purpose. The chunk doesn't need to be loaded in order to teleport to it. In fact, the armor stand doesn't seem to be necessary either. Couldn't you just replace all of this with a single command?

execute as @p in minecraft:the_nether run tp @s ~ ~ ~

But perhaps the commands you provided are just an example, and they don't indicate what you're actually trying to do.

In any case, hope this helps!

@maybenotconnor
Copy link

maybenotconnor commented Jun 15, 2021

@maybenotconnor After tping, you must execute at @s run another function with the rest of the commands you want to run at the new location. A function's execution position never changes without an execute command to change it.

@GrantGryczan Ah yes I forgot to put that in my comment, but that is how I've been testing as well. More like this:
execute at @s [player] summon marker ~ ~ ~
execute as @e[type=marker] run function debug:2

execute in the_nether run tp @s ~ ~ ~
execute at @s run function debug:3

execute at @s run forceload add ~ ~
execute at @s run tp @p @s
summon pig or whatever, just testing

Afterwards the marker is in the nether, but the pig is in the overworld, along with the forced chunk, etc.

The use case I'm doing requires transfer of Pos data to the marker as well, but I am leaving it out since the dimension switch is the same issue.
The forceload is included so I can determine where the command is executing by querying after, and the as @s is just to be sure haha.

This example is heavily simplified for what I'm trying to do, this is just what demonstrates the problem. This is for my Mystcraft Datapack, for a feature similar to homes.

Did you happen to get this technique working in VT Homes? If you did I can just study how it was done there, but I'm not looking to do something as complicated - checks or feedback etc.
Thank you Grant

@hqics
Copy link

hqics commented Jun 15, 2021

@maybenotconnor You are experiencing MC-152997.
You could use something like execute in the_nether positioned as @s rotated as @s run tp @p ~ ~ ~ ~ ~, without making the entity switch dimensions.

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