Advertisement
Guest User

Untitled

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