--- ../src-base/minecraft/net/minecraft/entity/player/EntityPlayer.java +++ ../src-work/minecraft/net/minecraft/entity/player/EntityPlayer.java @@ -98,6 +98,11 @@ @SuppressWarnings("incomplete-switch") public abstract class EntityPlayer extends EntityLivingBase { + public static final String PERSISTED_NBT_TAG = "PlayerPersisted"; + private java.util.HashMap spawnChunkMap = new java.util.HashMap(); + private java.util.HashMap spawnForcedMap = new java.util.HashMap(); + public float eyeHeight = this.getDefaultEyeHeight(); + private static final DataParameter field_184829_a = EntityDataManager.func_187226_a(EntityPlayer.class, DataSerializers.field_187193_c); private static final DataParameter field_184830_b = EntityDataManager.func_187226_a(EntityPlayer.class, DataSerializers.field_187192_b); protected static final DataParameter field_184827_bp = EntityDataManager.func_187226_a(EntityPlayer.class, DataSerializers.field_187191_a); @@ -180,6 +185,7 @@ public void func_70071_h_() { + net.minecraftforge.fml.common.FMLCommonHandler.instance().onPlayerPreTick(this); this.field_70145_X = this.func_175149_v(); if (this.func_175149_v()) @@ -372,6 +378,7 @@ this.func_70105_a(f, f1); } } + net.minecraftforge.fml.common.FMLCommonHandler.instance().onPlayerPostTick(this); } public int func_82145_z() @@ -459,11 +466,11 @@ this.field_71109_bG = 0.0F; this.func_71015_k(this.field_70165_t - d0, this.field_70163_u - d1, this.field_70161_v - d2); - if (this.func_184187_bx() instanceof EntityPig) + if (this.func_184187_bx() instanceof EntityLivingBase && ((EntityLivingBase)this.func_184187_bx()).shouldRiderFaceForward(this)) { this.field_70125_A = f1; this.field_70177_z = f; - this.field_70761_aq = ((EntityPig)this.func_184187_bx()).field_70761_aq; + this.field_70761_aq = ((EntityLivingBase)this.func_184187_bx()).field_70761_aq; } } } @@ -593,11 +600,15 @@ public void func_70645_a(DamageSource p_70645_1_) { + if (net.minecraftforge.common.ForgeHooks.onLivingDeath(this, p_70645_1_)) return; super.func_70645_a(p_70645_1_); this.func_70105_a(0.2F, 0.2F); this.func_70107_b(this.field_70165_t, this.field_70163_u, this.field_70161_v); this.field_70181_x = 0.10000000149011612D; + captureDrops = true; + capturedDrops.clear(); + if ("Notch".equals(this.func_70005_c_())) { this.func_146097_a(new ItemStack(Items.field_151034_e, 1), true, false); @@ -609,6 +620,9 @@ this.field_71071_by.func_70436_m(); } + captureDrops = false; + if (!field_70170_p.field_72995_K) net.minecraftforge.event.ForgeEventFactory.onPlayerDrops(this, p_70645_1_, capturedDrops, field_70718_bc > 0); + if (p_70645_1_ != null) { this.field_70159_w = (double)(-MathHelper.func_76134_b((this.field_70739_aP + this.field_70177_z) * 0.017453292F) * 0.1F); @@ -712,13 +726,24 @@ @Nullable public EntityItem func_71040_bB(boolean p_71040_1_) { - return this.func_146097_a(this.field_71071_by.func_70298_a(this.field_71071_by.field_70461_c, p_71040_1_ && !this.field_71071_by.func_70448_g().func_190926_b() ? this.field_71071_by.func_70448_g().func_190916_E() : 1), false, true); + ItemStack stack = field_71071_by.func_70448_g(); + + if (stack.func_190926_b()) + { + return null; + } + if (stack.func_77973_b().onDroppedByPlayer(stack, this)) + { + int count = p_71040_1_ ? this.field_71071_by.func_70448_g().func_190916_E() : 1; + return net.minecraftforge.common.ForgeHooks.onPlayerTossEvent(this, field_71071_by.func_70298_a(field_71071_by.field_70461_c, count), true); + } + return null; } @Nullable public EntityItem func_71019_a(ItemStack p_71019_1_, boolean p_71019_2_) { - return this.func_146097_a(p_71019_1_, false, p_71019_2_); + return net.minecraftforge.common.ForgeHooks.onPlayerTossEvent(this, p_71019_1_, false); } @Nullable @@ -778,14 +803,22 @@ public ItemStack func_184816_a(EntityItem p_184816_1_) { + if (captureDrops) capturedDrops.add(p_184816_1_); + else // Forge: Don't indent to keep patch smaller. this.field_70170_p.func_72838_d(p_184816_1_); return p_184816_1_.func_92059_d(); } + @Deprecated //Use location sensitive version below public float func_184813_a(IBlockState p_184813_1_) { - float f = this.field_71071_by.func_184438_a(p_184813_1_); + return getDigSpeed(p_184813_1_, null); + } + public float getDigSpeed(IBlockState state, BlockPos pos) + { + float f = this.field_71071_by.func_184438_a(state); + if (f > 1.0F) { int i = EnchantmentHelper.func_185293_e(this); @@ -835,12 +868,13 @@ f /= 5.0F; } - return f; + f = net.minecraftforge.event.ForgeEventFactory.getBreakSpeed(this, state, f, pos); + return (f < 0 ? 0 : f); } public boolean func_184823_b(IBlockState p_184823_1_) { - return this.field_71071_by.func_184432_b(p_184823_1_); + return net.minecraftforge.event.ForgeEventFactory.doPlayerHarvestCheck(this, p_184823_1_, this.field_71071_by.func_184432_b(p_184823_1_)); } public static void func_189806_a(DataFixer p_189806_0_) @@ -889,6 +923,16 @@ this.field_82248_d = p_70037_1_.func_74767_n("SpawnForced"); } + NBTTagList spawnlist = null; + spawnlist = p_70037_1_.func_150295_c("Spawns", 10); + for (int i = 0; i < spawnlist.func_74745_c(); i++) + { + NBTTagCompound spawndata = (NBTTagCompound)spawnlist.func_150305_b(i); + int spawndim = spawndata.func_74762_e("Dim"); + this.spawnChunkMap.put(spawndim, new BlockPos(spawndata.func_74762_e("SpawnX"), spawndata.func_74762_e("SpawnY"), spawndata.func_74762_e("SpawnZ"))); + this.spawnForcedMap.put(spawndim, spawndata.func_74767_n("SpawnForced")); + } + this.field_71100_bB.func_75112_a(p_70037_1_); this.field_71075_bZ.func_75095_b(p_70037_1_); @@ -903,6 +947,7 @@ { super.func_70014_b(p_70014_1_); p_70014_1_.func_74768_a("DataVersion", 819); + net.minecraftforge.fml.common.FMLCommonHandler.instance().getDataFixer().writeVersionData(p_70014_1_); p_70014_1_.func_74782_a("Inventory", this.field_71071_by.func_70442_a(new NBTTagList())); p_70014_1_.func_74768_a("SelectedItemSlot", this.field_71071_by.field_70461_c); p_70014_1_.func_74757_a("Sleeping", this.field_71083_bS); @@ -921,6 +966,23 @@ p_70014_1_.func_74757_a("SpawnForced", this.field_82248_d); } + NBTTagList spawnlist = new NBTTagList(); + for (java.util.Map.Entry entry : this.spawnChunkMap.entrySet()) + { + BlockPos spawn = entry.getValue(); + if (spawn == null) continue; + Boolean forced = spawnForcedMap.get(entry.getKey()); + if (forced == null) forced = false; + NBTTagCompound spawndata = new NBTTagCompound(); + spawndata.func_74768_a("Dim", entry.getKey()); + spawndata.func_74768_a("SpawnX", spawn.func_177958_n()); + spawndata.func_74768_a("SpawnY", spawn.func_177956_o()); + spawndata.func_74768_a("SpawnZ", spawn.func_177952_p()); + spawndata.func_74757_a("SpawnForced", forced); + spawnlist.func_74742_a(spawndata); + } + p_70014_1_.func_74782_a("Spawns", spawnlist); + this.field_71100_bB.func_75117_b(p_70014_1_); this.field_71075_bZ.func_75091_a(p_70014_1_); p_70014_1_.func_74782_a("EnderItems", this.field_71078_a.func_70487_g()); @@ -928,6 +990,7 @@ public boolean func_70097_a(DamageSource p_70097_1_, float p_70097_2_) { + if (!net.minecraftforge.common.ForgeHooks.onLivingAttack(this, p_70097_1_, p_70097_2_)) return false; if (this.func_180431_b(p_70097_1_)) { return false; @@ -1006,6 +1069,7 @@ if (this.field_184627_bm.func_190926_b()) { EnumHand enumhand = this.func_184600_cs(); + net.minecraftforge.event.ForgeEventFactory.onPlayerDestroyItem(this, this.field_184627_bm, enumhand); if (enumhand == EnumHand.MAIN_HAND) { @@ -1041,7 +1105,10 @@ { if (!this.func_180431_b(p_70665_1_)) { - p_70665_2_ = this.func_70655_b(p_70665_1_, p_70665_2_); + p_70665_2_ = net.minecraftforge.common.ForgeHooks.onLivingHurt(this, p_70665_1_, p_70665_2_); + if (p_70665_2_ <= 0) return; + p_70665_2_ = net.minecraftforge.common.ISpecialArmor.ArmorProperties.applyArmor(this, field_71071_by.field_70460_b, p_70665_1_, p_70665_2_); + if (p_70665_2_ <= 0) return; p_70665_2_ = this.func_70672_c(p_70665_1_, p_70665_2_); float f = p_70665_2_; p_70665_2_ = Math.max(p_70665_2_ - this.func_110139_bj(), 0.0F); @@ -1111,6 +1178,7 @@ } else { + if (net.minecraftforge.common.ForgeHooks.onInteractEntity(this, p_190775_1_, p_190775_2_)) return EnumActionResult.PASS; ItemStack itemstack = this.func_184586_b(p_190775_2_); ItemStack itemstack1 = itemstack.func_190926_b() ? ItemStack.field_190927_a : itemstack.func_77946_l(); @@ -1120,7 +1188,10 @@ { itemstack.func_190920_e(itemstack1.func_190916_E()); } - + if (!this.field_71075_bZ.field_75098_d && itemstack.func_190926_b()) + { + net.minecraftforge.event.ForgeEventFactory.onPlayerDestroyItem(this, itemstack1, p_190775_2_); + } return EnumActionResult.SUCCESS; } else @@ -1136,6 +1207,7 @@ { if (itemstack.func_190926_b() && !this.field_71075_bZ.field_75098_d) { + net.minecraftforge.event.ForgeEventFactory.onPlayerDestroyItem(this, itemstack1, p_190775_2_); this.func_184611_a(p_190775_2_, ItemStack.field_190927_a); } @@ -1161,6 +1233,7 @@ public void func_71059_n(Entity p_71059_1_) { + if (!net.minecraftforge.common.ForgeHooks.onPlayerAttackTarget(this, p_71059_1_)) return; if (p_71059_1_.func_70075_an()) { if (!p_71059_1_.func_85031_j(this)) @@ -1331,11 +1404,13 @@ if (!itemstack1.func_190926_b() && entity instanceof EntityLivingBase) { + ItemStack beforeHitCopy = itemstack1.func_77946_l(); itemstack1.func_77961_a((EntityLivingBase)entity, this); if (itemstack1.func_190926_b()) { this.func_184611_a(EnumHand.MAIN_HAND, ItemStack.field_190927_a); + net.minecraftforge.event.ForgeEventFactory.onPlayerDestroyItem(this, beforeHitCopy, EnumHand.MAIN_HAND); } } @@ -1441,6 +1516,8 @@ public EntityPlayer.SleepResult func_180469_a(BlockPos p_180469_1_) { + EntityPlayer.SleepResult ret = net.minecraftforge.event.ForgeEventFactory.onPlayerSleepInBed(this, p_180469_1_); + if (ret != null) return ret; EnumFacing enumfacing = (EnumFacing)this.field_70170_p.func_180495_p(p_180469_1_).func_177229_b(BlockHorizontal.field_185512_D); if (!this.field_70170_p.field_72995_K) @@ -1482,8 +1559,9 @@ this.func_70105_a(0.2F, 0.2F); - if (this.field_70170_p.func_175667_e(p_180469_1_)) - { + IBlockState state = null; + if (this.field_70170_p.func_175667_e(p_180469_1_)) state = this.field_70170_p.func_180495_p(p_180469_1_); + if (state != null && state.func_177230_c().isBed(state, this.field_70170_p, p_180469_1_, this)) { float f1 = 0.5F + (float)enumfacing.func_82601_c() * 0.4F; float f = 0.5F + (float)enumfacing.func_82599_e() * 0.4F; this.func_175139_a(enumfacing); @@ -1530,13 +1608,14 @@ public void func_70999_a(boolean p_70999_1_, boolean p_70999_2_, boolean p_70999_3_) { + net.minecraftforge.event.ForgeEventFactory.onPlayerWakeup(this, p_70999_1_, p_70999_2_, p_70999_3_); this.func_70105_a(0.6F, 1.8F); IBlockState iblockstate = this.field_70170_p.func_180495_p(this.field_71081_bT); - if (this.field_71081_bT != null && iblockstate.func_177230_c() == Blocks.field_150324_C) + if (this.field_71081_bT != null && iblockstate.func_177230_c().isBed(iblockstate, field_70170_p, field_71081_bT, this)) { - this.field_70170_p.func_180501_a(this.field_71081_bT, iblockstate.func_177226_a(BlockBed.field_176471_b, Boolean.valueOf(false)), 4); - BlockPos blockpos = BlockBed.func_176468_a(this.field_70170_p, this.field_71081_bT, 0); + iblockstate.func_177230_c().setBedOccupied(field_70170_p, field_71081_bT, this, false); + BlockPos blockpos = iblockstate.func_177230_c().getBedSpawnPosition(iblockstate, field_70170_p, field_71081_bT, this); if (blockpos == null) { @@ -1545,6 +1624,10 @@ this.func_70107_b((double)((float)blockpos.func_177958_n() + 0.5F), (double)((float)blockpos.func_177956_o() + 0.1F), (double)((float)blockpos.func_177952_p() + 0.5F)); } + else + { + p_70999_3_ = false; + } this.field_71083_bS = false; @@ -1563,15 +1646,16 @@ private boolean func_175143_p() { - return this.field_70170_p.func_180495_p(this.field_71081_bT).func_177230_c() == Blocks.field_150324_C; + return net.minecraftforge.event.ForgeEventFactory.fireSleepingLocationCheck(this, this.field_71081_bT); } @Nullable public static BlockPos func_180467_a(World p_180467_0_, BlockPos p_180467_1_, boolean p_180467_2_) { - Block block = p_180467_0_.func_180495_p(p_180467_1_).func_177230_c(); + IBlockState state = p_180467_0_.func_180495_p(p_180467_1_); + Block block = state.func_177230_c(); - if (block != Blocks.field_150324_C) + if (!block.isBed(state, p_180467_0_, p_180467_1_, null)) { if (!p_180467_2_) { @@ -1586,16 +1670,17 @@ } else { - return BlockBed.func_176468_a(p_180467_0_, p_180467_1_, 0); + return block.getBedSpawnPosition(state, p_180467_0_, p_180467_1_, null); } } @SideOnly(Side.CLIENT) public float func_71051_bG() { - if (this.field_71081_bT != null) + IBlockState state = this.field_71081_bT == null ? null : this.field_70170_p.func_180495_p(field_71081_bT); + if (state != null && state.func_177230_c().isBed(state, field_70170_p, field_71081_bT, this)) { - EnumFacing enumfacing = (EnumFacing)this.field_70170_p.func_180495_p(this.field_71081_bT).func_177229_b(BlockHorizontal.field_185512_D); + EnumFacing enumfacing = state.func_177230_c().getBedDirection(state, field_70170_p, field_71081_bT); switch (enumfacing) { @@ -1635,16 +1720,24 @@ public BlockPos func_180470_cg() { - return this.field_71077_c; + return getBedLocation(this.field_71093_bK); } + @Deprecated // Use dimension-sensitive version. public boolean func_82245_bX() { - return this.field_82248_d; + return isSpawnForced(this.field_71093_bK); } public void func_180473_a(BlockPos p_180473_1_, boolean p_180473_2_) { + if(net.minecraftforge.event.ForgeEventFactory.onPlayerSpawnSet(this, p_180473_1_, p_180473_2_)) return; + if (this.field_71093_bK != 0) + { + setSpawnChunk(p_180473_1_, p_180473_2_, this.field_71093_bK); + return; + } + if (p_180473_1_ != null) { this.field_71077_c = p_180473_1_; @@ -1839,6 +1932,10 @@ super.func_180430_e(p_180430_1_, p_180430_2_); } + else + { + net.minecraftforge.event.ForgeEventFactory.onPlayerFall(this, p_180430_1_, p_180430_2_); + } } protected void func_71061_d_() @@ -2039,6 +2136,18 @@ this.field_175152_f = p_71049_1_.field_175152_f; this.field_71078_a = p_71049_1_.field_71078_a; this.func_184212_Q().func_187227_b(field_184827_bp, p_71049_1_.func_184212_Q().func_187225_a(field_184827_bp)); + + this.spawnChunkMap = p_71049_1_.spawnChunkMap; + this.spawnForcedMap = p_71049_1_.spawnForcedMap; + + //Copy over a section of the Entity Data from the old player. + //Allows mods to specify data that persists after players respawn. + NBTTagCompound old = p_71049_1_.getEntityData(); + if (old.func_74764_b(PERSISTED_NBT_TAG)) + { + getEntityData().func_74782_a(PERSISTED_NBT_TAG, old.func_74775_l(PERSISTED_NBT_TAG)); + } + net.minecraftforge.event.ForgeEventFactory.onPlayerClone(this, p_71049_1_, !p_71049_2_); } protected boolean func_70041_e_() @@ -2137,7 +2246,10 @@ public ITextComponent func_145748_c_() { - ITextComponent itextcomponent = new TextComponentString(ScorePlayerTeam.func_96667_a(this.func_96124_cp(), this.func_70005_c_())); + ITextComponent itextcomponent = new TextComponentString(""); + if (!prefixes.isEmpty()) for (ITextComponent prefix : prefixes) itextcomponent.func_150257_a(prefix); + itextcomponent.func_150257_a(new TextComponentString(ScorePlayerTeam.func_96667_a(this.func_96124_cp(), this.getDisplayNameString()))); + if (!suffixes.isEmpty()) for (ITextComponent suffix : suffixes) itextcomponent.func_150257_a(suffix); itextcomponent.func_150256_b().func_150241_a(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/msg " + this.func_70005_c_() + " ")); itextcomponent.func_150256_b().func_150209_a(this.func_174823_aP()); itextcomponent.func_150256_b().func_179989_a(this.func_70005_c_()); @@ -2146,7 +2258,7 @@ public float func_70047_e() { - float f = 1.62F; + float f = eyeHeight; if (this.func_70608_bn()) { @@ -2362,6 +2474,162 @@ return this.field_71075_bZ.field_75098_d && this.func_70003_b(2, ""); } + /** + * Opens a GUI with this player, uses FML's IGuiHandler system. + * Allows for extension by modders. + * + * @param mod The mod trying to open a GUI + * @param modGuiId GUI ID + * @param world Current World + * @param x Passed directly to IGuiHandler, data meaningless Typically world X position + * @param y Passed directly to IGuiHandler, data meaningless Typically world Y position + * @param z Passed directly to IGuiHandler, data meaningless Typically world Z position + */ + public void openGui(Object mod, int modGuiId, World world, int x, int y, int z) + { + net.minecraftforge.fml.common.network.internal.FMLNetworkHandler.openGui(this, mod, modGuiId, world, x, y, z); + } + + + /* ======================================== FORGE START =====================================*/ + /** + * A dimension aware version of getBedLocation. + * @param dimension The dimension to get the bed spawn for + * @return The player specific spawn location for the dimension. May be null. + */ + public BlockPos getBedLocation(int dimension) + { + return dimension == 0 ? field_71077_c : spawnChunkMap.get(dimension); + } + + /** + * A dimension aware version of isSpawnForced. + * Noramally isSpawnForced is used to determine if the respawn system should check for a bed or not. + * This just extends that to be dimension aware. + * @param dimension The dimension to get whether to check for a bed before spawning for + * @return The player specific spawn location for the dimension. May be null. + */ + public boolean isSpawnForced(int dimension) + { + if (dimension == 0) return this.field_82248_d; + Boolean forced = this.spawnForcedMap.get(dimension); + return forced == null ? false : forced; + } + + /** + * A dimension aware version of setSpawnChunk. + * This functions identically, but allows you to specify which dimension to affect, rather than affecting the player's current dimension. + * @param pos The spawn point to set as the player-specific spawn point for the dimension + * @param forced Whether or not the respawn code should check for a bed at this location (true means it won't check for a bed) + * @param dimension Which dimension to apply the player-specific respawn point to + */ + public void setSpawnChunk(BlockPos pos, boolean forced, int dimension) + { + if (dimension == 0) + { + if (pos != null) + { + field_71077_c = pos; + field_82248_d = forced; + } + else + { + field_71077_c = null; + field_82248_d = false; + } + return; + } + + if (pos != null) + { + spawnChunkMap.put(dimension, pos); + spawnForcedMap.put(dimension, forced); + } + else + { + spawnChunkMap.remove(dimension); + spawnForcedMap.remove(dimension); + } + } + + private String displayname; + + /** + * Returns the default eye height of the player + * @return player default eye height + */ + public float getDefaultEyeHeight() + { + return 1.62F; + } + + /** + * Get the currently computed display name, cached for efficiency. + * @return the current display name + */ + public String getDisplayNameString() + { + if(this.displayname == null) + { + this.displayname = net.minecraftforge.event.ForgeEventFactory.getPlayerDisplayName(this, this.func_70005_c_()); + } + return this.displayname; + } + + /** + * Force the displayed name to refresh + */ + public void refreshDisplayName() + { + this.displayname = net.minecraftforge.event.ForgeEventFactory.getPlayerDisplayName(this, this.func_70005_c_()); + } + + private final java.util.Collection prefixes = new java.util.LinkedList(); + private final java.util.Collection suffixes = new java.util.LinkedList(); + + /** + * Add a prefix to the player's username in chat + * @param prefix The prefix + */ + public void addPrefix(ITextComponent prefix) { prefixes.add(prefix); } + + /** + * Add a suffix to the player's username in chat + * @param suffix The suffix + */ + public void addSuffix(ITextComponent suffix) { suffixes.add(suffix); } + + public java.util.Collection getPrefixes() { return this.prefixes; } + public java.util.Collection getSuffixes() { return this.suffixes; } + + private final net.minecraftforge.items.IItemHandler playerMainHandler = new net.minecraftforge.items.wrapper.PlayerMainInvWrapper(field_71071_by); + private final net.minecraftforge.items.IItemHandler playerEquipmentHandler = new net.minecraftforge.items.wrapper.CombinedInvWrapper( + new net.minecraftforge.items.wrapper.PlayerArmorInvWrapper(field_71071_by), + new net.minecraftforge.items.wrapper.PlayerOffhandInvWrapper(field_71071_by)); + private final net.minecraftforge.items.IItemHandler playerJoinedHandler = new net.minecraftforge.items.wrapper.PlayerInvWrapper(field_71071_by); + + @SuppressWarnings("unchecked") + @Override + @Nullable + public T getCapability(net.minecraftforge.common.capabilities.Capability capability, @Nullable net.minecraft.util.EnumFacing facing) + { + if (capability == net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) + { + if (facing == null) return (T) playerJoinedHandler; + else if (facing.func_176740_k().func_176720_b()) return (T) playerMainHandler; + else if (facing.func_176740_k().func_176722_c()) return (T) playerEquipmentHandler; + } + return super.getCapability(capability, facing); + } + + @Override + public boolean hasCapability(net.minecraftforge.common.capabilities.Capability capability, @Nullable net.minecraft.util.EnumFacing facing) + { + return capability == net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY || super.hasCapability(capability, facing); + } + + /* ======================================== FORGE END =====================================*/ + public static enum EnumChatVisibility { FULL(0, "options.chat.visibility.full"),