Guest User

Untitled

a guest
Dec 12th, 2018
213
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 79.47 KB | None | 0 0
  1. /*
  2. c ** 2012 August 13
  3. **
  4. ** The author disclaims copyright to this source code. In place of
  5. ** a legal notice, here is a blessing:
  6. ** May you do good and not evil.
  7. ** May you find forgiveness for yourself and forgive others.
  8. ** May you share freely, never taking more than you give.
  9. */
  10. package com.TheRPGAdventurer.ROTD.server.entity;
  11.  
  12. import static net.minecraft.entity.SharedMonsterAttributes.ATTACK_DAMAGE;
  13. import static net.minecraft.entity.SharedMonsterAttributes.FOLLOW_RANGE;
  14.  
  15. import java.util.ArrayList;
  16. import java.util.BitSet;
  17. import java.util.HashMap;
  18. import java.util.List;
  19. import java.util.Map;
  20. import java.util.Random;
  21. import java.util.UUID;
  22.  
  23. import javax.annotation.Nullable;
  24.  
  25. import org.apache.logging.log4j.LogManager;
  26. import org.apache.logging.log4j.Logger;
  27.  
  28. import com.TheRPGAdventurer.ROTD.DragonMounts;
  29. import com.TheRPGAdventurer.ROTD.DragonMountsConfig;
  30. import com.TheRPGAdventurer.ROTD.client.initialization.ModArmour;
  31. import com.TheRPGAdventurer.ROTD.client.initialization.ModKeys;
  32. import com.TheRPGAdventurer.ROTD.client.initialization.ModTools;
  33. import com.TheRPGAdventurer.ROTD.client.inventory.ContainerDragon;
  34. import com.TheRPGAdventurer.ROTD.client.message.DragonBreathMessage;
  35. import com.TheRPGAdventurer.ROTD.client.model.dragon.anim.DragonAnimator;
  36. import com.TheRPGAdventurer.ROTD.client.sound.ModSounds;
  37. import com.TheRPGAdventurer.ROTD.server.entity.ai.ground.EntityAIDragonSit;
  38. import com.TheRPGAdventurer.ROTD.server.entity.ai.path.PathNavigateFlying;
  39. import com.TheRPGAdventurer.ROTD.server.entity.breeds.DragonBreed;
  40. import com.TheRPGAdventurer.ROTD.server.entity.breeds.EnumDragonBreed;
  41. import com.TheRPGAdventurer.ROTD.server.entity.helper.DragonBodyHelper;
  42. import com.TheRPGAdventurer.ROTD.server.entity.helper.DragonBrain;
  43. import com.TheRPGAdventurer.ROTD.server.entity.helper.DragonBreedHelper;
  44. import com.TheRPGAdventurer.ROTD.server.entity.helper.DragonHeadPositionHelper;
  45. import com.TheRPGAdventurer.ROTD.server.entity.helper.DragonHelper;
  46. import com.TheRPGAdventurer.ROTD.server.entity.helper.DragonInteractHelper;
  47. import com.TheRPGAdventurer.ROTD.server.entity.helper.DragonLifeStageHelper;
  48. import com.TheRPGAdventurer.ROTD.server.entity.helper.DragonMoveHelper;
  49. import com.TheRPGAdventurer.ROTD.server.entity.helper.DragonParticleHelper;
  50. import com.TheRPGAdventurer.ROTD.server.entity.helper.DragonReproductionHelper;
  51. import com.TheRPGAdventurer.ROTD.server.entity.helper.DragonSoundManager;
  52. import com.TheRPGAdventurer.ROTD.server.entity.helper.breath.DragonBreathHelper;
  53. import com.TheRPGAdventurer.ROTD.server.network.MessageDragonInventory;
  54. import com.TheRPGAdventurer.ROTD.server.util.ItemUtils;
  55. import com.TheRPGAdventurer.ROTD.util.DMUtils;
  56. import com.TheRPGAdventurer.ROTD.util.PrivateFields;
  57. import com.google.common.base.Optional;
  58.  
  59. import net.minecraft.block.Block;
  60. import net.minecraft.block.material.Material;
  61. import net.minecraft.block.state.IBlockState;
  62. import net.minecraft.client.Minecraft;
  63. import net.minecraft.entity.Entity;
  64. import net.minecraft.entity.EntityAgeable;
  65. import net.minecraft.entity.EntityList;
  66. import net.minecraft.entity.EntityLiving;
  67. import net.minecraft.entity.EntityLivingBase;
  68. import net.minecraft.entity.EnumCreatureAttribute;
  69. import net.minecraft.entity.IEntityMultiPart;
  70. import net.minecraft.entity.MultiPartEntityPart;
  71. import net.minecraft.entity.SharedMonsterAttributes;
  72. import net.minecraft.entity.ai.EntityAITasks;
  73. import net.minecraft.entity.ai.attributes.IAttribute;
  74. import net.minecraft.entity.ai.attributes.RangedAttribute;
  75. import net.minecraft.entity.effect.EntityLightningBolt;
  76. import net.minecraft.entity.item.EntityEnderCrystal;
  77. import net.minecraft.entity.passive.EntityAnimal;
  78. import net.minecraft.entity.passive.EntityTameable;
  79. import net.minecraft.entity.player.EntityPlayer;
  80. import net.minecraft.init.Blocks;
  81. import net.minecraft.init.Items;
  82. import net.minecraft.init.MobEffects;
  83. import net.minecraft.init.SoundEvents;
  84. import net.minecraft.inventory.ContainerHorseChest;
  85. import net.minecraft.inventory.IInventory;
  86. import net.minecraft.inventory.IInventoryChangedListener;
  87. import net.minecraft.item.Item;
  88. import net.minecraft.item.ItemStack;
  89. import net.minecraft.nbt.NBTTagCompound;
  90. import net.minecraft.nbt.NBTTagList;
  91. import net.minecraft.network.datasync.DataParameter;
  92. import net.minecraft.network.datasync.DataSerializers;
  93. import net.minecraft.network.datasync.EntityDataManager;
  94. import net.minecraft.network.play.server.SPacketAnimation;
  95. import net.minecraft.pathfinding.PathNavigateGround;
  96. import net.minecraft.potion.PotionEffect;
  97. import net.minecraft.util.DamageSource;
  98. import net.minecraft.util.EntitySelectors;
  99. import net.minecraft.util.EnumHand;
  100. import net.minecraft.util.EnumParticleTypes;
  101. import net.minecraft.util.ResourceLocation;
  102. import net.minecraft.util.SoundCategory;
  103. import net.minecraft.util.SoundEvent;
  104. import net.minecraft.util.math.BlockPos;
  105. import net.minecraft.util.math.MathHelper;
  106. import net.minecraft.util.math.RayTraceResult;
  107. import net.minecraft.util.math.Vec3d;
  108. import net.minecraft.util.text.ITextComponent;
  109. import net.minecraft.util.text.TextComponentTranslation;
  110. import net.minecraft.world.IBlockAccess;
  111. import net.minecraft.world.World;
  112. import net.minecraft.world.WorldServer;
  113. import net.minecraftforge.common.IShearable;
  114. import net.minecraftforge.fml.relauncher.ReflectionHelper;
  115. import net.minecraftforge.fml.relauncher.Side;
  116. import net.minecraftforge.fml.relauncher.SideOnly;
  117. import net.minecraftforge.items.ItemStackHandler;
  118.  
  119. /**
  120. * Here be dragons.
  121. *
  122. * @author Nico Bergemann <barracuda415 at yahoo.de>
  123. * @Modifier James Miller <TheRPGAdventurer.>
  124. */
  125. public class EntityTameableDragon extends EntityTameable implements IShearable, IEntityMultiPart, IDragonWhistle {
  126.  
  127. private static final Logger L = LogManager.getLogger();
  128.  
  129. public static final IAttribute MOVEMENT_SPEED_AIR = new RangedAttribute(null, "generic.movementSpeedAir", 1.5, 0.0,
  130. Double.MAX_VALUE).setDescription("Movement Speed Air").setShouldWatch(true);
  131.  
  132. // base attributes
  133. public static final double BASE_GROUND_SPEED = 0.3;
  134. public static final double BASE_AIR_SPEED = 0.9;
  135. public static final double BASE_DAMAGE = 3.0D;
  136. public static final double BASE_ARMOR = 10.0D;
  137. public static final double BASE_TOUGHNESS = 30.0D;
  138. public static final float BASE_WIDTH = 2.75f;
  139. public static final float BASE_HEIGHT = 2.0f;
  140. public static final float RESISTANCE = 10.0f;
  141. public static final double BASE_FOLLOW_RANGE = 70;
  142. public static final double BASE_FOLLOW_RANGE_FLYING = BASE_FOLLOW_RANGE * 2;
  143. public static final int HOME_RADIUS = 64;
  144. public static final double IN_AIR_THRESH = 10;
  145.  
  146. protected int ticksSinceLastAttack;
  147. public static int ticksShear;
  148.  
  149. // data value IDs
  150. private static final DataParameter<Boolean> DATA_FLYING = EntityDataManager
  151. .<Boolean>createKey(EntityTameableDragon.class, DataSerializers.BOOLEAN);
  152. private static final DataParameter<Boolean> DATA_SADDLED = EntityDataManager
  153. .<Boolean>createKey(EntityTameableDragon.class, DataSerializers.BOOLEAN);
  154. private static final DataParameter<Boolean> DATA_BREATHING = EntityDataManager
  155. .<Boolean>createKey(EntityTameableDragon.class, DataSerializers.BOOLEAN);
  156. private static final DataParameter<Boolean> CHESTED = EntityDataManager
  157. .<Boolean>createKey(EntityTameableDragon.class, DataSerializers.BOOLEAN);
  158. private static final DataParameter<Boolean> ALLOW_OTHERPLAYERS = EntityDataManager
  159. .<Boolean>createKey(EntityTameableDragon.class, DataSerializers.BOOLEAN);
  160. private static final DataParameter<Boolean> IS_MALE = EntityDataManager
  161. .<Boolean>createKey(EntityTameableDragon.class, DataSerializers.BOOLEAN);
  162. private static final DataParameter<Integer> ARMOR = EntityDataManager
  163. .<Integer>createKey(EntityTameableDragon.class, DataSerializers.VARINT);
  164. private static final DataParameter<Integer> AIRSPEEDVERT = EntityDataManager
  165. .<Integer>createKey(EntityTameableDragon.class, DataSerializers.VARINT);
  166. private static final DataParameter<Optional<UUID>> DATA_BREEDER = EntityDataManager
  167. .<Optional<UUID>>createKey(EntityTameableDragon.class, DataSerializers.OPTIONAL_UNIQUE_ID);
  168. private static final DataParameter<String> DATA_BREED = EntityDataManager
  169. .<String>createKey(EntityTameableDragon.class, DataSerializers.STRING);
  170. private static final DataParameter<Integer> DATA_REPRO_COUNT = EntityDataManager
  171. .<Integer>createKey(EntityTameableDragon.class, DataSerializers.VARINT);
  172. private static final DataParameter<Integer> DATA_TICKS_SINCE_CREATION = EntityDataManager
  173. .<Integer>createKey(EntityTameableDragon.class, DataSerializers.VARINT);
  174. private static final DataParameter<Byte> DRAGON_SCALES = EntityDataManager
  175. .<Byte>createKey(EntityTameableDragon.class, DataSerializers.BYTE);
  176. private static final DataParameter<String> DATA_BREATH_WEAPON = EntityDataManager
  177. .<String>createKey(EntityTameableDragon.class, DataSerializers.STRING);
  178. private static final DataParameter<Boolean> BANNERED1 = EntityDataManager
  179. .<Boolean>createKey(EntityTameableDragon.class, DataSerializers.BOOLEAN);
  180. private static final DataParameter<Boolean> BANNERED2 = EntityDataManager
  181. .<Boolean>createKey(EntityTameableDragon.class, DataSerializers.BOOLEAN);
  182. private static final DataParameter<Boolean> BANNERED3 = EntityDataManager
  183. .<Boolean>createKey(EntityTameableDragon.class, DataSerializers.BOOLEAN);
  184. private static final DataParameter<Boolean> BANNERED4 = EntityDataManager
  185. .<Boolean>createKey(EntityTameableDragon.class, DataSerializers.BOOLEAN);
  186. private static final DataParameter<Boolean> HAS_ADJUCATOR_STONE = EntityDataManager
  187. .<Boolean>createKey(EntityTameableDragon.class, DataSerializers.BOOLEAN);
  188. private static final DataParameter<Boolean> HAS_ELDER_STONE = EntityDataManager
  189. .<Boolean>createKey(EntityTameableDragon.class, DataSerializers.BOOLEAN);
  190. private static final DataParameter<Byte> WHISTLE_STATE = EntityDataManager
  191. .<Byte>createKey(EntityTameableDragon.class, DataSerializers.BYTE);
  192.  
  193. // data NBT IDs
  194. public static final String NBT_ARMOR = "Armor";
  195. public static final String NBT_ALLOWOTHERPLAYERS = "AllowOtherPlayers";
  196. public static final String NBT_SADDLED = "Saddle";
  197. public static final String NBT_SHEARED = "Sheared";
  198. public static final String NBT_CHESTED = "Chested";
  199. public static final String NBT_BREATHING = "Breathing";
  200. public static final String NBT_ISMALE = "IsMale";
  201. public static final String NBT_BANNERED1 = "Bannered1";
  202. public static final String NBT_BANNERED2 = "Bannered2";
  203. public static final String NBT_BANNERED3 = "Bannered3";
  204. public static final String NBT_BANNERED4 = "Bannered4";
  205. public static final String NBT_ELDER = "Elder";
  206. public static final String NBT_ADJUCATOR = "Adjucator";
  207.  
  208. // server/client delegates
  209. private final Map<Class, DragonHelper> helpers = new HashMap<>();
  210.  
  211. // client-only delegates
  212. private final DragonBodyHelper bodyHelper = new DragonBodyHelper(this);
  213.  
  214. // server-only flags
  215. private BitSet controlFlags;
  216. private BitSet dragonWhistle;
  217.  
  218. public EntityEnderCrystal healingEnderCrystal;
  219. public DragonInventory dragonInv;
  220. public DragonInventory dragonStats;
  221. private ItemStackHandler itemHandler = null;
  222. private boolean hasChestVarChanged = false;
  223. public boolean nearGround;
  224. private boolean cancelYChanges;
  225. /** True if after a move this entity has collided with something on Y-axis */
  226. public boolean isCollidedVertically2;
  227. private boolean isUsingBreathWeapon;
  228. public boolean isSlowed;
  229. public int inAirTicks;
  230. public final EntityAITasks attackTasks;
  231. public DragonAnimator animator;
  232. private double airSpeedVertical = 0;
  233. public BlockPos airPosTarget;
  234. public final double nearGroundOffset = motionY + 5;
  235. public boolean hasHomePosition = false;
  236. public BlockPos homePos;
  237.  
  238. /** An array containing all body parts of this dragon */
  239. public MultiPartEntityPart[] dragonPartArray;
  240. public MultiPartEntityPart dragonPartHead = new MultiPartEntityPart(this, "head", 4.0F, 4.0F);
  241. public MultiPartEntityPart dragonPartBody = new MultiPartEntityPart(this, "body", 2.75f, 2.4f);
  242. public MultiPartEntityPart dragonPartNeck = new MultiPartEntityPart(this, "throat", 2.75f, 2.4f);
  243. public MultiPartEntityPart dragonPartTail = new MultiPartEntityPart(this, "tail", 5.0f, 5.0f);
  244.  
  245. public EntityTameableDragon(World world) {
  246. super(world);
  247.  
  248. this.dragonPartArray = new MultiPartEntityPart[] { this.dragonPartHead, this.dragonPartBody, this.dragonPartTail};
  249.  
  250. // override EntityBodyHelper field, which is private and has no setter
  251. // required to fixate body while sitting. also slows down rotation while
  252. // standing.
  253. try {
  254. ReflectionHelper.setPrivateValue(EntityLiving.class, this, new DragonBodyHelper(this),
  255. PrivateFields.ENTITYLIVING_BODYHELPER);
  256. } catch (Exception ex) {
  257. L.warn("Can't override EntityBodyHelper", ex);
  258. }
  259.  
  260. attackTasks = new EntityAITasks(world != null ? world.profiler : null);
  261.  
  262. // set base size
  263. setSize(BASE_WIDTH, BASE_HEIGHT);
  264.  
  265. // enables walking over blocks
  266. stepHeight = 1;
  267.  
  268. // create entity delegates
  269. addHelper(new DragonBreedHelper(this, DATA_BREED));
  270. addHelper(new DragonLifeStageHelper(this, DATA_TICKS_SINCE_CREATION));
  271. addHelper(new DragonReproductionHelper(this, DATA_BREEDER, DATA_REPRO_COUNT));
  272. addHelper(new DragonBreathHelper(this, DATA_BREATH_WEAPON));
  273. addHelper(new DragonSoundManager(this));
  274. addHelper(new DragonInteractHelper(this));
  275.  
  276. InitializeDragonInventory();
  277. InitializeDragonStats();
  278.  
  279. if (isClient()) {
  280. addHelper(new DragonParticleHelper(this));
  281. } else {
  282. addHelper(new DragonBrain(this));
  283. }
  284.  
  285. moveHelper = new DragonMoveHelper(this);
  286. aiSit = new EntityAIDragonSit(this);
  287.  
  288. // init helpers
  289. helpers.values().forEach(DragonHelper::applyEntityAttributes);
  290. animator = new DragonAnimator(this);
  291.  
  292. }
  293.  
  294. @Override
  295. protected void updateAITasks() {
  296. attackTasks.onUpdateTasks();
  297. }
  298.  
  299. @Override
  300. protected float updateDistance(float p_110146_1_, float p_110146_2_) {
  301. // required to fixate body while sitting. also slows down rotation while
  302. // standing.
  303. bodyHelper.updateRenderAngles();
  304. return p_110146_2_;
  305. }
  306.  
  307. @Override
  308. protected void entityInit() {
  309. super.entityInit();
  310.  
  311. dataManager.register(DATA_FLYING, false);
  312. dataManager.register(DATA_BREATHING, false);
  313. dataManager.register(DATA_SADDLED, false);
  314. dataManager.register(CHESTED, false);
  315. dataManager.register(IS_MALE, getRNG().nextBoolean());
  316. dataManager.register(DRAGON_SCALES, Byte.valueOf((byte) 0));
  317. dataManager.register(ARMOR, 0);
  318. dataManager.register(BANNERED1, false);
  319. dataManager.register(BANNERED2, false);
  320. dataManager.register(BANNERED3, false);
  321. dataManager.register(BANNERED4, false);
  322. dataManager.register(HAS_ELDER_STONE, false);
  323. dataManager.register(HAS_ADJUCATOR_STONE, false);
  324. dataManager.register(ALLOW_OTHERPLAYERS, false);
  325. dataManager.register(WHISTLE_STATE, Byte.valueOf((byte) 0));
  326. }
  327.  
  328. @Override
  329. protected void applyEntityAttributes() {
  330. super.applyEntityAttributes();
  331.  
  332. getAttributeMap().registerAttribute(MOVEMENT_SPEED_AIR);
  333. getAttributeMap().registerAttribute(ATTACK_DAMAGE);
  334. getEntityAttribute(MOVEMENT_SPEED_AIR).setBaseValue(BASE_AIR_SPEED);
  335. getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(BASE_GROUND_SPEED);
  336. getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(BASE_DAMAGE);
  337. getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).setBaseValue(BASE_FOLLOW_RANGE);
  338. getEntityAttribute(SharedMonsterAttributes.KNOCKBACK_RESISTANCE).setBaseValue(RESISTANCE);
  339. getEntityAttribute(SharedMonsterAttributes.ARMOR).setBaseValue(BASE_ARMOR);
  340. getEntityAttribute(SharedMonsterAttributes.ARMOR_TOUGHNESS).setBaseValue(BASE_TOUGHNESS);
  341. }
  342.  
  343. /**
  344. * (abstract) Protected helper method to write subclass entity data to NBT.
  345. */
  346. @Override
  347. public void writeEntityToNBT(NBTTagCompound nbt) {
  348. super.writeEntityToNBT(nbt);
  349. nbt.setBoolean(NBT_SADDLED, isSaddled());
  350. nbt.setInteger(NBT_ARMOR, this.getArmor());
  351. nbt.setBoolean(NBT_CHESTED, this.isChested());
  352. nbt.setBoolean(NBT_SHEARED, this.isSheared());
  353. nbt.setBoolean(NBT_BREATHING, this.isUsingBreathWeapon());
  354. nbt.setBoolean(NBT_ISMALE, this.isMale());
  355. nbt.setBoolean(NBT_BANNERED1, this.isBannered1());
  356. nbt.setBoolean(NBT_BANNERED2, this.isBannered2());
  357. nbt.setBoolean(NBT_BANNERED3, this.isBannered3());
  358. nbt.setBoolean(NBT_BANNERED4, this.isBannered4());
  359. nbt.setBoolean(NBT_ELDER, this.canBeElder());
  360. nbt.setBoolean(NBT_ADJUCATOR, this.canBeAdjucator());
  361. nbt.setBoolean(NBT_ALLOWOTHERPLAYERS, this.allowedOtherPlayers());
  362. //nbt.setBoolean("cancelY", );
  363. nbt.setBoolean("nearGround", this.nearGround);
  364. nbt.setBoolean("isCircling", isCircling);
  365. nbt.setBoolean("HasHomePosition", this.hasHomePosition);
  366. if (homePos != null && this.hasHomePosition) {
  367. nbt.setInteger("HomeAreaX", homePos.getX());
  368. nbt.setInteger("HomeAreaY", homePos.getY());
  369. nbt.setInteger("HomeAreaZ", homePos.getZ());
  370. }
  371. writeDragonInventory(nbt);
  372. writeDragonStats(nbt);
  373. helpers.values().forEach(helper -> helper.writeToNBT(nbt));
  374. }
  375.  
  376. /**
  377. * (abstract) Protected helper method to read subclass entity data from NBT.
  378. */
  379. @Override
  380. public void readEntityFromNBT(NBTTagCompound nbt) {
  381. super.readEntityFromNBT(nbt);
  382. this.setSaddled(nbt.getBoolean(NBT_SADDLED));
  383. this.setChested(nbt.getBoolean(NBT_CHESTED));
  384. this.setSheared(nbt.getBoolean(NBT_SHEARED));
  385. this.setUsingBreathWeapon(nbt.getBoolean(NBT_BREATHING));
  386. this.setArmor(nbt.getInteger(NBT_ARMOR));
  387. this.setMale(nbt.getBoolean(NBT_ISMALE));
  388. this.setBannered1(nbt.getBoolean(NBT_BANNERED1));
  389. this.setBannered2(nbt.getBoolean(NBT_BANNERED2));
  390. this.setBannered3(nbt.getBoolean(NBT_BANNERED3));
  391. this.setBannered4(nbt.getBoolean(NBT_BANNERED4));
  392. this.setCanBeElder(nbt.getBoolean(NBT_ELDER));
  393. this.setCanBeAdjucator(nbt.getBoolean(NBT_ADJUCATOR));
  394. this.setToAllowedOtherPlayers(nbt.getBoolean(NBT_ALLOWOTHERPLAYERS));
  395. this.nearGround = nbt.getBoolean("nearGround");
  396. this.isCircling = nbt.getBoolean("isCircling");
  397. this.hasHomePosition = nbt.getBoolean("HasHomePosition");
  398. if (hasHomePosition && nbt.getInteger("HomeAreaX") != 0 && nbt.getInteger("HomeAreaY") != 0
  399. && nbt.getInteger("HomeAreaZ") != 0) {
  400. homePos = new BlockPos(nbt.getInteger("HomeAreaX"), nbt.getInteger("HomeAreaY"),
  401. nbt.getInteger("HomeAreaZ"));
  402. }
  403. readDragonInventory(nbt);
  404. readDragonStats(nbt);
  405. helpers.values().forEach(helper -> helper.readFromNBT(nbt));
  406.  
  407. }
  408.  
  409. /**
  410. * Returns true if the dragon is saddled.
  411. */
  412. public boolean isSaddled() {
  413. return dataManager.get(DATA_SADDLED);
  414. }
  415.  
  416. public void setControlFlags(BitSet flags) {
  417. controlFlags = flags;
  418. }
  419.  
  420. public BitSet getControlFlags() {
  421. return controlFlags;
  422. }
  423.  
  424. public void setWhistleFlags(BitSet flags) {
  425. dragonWhistle = flags;
  426. }
  427.  
  428. public boolean isCircling;
  429.  
  430. public boolean isCircling() {
  431. return isCircling;
  432. }
  433.  
  434. public void setCircling(boolean isCircling) {
  435. this.isCircling = isCircling;
  436. }
  437.  
  438. public BitSet getWhistleFlags() {
  439. return dragonWhistle;
  440. }
  441.  
  442. private boolean getWhistleFlag(int index) {
  443. BitSet dragonWhistle = getWhistleFlags();
  444. return dragonWhistle == null ? false : dragonWhistle.get(index);
  445. }
  446.  
  447.  
  448. /**
  449. * Returns relative speed multiplier for the vertical flying speed.
  450. *
  451. * @return relative vertical speed multiplier
  452. */
  453. public double getMoveSpeedAirVert() {
  454. return this.airSpeedVertical;
  455. }
  456.  
  457. /**
  458. * Sets new relative speed multiplier for the vertical flying speed.
  459. *
  460. * @param airSpeedVertical new relative vertical speed multiplier
  461. */
  462. public void setMoveSpeedAirVert(double airSpeedVertical) {
  463. L.trace("setMoveSpeedAirVert({})", airSpeedVertical);
  464. this.airSpeedVertical = airSpeedVertical;
  465. }
  466.  
  467. /**
  468. * Set or remove the saddle of the dragon.
  469. */
  470. public void setSaddled(boolean saddled) {
  471. L.trace("setSaddled({})", saddled);
  472. dataManager.set(DATA_SADDLED, saddled);
  473. }
  474.  
  475. public boolean allowedOtherPlayers() {
  476. return dataManager.get(ALLOW_OTHERPLAYERS);
  477. }
  478.  
  479. public void setToAllowedOtherPlayers(boolean allow) {
  480. dataManager.set(ALLOW_OTHERPLAYERS, allow);
  481. }
  482.  
  483. // used to be called isChestedLeft
  484. public boolean isChested() {
  485. return dataManager.get(CHESTED);
  486. }
  487.  
  488. public void setChested(boolean chested) {
  489. dataManager.set(CHESTED, chested);
  490. hasChestVarChanged = true;
  491. }
  492.  
  493. public boolean isBannered1() {
  494. return dataManager.get(BANNERED1);
  495. }
  496.  
  497. public void setBannered1(boolean bannered) {
  498. dataManager.set(BANNERED1, bannered);
  499. }
  500.  
  501. public boolean canBeAdjucator() {
  502. return dataManager.get(HAS_ADJUCATOR_STONE);
  503. }
  504.  
  505. public void setCanBeAdjucator(boolean male) {
  506. dataManager.set(HAS_ADJUCATOR_STONE, male);
  507. }
  508.  
  509. public boolean canBeElder() {
  510. return dataManager.get(HAS_ELDER_STONE);
  511. }
  512.  
  513. public void setCanBeElder(boolean male) {
  514. dataManager.set(HAS_ELDER_STONE, male);
  515. }
  516.  
  517. public boolean isBannered2() {
  518. return dataManager.get(BANNERED2);
  519. }
  520.  
  521. public void setBannered2(boolean male) {
  522. dataManager.set(BANNERED2, male);
  523. }
  524.  
  525. public boolean isBannered3() {
  526. return dataManager.get(BANNERED2);
  527. }
  528.  
  529. public void setBannered3(boolean male) {
  530. dataManager.set(BANNERED2, male);
  531. }
  532.  
  533. public boolean isBannered4() {
  534. return dataManager.get(BANNERED4);
  535. }
  536.  
  537. public void setBannered4(boolean male) {
  538. dataManager.set(BANNERED4, male);
  539. }
  540.  
  541. public boolean nothing() {
  542. return (dataManager.get(WHISTLE_STATE).byteValue() & 1) == 1;
  543. }
  544.  
  545. public boolean follow() {
  546. return (dataManager.get(WHISTLE_STATE).byteValue() >> 1 & 1) == 1;
  547. }
  548.  
  549. public boolean circle() {
  550. return (dataManager.get(WHISTLE_STATE).byteValue() >> 2 & 1) == 1;
  551. }
  552.  
  553. public boolean landToPlayer() {
  554. return (dataManager.get(WHISTLE_STATE).byteValue() >> 3 & 1) == 1;
  555. }
  556.  
  557.  
  558. @Override
  559. public void nothing(boolean nothing) {
  560. setStateField(0, nothing);
  561. }
  562.  
  563. @Override
  564. public void follow(boolean follow) {
  565. setStateField(1, follow);
  566. }
  567.  
  568. @Override
  569. public void circle(boolean circle) {
  570. setStateField(2, circle);
  571. }
  572.  
  573. @Override
  574. public void landToPlayer(boolean landToPlayer) {
  575. setStateField(3, landToPlayer);
  576. }
  577.  
  578. /**
  579. * @TheRPGAdventurer thanks AlexThe666
  580. * @param
  581. * @param
  582. */
  583. private void setStateField(int i, boolean newState) {
  584. byte prevState = dataManager.get(WHISTLE_STATE).byteValue();
  585. if (newState) {
  586. dataManager.set(WHISTLE_STATE, (byte) (prevState | (1 << i)));
  587. } else {
  588. dataManager.set(WHISTLE_STATE, (byte) (prevState & ~(1 << i)));
  589. }
  590. }
  591.  
  592. public byte getControlState() {
  593. return dataManager.get(WHISTLE_STATE).byteValue();
  594. }
  595.  
  596. public void setControlState(byte state) {
  597. dataManager.set(WHISTLE_STATE, (byte) state);
  598. }
  599.  
  600. /**
  601. * Gets the gender since booleans return only 2 values (true or false) true == MALE, false == FEMALE
  602. * 2 genders only dont call me sexist and dont talk to me about political correctness
  603. */
  604. public boolean isMale() {
  605. return dataManager.get(IS_MALE);
  606. }
  607.  
  608. public void setMale(boolean male) {
  609. dataManager.set(IS_MALE, male);
  610. }
  611.  
  612. public void setOppositeGender() {
  613. if(isMale()) {
  614. this.setMale(false);
  615. } else if(!isMale()) {
  616. this.setMale(true);
  617. }
  618. }
  619. /**
  620. * 1 equals iron 2 equals gold 3 equals diamond
  621. *
  622. * @return 0 no armor
  623. */
  624. public int getArmor() {
  625. return this.dataManager.get(ARMOR);
  626. }
  627.  
  628. public void setArmor(int armorType) {
  629. this.dataManager.set(ARMOR, armorType);
  630. }
  631.  
  632. public boolean canFly() {
  633. // eggs can't fly, hatchlings now can
  634. return !isEgg();
  635. }
  636.  
  637. /**
  638. * Returns true if the entity is flying.
  639. */
  640. public boolean isFlying() {
  641. return dataManager.get(DATA_FLYING);
  642. }
  643.  
  644. /**
  645. * f Set the flying flag of the entity.
  646. */
  647. public void setFlying(boolean flying) {
  648. L.trace("setFlying({})", flying);
  649. dataManager.set(DATA_FLYING, flying);
  650. }
  651.  
  652. /**
  653. * Returns true if the entity is breathing.
  654. */
  655. public boolean isUsingBreathWeapon() {
  656. if (world.isRemote) {
  657. boolean usingBreathWeapon = this.dataManager.get(DATA_BREATHING);
  658. this.isUsingBreathWeapon = usingBreathWeapon;
  659. return usingBreathWeapon;
  660. }
  661. return isUsingBreathWeapon;
  662. }
  663.  
  664. /**
  665. * Set the breathing flag of the entity.
  666. */
  667. public void setUsingBreathWeapon(boolean usingBreathWeapon) {
  668. this.dataManager.set(DATA_BREATHING, usingBreathWeapon);
  669. if (!world.isRemote) {
  670. this.isUsingBreathWeapon = usingBreathWeapon;
  671. }
  672. }
  673.  
  674. /**
  675. * Called when the mob is falling. Calculates and applies fall damage.
  676. */
  677. @Override
  678. public void fall(float distance, float damageMultiplier) {
  679. // ignore fall damage if the entity can fly
  680. if (!canFly()) {
  681. super.fall(distance, damageMultiplier);
  682. }
  683. }
  684.  
  685. public int getTicksSinceLastAttack() {
  686. return ticksSinceLastAttack;
  687. }
  688.  
  689. /**
  690. * returns the pitch of the dragon's body
  691. *
  692. * @return
  693. */
  694. public float getBodyPitch() {
  695. return getAnimator().getBodyPitch();
  696. }
  697.  
  698. /**
  699. * Returns the distance to the ground while the entity is flying.
  700. */
  701. public double getAltitude() {
  702. BlockPos groundPos = world.getHeight(new BlockPos(this));
  703. double altitude = posY - groundPos.getY();
  704. return altitude;
  705. }
  706.  
  707. public float getDistanceSquared(Vec3d vec3d) {
  708. float f = (float) (this.posX - vec3d.x);
  709. float f1 = (float) (this.posY - vec3d.y);
  710. float f2 = (float) (this.posZ - vec3d.z);
  711. return f * f + f1 * f1 + f2 * f2;
  712. }
  713.  
  714. public void flyAround() {
  715. if (airPosTarget != null) {
  716. if (!isTargetInAir() || inAirTicks > 6000 || !this.isFlying()) {
  717. airPosTarget = null;
  718. }
  719.  
  720. flyTowardsTarget();
  721. }
  722.  
  723. DMUtils.getLogger().info("flyaround is called");
  724. }
  725.  
  726. public boolean doesWantToLand() {
  727. return this.inAirTicks > 6000 || inAirTicks > 40;
  728. }
  729.  
  730. public boolean isTargetBlocked(Vec3d target) {
  731. if (target != null) {
  732. RayTraceResult rayTrace = world.rayTraceBlocks(new Vec3d(this.getPosition()), target, false);
  733. if (rayTrace != null && rayTrace.hitVec != null) {
  734. BlockPos pos = new BlockPos(rayTrace.hitVec);
  735. if (!world.isAirBlock(pos)) {
  736. return true;
  737. }
  738. return rayTrace != null && rayTrace.typeOfHit != RayTraceResult.Type.BLOCK;
  739. }
  740. }
  741. return false;
  742. }
  743.  
  744. protected boolean isTargetInAir() {
  745. return airPosTarget != null && ((world.getBlockState(airPosTarget).getMaterial() == Material.AIR));
  746. }
  747.  
  748. public void flyTowardsTarget() {
  749. if (airPosTarget != null && isTargetInAir() && this.isFlying()
  750. && this.getDistanceSquared(new Vec3d(airPosTarget.getX(), this.posY, airPosTarget.getZ())) > 3) {
  751. double y = this.posY; // this.attackDecision ? airPosTarget.getY() :
  752.  
  753. double targetX = airPosTarget.getX() + 0.5D - posX;
  754. double targetY = Math.min(y, 256) + 1D - posY;
  755. double targetZ = airPosTarget.getZ() + 0.5D - posZ;
  756. motionX += (Math.signum(targetX) * 0.5D - motionX) * 0.100000000372529 * 3;
  757. motionY += (Math.signum(targetY) * 0.5D - motionY) * 0.100000000372529 * 3;
  758. motionZ += (Math.signum(targetZ) * 0.5D - motionZ) * 0.100000000372529 * 3;
  759. moveForward = 0.5F;
  760.  
  761. double d0 = airPosTarget.getX() + 0.5D - this.posX;
  762. double d2 = airPosTarget.getZ() + 0.5D - this.posZ;
  763. double d1 = y + 0.5D - this.posY;
  764. double d3 = (double) d0 + d2;
  765. float f = (float) (MathHelper.atan2(d2, d0) * (180D / Math.PI)) - 90.0F;
  766. float f1 = (float) (-(MathHelper.atan2(d1, d3) * (180D / Math.PI)));
  767. // this.rotationPitch = this.updateRotation(this.rotationPitch, f1, 30F);
  768. // this.rotationYaw = this.updateRotation(this.rotationYaw, f, 30F);
  769.  
  770. if (!this.isFlying()) {
  771. this.liftOff();
  772. }
  773. } else {
  774. this.airPosTarget = null;
  775. }
  776. // if (airPosTarget != null && isTargetInAir() && this.isFlying()
  777. // && this.getDistanceSquared(new Vec3d(airPosTarget.getX(), this.posY, airPosTarget.getZ())) < 3
  778. // && this.doesWantToLand()) {
  779. // this.setFlying(false);
  780. // this.setHovering(true);
  781. // this.flyHovering = 1;
  782. // }
  783. }
  784.  
  785. // public static BlockPos getBlockInView(EntityTameableDragon dragon) {
  786. /// float radius = 0.75F * (0.7F * 5 / 3) * - 7 - dragon.getRNG().nextInt(5 * 6);
  787. // float neg = dragon.getRNG().nextBoolean() ? 1 : -1;
  788. // float renderYawOffset = dragon.renderYawOffset;
  789. // if(dragon.hasHomePosition && dragon.homePos != null){
  790. // BlockPos dragonPos = new BlockPos(dragon);
  791. // BlockPos ground = dragon.world.getHeight(dragonPos);
  792. // int distFromGround = (int) dragon.posY - ground.getY();
  793. // for(int i = 0; i < 10; i++){
  794. // int homeWander = 40;
  795. // BlockPos pos = new BlockPos(dragon.homePos.getX() + dragon.getRNG().nextInt(DragonMountsConfig.dragonFlightHeight) - homeWander, (distFromGround > 16 ? (int) Math.min(DragonMountsConfig.dragonFlightHeight, dragon.posY + dragon.getRNG().nextInt(16) - 8) : (int) dragon.posY + dragon.getRNG().nextInt(16) + 1), (dragon.homePos.getZ() + dragon.getRNG().nextInt(homeWander * 2) - homeWander));
  796. // if (!dragon.isTargetBlocked(new Vec3d(pos)) && dragon.getDistanceSqToCenter(pos) > 6) {
  797. // return pos;
  798. // }
  799. // }
  800. // }
  801. // float angle = (0.01745329251F * renderYawOffset) + 3.15F + (dragon.getRNG().nextFloat() * neg);
  802.  
  803. // double extraX = (double) (radius * MathHelper.sin((float) (Math.PI + angle)));
  804. // double extraZ = (double) (radius * MathHelper.cos(angle));
  805. // BlockPos radialPos = new BlockPos(dragon.posX + extraX, 0, dragon.posZ + extraZ);
  806. // BlockPos ground = dragon.world.getHeight(radialPos);
  807. // int distFromGround = (int) dragon.posY - ground.getY();
  808. // BlockPos newPos = radialPos.up(distFromGround > 16 ? (int) Math.min(DragonMountsConfig.dragonFlightHeight, dragon.posY + dragon.getRNG().nextInt(16) - 8) : (int) dragon.posY + dragon.getRNG().nextInt(16) + 1);
  809. // if (!dragon.isTargetBlocked(new Vec3d(newPos)) && dragon.getDistanceSqToCenter(newPos) > 6) {
  810. // return newPos;
  811. // }
  812. // return null;
  813. // }
  814.  
  815. /**
  816. * Causes this entity to lift off if it can fly.
  817. */
  818. public void liftOff() {
  819. L.trace("liftOff");
  820. if (canFly()) {
  821. // stronger jump for an easier lift-off
  822. motionY += 25.5;
  823. inAirTicks += 400;
  824. jump();
  825. DMUtils.getLogger().info("tried to call dragon liftoff");
  826. }
  827. }
  828.  
  829.  
  830. @Override
  831. protected float getJumpUpwardsMotion() {
  832. // stronger jumps for easier lift-offs
  833. return canFly() ? 1 : super.getJumpUpwardsMotion();
  834. }
  835.  
  836. @SideOnly(Side.CLIENT)
  837. public void updateBreathing() {
  838. Minecraft mc = Minecraft.getMinecraft();
  839. if (hasControllingPlayer(mc.player)) {
  840. boolean isBreathing = ModKeys.KEY_BREATH.isKeyDown();
  841. DragonMounts.NETWORK_WRAPPER.sendToServer(new DragonBreathMessage(getEntityId(), isBreathing));
  842. }
  843. }
  844.  
  845. @Override
  846. public void onUpdate() {
  847. super.onUpdate();
  848. if (world.isRemote) {
  849. this.updateBreathing();
  850. }
  851. }
  852.  
  853. @Override
  854. public void onLivingUpdate() {
  855. helpers.values().forEach(DragonHelper::onLivingUpdate);
  856. getBreed().onLivingUpdate(this);
  857.  
  858. if (isServer()) {
  859. final float DUMMY_MOVETIME = 0;
  860. final float DUMMY_MOVESPEED = 0;
  861. animator.setMovement(DUMMY_MOVETIME, DUMMY_MOVESPEED);
  862. float netYawHead = getRotationYawHead() - renderYawOffset;
  863. animator.setLook(netYawHead, rotationPitch);
  864. animator.tickingUpdate();
  865. animator.animate();
  866.  
  867.  
  868. // set home position near owner when tamed
  869. if (isTamed()) {
  870. Entity owner = getOwner();
  871. if (owner != null) {
  872. setHomePosAndDistance(owner.getPosition(), HOME_RADIUS);
  873. }
  874. }
  875.  
  876. // delay flying state for 10 ticks (0.5s)
  877. if (!onGround) {
  878. inAirTicks++;
  879. } else {
  880. inAirTicks = 0;
  881. }
  882.  
  883. if(this.onGround && !isFlying() && this.getControllingPlayer() == null
  884. && !this.isHatchling() && this.getRNG().nextInt(500) == 1 && !isSitting()) {
  885. this.liftOff();
  886. DMUtils.getLogger().info("tried to liftoff RNG");
  887. }
  888.  
  889. boolean flying = canFly() && inAirTicks > IN_AIR_THRESH;
  890. if ((flying) != isFlying()) {
  891.  
  892. // notify client
  893. setFlying((flying));
  894.  
  895. // clear tasks (needs to be done before switching the navigator!)
  896. getBrain().clearTasks();
  897.  
  898. // update AI follow range (needs to be updated before creating
  899. // new PathNavigate!)
  900. getEntityAttribute(FOLLOW_RANGE).setBaseValue(getDragonSpeed());
  901.  
  902. // update pathfinding method
  903. if (isFlying()) {
  904. navigator = new PathNavigateFlying(this, world);
  905. } else {
  906. navigator = new PathNavigateGround(this, world);
  907. }
  908.  
  909. // tasks need to be updated after switching modes
  910. getBrain().updateAITasks();
  911.  
  912. setSitting(false);
  913.  
  914. }
  915. } else {
  916. animator.tickingUpdate();
  917. }
  918.  
  919. if (ticksSinceLastAttack >= 0) { // used for jaw animation
  920. ++ticksSinceLastAttack;
  921. if (ticksSinceLastAttack > 1000) {
  922. ticksSinceLastAttack = -1; // reset at arbitrary large value
  923. }
  924. }
  925.  
  926. if (hasChestVarChanged && dragonInv != null && !this.isChested()) {
  927. for (int i = ContainerDragon.chestStartIndex; i < 30; i++) {
  928. if (!dragonInv.getStackInSlot(i).isEmpty()) {
  929. if (!world.isRemote) {
  930. this.entityDropItem(dragonInv.getStackInSlot(i), 1);
  931. }
  932. dragonInv.removeStackFromSlot(i);
  933. }
  934. }
  935. hasChestVarChanged = false;
  936. }
  937.  
  938. updateMultipleBoundingBox();
  939. updateShearing();
  940. updateDragonEnderCrystal();
  941. regenerateHealth();
  942. updateForRiding();
  943. ACHOOOOO();
  944.  
  945. super.onLivingUpdate();
  946. }
  947.  
  948. /**
  949. * Called when the mob's health reaches 0.
  950. */
  951. public void onDeath(DamageSource src) {
  952. super.onDeath(src);
  953. if (dragonInv != null && !this.world.isRemote && !isEgg()) {
  954. for (int i = 0; i < dragonInv.getSizeInventory(); ++i) {
  955. ItemStack itemstack = dragonInv.getStackInSlot(i);
  956. if (!itemstack.isEmpty()) {
  957. this.entityDropItem(itemstack, 0.0F);
  958. }
  959. }
  960. }
  961. }
  962.  
  963. /**
  964. * Handles entity death timer, experience orb and particle creation
  965. */
  966. @Override
  967. protected void onDeathUpdate() {
  968. helpers.values().forEach(DragonHelper::onDeathUpdate);
  969.  
  970. // unmount any riding entities
  971. removePassengers();
  972.  
  973. // freeze at place
  974. motionX = motionY = motionZ = 0;
  975. rotationYaw = prevRotationYaw;
  976. rotationYawHead = prevRotationYawHead;
  977.  
  978. if (isEgg()) {
  979. setDead();
  980. } else {
  981. // actually delete entity after the time is up
  982. if (deathTime >= getMaxDeathTime()) {
  983. setDead();
  984. }
  985. }
  986. deathTime++;
  987. }
  988.  
  989. @Override
  990. public void setDead() {
  991. helpers.values().forEach(DragonHelper::onDeath);
  992. super.setDead();
  993. }
  994.  
  995. @Override
  996. public ITextComponent getDisplayName() {
  997. // return custom name if set
  998. // if (hasCustomName()) {
  999. // return getCustomNameTag();
  1000. // }
  1001.  
  1002. // return default breed name otherwise
  1003. String entName = EntityList.getEntityString(this);
  1004. String breedName = getBreed().getSkin().toLowerCase();
  1005. ITextComponent name = new TextComponentTranslation("entity." + entName + "." + breedName + ".name", new Object[0]);;
  1006. return name;
  1007. }
  1008.  
  1009. @Override
  1010. public void Whistle(EntityPlayer player) {
  1011. if(this.isTamed() && this.isTamedFor(player) && !hasControllingPlayer(player)) {
  1012. this.setCircling(true);
  1013. }
  1014.  
  1015. }
  1016.  
  1017. public void boostUp(int durationIn, int amplifierIn) {
  1018. PotionEffect speed = new PotionEffect(MobEffects.SPEED, durationIn, amplifierIn);
  1019. // if(!this.isPotionActive(speed) {
  1020. this.addPotionEffect(speed);
  1021. // }
  1022. }
  1023.  
  1024. public boolean followPlayerFlying(EntityLivingBase entityLivingBase) {
  1025. BlockPos midPoint = entityLivingBase.getPosition();
  1026. double x = midPoint.getX();
  1027. double y = midPoint.getY();
  1028. double z = midPoint.getZ();
  1029. boolean isMoving = entityLivingBase.motionX != 0 && entityLivingBase.motionY != 0 && entityLivingBase.motionZ != 0;
  1030. // if(isMoving) {
  1031. // return circleTarget(midPoint);
  1032. // } else {
  1033. double offset = 16D;
  1034. double leftOrRight = this.getRNG().nextBoolean() && !isMoving ? -offset: offset;
  1035. x = midPoint.getX() + 0.5 - 12;
  1036. y = midPoint.getY() + 0.5 + 20;
  1037. z = midPoint.getZ() + 0.5 - offset;
  1038. return this.getNavigator().tryMoveToXYZ(x, y, z, 1);
  1039. // }
  1040. }
  1041.  
  1042. public boolean circleTarget2(BlockPos target, float height, float radius, float speed, boolean direction, float offset, float moveSpeedMultiplier) {
  1043. int directionInt = direction ? 1 : -1;
  1044. return this.getNavigator().tryMoveToXYZ(
  1045. target.getX() + radius * Math.cos(directionInt * this.ticksExisted * 0.5 * speed / radius + offset),
  1046. DragonMountsConfig.dragonFlightHeight + target.getY(),
  1047. target.getZ() + radius * Math.sin(directionInt * this.ticksExisted * 0.5 * speed / radius + offset),
  1048. speed * moveSpeedMultiplier);
  1049. }
  1050.  
  1051. public boolean circleTarget1(BlockPos midPoint) {
  1052. if(this.getControllingPlayer() != null) {
  1053. return false;
  1054. }
  1055.  
  1056. Vec3d vec1 = this.getPositionVector().subtract(midPoint.getX(), midPoint.getY(), midPoint.getZ());
  1057. Vec3d vec2 = new Vec3d(0,0,1);
  1058.  
  1059. int directionInt = this.getRNG().nextInt(450) == 1 ? 1 : -1;
  1060. double a = Math.acos((vec1.dotProduct(vec2)) / (vec1.lengthVector() * vec2.lengthVector()));
  1061. double r = 50;
  1062. double x = midPoint.getX() + r * Math.cos(directionInt * a * this.ticksExisted * 2.5); // ()
  1063. double y = midPoint.getY() + DragonMountsConfig.dragonFlightHeight;
  1064. double z = midPoint.getZ() + r * Math.sin(directionInt * a * this.ticksExisted * 2.5); //()
  1065.  
  1066.  
  1067. return this.getNavigator().tryMoveToXYZ(x + 0.5, y + 0.5, z + 0.5, 1);
  1068. }
  1069.  
  1070. /**
  1071. * Returns the sound this mob makes while it's alive.
  1072. */
  1073. @Override
  1074. protected SoundEvent getAmbientSound() {
  1075. return getSoundManager().getLivingSound();
  1076. }
  1077.  
  1078. /**
  1079. * Returns the sound this mob makes when it is hurt.
  1080. */
  1081. @Override
  1082. protected SoundEvent getHurtSound(DamageSource src) {
  1083. return getSoundManager().getHurtSound();
  1084. }
  1085.  
  1086. /**
  1087. * Returns the sound this mob makes on death.
  1088. */
  1089. @Override
  1090. protected SoundEvent getDeathSound() {
  1091. return getSoundManager().getDeathSound();
  1092. }
  1093.  
  1094. /**
  1095. * Returns the sound this mob makes on swimming.
  1096. * @TheRPGAdenturer: disabled due to its annoyance while swimming underwater it
  1097. * played too many times
  1098. */
  1099. @Override
  1100. protected SoundEvent getSwimSound() {
  1101. return null;
  1102. }
  1103.  
  1104. /**
  1105. * Plays living's sound at its position
  1106. */
  1107. @Override
  1108. public void playLivingSound() {
  1109. getSoundManager().playLivingSound();
  1110. }
  1111.  
  1112. @Override
  1113. public void playSound(SoundEvent soundIn, float volume, float pitch) {
  1114. getSoundManager().playSound(soundIn, volume, pitch);
  1115. }
  1116.  
  1117. /**
  1118. * Plays step sound at given x, y, z for the entity
  1119. */
  1120. @Override
  1121. protected void playStepSound(BlockPos entityPos, Block block) {
  1122. getSoundManager().playStepSound(entityPos, block);
  1123. }
  1124.  
  1125. /**
  1126. * Returns the volume for the sounds this mob makes.
  1127. */
  1128. @Override
  1129. protected float getSoundVolume() {
  1130. // note: unused, managed in playSound()
  1131. return 1;
  1132. }
  1133.  
  1134. /**
  1135. * Gets the pitch of living sounds in living entities.
  1136. */
  1137. @Override
  1138. protected float getSoundPitch() {
  1139. // note: unused, managed in playSound()
  1140. return 1;
  1141. }
  1142.  
  1143. public void ACHOOOOO() {
  1144. Random rand = new Random();
  1145. if(this.getBreed().getSneezeParticle() != null && rand.nextInt(25) == 1 && !this.isUsingBreathWeapon() && getScale() > getScale() * 0.14 && !isEgg() && this.getAnimator().getSpeed() > 0) {
  1146. double throatPosX = (this.getAnimator().getThroatPosition().x);
  1147. double throatPosY = (this.getAnimator().getThroatPosition().z);
  1148. double throatPosZ = (this.getAnimator().getThroatPosition().y + 1.7);
  1149. world.spawnParticle(this.getBreed().getSneezeParticle(), throatPosX, throatPosY, throatPosZ, 0, 2, 0);
  1150. world.playSound(null, new BlockPos(throatPosX, throatPosY, throatPosZ), ModSounds.DRAGON_SNEEZE, SoundCategory.NEUTRAL, 1, 1);
  1151. }
  1152. }
  1153.  
  1154. public void playSneezeEffect(double throatPosX, double throatPosY, double throatPosZ) {
  1155. world.spawnParticle(this.getBreed().getSneezeParticle(), throatPosX, throatPosY, throatPosZ, 0, 0, 0);
  1156. world.playSound(null, new BlockPos(throatPosX, throatPosY, throatPosZ), ModSounds.DRAGON_SNEEZE, SoundCategory.NEUTRAL, 1, 1);
  1157.  
  1158. }
  1159.  
  1160. /**
  1161. * Get number of ticks, at least during which the living entity will be silent.
  1162. */
  1163. @Override
  1164. public int getTalkInterval() {
  1165. return getSoundManager().getTalkInterval();
  1166. }
  1167.  
  1168. /**
  1169. * Get this Entity's EnumCreatureAttribute
  1170. */
  1171. @Override
  1172. public EnumCreatureAttribute getCreatureAttribute() {
  1173. return getBreed().getCreatureAttribute();
  1174. }
  1175.  
  1176. @Nullable
  1177. public EntityLivingBase getOwner2() {
  1178. for (int i = 0; i < world.playerEntities.size();) {
  1179. EntityPlayer entityplayer = world.playerEntities.get(i);
  1180. return entityplayer;
  1181. }
  1182. return null;
  1183. }
  1184.  
  1185. @Override
  1186. protected float getWaterSlowDown() {
  1187. return 0.8F;
  1188. }
  1189.  
  1190. /**
  1191. * Called when a player interacts with a mob. e.g. gets milk from a cow, gets into the saddle on a pig.
  1192. */
  1193. @Override
  1194. public boolean processInteract(EntityPlayer player, EnumHand hand) {
  1195. ItemStack item = player.getHeldItem(hand);
  1196. // don't interact with eggs!
  1197. if (isEgg()) {
  1198. return !this.canBeLeashedTo(player);
  1199. }
  1200.  
  1201. // baby dragons are tameable now! :D
  1202. if (this.isChild() && !isTamed() && this.isBreedingItem(item)) {
  1203. ItemUtils.consumeEquipped(player, this.getBreed().getBreedingItem());
  1204. tamedFor(player, getRNG().nextInt(5) == 0);
  1205. return true;
  1206. }
  1207.  
  1208. // if (stack.getItem() == ModItems.dragon_stick) {
  1209. // if (player.isSneaking()) {
  1210. // BlockPos pos = new BlockPos(this);
  1211. // this.homePos = pos;
  1212. // this.hasHomePosition = true;
  1213. // player.sendStatusMessage(new TextComponentTranslation("dragon.command.new_home",
  1214. // homePos.getX(), homePos.getY(), homePos.getZ()), true);
  1215. // return true;
  1216. // }
  1217.  
  1218. // inherited interaction
  1219. if (super.processInteract(player, hand)) {
  1220. return true;
  1221. }
  1222.  
  1223. return getInteractHelper().interact(player, item);
  1224. }
  1225.  
  1226. public void tamedFor(EntityPlayer player, boolean successful) {
  1227. if (successful) {
  1228. setTamed(true);
  1229. navigator.clearPathEntity(); // replacement for setPathToEntity(null);
  1230. setAttackTarget(null);
  1231. setOwnerId(player.getUniqueID());
  1232. playTameEffect(true);
  1233. world.setEntityState(this, (byte) 7);
  1234. } else {
  1235. playTameEffect(false);
  1236. world.setEntityState(this, (byte) 6);
  1237. }
  1238. }
  1239.  
  1240. public boolean isTamedFor(EntityPlayer player) {
  1241. return isTamed() && isOwner(player);
  1242. }
  1243.  
  1244. /**
  1245. * Checks if the parameter is an item which this animal can be fed to breed it
  1246. * (wheat, carrots or seeds depending on the animal type)
  1247. */
  1248. @Override
  1249. public boolean isBreedingItem(ItemStack item) {
  1250. return getBreed().getBreedingItem() == item.getItem();
  1251. }
  1252.  
  1253. /**
  1254. * Returns the height of the eyes. Used for looking at other entities.
  1255. */
  1256. @Override
  1257. public float getEyeHeight() {
  1258. float eyeHeight = height * 0.85F;
  1259.  
  1260. if (isSitting()) {
  1261. eyeHeight *= 0.8f;
  1262. }
  1263.  
  1264. if (isEgg()) {
  1265. eyeHeight = 1.3f;
  1266. }
  1267.  
  1268. return eyeHeight;
  1269. }
  1270.  
  1271. /**
  1272. * Returns the height of the eyes. Used for looking at other entities.
  1273. * @TheRPGAdventurer duplicate one for firebreathing
  1274. */
  1275. public float getEyeHeight2() {
  1276. float eyeHeight = 2.75f * 0.85F;
  1277.  
  1278. if (isSitting()) {
  1279. eyeHeight *= 0.8f;
  1280. }
  1281.  
  1282. if (isEgg()) {
  1283. eyeHeight = 1.3f;
  1284. }
  1285.  
  1286. return eyeHeight;
  1287. }
  1288.  
  1289. /**
  1290. * Returns the Y offset from the entity's position for any entity riding this
  1291. * one.
  1292. */
  1293. @Override
  1294. public double getMountedYOffset() {
  1295. return (isSitting() ? 1.7f : 2.0f) * getScale();
  1296. }
  1297.  
  1298. /**
  1299. * Returns render size modifier
  1300. */
  1301. @Override
  1302. public float getRenderSizeModifier() {
  1303. return getScale();
  1304. }
  1305.  
  1306. /**
  1307. * Returns true if this entity should push and be pushed by other entities when
  1308. * colliding.
  1309. */
  1310. @Override
  1311. public boolean canBePushed() {
  1312. return super.canBePushed() && isEgg();
  1313. }
  1314.  
  1315. /**
  1316. * Determines if an entity can be despawned, used on idle far away entities
  1317. */
  1318. @Override
  1319. protected boolean canDespawn() {
  1320. return false;
  1321. }
  1322.  
  1323. /**
  1324. * returns true if this entity is by a ladder, false otherwise
  1325. */
  1326. @Override
  1327. public boolean isOnLadder() {
  1328. // this better doesn't happen...
  1329. return false;
  1330. }
  1331.  
  1332. /**
  1333. * Drop 0-2 items of this living's type.
  1334. *
  1335. * @param par1
  1336. * - Whether this entity has recently been hit by a player.
  1337. * @param par2
  1338. * - Level of Looting used to kill this mob.
  1339. */
  1340. @Override
  1341. protected void dropFewItems(boolean wasRecentlyHit, int lootingModifier) {
  1342. super.dropFewItems(wasRecentlyHit, lootingModifier);
  1343.  
  1344. // drop saddle if equipped
  1345. if (isSaddled()) {
  1346. dropItem(Items.SADDLE, 1);
  1347. }
  1348. }
  1349.  
  1350. /**
  1351. * Called when an entity attacks
  1352. */
  1353. public boolean attackEntityAsMob(Entity entityIn) {
  1354. boolean attacked = entityIn.attackEntityFrom(DamageSource.causeMobDamage(this),
  1355. (float) getEntityAttribute(ATTACK_DAMAGE).getAttributeValue());
  1356.  
  1357. if (attacked) {
  1358. applyEnchantments(this, entityIn);
  1359. }
  1360.  
  1361. if (getBreedType() == EnumDragonBreed.WITHER) {
  1362. ((EntityLivingBase) entityIn).addPotionEffect(new PotionEffect(MobEffects.WITHER, 200));
  1363. }
  1364.  
  1365. return attacked;
  1366.  
  1367. }
  1368.  
  1369. /**
  1370. * Used to get the hand in which to swing and play the hand swinging animation
  1371. * when attacking In this case the dragon's jaw
  1372. *
  1373. */
  1374. @Override
  1375. public void swingArm(EnumHand hand) {
  1376. // play eating sound
  1377. playSound(getSoundManager().getAttackSound(), 1, 0.7f);
  1378.  
  1379. // play attack animation
  1380. if (world instanceof WorldServer) {
  1381. ((WorldServer) world).getEntityTracker().sendToTracking(this, new SPacketAnimation(this, 0));
  1382. }
  1383.  
  1384. ticksSinceLastAttack = 0;
  1385. }
  1386.  
  1387. /**
  1388. * 1 equals iron 2 equals gold 3 equals diamond
  1389. *
  1390. * @return 0 no armor
  1391. */
  1392. public int getArmorResistance() {
  1393. if (getArmor() == 1) {
  1394. return 2;
  1395. }
  1396. if (getArmor() == 2) {
  1397. return 1;
  1398. }
  1399. if (getArmor() == 3) {
  1400. return 3;
  1401. }
  1402. return 0;
  1403. }
  1404.  
  1405. /**
  1406. * Return whether this entity should be rendered as on fire.
  1407. */
  1408. @Override
  1409. public boolean canRenderOnFire() {
  1410. return super.canRenderOnFire() && !getBreed().isImmuneToDamage(DamageSource.IN_FIRE);
  1411. }
  1412.  
  1413. /**
  1414. * Returns true if the mob is currently able to mate with the specified mob.
  1415. */
  1416. @Override
  1417. public boolean canMateWith(EntityAnimal mate) {
  1418. return getReproductionHelper().canMateWith(mate);
  1419. }
  1420.  
  1421. /**
  1422. * This function is used when two same-species animals in 'love mode' breed to
  1423. * generate the new baby animal.
  1424. */
  1425. @Override
  1426. public EntityAgeable createChild(EntityAgeable mate) {
  1427. EntityTameableDragon parent1 = this;
  1428. EntityTameableDragon parent2 = (EntityTameableDragon) mate;
  1429. EntityTameableDragon baby = new EntityTameableDragon(this.world);
  1430.  
  1431. if(parent1.isMale() && !parent2.isMale() || !parent1.isMale() && parent2.isMale()) {
  1432. return getReproductionHelper().createChild(mate);
  1433. } else {
  1434. return null;
  1435. }
  1436. }
  1437.  
  1438. private void addHelper(DragonHelper helper) {
  1439. L.trace("addHelper({})", helper.getClass().getName());
  1440. helpers.put(helper.getClass(), helper);
  1441. }
  1442.  
  1443. private <T extends DragonHelper> T getHelper(Class<T> clazz) {
  1444. return (T) helpers.get(clazz);
  1445. }
  1446.  
  1447. public DragonBreedHelper getBreedHelper() {
  1448. return getHelper(DragonBreedHelper.class);
  1449. }
  1450.  
  1451. public DragonLifeStageHelper getLifeStageHelper() {
  1452. return getHelper(DragonLifeStageHelper.class);
  1453. }
  1454.  
  1455. public DragonReproductionHelper getReproductionHelper() {
  1456. return getHelper(DragonReproductionHelper.class);
  1457. }
  1458.  
  1459. public DragonParticleHelper getParticleHelper() {
  1460. return getHelper(DragonParticleHelper.class);
  1461. }
  1462.  
  1463. public DragonBreathHelper getBreathHelper() {
  1464. return getHelper(DragonBreathHelper.class);
  1465. }
  1466.  
  1467. public DragonAnimator getAnimator() {
  1468. return animator;
  1469. }
  1470.  
  1471. public DragonSoundManager getSoundManager() {
  1472. return getHelper(DragonSoundManager.class);
  1473. }
  1474.  
  1475. public DragonBrain getBrain() {
  1476. return getHelper(DragonBrain.class);
  1477. }
  1478.  
  1479. public DragonInteractHelper getInteractHelper() {
  1480. return getHelper(DragonInteractHelper.class);
  1481. }
  1482.  
  1483. /**
  1484. * Returns the breed for this dragon.
  1485. *
  1486. * @return breed
  1487. */
  1488. public EnumDragonBreed getBreedType() {
  1489. return getBreedHelper().getBreedType();
  1490. }
  1491.  
  1492. /**
  1493. * Sets the new breed for this dragon.
  1494. *
  1495. * @param type
  1496. * new breed
  1497. */
  1498. public void setBreedType(EnumDragonBreed type) {
  1499. getBreedHelper().setBreedType(type);
  1500. }
  1501.  
  1502. public DragonBreed getBreed() {
  1503. return getBreedType().getBreed();
  1504. }
  1505.  
  1506. public double getDragonSpeed() {
  1507. return isFlying() ? BASE_FOLLOW_RANGE_FLYING : BASE_FOLLOW_RANGE;
  1508. }
  1509.  
  1510. @Override
  1511. public boolean canBeSteered() {
  1512. // must always return false or the vanilla movement code interferes
  1513. // with DragonMoveHelper a custom move coe that supports tameable flying entities like a dragonarmor_diamond
  1514. return false;
  1515. }
  1516.  
  1517. @Override
  1518. public void travel(float strafe, float up, float forward) {
  1519. // disable method while flying, the movement is done entirely by
  1520. // moveEntity() and this one just makes the dragon to fall slowly when
  1521. // hovering
  1522. if (!isFlying()) {
  1523. super.travel(strafe, up, forward);
  1524. }
  1525. }
  1526.  
  1527. // @Override
  1528. //public void move(MoverType type, double x, double y, double z) {
  1529. // double d3 = nearGroundOffset;
  1530. // this.isCollidedVertically2 = d3 != y;
  1531. //// this.nearGround = this.isCollidedVertically2 && y > 0;
  1532. // super.move(type, x, y, z);
  1533. // }
  1534.  
  1535. @Nullable
  1536. public Entity getControllingPassenger() {
  1537. return this.getPassengers().isEmpty() ? null : (Entity) getPassengers().get(0);
  1538. }
  1539.  
  1540. @Nullable
  1541. public EntityPlayer getControllingPlayer() {
  1542. Entity entity = this.getPassengers().isEmpty() ? null : (Entity) getPassengers().get(0);
  1543. if (entity instanceof EntityPlayer) {
  1544. return (EntityPlayer) entity;
  1545. } else {
  1546. return null;
  1547. }
  1548. }
  1549.  
  1550. @Nullable
  1551. public Entity getRidingCarriage() {
  1552. List<Entity> entity = this.getPassengers().isEmpty() ? null : this.getPassengers();
  1553. if (entity instanceof EntityCarriage) {
  1554. return (EntityCarriage) entity;
  1555. } else {
  1556. return null;
  1557. }
  1558. }
  1559.  
  1560. public boolean hasControllingPlayer(EntityPlayer player) {
  1561. return this.getControllingPassenger() != null && this.getControllingPassenger() instanceof EntityPlayer && this.getControllingPassenger().getUniqueID().equals(player.getUniqueID());
  1562. }
  1563.  
  1564. public void setRidingPlayer(EntityPlayer player) {
  1565. L.trace("setRidingPlayer({})", player.getName());
  1566. player.rotationYaw = rotationYaw;
  1567. player.rotationPitch = rotationPitch;
  1568. player.startRiding(this);
  1569. }
  1570.  
  1571. @Override
  1572. public void updatePassenger(Entity passenger) {
  1573. if (this.isPassenger(passenger)) {
  1574. double px = posX;
  1575. double py = posY + getMountedYOffset() + passenger.getYOffset();
  1576. double pz = posZ;
  1577.  
  1578. Vec3d pos = new Vec3d(0, 0, 0);
  1579.  
  1580. // dragon position is the middle of the model and the saddle is on
  1581. // the shoulders, so move player forwards on Z axis relative to the
  1582. // dragon's rotation to fix that
  1583. if (passenger == getPassengers().get(0)) {
  1584. pos = new Vec3d(0 * getScale(), 0.2 * getScale(), 1.1 * getScale());
  1585. } else if (passenger == getPassengers().get(1)) {
  1586. pos = new Vec3d(0.3 * getScale(), 0.2 * getScale(), 0.1 * getScale());
  1587. } else if (passenger == getPassengers().get(2)) {
  1588. pos = new Vec3d(-0.3 * getScale(), 0.2 * getScale(), 0.1 * getScale());
  1589. }
  1590.  
  1591. if(!(passenger instanceof EntityPlayer)) {
  1592. passenger.rotationYaw = this.rotationYaw;
  1593. passenger.setRotationYawHead(passenger.getRotationYawHead() + this.rotationYaw);
  1594. this.applyYawToEntity(passenger);
  1595. }
  1596.  
  1597. pos = pos.rotateYaw((float) Math.toRadians(-renderYawOffset)); // oops
  1598. px += pos.x;
  1599. py += pos.y;
  1600. pz += pos.z;
  1601.  
  1602. passenger.setPosition(px, py, pz);
  1603.  
  1604. // fix rider rotation
  1605. if (passenger == getControllingPlayer()) {
  1606. EntityPlayer rider = getControllingPlayer();
  1607. rider.prevRotationPitch = rider.rotationPitch;
  1608. rider.prevRotationYaw = rider.rotationYaw;
  1609. rider.renderYawOffset = renderYawOffset;
  1610. }
  1611. }
  1612. }
  1613.  
  1614. /**
  1615. * Applies this boat's yaw to the given entity. Used to update the orientation of its passenger.
  1616. */
  1617. protected void applyYawToEntity(Entity entityToUpdate) {
  1618. entityToUpdate.setRenderYawOffset(this.rotationYaw);
  1619. float f = MathHelper.wrapDegrees(entityToUpdate.rotationYaw - this.rotationYaw);
  1620. float f1 = MathHelper.clamp(f, -105.0F, 105.0F);
  1621. entityToUpdate.prevRotationYaw += f1 - f;
  1622. entityToUpdate.rotationYaw += f1 - f;
  1623. entityToUpdate.setRotationYawHead(entityToUpdate.rotationYaw);
  1624. }
  1625.  
  1626. @Override
  1627. public boolean isEntityInvulnerable(DamageSource src) {
  1628. Entity srcEnt = src.getImmediateSource();
  1629. if (srcEnt != null) {
  1630. // ignore own damage
  1631. if (srcEnt == this) {
  1632. return true;
  1633. }
  1634.  
  1635. // ignore damage from riders
  1636. if (isPassenger(srcEnt)) {
  1637. return true;
  1638. }
  1639. }
  1640.  
  1641. // don't drown as egg
  1642. if (src == DamageSource.DROWN && isEgg()) {
  1643. return true;
  1644. }
  1645.  
  1646. return getBreed().isImmuneToDamage(src);
  1647. }
  1648.  
  1649. /**
  1650. * Returns the entity's health relative to the maximum health.
  1651. *
  1652. * @return health normalized between 0 and 1
  1653. */
  1654. public double getHealthRelative() {
  1655. return getHealth() / (double) getMaxHealth();
  1656. }
  1657.  
  1658. public int getDeathTime() {
  1659. return deathTime;
  1660. }
  1661.  
  1662. public int getMaxDeathTime() {
  1663. return 120;
  1664. }
  1665.  
  1666. public boolean canBeLeashedTo(EntityPlayer player) {
  1667. return true;
  1668. }
  1669.  
  1670. public void setImmuneToFire(boolean isImmuneToFire) {
  1671. L.trace("setImmuneToFire({})", isImmuneToFire);
  1672. this.isImmuneToFire = isImmuneToFire;
  1673. }
  1674.  
  1675. public void setAttackDamage(double damage) {
  1676. L.trace("setAttackDamage({})", damage);
  1677. getEntityAttribute(ATTACK_DAMAGE).setBaseValue(damage);
  1678. }
  1679.  
  1680. /**
  1681. * Public wrapper for protected final setScale(), used by DragonLifeStageHelper.
  1682. *
  1683. * @param scale
  1684. */
  1685. public void setScalePublic(float scale) {
  1686. double posXTmp = posX;
  1687. double posYTmp = posY;
  1688. double posZTmp = posZ;
  1689. boolean onGroundTmp = onGround;
  1690.  
  1691. setScale(scale);
  1692.  
  1693. // workaround for a vanilla bug; the position is apparently not set correcty
  1694. // after changing the entity size, causing asynchronous server/client
  1695. // positioning
  1696. setPosition(posXTmp, posYTmp, posZTmp);
  1697.  
  1698. // otherwise, setScale stops the dragon from landing while it is growing
  1699. onGround = onGroundTmp;
  1700. }
  1701.  
  1702. /**
  1703. * The age value may be negative or positive or zero. If it's negative, it get's
  1704. * incremented on each tick, if it's positive, it get's decremented each tick.
  1705. * Don't confuse this with EntityLiving.getAge. With a negative value the Entity
  1706. * is considered a child.
  1707. */
  1708. @Override
  1709. public int getGrowingAge() {
  1710. // adapter for vanilla code to enable breeding interaction
  1711. return isAdult() ? 0 : -1;
  1712. }
  1713.  
  1714. /**
  1715. * The age value may be negative or positive or zero. If it's negative, it get's
  1716. * incremented on each tick, if it's positive, it get's decremented each tick.
  1717. * With a negative value the Entity is considered a child.
  1718. */
  1719. @Override
  1720. public void setGrowingAge(int age) {
  1721. // managed by DragonLifeStageHelper, so this is a no-op
  1722. }
  1723.  
  1724. /**
  1725. * Sets the scale for an ageable entity according to the boolean parameter,
  1726. * which says if it's a child.
  1727. */
  1728. @Override
  1729. public void setScaleForAge(boolean child) {
  1730. // managed by DragonLifeStageHelper, so this is a no-op
  1731. }
  1732.  
  1733. @Override
  1734. public boolean shouldDismountInWater(Entity rider) {
  1735. return false;
  1736. }
  1737.  
  1738. /**
  1739. * Returns the size multiplier for the current age.
  1740. *
  1741. * @return scale
  1742. */
  1743. public float getScale() {
  1744. return getLifeStageHelper().getScale();
  1745. }
  1746.  
  1747. public boolean isEgg() {
  1748. return getLifeStageHelper().isEgg();
  1749. }
  1750.  
  1751. public boolean isHatchling() {
  1752. return getLifeStageHelper().isHatchling();
  1753. }
  1754.  
  1755. public boolean isJuvenile() {
  1756. return getLifeStageHelper().isJuvenile();
  1757. }
  1758.  
  1759. public boolean isAdult() {
  1760. return getLifeStageHelper().isAdult();
  1761. }
  1762.  
  1763. @Override
  1764. public boolean isChild() {
  1765. return !isAdult();
  1766. }
  1767.  
  1768. /**
  1769. * Checks if this entity is running on a client.
  1770. *
  1771. * Required since MCP's isClientWorld returns the exact opposite...
  1772. *
  1773. * @return true if the entity runs on a client or false if it runs on a server
  1774. */
  1775. public final boolean isClient() {
  1776. return world.isRemote;
  1777. }
  1778.  
  1779. /**
  1780. * Checks if this entity is running on a server.
  1781. *
  1782. * @return true if the entity runs on a server or false if it runs on a client
  1783. */
  1784. public final boolean isServer() {
  1785. return !world.isRemote;
  1786. }
  1787.  
  1788. @Override
  1789. protected ResourceLocation getLootTable() {
  1790. return getBreed().getLootTable(this);
  1791.  
  1792. }
  1793.  
  1794. public boolean isSheared() {
  1795. return (((Byte) this.dataManager.get(DRAGON_SCALES)).byteValue() & 16) != 0;
  1796. }
  1797.  
  1798. /**
  1799. * make a dragon sheared if set to true
  1800. */
  1801. public void setSheared(boolean sheared) {
  1802. byte b0 = ((Byte) this.dataManager.get(DRAGON_SCALES)).byteValue();
  1803.  
  1804. if (sheared) {
  1805. dataManager.set(DRAGON_SCALES, Byte.valueOf((byte) (b0 | 16)));
  1806. } else {
  1807. dataManager.set(DRAGON_SCALES, Byte.valueOf((byte) (b0 & -17)));
  1808. }
  1809. }
  1810.  
  1811. @Override
  1812. public boolean isShearable(ItemStack item, IBlockAccess world, BlockPos pos) {
  1813. return item != null && item.getItem() == ModTools.diamond_shears && !this.isChild() && !this.isSheared()
  1814. && ticksShear <= 0;
  1815.  
  1816. }
  1817.  
  1818. /**
  1819. * when the dragon rotates its head left-right (yaw), how fast does it move?
  1820. *
  1821. * @return max yaw speed in degrees per tick
  1822. */
  1823. public float getHeadYawSpeed() {
  1824. return this.getControllingPlayer() != null ? 13 : 40;
  1825. }
  1826.  
  1827. /**
  1828. * when the dragon rotates its head up-down (pitch), how fast does it move?
  1829. *
  1830. * @return max pitch speed in degrees per tick
  1831. */
  1832. public float getHeadPitchSpeed() {
  1833. return 50;
  1834. }
  1835.  
  1836. @Override
  1837. public List<ItemStack> onSheared(ItemStack item, net.minecraft.world.IBlockAccess world, BlockPos pos,
  1838. int fortune) {
  1839. this.setSheared(true);
  1840. int i = 1 + this.rand.nextInt(2);
  1841.  
  1842. List<ItemStack> ret = new ArrayList<ItemStack>();
  1843. for (int j = 0; j < i; ++j)
  1844. ret.add(new ItemStack(this.getBreed().getShearDropitem(this)));
  1845.  
  1846.  
  1847. ticksShear = 3600;
  1848. playSound(SoundEvents.ENTITY_ITEM_BREAK, 1.0F, 1.0F);
  1849. playSound(ModSounds.ENTITY_DRAGON_GROWL, 1.0F, 1.0F);
  1850.  
  1851. return ret;
  1852. }
  1853.  
  1854. /**
  1855. * Called when a lightning bolt hits the entity.
  1856. */
  1857. @Override
  1858. public void onStruckByLightning(EntityLightningBolt lightningBolt) {
  1859. EnumDragonBreed currentType = getBreedType();
  1860. super.onStruckByLightning(lightningBolt);
  1861. Random random = new Random();
  1862. if (currentType == EnumDragonBreed.SKELETON) {
  1863. this.setBreedType(EnumDragonBreed.WITHER);
  1864.  
  1865. // if (world.getWorldInfo().isThundering() && currentType == EnumDragonBreed.SKELETON && isSitting()
  1866. // || isEgg()) {
  1867. // world.addWeatherEffect(new EntityLightningBolt(this.world, this.posX, this.posY, this.posZ, true));
  1868. // }
  1869. this.playSound(SoundEvents.BLOCK_PORTAL_TRIGGER, 2, 1);
  1870. this.playSound(SoundEvents.BLOCK_END_PORTAL_SPAWN, 2, 1);
  1871. }
  1872.  
  1873. if (currentType == EnumDragonBreed.SYLPHID) {
  1874. this.setBreedType(EnumDragonBreed.STORM);
  1875.  
  1876. // if (world.getWorldInfo().isThundering() && currentType == EnumDragonBreed.SYLPHID && isSitting()
  1877. // || isEgg()) {
  1878. // world.addWeatherEffect(new EntityLightningBolt(this.world, this.posX, this.posY, this.posZ, true));
  1879. // }
  1880. this.playSound(SoundEvents.BLOCK_PORTAL_TRIGGER, 2, 1);
  1881. this.playSound(SoundEvents.BLOCK_END_PORTAL_SPAWN, 2, 1);
  1882. }
  1883.  
  1884. addPotionEffect(new PotionEffect(MobEffects.STRENGTH, 35 * 20));
  1885. }
  1886.  
  1887. private void regenerateHealth() {
  1888. if (!isEgg() && this.getHealth() < this.getMaxHealth() && this.ticksExisted % 70 == 0 && !isDead) {
  1889. int[] exclude = {0};
  1890. int health = DMUtils.getRandomWithExclusionstatic(new Random(), 3, 5, exclude);
  1891. this.heal(health);
  1892. }
  1893. }
  1894.  
  1895. private void updateShearing() {
  1896. if (ticksShear <= 0) {
  1897. setSheared(false);
  1898. }
  1899. if (ticksShear >= 0) {
  1900. ticksShear--;
  1901. }
  1902. }
  1903.  
  1904. @Override
  1905. public boolean shouldAttackEntity(EntityLivingBase target, EntityLivingBase owner) {
  1906. if (!target.isChild()) {
  1907. if (target instanceof EntityTameable) {
  1908. EntityTameable tamedEntity = (EntityTameable) target;
  1909. if (tamedEntity.isTamed()) {
  1910. return false;
  1911. }
  1912. }
  1913.  
  1914. if (target instanceof EntityPlayer) {
  1915. EntityPlayer playertarget = (EntityPlayer) target;
  1916. if (this.isTamed()) {
  1917. return false;
  1918. }
  1919. }
  1920.  
  1921. if (target.hasCustomName()) {
  1922. return false;
  1923. }
  1924.  
  1925. }
  1926.  
  1927. return super.shouldAttackEntity(target, owner);
  1928. }
  1929.  
  1930. protected boolean canFitPassenger(Entity passenger) {
  1931. return this.getPassengers().size() < 3;
  1932. }
  1933.  
  1934. private void updateForRiding() {
  1935. doBlockCollisions();
  1936. List<Entity> list = this.world.getEntitiesInAABBexcluding(this,
  1937. this.getEntityBoundingBox().grow(0.20000000298023224D, -0.009999999776482582D, 0.20000000298023224D),
  1938. EntitySelectors.getTeamCollisionPredicate(this));
  1939.  
  1940. if (!list.isEmpty() && isSaddled() && isAdult()) {
  1941. boolean flag = !this.world.isRemote;
  1942.  
  1943. for (int j = 0; j < list.size(); ++j) {
  1944. Entity entity = list.get(j);
  1945. if (!entity.isPassenger(this) && !entity.isRiding() && entity instanceof EntityCarriage) {
  1946. if (flag && this.getPassengers().size() < 3 && !entity.isRiding() && (isJuvenile() || isAdult())) {
  1947. entity.startRiding(this);
  1948. } else {
  1949. this.applyEntityCollision(entity);
  1950. }
  1951. }
  1952. }
  1953. }
  1954.  
  1955. if (getControllingPlayer() == null && !isFlying() && isSitting()) {
  1956. removePassengers();
  1957. } else if (!isSaddled()) {
  1958. removePassengers();
  1959. }
  1960. }
  1961.  
  1962. /**
  1963. * Updates the state of the enderdragon's current endercrystal.
  1964. */
  1965. private void updateDragonEnderCrystal() {
  1966. if (!isDead) {
  1967. if (this.healingEnderCrystal != null) {
  1968. if (this.healingEnderCrystal.isDead) {
  1969. this.healingEnderCrystal = null;
  1970. } else if (this.ticksExisted % 10 == 0) {
  1971. if (this.getHealth() < this.getMaxHealth()) {
  1972. this.setHealth(this.getHealth() + 1.0F);
  1973. }
  1974.  
  1975. addPotionEffect(new PotionEffect(MobEffects.STRENGTH, 15 * 20));
  1976. }
  1977. }
  1978.  
  1979. if (this.rand.nextInt(10) == 0) {
  1980. List<EntityEnderCrystal> list = this.world.<EntityEnderCrystal>getEntitiesWithinAABB(
  1981. EntityEnderCrystal.class, this.getEntityBoundingBox().grow(32.0D));
  1982. EntityEnderCrystal entityendercrystal = null;
  1983. double d0 = Double.MAX_VALUE;
  1984.  
  1985. for (EntityEnderCrystal entityendercrystal1 : list) {
  1986. double d1 = entityendercrystal1.getDistanceSqToEntity(this);
  1987.  
  1988. if (d1 < d0) {
  1989. d0 = d1;
  1990. entityendercrystal = entityendercrystal1;
  1991. }
  1992. }
  1993.  
  1994. this.healingEnderCrystal = entityendercrystal;
  1995. }
  1996. }
  1997. }
  1998.  
  1999. /**
  2000. * Credits: AlexThe 666 Ice and Fire
  2001. */
  2002. public int getIntFromArmor(ItemStack stack) {
  2003. if (!stack.isEmpty() && stack.getItem() != null && stack.getItem() == ModArmour.dragonarmor_iron) {
  2004. return 1;
  2005. }
  2006. if (!stack.isEmpty() && stack.getItem() != null && stack.getItem() == ModArmour.dragonarmor_gold) {
  2007. return 2;
  2008. }
  2009. if (!stack.isEmpty() && stack.getItem() != null && stack.getItem() == ModArmour.dragonarmor_diamond) {
  2010. return 3;
  2011. }
  2012.  
  2013. return 0;
  2014. }
  2015.  
  2016. /**
  2017. * Credits: AlexThe 666 Ice and Fire
  2018. */
  2019. public void openGUI(EntityPlayer playerEntity, int guiId) {
  2020. if (!this.world.isRemote && (!this.isPassenger(playerEntity))) {
  2021. playerEntity.openGui(DragonMounts.instance, guiId, this.world, this.getEntityId(), 0, 0);
  2022. }
  2023. }
  2024.  
  2025. /**
  2026. * Credits: AlexThe 666 Ice and Fire
  2027. */
  2028. public boolean replaceItemInInventory(int inventorySlot, @Nullable ItemStack itemStackIn) {
  2029. int j = inventorySlot - 500 + 2;
  2030. if (j >= 0 && j < this.dragonInv.getSizeInventory()) {
  2031. this.dragonInv.setInventorySlotContents(j, itemStackIn);
  2032. return true;
  2033. } else {
  2034. return false;
  2035. }
  2036. }
  2037.  
  2038. @Override
  2039. public <T> T getCapability(net.minecraftforge.common.capabilities.Capability<T> capability,
  2040. net.minecraft.util.EnumFacing facing) {
  2041. if (capability == net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
  2042. return (T) itemHandler;
  2043. return super.getCapability(capability, facing);
  2044. }
  2045.  
  2046. @Override
  2047. public boolean hasCapability(net.minecraftforge.common.capabilities.Capability<?> capability,
  2048. net.minecraft.util.EnumFacing facing) {
  2049. return capability == net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY
  2050. || super.hasCapability(capability, facing);
  2051. }
  2052.  
  2053. /**
  2054. * Credits: AlexThe 666 Ice and Fire
  2055. */
  2056. private void InitializeDragonInventory() {
  2057. int numberOfInventoryforChest = 27;
  2058. int numberOfPlayerArmor = 5;
  2059. DragonInventory dragonInv = this.dragonInv;
  2060. this.dragonInv = new DragonInventory("dragonInv", 6 + numberOfInventoryforChest + 6 + numberOfPlayerArmor, this);
  2061. this.dragonInv.setCustomName(this.getName());
  2062. if (dragonInv != null) {
  2063. int i = Math.min(dragonInv.getSizeInventory(), this.dragonInv.getSizeInventory());
  2064. for (int j = 0; j < i; ++j) {
  2065. ItemStack itemstack = dragonInv.getStackInSlot(j);
  2066. if (!itemstack.isEmpty()) {
  2067. this.dragonInv.setInventorySlotContents(j, itemstack.copy());
  2068. }
  2069. }
  2070.  
  2071. if (world.isRemote) {
  2072. ItemStack saddle = dragonInv.getStackInSlot(0);
  2073. ItemStack chest_left = dragonInv.getStackInSlot(1);
  2074. ItemStack banner1 = this.dragonInv.getStackInSlot(31);
  2075. ItemStack banner2 = this.dragonInv.getStackInSlot(32);
  2076. ItemStack banner3 = this.dragonInv.getStackInSlot(33);
  2077. ItemStack banner4 = this.dragonInv.getStackInSlot(34);
  2078.  
  2079. DragonMounts.NETWORK_WRAPPER.sendToServer(new MessageDragonInventory(this.getEntityId(), 0,
  2080. saddle != null && saddle.getItem() == Items.SADDLE && !saddle.isEmpty() ? 1 : 0));
  2081.  
  2082. DragonMounts.NETWORK_WRAPPER.sendToServer(new MessageDragonInventory(this.getEntityId(), 1,
  2083. chest_left != null && chest_left.getItem() == Item.getItemFromBlock(Blocks.CHEST)
  2084. && !chest_left.isEmpty() ? 1 : 0));
  2085.  
  2086. DragonMounts.NETWORK_WRAPPER.sendToServer(new MessageDragonInventory(this.getEntityId(), 2,
  2087. this.getIntFromArmor(dragonInv.getStackInSlot(2))));
  2088.  
  2089. DragonMounts.NETWORK_WRAPPER.sendToServer(new MessageDragonInventory(this.getEntityId(), 31,
  2090. banner1 != null && banner1.getItem() == Items.BANNER && !banner1.isEmpty() ? 1 : 0));
  2091.  
  2092. DragonMounts.NETWORK_WRAPPER.sendToServer(new MessageDragonInventory(this.getEntityId(), 32,
  2093. banner2 != null && banner2.getItem() == Items.BANNER && !banner2.isEmpty() ? 1 : 0));
  2094.  
  2095. DragonMounts.NETWORK_WRAPPER.sendToServer(new MessageDragonInventory(this.getEntityId(), 33,
  2096. banner3 != null && banner3.getItem() == Items.BANNER && !banner3.isEmpty() ? 1 : 0));
  2097.  
  2098. DragonMounts.NETWORK_WRAPPER.sendToServer(new MessageDragonInventory(this.getEntityId(), 34,
  2099. banner4 != null && banner4.getItem() == Items.BANNER && !banner4.isEmpty() ? 1 : 0));
  2100.  
  2101. }
  2102. }
  2103. }
  2104.  
  2105. /**
  2106. * Credits: AlexThe 666 Ice and Fire
  2107. */
  2108. public void readDragonInventory(NBTTagCompound nbt) {
  2109. if (dragonInv != null) {
  2110. NBTTagList nbttaglist = nbt.getTagList("Items", 10);
  2111. InitializeDragonInventory();
  2112. for (int i = 0; i < nbttaglist.tagCount(); ++i) {
  2113. NBTTagCompound nbttagcompound = nbttaglist.getCompoundTagAt(i);
  2114. int j = nbttagcompound.getByte("Slot") & 255;
  2115. this.dragonInv.setInventorySlotContents(j, new ItemStack(nbttagcompound));
  2116. }
  2117. } else {
  2118. NBTTagList nbttaglist = nbt.getTagList("Items", 10);
  2119. InitializeDragonInventory();
  2120. for (int i = 0; i < nbttaglist.tagCount(); ++i) {
  2121. NBTTagCompound nbttagcompound = nbttaglist.getCompoundTagAt(i);
  2122. int j = nbttagcompound.getByte("Slot") & 255;
  2123. this.InitializeDragonInventory();
  2124. this.dragonInv.setInventorySlotContents(j, new ItemStack(nbttagcompound));
  2125.  
  2126. ItemStack saddle = dragonInv.getStackInSlot(0);
  2127. ItemStack chest = dragonInv.getStackInSlot(1);
  2128. ItemStack banner1 = dragonInv.getStackInSlot(31);
  2129. ItemStack banner2 = dragonInv.getStackInSlot(32);
  2130. ItemStack banner3 = dragonInv.getStackInSlot(33);
  2131. ItemStack banner4 = dragonInv.getStackInSlot(34);
  2132.  
  2133. if (world.isRemote) {
  2134. DragonMounts.NETWORK_WRAPPER.sendToServer(new MessageDragonInventory(this.getEntityId(), 0,
  2135. saddle != null && saddle.getItem() == Items.SADDLE && !saddle.isEmpty() ? 1 : 0));
  2136.  
  2137. DragonMounts.NETWORK_WRAPPER.sendToServer(new MessageDragonInventory(this.getEntityId(), 1,
  2138. chest != null && chest.getItem() == Item.getItemFromBlock(Blocks.CHEST) && !chest.isEmpty()
  2139. ? 1 : 0));
  2140.  
  2141. DragonMounts.NETWORK_WRAPPER.sendToServer(new MessageDragonInventory(this.getEntityId(), 2,
  2142. this.getIntFromArmor(dragonInv.getStackInSlot(2))));
  2143.  
  2144. DragonMounts.NETWORK_WRAPPER.sendToServer(new MessageDragonInventory(this.getEntityId(), 31,
  2145. banner1 != null && banner1.getItem() == Items.BANNER && !banner1.isEmpty() ? 1 : 0));
  2146.  
  2147. DragonMounts.NETWORK_WRAPPER.sendToServer(new MessageDragonInventory(this.getEntityId(), 32,
  2148. banner2 != null && banner2.getItem() == Items.BANNER && !banner2.isEmpty() ? 1 : 0));
  2149.  
  2150. DragonMounts.NETWORK_WRAPPER.sendToServer(new MessageDragonInventory(this.getEntityId(), 33,
  2151. banner3 != null && banner3.getItem() == Items.BANNER && !banner3.isEmpty() ? 1 : 0));
  2152.  
  2153. DragonMounts.NETWORK_WRAPPER.sendToServer(new MessageDragonInventory(this.getEntityId(), 34,
  2154. banner4 != null && banner4.getItem() == Items.BANNER && !banner4.isEmpty() ? 1 : 0));
  2155. }
  2156. }
  2157. }
  2158. }
  2159.  
  2160. /**
  2161. * Credits: AlexThe 666 Ice and Fire
  2162. */
  2163. public void refreshInventory() {
  2164. ItemStack saddle = this.dragonInv.getStackInSlot(0);
  2165. ItemStack leftChestforInv = this.dragonInv.getStackInSlot(1);
  2166. ItemStack banner1 = this.dragonInv.getStackInSlot(31);
  2167. ItemStack banner2 = this.dragonInv.getStackInSlot(32);
  2168. ItemStack banner3 = this.dragonInv.getStackInSlot(33);
  2169. ItemStack banner4 = this.dragonInv.getStackInSlot(34);
  2170. this.setSaddled (saddle != null && saddle.getItem() == Items.SADDLE && !saddle.isEmpty());
  2171. this.setChested (leftChestforInv != null && leftChestforInv.getItem() == Item.getItemFromBlock(Blocks.CHEST) && !leftChestforInv.isEmpty());
  2172. this.setBannered1(banner1 != null && banner1.getItem() == Items.BANNER && !banner1.isEmpty());
  2173. this.setBannered2(banner2 != null && banner2.getItem() == Items.BANNER && !banner2.isEmpty());
  2174. this.setBannered3(banner3 != null && banner3.getItem() == Items.BANNER && !banner3.isEmpty());
  2175. this.setBannered4(banner4 != null && banner4.getItem() == Items.BANNER && !banner4.isEmpty());
  2176. this.setArmor(getIntFromArmor(this.dragonInv.getStackInSlot(2)));
  2177.  
  2178. if (this.world.isRemote) {
  2179. DragonMounts.NETWORK_WRAPPER.sendToServer(new MessageDragonInventory(this.getEntityId(), 0,
  2180. saddle != null && saddle.getItem() == Items.SADDLE && !saddle.isEmpty() ? 1 : 0));
  2181. DragonMounts.NETWORK_WRAPPER.sendToServer(new MessageDragonInventory(this.getEntityId(), 1,
  2182. leftChestforInv != null && leftChestforInv.getItem() == Item.getItemFromBlock(Blocks.CHEST)
  2183. && !leftChestforInv.isEmpty() ? 1 : 0));
  2184. DragonMounts.NETWORK_WRAPPER.sendToServer(new MessageDragonInventory(this.getEntityId(), 2,
  2185. this.getIntFromArmor(this.dragonInv.getStackInSlot(2))));
  2186. DragonMounts.NETWORK_WRAPPER.sendToServer(new MessageDragonInventory(this.getEntityId(), 31,
  2187. banner1 != null && banner1.getItem() == Items.BANNER && !banner1.isEmpty() ? 1 : 0));
  2188. DragonMounts.NETWORK_WRAPPER.sendToServer(new MessageDragonInventory(this.getEntityId(), 32,
  2189. banner2 != null && banner2.getItem() == Items.BANNER && !banner2.isEmpty() ? 1 : 0));
  2190. DragonMounts.NETWORK_WRAPPER.sendToServer(new MessageDragonInventory(this.getEntityId(), 31,
  2191. banner3 != null && banner3.getItem() == Items.BANNER && !banner3.isEmpty() ? 1 : 0));
  2192. DragonMounts.NETWORK_WRAPPER.sendToServer(new MessageDragonInventory(this.getEntityId(), 32,
  2193. banner4 != null && banner4.getItem() == Items.BANNER && !banner4.isEmpty() ? 1 : 0));
  2194.  
  2195. }
  2196. }
  2197.  
  2198. /**
  2199. * Credits: AlexThe 666 Ice and Fire
  2200. */
  2201. public void writeDragonInventory(NBTTagCompound nbt) {
  2202. if (dragonInv != null) {
  2203. NBTTagList nbttaglist = new NBTTagList();
  2204. for (int i = 0; i < this.dragonInv.getSizeInventory(); ++i) {
  2205. ItemStack itemstack = this.dragonInv.getStackInSlot(i);
  2206. if (!itemstack.isEmpty()) {
  2207. NBTTagCompound nbttagcompound = new NBTTagCompound();
  2208. nbttagcompound.setByte("Slot", (byte) i);
  2209. itemstack.writeToNBT(nbttagcompound);
  2210. nbttaglist.appendTag(nbttagcompound);
  2211. }
  2212. }
  2213. nbt.setTag("Items", nbttaglist);
  2214. }
  2215. if (this.getCustomNameTag() != null && !this.getCustomNameTag().isEmpty()) {
  2216. nbt.setString("CustomName", this.getCustomNameTag());
  2217. }
  2218. }
  2219.  
  2220. public void InitializeDragonStats() {
  2221. DragonInventory dragonStats = this.dragonStats;
  2222. this.dragonStats = new DragonInventory("dragonStats", 27 + 6, this);
  2223. if(world.isRemote) {
  2224.  
  2225. }
  2226. }
  2227.  
  2228. public void readDragonStats(NBTTagCompound nbt) {
  2229. if(dragonStats != null) {
  2230. NBTTagList nbttaglist = nbt.getTagList("stones", 10);
  2231. InitializeDragonStats();
  2232. for (int i = 0; i < nbttaglist.tagCount(); ++i) {
  2233. NBTTagCompound nbttagcompound = nbttaglist.getCompoundTagAt(i);
  2234. int j = nbttagcompound.getByte("StoneSlot") & 255;
  2235. this.dragonStats.setInventorySlotContents(j, new ItemStack(nbttagcompound));
  2236. }
  2237. } else {
  2238. NBTTagList nbttaglist = nbt.getTagList("stones", 10);
  2239. InitializeDragonStats();
  2240. for (int i = 0; i < nbttaglist.tagCount(); ++i) {
  2241. NBTTagCompound nbttagcompound = nbttaglist.getCompoundTagAt(i);
  2242. int j = nbttagcompound.getByte("StoneSlot") & 255;
  2243. this.InitializeDragonStats();
  2244. this.dragonStats.setInventorySlotContents(j, new ItemStack(nbttagcompound));
  2245. }
  2246. }
  2247. }
  2248.  
  2249. /**
  2250. * Credits: AlexThe 666 Ice and Fire
  2251. */
  2252. public void writeDragonStats(NBTTagCompound nbt) {
  2253. if (dragonStats != null) {
  2254. NBTTagList nbttaglist = new NBTTagList();
  2255. for (int i = 0; i < this.dragonStats.getSizeInventory(); ++i) {
  2256. ItemStack itemstack = this.dragonStats.getStackInSlot(i);
  2257. if (!itemstack.isEmpty()) {
  2258. NBTTagCompound nbttagcompound = new NBTTagCompound();
  2259. nbttagcompound.setByte("StoneSlot", (byte) i);
  2260. itemstack.writeToNBT(nbttagcompound);
  2261. nbttaglist.appendTag(nbttagcompound);
  2262. }
  2263. }
  2264. nbt.setTag("stones", nbttaglist);
  2265. }
  2266. }
  2267.  
  2268. /**
  2269. * Credits: AlexThe 666 Ice and Fire
  2270. */
  2271. public class DragonInventory extends ContainerHorseChest {
  2272.  
  2273. public DragonInventory(String inventoryTitle, int slotCount, EntityTameableDragon dragon) {
  2274. super(inventoryTitle, slotCount);
  2275. this.addInventoryChangeListener(new DragonInventoryListener(dragon));
  2276. }
  2277. }
  2278.  
  2279. public class DragonInventoryListener implements IInventoryChangedListener {
  2280.  
  2281. EntityTameableDragon dragon;
  2282.  
  2283. public DragonInventoryListener(EntityTameableDragon dragon) {
  2284. this.dragon = dragon;
  2285. }
  2286.  
  2287. @Override
  2288. public void onInventoryChanged(IInventory invBasic) {
  2289. dragon.refreshInventory();
  2290. }
  2291. }
  2292.  
  2293. @Override
  2294. public World getWorld() {
  2295. return world;
  2296. }
  2297.  
  2298. @Override
  2299. public boolean attackEntityFrom(DamageSource source, float damage) {
  2300. Entity sourceEntity = source.getTrueSource();
  2301. if (this.isBeingRidden() && source.getTrueSource() != null && source.getTrueSource().isPassenger(source.getTrueSource())) {
  2302. return false;
  2303. }
  2304.  
  2305. if(isHatchling() && isJumping) {
  2306. return false;
  2307. }
  2308.  
  2309. if(this.isPassenger(sourceEntity)) {
  2310. return false;
  2311. }
  2312.  
  2313. if (damage >= 25 ) {
  2314. return damage == 15.0f;
  2315. }
  2316.  
  2317. // don't just sit there!
  2318. aiSit.setSitting(false);
  2319.  
  2320. float damageReduction = getArmorResistance() + 3.0F;
  2321. if (getArmorResistance() != 0) {
  2322. damage -= damageReduction;
  2323. }
  2324.  
  2325. return super.attackEntityFrom(source, damage);
  2326. }
  2327.  
  2328. @Override
  2329. public boolean attackEntityFromPart(MultiPartEntityPart dragonPart, DamageSource source, float damage) {
  2330. if (this.isBeingRidden() && source.getTrueSource() != null && source.getTrueSource().isPassenger(source.getTrueSource())) {
  2331. return false;
  2332. }
  2333.  
  2334. return this.attackEntityFrom(source, damage);
  2335. }
  2336.  
  2337. public void updateMultipleBoundingBox() {
  2338. DragonLifeStageHelper stage = getLifeStageHelper();
  2339. double hx, hy, hz;
  2340. float angle;
  2341. DragonHeadPositionHelper pos = getAnimator().getDragonHeadPositionHelper();
  2342. boolean isMoving = this.motionX != 0 && this.motionY != 0 && this.motionZ != 0;
  2343.  
  2344. angle = (((renderYawOffset + 0) * 3.14159265F) / 180F);
  2345. hx = posX - MathHelper.sin(angle) * 3.0 - pos.head.rotateAngleX * getScale();
  2346. double yChange = !isMoving && this.isFlying() ? 2.6 : 3.6 * getScale();
  2347. hy = posY + yChange;
  2348. hz = posZ + MathHelper.cos(angle) * 3.0 + pos.head.rotateAngleZ * getScale();
  2349. dragonPartHead.setPosition(hx, hy, hz);
  2350. dragonPartHead.width = dragonPartHead.height = 1.0F * getScale();
  2351. dragonPartHead.onUpdate();
  2352.  
  2353. dragonPartBody.width = (float) (this.width - 0.3 * getScale());
  2354. dragonPartBody.height = (float) (this.height - 0.3 * getScale());
  2355. dragonPartBody.setPosition(posX, posY, posZ);
  2356. dragonPartBody.onUpdate();
  2357.  
  2358. double tx, ty, tz;
  2359. tx = animator.getTail().rotateAngleX;
  2360. ty = animator.getTail().rotateAngleY;
  2361. tz = animator.getTail().rotateAngleZ;
  2362. dragonPartTail.setPosition(tx, ty, tz);
  2363. dragonPartTail.onUpdate();
  2364.  
  2365. // if (this.isFlying() && isMoving) {
  2366. // this.collideWithEntities(this.world.getEntitiesWithinAABBExcludingEntity(this, this.dragonPartBody.getEntityBoundingBox().grow(4.0D, 2.0D, 4.0D).offset(0.0D, -2.0D, 0.0D)), this.getScale() * 1.2);
  2367. // this.collideWithEntities(this.world.getEntitiesWithinAABBExcludingEntity(this, dragonPartHead.getEntityBoundingBox().grow(4.0D, 2.0D, 4.0D).offset(0.0D, -2.0D, 0.0D))
  2368. // , 4.0D);
  2369. // this.attackEntitiesInList(this.world.getEntitiesWithinAABBExcludingEntity(this, this.getEntityBoundingBox().grow(1.0D)));
  2370. // this.attackEntitiesInList(this.world.getEntitiesWithinAABBExcludingEntity(this, this.dragonPartBody.getEntityBoundingBox().grow(1.0D)));
  2371. /// }
  2372.  
  2373.  
  2374. }
  2375.  
  2376. /**
  2377. * Pushes all entities inside the list away from the enderdragon.
  2378. */
  2379. private void collideWithEntities(List<Entity> p_70970_1_, double strength) {
  2380. double d0 = (this.dragonPartBody.getEntityBoundingBox().minX + this.dragonPartBody.getEntityBoundingBox().maxX) / 2.0D;
  2381. double d1 = (this.dragonPartBody.getEntityBoundingBox().minZ + this.dragonPartBody.getEntityBoundingBox().maxZ) / 2.0D;
  2382.  
  2383. for (Entity entity : p_70970_1_) {
  2384. if (entity instanceof EntityLivingBase && !this.isPassenger(entity)) {
  2385. double d2 = entity.posX - d0;
  2386. double d3 = entity.posZ - d1;
  2387. double d4 = d2 * d2 + d3 * d3;
  2388. entity.addVelocity(d2 / d4 * 4.0D, 0.20000000298023224D, d3 / d4 * strength);
  2389.  
  2390. if (this.isFlying()) {
  2391. entity.attackEntityFrom(DamageSource.causeMobDamage(this), 5.0F);
  2392. this.applyEnchantments(this, entity);
  2393. }
  2394. }
  2395. }
  2396. }
  2397.  
  2398. /**
  2399. * Attacks all entities inside this list, dealing 5 hearts of damage.
  2400. */
  2401. private void attackEntitiesInList(List<Entity> p_70971_1_) {
  2402. for (int i = 0; i < p_70971_1_.size(); ++i) {
  2403. Entity entity = p_70971_1_.get(i);
  2404.  
  2405. if (entity instanceof EntityLivingBase && !this.isPassenger(entity)) {
  2406. entity.attackEntityFrom(DamageSource.causeMobDamage(this), 10.0F);
  2407. this.applyEnchantments(this, entity);
  2408. }
  2409. }
  2410. }
  2411.  
  2412. /**
  2413. * Return the Entity parts making up this Entity (currently only for dragons)
  2414. */
  2415. @Override
  2416. public Entity[] getParts() {
  2417. return dragonPartArray;
  2418. }
  2419.  
  2420. }
Advertisement
Add Comment
Please, Sign In to add comment