Fix players not getting advancements when they own turtles

When we construct a new ServerPlayerEntity (and thus TurtlePlayer), we
get the current (global) advancement state and call .setPlayer() on it.

As grantCriterion blocks FakePlayers from getting advancements, this
means a player will no longer receive any advancements, as the "wrong"
player object is being consulted.

As a temporary work around, we attempt to restore the previous player to
the advancement store. I'll try to upstream something into Forge to
resolve this properly.

Fixes #564
This commit is contained in:
SquidDev 2020-10-31 10:59:24 +00:00
parent 6aae4e5766
commit f6160bdc57
4 changed files with 30 additions and 9 deletions

View File

@ -9,7 +9,7 @@
}
dependencies {
classpath 'com.google.code.gson:gson:2.8.1'
classpath 'net.minecraftforge.gradle:ForgeGradle:3.0.179'
classpath 'net.minecraftforge.gradle:ForgeGradle:3.0.187'
classpath 'net.sf.proguard:proguard-gradle:6.1.0beta2'
classpath 'org.ajoberstar.grgit:grgit-gradle:3.0.0'
}

View File

@ -139,7 +139,7 @@ public interface ITurtleAccess
*
* @return This turtle's owner.
*/
@Nonnull
@Nullable
GameProfile getOwningPlayer();
/**

View File

@ -45,6 +45,7 @@
import net.minecraftforge.items.wrapper.InvWrapper;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.*;
import java.util.concurrent.TimeUnit;
@ -598,7 +599,7 @@ public void setOwningPlayer( GameProfile profile )
m_owningPlayer = profile;
}
@Nonnull
@Nullable
@Override
public GameProfile getOwningPlayer()
{

View File

@ -17,6 +17,7 @@
import net.minecraft.entity.EntityType;
import net.minecraft.entity.Pose;
import net.minecraft.entity.passive.horse.AbstractHorseEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.container.INamedContainerProvider;
import net.minecraft.item.ItemStack;
@ -41,11 +42,30 @@ public final class TurtlePlayer extends FakePlayer
"[ComputerCraft]"
);
private TurtlePlayer( ITurtleAccess turtle )
private TurtlePlayer( ServerWorld world, GameProfile name )
{
super( (ServerWorld) turtle.getWorld(), getProfile( turtle.getOwningPlayer() ) );
this.connection = new FakeNetHandler( this );
setState( turtle );
super( world, name );
}
private static TurtlePlayer create( ITurtleAccess turtle )
{
ServerWorld world = (ServerWorld) turtle.getWorld();
GameProfile profile = turtle.getOwningPlayer();
TurtlePlayer player = new TurtlePlayer( world, getProfile( profile ) );
player.connection = new FakeNetHandler( player );
player.setState( turtle );
if( profile != null && profile.getId() != null )
{
// Constructing a player overrides the "active player" variable in advancements. As fake players cannot
// get advancements, this prevents a normal player who has placed a turtle from getting advancements.
// We try to locate the "actual" player and restore them.
ServerPlayerEntity actualPlayer = world.getServer().getPlayerList().getPlayerByUUID( profile.getId() );
if( actualPlayer != null ) player.getAdvancements().setPlayer( actualPlayer );
}
return player;
}
private static GameProfile getProfile( @Nullable GameProfile profile )
@ -72,14 +92,14 @@ private void setState( ITurtleAccess turtle )
public static TurtlePlayer get( ITurtleAccess access )
{
if( !(access instanceof TurtleBrain) ) return new TurtlePlayer( access );
if( !(access instanceof TurtleBrain) ) return create( access );
TurtleBrain brain = (TurtleBrain) access;
TurtlePlayer player = brain.m_cachedPlayer;
if( player == null || player.getGameProfile() != getProfile( access.getOwningPlayer() )
|| player.getEntityWorld() != access.getWorld() )
{
player = brain.m_cachedPlayer = new TurtlePlayer( brain );
player = brain.m_cachedPlayer = create( brain );
}
else
{