I can reproduce it via other means. Let me update the method.
No, I run the command block and no put is given sometimes. https://youtu.be/9Zl215WqHDg
The X or O did not matter when we tested it with the kill command. You are right the X removes the output, but the O is still not working for us all the time.
This is not intentional in my mind. I think you might be misunderstanding what I am saying. If you place a wool on certain axis from a lever, sometimes it will detect the sound other times it will not. Watch this video: https://youtu.be/7HN89WI5_SQ
@Galaxy_2Alex It works when the player block position is even over the cobweb, as can be done with anvils instead of wall block for alignment. (Just takes the values it finds last in collision)
Code Analysis:
Using 1.16.1 Yarn mappings.
The reason TNT cannot enter the nether via a nether portal is simple.
The TNT extends entity however never uses the entity tick which would call the base tick and thus call the netherportaltick to enter the nether.
Instead TNT uses it own tick method with no super call to the entity tick at all and thus no calling of the nether portal stuff.
public class TntEntity
extends Entity {
//Removed code not needed
@Override
public void tick() {
if (!this.hasNoGravity()) {
this.setVelocity(this.getVelocity().add(0.0, -0.04, 0.0));
}
this.move(MovementType.SELF, this.getVelocity());
this.setVelocity(this.getVelocity().multiply(0.98));
if (this.onGround) {
this.setVelocity(this.getVelocity().multiply(0.7, -0.5, 0.7));
}
--this.fuseTimer;
if (this.fuseTimer <= 0) {
this.remove();
if (!this.world.isClient) {
this.explode();
}
} else {
this.updateWaterState();
if (this.world.isClient) {
this.world.addParticle(ParticleTypes.SMOKE, this.getX(), this.getY() + 0.5, this.getZ(), 0.0, 0.0, 0.0);
}
}
//Removed code not needed
}
}
Here is the default entity tick:
It first calls the tick which call the base tick.
public void tick() {
if (!this.world.isClient) {
this.setFlag(6, this.isGlowing());
}
this.baseTick();
}
From the base tick it calls the this.tickNetherPortal().
public void baseTick() {
//Removed code not needed
this.tickNetherPortal();
//Removed code not needed
}
From the this.tickNetherPortal(), it checks to see if the entity is in a nether portal which TNT can be at is uses the move method which checks for collisions. If it had this calling it would be able to call this.changeDimension(lv3) and enter the nether.
protected void tickNetherPortal() {
//Removed code not needed
if (this.inNetherPortal) {
//Removed code not needed
this.changeDimension(lv3);
//Removed code not needed
}
//Removed code not needed
}
This bug report was to address a few issues that caused an entity to not be sent to the nether in one gametick. That is why I was going for this title "Entities that tick in nether portal for one gametick don't get sent to the nether".
The first issues was that it took around 3 ticks for the entity to be sent to the nether pre-28a.
That the move method is after portal so that entity could never be sent to the nether in the same game-tick that is arrived in it. (This would also solve the "If an entity is in a portal in a non-ticking chunk, it will not teleport." unless they were piston pushed in or some other move call.)
The reproducing steps of this bug report also work with "Entities teleport though portals at the start of a tick (before they move) instead of at the end of a tick (after they move)" suggestion as the original bug report covered both of the issues that made one action not possible.
If you think that "Entities teleport though portals at the start of a tick (before they move) instead of at the end of a tick (after they move)" should be a separate ticket after this address I will do so.
Edit: I created a bug report based on your third suggestion MC-196897
[media]
Seems to not work in 20w30a. Still same as 20w28/29a.
Seems to not work in 20w29a. Still same as 20w28a.
[media]
Still not working in 20w28a; however, the ticking has been reduced by 1 gt as of testing. I will add the new code changed when the mappings come out.
(Disclaimer: 20w28a reduces the time by 1 more gt than previous versions as int I (this.netherPortalTime) is equal to 0)
The problem:
This code analysis is using Yarn mappings for 1.16.1.
This is very dry and a long explanation so that most people who aren't that code savy can understand it.
Below is the reason why the current game can't send an entity into the nether in one gametick via a portal.
For this example, I will only be using LivingEntities (a pig).
When the pig is ticked for the gametick, it calls the LivingEntity tick().
// @Override
public void tick() {
super.tick();
//cutting off lines between the two methods
this.tickMovement();
//cutting off as the rest is not needed....
}
}
As shown, it will first preform the super.tick() then the this.tickMovement() which contains the movement of the pig in the entity class after a few more method calls. This movement is needed to do block collisions in order to say it is in a portal.
So let's explore the super.tick()
public void tick() {
if (!this.world.isClient) {
this.setFlag(6, this.isGlowing());
}
this.baseTick();
}
From the tick(), it calls the this.basetick() method which will contain some important code involving portals, so let's now look at the base tick.
public void baseTick() {
//cutting off lines above as they are not needed
this.tickNetherPortal();
//cutting off as the rest is not needed....
}
In the base tick, it calls the this.tickNetherPortal() method, which is a very important method in this exploration.
protected void tickNetherPortal() {
//removed some lines above as not needed
int i = this.getMaxNetherPortalTime();
//removed some lines above as not needed
if (this.inNetherPortal) {
//removed some lines above as not needed
if (lv3 != null && minecraftServer.isNetherAllowed() && !this.hasVehicle() && this.netherPortalTime++ >= i) {
this.world.getProfiler().push("portal");
this.netherPortalTime = i;
this.netherPortalCooldown = this.getDefaultNetherPortalCooldown();
this.changeDimension(lv3);
this.world.getProfiler().pop();
}
//removed some lines above as not needed
}
The first important thing to look at here is the this.inNetherPortal(). For this statement to be true, it must first collide with a portal via some move method/block collision.
As the move method of entities (velocity), that is called in the LivingEntity, is after the super.tick() (aka the tickNetherPortal()), the pig can't pass this first statement, thus can't end up in the nether on the same tick it moves.
However, it gets worse....
Let's now look at this.netherPortalTime. This.netherPortalTime can only increase via an entering into the
if (lv3 != null && minecraftServer.isNetherAllowed() && !this.hasVehicle() && this.netherPortalTime++ >= i)
if statement, which means it first needs to be in a nether portal. So in most cases, the pig's movement will have to collide with a portal first, then wait another tick just to be able to hit that if statement.
Now, once that if statement is called once, it will need to be called again as the first time it is called, this.netherPortalTime is equal to 0 and thus fails the check as i is 1. After the first calling of the if, the value is now 1 due to the this.netherPortalTime++, which means it can complete the if statement once it ticks again.
So, by looking at the code, it takes 3 ticks for a pig to enter the nether via normal means.
A potential fix to make it enter in the same tick it moves:
So, a potential fix would be to first move the this.tickNetherPortal() out of the super.tick() and place it after the movement of the different entities types. Once that is done, the this.netherPortalTime is not needed for most none player entities so it can be zero for most. This means that the entity would move, collide with a portal, and then tick the portal and get sent to the nether all in the same tick.
I can say the bug is still there for snapshot 20w27a. Can anyone else confirm it as I am the bug poster.
Relates to MC-207866