summaryrefslogblamecommitdiffstats
path: root/src/Entities/Minecart.h
blob: bf3c74da5529008c284f7b7fab67610d915e208f (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12











                                                                    
                     
                              




 
                                
 
                              
 
         
                                 
 
                                                                    

                     

                                                                                     
                                                                        

                                                                                     
                                                                                                   
          
 
                             
                                                                      
                                                                                              
                                                                 

                                                                  
                                                                                         
                                                           
                                                             
 
            
                           
                         

                                        
 


                                                                                                                          
                                                      

                                           

                                                                                                                   
                                                                                      



                                                                                                     
                                                             



                                                                                                                      
                                                                                              
 

                                                                                                       
 

                                                                                                   
                                               

                                                                                                                          
                                                       

                                                                                                   

                                                                                      


                                                         

                                                                                                                       
                                                        
  




 
                                                
 
                                
 
         
                                         
 
                                                                                        
 

                                                                  
 
                             
                                                                                       
                                                                 
 
            
                        
                            
  




 


                                                                                             
 
                                
 
         
                                          
 
                                           





                                   
 
                                                                                    
                                                                                            
 
 
            

                                 
 
                                          
                                                                              


                                              
                                       
                 
                                                   






                                                                          
 
                             

                                                                                       
                                                                 
  




 
                                                   
 
                                
 
         
                                            
 
                                             
 
                             
                                                                                       
                                                                 
                                                                                     

                         




                                                                    

                         

                                                                      
 
          
                             
                        
  



 
 
                                               
 
                                
 
         
                                        
 
                                         
                                                                             
 
          

                                  

                                                                                       
                                                                                                        
  




 
                                                  
 
                                
 
         
                                           
 
                                            
 
          
                                                                                       
  

// Minecart.h

// Declares the cMinecart class representing a minecart in the world





#pragma once

#include "Entity.h"
#include "../World.h"
#include "../UI/WindowOwner.h"





class cMinecart : public cEntity
{
	using Super = cEntity;

  public:
	CLASS_PROTODEF(cMinecart)

	/** Minecart payload, values correspond to packet subtype */
	enum ePayload
	{
		mpNone = 0,  // Empty minecart, ridable by player or mobs
		mpChest = 1,  // Minecart-with-chest, can store a grid of 3 * 8 items
		mpFurnace = 2,  // Minecart-with-furnace, can be powered
		mpTNT = 3,  // Minecart-with-TNT, can be blown up with activator rail
		mpHopper = 5,  // Minecart-with-hopper, can be hopper
		// TODO: Spawner minecarts, (and possibly any block in a minecart with NBT editing)
	};

	// cEntity overrides:
	virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
	virtual void HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
	virtual bool DoTakeDamage(TakeDamageInfo & TDI) override;
	virtual void KilledBy(TakeDamageInfo & a_TDI) override;
	virtual void OnRemoveFromWorld(cWorld & a_World) override;
	virtual void HandleSpeedFromAttachee(float a_Forward, float a_Sideways) override;
	int LastDamage(void) const { return m_LastDamage; }
	ePayload GetPayload(void) const { return m_Payload; }

  protected:
	ePayload m_Payload;
	int m_LastDamage;
	Vector3i m_DetectorRailPosition;
	bool m_bIsOnDetectorRail;

	/** Applies an acceleration to the minecart parallel to a_ForwardDirection but without allowing backward speed. */
	void ApplyAcceleration(Vector3d a_ForwardDirection, double a_Acceleration);

	cMinecart(ePayload a_Payload, Vector3d a_Pos);

	/** Handles physics on normal rails
	For each tick, slow down on flat rails, speed up or slow down on ascending / descending rails (depending on
	direction), and turn on curved rails. */
	void HandleRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::milliseconds a_Dt);

	/** Handles powered rail physics
		Each tick, speed up or slow down cart, depending on metadata of rail (powered or not)
	*/
	void HandlePoweredRailPhysics(NIBBLETYPE a_RailMeta);

	/** Handles detector rail activation
		Activates detector rails when a minecart is on them. Calls HandleRailPhysics() for physics simulations
	*/
	void HandleDetectorRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::milliseconds a_Dt);

	/** Handles activator rails */
	virtual void HandleActivatorRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::milliseconds a_Dt);

	/** Snaps a mincecart to a rail's axis, resetting its speed
		For curved rails, it changes the cart's direction as well as snapping it to axis */
	void SnapToRail(NIBBLETYPE a_RailMeta);
	/** Tests if a solid block is in front of a cart, and stops the cart (and returns true) if so; returns false if no
	 * obstruction */
	bool TestBlockCollision(NIBBLETYPE a_RailMeta);
	/** Tests if there is a block at the specified position which is impassable to minecarts */
	bool IsSolidBlockAtPosition(Vector3i a_Offset);
	/** Tests if a solid block is at a specific offset of the minecart position */
	bool IsSolidBlockAtOffset(int a_XOffset, int a_YOffset, int a_ZOffset);

	bool IsBlockCollisionAtOffset(Vector3i a_Offset);

	/** Tests if this mincecart's bounding box is intersecting another entity's bounding box (collision) and pushes
	 * mincecart away if necessary */
	bool TestEntityCollision(NIBBLETYPE a_RailMeta);
};





class cRideableMinecart final : public cMinecart
{
	using Super = cMinecart;

  public:
	CLASS_PROTODEF(cRideableMinecart)

	cRideableMinecart(Vector3d a_Pos, const cItem & a_Content, int a_ContentHeight);

	const cItem & GetContent(void) const { return m_Content; }
	int GetBlockHeight(void) const { return m_ContentHeight; }

	// cEntity overrides:
	virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override;
	virtual void OnRightClicked(cPlayer & a_Player) override;

  protected:
	cItem m_Content;
	int m_ContentHeight;
};





class cMinecartWithChest final : public cMinecart,
								 public cItemGrid::cListener,
								 public cEntityWindowOwner
{
	using Super = cMinecart;

  public:
	CLASS_PROTODEF(cMinecartWithChest)

	cMinecartWithChest(Vector3d a_Pos);

	enum
	{
		ContentsHeight = 3,
		ContentsWidth = 9,
	};

	const cItem & GetSlot(int a_Idx) const { return m_Contents.GetSlot(a_Idx); }
	void SetSlot(int a_Idx, const cItem & a_Item) { m_Contents.SetSlot(a_Idx, a_Item); }


  protected:
	cItemGrid m_Contents;
	void OpenNewWindow(void);

	// cItemGrid::cListener overrides:
	virtual void OnSlotChanged(cItemGrid * a_Grid, int a_SlotNum) override
	{
		UNUSED(a_SlotNum);
		ASSERT(a_Grid == &m_Contents);
		if (m_World != nullptr)
		{
			if (GetWindow() != nullptr)
			{
				GetWindow()->BroadcastWholeWindow();
			}

			m_World->MarkChunkDirty(GetChunkX(), GetChunkZ());
		}
	}

	// cEntity overrides:
	virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override;
	virtual void OnRemoveFromWorld(cWorld & a_World) override;
	virtual void OnRightClicked(cPlayer & a_Player) override;
};





class cMinecartWithFurnace final : public cMinecart
{
	using Super = cMinecart;

  public:
	CLASS_PROTODEF(cMinecartWithFurnace)

	cMinecartWithFurnace(Vector3d a_Pos);

	// cEntity overrides:
	virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override;
	virtual void OnRightClicked(cPlayer & a_Player) override;
	virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;

	// Set functions.
	void SetIsFueled(bool a_IsFueled, int a_FueledTimeLeft = -1)
	{
		m_IsFueled = a_IsFueled;
		m_FueledTimeLeft = a_FueledTimeLeft;
	}

	// Get functions.
	int GetFueledTimeLeft(void) const { return m_FueledTimeLeft; }
	bool IsFueled(void) const { return m_IsFueled; }

  private:
	int m_FueledTimeLeft;
	bool m_IsFueled;
};





class cMinecartWithTNT final : public cMinecart
{
	using Super = cMinecart;

  public:
	CLASS_PROTODEF(cMinecartWithTNT)

	cMinecartWithTNT(Vector3d a_Pos);
	void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;

  private:
	int m_TNTFuseTicksLeft;
	bool m_isTNTFused = false;

	virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override;
	void HandleActivatorRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::milliseconds a_Dt) override;
};





class cMinecartWithHopper final : public cMinecart
{
	using Super = cMinecart;

  public:
	CLASS_PROTODEF(cMinecartWithHopper)

	cMinecartWithHopper(Vector3d a_Pos);

  private:
	virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override;
};