Jump to content

[1.12] Threading crash when accessing chunks from GUI


Recommended Posts

Posted

Hi all,

 

I have a GUI in my mod that displays a map of nearby chunks with their load status and whether or not they are "force loaded" by my mod. In 1.7, it worked fine, in 1.12, it occasionally crashes with this error:

 

net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:835)

 

(Sorry, I don't have the full stack trace on hand, I'll add it when I can)

 

This error actually happens in the main thread, not my GUI code, and I've had it before when doing actions in other threads that are not thread-safe.

 

The code I'm running in my GUI is this:

 

private void drawChunkMap(final int i, final int j) {

		if (Mill.serverWorlds.isEmpty()) {
			return;
		}

		final int windowXstart = (width - getXSize()) / 2;
		final int windowYstart = (height - getYSize()) / 2;

		final World world = Mill.serverWorlds.get(0).world;
		final MillWorld mw = Mill.serverWorlds.get(0);

		GL11.glDisable(2896 /* GL_LIGHTING */);
		GL11.glDisable(2929 /* GL_DEPTH_TEST */);

		final int startX = (getXSize() - (chunkMapSizeInBlocks / 8)) / 2;
		final int startY = (getYSize() - (chunkMapSizeInBlocks / 8)) / 2;

		final int posXstart = (player.chunkCoordX * 16) - (chunkMapSizeInBlocks / 2);
		final int posZstart = (player.chunkCoordZ * 16) - (chunkMapSizeInBlocks / 2);

		final int mouseX = (((i - startX - windowXstart) / 2) * 16) + posXstart;
		final int mouseZ = (((j - startY - windowYstart) / 2) * 16) + posZstart;

		drawGradientRect(startX - 2, startY - 2, startX + (chunkMapSizeInBlocks / 8) + 2,
				startY + (chunkMapSizeInBlocks / 8) + 2, 0x20000000, 0x20000000);

		final ArrayList<String> labels = new ArrayList<String>();

		for (int x = posXstart; x < (posXstart + chunkMapSizeInBlocks); x += 16) {
			for (int z = posZstart; z < (posZstart + chunkMapSizeInBlocks); z += 16) {

				int colour = 0;
				if (!world.isChunkGeneratedAt(x / 16, z / 16)) {
					colour = 0x40111111;
				} else {
					final Chunk chunk = world.getChunkProvider().provideChunk(x / 16, z / 16);
					if (chunk.isLoaded()) {
						colour = 0xc000ff00;
					} else {
						colour = 0xc0ff0000;
					}
					drawPixel(startX + ((x - posXstart) / 8), startY + ((z - posZstart) / 8), colour);

					if ((mouseX == x) && (mouseZ == z)) {
						labels.add(MLN.string("chunk.chunkcoords", "" + (x / 16) + "/" + (z / 16)));
					}
				}

			}
		}

		// copy to avoid ConcurrentModificationException
		final ArrayList<Building> buildings = new ArrayList<Building>(mw.allBuildings());

		for (final Building b : buildings) {
			if (b.isTownhall && (b.winfo != null) && (b.villageType != null)) {
				for (int x = b.winfo.mapStartX; x < (b.winfo.mapStartX + b.winfo.length); x += 16) {
					for (int z = b.winfo.mapStartZ; z < (b.winfo.mapStartZ + b.winfo.width); z += 16) {
						if ((x >= posXstart) && (x <= (posXstart + chunkMapSizeInBlocks)) && (z >= posZstart)
								&& (z <= (posZstart + chunkMapSizeInBlocks))) {
							int colour;

							if (b.villageType.lonebuilding) {
								colour = 0xf0990099;
							} else {
								colour = 0xf00000ff;
							}

							drawPixel(startX + ((x - posXstart) / 8) + 1, startY + ((z - posZstart) / 8) + 1, colour);

							if ((mouseX == x) && (mouseZ == z)) {
								labels.add(MLN.string("chunk.village", b.getVillageQualifiedName()));
							}
						}
					}
				}
			}
		}

		boolean labelForced = false;

		for (final ChunkPos cc : ForgeChunkManager.getPersistentChunksFor(world).keys()) {
			if (((cc.x * 16) >= posXstart) && ((cc.x * 16) <= (posXstart + chunkMapSizeInBlocks))
					&& ((cc.z * 16) >= posZstart) && ((cc.z * 16) <= (posZstart + chunkMapSizeInBlocks))) {
				drawPixel(startX + (((cc.x * 16) - posXstart) / 8), startY + (((cc.z * 16) - posZstart) / 8) + 1,
						0xf0ffffff);

				if ((mouseX == (cc.x * 16)) && (mouseZ == (cc.z * 16)) && !labelForced) {
					labels.add(MLN.string("chunk.chunkforced"));
					labelForced = true;
				}
			}
		}

		if (!labels.isEmpty()) {
			int stringlength = 0;

			for (final String s : labels) {
				final int w = fontRenderer.getStringWidth(s);
				if (w > stringlength) {
					stringlength = w;
				}
			}

			drawGradientRect((i - 3 - windowXstart) + 10, j - 3 - windowYstart,
					((i + stringlength + 3) - windowXstart) + 10, (j + (11 * labels.size())) - windowYstart, 0xc0000000,
					0xc0000000);

			for (int si = 0; si < labels.size(); si++) {
				fontRenderer.drawString(labels.get(si), (i - windowXstart) + 10, (j - windowYstart) + (11 * si),
						0x909090);
			}

		}

		GL11.glEnable(2896 /* GL_LIGHTING */);
		GL11.glEnable(2929 /* GL_DEPTH_TEST */);

	}

 

Can anybody confirm that it is my calls to the chunk provider that are forbidden from a GUI? And if that's the case, is there a recommanded way of dealing with this? I could have the data be pre-calculated in the main thread, but it would be an ugly hack...

 

Thanks

Posted (edited)

The full error would be good. But I am suspecting a dictionary change while you are reading the chunks. But I can only confirm with the whole error.

Edit: I am stupid. You are not modifying anything. But yet, a full error would help :D

Edited by SatyPardus
Posted

I realise I'm not supposed to do this, but as a debugging tool for SP-only usage it worked fine in 1.7. I'm just wondering if anybody can confirm that yes, you can no longer access chunks for other threads than the main one in 1.12. The Client-Server thing is not the real issue there, I assume I'd have the same problems if I was running that code in a thread split from the main server thread.

 

After that I could of course fix it by using packets, it's just a lot more work for a very side feature.

 

And those static references are because my mod requires a large amount of world-specific data that can't be accessed via Minecraft means like DimensionManager.

Posted

It worked in 1.7. I've had thousands of players over the four years of the 1.7 version with this bug never reported, I saw it myself and had it reported to me several times for 1.12 in two days of having an alpha out.

 

WorldSavedData is great but not suitable for saving the amount of data I need. It's not the perfect solution for everything. For one thing it requires saving everything to NBT, which is not cool for saving thousands of building points for planned constructions. Plus it does't allow you to finally control what gets sent to the client and what doesn't; in my case just sending everything would be a waste of bandwidth.

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



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • I tried do download the essential mod to my mod pack but i didnt work. I paly on 1.21 and it should work. I use neoforge for my modding. The weird things is my friend somehow added the mod to his modpack and many others that I somehow can´t. Is there anything i can do? 
    • Thanks, I've now installed a slightly newer version and the server is at least starting up now.
    • i have the same issue. Found 1 Create mod class dependency(ies) in createdeco-1.3.3-1.19.2.jar, which are missing from the current create-1.19.2-0.5.1.i.jar Found 11 Create mod class dependency(ies) in createaddition-fabric+1.19.2-20230723a.jar, which are missing from the current create-1.19.2-0.5.1.i.jar Detailed walkthrough of mods which rely on missing Create mod classes: Mod: createaddition-fabric+1.19.2-20230723a.jar Missing classes of create: com/simibubi/create/compat/jei/category/sequencedAssembly/JeiSequencedAssemblySubCategory com/simibubi/create/compat/recipeViewerCommon/SequencedAssemblySubCategoryType com/simibubi/create/compat/rei/CreateREI com/simibubi/create/compat/rei/EmptyBackground com/simibubi/create/compat/rei/ItemIcon com/simibubi/create/compat/rei/category/CreateRecipeCategory com/simibubi/create/compat/rei/category/WidgetUtil com/simibubi/create/compat/rei/category/animations/AnimatedBlazeBurner com/simibubi/create/compat/rei/category/animations/AnimatedKinetics com/simibubi/create/compat/rei/category/sequencedAssembly/ReiSequencedAssemblySubCategory com/simibubi/create/compat/rei/display/CreateDisplay Mod: createdeco-1.3.3-1.19.2.jar Missing classes of create: com/simibubi/create/content/kinetics/fan/SplashingRecipe
    • The crash points to moonlight lib - try other builds or make a test without this mod and the mods requiring it
    • Do you have shaders enabled? There is an issue with the mod simpleclouds - remove this mod or disable shaders, if enabled  
  • Topics

×
×
  • Create New...

Important Information

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