Beispiel #1
0
void CTurtle::Update(float fElapsedTime)
{
	m_vAnimations[m_nCurrAnimation].Update(fElapsedTime);
	if(GetExperience() >= (100 * GetLevel()))
	{
		CBattleMap::GetInstance()->PlaySFX(CAssets::GetInstance()->aBMcowabungaSnd);
		SetExperience(0/*GetExperience()-(100* GetLevel())*/);
		SetLevel(GetLevel() + 1);
		SetHealthMax((int)((float)GetMaxHealth() * 1.25f));
		SetHealth((int)((float)GetMaxHealth()));
		SetBaseAP(GetBaseAP()+2);
		SetStrength( (int)( (float)GetStrength() * 1.2f ) );
		SetDefense( (int) ( (float)GetDefense() * 1.2f ) );
		SetAccuracy( (int) ( (float)GetAccuracy() * 1.2f ) );
		SetSpeed( (int) ( (float)GetSpeed() * 1.2f ) );
	}
	if( GetHealth() <= 0)
	{
		if(GetAlive() == true)
		{
			CBattleMap::GetInstance()->DecrementNumChars();
			CBattleMap::GetInstance()->DecrementNumTurtles();
			CBattleMap::GetInstance()->SetTurtleDead();
			SetAlive(false);
			if(GetCurrAnimNum() != 9)
				SetCurrAnim(9);
			SetPosZ(0.9f);
		}
	}
}
Beispiel #2
0
void CTurtle::Render()
{
	if(!m_bIsAlive)
	{
		if(GetCurrAnimNum() != 9)
				SetCurrAnim(9);
			SetPosZ(0.9f);
	}
	m_vAnimations[m_nCurrAnimation].Render((int)GetPosX()+m_vAnimations[0].GetFrames()[0].nAnchorX,(int)GetPosY()+m_vAnimations[0].GetFrames()[0].nAnchorY, GetPosZ(), 1.0f, m_dwColor);

}
Beispiel #3
0
bool cMinecart::TestBlockCollision(NIBBLETYPE a_RailMeta)
{
    switch (a_RailMeta)
    {
    case E_META_RAIL_ZM_ZP:
    {
        if (GetSpeedZ() > 0)
        {
            BLOCKTYPE Block = m_World->GetBlock(POSX_TOINT, POSY_TOINT, (int)ceil(GetPosZ()));
            if (!IsBlockRail(Block) && cBlockInfo::IsSolid(Block))
            {
                // We could try to detect a block in front based purely on coordinates, but xoft made a bounding box system - why not use? :P
                cBoundingBox bbBlock(Vector3d(POSX_TOINT, POSY_TOINT, (int)ceil(GetPosZ())), 0.5, 1);
                cBoundingBox bbMinecart(Vector3d(GetPosX(), floor(GetPosY()), GetPosZ()), GetWidth() / 2, GetHeight());

                if (bbBlock.DoesIntersect(bbMinecart))
                {
                    SetSpeed(0, 0, 0);
                    SetPosZ(floor(GetPosZ()) + 0.4);
                    return true;
                }
            }
        }
        else if (GetSpeedZ() < 0)
        {
            BLOCKTYPE Block = m_World->GetBlock(POSX_TOINT, POSY_TOINT, POSZ_TOINT - 1);
            if (!IsBlockRail(Block) && cBlockInfo::IsSolid(Block))
            {
                cBoundingBox bbBlock(Vector3d(POSX_TOINT, POSY_TOINT, POSZ_TOINT - 1), 0.5, 1);
                cBoundingBox bbMinecart(Vector3d(GetPosX(), floor(GetPosY()), GetPosZ() - 1), GetWidth() / 2, GetHeight());

                if (bbBlock.DoesIntersect(bbMinecart))
                {
                    SetSpeed(0, 0, 0);
                    SetPosZ(floor(GetPosZ()) + 0.65);
                    return true;
                }
            }
        }
        break;
    }
    case E_META_RAIL_XM_XP:
    {
        if (GetSpeedX() > 0)
        {
            BLOCKTYPE Block = m_World->GetBlock((int)ceil(GetPosX()), POSY_TOINT, POSZ_TOINT);
            if (!IsBlockRail(Block) && cBlockInfo::IsSolid(Block))
            {
                cBoundingBox bbBlock(Vector3d((int)ceil(GetPosX()), POSY_TOINT, POSZ_TOINT), 0.5, 1);
                cBoundingBox bbMinecart(Vector3d(GetPosX(), floor(GetPosY()), GetPosZ()), GetWidth() / 2, GetHeight());

                if (bbBlock.DoesIntersect(bbMinecart))
                {
                    SetSpeed(0, 0, 0);
                    SetPosX(floor(GetPosX()) + 0.4);
                    return true;
                }
            }
        }
        else if (GetSpeedX() < 0)
        {
            BLOCKTYPE Block = m_World->GetBlock(POSX_TOINT - 1, POSY_TOINT, POSZ_TOINT);
            if (!IsBlockRail(Block) && cBlockInfo::IsSolid(Block))
            {
                cBoundingBox bbBlock(Vector3d(POSX_TOINT - 1, POSY_TOINT, POSZ_TOINT), 0.5, 1);
                cBoundingBox bbMinecart(Vector3d(GetPosX() - 1, floor(GetPosY()), GetPosZ()), GetWidth() / 2, GetHeight());

                if (bbBlock.DoesIntersect(bbMinecart))
                {
                    SetSpeed(0, 0, 0);
                    SetPosX(floor(GetPosX()) + 0.65);
                    return true;
                }
            }
        }
        break;
    }
    case E_META_RAIL_CURVED_ZM_XM:
    case E_META_RAIL_CURVED_ZM_XP:
    case E_META_RAIL_CURVED_ZP_XM:
    case E_META_RAIL_CURVED_ZP_XP:
    {
        BLOCKTYPE BlockXM = m_World->GetBlock(POSX_TOINT - 1, POSY_TOINT, POSZ_TOINT);
        BLOCKTYPE BlockXP = m_World->GetBlock(POSX_TOINT + 1, POSY_TOINT, POSZ_TOINT);
        BLOCKTYPE BlockZM = m_World->GetBlock(POSX_TOINT, POSY_TOINT, POSZ_TOINT - 1);
        BLOCKTYPE BlockZP = m_World->GetBlock(POSX_TOINT, POSY_TOINT, POSZ_TOINT + 1);
        if (
            (!IsBlockRail(BlockXM) && cBlockInfo::IsSolid(BlockXM)) ||
            (!IsBlockRail(BlockXP) && cBlockInfo::IsSolid(BlockXP)) ||
            (!IsBlockRail(BlockZM) && cBlockInfo::IsSolid(BlockZM)) ||
            (!IsBlockRail(BlockZP) && cBlockInfo::IsSolid(BlockZP))
        )
        {
            SetSpeed(0, 0, 0);
            SetPosition(POSX_TOINT + 0.5, GetPosY(), POSZ_TOINT + 0.5);
            return true;
        }
        break;
    }
    default:
        break;
    }
    return false;
}
Beispiel #4
0
void cMinecart::SnapToRail(NIBBLETYPE a_RailMeta)
{
    switch (a_RailMeta)
    {
    case E_META_RAIL_ASCEND_XM:
    case E_META_RAIL_ASCEND_XP:
    case E_META_RAIL_XM_XP:
    {
        SetSpeedZ(0);
        SetPosZ(floor(GetPosZ()) + 0.5);
        break;
    }
    case E_META_RAIL_ASCEND_ZM:
    case E_META_RAIL_ASCEND_ZP:
    case E_META_RAIL_ZM_ZP:
    {
        SetSpeedX(0);
        SetPosX(floor(GetPosX()) + 0.5);
        break;
    }
    // Curved rail physics: once minecart has reached more than half of the block in the direction that it is travelling in, jerk it in the direction of curvature
    case E_META_RAIL_CURVED_ZM_XM:
    {
        if (GetPosZ() > floor(GetPosZ()) + 0.5)
        {
            if (GetSpeedZ() > 0)
            {
                SetSpeedX(-GetSpeedZ() * 0.7);
            }

            SetSpeedZ(0);
            SetPosZ(floor(GetPosZ()) + 0.5);
        }
        else if (GetPosX() > floor(GetPosX()) + 0.5)
        {
            if (GetSpeedX() > 0)
            {
                SetSpeedZ(-GetSpeedX() * 0.7);
            }

            SetSpeedX(0);
            SetPosX(floor(GetPosX()) + 0.5);
        }
        SetSpeedY(0);
        break;
    }
    case E_META_RAIL_CURVED_ZM_XP:
    {
        if (GetPosZ() > floor(GetPosZ()) + 0.5)
        {
            if (GetSpeedZ() > 0)
            {
                SetSpeedX(GetSpeedZ() * 0.7);
            }

            SetSpeedZ(0);
            SetPosZ(floor(GetPosZ()) + 0.5);
        }
        else if (GetPosX() < floor(GetPosX()) + 0.5)
        {
            if (GetSpeedX() < 0)
            {
                SetSpeedZ(GetSpeedX() * 0.7);
            }

            SetSpeedX(0);
            SetPosX(floor(GetPosX()) + 0.5);
        }
        SetSpeedY(0);
        break;
    }
    case E_META_RAIL_CURVED_ZP_XM:
    {
        if (GetPosZ() < floor(GetPosZ()) + 0.5)
        {
            if (GetSpeedZ() < 0)
            {
                SetSpeedX(GetSpeedZ() * 0.7);
            }

            SetSpeedZ(0);
            SetPosZ(floor(GetPosZ()) + 0.5);
        }
        else if (GetPosX() > floor(GetPosX()) + 0.5)
        {
            if (GetSpeedX() > 0)
            {
                SetSpeedZ(GetSpeedX() * 0.7);
            }

            SetSpeedX(0);
            SetPosX(floor(GetPosX()) + 0.5);
        }
        SetSpeedY(0);
        break;
    }
    case E_META_RAIL_CURVED_ZP_XP:
    {
        if (GetPosZ() < floor(GetPosZ()) + 0.5)
        {
            if (GetSpeedZ() < 0)
            {
                SetSpeedX(-GetSpeedZ() * 0.7);
            }

            SetSpeedZ(0);
            SetPosZ(floor(GetPosZ()) + 0.5);
        }
        else if (GetPosX() < floor(GetPosX()) + 0.5)
        {
            if (GetSpeedX() < 0)
            {
                SetSpeedZ(-GetSpeedX() * 0.7);
            }

            SetSpeedX(0);
            SetPosX(floor(GetPosX()) + 0.5);
        }
        SetSpeedY(0);
        break;
    }
    default:
        break;
    }
}
Beispiel #5
0
cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName)
	: super(etPlayer, 0.6, 1.8)
	, m_bVisible(true)
	, m_FoodLevel(MAX_FOOD_LEVEL)
	, m_FoodSaturationLevel(5)
	, m_FoodTickTimer(0)
	, m_FoodExhaustionLevel(0)
	, m_FoodPoisonedTicksRemaining(0)
	, m_LastJumpHeight(0)
	, m_LastGroundHeight(0)
	, m_bTouchGround(false)
	, m_Stance(0.0)
	, m_Inventory(*this)
	, m_CurrentWindow(NULL)
	, m_InventoryWindow(NULL)
	, m_Color('-')
	, m_GameMode(eGameMode_NotSet)
	, m_IP("")
	, m_ClientHandle(a_Client)
	, m_NormalMaxSpeed(1.0)
	, m_SprintingMaxSpeed(1.3)
	, m_FlyingMaxSpeed(1.0)
	, m_IsCrouched(false)
	, m_IsSprinting(false)
	, m_IsFlying(false)
	, m_IsSwimming(false)
	, m_IsSubmerged(false)
	, m_IsFishing(false)
	, m_CanFly(false)
	, m_EatingFinishTick(-1)
	, m_LifetimeTotalXp(0)
	, m_CurrentXp(0)
	, m_bDirtyExperience(false)
	, m_IsChargingBow(false)
	, m_BowCharge(0)
	, m_FloaterID(-1)
	, m_Team(NULL)
{
	LOGD("Created a player object for \"%s\" @ \"%s\" at %p, ID %d", 
		a_PlayerName.c_str(), a_Client->GetIPString().c_str(),
		this, GetUniqueID()
	);
	
	m_InventoryWindow = new cInventoryWindow(*this);
	m_CurrentWindow = m_InventoryWindow;
	m_InventoryWindow->OpenedByPlayer(*this);

	SetMaxHealth(MAX_HEALTH);
	m_Health = MAX_HEALTH;
	
	cTimer t1;
	m_LastPlayerListTime = t1.GetNowTime();
	
	m_PlayerName = a_PlayerName;

	if (!LoadFromDisk())
	{
		m_Inventory.Clear();
		cWorld * DefaultWorld = cRoot::Get()->GetDefaultWorld();
		SetPosX(DefaultWorld->GetSpawnX());
		SetPosY(DefaultWorld->GetSpawnY());
		SetPosZ(DefaultWorld->GetSpawnZ());
		
		LOGD("Player \"%s\" is connecting for the first time, spawning at default world spawn {%.2f, %.2f, %.2f}",
			a_PlayerName.c_str(), GetPosX(), GetPosY(), GetPosZ()
		);
	}

	m_LastJumpHeight = (float)(GetPosY());
	m_LastGroundHeight = (float)(GetPosY());
	m_Stance = GetPosY() + 1.62;

	if (m_GameMode == gmNotSet)
	{
		cWorld * World = cRoot::Get()->GetWorld(GetLoadedWorldName());
		if (World == NULL)
		{
			World = cRoot::Get()->GetDefaultWorld();
		}
		if (World->IsGameModeCreative())
		{
			m_CanFly = true;
		}
	}
	
	cRoot::Get()->GetServer()->PlayerCreated(this);
}
Beispiel #6
0
bool cPlayer::LoadFromDisk()
{
	LoadPermissionsFromDisk();

	AString SourceFile;
	Printf(SourceFile, "players/%s.json", GetName().c_str() );

	cFile f;
	if (!f.Open(SourceFile, cFile::fmRead))
	{
		// This is a new player whom we haven't seen yet, bail out, let them have the defaults
		return false;
	}

	AString buffer;
	if (f.ReadRestOfFile(buffer) != f.GetSize())
	{
		LOGWARNING("Cannot read player data from file \"%s\"", SourceFile.c_str()); 
		return false;
	}
	f.Close(); //cool kids play nice

	Json::Value root;
	Json::Reader reader;
	if (!reader.parse(buffer, root, false))
	{
		LOGWARNING("Cannot parse player data in file \"%s\", player will be reset", SourceFile.c_str());
	}

	Json::Value & JSON_PlayerPosition = root["position"];
	if (JSON_PlayerPosition.size() == 3)
	{
		SetPosX(JSON_PlayerPosition[(unsigned int)0].asDouble());
		SetPosY(JSON_PlayerPosition[(unsigned int)1].asDouble());
		SetPosZ(JSON_PlayerPosition[(unsigned int)2].asDouble());
		m_LastPos = GetPosition();
	}

	Json::Value & JSON_PlayerRotation = root["rotation"];
	if (JSON_PlayerRotation.size() == 3)
	{
		SetYaw      ((float)JSON_PlayerRotation[(unsigned int)0].asDouble());
		SetPitch    ((float)JSON_PlayerRotation[(unsigned int)1].asDouble());
		SetRoll     ((float)JSON_PlayerRotation[(unsigned int)2].asDouble());
	}

	m_Health              = root.get("health", 0).asInt();
	m_AirLevel            = root.get("air",            MAX_AIR_LEVEL).asInt();
	m_FoodLevel           = root.get("food",           MAX_FOOD_LEVEL).asInt();
	m_FoodSaturationLevel = root.get("foodSaturation", MAX_FOOD_LEVEL).asDouble();
	m_FoodTickTimer       = root.get("foodTickTimer",  0).asInt();
	m_FoodExhaustionLevel = root.get("foodExhaustion", 0).asDouble();
	m_LifetimeTotalXp     = (short) root.get("xpTotal", 0).asInt();
	m_CurrentXp           = (short) root.get("xpCurrent", 0).asInt();
	m_IsFlying            = root.get("isflying", 0).asBool();

	m_GameMode = (eGameMode) root.get("gamemode", eGameMode_NotSet).asInt();

	if (m_GameMode == eGameMode_Creative)
	{
		m_CanFly = true;
	}
	
	m_Inventory.LoadFromJson(root["inventory"]);

	m_LoadedWorldName = root.get("world", "world").asString();

	// Load the player stats.
	// We use the default world name (like bukkit) because stats are shared between dimensions/worlds.
	cStatSerializer StatSerializer(cRoot::Get()->GetDefaultWorld()->GetName(), GetName(), &m_Stats);
	StatSerializer.Load();
	
	LOGD("Player \"%s\" was read from file, spawning at {%.2f, %.2f, %.2f} in world \"%s\"",
		GetName().c_str(), GetPosX(), GetPosY(), GetPosZ(), m_LoadedWorldName.c_str()
	);
	
	return true;
}
Beispiel #7
0
cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName)
    : super(etPlayer, 0.6, 1.8)
    , m_GameMode(eGameMode_NotSet)
    , m_IP("")
    , m_LastBlockActionTime( 0 )
    , m_LastBlockActionCnt( 0 )
    , m_AirLevel( MAX_AIR_LEVEL )
    , m_AirTickTimer( DROWNING_TICKS )
    , m_bVisible( true )
    , m_LastGroundHeight( 0 )
    , m_bTouchGround( false )
    , m_Stance( 0.0 )
    , m_Inventory(*this)
    , m_CurrentWindow(NULL)
    , m_InventoryWindow(NULL)
    , m_TimeLastPickupCheck( 0.f )
    , m_Color('-')
    , m_ClientHandle( a_Client )
    , m_FoodLevel(MAX_FOOD_LEVEL)
    , m_FoodSaturationLevel(5)
    , m_FoodTickTimer(0)
    , m_FoodExhaustionLevel(0)
    , m_FoodPoisonedTicksRemaining(0)
    , m_NormalMaxSpeed(0.1)
    , m_SprintingMaxSpeed(0.13)
    , m_IsCrouched(false)
    , m_IsSprinting(false)
    , m_IsSwimming(false)
    , m_IsSubmerged(false)
    , m_EatingFinishTick(-1)
    , m_IsChargingBow(false)
    , m_BowCharge(0)
    , m_CurrentXp(0)
    , m_LifetimeTotalXp(0)
    , m_bDirtyExperience(false)
{
    LOGD("Created a player object for \"%s\" @ \"%s\" at %p, ID %d",
         a_PlayerName.c_str(), a_Client->GetIPString().c_str(),
         this, GetUniqueID()
        );

    m_InventoryWindow = new cInventoryWindow(*this);
    m_CurrentWindow = m_InventoryWindow;
    m_InventoryWindow->OpenedByPlayer(*this);

    SetMaxHealth(MAX_HEALTH);
    m_Health = MAX_HEALTH;

    cTimer t1;
    m_LastPlayerListTime = t1.GetNowTime();

    m_TimeLastTeleportPacket = 0;
    m_TimeLastPickupCheck = 0;

    m_PlayerName = a_PlayerName;
    m_bDirtyPosition = true; // So chunks are streamed to player at spawn

    if (!LoadFromDisk())
    {
        m_Inventory.Clear();
        SetPosX(cRoot::Get()->GetDefaultWorld()->GetSpawnX());
        SetPosY(cRoot::Get()->GetDefaultWorld()->GetSpawnY());
        SetPosZ(cRoot::Get()->GetDefaultWorld()->GetSpawnZ());

        LOGD("Player \"%s\" is connecting for the first time, spawning at default world spawn {%.2f, %.2f, %.2f}",
             a_PlayerName.c_str(), GetPosX(), GetPosY(), GetPosZ()
            );
    }
    m_LastJumpHeight = (float)(GetPosY());
    m_LastGroundHeight = (float)(GetPosY());
    m_Stance = GetPosY() + 1.62;

    cRoot::Get()->GetServer()->PlayerCreated(this);
}
Beispiel #8
0
bool cPlayer::LoadFromDisk()
{
    LoadPermissionsFromDisk();

    // Log player permissions, cause it's what the cool kids do
    LOGINFO("Player %s has permissions:", m_PlayerName.c_str() );
    for( PermissionMap::iterator itr = m_ResolvedPermissions.begin(); itr != m_ResolvedPermissions.end(); ++itr )
    {
        if( itr->second ) LOGINFO("%s", itr->first.c_str() );
    }

    AString SourceFile;
    Printf(SourceFile, "players/%s.json", m_PlayerName.c_str() );

    cFile f;
    if (!f.Open(SourceFile, cFile::fmRead))
    {
        // This is a new player whom we haven't seen yet, bail out, let them have the defaults
        return false;
    }

    AString buffer;
    if (f.ReadRestOfFile(buffer) != f.GetSize())
    {
        LOGWARNING("Cannot read player data from file \"%s\"", SourceFile.c_str());
        return false;
    }
    f.Close(); //cool kids play nice

    Json::Value root;
    Json::Reader reader;
    if (!reader.parse(buffer, root, false))
    {
        LOGWARNING("Cannot parse player data in file \"%s\", player will be reset", SourceFile.c_str());
    }

    Json::Value & JSON_PlayerPosition = root["position"];
    if (JSON_PlayerPosition.size() == 3)
    {
        SetPosX(JSON_PlayerPosition[(unsigned int)0].asDouble());
        SetPosY(JSON_PlayerPosition[(unsigned int)1].asDouble());
        SetPosZ(JSON_PlayerPosition[(unsigned int)2].asDouble());
        m_LastPosX = GetPosX();
        m_LastPosY = GetPosY();
        m_LastPosZ = GetPosZ();
        m_LastFoodPos = GetPosition();
    }

    Json::Value & JSON_PlayerRotation = root["rotation"];
    if (JSON_PlayerRotation.size() == 3)
    {
        SetRotation ((float)JSON_PlayerRotation[(unsigned int)0].asDouble());
        SetPitch    ((float)JSON_PlayerRotation[(unsigned int)1].asDouble());
        SetRoll     ((float)JSON_PlayerRotation[(unsigned int)2].asDouble());
    }

    m_Health              = root.get("health", 0).asInt();
    m_AirLevel            = root.get("air",            MAX_AIR_LEVEL).asInt();
    m_FoodLevel           = root.get("food",           MAX_FOOD_LEVEL).asInt();
    m_FoodSaturationLevel = root.get("foodSaturation", MAX_FOOD_LEVEL).asDouble();
    m_FoodTickTimer       = root.get("foodTickTimer",  0).asInt();
    m_FoodExhaustionLevel = root.get("foodExhaustion", 0).asDouble();
    m_LifetimeTotalXp     = (short) root.get("xpTotal", 0).asInt();
    m_CurrentXp           = (short) root.get("xpCurrent", 0).asInt();

    //SetExperience(root.get("experience", 0).asInt());

    m_GameMode = (eGameMode) root.get("gamemode", eGameMode_NotSet).asInt();

    m_Inventory.LoadFromJson(root["inventory"]);

    m_LoadedWorldName = root.get("world", "world").asString();

    LOGD("Player \"%s\" was read from file, spawning at {%.2f, %.2f, %.2f} in world \"%s\"",
         m_PlayerName.c_str(), GetPosX(), GetPosY(), GetPosZ(), m_LoadedWorldName.c_str()
        );

    return true;
}
Beispiel #9
0
cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName) :
	super(etPlayer, 0.6, 1.8),
	m_bVisible(true),
	m_FoodLevel(MAX_FOOD_LEVEL),
	m_FoodSaturationLevel(5.0),
	m_FoodTickTimer(0),
	m_FoodExhaustionLevel(0.0),
	m_LastJumpHeight(0),
	m_LastGroundHeight(0),
	m_bTouchGround(false),
	m_Stance(0.0),
	m_Inventory(*this),
	m_EnderChestContents(9, 3),
	m_CurrentWindow(NULL),
	m_InventoryWindow(NULL),
	m_GameMode(eGameMode_NotSet),
	m_IP(""),
	m_ClientHandle(a_Client),
	m_NormalMaxSpeed(1.0),
	m_SprintingMaxSpeed(1.3),
	m_FlyingMaxSpeed(1.0),
	m_IsCrouched(false),
	m_IsSprinting(false),
	m_IsFlying(false),
	m_IsSwimming(false),
	m_IsSubmerged(false),
	m_IsFishing(false),
	m_CanFly(false),
	m_EatingFinishTick(-1),
	m_LifetimeTotalXp(0),
	m_CurrentXp(0),
	m_bDirtyExperience(false),
	m_IsChargingBow(false),
	m_BowCharge(0),
	m_FloaterID(-1),
	m_Team(NULL),
	m_TicksUntilNextSave(PLAYER_INVENTORY_SAVE_INTERVAL),
	m_bIsTeleporting(false),
	m_UUID((a_Client != NULL) ? a_Client->GetUUID() : "")
{
	m_InventoryWindow = new cInventoryWindow(*this);
	m_CurrentWindow = m_InventoryWindow;
	m_InventoryWindow->OpenedByPlayer(*this);

	SetMaxHealth(MAX_HEALTH);
	m_Health = MAX_HEALTH;
	
	cTimer t1;
	m_LastPlayerListTime = t1.GetNowTime();
	
	m_PlayerName = a_PlayerName;

	cWorld * World = NULL;
	if (!LoadFromDisk(World))
	{
		m_Inventory.Clear();
		SetPosX(World->GetSpawnX());
		SetPosY(World->GetSpawnY());
		SetPosZ(World->GetSpawnZ());
		SetBedPos(Vector3i((int)World->GetSpawnX(), (int)World->GetSpawnY(), (int)World->GetSpawnZ()));
		
		LOGD("Player \"%s\" is connecting for the first time, spawning at default world spawn {%.2f, %.2f, %.2f}",
			a_PlayerName.c_str(), GetPosX(), GetPosY(), GetPosZ()
		);
	}

	m_LastJumpHeight = (float)(GetPosY());
	m_LastGroundHeight = (float)(GetPosY());
	m_Stance = GetPosY() + 1.62;

	if (m_GameMode == gmNotSet)
	{
		if (World->IsGameModeCreative())
		{
			m_CanFly = true;
		}
	}
	
	cRoot::Get()->GetServer()->PlayerCreated(this);
}
Beispiel #10
0
bool cPlayer::LoadFromFile(const AString & a_FileName, cWorldPtr & a_World)
{
	// Load the data from the file:
	cFile f;
	if (!f.Open(a_FileName, cFile::fmRead))
	{
		// This is a new player whom we haven't seen yet, bail out, let them have the defaults
		return false;
	}
	AString buffer;
	if (f.ReadRestOfFile(buffer) != f.GetSize())
	{
		LOGWARNING("Cannot read player data from file \"%s\"", a_FileName.c_str());
		return false;
	}
	f.Close();

	// Parse the JSON format:
	Json::Value root;
	Json::Reader reader;
	if (!reader.parse(buffer, root, false))
	{
		LOGWARNING("Cannot parse player data in file \"%s\"", a_FileName.c_str());
		return false;
	}

	// Load the player data:
	Json::Value & JSON_PlayerPosition = root["position"];
	if (JSON_PlayerPosition.size() == 3)
	{
		SetPosX(JSON_PlayerPosition[(unsigned)0].asDouble());
		SetPosY(JSON_PlayerPosition[(unsigned)1].asDouble());
		SetPosZ(JSON_PlayerPosition[(unsigned)2].asDouble());
		m_LastPos = GetPosition();
	}

	Json::Value & JSON_PlayerRotation = root["rotation"];
	if (JSON_PlayerRotation.size() == 3)
	{
		SetYaw      ((float)JSON_PlayerRotation[(unsigned)0].asDouble());
		SetPitch    ((float)JSON_PlayerRotation[(unsigned)1].asDouble());
		SetRoll     ((float)JSON_PlayerRotation[(unsigned)2].asDouble());
	}

	m_Health              = root.get("health",         0).asInt();
	m_AirLevel            = root.get("air",            MAX_AIR_LEVEL).asInt();
	m_FoodLevel           = root.get("food",           MAX_FOOD_LEVEL).asInt();
	m_FoodSaturationLevel = root.get("foodSaturation", MAX_FOOD_LEVEL).asDouble();
	m_FoodTickTimer       = root.get("foodTickTimer",  0).asInt();
	m_FoodExhaustionLevel = root.get("foodExhaustion", 0).asDouble();
	m_LifetimeTotalXp     = (short) root.get("xpTotal", 0).asInt();
	m_CurrentXp           = (short) root.get("xpCurrent", 0).asInt();
	m_IsFlying            = root.get("isflying", 0).asBool();

	m_GameMode = (eGameMode) root.get("gamemode", eGameMode_NotSet).asInt();

	if (m_GameMode == eGameMode_Creative)
	{
		m_CanFly = true;
	}
	
	m_Inventory.LoadFromJson(root["inventory"]);
	cEnderChestEntity::LoadFromJson(root["enderchestinventory"], m_EnderChestContents);

	m_LoadedWorldName = root.get("world", "world").asString();
	a_World = cRoot::Get()->GetWorld(GetLoadedWorldName(), false);
	if (a_World == NULL)
	{
		a_World = cRoot::Get()->GetDefaultWorld();
	}

	m_LastBedPos.x = root.get("SpawnX", a_World->GetSpawnX()).asInt();
	m_LastBedPos.y = root.get("SpawnY", a_World->GetSpawnY()).asInt();
	m_LastBedPos.z = root.get("SpawnZ", a_World->GetSpawnZ()).asInt();

	// Load the player stats.
	// We use the default world name (like bukkit) because stats are shared between dimensions/worlds.
	cStatSerializer StatSerializer(cRoot::Get()->GetDefaultWorld()->GetName(), GetName(), &m_Stats);
	StatSerializer.Load();
	
	LOGD("Player %s was read from file \"%s\", spawning at {%.2f, %.2f, %.2f} in world \"%s\"",
		GetName().c_str(), a_FileName.c_str(), GetPosX(), GetPosY(), GetPosZ(), a_World->GetName().c_str()
	);
	
	return true;
}
Beispiel #11
0
void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
{
	// TODO Add collision detection with entities.
	a_Dt /= 1000;
	Vector3d NextPos = Vector3d(GetPosX(),GetPosY(),GetPosZ());
	Vector3d NextSpeed = Vector3d(GetSpeedX(),GetSpeedY(),GetSpeedZ());
	int BlockX = (int) floor(NextPos.x);
	int BlockY = (int) floor(NextPos.y);
	int BlockZ = (int) floor(NextPos.z);
	
	if ((BlockY >= cChunkDef::Height) || (BlockY < 0))
	{
		// Outside of the world
		// TODO: Current speed should still be added to the entity position
		// Otherwise TNT explosions in the void will still effect the bottommost layers of the world
		return;
	}
	
	// Make sure we got the correct chunk and a valid one. No one ever knows...
	cChunk * NextChunk = a_Chunk.GetNeighborChunk(BlockX,BlockZ);
	if (NextChunk != NULL)
	{
		int RelBlockX = BlockX - (NextChunk->GetPosX() * cChunkDef::Width);
		int RelBlockZ = BlockZ - (NextChunk->GetPosZ() * cChunkDef::Width);
		BLOCKTYPE BlockIn = NextChunk->GetBlock( RelBlockX, BlockY, RelBlockZ );
		if (!g_BlockIsSolid[BlockIn])  // Making sure we are not inside a solid block
		{
			if (m_bOnGround)  // check if it's still on the ground
			{
				BLOCKTYPE BlockBelow = NextChunk->GetBlock( RelBlockX, BlockY - 1, RelBlockZ );
				if (!g_BlockIsSolid[BlockBelow])  // Check if block below is air or water.
				{
					m_bOnGround = false;
				}
			}
		}
		else
		{
			//Push out entity.
			m_bOnGround = true;
			NextPos.y += 0.2;
			LOGD("Entity #%d (%s) is inside a block at {%d,%d,%d}",
				m_UniqueID, GetClass(), BlockX, BlockY, BlockZ);
		}

		if (!m_bOnGround)
		{
			float fallspeed;
			if (IsBlockWater(BlockIn))
			{
				fallspeed = -3.0f * a_Dt; //Fall slower in water.
			}
			else if (BlockIn == E_BLOCK_COBWEB)
			{
				NextSpeed.y *= 0.05; //Reduce overall falling speed
				fallspeed = 0; //No falling.
			}
			else
			{
				//Normal gravity
				fallspeed = m_Gravity * a_Dt;
			}
			NextSpeed.y += fallspeed;
		}
		else
		{
			//Friction
			if (NextSpeed.SqrLength() > 0.0004f)
			{
				NextSpeed.x *= 0.7f/(1+a_Dt);
				if ( fabs(NextSpeed.x) < 0.05 ) NextSpeed.x = 0;
				NextSpeed.z *= 0.7f/(1+a_Dt);
				if ( fabs(NextSpeed.z) < 0.05 ) NextSpeed.z = 0;
			}
		}

		//Adjust X and Z speed for COBWEB temporary. This speed modification should be handled inside block handlers since we
		//might have different speed modifiers according to terrain.
		if (BlockIn == E_BLOCK_COBWEB)
		{
			NextSpeed.x *= 0.25;
			NextSpeed.z *= 0.25;
		}
					
		//Get water direction
		Direction WaterDir = m_World->GetWaterSimulator()->GetFlowingDirection(BlockX, BlockY, BlockZ);

		m_WaterSpeed *= 0.9f;		//Reduce speed each tick

		switch(WaterDir)
		{
			case X_PLUS:
				m_WaterSpeed.x = 1.f;
				m_bOnGround = false;
				break;
			case X_MINUS:
				m_WaterSpeed.x = -1.f;
				m_bOnGround = false;
				break;
			case Z_PLUS:
				m_WaterSpeed.z = 1.f;
				m_bOnGround = false;
				break;
			case Z_MINUS:
				m_WaterSpeed.z = -1.f;
				m_bOnGround = false;
				break;
			
		default:
			break;
		}

		if (fabs(m_WaterSpeed.x) < 0.05)
		{
			m_WaterSpeed.x = 0;
		}

		if (fabs(m_WaterSpeed.z) < 0.05)
		{
			m_WaterSpeed.z = 0;
		}

		NextSpeed += m_WaterSpeed;

		if( NextSpeed.SqrLength() > 0.f )
		{
			cTracer Tracer( GetWorld() );
			int Ret = Tracer.Trace( NextPos, NextSpeed, 2 );
			if( Ret ) // Oh noez! we hit something
			{
				// Set to hit position
				if( (Tracer.RealHit - NextPos).SqrLength() <= ( NextSpeed * a_Dt ).SqrLength() )
				{
					if( Ret == 1 )
					{

						if( Tracer.HitNormal.x != 0.f ) NextSpeed.x = 0.f;
						if( Tracer.HitNormal.y != 0.f ) NextSpeed.y = 0.f;
						if( Tracer.HitNormal.z != 0.f ) NextSpeed.z = 0.f;

						if( Tracer.HitNormal.y > 0 ) // means on ground
						{
							m_bOnGround = true;
						}
					}
					NextPos.Set(Tracer.RealHit.x,Tracer.RealHit.y,Tracer.RealHit.z);
					NextPos.x += Tracer.HitNormal.x * 0.5f;
					NextPos.z += Tracer.HitNormal.z * 0.5f;
				}
				else
					NextPos += (NextSpeed * a_Dt);
			}
			else
			{
				// We didn't hit anything, so move =]
				NextPos += (NextSpeed * a_Dt);
			}
		}
		BlockX = (int) floor(NextPos.x);
		BlockZ = (int) floor(NextPos.z);
		NextChunk = NextChunk->GetNeighborChunk(BlockX,BlockZ);
		// See if we can commit our changes. If not, we will discard them.
		if (NextChunk != NULL)
		{
			if (NextPos.x != GetPosX()) SetPosX(NextPos.x);
			if (NextPos.y != GetPosY()) SetPosY(NextPos.y);
			if (NextPos.z != GetPosZ()) SetPosZ(NextPos.z);
			if (NextSpeed.x != GetSpeedX()) SetSpeedX(NextSpeed.x);
			if (NextSpeed.y != GetSpeedY()) SetSpeedY(NextSpeed.y);
			if (NextSpeed.z != GetSpeedZ()) SetSpeedZ(NextSpeed.z);
		}
	}
}
Beispiel #12
0
void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
{
	// TODO Add collision detection with entities.
	a_Dt /= 1000;  // Convert from msec to sec
	Vector3d NextPos = Vector3d(GetPosX(),GetPosY(),GetPosZ());
	Vector3d NextSpeed = Vector3d(GetSpeedX(),GetSpeedY(),GetSpeedZ());
	int BlockX = (int) floor(NextPos.x);
	int BlockY = (int) floor(NextPos.y);
	int BlockZ = (int) floor(NextPos.z);
	
	if ((BlockY >= cChunkDef::Height) || (BlockY < 0))
	{
		// Outside of the world

		cChunk * NextChunk = a_Chunk.GetNeighborChunk(BlockX, BlockZ);
		// See if we can commit our changes. If not, we will discard them.
		if (NextChunk != NULL)
		{
			SetSpeed(NextSpeed);
			NextPos += (NextSpeed * a_Dt);
			SetPosition(NextPos);
		}
		return;
	}
	
	// Make sure we got the correct chunk and a valid one. No one ever knows...
	cChunk * NextChunk = a_Chunk.GetNeighborChunk(BlockX, BlockZ);
	if (NextChunk != NULL)
	{
		int RelBlockX = BlockX - (NextChunk->GetPosX() * cChunkDef::Width);
		int RelBlockZ = BlockZ - (NextChunk->GetPosZ() * cChunkDef::Width);
		BLOCKTYPE BlockIn = NextChunk->GetBlock( RelBlockX, BlockY, RelBlockZ );
		BLOCKTYPE BlockBelow = (BlockY > 0) ? NextChunk->GetBlock(RelBlockX, BlockY - 1, RelBlockZ) : E_BLOCK_AIR;
		if (!g_BlockIsSolid[BlockIn])  // Making sure we are not inside a solid block
		{
			if (m_bOnGround)  // check if it's still on the ground
			{
				if (!g_BlockIsSolid[BlockBelow])  // Check if block below is air or water.
				{
					m_bOnGround = false;
				}
			}
		}
		else
		{
			// Push out entity.
			BLOCKTYPE GotBlock;

			static const struct
			{
				int x, y, z;
			} gCrossCoords[] =
			{
				{ 1, 0,  0},
				{-1, 0,  0},
				{ 0, 0,  1},
				{ 0, 0, -1},
			} ;

			bool IsNoAirSurrounding = true;
			for (int i = 0; i < ARRAYCOUNT(gCrossCoords); i++)
			{
				if (!NextChunk->UnboundedRelGetBlockType(RelBlockX + gCrossCoords[i].x, BlockY, RelBlockZ + gCrossCoords[i].z, GotBlock))
				{
					// The pickup is too close to an unloaded chunk, bail out of any physics handling
					return;
				}
				if (!g_BlockIsSolid[GotBlock])
				{
					NextPos.x += gCrossCoords[i].x;
					NextPos.z += gCrossCoords[i].z;
					IsNoAirSurrounding = false;
					break;
				}
			}  // for i - gCrossCoords[]
			
			if (IsNoAirSurrounding)
			{
				NextPos.y += 0.5;
			}

			m_bOnGround = true;

			LOGD("Entity #%d (%s) is inside a block at {%d, %d, %d}",
				m_UniqueID, GetClass(), BlockX, BlockY, BlockZ
			);
		}

		if (!m_bOnGround)
		{
			float fallspeed;
			if (IsBlockWater(BlockIn))
			{
				fallspeed = m_Gravity * a_Dt / 3;  // Fall 3x slower in water.
			}
			else if (IsBlockRail(BlockBelow) && IsMinecart())  // Rails aren't solid, except for Minecarts
			{
				fallspeed = 0;
				m_bOnGround = true;
			}
			else if (BlockIn == E_BLOCK_COBWEB)
			{
				NextSpeed.y *= 0.05;  // Reduce overall falling speed
				fallspeed = 0;  // No falling.
			}
			else
			{
				// Normal gravity
				fallspeed = m_Gravity * a_Dt;
			}
			NextSpeed.y += fallspeed;
		}
		else
		{
			if (IsMinecart())
			{
				if (!IsBlockRail(BlockBelow))
				{
					// Friction if minecart is off track, otherwise, Minecart.cpp handles this
					if (NextSpeed.SqrLength() > 0.0004f)
					{
						NextSpeed.x *= 0.7f / (1 + a_Dt);
						if (fabs(NextSpeed.x) < 0.05)
						{
							NextSpeed.x = 0;
						}
						NextSpeed.z *= 0.7f / (1 + a_Dt);
						if (fabs(NextSpeed.z) < 0.05)
						{
							NextSpeed.z = 0;
						}
					}
				}
			}
			else
			{
				// Friction for non-minecarts
				if (NextSpeed.SqrLength() > 0.0004f)
				{
					NextSpeed.x *= 0.7f / (1 + a_Dt);
					if (fabs(NextSpeed.x) < 0.05)
					{
						NextSpeed.x = 0;
					}
					NextSpeed.z *= 0.7f / (1 + a_Dt);
					if (fabs(NextSpeed.z) < 0.05)
					{
						NextSpeed.z = 0;
					}
				}
			}
		}

		// Adjust X and Z speed for COBWEB temporary. This speed modification should be handled inside block handlers since we
		// might have different speed modifiers according to terrain.
		if (BlockIn == E_BLOCK_COBWEB)
		{
			NextSpeed.x *= 0.25;
			NextSpeed.z *= 0.25;
		}
					
		//Get water direction
		Direction WaterDir = m_World->GetWaterSimulator()->GetFlowingDirection(BlockX, BlockY, BlockZ);

		m_WaterSpeed *= 0.9f;		//Reduce speed each tick

		switch(WaterDir)
		{
			case X_PLUS:
				m_WaterSpeed.x = 0.2f;
				m_bOnGround = false;
				break;
			case X_MINUS:
				m_WaterSpeed.x = -0.2f;
				m_bOnGround = false;
				break;
			case Z_PLUS:
				m_WaterSpeed.z = 0.2f;
				m_bOnGround = false;
				break;
			case Z_MINUS:
				m_WaterSpeed.z = -0.2f;
				m_bOnGround = false;
				break;
			
		default:
			break;
		}

		if (fabs(m_WaterSpeed.x) < 0.05)
		{
			m_WaterSpeed.x = 0;
		}

		if (fabs(m_WaterSpeed.z) < 0.05)
		{
			m_WaterSpeed.z = 0;
		}

		NextSpeed += m_WaterSpeed;

		if( NextSpeed.SqrLength() > 0.f )
		{
			cTracer Tracer( GetWorld() );
			int Ret = Tracer.Trace( NextPos, NextSpeed, 2 );
			if( Ret ) // Oh noez! we hit something
			{
				// Set to hit position
				if( (Tracer.RealHit - NextPos).SqrLength() <= ( NextSpeed * a_Dt ).SqrLength() )
				{
					if( Ret == 1 )
					{
						if( Tracer.HitNormal.x != 0.f ) NextSpeed.x = 0.f;
						if( Tracer.HitNormal.y != 0.f ) NextSpeed.y = 0.f;
						if( Tracer.HitNormal.z != 0.f ) NextSpeed.z = 0.f;

						if( Tracer.HitNormal.y > 0 ) // means on ground
						{
							m_bOnGround = true;
						}
					}
					NextPos.Set(Tracer.RealHit.x,Tracer.RealHit.y,Tracer.RealHit.z);
					NextPos.x += Tracer.HitNormal.x * 0.3f;
					NextPos.y += Tracer.HitNormal.y * 0.05f; // Any larger produces entity vibration-upon-the-spot
					NextPos.z += Tracer.HitNormal.z * 0.3f;
				}
				else
				{
					NextPos += (NextSpeed * a_Dt);
				}
			}
			else
			{
				// We didn't hit anything, so move =]
				NextPos += (NextSpeed * a_Dt);
			}
		}
		BlockX = (int) floor(NextPos.x);
		BlockZ = (int) floor(NextPos.z);
		NextChunk = NextChunk->GetNeighborChunk(BlockX,BlockZ);
		// See if we can commit our changes. If not, we will discard them.
		if (NextChunk != NULL)
		{
			if (NextPos.x != GetPosX()) SetPosX(NextPos.x);
			if (NextPos.y != GetPosY()) SetPosY(NextPos.y);
			if (NextPos.z != GetPosZ()) SetPosZ(NextPos.z);
			if (NextSpeed.x != GetSpeedX()) SetSpeedX(NextSpeed.x);
			if (NextSpeed.y != GetSpeedY()) SetSpeedY(NextSpeed.y);
			if (NextSpeed.z != GetSpeedZ()) SetSpeedZ(NextSpeed.z);
		}
	}
}