2011-10-03 11:41:19 -07:00
# include "cPlayer.h"
# include "cServer.h"
2011-12-31 20:55:17 -08:00
# include "cCreativeInventory.h"
# include "cSurvivalInventory.h"
2011-10-03 11:41:19 -07:00
# include "cClientHandle.h"
# include "cWorld.h"
# include "cPickup.h"
# include "cPluginManager.h"
# include "cChunk.h"
# include "cMCLogger.h"
# include "cWindow.h"
# include "cBlockEntity.h"
# include "cGroupManager.h"
# include "cGroup.h"
# include "cChatColor.h"
# include "cItem.h"
# include "cTracer.h"
# include "cRoot.h"
2011-11-01 14:57:08 -07:00
# include "cMakeDir.h"
2011-12-25 20:06:29 -08:00
# include "cTimer.h"
2011-12-26 01:09:47 -08:00
# include "MersenneTwister.h"
2011-10-03 11:41:19 -07:00
# include "packets/cPacket_NamedEntitySpawn.h"
# include "packets/cPacket_EntityLook.h"
# include "packets/cPacket_TeleportEntity.h"
# include "packets/cPacket_RelativeEntityMove.h"
# include "packets/cPacket_RelativeEntityMoveLook.h"
# include "packets/cPacket_UpdateHealth.h"
# include "packets/cPacket_Respawn.h"
# include "packets/cPacket_PlayerPosition.h"
# include "packets/cPacket_DestroyEntity.h"
# include "packets/cPacket_Metadata.h"
# include "packets/cPacket_Chat.h"
2011-11-10 10:28:21 -08:00
# include "packets/cPacket_NewInvalidState.h"
2011-12-25 17:07:35 -08:00
# include "packets/cPacket_PlayerListItem.h"
2011-12-29 05:16:23 -08:00
# include "packets/cPacket_BlockAction.h"
2011-10-03 11:41:19 -07:00
# include "Vector3d.h"
# include "Vector3f.h"
# include "../iniFile/iniFile.h"
2011-10-31 14:30:14 -07:00
# include <json/json.h>
2011-10-03 11:41:19 -07:00
# ifndef _WIN32 // for mkdir
# include <sys/stat.h>
# include <sys/types.h>
2011-10-21 14:25:29 -07:00
# define sprintf_s(dst, size, format, ...) sprintf(dst, format, __VA_ARGS__ )
2011-10-03 11:41:19 -07:00
# endif
2011-11-06 01:23:20 -08:00
# define float2int(x) ((x)<0 ? ((int)(x))-1 : (int)(x))
2011-10-03 11:41:19 -07:00
extern std : : vector < std : : string > StringSplit ( std : : string str , std : : string delim ) ;
CLASS_DEFINITION ( cPlayer , cPawn ) ;
typedef std : : map < std : : string , bool > PermissionMap ;
struct cPlayer : : sPlayerState
{
PermissionMap ResolvedPermissions ;
PermissionMap Permissions ;
cPlayer : : GroupList ResolvedGroups ;
cPlayer : : GroupList Groups ;
std : : string PlayerName ;
2011-11-02 13:19:57 -07:00
std : : string LoadedWorldName ;
2011-10-03 11:41:19 -07:00
} ;
cPlayer : : cPlayer ( cClientHandle * a_Client , const char * a_PlayerName )
2011-12-27 18:10:05 -08:00
: m_GameMode ( 0 )
2011-11-09 14:17:30 -08:00
, m_IP ( " " )
2011-11-01 13:09:13 -07:00
, m_LastBlockActionTime ( 0 )
2011-11-10 08:30:14 -08:00
, m_LastBlockActionCnt ( 0 )
2011-10-03 11:41:19 -07:00
, m_bVisible ( true )
, m_LastGroundHeight ( 0 )
, m_bTouchGround ( false )
, m_Stance ( 0.0 )
, m_Inventory ( 0 )
, m_CurrentWindow ( 0 )
, m_TimeLastPickupCheck ( 0.f )
, m_Color ( ' - ' )
, m_ClientHandle ( a_Client )
, m_pState ( new sPlayerState )
{
m_EntityType = E_PLAYER ;
2011-12-27 18:10:05 -08:00
SetMaxHealth ( 20 ) ;
2011-12-29 07:31:48 -08:00
SetMaxFoodLevel ( 125 ) ;
2011-12-31 20:55:17 -08:00
m_Inventory = new cSurvivalInventory ( this ) ;
m_CreativeInventory = new cCreativeInventory ( this ) ;
2011-12-25 20:06:29 -08:00
cTimer t1 ;
m_LastPlayerListTime = t1 . GetNowTime ( ) ;
2011-10-03 11:41:19 -07:00
m_TimeLastTeleportPacket = cWorld : : GetTime ( ) ;
m_TimeLastPickupCheck = cWorld : : GetTime ( ) ;
2011-11-06 01:23:20 -08:00
2011-10-03 11:41:19 -07:00
m_pState - > PlayerName = a_PlayerName ;
m_bDirtyPosition = true ; // So chunks are streamed to player at spawn
if ( ! LoadFromDisk ( ) )
{
m_Inventory - > Clear ( ) ;
2012-01-01 10:45:28 -08:00
m_CreativeInventory - > Clear ( ) ;
2011-11-01 14:57:08 -07:00
SetPosX ( cRoot : : Get ( ) - > GetDefaultWorld ( ) - > GetSpawnX ( ) ) ;
SetPosY ( cRoot : : Get ( ) - > GetDefaultWorld ( ) - > GetSpawnY ( ) ) ;
SetPosZ ( cRoot : : Get ( ) - > GetDefaultWorld ( ) - > GetSpawnZ ( ) ) ;
2011-10-03 11:41:19 -07:00
}
2011-11-01 14:57:08 -07:00
}
2011-10-03 11:41:19 -07:00
2011-11-01 14:57:08 -07:00
void cPlayer : : Initialize ( cWorld * a_World )
{
cPawn : : Initialize ( a_World ) ;
GetWorld ( ) - > AddPlayer ( this ) ;
2011-10-03 11:41:19 -07:00
}
cPlayer : : ~ cPlayer ( void )
{
SaveToDisk ( ) ;
m_ClientHandle = 0 ;
2011-11-06 01:23:20 -08:00
2011-12-25 06:03:01 -08:00
CloseWindow ( - 1 ) ;
2011-10-03 11:41:19 -07:00
if ( m_Inventory )
{
delete m_Inventory ;
m_Inventory = 0 ;
}
2011-12-31 20:55:17 -08:00
if ( m_CreativeInventory )
{
delete m_CreativeInventory ;
}
2011-10-03 11:41:19 -07:00
delete m_pState ;
2011-11-02 13:19:57 -07:00
GetWorld ( ) - > RemovePlayer ( this ) ; // TODO - Remove from correct world? Or get rid of this?
2011-10-03 11:41:19 -07:00
}
2011-11-01 13:09:13 -07:00
2011-10-03 11:41:19 -07:00
void cPlayer : : SpawnOn ( cClientHandle * a_Target )
{
if ( a_Target = = m_ClientHandle | | ! m_bVisible ) return ;
LOG ( " cPlayer::SpawnOn -> Sending %s to %s " , m_pState - > PlayerName . c_str ( ) , ( a_Target ) ? a_Target - > GetUsername ( ) : " Everybody " ) ;
cPacket_NamedEntitySpawn SpawnPacket ;
SpawnPacket . m_UniqueID = m_UniqueID ;
SpawnPacket . m_PlayerName = m_pState - > PlayerName ;
SpawnPacket . m_PosX = ( int ) ( m_Pos - > x * 32 ) ;
SpawnPacket . m_PosY = ( int ) ( m_Pos - > y * 32 ) ;
SpawnPacket . m_PosZ = ( int ) ( m_Pos - > z * 32 ) ;
SpawnPacket . m_Rotation = ( char ) ( ( m_Rot - > x / 360.f ) * 256 ) ;
SpawnPacket . m_Pitch = ( char ) ( ( m_Rot - > y / 360.f ) * 256 ) ;
SpawnPacket . m_CurrentItem = ( short ) m_Inventory - > GetEquippedItem ( ) . m_ItemID ;
if ( a_Target = = 0 )
{
2011-10-30 17:52:20 -07:00
cChunk * Chunk = GetWorld ( ) - > GetChunk ( m_ChunkX , m_ChunkY , m_ChunkZ ) ;
2011-10-03 11:41:19 -07:00
Chunk - > Broadcast ( SpawnPacket , m_ClientHandle ) ;
}
else
{
a_Target - > Send ( SpawnPacket ) ;
}
}
void cPlayer : : Tick ( float a_Dt )
{
2011-10-30 17:52:20 -07:00
cChunk * InChunk = GetWorld ( ) - > GetChunk ( m_ChunkX , m_ChunkY , m_ChunkZ ) ;
2011-12-24 15:34:30 -08:00
if ( ! InChunk ) return ;
2011-12-27 18:10:05 -08:00
cPawn : : Tick ( a_Dt ) ;
2011-10-03 11:41:19 -07:00
if ( m_bDirtyOrientation & & ! m_bDirtyPosition )
{
cPacket_EntityLook EntityLook ( this ) ;
InChunk - > Broadcast ( EntityLook , m_ClientHandle ) ;
m_bDirtyOrientation = false ;
2011-12-27 18:10:05 -08:00
} else if ( m_bDirtyPosition )
2011-10-03 11:41:19 -07:00
{
cRoot : : Get ( ) - > GetPluginManager ( ) - > CallHook ( cPluginManager : : E_PLUGIN_PLAYER_MOVE , 1 , this ) ;
float DiffX = ( float ) ( GetPosX ( ) - m_LastPosX ) ;
float DiffY = ( float ) ( GetPosY ( ) - m_LastPosY ) ;
float DiffZ = ( float ) ( GetPosZ ( ) - m_LastPosZ ) ;
float SqrDist = DiffX * DiffX + DiffY * DiffY + DiffZ * DiffZ ;
if ( SqrDist > 4 * 4 // 4 blocks is max Relative Move
| | cWorld : : GetTime ( ) - m_TimeLastTeleportPacket > 2 ) // Send an absolute position every 2 seconds
{
//LOG("Teleported %f", sqrtf(SqrDist) );
cPacket_TeleportEntity TeleportEntity ( this ) ;
InChunk - > Broadcast ( TeleportEntity , m_ClientHandle ) ;
m_TimeLastTeleportPacket = cWorld : : GetTime ( ) ;
}
else
{ // Relative move sucks balls! It's always wrong wtf!
if ( m_bDirtyOrientation )
{
cPacket_RelativeEntityMoveLook RelativeEntityMoveLook ;
RelativeEntityMoveLook . m_UniqueID = GetUniqueID ( ) ;
RelativeEntityMoveLook . m_MoveX = ( char ) ( DiffX * 32 ) ;
RelativeEntityMoveLook . m_MoveY = ( char ) ( DiffY * 32 ) ;
RelativeEntityMoveLook . m_MoveZ = ( char ) ( DiffZ * 32 ) ;
RelativeEntityMoveLook . m_Yaw = ( char ) ( ( GetRotation ( ) / 360.f ) * 256 ) ;
RelativeEntityMoveLook . m_Pitch = ( char ) ( ( GetPitch ( ) / 360.f ) * 256 ) ;
InChunk - > Broadcast ( RelativeEntityMoveLook , m_ClientHandle ) ;
}
else
{
cPacket_RelativeEntityMove RelativeEntityMove ;
RelativeEntityMove . m_UniqueID = GetUniqueID ( ) ;
RelativeEntityMove . m_MoveX = ( char ) ( DiffX * 32 ) ;
RelativeEntityMove . m_MoveY = ( char ) ( DiffY * 32 ) ;
RelativeEntityMove . m_MoveZ = ( char ) ( DiffZ * 32 ) ;
InChunk - > Broadcast ( RelativeEntityMove , m_ClientHandle ) ;
}
}
m_LastPosX = GetPosX ( ) ;
m_LastPosY = GetPosY ( ) ;
m_LastPosZ = GetPosZ ( ) ;
m_bDirtyPosition = false ;
m_ClientHandle - > StreamChunks ( ) ;
}
if ( m_Health > 0 ) // make sure player is alive
{
if ( cWorld : : GetTime ( ) - m_TimeLastPickupCheck > 0.5f ) // Each 0.5 second, check for pickups
{
m_TimeLastPickupCheck = cWorld : : GetTime ( ) ;
// and also check if near a pickup
// TODO: Don't only check in current chunks, but also close chunks (chunks within range)
2011-10-30 17:52:20 -07:00
cChunk * Chunk = GetWorld ( ) - > GetChunk ( m_ChunkX , m_ChunkY , m_ChunkZ ) ;
2011-10-03 11:41:19 -07:00
Chunk - > LockEntities ( ) ;
cWorld : : EntityList Entities = Chunk - > GetEntities ( ) ;
for ( cWorld : : EntityList : : iterator itr = Entities . begin ( ) ; itr ! = Entities . end ( ) ; + + itr )
{
if ( ( * itr ) - > GetEntityType ( ) ! = cEntity : : E_PICKUP ) continue ; // Only pickups
float DiffX = ( float ) ( ( * itr ) - > GetPosX ( ) - GetPosX ( ) ) ;
float DiffY = ( float ) ( ( * itr ) - > GetPosY ( ) - GetPosY ( ) ) ;
float DiffZ = ( float ) ( ( * itr ) - > GetPosZ ( ) - GetPosZ ( ) ) ;
float SqrDist = DiffX * DiffX + DiffY * DiffY + DiffZ * DiffZ ;
if ( SqrDist < 1.5f * 1.5f ) // 1.5 block
{
cPickup * Pickup = reinterpret_cast < cPickup * > ( * itr ) ;
Pickup - > CollectedBy ( this ) ;
}
}
Chunk - > UnlockEntities ( ) ;
}
}
2011-12-25 17:07:35 -08:00
2011-12-25 20:06:29 -08:00
cTimer t1 ;
2011-12-27 10:39:06 -08:00
// Send Player List (Once per m_LastPlayerListTime/1000 ms)
if ( m_LastPlayerListTime + cPlayer : : PLAYER_LIST_TIME_MS < = t1 . GetNowTime ( ) ) {
2011-12-25 20:06:29 -08:00
cWorld : : PlayerList PlayerList = cRoot : : Get ( ) - > GetWorld ( ) - > GetAllPlayers ( ) ;
for ( cWorld : : PlayerList : : iterator itr = PlayerList . begin ( ) ; itr ! = PlayerList . end ( ) ; + + itr )
{
if ( ( * itr ) & & ( * itr ) - > GetClientHandle ( ) & & ! ( ( * itr ) - > GetClientHandle ( ) - > IsDestroyed ( ) ) ) {
2011-12-28 07:40:14 -08:00
cPacket_PlayerListItem PlayerListItem ( GetColor ( ) + GetName ( ) , true , GetClientHandle ( ) - > GetPing ( ) ) ;
2011-12-27 10:39:06 -08:00
( * itr ) - > GetClientHandle ( ) - > Send ( PlayerListItem ) ;
2011-12-25 20:06:29 -08:00
}
2011-12-25 17:07:35 -08:00
}
2011-12-25 20:06:29 -08:00
m_LastPlayerListTime = t1 . GetNowTime ( ) ;
2011-12-25 17:07:35 -08:00
}
2011-10-03 11:41:19 -07:00
}
void cPlayer : : SetTouchGround ( bool a_bTouchGround )
{
m_bTouchGround = a_bTouchGround ;
if ( ! m_bTouchGround )
{
2011-10-30 17:52:20 -07:00
cWorld * World = GetWorld ( ) ;
2011-11-06 01:23:20 -08:00
char BlockID = World - > GetBlock ( float2int ( m_Pos - > x ) , float2int ( m_Pos - > y ) , float2int ( m_Pos - > z ) ) ;
2011-10-03 11:41:19 -07:00
if ( BlockID ! = E_BLOCK_AIR )
{
m_bTouchGround = true ;
}
if ( BlockID = = E_BLOCK_WATER | | BlockID = = E_BLOCK_STATIONARY_WATER | | BlockID = = E_BLOCK_LADDER | | BlockID = = E_BLOCK_TORCH )
{
m_LastGroundHeight = ( float ) m_Pos - > y ;
}
}
if ( m_bTouchGround )
{
float Dist = ( float ) ( m_LastGroundHeight - m_Pos - > y ) ;
if ( Dist > 4.f ) // Player dropped
{
int Damage = ( int ) ( Dist - 4.f ) ;
if ( Damage > 0 )
{
TakeDamage ( Damage , 0 ) ;
}
}
m_LastGroundHeight = ( float ) m_Pos - > y ;
}
}
void cPlayer : : Heal ( int a_Health )
{
2011-12-27 18:10:05 -08:00
if ( m_Health < GetMaxHealth ( ) )
2011-10-03 11:41:19 -07:00
{
2011-12-27 18:10:05 -08:00
m_Health = ( short ) MIN ( a_Health + m_Health , GetMaxHealth ( ) ) ;
2011-10-03 11:41:19 -07:00
cPacket_UpdateHealth Health ;
Health . m_Health = m_Health ;
2011-12-29 07:31:48 -08:00
Health . m_Food = GetFood ( ) ;
Health . m_Saturation = GetFoodSaturation ( ) ;
m_ClientHandle - > Send ( Health ) ;
}
}
void cPlayer : : Feed ( short a_Food )
{
if ( m_FoodLevel < GetMaxFoodLevel ( ) )
{
m_FoodLevel = MIN ( a_Food + m_FoodLevel , GetMaxFoodLevel ( ) ) ;
cPacket_UpdateHealth Health ;
Health . m_Health = m_Health ;
Health . m_Food = GetFood ( ) ;
Health . m_Saturation = GetFoodSaturation ( ) ;
2011-10-03 11:41:19 -07:00
m_ClientHandle - > Send ( Health ) ;
}
}
void cPlayer : : TakeDamage ( int a_Damage , cEntity * a_Instigator )
{
2011-11-01 13:26:11 -07:00
if ( ! ( m_GameMode = = 1 ) ) {
2011-10-26 12:13:49 -07:00
cPawn : : TakeDamage ( a_Damage , a_Instigator ) ;
2011-10-03 11:41:19 -07:00
2011-10-26 12:13:49 -07:00
cPacket_UpdateHealth Health ;
Health . m_Health = m_Health ;
2011-12-29 07:31:48 -08:00
Health . m_Food = GetFood ( ) ;
Health . m_Saturation = GetFoodSaturation ( ) ;
2011-12-21 12:42:34 -08:00
//TODO: Causes problems sometimes O.o (E.G. Disconnecting when attacked)
if ( m_ClientHandle ! = 0 )
m_ClientHandle - > Send ( Health ) ;
2011-10-26 12:13:49 -07:00
}
2011-10-03 11:41:19 -07:00
}
void cPlayer : : KilledBy ( cEntity * a_Killer )
{
cPawn : : KilledBy ( a_Killer ) ;
if ( m_Health > 0 ) return ; // not dead yet =]
m_bVisible = false ; // So new clients don't see the player
2011-12-26 01:09:47 -08:00
MTRand r1 ;
2011-10-03 11:41:19 -07:00
// Puke out all the items
cItem * Items = m_Inventory - > GetSlots ( ) ;
for ( unsigned int i = 1 ; i < m_Inventory - > c_NumSlots ; + + i )
{
if ( ! Items [ i ] . IsEmpty ( ) )
{
2011-12-26 01:09:47 -08:00
float SpeedX = ( ( r1 . randInt ( ) % 1000 ) - 500 ) / 100.f ;
float SpeedY = ( ( r1 . randInt ( ) % 1000 ) ) / 100.f ;
float SpeedZ = ( ( r1 . randInt ( ) % 1000 ) - 500 ) / 100.f ;
2011-10-03 11:41:19 -07:00
cPickup * Pickup = new cPickup ( ( int ) ( m_Pos - > x * 32 ) , ( int ) ( m_Pos - > y * 32 ) , ( int ) ( m_Pos - > z * 32 ) , Items [ i ] , SpeedX , SpeedY , SpeedZ ) ;
2011-10-30 17:52:20 -07:00
Pickup - > Initialize ( GetWorld ( ) ) ;
2011-10-03 11:41:19 -07:00
}
Items [ i ] . Empty ( ) ;
}
SaveToDisk ( ) ; // Save it, yeah the world is a tough place !
}
void cPlayer : : Respawn ( )
{
2011-12-27 18:10:05 -08:00
m_Health = GetMaxHealth ( ) ;
2011-10-03 11:41:19 -07:00
2011-10-26 13:52:19 -07:00
// Create Respawn player packet
cPacket_Respawn Packet ;
//Set Gamemode for packet by looking at world's gamemode (Need to check players gamemode.)
2011-11-01 13:09:13 -07:00
//Packet.m_CreativeMode = (char)GetWorld()->GetGameMode();
Packet . m_CreativeMode = ( char ) m_GameMode ; //Set GameMode packet based on Player's GameMode;
2011-12-27 18:10:05 -08:00
//TODO Less hardcoded
Packet . m_World = 0 ;
Packet . m_MapSeed = GetWorld ( ) - > GetWorldSeed ( ) ;
2011-10-26 13:52:19 -07:00
//Send Packet
m_ClientHandle - > Send ( Packet ) ;
2011-12-27 18:10:05 -08:00
//Set non Burning
SetMetaData ( NORMAL ) ;
2011-10-30 17:52:20 -07:00
TeleportTo ( GetWorld ( ) - > GetSpawnX ( ) , GetWorld ( ) - > GetSpawnY ( ) , GetWorld ( ) - > GetSpawnZ ( ) ) ;
2011-12-27 18:10:05 -08:00
2011-10-03 11:41:19 -07:00
SetVisible ( true ) ;
}
double cPlayer : : GetEyeHeight ( )
{
return m_Stance ;
}
Vector3d cPlayer : : GetEyePosition ( )
{
return Vector3d ( m_Pos - > x , m_Stance , m_Pos - > z ) ;
}
void cPlayer : : OpenWindow ( cWindow * a_Window )
{
2011-12-25 06:03:01 -08:00
CloseWindow ( m_CurrentWindow ? ( char ) m_CurrentWindow - > GetWindowType ( ) : 0 ) ;
2011-10-03 11:41:19 -07:00
a_Window - > Open ( * this ) ;
m_CurrentWindow = a_Window ;
}
2011-12-25 17:07:35 -08:00
void cPlayer : : CloseWindow ( char a_WindowType )
2011-10-03 11:41:19 -07:00
{
2011-12-29 05:16:23 -08:00
if ( a_WindowType = = 0 ) { // Inventory
2011-12-31 20:55:17 -08:00
if ( m_Inventory - > GetWindow ( ) - > GetDraggingItem ( ) & & m_Inventory - > GetWindow ( ) - > GetDraggingItem ( ) - > m_ItemCount > 0 )
2011-12-25 06:03:01 -08:00
{
LOG ( " Player holds item! Dropping it... " ) ;
2011-12-31 20:55:17 -08:00
TossItem ( true , m_Inventory - > GetWindow ( ) - > GetDraggingItem ( ) - > m_ItemCount ) ;
2011-12-25 06:03:01 -08:00
}
//Drop whats in the crafting slots (1, 2, 3, 4)
for ( int i = 1 ; i < = 4 ; i + + )
{
cItem * Item = m_Inventory - > GetSlot ( i ) ;
if ( Item - > m_ItemID > 0 & & Item - > m_ItemCount > 0 )
{
float vX = 0 , vY = 0 , vZ = 0 ;
EulerToVector ( - GetRotation ( ) , GetPitch ( ) , vZ , vX , vY ) ;
vY = - vY * 2 + 1.f ;
cPickup * Pickup = new cPickup ( ( int ) ( GetPosX ( ) * 32 ) , ( int ) ( GetPosY ( ) * 32 ) + ( int ) ( 1.6f * 32 ) , ( int ) ( GetPosZ ( ) * 32 ) , * Item , vX * 2 , vY * 2 , vZ * 2 ) ;
Pickup - > Initialize ( GetWorld ( ) ) ;
}
Item - > Empty ( ) ;
}
}
2012-01-01 10:45:28 -08:00
if ( m_CurrentWindow )
{
if ( a_WindowType = = 1 & & strcmp ( m_CurrentWindow - > GetWindowTitle ( ) . c_str ( ) , " UberChest " ) = = 0 ) { // Chest
cBlockEntity * block = m_CurrentWindow - > GetOwner ( ) - > GetEntity ( ) ;
cPacket_BlockAction ChestClose ;
ChestClose . m_PosX = block - > GetPosX ( ) ;
ChestClose . m_PosY = ( short ) block - > GetPosY ( ) ;
ChestClose . m_PosZ = block - > GetPosZ ( ) ;
ChestClose . m_Byte1 = 1 ;
ChestClose . m_Byte2 = 0 ;
cWorld : : PlayerList PlayerList = cRoot : : Get ( ) - > GetWorld ( ) - > GetAllPlayers ( ) ;
for ( cWorld : : PlayerList : : iterator itr = PlayerList . begin ( ) ; itr ! = PlayerList . end ( ) ; + + itr )
{
if ( ( * itr ) & & ( * itr ) - > GetClientHandle ( ) & & ! ( ( * itr ) - > GetClientHandle ( ) - > IsDestroyed ( ) ) ) {
( * itr ) - > GetClientHandle ( ) - > Send ( ChestClose ) ;
}
2011-12-29 05:16:23 -08:00
}
}
2012-01-01 10:45:28 -08:00
m_CurrentWindow - > Close ( * this ) ;
2011-12-29 05:16:23 -08:00
}
2011-10-03 11:41:19 -07:00
m_CurrentWindow = 0 ;
}
2011-11-01 13:09:13 -07:00
void cPlayer : : SetLastBlockActionTime ( )
{
m_LastBlockActionTime = cRoot : : Get ( ) - > GetWorld ( ) - > GetTime ( ) ;
}
2011-11-10 08:30:14 -08:00
void cPlayer : : SetLastBlockActionCnt ( int a_LastBlockActionCnt )
{
m_LastBlockActionCnt = a_LastBlockActionCnt ;
}
2011-11-01 13:09:13 -07:00
void cPlayer : : SetGameMode ( int a_GameMode )
{
2012-01-01 10:45:28 -08:00
if ( ( a_GameMode < 2 ) & & ( a_GameMode > = 0 ) )
{
if ( m_GameMode ! = a_GameMode )
{
cInventory * OldInventory = 0 ;
if ( m_GameMode = = 0 )
OldInventory = m_Inventory ;
else
OldInventory = m_CreativeInventory ;
2011-11-10 10:28:21 -08:00
m_GameMode = a_GameMode ;
cPacket_NewInvalidState GameModePacket ;
GameModePacket . m_Reason = 3 ; //GameModeChange
GameModePacket . m_GameMode = ( char ) a_GameMode ; //GameModeChange
m_ClientHandle - > Send ( GameModePacket ) ;
2011-12-31 20:55:17 -08:00
GetInventory ( ) . SendWholeInventory ( m_ClientHandle ) ;
2012-01-01 10:45:28 -08:00
OldInventory - > SetEquippedSlot ( GetInventory ( ) . GetEquippedSlot ( ) ) ;
2011-11-10 10:28:21 -08:00
}
}
}
void cPlayer : : LoginSetGameMode ( int a_GameMode )
{
m_GameMode = a_GameMode ;
2011-11-01 13:09:13 -07:00
}
2011-11-09 14:17:30 -08:00
void cPlayer : : SetIP ( std : : string a_IP )
{
m_IP = a_IP ;
}
2011-11-01 13:09:13 -07:00
2011-10-03 11:41:19 -07:00
# ifdef SendMessage // Cause stupid windows.h defines SendMessage as SendMessageA
# undef SendMessage
# endif
void cPlayer : : SendMessage ( const char * a_Message )
{
m_ClientHandle - > Send ( cPacket_Chat ( a_Message ) ) ;
}
void cPlayer : : TeleportTo ( const double & a_PosX , const double & a_PosY , const double & a_PosZ )
{
2011-12-27 18:10:05 -08:00
SetPosition ( a_PosX , a_PosY , a_PosZ ) ;
cPacket_TeleportEntity TeleportEntity ( this ) ;
cRoot : : Get ( ) - > GetServer ( ) - > Broadcast ( TeleportEntity , GetClientHandle ( ) ) ;
2011-10-03 11:41:19 -07:00
cPacket_PlayerPosition PlayerPosition ( this ) ;
2011-12-27 18:10:05 -08:00
2011-10-03 11:41:19 -07:00
m_ClientHandle - > Send ( PlayerPosition ) ;
}
void cPlayer : : MoveTo ( const Vector3d & a_NewPos )
{
// TODO: should do some checks to see if player is not moving through terrain
SetPosition ( a_NewPos ) ;
}
void cPlayer : : SetVisible ( bool a_bVisible )
{
if ( a_bVisible = = true & & m_bVisible = = false ) // Make visible
{
m_bVisible = true ;
SpawnOn ( 0 ) ; // Spawn on everybody
}
if ( a_bVisible = = false & & m_bVisible = = true )
{
m_bVisible = false ;
cPacket_DestroyEntity DestroyEntity ( this ) ;
2011-10-30 17:52:20 -07:00
cChunk * Chunk = GetWorld ( ) - > GetChunkUnreliable ( m_ChunkX , m_ChunkY , m_ChunkZ ) ;
2011-10-03 11:41:19 -07:00
if ( Chunk )
{
Chunk - > Broadcast ( DestroyEntity ) ; // Destroy on all clients
}
}
}
void cPlayer : : AddToGroup ( const char * a_GroupName )
{
cGroup * Group = cRoot : : Get ( ) - > GetGroupManager ( ) - > GetGroup ( a_GroupName ) ;
m_pState - > Groups . push_back ( Group ) ;
LOG ( " Added %s to group %s " , m_pState - > PlayerName . c_str ( ) , a_GroupName ) ;
ResolveGroups ( ) ;
ResolvePermissions ( ) ;
}
bool cPlayer : : CanUseCommand ( const char * a_Command )
{
for ( GroupList : : iterator itr = m_pState - > Groups . begin ( ) ; itr ! = m_pState - > Groups . end ( ) ; + + itr )
{
if ( ( * itr ) - > HasCommand ( a_Command ) ) return true ;
}
return false ;
}
bool cPlayer : : HasPermission ( const char * a_Permission )
{
std : : vector < std : : string > Split = StringSplit ( a_Permission , " . " ) ;
PermissionMap Possibilities = m_pState - > ResolvedPermissions ;
// Now search the namespaces
while ( Possibilities . begin ( ) ! = Possibilities . end ( ) )
{
PermissionMap : : iterator itr = Possibilities . begin ( ) ;
if ( itr - > second )
{
std : : vector < std : : string > OtherSplit = StringSplit ( itr - > first , " . " ) ;
if ( OtherSplit . size ( ) < = Split . size ( ) )
{
unsigned int i ;
for ( i = 0 ; i < OtherSplit . size ( ) ; + + i )
{
if ( OtherSplit [ i ] . compare ( Split [ i ] ) ! = 0 )
{
if ( OtherSplit [ i ] . compare ( " * " ) = = 0 ) return true ; // WildCard man!! WildCard!
break ;
}
}
if ( i = = Split . size ( ) ) return true ;
}
}
Possibilities . erase ( itr ) ;
}
// Nothing that matched :(
return false ;
}
bool cPlayer : : IsInGroup ( const char * a_Group )
{
for ( GroupList : : iterator itr = m_pState - > ResolvedGroups . begin ( ) ; itr ! = m_pState - > ResolvedGroups . end ( ) ; + + itr )
{
if ( strcmp ( a_Group , ( * itr ) - > GetName ( ) . c_str ( ) ) = = 0 )
return true ;
}
return false ;
}
void cPlayer : : ResolvePermissions ( )
{
m_pState - > ResolvedPermissions . clear ( ) ; // Start with an empty map yo~
// Copy all player specific permissions into the resolved permissions map
for ( PermissionMap : : iterator itr = m_pState - > Permissions . begin ( ) ; itr ! = m_pState - > Permissions . end ( ) ; + + itr )
{
m_pState - > ResolvedPermissions [ itr - > first ] = itr - > second ;
}
for ( GroupList : : iterator GroupItr = m_pState - > ResolvedGroups . begin ( ) ; GroupItr ! = m_pState - > ResolvedGroups . end ( ) ; + + GroupItr )
{
const cGroup : : PermissionMap & Permissions = ( * GroupItr ) - > GetPermissions ( ) ;
for ( cGroup : : PermissionMap : : const_iterator itr = Permissions . begin ( ) ; itr ! = Permissions . end ( ) ; + + itr )
{
m_pState - > ResolvedPermissions [ itr - > first ] = itr - > second ;
}
}
}
void cPlayer : : ResolveGroups ( )
{
// Clear resolved groups first
m_pState - > ResolvedGroups . clear ( ) ;
// Get a complete resolved list of all groups the player is in
std : : map < cGroup * , bool > AllGroups ; // Use a map, because it's faster than iterating through a list to find duplicates
GroupList ToIterate ;
for ( GroupList : : iterator GroupItr = m_pState - > Groups . begin ( ) ; GroupItr ! = m_pState - > Groups . end ( ) ; + + GroupItr )
{
ToIterate . push_back ( * GroupItr ) ;
}
while ( ToIterate . begin ( ) ! = ToIterate . end ( ) )
{
cGroup * CurrentGroup = * ToIterate . begin ( ) ;
if ( AllGroups . find ( CurrentGroup ) ! = AllGroups . end ( ) )
{
LOGERROR ( " ERROR: Player %s is in the same group multiple times (%s). FIX IT! " , m_pState - > PlayerName . c_str ( ) , CurrentGroup - > GetName ( ) . c_str ( ) ) ;
}
else
{
AllGroups [ CurrentGroup ] = true ;
m_pState - > ResolvedGroups . push_back ( CurrentGroup ) ; // Add group to resolved list
const cGroup : : GroupList & Inherits = CurrentGroup - > GetInherits ( ) ;
for ( cGroup : : GroupList : : const_iterator itr = Inherits . begin ( ) ; itr ! = Inherits . end ( ) ; + + itr )
{
if ( AllGroups . find ( * itr ) ! = AllGroups . end ( ) )
{
LOGERROR ( " ERROR: Player %s is in the same group multiple times due to inheritance (%s). FIX IT! " , m_pState - > PlayerName . c_str ( ) , ( * itr ) - > GetName ( ) . c_str ( ) ) ;
continue ;
}
ToIterate . push_back ( * itr ) ;
}
}
ToIterate . erase ( ToIterate . begin ( ) ) ;
}
}
std : : string cPlayer : : GetColor ( )
{
if ( m_Color ! = ' - ' )
return cChatColor : : MakeColor ( m_Color ) ;
if ( m_pState - > Groups . size ( ) < 1 )
return cChatColor : : White ;
return ( * m_pState - > Groups . begin ( ) ) - > GetColor ( ) ;
}
void cPlayer : : TossItem ( bool a_bDraggingItem , int a_Amount /* = 1 */ )
{
if ( a_bDraggingItem )
{
2012-01-01 10:45:28 -08:00
cItem * Item = GetInventory ( ) . GetWindow ( ) - > GetDraggingItem ( ) ;
2011-10-03 11:41:19 -07:00
if ( Item - > m_ItemID > 0 & & Item - > m_ItemCount > = a_Amount )
{
float vX = 0 , vY = 0 , vZ = 0 ;
EulerToVector ( - GetRotation ( ) , GetPitch ( ) , vZ , vX , vY ) ;
vY = - vY * 2 + 1.f ;
cPickup * Pickup = new cPickup ( ( int ) ( GetPosX ( ) * 32 ) , ( int ) ( GetPosY ( ) * 32 ) + ( int ) ( 1.6f * 32 ) , ( int ) ( GetPosZ ( ) * 32 ) , cItem ( Item - > m_ItemID , ( char ) a_Amount , Item - > m_ItemHealth ) , vX * 2 , vY * 2 , vZ * 2 ) ;
2011-10-30 17:52:20 -07:00
Pickup - > Initialize ( GetWorld ( ) ) ;
2011-10-03 11:41:19 -07:00
if ( Item - > m_ItemCount > a_Amount )
Item - > m_ItemCount - = ( char ) a_Amount ;
else
Item - > Empty ( ) ;
}
return ;
}
// Else drop equipped item
cItem DroppedItem = GetInventory ( ) . GetEquippedItem ( ) ;
if ( DroppedItem . m_ItemID > 0 & & DroppedItem . m_ItemCount > 0 )
{
DroppedItem . m_ItemCount = 1 ;
if ( GetInventory ( ) . RemoveItem ( DroppedItem ) )
{
DroppedItem . m_ItemCount = 1 ; // RemoveItem decreases the count, so set it to 1 again
float vX = 0 , vY = 0 , vZ = 0 ;
EulerToVector ( - GetRotation ( ) , GetPitch ( ) , vZ , vX , vY ) ;
vY = - vY * 2 + 1.f ;
cPickup * Pickup = new cPickup ( ( int ) ( GetPosX ( ) * 32 ) , ( int ) ( GetPosY ( ) * 32 ) + ( int ) ( 1.6f * 32 ) , ( int ) ( GetPosZ ( ) * 32 ) , DroppedItem , vX * 2 , vY * 2 , vZ * 2 ) ;
2011-10-30 17:52:20 -07:00
Pickup - > Initialize ( GetWorld ( ) ) ;
2011-10-03 11:41:19 -07:00
}
}
}
2011-12-26 13:54:08 -08:00
bool cPlayer : : MoveToWorld ( const char * a_WorldName )
{
cWorld * World = cRoot : : Get ( ) - > GetWorld ( a_WorldName ) ;
if ( World )
{
/* Remove all links to the old world */
GetWorld ( ) - > RemovePlayer ( this ) ;
GetClientHandle ( ) - > RemoveFromAllChunks ( ) ;
cChunk * Chunk = GetWorld ( ) - > GetChunkUnreliable ( m_ChunkX , m_ChunkY , m_ChunkZ ) ;
if ( Chunk )
{
Chunk - > RemoveEntity ( * this ) ;
Chunk - > Broadcast ( cPacket_DestroyEntity ( this ) ) ; // Remove player entity from all clients in old world
}
/* Add player to all the necessary parts of the new world */
SetWorld ( World ) ;
GetWorld ( ) - > AddPlayer ( this ) ;
MoveToCorrectChunk ( true ) ;
GetClientHandle ( ) - > StreamChunks ( ) ;
return true ;
}
return false ;
}
2011-11-01 14:57:08 -07:00
bool cPlayer : : LoadFromDisk ( ) // TODO - This should also get/set/whatever the correct world for this player
2011-10-03 11:41:19 -07:00
{
cIniFile IniFile ( " users.ini " ) ;
if ( IniFile . ReadFile ( ) )
{
std : : string Groups = IniFile . GetValue ( m_pState - > PlayerName , " Groups " , " " ) ;
if ( Groups . size ( ) > 0 )
{
std : : vector < std : : string > Split = StringSplit ( Groups , " , " ) ;
for ( unsigned int i = 0 ; i < Split . size ( ) ; i + + )
{
AddToGroup ( Split [ i ] . c_str ( ) ) ;
}
}
else
{
AddToGroup ( " Default " ) ;
}
m_Color = IniFile . GetValue ( m_pState - > PlayerName , " Color " , " - " ) [ 0 ] ;
}
else
{
2011-12-27 14:57:33 -08:00
LOGWARN ( " WARNING: Failed to read ini file users.ini " ) ;
2011-10-03 11:41:19 -07:00
AddToGroup ( " Default " ) ;
}
ResolvePermissions ( ) ;
// Log player permissions, cause it's what the cool kids do
LOGINFO ( " Player %s has permissions: " , m_pState - > PlayerName . c_str ( ) ) ;
for ( PermissionMap : : iterator itr = m_pState - > ResolvedPermissions . begin ( ) ; itr ! = m_pState - > ResolvedPermissions . end ( ) ; + + itr )
{
if ( itr - > second ) LOGINFO ( " %s " , itr - > first . c_str ( ) ) ;
}
char SourceFile [ 128 ] ;
2011-11-01 14:57:08 -07:00
sprintf_s ( SourceFile , 128 , " players/%s.json " , m_pState - > PlayerName . c_str ( ) ) ;
2011-10-03 11:41:19 -07:00
FILE * f ;
# ifdef _WIN32
if ( fopen_s ( & f , SourceFile , " rb " ) = = 0 ) // no error
# else
if ( ( f = fopen ( SourceFile , " rb " ) ) ! = 0 ) // no error
# endif
{
2011-10-31 14:30:14 -07:00
// Get file size
fseek ( f , 0 , SEEK_END ) ;
long FileSize = ftell ( f ) ;
rewind ( f ) ;
char * buffer = new char [ FileSize ] ;
if ( fread ( buffer , FileSize , 1 , f ) ! = 1 ) { LOGERROR ( " ERROR READING FROM FILE %s " , SourceFile ) ; fclose ( f ) ; return false ; }
2011-10-03 11:41:19 -07:00
fclose ( f ) ;
2011-10-31 14:30:14 -07:00
Json : : Value root ;
Json : : Reader reader ;
if ( ! reader . parse ( buffer , root , false ) )
{
LOGERROR ( " ERROR WHILE PARSING JSON FROM FILE %s " , SourceFile ) ;
}
2012-01-01 10:45:28 -08:00
2011-10-31 14:30:14 -07:00
delete [ ] buffer ;
Json : : Value & JSON_PlayerPosition = root [ " position " ] ;
if ( JSON_PlayerPosition . size ( ) = = 3 )
{
m_Pos - > x = JSON_PlayerPosition [ ( unsigned int ) 0 ] . asDouble ( ) ;
m_Pos - > y = JSON_PlayerPosition [ ( unsigned int ) 1 ] . asDouble ( ) ;
m_Pos - > z = JSON_PlayerPosition [ ( unsigned int ) 2 ] . asDouble ( ) ;
}
Json : : Value & JSON_PlayerRotation = root [ " rotation " ] ;
if ( JSON_PlayerRotation . size ( ) = = 3 )
{
m_Rot - > x = ( float ) JSON_PlayerRotation [ ( unsigned int ) 0 ] . asDouble ( ) ;
m_Rot - > y = ( float ) JSON_PlayerRotation [ ( unsigned int ) 1 ] . asDouble ( ) ;
m_Rot - > z = ( float ) JSON_PlayerRotation [ ( unsigned int ) 2 ] . asDouble ( ) ;
}
2011-11-01 14:57:08 -07:00
m_Health = ( short ) root . get ( " health " , 0 ) . asInt ( ) ;
2011-12-29 07:31:48 -08:00
m_FoodLevel = ( short ) root . get ( " food " , 0 ) . asInt ( ) ;
2011-10-31 14:30:14 -07:00
m_Inventory - > LoadFromJson ( root [ " inventory " ] ) ;
2012-01-01 10:45:28 -08:00
m_CreativeInventory - > LoadFromJson ( root [ " creativeinventory " ] ) ;
2011-11-02 13:19:57 -07:00
m_pState - > LoadedWorldName = root . get ( " world " , " world " ) . asString ( ) ;
2011-10-31 14:30:14 -07:00
2011-10-03 11:41:19 -07:00
return true ;
}
return false ;
}
bool cPlayer : : SaveToDisk ( )
{
2011-11-01 14:57:08 -07:00
cMakeDir : : MakeDir ( " players " ) ;
2011-10-03 11:41:19 -07:00
2011-10-31 14:30:14 -07:00
// create the JSON data
Json : : Value JSON_PlayerPosition ;
JSON_PlayerPosition . append ( Json : : Value ( m_Pos - > x ) ) ;
JSON_PlayerPosition . append ( Json : : Value ( m_Pos - > y ) ) ;
JSON_PlayerPosition . append ( Json : : Value ( m_Pos - > z ) ) ;
Json : : Value JSON_PlayerRotation ;
JSON_PlayerRotation . append ( Json : : Value ( m_Rot - > x ) ) ;
JSON_PlayerRotation . append ( Json : : Value ( m_Rot - > y ) ) ;
JSON_PlayerRotation . append ( Json : : Value ( m_Rot - > z ) ) ;
Json : : Value JSON_Inventory ;
m_Inventory - > SaveToJson ( JSON_Inventory ) ;
2012-01-01 10:45:28 -08:00
Json : : Value JSON_CreativeInventory ;
m_CreativeInventory - > SaveToJson ( JSON_CreativeInventory ) ;
2011-10-31 14:30:14 -07:00
Json : : Value root ;
root [ " position " ] = JSON_PlayerPosition ;
root [ " rotation " ] = JSON_PlayerRotation ;
root [ " inventory " ] = JSON_Inventory ;
2012-01-01 10:45:28 -08:00
root [ " creativeinventory " ] = JSON_CreativeInventory ;
2011-10-31 14:30:14 -07:00
root [ " health " ] = m_Health ;
2011-12-29 07:31:48 -08:00
root [ " food " ] = m_FoodLevel ;
2011-11-02 13:19:57 -07:00
root [ " world " ] = GetWorld ( ) - > GetName ( ) ;
2011-10-31 14:30:14 -07:00
Json : : StyledWriter writer ;
std : : string JsonData = writer . write ( root ) ;
2011-10-03 11:41:19 -07:00
char SourceFile [ 128 ] ;
2011-11-01 14:57:08 -07:00
sprintf_s ( SourceFile , 128 , " players/%s.json " , m_pState - > PlayerName . c_str ( ) ) ;
2011-10-03 11:41:19 -07:00
FILE * f ;
# ifdef _WIN32
if ( fopen_s ( & f , SourceFile , " wb " ) = = 0 ) // no error
# else
if ( ( f = fopen ( SourceFile , " wb " ) ) ! = 0 ) // no error
# endif
{
2011-10-31 14:30:14 -07:00
if ( fwrite ( JsonData . c_str ( ) , JsonData . size ( ) , 1 , f ) ! = 1 ) { LOGERROR ( " ERROR WRITING PLAYER JSON TO FILE %s " , SourceFile ) ; return false ; }
2011-10-03 11:41:19 -07:00
fclose ( f ) ;
return true ;
}
LOGERROR ( " ERROR WRITING PLAYER %s TO FILE %s " , m_pState - > PlayerName . c_str ( ) , SourceFile ) ;
return false ;
}
const char * cPlayer : : GetName ( )
{
return m_pState - > PlayerName . c_str ( ) ;
}
void cPlayer : : SetName ( const char * a_Name )
{
m_pState - > PlayerName = a_Name ;
}
const cPlayer : : GroupList & cPlayer : : GetGroups ( )
{
return m_pState - > Groups ;
2011-10-26 12:13:49 -07:00
}
2011-11-02 13:19:57 -07:00
const char * cPlayer : : GetLoadedWorldName ( )
{
return m_pState - > LoadedWorldName . c_str ( ) ;
2011-12-28 13:00:35 -08:00
}
void cPlayer : : UseEquippedItem ( )
{
if ( GetGameMode ( ) ! = 1 ) //No damage in creative
if ( GetInventory ( ) . GetEquippedItem ( ) . DamageItem ( ) )
{
LOG ( " Player %s Broke ID: %i " , GetClientHandle ( ) - > GetUsername ( ) , GetInventory ( ) . GetEquippedItem ( ) . m_ItemID ) ;
GetInventory ( ) . RemoveItem ( GetInventory ( ) . GetEquippedItem ( ) ) ;
}
2011-11-02 13:19:57 -07:00
}