Posted February 16, 20214 yr 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 February 16, 20214 yr by Cobra111783
February 16, 20214 yr Author 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).
February 16, 20214 yr Author 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 February 16, 20214 yr by Cobra111783
February 16, 20214 yr Author That's much cleaner! Thanks! 🙂 Updated solution for future knowledge-seekers: ServerLifecycleHooks.getCurrentServer().execute(() -> { [YOUR TASK HERE] });
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.