Posted November 18, 20222 yr I can't figure out why I get the exception "java.lang.IllegalStateException: Rendersystem called from wrong thread" Exception: Spoiler [11:10:48] [Server thread/ERROR] [minecraft/PacketUtils]: Failed to handle packet net.minecraft.network.protocol.game.ServerboundInteractPacket@7d415afd, suppressing error java.lang.IllegalStateException: Rendersystem called from wrong thread at com.mojang.blaze3d.systems.RenderSystem.constructThreadException(RenderSystem.java:152) ~[forge-1.19.2-43.1.52_mapped_official_1.19.2-recomp.jar%23183!/:?] {re:classloading,pl:runtimedistcleaner:A} at com.mojang.blaze3d.systems.RenderSystem.assertOnRenderThreadOrInit(RenderSystem.java:135) ~[forge-1.19.2-43.1.52_mapped_official_1.19.2-recomp.jar%23183!/:?] {re:classloading,pl:runtimedistcleaner:A} at com.mojang.blaze3d.platform.GlStateManager._clear(GlStateManager.java:700) ~[forge-1.19.2-43.1.52_mapped_official_1.19.2-recomp.jar%23183!/:?] {re:classloading,pl:runtimedistcleaner:A} at com.mojang.blaze3d.systems.RenderSystem.clear(RenderSystem.java:378) ~[forge-1.19.2-43.1.52_mapped_official_1.19.2-recomp.jar%23183!/:?] {re:classloading,pl:runtimedistcleaner:A} at net.minecraft.client.Minecraft.runTick(Minecraft.java:1104) ~[forge-1.19.2-43.1.52_mapped_official_1.19.2-recomp.jar%23183!/:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A} at net.minecraft.client.Minecraft.forceSetScreen(Minecraft.java:2123) ~[forge-1.19.2-43.1.52_mapped_official_1.19.2-recomp.jar%23183!/:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A} at com.talesofcraft.common.entity.QuestGiverVillager.mobInteract(QuestGiverVillager.java:80) ~[%23188!/:?] {re:classloading} at net.minecraft.world.entity.Mob.interact(Mob.java:1061) ~[forge-1.19.2-43.1.52_mapped_official_1.19.2-recomp.jar%23183!/:?] {re:classloading,pl:accesstransformer:B} at net.minecraft.world.entity.player.Player.interactOn(Player.java:996) ~[forge-1.19.2-43.1.52_mapped_official_1.19.2-recomp.jar%23183!/:?] {re:classloading,pl:accesstransformer:B} at net.minecraft.server.network.ServerGamePacketListenerImpl$1.performInteraction(ServerGamePacketListenerImpl.java:1550) ~[forge-1.19.2-43.1.52_mapped_official_1.19.2-recomp.jar%23183!/:?] {re:classloading} at net.minecraft.server.network.ServerGamePacketListenerImpl$1.onInteraction(ServerGamePacketListenerImpl.java:1561) ~[forge-1.19.2-43.1.52_mapped_official_1.19.2-recomp.jar%23183!/:?] {re:classloading} at net.minecraft.network.protocol.game.ServerboundInteractPacket$InteractionAction.dispatch(ServerboundInteractPacket.java:124) ~[forge-1.19.2-43.1.52_mapped_official_1.19.2-recomp.jar%23183!/:?] {re:classloading} at net.minecraft.network.protocol.game.ServerboundInteractPacket.dispatch(ServerboundInteractPacket.java:75) ~[forge-1.19.2-43.1.52_mapped_official_1.19.2-recomp.jar%23183!/:?] {re:classloading} at net.minecraft.server.network.ServerGamePacketListenerImpl.handleInteract(ServerGamePacketListenerImpl.java:1546) ~[forge-1.19.2-43.1.52_mapped_official_1.19.2-recomp.jar%23183!/:?] {re:classloading} at net.minecraft.network.protocol.game.ServerboundInteractPacket.handle(ServerboundInteractPacket.java:62) ~[forge-1.19.2-43.1.52_mapped_official_1.19.2-recomp.jar%23183!/:?] {re:classloading} at net.minecraft.network.protocol.game.ServerboundInteractPacket.handle(ServerboundInteractPacket.java:12) ~[forge-1.19.2-43.1.52_mapped_official_1.19.2-recomp.jar%23183!/:?] {re:classloading} at net.minecraft.network.protocol.PacketUtils.lambda$ensureRunningOnSameThread$0(PacketUtils.java:22) ~[forge-1.19.2-43.1.52_mapped_official_1.19.2-recomp.jar%23183!/:?] {re:classloading} at net.minecraft.server.TickTask.run(TickTask.java:17) ~[forge-1.19.2-43.1.52_mapped_official_1.19.2-recomp.jar%23183!/:?] {re:classloading} at net.minecraft.util.thread.BlockableEventLoop.doRunTask(BlockableEventLoop.java:143) ~[forge-1.19.2-43.1.52_mapped_official_1.19.2-recomp.jar%23183!/:?] {re:classloading,pl:accesstransformer:B} at net.minecraft.util.thread.ReentrantBlockableEventLoop.doRunTask(ReentrantBlockableEventLoop.java:22) ~[forge-1.19.2-43.1.52_mapped_official_1.19.2-recomp.jar%23183!/:?] {re:classloading} at net.minecraft.server.MinecraftServer.doRunTask(MinecraftServer.java:763) ~[forge-1.19.2-43.1.52_mapped_official_1.19.2-recomp.jar%23183!/:?] {re:classloading,pl:accesstransformer:B} at net.minecraft.server.MinecraftServer.doRunTask(MinecraftServer.java:157) ~[forge-1.19.2-43.1.52_mapped_official_1.19.2-recomp.jar%23183!/:?] {re:classloading,pl:accesstransformer:B} at net.minecraft.util.thread.BlockableEventLoop.pollTask(BlockableEventLoop.java:116) ~[forge-1.19.2-43.1.52_mapped_official_1.19.2-recomp.jar%23183!/:?] {re:classloading,pl:accesstransformer:B} at net.minecraft.server.MinecraftServer.pollTaskInternal(MinecraftServer.java:746) ~[forge-1.19.2-43.1.52_mapped_official_1.19.2-recomp.jar%23183!/:?] {re:classloading,pl:accesstransformer:B} at net.minecraft.server.MinecraftServer.pollTask(MinecraftServer.java:740) ~[forge-1.19.2-43.1.52_mapped_official_1.19.2-recomp.jar%23183!/:?] {re:classloading,pl:accesstransformer:B} at net.minecraft.util.thread.BlockableEventLoop.managedBlock(BlockableEventLoop.java:126) ~[forge-1.19.2-43.1.52_mapped_official_1.19.2-recomp.jar%23183!/:?] {re:classloading,pl:accesstransformer:B} at net.minecraft.server.MinecraftServer.waitUntilNextTick(MinecraftServer.java:726) ~[forge-1.19.2-43.1.52_mapped_official_1.19.2-recomp.jar%23183!/:?] {re:classloading,pl:accesstransformer:B} at net.minecraft.server.MinecraftServer.runServer(MinecraftServer.java:658) ~[forge-1.19.2-43.1.52_mapped_official_1.19.2-recomp.jar%23183!/:?] {re:classloading,pl:accesstransformer:B} at net.minecraft.server.MinecraftServer.lambda$spin$2(MinecraftServer.java:244) ~[forge-1.19.2-43.1.52_mapped_official_1.19.2-recomp.jar%23183!/:?] {re:classloading,pl:accesstransformer:B} at java.lang.Thread.run(Thread.java:833) [?:?] {} Custom Screen: Spoiler @OnlyIn(Dist.CLIENT) public class QuestScreen extends Screen { private String name; private String[] descriptionLines; private Entity questGiver; public QuestScreen(String name, Entity questGiver) { super(Component.translatable("quest.tutorialmod." + name).withStyle(ChatFormatting.GOLD)); this.name = "quest.tutorialmod." + name; this.descriptionLines = Component.translatable(this.name + ".description").getString().split("\n"); this.questGiver = questGiver; } @Override protected void init() { addRenderableWidget(new Button(this.width / 2 - 100, this.height - 30, 100, 20, Component.literal("Accept"), this::onAccept)); addRenderableWidget(new Button(this.width / 2 + 10, this.height - 30, 100, 20, Component.literal("Decline"), (button) -> { closeScreen(); })); } public void render(PoseStack poseStack, int p_96693_, int p_96694_, float p_96695_) { this.renderBackground(poseStack); drawCenteredString(poseStack, this.font, this.title, this.width / 2, 20, 16777215); // title // load descriptionText int posY = 40; for (int i = 0; i < this.descriptionLines.length; i++) { drawString(poseStack, this.font, Component.literal(this.descriptionLines[i]).withStyle(ChatFormatting.WHITE), this.width / 2 - 100, posY, 16777215); posY += 10; } super.render(poseStack, p_96693_, p_96694_, p_96695_); } private void onAccept(Button button) { closeScreen(); // add quest to player } public void closeScreen() { if(this.questGiver instanceof QuestGiverVillager) { ((QuestGiverVillager) this.questGiver).closeQuestScreen(); this.onClose(); } } public void show() { Minecraft.getInstance().setScreen(this); } @Override public boolean isPauseScreen() { return false; } } Custom Entity Spoiler public class QuestGiverVillager extends Villager implements IAnimatable { private AnimationFactory factory = GeckoLibUtil.createFactory(this); private EntityDimensions dimensions = new EntityDimensions(1.0f, 2.0f, true); // dimensions for hitbox private boolean isTalking = false; private QuestScreen questScreen; public QuestGiverVillager(EntityType<? extends Villager> type, Level level) { super(type, level); this.setCustomName(Component.literal("Malthor").withStyle(ChatFormatting.BLUE)); this.setCustomNameVisible(true); this.questScreen = new QuestScreen("a_long_forgotten_tale", this); } public static AttributeSupplier setAttributes() { return Villager.createAttributes() .add(Attributes.MAX_HEALTH, 20.0D) .add(Attributes.FOLLOW_RANGE, 50.0D).build(); } private <E extends IAnimatable> PlayState predicate(AnimationEvent<E> event) { if(event.isMoving()) { event.getController().setAnimation(new AnimationBuilder().addAnimation("walk")); return PlayState.CONTINUE; } event.getController().setAnimation(new AnimationBuilder().addAnimation("idle")); return PlayState.CONTINUE; } @Override public void registerControllers(AnimationData data) { data.addAnimationController(new AnimationController<QuestGiverVillager>(this, "controller", 0, this::predicate)); } @Override public AnimationFactory getFactory() { return factory; } @Override public EntityDimensions getDimensions(Pose p_21047_) { // return new dimensions (width, length, fixed) for hitbox return p_21047_ == Pose.SLEEPING ? SLEEPING_DIMENSIONS : dimensions; } @Override public InteractionResult mobInteract(Player player, InteractionHand interactionHand) { // when isTalking == false AND isSleeping == false AND "shift"-key isn't pushed then show QuestScreen if(!this.isTalking && !this.isSleeping() && !player.isSecondaryUseActive()) { if(interactionHand == InteractionHand.MAIN_HAND) { // successful talking with Entity (QuestGiverVillager) this.isTalking = true; this.questScreen.show(); return InteractionResult.sidedSuccess(this.level.isClientSide); } else { // unsuccessful talking with Entity (QuestGiverVillager) return InteractionResult.PASS; } } else { // unsuccessful talking with Entity (QuestGiverVillager) return InteractionResult.PASS; } } public void closeQuestScreen() { this.isTalking = false; } } When I show the Custom Screen (QuestScreen) for the first time it's all perfect without any exception or error. Just when I close it by clicking a button or pressing ESC and then right click my QuestGiverVillager again the problem occours. Edited November 18, 20222 yr by Ezio214 forgot title
November 18, 20222 yr You are calling setScreen() on the server thread. mobInteract() is called on both the client and server. https://forge.gemwire.uk/wiki/Sides You shouldn't even be referencing client classes directly, like your QuestScreen, in common classes like an Entity that exists on dedicated servers. The vanilla villager's mobInteract() uses Player.openMenu() which opens a container menu. i.e. a screen that is managed on the server with a "proxy" on the client. In particular MerchantMenu with its gui MerchantScreen. Boilerplate: If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one. If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install Large files should be posted to a file sharing site like https://gist.github.com You should also read the support forum sticky post.
November 18, 20222 yr Author So do I have to rewrite/modify my QuestScreen to a MenuProvider/SimpleMenuProvider subclass or how can I show my Screen without getting the "Rendersystem called from wrong thread" exception?
November 18, 20222 yr If you don't want to use a container menu, you will need to send a custom network packet to the client that tells it to the open the screen. I don't know of any vanilla code that does this? You normally want the linkage between client and server that the container menu provides for making sure state is updated on the server. Boilerplate: If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one. If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install Large files should be posted to a file sharing site like https://gist.github.com You should also read the support forum sticky post.
November 20, 20222 yr Author But why dont I get the exception when it opens the first time? Why is it only when it shows the second time? Also I wouldn't like to rewrite it to a new container menu, because I don't need the players inventory. I just want to show some text and give the player to press the accept or decline. Since any vanilla code does not send a network packet to the client I think I shouldn't either. Isn't there any other way I can show a screen to the player when he interacts with an entity?
November 20, 20222 yr If there is no data or processing relevant on the server, you can check the side. You basically let the client decide to show the screen with no veto by the server. You still shouldn't have client classes directly in your entity. But I don't think that is what you want? You have an "isTalking" field which doesn't look to implemented properly no synch server <-> client I am guessing your intention is that the villager can only talk to one player at once? As it stands, that is kind of true on the server, but not on the client. The client has no idea if the villager is talking to other players only if the local player is. And the server has no idea when players stop talking to villagers. Edited November 20, 20222 yr by warjort Boilerplate: If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one. If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install Large files should be posted to a file sharing site like https://gist.github.com You should also read the support forum sticky post.
November 20, 20222 yr Author Yep you are right. There is no synch between server <-> client with my variable isTalking, which indeed was for my intention, that only one player can talk to the villager at a time. I removed it completly since I already had in mind to change it because it doesn't make any sense for my mod. With that said, thank you again !
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.