mojira.dev
MC-121098

Entering a tall portal that takes you to a short portal from the top causes you to take suffocation damage

The bug

When entering a tall portal that takes you to a short portal from the top, you take suffocation damage. This also happens when going from a wide portal to a thin portal.

How to reproduce

  1. Download the attached test world

  2. Enter the portal from the very top platform (you should spawn at it; be careful not to fall down inside the portal)

  3. Observe that when you enter the nether, note blocks triggered by pressure plates on top of the portal play, and you take a few hits of suffocation damage. (Also, you spawn at y=46.71429, while the max y you can fly up to under the portal is 45.2)

Code analysis

By @unknown, based on 1.12.2 decompiled using MCP 9.40. The problem is that the player's height and width aren't accounted for in net.minecraft.entity.Entity.setPortal(BlockPos) when calculating lastPortalVec. Player height and width then also need to be accounted for in net.minecraft.world.Teleporter.placeInExistingPortal(Entity, float).

Related issues

Attachments

Comments

migrated
[media][media]
gnembon

here is the partial solution that I implemented (names based on MCP 9.40 pre1)
Location: world/Teletporter.java#placeInExistingPortal

double d5 = (double)blockpos.getX() + 0.5D;
            double d7 = (double)blockpos.getZ() + 0.5D;
            BlockPattern.PatternHelper blockpattern$patternhelper = Blocks.PORTAL.createPatternHelper(this.worldServerInstance, blockpos);
            boolean flag1 = blockpattern$patternhelper.getForwards().rotateY().getAxisDirection() == EnumFacing.AxisDirection.NEGATIVE;
            double d2 = blockpattern$patternhelper.getForwards().getAxis() == EnumFacing.Axis.X ? (double)blockpattern$patternhelper.getFrontTopLeft().getZ() : (double)blockpattern$patternhelper.getFrontTopLeft().getX();
            double d6 = (double)(blockpattern$patternhelper.getFrontTopLeft().getY() + 1) - entityIn.getLastPortalVec().yCoord * (double)blockpattern$patternhelper.getHeight();

            if (flag1)
            {
                ++d2;
            }
			
			//CM portalSuffocationFix
			//removed offset calculation outside of the if statement
			double offset = (1.0D - entityIn.getLastPortalVec().xCoord) * (double)blockpattern$patternhelper.getWidth() * (double)blockpattern$patternhelper.getForwards().rotateY().getAxisDirection().getOffset();
			//CarpetSettings.LOG.info("[CM]offset, width: "+offset+", "+blockpattern$patternhelper.getWidth());
			if (CarpetSettings.getBool("portalSuffocationFix"))
			{
				// correcting to fit within 98% of the exit portal to account for FP rounding errors - optional
				double entity_corrected_radius = 1.02*(double)entityIn.width/2;
				if (entity_corrected_radius >= (double)blockpattern$patternhelper.getWidth()-entity_corrected_radius)
				{
					//entity is wider than portal, so will suffocate anyways, so place it directly in the middle
					entity_corrected_radius = (double)blockpattern$patternhelper.getWidth()/2-0.001;
				}
					
				if (offset >= 0) // offset can be positive or negative depending on the portal orientation and world quadrant
				//I am here clamping the offset to fit in the portal, other option would be scale in it, but this was easier to implement
				{
					offset = MathHelper.clamp(offset, entity_corrected_radius, (double)blockpattern$patternhelper.getWidth()-entity_corrected_radius);
				}
				else
				{
					offset = MathHelper.clamp(offset, -(double)blockpattern$patternhelper.getWidth()+entity_corrected_radius, -entity_corrected_radius);
				}
				//CarpetSettings.LOG.info("  [CM]offset corrected to: "+offset);
			}
            if (blockpattern$patternhelper.getForwards().getAxis() == EnumFacing.Axis.X)
            {
                d7 = d2 + offset;
            }
            else
            {
                d5 = d2 + offset;
            }

its a partial fix - fixes offset in X and Z dimentions, not the Y. In essence translated offset in the exit portal doesn't account for enity width/height which may end up it spawning inside obsidian blocks.
Side note - I presented the fix in a video of mine with a poll (along other fixes and QOL improvements and this one got the most upvotes)

migrated

This also occurs for wide portals - in a 5 block wide portal, teleporting from the end of either side causes the player to be teleported inside the nether portal frame, taking suffocation damage and being pushed inside the nether portal.

migrated

If the portal is 1 tall, it should make you crawl in the 1 tall space instead of taking suffocation damage.

migrated

Can confirm, if I enter a 3x3 portal and I am supposed to exit a 2x3 portal, I suffocate.

migrated

Cannot reproduce in 1.16.2.

[media]

Adrian Östergård

Is this still an issue in 1.16.3 or later? It might have been fixed with some recent portal changes.

pokechu22

It seems to have been fixed with some portal changes in 20w28a, along with MC-80032.

pokechu22

(Unassigned)

Confirmed

(Unassigned)

portal

Minecraft 1.12.2, Minecraft 17w43a, Minecraft 17w43b, Minecraft 17w45a, Minecraft 17w45b, ..., 1.15.1, 1.15.2, 20w08a, 20w10a, 20w21a

20w28a

Retrieved