Fixed various disguise bugs

- Fixed changeligns playing hurt sounds when flying whilst disguised as a player
 - Fixed invisible disguised changelings
 - Fixed disguised changelings not showing all the hat layer parts
 - Changeling disguises will work better with falling blocks and shulkers
This commit is contained in:
Sollace 2019-02-11 17:41:24 +02:00
parent a687b0b8d5
commit ea39dd0f98
8 changed files with 289 additions and 60 deletions

View file

@ -5,6 +5,7 @@ import java.util.UUID;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import com.minelittlepony.unicopia.entity.EntityFakeServerPlayer;
import com.minelittlepony.unicopia.forgebullshit.FUF;
import com.mojang.authlib.GameProfile;
@ -12,7 +13,6 @@ import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.world.IInteractionObject;
import net.minecraft.world.WorldServer;
import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
@ -72,7 +72,7 @@ public class UClient {
*/
@Nonnull
public EntityPlayer createPlayer(Entity observer, GameProfile profile) {
return new FakePlayer((WorldServer)observer.world, profile);
return new EntityFakeServerPlayer((WorldServer)observer.world, profile);
}
public void preInit(FMLPreInitializationEvent event) {}

View file

@ -15,8 +15,7 @@ import com.minelittlepony.unicopia.network.MsgRequestCapabilities;
import com.minelittlepony.unicopia.player.IPlayer;
import com.minelittlepony.unicopia.player.IView;
import com.minelittlepony.unicopia.player.PlayerSpeciesList;
import com.minelittlepony.unicopia.spell.IMagicEffect;
import com.minelittlepony.unicopia.spell.SpellDisguise;
import com.minelittlepony.unicopia.render.DisguiseRenderer;
import com.minelittlepony.util.gui.ButtonGridLayout;
import com.minelittlepony.util.gui.UButton;
import com.mojang.authlib.GameProfile;
@ -28,7 +27,6 @@ import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiOptions;
import net.minecraft.client.gui.GuiShareToLan;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.resources.I18n;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
@ -124,7 +122,7 @@ public class UnicopiaClient extends UClient {
return false;
}
return getPlayer().getGameProfile().getId().equals(player.getGameProfile().getId());
return IPlayer.equal(getPlayer(), player);
}
@Override
@ -173,56 +171,52 @@ public class UnicopiaClient extends UClient {
@SideOnly(Side.CLIENT)
@SubscribeEvent
public static void preEntityRender(RenderLivingEvent.Pre<?> event) {
if (event.getEntity() instanceof EntityPlayer) {
IPlayer iplayer = PlayerSpeciesList.instance().getPlayer((EntityPlayer)event.getEntity());
/*if (!MineLP.modIsActive()) {
float roll = iplayer.getCamera().calculateRoll();
float pitch = iplayer.getCamera().calculatePitch(0);
GlStateManager.rotate(roll, 0, 0, 1);
GlStateManager.rotate(pitch, 1, 0, 0);
}*/
Entity entity = event.getEntity();
if (DisguiseRenderer.instance().renderDisguise(entity, event.getPartialRenderTick())) {
event.setCanceled(true);
}
if (entity instanceof EntityPlayer) {
IPlayer iplayer = PlayerSpeciesList.instance().getPlayer((EntityPlayer)entity);
if (iplayer.isInvisible()) {
event.setCanceled(true);
} else {
GlStateManager.pushMatrix();
// This fixes lighting errors on the armour slots.
// #MahjongPls
// @FUF(reason = "Forge should fix this. Cancelling their event skips neccessary state resetting at the end of the render method")
GlStateManager.enableAlpha();
if (!MineLP.modIsActive() && !entity.onGround) {
float roll = iplayer.getCamera().calculateRoll();
float pitch = iplayer.getCamera().calculatePitch(0);
GlStateManager.rotate(roll, 0, 0, 1);
GlStateManager.rotate(pitch, 1, 0, 0);
}
}
if (iplayer.hasEffect()) {
RenderManager renderMan = Minecraft.getMinecraft().getRenderManager();
IMagicEffect effect = iplayer.getEffect(false);
if (!effect.getDead() && effect instanceof SpellDisguise) {
Entity e = ((SpellDisguise)effect).getDisguise();
if (renderMan.isRenderShadow() && !(e instanceof EntityPlayer)) {
return;
}
// Check for a disguise and render it in our place.
if (e != null) {
e.setInvisible(false);
float partialTicks = Minecraft.getMinecraft().getRenderPartialTicks();
if (renderMan.isRenderShadow()) {
renderMan.renderEntityStatic(e, partialTicks, false);
} else {
e.setAlwaysRenderNameTag(false);
effect.update(iplayer);
renderMan.renderEntity(e, 0, 0, 0, 0, 1, false);
}
}
}
DisguiseRenderer.instance().renderDisguiseToGui(iplayer);
}
}
}
@SideOnly(Side.CLIENT)
@SubscribeEvent
public static void postEntityRender(RenderLivingEvent.Post<?> event) {
Entity entity = event.getEntity();
if (entity instanceof EntityPlayer) {
GlStateManager.popMatrix();
}
// This fixes lighting errors on the armour slots.
// #MahjongPls
// @FUF(reason = "Forge should fix this. Cancelling their event skips neccessary state resetting at the end of the render method")
GlStateManager.enableAlpha();
}
@SideOnly(Side.CLIENT)
@Override
public void preInit(FMLPreInitializationEvent event) {

View file

@ -1,26 +1,25 @@
package com.minelittlepony.unicopia.entity;
import java.util.UUID;
import javax.annotation.Nullable;
import com.minelittlepony.unicopia.UClient;
import com.minelittlepony.unicopia.player.IOwned;
import com.mojang.authlib.GameProfile;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.AbstractClientPlayer;
import net.minecraft.client.network.NetworkPlayerInfo;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.World;
public class EntityFakeClientPlayer extends AbstractClientPlayer implements IOwned<UUID> {
public class EntityFakeClientPlayer extends AbstractClientPlayer implements IOwned<EntityPlayer> {
private final GameProfile profile;
private NetworkPlayerInfo playerInfo;
private UUID owner;
private EntityPlayer owner;
public EntityFakeClientPlayer(World world, GameProfile profile) {
super(world, profile);
@ -28,6 +27,7 @@ public class EntityFakeClientPlayer extends AbstractClientPlayer implements IOwn
this.profile = profile;
}
@Override
@Nullable
protected NetworkPlayerInfo getPlayerInfo() {
if (playerInfo == null) {
@ -53,18 +53,22 @@ public class EntityFakeClientPlayer extends AbstractClientPlayer implements IOwn
}
@Override
public boolean getAlwaysRenderNameTagForRender() {
return !(Minecraft.getMinecraft().player != null
&& Minecraft.getMinecraft().player.getGameProfile().getId().equals(getOwner()));
public boolean getAlwaysRenderNameTag() {
return !UClient.instance().isClientPlayer(getOwner());
}
@Override
public UUID getOwner() {
public boolean getAlwaysRenderNameTagForRender() {
return getAlwaysRenderNameTag();
}
@Override
public EntityPlayer getOwner() {
return owner;
}
@Override
public void setOwner(UUID owner) {
public void setOwner(EntityPlayer owner) {
this.owner = owner;
}

View file

@ -0,0 +1,57 @@
package com.minelittlepony.unicopia.entity;
import com.minelittlepony.unicopia.UClient;
import com.minelittlepony.unicopia.player.IOwned;
import com.mojang.authlib.GameProfile;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.WorldServer;
import net.minecraftforge.common.util.FakePlayer;
public class EntityFakeServerPlayer extends FakePlayer implements IOwned<EntityPlayer> {
private EntityPlayer owner;
public EntityFakeServerPlayer(WorldServer world, GameProfile profile) {
super(world, profile);
}
@Override
public boolean isPlayer() {
return false;
}
@Override
protected void playEquipSound(ItemStack stack) {
/*noop*/
}
@Override
public EntityPlayer getOwner() {
return owner;
}
@Override
public void setOwner(EntityPlayer owner) {
this.owner = owner;
}
@Override
public boolean getAlwaysRenderNameTag() {
return !UClient.instance().isClientPlayer(getOwner());
}
@Override
public boolean getAlwaysRenderNameTagForRender() {
return getAlwaysRenderNameTag();
}
@Override
public ITextComponent getDisplayName() {
ITextComponent name = super.getDisplayName();
name.getStyle().setItalic(true);
return name;
}
}

View file

@ -1,17 +1,34 @@
package com.minelittlepony.unicopia.mixin;
import com.google.common.base.Optional;
import com.minelittlepony.unicopia.forgebullshit.FUF;
import net.minecraft.entity.Entity;
import net.minecraft.entity.MoverType;
import net.minecraft.entity.monster.EntityShulker;
import net.minecraft.network.datasync.DataParameter;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
@FUF(reason = "Waiting for mixins?")
// pseudo code for things forge can't do.
// @Mixin(Entity.class)
public interface MixinEntity {
// @Accessor("setSize")
abstract class Player extends net.minecraft.entity.player.EntityPlayer {
private Player() { super(null, null);}
public static DataParameter<Byte> getModelFlag() {
return PLAYER_MODEL_FLAG;
}
}
abstract class Shulker extends EntityShulker {
private Shulker() { super(null);}
public static DataParameter<Optional<BlockPos>> getAttachmentPosFlag() {
return ATTACHED_BLOCK_POS;
}
}
static void setSize(Entity self, float width, float height) {
if (self.width != width || self.height != height) {
float f = self.width;

View file

@ -9,6 +9,7 @@ import com.minelittlepony.unicopia.UClient;
import com.minelittlepony.unicopia.enchanting.IPageOwner;
import com.minelittlepony.unicopia.network.ITransmittable;
import com.minelittlepony.unicopia.spell.ICaster;
import com.mojang.authlib.GameProfile;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
@ -78,4 +79,12 @@ public interface IPlayer extends ICaster<EntityPlayer>, IRaceContainer<EntityPla
return null;
}
static boolean equal(GameProfile one, GameProfile two) {
return one == two || (one != null && two != null && one.getId().equals(two.getId()));
}
static boolean equal(EntityPlayer one, EntityPlayer two) {
return one == two || (one != null && two != null && equal(one.getGameProfile(), two.getGameProfile()));
}
}

View file

@ -0,0 +1,84 @@
package com.minelittlepony.unicopia.render;
import com.minelittlepony.unicopia.player.IPlayer;
import com.minelittlepony.unicopia.spell.IMagicEffect;
import com.minelittlepony.unicopia.spell.SpellDisguise;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.EntityFallingBlock;
import net.minecraft.entity.monster.EntityShulker;
public class DisguiseRenderer {
private static final DisguiseRenderer instance = new DisguiseRenderer();
public static DisguiseRenderer instance() {
return instance;
}
public boolean renderDisguise(Entity entity, float usedPartialTick) {
Minecraft mc = Minecraft.getMinecraft();
RenderManager renderMan = mc.getRenderManager();
if (entity.getEntityData().hasKey("disguise") && entity.getEntityData().getBoolean("disguise")) {
entity.getEntityData().setBoolean("disguise", false);
renderMan.setRenderShadow(true);
if (isAttachedEntity(entity)) {
double blockMoveX = entity.posX - Math.round(entity.posX - 0.5F);
double blockMoveY = entity.posY - Math.round(entity.posY);
double blockMoveZ = entity.posZ - Math.round(entity.posZ - 0.5F);
renderMan.renderEntity(entity, -blockMoveX + 0.5, -blockMoveY, -blockMoveZ + 0.5, 0, 1, false);
} else {
renderMan.renderEntity(entity, 0, 0, 0, 0, 1, false);
}
renderMan.setRenderShadow(false);
entity.getEntityData().setBoolean("disguise", true);
return true;
} else {
renderMan.setRenderShadow(renderMan.isRenderShadow() || usedPartialTick != 1);
}
return false;
}
public boolean renderDisguiseToGui(IPlayer player) {
IMagicEffect effect = player.getEffect(false);
if (!(effect instanceof SpellDisguise) || effect.getDead()) {
return false;
}
Minecraft mc = Minecraft.getMinecraft();
RenderManager renderMan = mc.getRenderManager();
if (renderMan.isRenderShadow()) {
return false;
}
Entity e = ((SpellDisguise)effect).getDisguise();
// Check for a disguise and render it in our place.
if (e != null) {
effect.update(player);
e.setInvisible(false);
e.setAlwaysRenderNameTag(false);
renderMan.renderEntity(e, 0, 0, 0, 0, 1, false);
}
return true;
}
public boolean isAttachedEntity(Entity entity) {
return entity instanceof EntityShulker
|| entity instanceof EntityFallingBlock;
}
}

View file

@ -7,6 +7,7 @@ import javax.annotation.Nullable;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.UClient;
import com.minelittlepony.unicopia.mixin.MixinEntity;
import com.minelittlepony.unicopia.player.IFlyingPredicate;
import com.minelittlepony.unicopia.player.IOwned;
import com.minelittlepony.unicopia.player.IPlayer;
@ -19,6 +20,9 @@ import net.minecraft.entity.EntityList;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.boss.EntityDragon;
import net.minecraft.entity.item.EntityFallingBlock;
import net.minecraft.entity.item.EntityMinecart;
import net.minecraft.entity.monster.EntityShulker;
import net.minecraft.entity.passive.EntityAmbientCreature;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.EntityEquipmentSlot;
@ -107,7 +111,14 @@ public class SpellDisguise extends AbstractSpell implements IFlyingPredicate {
entity.setCustomNameTag(source.getOwner().getName());
entity.setUniqueId(UUID.randomUUID());
entity.readFromNBT(entityNbt.getCompoundTag("playerNbt"));
PlayerSpeciesList.instance().getPlayer((EntityPlayer)entity).setEffect(null);;
if (entity != null && source.getWorld().isRemote) {
source.getWorld().spawnEntity(entity);
}
entityNbt = null;
} else {
entity = EntityList.createEntityFromNBT(entityNbt, source.getWorld());
@ -127,12 +138,21 @@ public class SpellDisguise extends AbstractSpell implements IFlyingPredicate {
if (entity != null) {
entity.onGround = owner.onGround;
entity.onUpdate();
if (!(entity instanceof EntityFallingBlock)) {
entity.onUpdate();
}
entity.copyLocationAndAnglesFrom(owner);
entity.setNoGravity(true);
entity.getEntityData().setBoolean("disguise", true);
entity.lastTickPosX = owner.lastTickPosX;
entity.lastTickPosY = owner.lastTickPosY;
entity.lastTickPosZ = owner.lastTickPosZ;
entity.prevPosX = owner.prevPosX;
entity.prevPosY = owner.prevPosY;
entity.prevPosZ = owner.prevPosZ;
@ -176,6 +196,40 @@ public class SpellDisguise extends AbstractSpell implements IFlyingPredicate {
l.setItemStackToSlot(i, neu);
}
}
if (l instanceof EntityShulker) {
l.rotationYaw = 0;
l.rotationPitch = 0;
l.rotationYawHead = 0;
l.prevRotationYawHead = 0;
l.renderYawOffset = 0;
l.prevRenderYawOffset = 0;
}
}
if (entity instanceof EntityShulker || entity instanceof EntityFallingBlock) {
if (entity instanceof EntityFallingBlock) {
entity.posX = Math.floor(owner.posX) + 0.5;
entity.posY = Math.floor(owner.posY);
entity.posZ = Math.floor(owner.posZ) + 0.5;
} else {
entity.posX = owner.posX;
entity.posY = owner.posY;
entity.posZ = owner.posZ;
}
entity.lastTickPosX = entity.posX;
entity.lastTickPosY = entity.posY;
entity.lastTickPosZ = entity.posZ;
entity.prevPosX = entity.posX;
entity.prevPosY = entity.posY;
entity.prevPosZ = entity.posZ;
if (entity instanceof EntityShulker) {
((EntityShulker)entity).setAttachmentPos(null);
}
}
if (entity instanceof EntityLiving) {
@ -184,6 +238,11 @@ public class SpellDisguise extends AbstractSpell implements IFlyingPredicate {
l.setNoAI(true);
}
if (entity instanceof EntityMinecart) {
entity.rotationYaw += 90;
entity.rotationPitch = 0;
}
if (entity instanceof EntityPlayer) {
EntityPlayer l = (EntityPlayer)entity;
@ -207,6 +266,7 @@ public class SpellDisguise extends AbstractSpell implements IFlyingPredicate {
if (source instanceof IPlayer) {
((IPlayer) source).setInvisible(true);
}
owner.setInvisible(true);
if (owner instanceof EntityPlayer) {
@ -215,7 +275,11 @@ public class SpellDisguise extends AbstractSpell implements IFlyingPredicate {
player.eyeHeight = entity.getEyeHeight();
if (entity instanceof IOwned) {
IOwned.cast(entity).setOwner(player.getGameProfile().getId());
IOwned.cast(entity).setOwner(player);
}
if (entity instanceof EntityPlayer) {
entity.getDataManager().set(MixinEntity.Player.getModelFlag(), owner.getDataManager().get(MixinEntity.Player.getModelFlag()));
}
if (UClient.instance().isClientPlayer(player)) {
@ -321,7 +385,7 @@ public class SpellDisguise extends AbstractSpell implements IFlyingPredicate {
}
if (entity instanceof IOwned) {
IPlayer iplayer = PlayerSpeciesList.instance().getPlayer(IOwned.<UUID>cast(entity).getOwner());
IPlayer iplayer = PlayerSpeciesList.instance().getPlayer(IOwned.<EntityPlayer>cast(entity).getOwner());
return iplayer != null && iplayer.getPlayerSpecies().canFly();
}