1
0

Merge pull request #353 from marmot21/playerxp

Playerxp
This commit is contained in:
Mattes D 2013-11-17 14:12:09 -08:00
commit d169a1959d
14 changed files with 246 additions and 79 deletions

View File

@ -45,6 +45,8 @@ function Initialize(Plugin)
PluginManager:BindCommand("/fs", "debuggers", HandleFoodStatsCmd, "- Turns regular foodstats message on or off"); PluginManager:BindCommand("/fs", "debuggers", HandleFoodStatsCmd, "- Turns regular foodstats message on or off");
PluginManager:BindCommand("/arr", "debuggers", HandleArrowCmd, "- Creates an arrow going away from the player"); PluginManager:BindCommand("/arr", "debuggers", HandleArrowCmd, "- Creates an arrow going away from the player");
PluginManager:BindCommand("/fb", "debuggers", HandleFireballCmd, "- Creates a ghast fireball as if shot by the player"); PluginManager:BindCommand("/fb", "debuggers", HandleFireballCmd, "- Creates a ghast fireball as if shot by the player");
PluginManager:BindCommand("/xpa", "debuggers", HandleAddExperience, "- Adds 200 experience to the player");
PluginManager:BindCommand("/xpr", "debuggers", HandleRemoveXp, "- Remove all xp");
-- Enable the following line for BlockArea / Generator interface testing: -- Enable the following line for BlockArea / Generator interface testing:
-- PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHUNK_GENERATED); -- PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHUNK_GENERATED);
@ -846,3 +848,18 @@ end
function HandleAddExperience(a_Split, a_Player)
a_Player:DeltaExperience(200);
return true;
end
function HandleRemoveXp(a_Split, a_Player)
a_Player:SetCurrentExperience(0);
return true;
end

View File

@ -1,6 +1,6 @@
/* /*
** Lua binding: AllToLua ** Lua binding: AllToLua
** Generated automatically by tolua++-1.0.92 on 11/15/13 10:14:19. ** Generated automatically by tolua++-1.0.92 on 11/16/13 21:58:48.
*/ */
#ifndef __cplusplus #ifndef __cplusplus
@ -7650,9 +7650,9 @@ static int tolua_AllToLua_cEntity_IsInvisible00(lua_State* tolua_S)
} }
#endif //#ifndef TOLUA_DISABLE #endif //#ifndef TOLUA_DISABLE
/* method: SetExperience of class cPlayer */ /* method: SetCurrentExperience of class cPlayer */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_SetExperience00 #ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_SetCurrentExperience00
static int tolua_AllToLua_cPlayer_SetExperience00(lua_State* tolua_S) static int tolua_AllToLua_cPlayer_SetCurrentExperience00(lua_State* tolua_S)
{ {
#ifndef TOLUA_RELEASE #ifndef TOLUA_RELEASE
tolua_Error tolua_err; tolua_Error tolua_err;
@ -7666,27 +7666,27 @@ static int tolua_AllToLua_cPlayer_SetExperience00(lua_State* tolua_S)
#endif #endif
{ {
cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S,1,0); cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S,1,0);
int a_XpTotal = ((int) tolua_tonumber(tolua_S,2,0)); short a_XpTotal = ((short) tolua_tonumber(tolua_S,2,0));
#ifndef TOLUA_RELEASE #ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SetExperience'", NULL); if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SetCurrentExperience'", NULL);
#endif #endif
{ {
bool tolua_ret = (bool) self->SetExperience(a_XpTotal); bool tolua_ret = (bool) self->SetCurrentExperience(a_XpTotal);
tolua_pushboolean(tolua_S,(bool)tolua_ret); tolua_pushboolean(tolua_S,(bool)tolua_ret);
} }
} }
return 1; return 1;
#ifndef TOLUA_RELEASE #ifndef TOLUA_RELEASE
tolua_lerror: tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'SetExperience'.",&tolua_err); tolua_error(tolua_S,"#ferror in function 'SetCurrentExperience'.",&tolua_err);
return 0; return 0;
#endif #endif
} }
#endif //#ifndef TOLUA_DISABLE #endif //#ifndef TOLUA_DISABLE
/* method: AddExperience of class cPlayer */ /* method: DeltaExperience of class cPlayer */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_AddExperience00 #ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_DeltaExperience00
static int tolua_AllToLua_cPlayer_AddExperience00(lua_State* tolua_S) static int tolua_AllToLua_cPlayer_DeltaExperience00(lua_State* tolua_S)
{ {
#ifndef TOLUA_RELEASE #ifndef TOLUA_RELEASE
tolua_Error tolua_err; tolua_Error tolua_err;
@ -7700,27 +7700,27 @@ static int tolua_AllToLua_cPlayer_AddExperience00(lua_State* tolua_S)
#endif #endif
{ {
cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S,1,0); cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S,1,0);
int a_Xp_delta = ((int) tolua_tonumber(tolua_S,2,0)); short a_Xp_delta = ((short) tolua_tonumber(tolua_S,2,0));
#ifndef TOLUA_RELEASE #ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'AddExperience'", NULL); if (!self) tolua_error(tolua_S,"invalid 'self' in function 'DeltaExperience'", NULL);
#endif #endif
{ {
int tolua_ret = (int) self->AddExperience(a_Xp_delta); short tolua_ret = (short) self->DeltaExperience(a_Xp_delta);
tolua_pushnumber(tolua_S,(lua_Number)tolua_ret); tolua_pushnumber(tolua_S,(lua_Number)tolua_ret);
} }
} }
return 1; return 1;
#ifndef TOLUA_RELEASE #ifndef TOLUA_RELEASE
tolua_lerror: tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'AddExperience'.",&tolua_err); tolua_error(tolua_S,"#ferror in function 'DeltaExperience'.",&tolua_err);
return 0; return 0;
#endif #endif
} }
#endif //#ifndef TOLUA_DISABLE #endif //#ifndef TOLUA_DISABLE
/* method: XpGetTotal of class cPlayer */ /* method: GetXpLifetimeTotal of class cPlayer */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_XpGetTotal00 #ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_GetXpLifetimeTotal00
static int tolua_AllToLua_cPlayer_XpGetTotal00(lua_State* tolua_S) static int tolua_AllToLua_cPlayer_GetXpLifetimeTotal00(lua_State* tolua_S)
{ {
#ifndef TOLUA_RELEASE #ifndef TOLUA_RELEASE
tolua_Error tolua_err; tolua_Error tolua_err;
@ -7734,25 +7734,25 @@ static int tolua_AllToLua_cPlayer_XpGetTotal00(lua_State* tolua_S)
{ {
cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S,1,0); cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S,1,0);
#ifndef TOLUA_RELEASE #ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'XpGetTotal'", NULL); if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetXpLifetimeTotal'", NULL);
#endif #endif
{ {
int tolua_ret = (int) self->XpGetTotal(); short tolua_ret = (short) self->GetXpLifetimeTotal();
tolua_pushnumber(tolua_S,(lua_Number)tolua_ret); tolua_pushnumber(tolua_S,(lua_Number)tolua_ret);
} }
} }
return 1; return 1;
#ifndef TOLUA_RELEASE #ifndef TOLUA_RELEASE
tolua_lerror: tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'XpGetTotal'.",&tolua_err); tolua_error(tolua_S,"#ferror in function 'GetXpLifetimeTotal'.",&tolua_err);
return 0; return 0;
#endif #endif
} }
#endif //#ifndef TOLUA_DISABLE #endif //#ifndef TOLUA_DISABLE
/* method: XpGetLevel of class cPlayer */ /* method: GetCurrentXp of class cPlayer */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_XpGetLevel00 #ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_GetCurrentXp00
static int tolua_AllToLua_cPlayer_XpGetLevel00(lua_State* tolua_S) static int tolua_AllToLua_cPlayer_GetCurrentXp00(lua_State* tolua_S)
{ {
#ifndef TOLUA_RELEASE #ifndef TOLUA_RELEASE
tolua_Error tolua_err; tolua_Error tolua_err;
@ -7766,25 +7766,25 @@ static int tolua_AllToLua_cPlayer_XpGetLevel00(lua_State* tolua_S)
{ {
cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S,1,0); cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S,1,0);
#ifndef TOLUA_RELEASE #ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'XpGetLevel'", NULL); if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetCurrentXp'", NULL);
#endif #endif
{ {
int tolua_ret = (int) self->XpGetLevel(); short tolua_ret = (short) self->GetCurrentXp();
tolua_pushnumber(tolua_S,(lua_Number)tolua_ret); tolua_pushnumber(tolua_S,(lua_Number)tolua_ret);
} }
} }
return 1; return 1;
#ifndef TOLUA_RELEASE #ifndef TOLUA_RELEASE
tolua_lerror: tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'XpGetLevel'.",&tolua_err); tolua_error(tolua_S,"#ferror in function 'GetCurrentXp'.",&tolua_err);
return 0; return 0;
#endif #endif
} }
#endif //#ifndef TOLUA_DISABLE #endif //#ifndef TOLUA_DISABLE
/* method: XpGetPercentage of class cPlayer */ /* method: GetXpLevel of class cPlayer */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_XpGetPercentage00 #ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_GetXpLevel00
static int tolua_AllToLua_cPlayer_XpGetPercentage00(lua_State* tolua_S) static int tolua_AllToLua_cPlayer_GetXpLevel00(lua_State* tolua_S)
{ {
#ifndef TOLUA_RELEASE #ifndef TOLUA_RELEASE
tolua_Error tolua_err; tolua_Error tolua_err;
@ -7798,17 +7798,49 @@ static int tolua_AllToLua_cPlayer_XpGetPercentage00(lua_State* tolua_S)
{ {
cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S,1,0); cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S,1,0);
#ifndef TOLUA_RELEASE #ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'XpGetPercentage'", NULL); if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetXpLevel'", NULL);
#endif #endif
{ {
float tolua_ret = (float) self->XpGetPercentage(); short tolua_ret = (short) self->GetXpLevel();
tolua_pushnumber(tolua_S,(lua_Number)tolua_ret); tolua_pushnumber(tolua_S,(lua_Number)tolua_ret);
} }
} }
return 1; return 1;
#ifndef TOLUA_RELEASE #ifndef TOLUA_RELEASE
tolua_lerror: tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'XpGetPercentage'.",&tolua_err); tolua_error(tolua_S,"#ferror in function 'GetXpLevel'.",&tolua_err);
return 0;
#endif
}
#endif //#ifndef TOLUA_DISABLE
/* method: GetXpPercentage of class cPlayer */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_GetXpPercentage00
static int tolua_AllToLua_cPlayer_GetXpPercentage00(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
if (
!tolua_isusertype(tolua_S,1,"cPlayer",0,&tolua_err) ||
!tolua_isnoobj(tolua_S,2,&tolua_err)
)
goto tolua_lerror;
else
#endif
{
cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S,1,0);
#ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetXpPercentage'", NULL);
#endif
{
float tolua_ret = (float) self->GetXpPercentage();
tolua_pushnumber(tolua_S,(lua_Number)tolua_ret);
}
}
return 1;
#ifndef TOLUA_RELEASE
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'GetXpPercentage'.",&tolua_err);
return 0; return 0;
#endif #endif
} }
@ -30417,11 +30449,13 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_constant(tolua_S,"EATING_TICKS",cPlayer::EATING_TICKS); tolua_constant(tolua_S,"EATING_TICKS",cPlayer::EATING_TICKS);
tolua_constant(tolua_S,"MAX_AIR_LEVEL",cPlayer::MAX_AIR_LEVEL); tolua_constant(tolua_S,"MAX_AIR_LEVEL",cPlayer::MAX_AIR_LEVEL);
tolua_constant(tolua_S,"DROWNING_TICKS",cPlayer::DROWNING_TICKS); tolua_constant(tolua_S,"DROWNING_TICKS",cPlayer::DROWNING_TICKS);
tolua_function(tolua_S,"SetExperience",tolua_AllToLua_cPlayer_SetExperience00); tolua_constant(tolua_S,"MIN_EXPERIENCE",cPlayer::MIN_EXPERIENCE);
tolua_function(tolua_S,"AddExperience",tolua_AllToLua_cPlayer_AddExperience00); tolua_function(tolua_S,"SetCurrentExperience",tolua_AllToLua_cPlayer_SetCurrentExperience00);
tolua_function(tolua_S,"XpGetTotal",tolua_AllToLua_cPlayer_XpGetTotal00); tolua_function(tolua_S,"DeltaExperience",tolua_AllToLua_cPlayer_DeltaExperience00);
tolua_function(tolua_S,"XpGetLevel",tolua_AllToLua_cPlayer_XpGetLevel00); tolua_function(tolua_S,"GetXpLifetimeTotal",tolua_AllToLua_cPlayer_GetXpLifetimeTotal00);
tolua_function(tolua_S,"XpGetPercentage",tolua_AllToLua_cPlayer_XpGetPercentage00); tolua_function(tolua_S,"GetCurrentXp",tolua_AllToLua_cPlayer_GetCurrentXp00);
tolua_function(tolua_S,"GetXpLevel",tolua_AllToLua_cPlayer_GetXpLevel00);
tolua_function(tolua_S,"GetXpPercentage",tolua_AllToLua_cPlayer_GetXpPercentage00);
tolua_function(tolua_S,"GetEyeHeight",tolua_AllToLua_cPlayer_GetEyeHeight00); tolua_function(tolua_S,"GetEyeHeight",tolua_AllToLua_cPlayer_GetEyeHeight00);
tolua_function(tolua_S,"GetEyePosition",tolua_AllToLua_cPlayer_GetEyePosition00); tolua_function(tolua_S,"GetEyePosition",tolua_AllToLua_cPlayer_GetEyePosition00);
tolua_function(tolua_S,"IsOnGround",tolua_AllToLua_cPlayer_IsOnGround00); tolua_function(tolua_S,"IsOnGround",tolua_AllToLua_cPlayer_IsOnGround00);

View File

@ -1,6 +1,6 @@
/* /*
** Lua binding: AllToLua ** Lua binding: AllToLua
** Generated automatically by tolua++-1.0.92 on 11/15/13 10:14:20. ** Generated automatically by tolua++-1.0.92 on 11/16/13 21:58:48.
*/ */
/* Exported function */ /* Exported function */

View File

@ -260,6 +260,9 @@ void cClientHandle::Authenticate(void)
// Send health // Send health
m_Player->SendHealth(); m_Player->SendHealth();
// Send experience
m_Player->SendExperience();
// Send gamemode (1.6.1 movementSpeed): // Send gamemode (1.6.1 movementSpeed):
SendGameMode(m_Player->GetGameMode()); SendGameMode(m_Player->GetGameMode());
@ -1873,6 +1876,15 @@ void cClientHandle::SendRespawn(void)
void cClientHandle::SendExperience(void)
{
m_Protocol->SendExperience();
}
void cClientHandle::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) void cClientHandle::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch)
{ {
m_Protocol->SendSoundEffect(a_SoundName, a_SrcX, a_SrcY, a_SrcZ, a_Volume, a_Pitch); m_Protocol->SendSoundEffect(a_SoundName, a_SrcX, a_SrcY, a_SrcZ, a_Volume, a_Pitch);

View File

@ -120,6 +120,7 @@ public:
void SendPlayerPosition (void); void SendPlayerPosition (void);
void SendPlayerSpawn (const cPlayer & a_Player); void SendPlayerSpawn (const cPlayer & a_Player);
void SendRespawn (void); void SendRespawn (void);
void SendExperience (void);
void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch); // a_Src coords are Block * 8 void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch); // a_Src coords are Block * 8
void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data); void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data);
void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock); void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock);

View File

@ -66,7 +66,9 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName)
, m_EatingFinishTick(-1) , m_EatingFinishTick(-1)
, m_IsChargingBow(false) , m_IsChargingBow(false)
, m_BowCharge(0) , m_BowCharge(0)
, m_XpTotal(0) , m_CurrentXp(0)
, m_LifetimeTotalXp(0)
, m_bDirtyExperience(false)
{ {
LOGD("Created a player object for \"%s\" @ \"%s\" at %p, ID %d", LOGD("Created a player object for \"%s\" @ \"%s\" at %p, ID %d",
a_PlayerName.c_str(), a_Client->GetIPString().c_str(), a_PlayerName.c_str(), a_Client->GetIPString().c_str(),
@ -222,6 +224,12 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk)
{ {
m_BowCharge += 1; m_BowCharge += 1;
} }
//handle updating experience
if (m_bDirtyExperience)
{
SendExperience();
}
if (m_bDirtyPosition) if (m_bDirtyPosition)
{ {
@ -262,7 +270,7 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk)
int cPlayer::CalcLevelFromXp(int a_XpTotal) short cPlayer::CalcLevelFromXp(short a_XpTotal)
{ {
//level 0 to 15 //level 0 to 15
if(a_XpTotal <= XP_TO_LEVEL15) if(a_XpTotal <= XP_TO_LEVEL15)
@ -273,18 +281,18 @@ int cPlayer::CalcLevelFromXp(int a_XpTotal)
//level 30+ //level 30+
if(a_XpTotal > XP_TO_LEVEL30) if(a_XpTotal > XP_TO_LEVEL30)
{ {
return (int) (151.5 + sqrt( 22952.25 - (14 * (2220 - a_XpTotal)))) / 7; return (short) (151.5 + sqrt( 22952.25 - (14 * (2220 - a_XpTotal)))) / 7;
} }
//level 16 to 30 //level 16 to 30
return (int) ( 29.5 + sqrt( 870.25 - (6 * ( 360 - a_XpTotal )))) / 3; return (short) ( 29.5 + sqrt( 870.25 - (6 * ( 360 - a_XpTotal )))) / 3;
} }
int cPlayer::XpForLevel(int a_Level) short cPlayer::XpForLevel(short a_Level)
{ {
//level 0 to 15 //level 0 to 15
if(a_Level <= 15) if(a_Level <= 15)
@ -295,46 +303,51 @@ int cPlayer::XpForLevel(int a_Level)
//level 30+ //level 30+
if(a_Level >= 31) if(a_Level >= 31)
{ {
return (int) ( (3.5 * a_Level * a_Level) - (151.5 * a_Level) + 2220 ); return (short) ( (3.5 * a_Level * a_Level) - (151.5 * a_Level) + 2220 );
} }
//level 16 to 30 //level 16 to 30
return (int) ( (1.5 * a_Level * a_Level) - (29.5 * a_Level) + 360 ); return (short) ( (1.5 * a_Level * a_Level) - (29.5 * a_Level) + 360 );
} }
int cPlayer::XpGetLevel() short cPlayer::GetXpLevel()
{ {
return CalcLevelFromXp(m_XpTotal); return CalcLevelFromXp(m_CurrentXp);
} }
float cPlayer::XpGetPercentage() float cPlayer::GetXpPercentage()
{ {
int currentLevel = CalcLevelFromXp(m_XpTotal); short int currentLevel = CalcLevelFromXp(m_CurrentXp);
short int currentLevel_XpBase = XpForLevel(currentLevel);
return (float)m_XpTotal / (float)XpForLevel(1+currentLevel); return (float)(m_CurrentXp - currentLevel_XpBase) /
(float)(XpForLevel(1+currentLevel) - currentLevel_XpBase);
} }
bool cPlayer::SetExperience(int a_XpTotal) bool cPlayer::SetCurrentExperience(short int a_CurrentXp)
{ {
if(!(a_XpTotal >= 0) || (a_XpTotal > (INT_MAX - m_XpTotal))) if(!(a_CurrentXp >= 0) || (a_CurrentXp > (SHRT_MAX - m_LifetimeTotalXp)))
{ {
LOGWARNING("Tried to update experiece with an invalid Xp value: %d", a_XpTotal); LOGWARNING("Tried to update experiece with an invalid Xp value: %d", a_CurrentXp);
return false; //oops, they gave us a dodgey number return false; //oops, they gave us a dodgey number
} }
m_XpTotal = a_XpTotal; m_CurrentXp = a_CurrentXp;
// Set experience to be updated
m_bDirtyExperience = true;
return true; return true;
} }
@ -343,21 +356,38 @@ bool cPlayer::SetExperience(int a_XpTotal)
int cPlayer::AddExperience(int a_Xp_delta) short cPlayer::DeltaExperience(short a_Xp_delta)
{ {
if(a_Xp_delta < 0) //ToDo: figure out a better name?...
if(a_Xp_delta > (SHRT_MAX - m_LifetimeTotalXp))
{ {
//value was negative, abort and report // Value was bad, abort and report
LOGWARNING("Attempt was made to increment Xp by %d, must be positive", LOGWARNING("Attempt was made to increment Xp by %d, which was bad",
a_Xp_delta); a_Xp_delta);
return -1; //should we instead just return the current Xp? return -1; // Should we instead just return the current Xp?
} }
LOGD("Player \"%s\" earnt %d experience", m_PlayerName.c_str(), a_Xp_delta);
m_XpTotal += a_Xp_delta; m_CurrentXp += a_Xp_delta;
return m_XpTotal; // Make sure they didn't subtract too much
if(m_CurrentXp < MIN_EXPERIENCE)
{
m_CurrentXp = MIN_EXPERIENCE;
}
// Update total for score calculation
if(a_Xp_delta > 0)
{
m_LifetimeTotalXp += a_Xp_delta;
}
LOGD("Player \"%s\" gained/lost %d experience, total is now: %d",
m_PlayerName.c_str(), a_Xp_delta, m_CurrentXp);
// Set experience to be updated
m_bDirtyExperience = true;
return m_CurrentXp;
} }
@ -607,6 +637,19 @@ void cPlayer::SendHealth(void)
void cPlayer::SendExperience(void)
{
if (m_ClientHandle != NULL)
{
m_ClientHandle->SendExperience();
m_bDirtyExperience = false;
}
}
void cPlayer::ClearInventoryPaintSlots(void) void cPlayer::ClearInventoryPaintSlots(void)
{ {
// Clear the list of slots that are being inventory-painted. Used by cWindow only // Clear the list of slots that are being inventory-painted. Used by cWindow only
@ -759,6 +802,11 @@ void cPlayer::Respawn(void)
m_FoodLevel = MAX_FOOD_LEVEL; m_FoodLevel = MAX_FOOD_LEVEL;
m_FoodSaturationLevel = 5; m_FoodSaturationLevel = 5;
// Reset Experience
m_CurrentXp = MIN_EXPERIENCE;
m_LifetimeTotalXp = MIN_EXPERIENCE;
// ToDo: send score to client? How?
m_ClientHandle->SendRespawn(); m_ClientHandle->SendRespawn();
// Extinguish the fire: // Extinguish the fire:
@ -1411,14 +1459,16 @@ bool cPlayer::LoadFromDisk()
SetRoll ((float)JSON_PlayerRotation[(unsigned int)2].asDouble()); SetRoll ((float)JSON_PlayerRotation[(unsigned int)2].asDouble());
} }
m_Health = root.get("health", 0).asInt(); m_Health = root.get("health", 0).asInt();
m_AirLevel = root.get("air", MAX_AIR_LEVEL).asInt(); m_AirLevel = root.get("air", MAX_AIR_LEVEL).asInt();
m_FoodLevel = root.get("food", MAX_FOOD_LEVEL).asInt(); m_FoodLevel = root.get("food", MAX_FOOD_LEVEL).asInt();
m_FoodSaturationLevel = root.get("foodSaturation", MAX_FOOD_LEVEL).asDouble(); m_FoodSaturationLevel = root.get("foodSaturation", MAX_FOOD_LEVEL).asDouble();
m_FoodTickTimer = root.get("foodTickTimer", 0).asInt(); m_FoodTickTimer = root.get("foodTickTimer", 0).asInt();
m_FoodExhaustionLevel = root.get("foodExhaustion", 0).asDouble(); 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()); //SetExperience(root.get("experience", 0).asInt());
m_GameMode = (eGameMode) root.get("gamemode", eGameMode_NotSet).asInt(); m_GameMode = (eGameMode) root.get("gamemode", eGameMode_NotSet).asInt();
@ -1460,7 +1510,8 @@ bool cPlayer::SaveToDisk()
root["rotation"] = JSON_PlayerRotation; root["rotation"] = JSON_PlayerRotation;
root["inventory"] = JSON_Inventory; root["inventory"] = JSON_Inventory;
root["health"] = m_Health; root["health"] = m_Health;
root["experience"] = m_XpTotal; root["xpTotal"] = m_LifetimeTotalXp;
root["xpCurrent"] = m_CurrentXp;
root["air"] = m_AirLevel; root["air"] = m_AirLevel;
root["food"] = m_FoodLevel; root["food"] = m_FoodLevel;
root["foodSaturation"] = m_FoodSaturationLevel; root["foodSaturation"] = m_FoodSaturationLevel;

View File

@ -32,6 +32,7 @@ public:
EATING_TICKS = 30, ///< Number of ticks it takes to eat an item EATING_TICKS = 30, ///< Number of ticks it takes to eat an item
MAX_AIR_LEVEL = 300, MAX_AIR_LEVEL = 300,
DROWNING_TICKS = 10, //number of ticks per heart of damage DROWNING_TICKS = 10, //number of ticks per heart of damage
MIN_EXPERIENCE = 0,
} ; } ;
// tolua_end // tolua_end
@ -71,21 +72,25 @@ public:
Returns true on success Returns true on success
"should" really only be called at init or player death, plugins excepted "should" really only be called at init or player death, plugins excepted
*/ */
bool SetExperience(int a_XpTotal); bool SetCurrentExperience(short a_XpTotal);
/* Adds Xp, "should" not inc more than MAX_EXPERIENCE_ORB_SIZE unless you're a plugin being funny, *cough* cheating /* changes Xp by Xp_delta, you "shouldn't" inc more than MAX_EXPERIENCE_ORB_SIZE
Returns the new total experience, -1 on error Wont't allow xp to go negative
Returns the new current experience, -1 on error
*/ */
int AddExperience(int a_Xp_delta); short DeltaExperience(short a_Xp_delta);
/// Gets the experience total - XpTotal /// Gets the experience total - XpTotal for score on death
inline int XpGetTotal(void) { return m_XpTotal; } inline short GetXpLifetimeTotal(void) { return m_LifetimeTotalXp; }
/// Gets the currrent experience
inline short GetCurrentXp(void) { return m_CurrentXp; }
/// Gets the current level - XpLevel /// Gets the current level - XpLevel
int XpGetLevel(void); short GetXpLevel(void);
/// Gets the experience bar percentage - XpP /// Gets the experience bar percentage - XpP
float XpGetPercentage(void); float GetXpPercentage(void);
// tolua_end // tolua_end
@ -269,6 +274,8 @@ public:
void UseEquippedItem(void); void UseEquippedItem(void);
void SendHealth(void); void SendHealth(void);
void SendExperience(void);
// In UI windows, the item that the player is dragging: // In UI windows, the item that the player is dragging:
bool IsDraggingItem(void) const { return !m_DraggingItem.IsEmpty(); } bool IsDraggingItem(void) const { return !m_DraggingItem.IsEmpty(); }
@ -413,13 +420,17 @@ protected:
Int64 m_EatingFinishTick; Int64 m_EatingFinishTick;
/// Player Xp level /// Player Xp level
int m_XpTotal; short int m_LifetimeTotalXp;
short int m_CurrentXp;
// flag saying we need to send a xp update to client
bool m_bDirtyExperience;
/// Caculates the Xp needed for a given level, ref: http://minecraft.gamepedia.com/XP /// Caculates the Xp needed for a given level, ref: http://minecraft.gamepedia.com/XP
static int XpForLevel(int a_Level); static short XpForLevel(short int a_Level);
/// inverse of XpAtLevel, ref: http://minecraft.gamepedia.com/XP values are as per this with pre-calculations /// inverse of XpAtLevel, ref: http://minecraft.gamepedia.com/XP values are as per this with pre-calculations
static int CalcLevelFromXp(int a_XpTotal); static short CalcLevelFromXp(short int a_CurrentXp);
bool m_IsChargingBow; bool m_IsChargingBow;
int m_BowCharge; int m_BowCharge;

View File

@ -22,9 +22,9 @@ class cWindow;
class cInventory; class cInventory;
class cPawn; class cPawn;
class cPickup; class cPickup;
class cWorld;
class cMonster; class cMonster;
class cChunkDataSerializer; class cChunkDataSerializer;
class cWorld;
class cFallingBlock; class cFallingBlock;
@ -85,6 +85,7 @@ public:
virtual void SendPlayerPosition (void) = 0; virtual void SendPlayerPosition (void) = 0;
virtual void SendPlayerSpawn (const cPlayer & a_Player) = 0; virtual void SendPlayerSpawn (const cPlayer & a_Player) = 0;
virtual void SendRespawn (void) = 0; virtual void SendRespawn (void) = 0;
virtual void SendExperience (void) = 0;
virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) = 0; // a_Src coords are Block * 8 virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) = 0; // a_Src coords are Block * 8
virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) = 0; virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) = 0;
virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) = 0; virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) = 0;

View File

@ -72,6 +72,7 @@ enum
PACKET_ENT_STATUS = 0x26, PACKET_ENT_STATUS = 0x26,
PACKET_ATTACH_ENTITY = 0x27, PACKET_ATTACH_ENTITY = 0x27,
PACKET_METADATA = 0x28, PACKET_METADATA = 0x28,
PACKET_EXPERIENCE = 0x2b,
PACKET_PRE_CHUNK = 0x32, PACKET_PRE_CHUNK = 0x32,
PACKET_MAP_CHUNK = 0x33, PACKET_MAP_CHUNK = 0x33,
PACKET_MULTI_BLOCK = 0x34, PACKET_MULTI_BLOCK = 0x34,
@ -690,6 +691,20 @@ void cProtocol125::SendRespawn(void)
void cProtocol125::SendExperience(void)
{
cCSLock Lock(m_CSPacket);
WriteByte (PACKET_EXPERIENCE);
WriteFloat (m_Client->GetPlayer()->GetXpPercentage());
WriteShort (m_Client->GetPlayer()->GetXpLevel());
WriteShort (m_Client->GetPlayer()->GetCurrentXp());
Flush();
}
void cProtocol125::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) void cProtocol125::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch)
{ {
// Not needed in this protocol version // Not needed in this protocol version

View File

@ -62,6 +62,7 @@ public:
virtual void SendPlayerPosition (void) override; virtual void SendPlayerPosition (void) override;
virtual void SendPlayerSpawn (const cPlayer & a_Player) override; virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
virtual void SendRespawn (void) override; virtual void SendRespawn (void) override;
virtual void SendExperience (void) override;
virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; // a_Src coords are Block * 8 virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; // a_Src coords are Block * 8
virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override; virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override;
virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override; virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override;

View File

@ -597,6 +597,18 @@ void cProtocol172::SendRespawn(void)
void cProtocol172::SendExperience (void)
{
cPacketizer Pkt(*this, 0x1F); //Experience Packet
Pkt.WriteFloat(m_Client->GetPlayer()->GetXpPercentage());
Pkt.WriteShort(m_Client->GetPlayer()->GetXpLevel());
Pkt.WriteShort(m_Client->GetPlayer()->GetCurrentXp());
}
void cProtocol172::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) // a_Src coords are Block * 8 void cProtocol172::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) // a_Src coords are Block * 8
{ {
cPacketizer Pkt(*this, 0x29); // Sound Effect packet cPacketizer Pkt(*this, 0x29); // Sound Effect packet

View File

@ -72,6 +72,7 @@ public:
virtual void SendPlayerSpawn (const cPlayer & a_Player) override; virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
virtual void SendRespawn (void) override; virtual void SendRespawn (void) override;
virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; // a_Src coords are Block * 8 virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; // a_Src coords are Block * 8
virtual void SendExperience (void) override;
virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override; virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override;
virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override; virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override;
virtual void SendSpawnMob (const cMonster & a_Mob) override; virtual void SendSpawnMob (const cMonster & a_Mob) override;

View File

@ -466,6 +466,16 @@ void cProtocolRecognizer::SendRespawn(void)
void cProtocolRecognizer::SendExperience(void)
{
ASSERT(m_Protocol != NULL);
m_Protocol->SendExperience();
}
void cProtocolRecognizer::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) void cProtocolRecognizer::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch)
{ {
ASSERT(m_Protocol != NULL); ASSERT(m_Protocol != NULL);

View File

@ -97,6 +97,7 @@ public:
virtual void SendPlayerPosition (void) override; virtual void SendPlayerPosition (void) override;
virtual void SendPlayerSpawn (const cPlayer & a_Player) override; virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
virtual void SendRespawn (void) override; virtual void SendRespawn (void) override;
virtual void SendExperience (void) override;
virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override;
virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override; virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override;
virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override; virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override;