Advertisement
Guest User

Untitled

a guest
Aug 5th, 2012
129
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 29.99 KB | None | 0 0
  1. package net.minecraft.src.ic2.common;
  2.  
  3. import java.util.List;
  4. import java.util.Random;
  5.  
  6. import net.minecraft.src.AxisAlignedBB;
  7. import net.minecraft.src.Block;
  8. import net.minecraft.src.ChunkCoordinates;
  9. import net.minecraft.src.Container;
  10. import net.minecraft.src.DamageSource;
  11. import net.minecraft.src.Entity;
  12. import net.minecraft.src.EntityItem;
  13. import net.minecraft.src.EntityLiving;
  14. import net.minecraft.src.EntityPlayer;
  15. import net.minecraft.src.InventoryPlayer;
  16. import net.minecraft.src.Item;
  17. import net.minecraft.src.ItemStack;
  18. import net.minecraft.src.Material;
  19. import net.minecraft.src.NBTTagCompound;
  20. import net.minecraft.src.TileEntity;
  21. import net.minecraft.src.World;
  22. import net.minecraft.src.mod_IC2;
  23.  
  24. import net.minecraft.src.ic2.api.*;
  25. import net.minecraft.src.ic2.platform.*;
  26.  
  27. /**
  28. * TE class of Nuclear reactor. Seperated from Generators due to it' complexity.
  29. * does NOT extend TEBaseGenerator, will need seperate Wiring Algorythms
  30. * @author Alblaka
  31. */
  32. public class TileEntityNuclearReactor extends TileEntityMachine implements IEnergySource, IHasGui, IReactor {
  33. public static Random randomizer = new Random();
  34.  
  35. public TileEntityNuclearReactor() {
  36. super(54);
  37.  
  38. updateTicker = randomizer.nextInt(getTickRate());
  39. }
  40.  
  41. @Override
  42. public void onUnloaded() {
  43. if (Platform.isSimulating() && addedToEnergyNet) {
  44. EnergyNet.getForWorld(worldObj).removeTileEntity(this);
  45. addedToEnergyNet = false;
  46. }
  47.  
  48. if (Platform.isRendering()) {
  49. AudioManager.removeSources(this);
  50.  
  51. audioSourceMain = null;
  52. audioSourceGeiger = null;
  53. }
  54.  
  55. super.onUnloaded();
  56. }
  57.  
  58. @Override
  59. public String getInvName() {
  60. return "Nuclear Reactor";
  61. }
  62.  
  63. /**
  64. * EUf Output
  65. * Calculated every tickRate() frames in advance
  66. */
  67. public short output = 0;
  68. /**
  69. * Ticker to reduce CPU-usage.
  70. * Assume'd to be 10;
  71. */
  72. public int updateTicker;
  73. /**
  74. * Heat of the reactor.
  75. * High heat = Bad.
  76. */
  77. public int heat = 0;
  78.  
  79. /**
  80. * Loads heat and output.
  81. */
  82. @Override
  83. public void readFromNBT(NBTTagCompound nbttagcompound)
  84. {
  85. super.readFromNBT(nbttagcompound);
  86.  
  87. try {
  88. heat = nbttagcompound.getInteger("heat");
  89. } catch (Exception e) {
  90. heat = nbttagcompound.getShort("heat");
  91. }
  92.  
  93. output = nbttagcompound.getShort("output");
  94. }
  95.  
  96. /**
  97. * Saves heat and output.
  98. */
  99. @Override
  100. public void writeToNBT(NBTTagCompound nbttagcompound) {
  101. super.writeToNBT(nbttagcompound);
  102.  
  103. nbttagcompound.setInteger("heat", heat);
  104. nbttagcompound.setShort("output", (short)output);
  105. }
  106.  
  107. @Override
  108. public void updateEntity() { // WARNING: only executed server-side, see canUpdate()
  109. super.updateEntity();
  110.  
  111. if (!addedToEnergyNet) {
  112. EnergyNet.getForWorld(worldObj).addTileEntity(this);
  113. addedToEnergyNet = true;
  114. }
  115.  
  116. sendEnergy(output);
  117.  
  118. if (updateTicker++ % getTickRate() != 0) return;
  119.  
  120. if (!worldObj.doChunksNearChunkExist(xCoord, yCoord, zCoord, 2)) {
  121. output = 0;
  122. } else {
  123. dropAllUnfittingStuff(); // Clean up the inventory of the Reactor
  124.  
  125. if (heat > 0) {
  126. heat -= coolReactorFromOutside();
  127.  
  128. if (heat <= 0) {
  129. heat = 0;
  130. } else if (calculateHeatEffects()) { // explosion
  131. return;
  132. }
  133. }
  134.  
  135. output = 0; // Recalculate output
  136.  
  137. processChambers();
  138. //System.out.println("Output: "+output+"EUf / Heat: "+heat);
  139.  
  140. setActive(heat>=1000 || output > 0); // "Displayed" Activity = Either heated or producing
  141.  
  142. onInventoryChanged(); // AS the reactor merely works every 10 frames, this will be fine to be called every time. Ntm inventory WILL change quite every time
  143. }
  144.  
  145. NetworkManager.updateTileEntityField(this, "output");
  146. }
  147.  
  148. /**
  149. * Will eject anything "unfitting" from it's inventory into the world.
  150. * Unfitting: Either out of the reactors chamber (size changed?) or not used by the Reactor at all.
  151. */
  152. public void dropAllUnfittingStuff()
  153. {
  154. int size = getReactorSize();
  155. for (int x = 0; x < 9; x++)
  156. {
  157. for (int y = 0; y < 6; y++)
  158. {
  159. ItemStack stack = getMatrixCoord(x,y);
  160. if (stack == null)
  161. {
  162. continue;
  163. }
  164. if (stack.stackSize <= 0)
  165. {
  166. setMatrixCoord(x,y,null);
  167. continue;
  168. }
  169. if (x >= size || !isUsefulItem(stack))
  170. { // If the item is beyond reactor size || the item is useless
  171. eject(stack);
  172. setMatrixCoord(x,y,null);
  173. //System.out.println("Dropping "+x+"/"+y);
  174. }
  175. }
  176. }
  177. }
  178.  
  179. /**
  180. * Will spawn the given itemstack into the world (if !!Platform.isSimulating()).
  181. * Don't forget to set the previous position of the itemstack to null!
  182. * @param drop The ItemStack meant to be ejected
  183. */
  184. public void eject (ItemStack drop)
  185. {
  186. if (!Platform.isSimulating() || drop==null)
  187. {
  188. return;
  189. }
  190. // Standard Drop-Code, C&P from Block.dropBlockAsItem_do
  191. float f = 0.7F;
  192. double d = (double)(worldObj.rand.nextFloat() * f) + (double)(1.0F - f) * 0.5D;
  193. double d1 = (double)(worldObj.rand.nextFloat() * f) + (double)(1.0F - f) * 0.5D;
  194. double d2 = (double)(worldObj.rand.nextFloat() * f) + (double)(1.0F - f) * 0.5D;
  195. EntityItem entityitem = new EntityItem(worldObj, (double)xCoord + d, (double)yCoord + d1, (double)zCoord + d2, drop);
  196. entityitem.delayBeforeCanPickup = 10;
  197. worldObj.spawnEntityInWorld(entityitem);
  198. return;
  199. }
  200.  
  201. /**
  202. * @return true, if the given ItemStack is used by the Reactor in any Way
  203. */
  204. public static boolean isUsefulItem(ItemStack item) {
  205. if (item == null) return false;
  206.  
  207. int id = item.itemID;
  208.  
  209. if (id == Ic2Items.uraniumCell.itemID ||
  210. id == Ic2Items.coolingCell.itemID ||
  211. id == Ic2Items.integratedReactorPlating.itemID ||
  212. id == Block.ice.blockID ||
  213. id == Item.bucketWater.shiftedIndex ||
  214. id == Item.bucketLava.shiftedIndex ||
  215. id == Item.bucketEmpty.shiftedIndex ||
  216. id == Ic2Items.integratedHeatDisperser.itemID ||
  217. id == Ic2Items.depletedIsotopeCell.itemID ||
  218. id == Ic2Items.reEnrichedUraniumCell.itemID ||
  219. id == Ic2Items.nearDepletedUraniumCell.itemID) {
  220. return true;
  221. }
  222. return false;
  223. }
  224.  
  225. /**
  226. * Will iterize adjacent blocks and search for stuff which can be taken to cool the reactor.
  227. * @return amount of heat reduced;
  228. */
  229. public int coolReactorFromOutside()
  230. {
  231. int cool = 1; // Standard cooling.
  232. int air = 0;
  233. for (int x = xCoord-1; x <= xCoord+1; x++)
  234. {
  235. for (int y = yCoord-1; y <= yCoord+1; y++)
  236. {
  237. for (int z = zCoord-1; z <= zCoord+1; z++)
  238. {
  239. if (worldObj.getBlockId(x, y, z) == Ic2Items.reactorChamber.itemID)
  240. { // Chambers provide increased cooling
  241. cool+=2;
  242. }
  243. if (worldObj.getBlockMaterial(x, y, z)==Material.water)
  244. { // Water cools for 1 point
  245. cool++;
  246. }
  247. if (worldObj.getBlockId(x, y, z)==0)
  248. { // Air cools for 1/4th point
  249. air++;
  250. }
  251. if (worldObj.getBlockId(x, y, z)==Block.fire.blockID)
  252. { // Fire is bad
  253. air-=2;
  254. }
  255. if (worldObj.getBlockMaterial(x, y, z)==Material.lava)
  256. { // Lava disables cooling
  257. cool-=3;
  258. }
  259. }
  260. }
  261. }
  262. cool+=air/4;
  263. if (cool < 0)
  264. {
  265. return 0;
  266. }
  267. //System.out.println("Total Outside-ish cooling: "+cool);
  268. return cool;
  269. }
  270.  
  271. /**
  272. * Calculates the effect of the Reactor's heat
  273. * @return true if the reactor exploded (stops updateTick)
  274. */
  275. @SuppressWarnings("rawtypes")
  276. public boolean calculateHeatEffects()
  277. {
  278. if (heat < 4000 || !Platform.isSimulating() || mod_IC2.explosionPowerReactorMax <= 0.0F)
  279. { // Save CPU, below 4000 nothing will happen, either way - also only apply effects if the config explosion maximum is >0
  280. return false;
  281. }
  282.  
  283. int size = getReactorSize();
  284. int maxHeat = getMaxHeat();
  285.  
  286. float power = ((float)heat)/((float)maxHeat); // Ranges from 0F (cold) to 1F (explodingly hot)
  287.  
  288. if (power >= 1F) {// BoomHeat
  289. explode();
  290. return true;
  291. }
  292. if (power >= 0.85F && worldObj.rand.nextFloat() <= 4*(power-0.7F))
  293. { // Turn material into lava / fire
  294. int[] coord = getRandCoord(2);
  295. if (coord!= null)
  296. {
  297. //System.out.println("Attempting lava on "+coord[0]+"/"+coord[1]+"/"+coord[2]);
  298. int id = worldObj.getBlockId(coord[0], coord[1], coord[2]);
  299. if (id == 0)
  300. {
  301. worldObj.setBlockWithNotify(coord[0], coord[1], coord[2], Block.fire.blockID);
  302. }
  303. else
  304. {
  305. Material mat = Block.blocksList[id].blockMaterial;
  306. if (id != Block.bedrock.blockID)
  307. {
  308. if (mat==Material.rock || mat == Material.iron || mat == Material.lava || mat == Material.ground|| mat == Material.clay)
  309. {
  310. worldObj.setBlockAndMetadataWithNotify(coord[0], coord[1], coord[2], Block.lavaMoving.blockID, 15);
  311. }
  312. else
  313. {
  314. worldObj.setBlockWithNotify(coord[0], coord[1], coord[2], Block.fire.blockID);
  315. }
  316. }
  317. }
  318. }
  319. }
  320. if (power >= 0.7F)
  321. { // Deal damage to nearby players, with chance F
  322. //System.out.println("Burning ent's");
  323. List list1 = worldObj.getEntitiesWithinAABB(EntityLiving.class, AxisAlignedBB.getBoundingBox(xCoord-3, yCoord-3, zCoord-3, xCoord+4, yCoord+4, zCoord+4));
  324. for (int l = 0; l < list1.size(); l++)
  325. {
  326. Entity ent = (Entity) list1.get(l);
  327. ent.attackEntityFrom(IC2DamageSource.radiation, 1); //TODO Add hazmat suits?
  328. }
  329. }
  330. if (power >= 0.5F)
  331. { // Puff water
  332. int[] coord = getRandCoord(2);
  333. if (coord!= null)
  334. {
  335. //System.out.println("Dampening water on "+coord[0]+"/"+coord[1]+"/"+coord[2]);
  336. int id = worldObj.getBlockId(coord[0], coord[1], coord[2]);
  337. if (id > 0 && Block.blocksList[id].blockMaterial==Material.water)
  338. {
  339. worldObj.setBlockWithNotify(coord[0], coord[1], coord[2], 0);
  340. }
  341. }
  342. }
  343. if (power >= 0.4F && worldObj.rand.nextFloat() <= 1.5F*(power-0.4F))
  344. { // Create fire, ignite flameables
  345. int[] coord = getRandCoord(2);
  346. if (coord!= null)
  347. {
  348. //System.out.println("Setting fire on "+coord[0]+"/"+coord[1]+"/"+coord[2]);
  349. int id = worldObj.getBlockId(coord[0], coord[1], coord[2]);
  350. if (id > 0)
  351. {
  352. Material mat = Block.blocksList[id].blockMaterial;
  353. if (mat==Material.wood || mat == Material.leaves || mat == Material.cloth)
  354. {
  355. worldObj.setBlockWithNotify(coord[0], coord[1], coord[2], Block.fire.blockID);
  356. }
  357. }
  358. }
  359. }
  360. return false;
  361. }
  362.  
  363. /**
  364. * Returns a random coordinate set within the specified block radius
  365. * @return int[3] coordinates, or null if invalid radius or the Reactor itself was chooen.
  366. */
  367. public int[] getRandCoord(int radius)
  368. {
  369. if (radius <= 0)
  370. {
  371. return null;
  372. }
  373. int[] c = new int[3];
  374. c[0]=xCoord+worldObj.rand.nextInt(2*radius+1)-radius;
  375. c[1]=yCoord+worldObj.rand.nextInt(2*radius+1)-radius;
  376. c[2]=zCoord+worldObj.rand.nextInt(2*radius+1)-radius;
  377. if (c[0]==xCoord && c[1]==yCoord && c[2]==zCoord)
  378. {
  379. return null;
  380. }
  381. return c;
  382. }
  383.  
  384. /**
  385. * Main calculation method of Nuclear Reactor.
  386. * Accesses the inventory-content and calculates Energy gain, heat production, etc.
  387. */
  388. public void processChambers()
  389. {
  390. int size = getReactorSize();
  391. for (int y = 0; y < 6; y++)
  392. {
  393. for (int x = 0; x < size; x++)
  394. {
  395. processChamber(x,y);
  396. }
  397. }
  398. }
  399.  
  400. /**
  401. * Calculates the Nuclear Reactor'ing of the given slot
  402. * @param x Row
  403. * @param y Column
  404. */
  405. public void processChamber(int x, int y)
  406. {
  407. ////System.out.println("Chamber "+x+"/"+y);
  408. if (getMatrixCoord(x,y)==null)
  409. { // Empty chamber
  410. return;
  411. }
  412. int id = getMatrixCoord(x,y).itemID;
  413. if (id == Ic2Items.coolingCell.itemID)
  414. { // Coolants cool down
  415. if (getMatrixCoord(x,y).getItemDamage()>0)
  416. {
  417. damageReactorItem(getMatrixCoord(x,y), -1);
  418. }
  419. }
  420. if (id == Ic2Items.integratedReactorPlating.itemID)
  421. { // Platings only cool slowly
  422. if (getMatrixCoord(x,y).getItemDamage()>0 && worldObj.rand.nextInt(10)==0)
  423. {
  424. damageReactorItem(getMatrixCoord(x,y), -1);
  425. }
  426. }
  427. if (id == Ic2Items.nearDepletedUraniumCell.itemID ||
  428. id == Ic2Items.depletedIsotopeCell.itemID ||
  429. id == Ic2Items.reEnrichedUraniumCell.itemID)
  430. { // Depleted stuff keeps emitting low heat
  431. heat++;
  432. }
  433. if (id == Item.bucketWater.shiftedIndex)
  434. { // WaterBuckets act as one-time coolers
  435. if (heat > 4000)
  436. {
  437. heat-=250;
  438. getMatrixCoord(x,y).itemID=Item.bucketEmpty.shiftedIndex;
  439. }
  440. }
  441. if (id == Item.bucketLava.shiftedIndex)
  442. { // Lava-Buckets act as suicidal HEATERS
  443. heat+=2000;
  444. getMatrixCoord(x,y).itemID=Item.bucketEmpty.shiftedIndex;
  445. }
  446. if (id == Block.ice.blockID)
  447. { // Ice is a continous cooler
  448. if (heat > 300)
  449. {
  450. heat-=300;
  451. getMatrixCoord(x,y).stackSize--;
  452. if (getMatrixCoord(x,y).stackSize <= 0)
  453. {
  454. setMatrixCoord(x,y,null);
  455. }
  456. }
  457. }
  458. if (id == Ic2Items.integratedHeatDisperser.itemID)
  459. { // Heat Dispersers will attempt to balance surrounding heat levels
  460. disperseHeat(x,y);
  461. }
  462. if (id == Ic2Items.uraniumCell.itemID && produceEnergy())
  463. { // Uranisation, if energy ned
  464. generateEnergy(x,y);
  465. }
  466. }
  467.  
  468. /**
  469. * Sub-Method
  470. * Will attempt to balance the heat of all surroundings
  471. */
  472. public void disperseHeat(int x, int y)
  473. {
  474. switchHeat(x,y,x-1,y);
  475. switchHeat(x,y,x+1,y);
  476. switchHeat(x,y,x,y-1);
  477. switchHeat(x,y,x,y+1);
  478. // Balance up to 25 points between cooler and reactor
  479. int rebalance = ((getMatrixCoord(x,y).getItemDamage()-heat)+1)/2; //+1 to ensure "1 heat" is still transferred
  480. if (rebalance > 0)
  481. { // Cooler sends heat
  482. if (rebalance > 25)
  483. {
  484. rebalance = 25;
  485. }
  486. heat+=rebalance;
  487. damageReactorItem(getMatrixCoord(x,y), -1 * rebalance);
  488. }
  489. else
  490. { // Cooler takes heat
  491. rebalance*=-1;
  492. if (rebalance > 25)
  493. {
  494. rebalance = 25;
  495. }
  496. heat-=rebalance;
  497. damageReactorItem(getMatrixCoord(x,y), rebalance);
  498. }
  499. }
  500.  
  501. /**
  502. * Switches up to 6 points of heat between the two grid-spots, trying to balance both
  503. * Assumes first coordinate to be the cooler, no null-checks
  504. */
  505. public void switchHeat(int x, int y, int x2, int y2)
  506. {
  507. if (getMatrixCoord(x2,y2)==null)
  508. {
  509. return;
  510. }
  511. int id = getMatrixCoord(x2,y2).itemID;
  512. if (id != Ic2Items.coolingCell.itemID && id != Ic2Items.integratedReactorPlating.itemID)
  513. {// Nothing heatable
  514. return;
  515. }
  516. int heat = getMatrixCoord(x,y).getItemDamage();
  517. int heat2 = getMatrixCoord(x2,y2).getItemDamage();
  518. int rebalance = (heat-heat2)/2;
  519. //System.out.println(""+x+"/"+y+" sends "+rebalance+" heat to "+x2+"/"+y2);
  520. if (rebalance > 0)
  521. { // Cooler sends heat
  522. if (rebalance > 6)
  523. {
  524. rebalance = 6;
  525. }
  526. getMatrixCoord(x,y).setItemDamage(heat-rebalance);
  527. if (id == Ic2Items.coolingCell.itemID)
  528. { // Coolant
  529. damageReactorItem(getMatrixCoord(x2,y2), rebalance);
  530. }
  531. else
  532. { // Plating
  533. spreadHeat(x2,y2,rebalance,false);
  534. }
  535. }
  536. else
  537. { // Cooler takes heat
  538. rebalance*=-1;
  539. if (rebalance > 6)
  540. {
  541. rebalance = 6;
  542. }
  543. damageReactorItem(getMatrixCoord(x,y), rebalance);
  544. getMatrixCoord(x2,y2).setItemDamage(heat2-rebalance);
  545. }
  546. }
  547.  
  548. /**
  549. * Generate Energy from a Uran-Cell, while creating heat, etc
  550. * @param x Row
  551. * @param y Column
  552. */
  553. public void generateEnergy(int x, int y)
  554. {
  555. int pulses = 1+isUranium(x+1,y)+isUranium(x-1,y)+isUranium(x,y+1)+isUranium(x,y-1); // Uran produces more energy + heat if clustered
  556. //System.out.println("Generating Energy on "+x+"/"+y+" , "+pulses+" Pulses");
  557. output+= pulses*pulsePower(); // Energy Generation
  558. pulses += enrichDepleted(x+1,y)+enrichDepleted(x-1,y)+enrichDepleted(x,y+1)+enrichDepleted(x,y-1); // Enrich Depleted Isotopes
  559.  
  560. for (; pulses > 0; pulses--) // Heat generation
  561. {
  562. int takers = canTakeHeat(x+1,y,true,true)+canTakeHeat(x-1,y,true,true)+canTakeHeat(x,y+1,true,true)+canTakeHeat(x,y-1,true,true);
  563. int genHeat;
  564. switch (takers)
  565. {
  566. case 2: genHeat = 4; break;
  567. case 3: genHeat = 2; break;
  568. case 4: genHeat = 1; break;
  569. default: genHeat = 10; break;
  570. }
  571. //System.out.println("Heat produced: "+genHeat*takers);
  572. if (takers == 0)
  573. {
  574. heat+=genHeat; // Reactor heats up, bad
  575. }
  576. else
  577. { // Radiate heat to all surroundings.. not-heatables will ignore it
  578. giveHeatTo(x+1,y,genHeat);
  579. giveHeatTo(x-1,y,genHeat);
  580. giveHeatTo(x,y+1,genHeat);
  581. giveHeatTo(x,y-1,genHeat);
  582. }
  583. }
  584. if (getMatrixCoord(x,y).getItemDamage()==9999 && worldObj.rand.nextInt(3)==0)
  585. {
  586. setMatrixCoord(x,y, Ic2Items.nearDepletedUraniumCell.copy());
  587. }
  588. else
  589. {
  590. /*if (getMatrixCoord(x,y).getItemDamage() < 9000){
  591. getMatrixCoord(x,y).setItemDamage(9950);}*/ // Useful for testing stuff at the end
  592. damageReactorItem(getMatrixCoord(x,y), 1); // of the reactor cycle :D
  593. }
  594. }
  595.  
  596. /**
  597. * @return 1 if the given slot is uranium, 0 otherwise
  598. */
  599. public int isUranium(int x, int y)
  600. {
  601. if (getMatrixCoord(x,y)!= null && getMatrixCoord(x,y).itemID == Ic2Items.uraniumCell.itemID)
  602. {
  603. return 1;
  604. }
  605. return 0;
  606. }
  607.  
  608. /**
  609. * Enriches Depleted Isotopes on the given gridspot, if present.
  610. * @return 1 if there was an isotope to enrich, 0 otherwise
  611. */
  612. public int enrichDepleted(int x, int y)
  613. {
  614. if (getMatrixCoord(x,y)==null || getMatrixCoord(x,y).itemID != Ic2Items.depletedIsotopeCell.itemID)
  615. {
  616. return 0;
  617. }
  618. int oneInChance = 8;
  619. if (heat >= 3000)
  620. {
  621. oneInChance=4;
  622. }
  623. if (heat >= 6000)
  624. {
  625. oneInChance=2;
  626. }
  627. if (heat >= 9000)
  628. {
  629. oneInChance=1;
  630. }
  631. if (worldObj.rand.nextInt(oneInChance)!=0)
  632. {
  633. return 1;
  634. }
  635. if (getMatrixCoord(x,y).getItemDamage()<=0)
  636. {
  637. setMatrixCoord(x,y, Ic2Items.reEnrichedUraniumCell.copy());
  638. }
  639. else
  640. {
  641. damageReactorItem(getMatrixCoord(x,y), -2);
  642. }
  643. return 1;
  644. }
  645.  
  646. /**
  647. * @param countPlating Shall Plating be considered a heat-taker, too?
  648. * @param countCooler Same for coolers
  649. * @return 1 if the given slot can take heat, 0 otherwise
  650. */
  651. public int canTakeHeat(int x, int y, boolean countPlating, boolean countCooler)
  652. {
  653. if (getMatrixCoord(x,y)==null)
  654. {
  655. return 0;
  656. }
  657. int id = getMatrixCoord(x,y).itemID;
  658. if (id == Ic2Items.coolingCell.itemID ||
  659. id == Ic2Items.integratedReactorPlating.itemID && countPlating ||
  660. id == Ic2Items.integratedHeatDisperser.itemID && countCooler)
  661. {
  662. return 1;
  663. }
  664. return 0;
  665. }
  666.  
  667. /**
  668. * Distributes heat to the given grid-slot.
  669. * Will do nothing if the given slot can't take heat.
  670. * @param heat Amount of heat
  671. */
  672. public void giveHeatTo(int x, int y, int heat)
  673. {
  674. if (canTakeHeat(x,y,true,true)==0)
  675. { // I wasnt meant to take the heat
  676. return;
  677. }
  678. if (getMatrixCoord(x,y).itemID == Ic2Items.integratedReactorPlating.itemID)
  679. {
  680. spreadHeat(x,y,heat,true);
  681. }
  682. else
  683. {
  684. damageReactorItem(getMatrixCoord(x,y), heat);
  685. }
  686. }
  687.  
  688. /**
  689. * Calculates how to send heat around via a Plating
  690. * Will spread heat to adjacent tiles and store 1 point by itself
  691. * @param heat Amount of heat
  692. * @param primary Used to prevent lockups. Heat send to further Platings get's false
  693. */
  694. public void spreadHeat (int x, int y, int heat, boolean primary)
  695. {
  696. int takers = canTakeHeat(x+1,y,primary,false)+canTakeHeat(x-1,y,primary,false)+canTakeHeat(x,y+1,primary,false)+canTakeHeat(x,y-1,primary,false);
  697. if (takers == 0)
  698. { // Need to take the whole heat by myself
  699. //System.out.println("Plating takes "+heat+" heat by itself.");
  700. damageReactorItem(getMatrixCoord(x,y), heat);
  701. //System.out.println("Taking heat for myself, now on heat "+getMatrixCoord(x,y).getItemDamage());
  702. return;
  703. }
  704. for (;heat%takers!=0 && getMatrixCoord(x,y).getItemDamage()>0;)
  705. { // Get some heat from the plating itself
  706. heat++;
  707. damageReactorItem(getMatrixCoord(x,y), -1);
  708. }
  709. int genHeat = heat/takers;
  710. //System.out.println("Splitting "+heat+" from "+x+"/"+y+" into "+genHeat+" each for "+takers+" sinks.");
  711. heat-=genHeat*takers; // Rest
  712. if (heat > 0)
  713. {
  714. damageReactorItem(getMatrixCoord(x,y), heat);
  715. }
  716. spreadHeatTo(x-1,y,genHeat, primary);
  717. spreadHeatTo(x+1,y,genHeat, primary);
  718. spreadHeatTo(x,y-1,genHeat, primary);
  719. spreadHeatTo(x,y+1,genHeat, primary);
  720. }
  721.  
  722. /**
  723. * Distributes heat to the given grid-slot from a Plating
  724. * Will do nothing if the given slot can't take heat.
  725. * @param heat Amount of heat
  726. * @param toPlatings Spread to platings?
  727. */
  728. public void spreadHeatTo(int x, int y, int heat, boolean toPlatings)
  729. {
  730. if (canTakeHeat(x,y,toPlatings,false)==0)
  731. { // I wasnt meant to take the heat
  732. return;
  733. }
  734. if (getMatrixCoord(x,y).itemID == Ic2Items.integratedReactorPlating.itemID && toPlatings)
  735. {
  736. spreadHeat(x,y,heat,false);
  737. }
  738. else
  739. {
  740.  
  741. damageReactorItem(getMatrixCoord(x,y), heat);
  742. }
  743. }
  744.  
  745. /**
  746. * Checks for redstone input, active Redstone will shutdown the Reactor.
  747. * @return !Redstone
  748. */
  749. public boolean produceEnergy()
  750. {
  751. return !worldObj.isBlockIndirectlyGettingPowered(xCoord, yCoord, zCoord);
  752. }
  753.  
  754. /**
  755. * Returns the correct ItemStack, as if the Array of ItemStacks would be a 2-dimensional Matrix of size 6by9
  756. * @param x Row of ItemStack
  757. * @param y Column of ItemStack
  758. * @return The specified ItemStack
  759. */
  760. public ItemStack getMatrixCoord(int x, int y) {
  761. if (x < 0 || x >= 9 || y < 0 || y >= 6) return null;
  762.  
  763. return super.getStackInSlot(x+y*9);
  764. }
  765.  
  766. /**
  767. * Method to deal damage to items within the reactor
  768. * @param itemStack The ItemStack to be damaged
  769. * @param damage The amount of damage to be dealt, can be negative for cooling
  770. */
  771.  
  772. public void damageReactorItem(ItemStack itemStack, int damage)
  773. {
  774. if(!itemStack.isItemStackDamageable())
  775. {
  776. return;
  777. }
  778. itemStack.setItemDamage(itemStack.getItemDamage() + damage);
  779.  
  780. if (itemStack.getItemDamage() > itemStack.getMaxDamage())
  781. {
  782. itemStack.stackSize--;
  783. if(itemStack.stackSize < 0)
  784. {
  785. itemStack.stackSize = 0;
  786. }
  787. itemStack.setItemDamage(0);
  788. }
  789. }
  790.  
  791. @Override
  792. public ItemStack getStackInSlot(int i) {
  793. int x = i % 9;
  794. int size = getReactorSize();
  795.  
  796. if (x >= size) { // return last valid slot in row
  797. return getMatrixCoord(size-1, i/9);
  798. } else {
  799. return super.getStackInSlot(i);
  800. }
  801. }
  802.  
  803. /**
  804. * Sets the slot specified by the coordinates to the given stack, as if the Array of ItemStacks would be a 2-dimensional Matrix of size 6by9
  805. * @param x Row of ItemStack
  806. * @param y Column of ItemStack
  807. * @param stack The specified ItemStack
  808. */
  809. public void setMatrixCoord(int x, int y, ItemStack stack) {
  810. if (x < 0 || x >= 9 || y < 0 || y >= 6) return;
  811.  
  812. super.setInventorySlotContents(x+y*9, stack);
  813. }
  814.  
  815. @Override
  816. public void setInventorySlotContents(int i, ItemStack itemstack) {
  817. int x = i % 9;
  818. int size = getReactorSize();
  819.  
  820. if (x >= size) { // return last valid slot in row
  821. setMatrixCoord(size-1, i/9, itemstack);
  822. } else {
  823. super.setInventorySlotContents(i, itemstack);
  824. }
  825. }
  826.  
  827. /**
  828. * Returns the "size" of the Reactor Chamber = The number of coloumns the GUI has.
  829. * Determined by 3 + count of adjancent Chamber Blocks
  830. * @return Reactor's Size as int
  831. */
  832. public short getReactorSize() {
  833. if (worldObj == null) return 9;
  834.  
  835. short rows = 3;
  836. for (Direction direction: Direction.values()) {
  837. TileEntity target = direction.applyToTileEntity(this);
  838. if (target instanceof TileEntityReactorChamber) {
  839. rows++;
  840. }
  841. }
  842. return rows;
  843. }
  844.  
  845. /**
  846. * Specifyable TickRate of the reactor
  847. * @return 20
  848. */
  849. public int getTickRate()
  850. {
  851. return 20;
  852. }
  853.  
  854. /**
  855. * Specifyable power generated from each "uranium pulse" in EUf
  856. * @return 10
  857. */
  858. public static int pulsePower()
  859. {
  860. return mod_IC2.energyGeneratorNuclear; // 1 cell == 10 EU per tick * 20 ticks * 10000 life length = 2-10 kk EU
  861. }
  862.  
  863. public boolean isAddedToEnergyNet() {
  864. return addedToEnergyNet;
  865. }
  866.  
  867. @Override
  868. public boolean emitsEnergyTo(TileEntity receiver, Direction direction)
  869. {
  870. return true;
  871. }
  872.  
  873. @Override
  874. public int getMaxEnergyOutput()
  875. {
  876. return 240*pulsePower();
  877. }
  878.  
  879. /**
  880. * Hook for the Energy Net. Provides an amount of power "send".
  881. * @return Return the un-used power
  882. */
  883. public int sendEnergy(int send)
  884. {
  885. send = EnergyNet.getForWorld(worldObj).emitEnergyFrom(this, send);
  886. if (send > 0 && worldObj.getBlockTileEntity(xCoord,yCoord+1,zCoord) instanceof TileEntityReactorChamber)
  887. {
  888. send = ((TileEntityReactorChamber)worldObj.getBlockTileEntity(xCoord,yCoord+1,zCoord)).sendEnergy(send);
  889. }
  890. if (send > 0 && worldObj.getBlockTileEntity(xCoord,yCoord-1,zCoord) instanceof TileEntityReactorChamber)
  891. {
  892. send = ((TileEntityReactorChamber)worldObj.getBlockTileEntity(xCoord,yCoord-1,zCoord)).sendEnergy(send);
  893. }
  894. if (send > 0 && worldObj.getBlockTileEntity(xCoord+1,yCoord,zCoord) instanceof TileEntityReactorChamber)
  895. {
  896. send = ((TileEntityReactorChamber)worldObj.getBlockTileEntity(xCoord+1,yCoord,zCoord)).sendEnergy(send);
  897. }
  898. if (send > 0 && worldObj.getBlockTileEntity(xCoord-1,yCoord,zCoord) instanceof TileEntityReactorChamber)
  899. {
  900. send = ((TileEntityReactorChamber)worldObj.getBlockTileEntity(xCoord-1,yCoord,zCoord)).sendEnergy(send);
  901. }
  902. if (send > 0 && worldObj.getBlockTileEntity(xCoord,yCoord,zCoord+1) instanceof TileEntityReactorChamber)
  903. {
  904. send = ((TileEntityReactorChamber)worldObj.getBlockTileEntity(xCoord,yCoord,zCoord+1)).sendEnergy(send);
  905. }
  906. if (send > 0 && worldObj.getBlockTileEntity(xCoord,yCoord,zCoord-1) instanceof TileEntityReactorChamber)
  907. {
  908. send = ((TileEntityReactorChamber)worldObj.getBlockTileEntity(xCoord,yCoord,zCoord-1)).sendEnergy(send);
  909. }
  910. return send;
  911. }
  912.  
  913. @Override
  914. public ContainerIC2 getGuiContainer(EntityPlayer entityPlayer) {
  915. return new ContainerNuclearReactor(entityPlayer, this);
  916. }
  917.  
  918. @Override
  919. public String getGuiClassName(EntityPlayer entityPlayer) {
  920. return "GuiNuclearReactor";
  921. }
  922.  
  923. @Override
  924. public void onGuiClosed(EntityPlayer entityPlayer) {
  925. }
  926.  
  927. @Override
  928. public void onNetworkUpdate(String field) {
  929. if (field.equals("output")) {
  930. if (output > 0) {
  931. if (lastOutput <= 0) {
  932. if (audioSourceMain == null) audioSourceMain = AudioManager.createSource(this, PositionSpec.Center, "Generators/NuclearReactor/NuclearReactorLoop.ogg", true, false, AudioManager.defaultVolume);
  933. if (audioSourceMain != null) audioSourceMain.play();
  934. }
  935.  
  936. if (output < 40) {
  937. if (lastOutput <= 0 || lastOutput >= 40) {
  938. if (audioSourceGeiger != null) audioSourceGeiger.remove();
  939. audioSourceGeiger = AudioManager.createSource(this, PositionSpec.Center, "Generators/NuclearReactor/GeigerLowEU.ogg", true, false, AudioManager.defaultVolume);
  940. if (audioSourceGeiger != null) audioSourceGeiger.play();
  941. }
  942. } else if (output < 80) {
  943. if (lastOutput < 40 || lastOutput >= 80) {
  944. if (audioSourceGeiger != null) audioSourceGeiger.remove();
  945. audioSourceGeiger = AudioManager.createSource(this, PositionSpec.Center, "Generators/NuclearReactor/GeigerMedEU.ogg", true, false, AudioManager.defaultVolume);
  946. if (audioSourceGeiger != null) audioSourceGeiger.play();
  947. }
  948. } else if (output >= 80) {
  949. if (lastOutput < 80) {
  950. if (audioSourceGeiger != null) audioSourceGeiger.remove();
  951. audioSourceGeiger = AudioManager.createSource(this, PositionSpec.Center, "Generators/NuclearReactor/GeigerHighEU.ogg", true, false, AudioManager.defaultVolume);
  952. if (audioSourceGeiger != null) audioSourceGeiger.play();
  953. }
  954. }
  955.  
  956. } else if (lastOutput > 0) {
  957. if (audioSourceMain != null) audioSourceMain.stop();
  958. if (audioSourceGeiger != null) audioSourceGeiger.stop();
  959. }
  960.  
  961. lastOutput = output;
  962. }
  963.  
  964. super.onNetworkUpdate(field);
  965. }
  966.  
  967. @Override
  968. public float getWrenchDropRate() {
  969. return 0.8f;
  970. }
  971.  
  972. public boolean addedToEnergyNet = false;
  973. public AudioSource audioSourceMain;
  974. public AudioSource audioSourceGeiger;
  975.  
  976. private short lastOutput = 0;
  977.  
  978. // IReactor
  979.  
  980. @Override
  981. public ChunkCoordinates getPosition() {
  982. return new ChunkCoordinates(xCoord, yCoord, zCoord);
  983. }
  984.  
  985. @Override
  986. public World getWorld() {
  987. return worldObj;
  988. }
  989.  
  990. @Override
  991. public int getHeat() {
  992. return heat;
  993. }
  994.  
  995. @Override
  996. public void setHeat(int heat) {
  997. this.heat = heat;
  998. }
  999.  
  1000. @Override
  1001. public int addHeat(int amount) {
  1002. heat += amount;
  1003. return heat;
  1004. }
  1005.  
  1006. @Override
  1007. public ItemStack getItemAt(int x, int y) {
  1008. return getMatrixCoord(x, y);
  1009. }
  1010.  
  1011. @Override
  1012. public void setItemAt(int x, int y, ItemStack item) {
  1013. setMatrixCoord(x, y, item);
  1014. }
  1015.  
  1016. @Override
  1017. public void explode() {
  1018. float boomPower = 10;
  1019.  
  1020. for (int y = 0; y < 6; y++) {
  1021. for (int x = 0; x < getReactorSize(); x++) {
  1022. if (getMatrixCoord(x,y)!=null && getMatrixCoord(x,y).itemID == Ic2Items.uraniumCell.itemID) { // Plating reduces devastion
  1023. boomPower += 3;
  1024. } else if (getMatrixCoord(x,y)!=null && getMatrixCoord(x,y).itemID == Ic2Items.integratedReactorPlating.itemID) { // Plating reduces devastion
  1025. boomPower -= 1;
  1026. }
  1027. }
  1028. }
  1029.  
  1030. if (boomPower > mod_IC2.explosionPowerReactorMax) boomPower = mod_IC2.explosionPowerReactorMax;
  1031.  
  1032. worldObj.setBlockWithNotify(xCoord, yCoord, zCoord, 0);
  1033. ExplosionIC2 explosion = new ExplosionIC2(worldObj, null, xCoord, yCoord, zCoord, boomPower, 0.01F, 1.5F, IC2DamageSource.nuke);
  1034. explosion.doExplosion();
  1035. }
  1036.  
  1037. @Override
  1038. public int getMaxHeat() {
  1039. int maxHeat = 10000;
  1040. maxHeat += 1000*(getReactorSize()-3);
  1041. for (int y = 0; y < 6; y++)
  1042. {
  1043. for (int x = 0; x < getReactorSize(); x++)
  1044. {
  1045. if (getMatrixCoord(x,y)!=null && getMatrixCoord(x,y).itemID == Ic2Items.integratedReactorPlating.itemID)
  1046. { // Additional Plating
  1047. maxHeat+=100;
  1048. }
  1049. }
  1050. }
  1051.  
  1052. return maxHeat;
  1053. }
  1054.  
  1055. @Override
  1056. public int getOutput() {
  1057. return output;
  1058. }
  1059. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement