Jump to content

Recommended Posts

Posted (edited)

I need to retrieve a TileEntity from another thread. I have the BlockPos of the entity, as well as the appropriate ServerWorld. However, I keep running afoul of this line in net.minecraft.world.World (line 639):

} else if (!this.isRemote && Thread.currentThread() != this.mainThread) {
    return null;
} 

(Specifically, it's detecting that the current thread isn't the main thread)

 

I've also tried variations of this with no luck (Kotlin code):

val queue = SynchronousQueue<TileEntity>()
Minecraft.getInstance().enqueue {
    val tileEntity = dimension.getTileEntity(BlockPos(destination.x, destination.y, destination.z))
    queue.put(tileEntity)
}
val tileEntity = queue.take()

 

However, this seems to run on a rendering thread rather than the "main" thread. Is there any way to get a TileEntity from another thread? (FYI, the part of TileEntity in that I'm planning to access uses thread safe code, so I'm not concerned about that part of the equation.)

 

(Side note: Just getting the TileEntity from the ServerWorld worked in 1.12, so I'm guessing that "safety check" is new...)

Edited by Cobra111783
Posted

  

6 hours ago, diesieben07 said:

You cannot.

Minecraft's data structures are not threadsafe. You cannot access them from other threads.

 

No, it did not work. It might appear to work, most of the time. But as is the issue with threading issues, it will randomly fail with strange error messages every now and then - and then appear to work again the next time you try.

Hrm... I hadn't considered thread safety on MC's end... (derp!) Thanks for the clarification!

 

Is there a built-in mechanism to schedule a task to occur inside the main thread? I thought that's what Minecraft.getInstance().enqueue(...) was supposed to do, but maybe I'm misunderstanding the correct uses of that method (since it appears to run things inside a rendering thread).

Posted (edited)
39 minutes ago, diesieben07 said:

Yes, that is indeed what it does. If you use Minecraft#enqueue you schedule something to run on the client main thread, MinecraftServer#enqueue runs it on the server main thread. Both Minecraft as well as MinecraftServer also implement the Executor interface, as such you can use e.g. CompletableFuture.supplyAsync with it.

 

Switching to enqueueing it on the server (vs client) fixed it. Thanks for your help!

 

For anyone else looking for the solution, I used something like this:

var server = ServerLifecycleHooks.getCurrentServer();
server.enqueue(TickDelayedTask(server.getTicketCounter(), () -> { [YOUR TASK HERE] }));

 

(See below for better solution)

Edited by Cobra111783

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.