PageRenderTime 61ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/src/main/java/appeng/parts/PartPlacement.java

https://gitlab.com/MineYourMind/Applied-Energistics-2
Java | 440 lines | 352 code | 68 blank | 20 comment | 147 complexity | ac9a9cd10f7f565f1ce19132f240a991 MD5 | raw file
  1. /*
  2. * This file is part of Applied Energistics 2.
  3. * Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
  4. *
  5. * Applied Energistics 2 is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Lesser General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * Applied Energistics 2 is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Lesser General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Lesser General Public License
  16. * along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
  17. */
  18. package appeng.parts;
  19. import java.util.LinkedList;
  20. import java.util.List;
  21. import net.minecraft.block.Block;
  22. import net.minecraft.block.Block.SoundType;
  23. import net.minecraft.client.Minecraft;
  24. import net.minecraft.entity.player.EntityPlayer;
  25. import net.minecraft.item.ItemBlock;
  26. import net.minecraft.item.ItemStack;
  27. import net.minecraft.tileentity.TileEntity;
  28. import net.minecraft.util.MovingObjectPosition;
  29. import net.minecraft.util.Vec3;
  30. import net.minecraft.world.World;
  31. import net.minecraftforge.common.MinecraftForge;
  32. import net.minecraftforge.common.util.ForgeDirection;
  33. import net.minecraftforge.event.entity.player.PlayerDestroyItemEvent;
  34. import net.minecraftforge.event.entity.player.PlayerInteractEvent;
  35. import net.minecraftforge.event.entity.player.PlayerInteractEvent.Action;
  36. import cpw.mods.fml.common.eventhandler.SubscribeEvent;
  37. import cpw.mods.fml.common.gameevent.TickEvent;
  38. import appeng.api.AEApi;
  39. import appeng.api.definitions.Items;
  40. import appeng.api.parts.IFacadePart;
  41. import appeng.api.parts.IPartHost;
  42. import appeng.api.parts.IPartItem;
  43. import appeng.api.parts.PartItemStack;
  44. import appeng.api.parts.SelectedPart;
  45. import appeng.api.util.DimensionalCoord;
  46. import appeng.core.AppEng;
  47. import appeng.core.CommonHelper;
  48. import appeng.core.sync.network.NetworkHandler;
  49. import appeng.core.sync.packets.PacketClick;
  50. import appeng.core.sync.packets.PacketPartPlacement;
  51. import appeng.facade.IFacadeItem;
  52. import appeng.integration.IntegrationType;
  53. import appeng.integration.abstraction.IBC;
  54. import appeng.integration.abstraction.IFMP;
  55. import appeng.integration.abstraction.IImmibisMicroblocks;
  56. import appeng.util.LookDirection;
  57. import appeng.util.Platform;
  58. public class PartPlacement
  59. {
  60. private final ThreadLocal<Object> placing = new ThreadLocal<Object>();
  61. private boolean wasCanceled = false;
  62. @SubscribeEvent
  63. public void playerInteract(TickEvent.ClientTickEvent event)
  64. {
  65. this.wasCanceled = false;
  66. }
  67. @SubscribeEvent
  68. public void playerInteract(PlayerInteractEvent event)
  69. {
  70. if ( event.action == Action.RIGHT_CLICK_AIR && event.entityPlayer.worldObj.isRemote )
  71. {
  72. // re-check to see if this event was already channeled, cause these two events are really stupid...
  73. MovingObjectPosition mop = Platform.rayTrace( event.entityPlayer, true, false );
  74. Minecraft mc = Minecraft.getMinecraft();
  75. float f = 1.0F;
  76. double d0 = mc.playerController.getBlockReachDistance();
  77. Vec3 vec3 = mc.renderViewEntity.getPosition( f );
  78. if ( mop != null && mop.hitVec.distanceTo( vec3 ) < d0 )
  79. {
  80. World w = event.entity.worldObj;
  81. TileEntity te = w.getTileEntity( mop.blockX, mop.blockY, mop.blockZ );
  82. if ( te instanceof IPartHost && this.wasCanceled )
  83. event.setCanceled( true );
  84. }
  85. else
  86. {
  87. ItemStack held = event.entityPlayer.getHeldItem();
  88. final Items items = AEApi.instance().items();
  89. final boolean sameAsMemoryCard = items.itemMemoryCard != null && items.itemMemoryCard.sameAsStack( held );
  90. final boolean sameAsColorApp = items.itemColorApplicator != null && items.itemColorApplicator.sameAsStack( held );
  91. final boolean supportedItem = sameAsMemoryCard || sameAsColorApp;
  92. if ( event.entityPlayer.isSneaking() && held != null && supportedItem )
  93. {
  94. NetworkHandler.instance.sendToServer( new PacketClick( event.x, event.y, event.z, event.face, 0, 0, 0 ) );
  95. }
  96. }
  97. }
  98. else if ( event.action == Action.RIGHT_CLICK_BLOCK && event.entityPlayer.worldObj.isRemote )
  99. {
  100. if ( this.placing.get() != null )
  101. return;
  102. this.placing.set( event );
  103. ItemStack held = event.entityPlayer.getHeldItem();
  104. if ( place( held, event.x, event.y, event.z, event.face, event.entityPlayer, event.entityPlayer.worldObj, PlaceType.INTERACT_FIRST_PASS, 0 ) )
  105. {
  106. event.setCanceled( true );
  107. this.wasCanceled = true;
  108. }
  109. this.placing.set( null );
  110. }
  111. }
  112. public enum PlaceType
  113. {
  114. PLACE_ITEM, INTERACT_FIRST_PASS, INTERACT_SECOND_PASS
  115. }
  116. public static boolean place(ItemStack held, int x, int y, int z, int face, EntityPlayer player, World world, PlaceType pass, int depth)
  117. {
  118. if ( depth > 3 )
  119. return false;
  120. ForgeDirection side = ForgeDirection.getOrientation( face );
  121. if ( held != null && Platform.isWrench( player, held, x, y, z ) && player.isSneaking() )
  122. {
  123. if ( !Platform.hasPermissions( new DimensionalCoord( world, x, y, z ), player ) )
  124. return false;
  125. Block block = world.getBlock( x, y, z );
  126. TileEntity tile = world.getTileEntity( x, y, z );
  127. IPartHost host = null;
  128. if ( tile instanceof IPartHost )
  129. host = (IPartHost) tile;
  130. if ( host != null )
  131. {
  132. if ( !world.isRemote )
  133. {
  134. LookDirection dir = Platform.getPlayerRay( player, getEyeOffset( player ) );
  135. MovingObjectPosition mop = block.collisionRayTrace( world, x, y, z, dir.a, dir.b );
  136. if ( mop != null )
  137. {
  138. List<ItemStack> is = new LinkedList<ItemStack>();
  139. SelectedPart sp = selectPart( player, host, mop.hitVec.addVector( -mop.blockX, -mop.blockY, -mop.blockZ ) );
  140. if ( sp.part != null )
  141. {
  142. is.add( sp.part.getItemStack( PartItemStack.Wrench ) );
  143. sp.part.getDrops( is, true );
  144. host.removePart( sp.side, false );
  145. }
  146. if ( sp.facade != null )
  147. {
  148. is.add( sp.facade.getItemStack() );
  149. host.getFacadeContainer().removeFacade( host, sp.side );
  150. Platform.notifyBlocksOfNeighbors( world, x, y, z );
  151. }
  152. if ( host.isEmpty() )
  153. host.cleanup();
  154. if ( !is.isEmpty() )
  155. {
  156. Platform.spawnDrops( world, x, y, z, is );
  157. }
  158. }
  159. }
  160. else
  161. {
  162. player.swingItem();
  163. NetworkHandler.instance.sendToServer( new PacketPartPlacement( x, y, z, face, getEyeOffset( player ) ) );
  164. }
  165. return true;
  166. }
  167. return false;
  168. }
  169. TileEntity tile = world.getTileEntity( x, y, z );
  170. IPartHost host = null;
  171. if ( tile instanceof IPartHost )
  172. host = (IPartHost) tile;
  173. if ( held != null )
  174. {
  175. IFacadePart fp = isFacade( held, side );
  176. if ( fp != null )
  177. {
  178. if ( host != null )
  179. {
  180. if ( !world.isRemote )
  181. {
  182. if ( host.getPart( ForgeDirection.UNKNOWN ) == null )
  183. return false;
  184. if ( host.canAddPart( held, side ) )
  185. {
  186. if ( host.getFacadeContainer().addFacade( fp ) )
  187. {
  188. host.markForUpdate();
  189. if ( !player.capabilities.isCreativeMode )
  190. {
  191. held.stackSize--;
  192. if ( held.stackSize == 0 )
  193. {
  194. player.inventory.mainInventory[player.inventory.currentItem] = null;
  195. MinecraftForge.EVENT_BUS.post( new PlayerDestroyItemEvent( player, held ) );
  196. }
  197. }
  198. return true;
  199. }
  200. }
  201. }
  202. else
  203. {
  204. player.swingItem();
  205. NetworkHandler.instance.sendToServer( new PacketPartPlacement( x, y, z, face, getEyeOffset( player ) ) );
  206. return true;
  207. }
  208. }
  209. return false;
  210. }
  211. }
  212. if ( host == null && tile != null && AppEng.instance.isIntegrationEnabled( IntegrationType.FMP ) )
  213. host = ((IFMP) AppEng.instance.getIntegration( IntegrationType.FMP )).getOrCreateHost( tile );
  214. if ( host == null && tile != null && AppEng.instance.isIntegrationEnabled( IntegrationType.ImmibisMicroblocks ) )
  215. host = ((IImmibisMicroblocks) AppEng.instance.getIntegration( IntegrationType.ImmibisMicroblocks )).getOrCreateHost( player, face, tile );
  216. // if ( held == null )
  217. {
  218. Block block = world.getBlock( x, y, z );
  219. if ( host != null && player.isSneaking() && block != null )
  220. {
  221. LookDirection dir = Platform.getPlayerRay( player, getEyeOffset( player ) );
  222. MovingObjectPosition mop = block.collisionRayTrace( world, x, y, z, dir.a, dir.b );
  223. if ( mop != null )
  224. {
  225. mop.hitVec = mop.hitVec.addVector( -mop.blockX, -mop.blockY, -mop.blockZ );
  226. SelectedPart sPart = selectPart( player, host, mop.hitVec );
  227. if ( sPart != null && sPart.part != null )
  228. if ( sPart.part.onShiftActivate( player, mop.hitVec ) )
  229. {
  230. if ( world.isRemote )
  231. {
  232. NetworkHandler.instance.sendToServer( new PacketPartPlacement( x, y, z, face, getEyeOffset( player ) ) );
  233. }
  234. return true;
  235. }
  236. }
  237. }
  238. }
  239. if ( held == null || !(held.getItem() instanceof IPartItem) )
  240. return false;
  241. int te_x = x;
  242. int te_y = y;
  243. int te_z = z;
  244. if ( host == null && pass == PlaceType.PLACE_ITEM )
  245. {
  246. ItemStack is = AEApi.instance().blocks().blockMultiPart.stack( 1 );
  247. ItemBlock ib = (ItemBlock) is.getItem();
  248. ForgeDirection offset = ForgeDirection.UNKNOWN;
  249. Block blkID = world.getBlock( x, y, z );
  250. if ( blkID != null && !blkID.isReplaceable( world, x, y, z ) )
  251. {
  252. offset = side;
  253. if ( Platform.isServer() )
  254. side = side.getOpposite();
  255. }
  256. te_x = x + offset.offsetX;
  257. te_y = y + offset.offsetY;
  258. te_z = z + offset.offsetZ;
  259. tile = world.getTileEntity( te_x, te_y, te_z );
  260. if ( tile instanceof IPartHost )
  261. host = (IPartHost) tile;
  262. if ( host == null && tile != null && AppEng.instance.isIntegrationEnabled( IntegrationType.FMP ) )
  263. host = ((IFMP) AppEng.instance.getIntegration( IntegrationType.FMP )).getOrCreateHost( tile );
  264. if ( host == null && tile != null && AppEng.instance.isIntegrationEnabled( IntegrationType.ImmibisMicroblocks ) )
  265. host = ((IImmibisMicroblocks) AppEng.instance.getIntegration( IntegrationType.ImmibisMicroblocks )).getOrCreateHost( player, face, tile );
  266. if ( host == null && AEApi.instance().blocks().blockMultiPart.block().canPlaceBlockAt( world, te_x, te_y, te_z )
  267. && ib.placeBlockAt( is, player, world, te_x, te_y, te_z, side.ordinal(), 0.5f, 0.5f, 0.5f, 0 ) )
  268. {
  269. if ( !world.isRemote )
  270. {
  271. tile = world.getTileEntity( te_x, te_y, te_z );
  272. if ( tile instanceof IPartHost )
  273. host = (IPartHost) tile;
  274. pass = PlaceType.INTERACT_SECOND_PASS;
  275. }
  276. else
  277. {
  278. player.swingItem();
  279. NetworkHandler.instance.sendToServer( new PacketPartPlacement( x, y, z, face, getEyeOffset( player ) ) );
  280. return true;
  281. }
  282. }
  283. else if ( host != null && !host.canAddPart( held, side ) )
  284. return false;
  285. }
  286. if ( host == null )
  287. return false;
  288. if ( !host.canAddPart( held, side ) )
  289. {
  290. if ( pass == PlaceType.INTERACT_FIRST_PASS || pass == PlaceType.PLACE_ITEM )
  291. {
  292. te_x = x + side.offsetX;
  293. te_y = y + side.offsetY;
  294. te_z = z + side.offsetZ;
  295. Block blkID = world.getBlock( te_x, te_y, te_z );
  296. tile = world.getTileEntity( te_x, te_y, te_z );
  297. if ( tile != null && AppEng.instance.isIntegrationEnabled( IntegrationType.FMP ) )
  298. host = ((IFMP) AppEng.instance.getIntegration( IntegrationType.FMP )).getOrCreateHost( tile );
  299. if ( (blkID == null || blkID.isReplaceable( world, te_x, te_y, te_z ) || host != null) && side != ForgeDirection.UNKNOWN )
  300. return place( held, te_x, te_y, te_z, side.getOpposite().ordinal(), player, world,
  301. pass == PlaceType.INTERACT_FIRST_PASS ? PlaceType.INTERACT_SECOND_PASS : PlaceType.PLACE_ITEM, depth + 1 );
  302. }
  303. return false;
  304. }
  305. if ( !world.isRemote )
  306. {
  307. Block block = world.getBlock( x, y, z );
  308. LookDirection dir = Platform.getPlayerRay( player, getEyeOffset( player ) );
  309. MovingObjectPosition mop = block.collisionRayTrace( world, x, y, z, dir.a, dir.b );
  310. if ( mop != null )
  311. {
  312. SelectedPart sp = selectPart( player, host, mop.hitVec.addVector( -mop.blockX, -mop.blockY, -mop.blockZ ) );
  313. if ( sp.part != null )
  314. {
  315. if ( !player.isSneaking() && sp.part.onActivate( player, mop.hitVec ) )
  316. return false;
  317. }
  318. }
  319. DimensionalCoord dc = host.getLocation();
  320. if ( !Platform.hasPermissions( dc, player ) )
  321. return false;
  322. ForgeDirection mySide = host.addPart( held, side, player );
  323. if ( mySide != null )
  324. {
  325. SoundType ss = AEApi.instance().blocks().blockMultiPart.block().stepSound;
  326. // ss.getPlaceSound()
  327. world.playSoundEffect( 0.5 + x, 0.5 + y, 0.5 + z, ss.func_150496_b(), (ss.getVolume() + 1.0F) / 2.0F, ss.getPitch() * 0.8F );
  328. if ( !player.capabilities.isCreativeMode )
  329. {
  330. held.stackSize--;
  331. if ( held.stackSize == 0 )
  332. {
  333. player.inventory.mainInventory[player.inventory.currentItem] = null;
  334. MinecraftForge.EVENT_BUS.post( new PlayerDestroyItemEvent( player, held ) );
  335. }
  336. }
  337. }
  338. }
  339. else
  340. {
  341. player.swingItem();
  342. NetworkHandler.instance.sendToServer( new PacketPartPlacement( x, y, z, face, getEyeOffset( player ) ) );
  343. }
  344. return true;
  345. }
  346. public static float eyeHeight = 0.0f;
  347. private static float getEyeOffset(EntityPlayer p)
  348. {
  349. if ( p.worldObj.isRemote )
  350. return Platform.getEyeOffset( p );
  351. return eyeHeight;
  352. }
  353. private static SelectedPart selectPart(EntityPlayer player, IPartHost host, Vec3 pos)
  354. {
  355. CommonHelper.proxy.updateRenderMode( player );
  356. SelectedPart sp = host.selectPart( pos );
  357. CommonHelper.proxy.updateRenderMode( null );
  358. return sp;
  359. }
  360. public static IFacadePart isFacade(ItemStack held, ForgeDirection side)
  361. {
  362. if ( held.getItem() instanceof IFacadeItem )
  363. return ((IFacadeItem) held.getItem()).createPartFromItemStack( held, side );
  364. if ( AppEng.instance.isIntegrationEnabled( IntegrationType.BC ) )
  365. {
  366. IBC bc = (IBC) AppEng.instance.getIntegration( IntegrationType.BC );
  367. if ( bc.isFacade( held ) )
  368. return bc.createFacadePart( held, side );
  369. }
  370. return null;
  371. }
  372. }