Fixed player-like disguises

This commit is contained in:
Sollace 2021-08-18 17:30:59 +02:00
parent 85623bd1c0
commit 0e007b3611
10 changed files with 133 additions and 24 deletions

View file

@ -7,10 +7,12 @@ import com.minelittlepony.unicopia.entity.player.dummy.DummyPlayerEntity;
import com.minelittlepony.unicopia.entity.player.dummy.DummyServerPlayerEntity;
import com.minelittlepony.unicopia.network.handler.ClientNetworkHandler;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.minecraft.MinecraftSessionService;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.world.World;
public class InteractionManager {
public static final int SOUND_EARS_RINGING = 0;
@ -24,6 +26,14 @@ public class InteractionManager {
return INSTANCE;
}
public MinecraftSessionService getSessionService(World world) {
if (world instanceof ServerWorld) {
return ((ServerWorld)world).getServer().getSessionService();
}
throw new NullPointerException("Cannot get session service");
}
/**
* Returns the client network handler, or throws if called on the server.
*/
@ -60,9 +70,19 @@ public class InteractionManager {
*/
@NotNull
public PlayerEntity createPlayer(Entity observer, GameProfile profile) {
if (observer.world instanceof ServerWorld) {
return new DummyServerPlayerEntity((ServerWorld)observer.world, profile);
return createPlayer(observer.world, profile);
}
/**
* Side-independent method to create a new player.
*
* Returns an implementation of PlayerEntity appropriate to the side being called on.
*/
@NotNull
public PlayerEntity createPlayer(World world, GameProfile profile) {
if (world instanceof ServerWorld) {
return new DummyServerPlayerEntity((ServerWorld)world, profile);
}
return new DummyPlayerEntity(observer.world, profile);
return new DummyPlayerEntity(world, profile);
}
}

View file

@ -14,6 +14,7 @@ import com.minelittlepony.unicopia.entity.player.dummy.DummyClientPlayerEntity;
import com.minelittlepony.unicopia.network.handler.ClientNetworkHandler;
import com.minelittlepony.unicopia.network.handler.ClientNetworkHandlerImpl;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.minecraft.MinecraftSessionService;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.sound.AggressiveBeeSoundInstance;
@ -26,12 +27,18 @@ import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.passive.BeeEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.vehicle.AbstractMinecartEntity;
import net.minecraft.world.World;
public class ClientInteractionManager extends InteractionManager {
private final ClientNetworkHandler handler = new ClientNetworkHandlerImpl();
private final MinecraftClient client = MinecraftClient.getInstance();
@Override
public MinecraftSessionService getSessionService(World world) {
return MinecraftClient.getInstance().getSessionService();
}
@Override
@Nullable
public ClientNetworkHandler getClientNetworkHandler() {
@ -62,11 +69,11 @@ public class ClientInteractionManager extends InteractionManager {
@Override
@NotNull
public PlayerEntity createPlayer(Entity observer, GameProfile profile) {
if (observer.world instanceof ClientWorld) {
return new DummyClientPlayerEntity((ClientWorld)observer.world, profile);
public PlayerEntity createPlayer(World world, GameProfile profile) {
if (world instanceof ClientWorld) {
return new DummyClientPlayerEntity((ClientWorld)world, profile);
}
return super.createPlayer(observer, profile);
return super.createPlayer(world, profile);
}
@Override

View file

@ -0,0 +1,5 @@
package com.minelittlepony.unicopia.entity;
public interface CapeHolder {
void callUpdateCapeAngles();
}

View file

@ -4,4 +4,13 @@ public interface Leaner {
float getLeaningPitch();
void setLeaningPitch(float pitch);
float getLastLeaningPitch();
void setLastLeaningPitch(float pitch);
default void copyFrom(Leaner other) {
setLeaningPitch(other.getLeaningPitch());
setLastLeaningPitch(other.getLastLeaningPitch());
}
}

View file

@ -2,6 +2,7 @@ package com.minelittlepony.unicopia.entity.behaviour;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import java.util.function.Consumer;
@ -144,16 +145,20 @@ public class Disguise implements NbtSerialisable {
public Entity getOrCreate(Caster<?> source) {
if (entity == null && entityNbt != null) {
NbtCompound nbt = entityNbt;
entity = null;
entityNbt = null;
attachments.clear();
if ("player".equals(entityId)) {
createPlayer(nbt, new GameProfile(
nbt.getUuid("playerId"),
nbt.getString("playerName")
), source);
nbt.containsUuid("playerId") ? nbt.getUuid("playerId") : UUID.randomUUID(),
nbt.getString("playerName")
), source);
SkullBlockEntity.loadProperties(new GameProfile(null, nbt.getString("playerName")), profile ->{ });
SkullBlockEntity.loadProperties(new GameProfile(
nbt.containsUuid("playerId") ? nbt.getUuid("playerId") : null,
nbt.getString("playerName")
), p -> createPlayer(nbt, p, source));
} else {
if (source.isClient()) {
entity = EntityType.fromNbt(nbt).map(type -> type.create(source.getWorld())).orElse(null);
@ -170,9 +175,9 @@ public class Disguise implements NbtSerialisable {
return EntityBehaviour.forEntity(e).onCreate(e, this, true);
});
}
}
onEntityLoaded(source);
onEntityLoaded(source);
}
}
return entity;
@ -282,7 +287,14 @@ public class Disguise implements NbtSerialisable {
public void fromNBT(NbtCompound compound) {
String newId = compound.getString("entityId");
if (!newId.contentEquals(entityId)) {
String newPlayerName = null;
if (compound.contains("entity") && compound.getCompound("entity").contains("playerName")) {
newPlayerName = compound.getCompound("entity").getString("playerName");
}
String oldPlayerName = entity != null && entity instanceof PlayerEntity ? ((PlayerEntity)entity).getGameProfile().getName() : null;
if (!Objects.equals(newId, entityId) || !Objects.equals(newPlayerName, oldPlayerName)) {
entityNbt = null;
remove();
}
@ -320,7 +332,9 @@ public class Disguise implements NbtSerialisable {
GameProfile profile = ((PlayerEntity)entity).getGameProfile();
entityNbt.putString("id", "player");
entityNbt.putUuid("playerId", profile.getId());
if (profile.getId() != null) {
entityNbt.putUuid("playerId", profile.getId());
}
entityNbt.putString("playerName", profile.getName());
NbtCompound tag = new NbtCompound();

View file

@ -40,6 +40,11 @@ public class EntityBehaviour<T extends Entity> {
private static final EntityBehaviour<Entity> DEFAULT = new EntityBehaviour<>();
private static final Registry<EntityBehaviour<?>> REGISTRY = Registries.createSimple(new Identifier("unicopia", "entity_behaviour"));
/**
* Equivalent of the entity#tick method. Called every tick to update th logic for a disguise.
* <br>
* We use this to add entity-specific behaviours.
*/
public void update(Caster<?> source, T entity, DisguiseSpell spell) {
if (source instanceof Pony) {
update((Pony)source, entity, spell);
@ -151,14 +156,6 @@ public class EntityBehaviour<T extends Entity> {
to.lastRenderZ = positionOffset.z + from.lastRenderZ;
}
if (to instanceof PlayerEntity) {
PlayerEntity l = (PlayerEntity)to;
l.capeX = positionOffset.x + l.getX();
l.capeY = positionOffset.y + l.getY();
l.capeZ = positionOffset.z + l.getZ();
}
to.setVelocity(from.getVelocity());
to.setPitch(from.getPitch());
@ -267,6 +264,7 @@ public class EntityBehaviour<T extends Entity> {
}
static {
register(PlayerBehaviour::new, EntityType.PLAYER);
register(FallingBlockBehaviour::new, EntityType.FALLING_BLOCK);
register(MobBehaviour::new, EntityType.RAVAGER, EntityType.IRON_GOLEM);
register(HoppingBehaviour::new, EntityType.RABBIT, EntityType.SLIME, EntityType.MAGMA_CUBE);

View file

@ -0,0 +1,37 @@
package com.minelittlepony.unicopia.entity.behaviour;
import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.spell.DisguiseSpell;
import com.minelittlepony.unicopia.entity.CapeHolder;
import com.minelittlepony.unicopia.entity.Leaner;
import com.minelittlepony.unicopia.entity.player.Pony;
import net.minecraft.entity.player.PlayerEntity;
public class PlayerBehaviour extends EntityBehaviour<PlayerEntity> {
@Override
public void update(Caster<?> source, PlayerEntity entity, DisguiseSpell spell) {
if (source instanceof Pony) {
PlayerEntity pFrom = ((Pony)source).getMaster();
entity.capeX = pFrom.capeX;
entity.capeY = pFrom.capeY;
entity.capeZ = pFrom.capeZ;
entity.prevCapeX = pFrom.prevCapeX;
entity.prevCapeY = pFrom.prevCapeY;
entity.prevCapeZ = pFrom.prevCapeZ;
} else {
((CapeHolder)entity).callUpdateCapeAngles();
}
if (source.getEntity().getPose() != entity.getPose()) {
entity.setPose(source.getEntity().getPose());
}
if (source.getEntity().isSwimming() != entity.isSwimming()) {
entity.setSwimming(source.getEntity().isSwimming());
}
if (source.getEntity() instanceof Leaner) {
((Leaner)entity).copyFrom(((Leaner)source.getEntity()));
}
}
}

View file

@ -4,6 +4,7 @@ import com.minelittlepony.unicopia.InteractionManager;
import com.minelittlepony.unicopia.Owned;
import com.mojang.authlib.GameProfile;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.server.network.ServerPlayerEntity;
@ -22,6 +23,11 @@ public class DummyServerPlayerEntity extends ServerPlayerEntity implements Owned
/*noop*/
}
@Override
protected void onBlockCollision(BlockState state) {
/*noop*/
}
@Override
public PlayerEntity getMaster() {
return owner;

View file

@ -75,6 +75,14 @@ abstract class MixinLivingEntity extends Entity implements PonyContainer<Equine<
@Accessor("leaningPitch")
public abstract void setLeaningPitch(float pitch);
@Override
@Accessor("lastLeaningPitch")
public abstract float getLastLeaningPitch();
@Override
@Accessor("lastLeaningPitch")
public abstract void setLastLeaningPitch(float pitch);
@Inject(method = "createLivingAttributes()Lnet/minecraft/entity/attribute/DefaultAttributeContainer$Builder;", at = @At("RETURN"))
private static void onCreateAttributes(CallbackInfoReturnable<DefaultAttributeContainer.Builder> info) {
Creature.registerAttributes(info.getReturnValue());

View file

@ -1,11 +1,13 @@
package com.minelittlepony.unicopia.mixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.minelittlepony.unicopia.entity.PonyContainer;
import com.minelittlepony.unicopia.entity.CapeHolder;
import com.minelittlepony.unicopia.entity.Equine;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.mojang.datafixers.util.Either;
@ -25,8 +27,11 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
@Mixin(PlayerEntity.class)
abstract class MixinPlayerEntity extends LivingEntity implements PonyContainer<Pony> {
abstract class MixinPlayerEntity extends LivingEntity implements PonyContainer<Pony>, CapeHolder {
private MixinPlayerEntity() { super(null, null); }
@Override
@Invoker("updateCapeAngles")
public abstract void callUpdateCapeAngles();
@Override
public Equine<?> create() {