Jump to content
Search In
  • More options...
Find results that contain...
Find results in...

[1.16.5] Creating my own screen overlay for my custom Effect


mclich
 Share

Recommended Posts

Hello. In my mod i created my own Effect and registered it. What i want this effect to do when applying on player is create screen overlay animation, similar to Nausea Effect (or Confusion Effect). I've done some researching in game files and discovered renderConfusionOverlay method in GameRenderer class. This method is private, so i just copy-pasted it in my applyEffectTick method, but it didn't work. That method used some RenderSystem static methods inside itself, and they throwed IllegalStateException("Rendersystem called from wrong thread") when i tried to use them in my files. So that is the problem. Is there any way to implement such kind of an animation since renderConfusionOverlay doesn't work?

Link to comment
Share on other sites

2 hours ago, diesieben07 said:

Tracing the code as to where that overlay is rendered, I think TickEvent.RenderTickEvent with Phase.END is the closest you can get to it, it runs shortly after renderConfusionOverlay.

Seems it won't help much in my case. I mean what i want to do is just make my own renderConfusionOverlay method, since i cannot use renderConfusionOverlay implementation because it needs to be called in a specific thread

Link to comment
Share on other sites

So i just need to call my overlay method inside that event listener? Like this e.g.?

@SubscribeEvent
public void renderOverlay(RenderTickEvent event)
{
	if(event.phase==Phase.END)
	{
		this.createOverlay();
	}
}

Sorry if i am asking obvious things, but i don't understand at all how this should works since RenderTickEvent is called after renderConfusionOverlay. To create overlay in game, i need to manually call my renderOverlay method?

Link to comment
Share on other sites

5 hours ago, mclich said:

but i don't understand at all how this should works since RenderTickEvent is called after renderConfusionOverlay

So?

5 hours ago, mclich said:

To create overlay in game, i need to manually call my renderOverlay method?

Yes, that is why we have events.

Link to comment
Share on other sites

5 minutes ago, diesieben07 said:

Show updated code and the full stacktrace.

Effect class:

@EventBusSubscriber(modid=ElderNorseGods.MOD_ID, bus=EventBusSubscriber.Bus.MOD)
public class DrunkennessEffect extends Effect
{
	public static final String ID="drunkenness";
	public static final int COLOR=0xf0c02c;
	
	private float deformation=1F;
	
	public DrunkennessEffect()
	{
		super(EffectType.HARMFUL, DrunkennessEffect.COLOR);
		this.addAttributeModifier(Attributes.MOVEMENT_SPEED, "1f8955f0-2985-4658-9dd8-0eb83fe32283", -0.05D, AttributeModifier.Operation.MULTIPLY_TOTAL);
		this.addAttributeModifier(Attributes.ATTACK_SPEED, "490e03c0-319b-4b22-b094-a98636fa6a4a", -0.05D, AttributeModifier.Operation.MULTIPLY_TOTAL);
		this.addAttributeModifier(Attributes.ATTACK_DAMAGE, "9855509b-0900-48de-a4b0-82eefaa24d62", 0.1D, AttributeModifier.Operation.MULTIPLY_TOTAL);
	}
	
	@Override
	public boolean isDurationEffectTick(int duration, int amplifier)
	{
		this.deformation=this.deformation==1F?3F:1F;
		this.renderOverlay(new RenderTickEvent(Phase.END, 10F));
		return false;
	}
	
	@SubscribeEvent
	public void renderOverlay(RenderTickEvent event)
	{
		this.createOverlay();
	}
	
	@SuppressWarnings("deprecation")
	private void createOverlay()
	{
		ElderNorseGods.LOGGER.info("createOverlay");
		Minecraft minecraft=Minecraft.getInstance();
		int i = minecraft.getWindow().getGuiScaledWidth();
		int j = minecraft.getWindow().getGuiScaledHeight();
		double d0 = MathHelper.lerp((double)deformation, 2.0D, 1.0D);
		float f = 0.2F * deformation;
		float f1 = 0.4F * deformation;
		float f2 = 0.2F * deformation;
		double d1 = (double)i * d0;
		double d2 = (double)j * d0;
		double d3 = ((double)i - d1) / 2.0D;
		double d4 = ((double)j - d2) / 2.0D;
		RenderSystem.disableDepthTest();
		RenderSystem.depthMask(false);
		RenderSystem.enableBlend();
		RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ONE, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ONE);
		RenderSystem.color4f(f, f1, f2, 1.0F);
		minecraft.getTextureManager().bind(new ResourceLocation("minecraft", "textures/misc/nausea.png"));
		Tessellator tessellator = Tessellator.getInstance();
		BufferBuilder bufferbuilder = tessellator.getBuilder();
		bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX);
		bufferbuilder.vertex(d3, d4 + d2, -90.0D).uv(0.0F, 1.0F).endVertex();
		bufferbuilder.vertex(d3 + d1, d4 + d2, -90.0D).uv(1.0F, 1.0F).endVertex();
		bufferbuilder.vertex(d3 + d1, d4, -90.0D).uv(1.0F, 0.0F).endVertex();
		bufferbuilder.vertex(d3, d4, -90.0D).uv(0.0F, 0.0F).endVertex();
		tessellator.end();
		RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
		RenderSystem.defaultBlendFunc();
		RenderSystem.disableBlend();
		RenderSystem.depthMask(true);
		RenderSystem.enableDepthTest();
	}
}

Logs:

[18:41:35] [Server thread/FATAL] [ne.mi.co.ForgeMod/]: Preparing crash report with UUID ada9d733-775c-491b-9cb2-7b4d0883f163
[18:41:35] [Server thread/ERROR] [minecraft/MinecraftServer]: Encountered an unexpected exception
net.minecraft.crash.ReportedException: Ticking player
	at net.minecraft.network.NetworkSystem.tick(NetworkSystem.java:137) ~[forge:?] {re:classloading}
	at net.minecraft.server.MinecraftServer.tickChildren(MinecraftServer.java:865) ~[forge:?] {re:classloading,pl:accesstransformer:B}
	at net.minecraft.server.MinecraftServer.tickServer(MinecraftServer.java:787) ~[forge:?] {re:classloading,pl:accesstransformer:B}
	at net.minecraft.server.integrated.IntegratedServer.tickServer(IntegratedServer.java:78) ~[forge:?] {re:classloading,pl:runtimedistcleaner:A}
	at net.minecraft.server.MinecraftServer.runServer(MinecraftServer.java:642) ~[forge:?] {re:classloading,pl:accesstransformer:B}
	at net.minecraft.server.MinecraftServer.lambda$spin$0(MinecraftServer.java:232) ~[forge:?] {re:classloading,pl:accesstransformer:B}
	at java.lang.Thread.run(Thread.java:748) [?:1.8.0_291] {}
Caused by: java.lang.IllegalStateException: Rendersystem called from wrong thread
	at com.mojang.blaze3d.systems.RenderSystem.assertThread(RenderSystem.java:76) ~[forge:?] {re:classloading,pl:runtimedistcleaner:A}
	at com.mojang.blaze3d.platform.GlStateManager._disableDepthTest(GlStateManager.java:182) ~[forge:?] {re:classloading,pl:runtimedistcleaner:A}
	at com.mojang.blaze3d.systems.RenderSystem.disableDepthTest(RenderSystem.java:192) ~[forge:?] {re:classloading,pl:runtimedistcleaner:A}
	at com.mclich.engmod.effect.DrunkennessEffect.createOverlay(DrunkennessEffect.java:73) ~[?:?] {re:classloading}
	at com.mclich.engmod.effect.DrunkennessEffect.renderOverlay(DrunkennessEffect.java:55) ~[?:?] {re:classloading}
	at com.mclich.engmod.effect.DrunkennessEffect.isDurationEffectTick(DrunkennessEffect.java:48) ~[?:?] {re:classloading}
	at net.minecraft.potion.EffectInstance.tick(EffectInstance.java:141) ~[forge:?] {re:classloading,xf:fml:forge:potion}
	at net.minecraft.entity.LivingEntity.tickEffects(LivingEntity.java:671) ~[forge:?] {re:classloading}
	at net.minecraft.entity.LivingEntity.baseTick(LivingEntity.java:386) ~[forge:?] {re:classloading}
	at net.minecraft.entity.Entity.tick(Entity.java:386) ~[forge:?] {re:classloading,pl:accesstransformer:B}
	at net.minecraft.entity.LivingEntity.tick(LivingEntity.java:2113) ~[forge:?] {re:classloading}
	at net.minecraft.entity.player.PlayerEntity.tick(PlayerEntity.java:223) ~[forge:?] {re:classloading,pl:accesstransformer:B}
	at net.minecraft.entity.player.ServerPlayerEntity.doTick(ServerPlayerEntity.java:404) ~[forge:?] {re:classloading,pl:accesstransformer:B}
	at net.minecraft.network.play.ServerPlayNetHandler.tick(ServerPlayNetHandler.java:207) ~[forge:?] {re:classloading}
	at net.minecraft.network.NetworkManager.tick(NetworkManager.java:226) ~[forge:?] {re:classloading}
	at net.minecraft.network.NetworkSystem.tick(NetworkSystem.java:134) ~[forge:?] {re:classloading}
	... 6 more
AL lib: (EE) alc_cleanup: 1 device not closed

 

Link to comment
Share on other sites

Just now, mclich said:
this.renderOverlay(new RenderTickEvent(Phase.END, 10F));

What on earth are you doing this for? What is your goal?

1 minute ago, mclich said:
	@SubscribeEvent
	public void renderOverlay(RenderTickEvent event)
	{
		this.createOverlay();
	}

You have to check the Phase of the event.

Link to comment
Share on other sites

18 minutes ago, diesieben07 said:

What on earth are you doing this for? What is your goal?

6 hours ago, mclich said:

To create overlay in game, i need to manually call my renderOverlay method?

56 minutes ago, diesieben07 said:

Yes, that is why we have events.

That is exactly what you have said previously

18 minutes ago, diesieben07 said:

You have to check the Phase of the event.

I passed Phase.END to event constructor, so i guess there is no need in this

Edited by mclich
Link to comment
Share on other sites

20 minutes ago, diesieben07 said:

You should not be creating the event yourself.

I commented line which was creating event:

//this.renderOverlay(new RenderTickEvent(Phase.END, 10F));

but it still doesn't work. My effect code actually do nothing now, and my createOverlay method is never called

20 minutes ago, diesieben07 said:

Please refer to the documentation on events.

Already read the most of it

Edited by mclich
Link to comment
Share on other sites

6 minutes ago, diesieben07 said:

You are using @EventBusSubscriber, which registers the class to the event bus. This only looks at static methods for event handlers.

Is there way to use non-static methods? Maybe there is another anotation which looks at all methods?

Link to comment
Share on other sites

On 9/12/2021 at 7:53 PM, diesieben07 said:

Read the documentation.

A little update: i discovered that GameRenderer#renderConfusionOverlay just renders a nausea texture, not an actual distortion, which is not what i needed. I found information about EntityRenderer#setupCameraTransform, but it's not currently available in 1.16.5 forge version. In previous versions it looks like this:

f2 = this.mc.thePlayer.prevTimeInPortal + (this.mc.thePlayer.timeInPortal - this.mc.thePlayer.prevTimeInPortal) * par1;
if (f2 > 0.0F)
{
	byte b0 = 20;
	if (this.mc.thePlayer.isPotionActive(Potion.confusion))
	{
		b0 = 7;
	}
	float f3 = 5.0F / (f2 * f2 + 5.0F) - f2 * 0.04F;
	f3 *= f3;
	GL11.glRotatef(((float)this.rendererUpdateCount + par1) * (float)b0, 0.0F, 1.0F, 1.0F);
	GL11.glScalef(1.0F / f3, 1.0F, 1.0F);
	GL11.glRotatef(-((float)this.rendererUpdateCount + par1) * (float)b0, 0.0F, 1.0F, 1.0F);
}

As i understand, an actual distortion is caused by GL11 static methods. I tried to experiment with those methods and some render events to make nausea distortion effect, but it works not as i expected and still doesn't make what i want. Is there any EntityRenderer#setupCameraTransform method, but available in 1.16.5 forge version? Or maybe am i doing something wrong?

Link to comment
Share on other sites

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
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.

 Share



×
×
  • Create New...

Important Information

By using this site, you agree to our Privacy Policy.