diff options
-rw-r--r-- | MCServer/Plugins/Debuggers/Debuggers.lua | 43 | ||||
-rw-r--r-- | source/Bindings.cpp | 374 | ||||
-rw-r--r-- | source/Bindings.h | 2 | ||||
-rw-r--r-- | source/ClientHandle.cpp | 28 | ||||
-rw-r--r-- | source/Player.cpp | 283 | ||||
-rw-r--r-- | source/Player.h | 62 | ||||
-rw-r--r-- | source/Protocol/Protocol125.cpp | 2 |
7 files changed, 646 insertions, 148 deletions
diff --git a/MCServer/Plugins/Debuggers/Debuggers.lua b/MCServer/Plugins/Debuggers/Debuggers.lua index e2124c079..e2523e63e 100644 --- a/MCServer/Plugins/Debuggers/Debuggers.lua +++ b/MCServer/Plugins/Debuggers/Debuggers.lua @@ -5,6 +5,8 @@ ShouldDumpFunctions = true; -- If set to true, all available functions are writ g_DropSpensersToActivate = {}; -- A list of dispensers and droppers (as {World, X, Y Z} quadruplets) that are to be activated every tick
+g_HungerReportTick = 10;
+
@@ -29,6 +31,8 @@ function Initialize(Plugin) PluginManager:BindCommand("/gc", "debuggers", HandleGCCmd, "Activates the Lua garbage collector");
PluginManager:BindCommand("/fast", "debuggers", HandleFastCmd, "Switches between fast and normal movement speed");
PluginManager:BindCommand("/dash", "debuggers", HandleDashCmd, "Switches between fast and normal sprinting speed");
+ PluginManager:BindCommand("/hunger", "debuggers", HandleHungerCmd, "Lists the current hunger-related variables");
+ PluginManager:BindCommand("/poison", "debuggers", HandlePoisonCmd, "Sets food-poisoning for 15 seconds");
-- Enable the following line for BlockArea / Generator interface testing:
-- PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHUNK_GENERATED);
@@ -480,6 +484,19 @@ function OnTick() GCOnTick = GCOnTick - 1;
end
+ --[[
+ if (g_HungerReportTick > 0) then
+ g_HungerReportTick = g_HungerReportTick - 1;
+ else
+ g_HungerReportTick = 10;
+ cRoot:Get():GetDefaultWorld():ForEachPlayer(
+ function(a_Player)
+ a_Player:SendMessage("FoodStat: " .. a_Player:GetFoodLevel() .. " / " .. a_Player:GetFoodExhaustionLevel());
+ end
+ );
+ end
+ ]]
+
return false;
end
@@ -502,6 +519,14 @@ end +function OnChat(a_Player, a_Message)
+ return false, "blabla " .. a_Message;
+end
+
+
+
+
+
-- Function "round" copied from http://lua-users.org/wiki/SimpleRound
function round(num, idp)
local mult = 10^(idp or 0)
@@ -669,8 +694,22 @@ end; -function OnChat(a_Player, a_Message)
- return false, "blabla " .. a_Message;
+function HandleHungerCmd(a_Split, a_Player)
+ a_Player:SendMessage("FoodLevel: " .. a_Player:GetFoodLevel());
+ a_Player:SendMessage("FoodSaturationLevel: " .. a_Player:GetFoodSaturationLevel());
+ a_Player:SendMessage("FoodTickTimer: " .. a_Player:GetFoodTickTimer());
+ a_Player:SendMessage("FoodExhaustionLevel: " .. a_Player:GetFoodExhaustionLevel());
+ a_Player:SendMessage("FoodPoisonedTicksRemaining: " .. a_Player:GetFoodPoisonedTicksRemaining());
+ return true;
+end
+
+
+
+
+
+function HandlePoisonCmd(a_Split, a_Player)
+ a_Player:FoodPoison(15 * 20);
+ return true;
end
diff --git a/source/Bindings.cpp b/source/Bindings.cpp index 72e82c25f..9333c7d16 100644 --- a/source/Bindings.cpp +++ b/source/Bindings.cpp @@ -1,6 +1,6 @@ /* ** Lua binding: AllToLua -** Generated automatically by tolua++-1.0.92 on 07/07/13 16:40:05. +** Generated automatically by tolua++-1.0.92 on 07/09/13 09:51:25. */ #ifndef __cplusplus @@ -6786,6 +6786,39 @@ static int tolua_AllToLua_cEntity_GetHealth00(lua_State* tolua_S) } #endif //#ifndef TOLUA_DISABLE +/* method: SetHealth of class cEntity */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cEntity_SetHealth00 +static int tolua_AllToLua_cEntity_SetHealth00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"cEntity",0,&tolua_err) || + !tolua_isnumber(tolua_S,2,0,&tolua_err) || + !tolua_isnoobj(tolua_S,3,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + cEntity* self = (cEntity*) tolua_tousertype(tolua_S,1,0); + int a_Health = ((int) tolua_tonumber(tolua_S,2,0)); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SetHealth'", NULL); +#endif + { + self->SetHealth(a_Health); + } + } + return 0; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'SetHealth'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + /* method: SetMaxHealth of class cEntity */ #ifndef TOLUA_DISABLE_tolua_AllToLua_cEntity_SetMaxHealth00 static int tolua_AllToLua_cEntity_SetMaxHealth00(lua_State* tolua_S) @@ -9111,165 +9144,362 @@ static int tolua_AllToLua_cPlayer_Heal00(lua_State* tolua_S) } #endif //#ifndef TOLUA_DISABLE -/* method: Feed of class cPlayer */ -#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_Feed00 -static int tolua_AllToLua_cPlayer_Feed00(lua_State* tolua_S) +/* method: GetFoodLevel of class cPlayer */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_GetFoodLevel00 +static int tolua_AllToLua_cPlayer_GetFoodLevel00(lua_State* tolua_S) { #ifndef TOLUA_RELEASE tolua_Error tolua_err; if ( - !tolua_isusertype(tolua_S,1,"cPlayer",0,&tolua_err) || - !tolua_isnumber(tolua_S,2,0,&tolua_err) || - !tolua_isnumber(tolua_S,3,0,&tolua_err) || - !tolua_isnoobj(tolua_S,4,&tolua_err) + !tolua_isusertype(tolua_S,1,"const 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); - short a_Food = ((short) tolua_tonumber(tolua_S,2,0)); - float a_Saturation = ((float) tolua_tonumber(tolua_S,3,0)); + const cPlayer* self = (const cPlayer*) tolua_tousertype(tolua_S,1,0); #ifndef TOLUA_RELEASE - if (!self) tolua_error(tolua_S,"invalid 'self' in function 'Feed'", NULL); + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetFoodLevel'", NULL); #endif { - bool tolua_ret = (bool) self->Feed(a_Food,a_Saturation); - tolua_pushboolean(tolua_S,(bool)tolua_ret); + int tolua_ret = (int) self->GetFoodLevel(); + tolua_pushnumber(tolua_S,(lua_Number)tolua_ret); } } return 1; #ifndef TOLUA_RELEASE tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'Feed'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'GetFoodLevel'.",&tolua_err); return 0; #endif } #endif //#ifndef TOLUA_DISABLE -/* method: GetMaxFoodLevel of class cPlayer */ -#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_GetMaxFoodLevel00 -static int tolua_AllToLua_cPlayer_GetMaxFoodLevel00(lua_State* tolua_S) +/* method: GetFoodSaturationLevel of class cPlayer */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_GetFoodSaturationLevel00 +static int tolua_AllToLua_cPlayer_GetFoodSaturationLevel00(lua_State* tolua_S) { #ifndef TOLUA_RELEASE tolua_Error tolua_err; if ( - !tolua_isusertype(tolua_S,1,"cPlayer",0,&tolua_err) || + !tolua_isusertype(tolua_S,1,"const 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); + const cPlayer* self = (const cPlayer*) tolua_tousertype(tolua_S,1,0); #ifndef TOLUA_RELEASE - if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetMaxFoodLevel'", NULL); + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetFoodSaturationLevel'", NULL); #endif { - short tolua_ret = (short) self->GetMaxFoodLevel(); + double tolua_ret = (double) self->GetFoodSaturationLevel(); tolua_pushnumber(tolua_S,(lua_Number)tolua_ret); } } return 1; #ifndef TOLUA_RELEASE tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'GetMaxFoodLevel'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'GetFoodSaturationLevel'.",&tolua_err); return 0; #endif } #endif //#ifndef TOLUA_DISABLE -/* method: GetFoodLevel of class cPlayer */ -#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_GetFoodLevel00 -static int tolua_AllToLua_cPlayer_GetFoodLevel00(lua_State* tolua_S) +/* method: GetFoodTickTimer of class cPlayer */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_GetFoodTickTimer00 +static int tolua_AllToLua_cPlayer_GetFoodTickTimer00(lua_State* tolua_S) { #ifndef TOLUA_RELEASE tolua_Error tolua_err; if ( - !tolua_isusertype(tolua_S,1,"cPlayer",0,&tolua_err) || + !tolua_isusertype(tolua_S,1,"const 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); + const cPlayer* self = (const cPlayer*) tolua_tousertype(tolua_S,1,0); #ifndef TOLUA_RELEASE - if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetFoodLevel'", NULL); + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetFoodTickTimer'", NULL); #endif { - short tolua_ret = (short) self->GetFoodLevel(); + int tolua_ret = (int) self->GetFoodTickTimer(); tolua_pushnumber(tolua_S,(lua_Number)tolua_ret); } } return 1; #ifndef TOLUA_RELEASE tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'GetFoodLevel'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'GetFoodTickTimer'.",&tolua_err); return 0; #endif } #endif //#ifndef TOLUA_DISABLE -/* method: GetMaxFoodSaturationLevel of class cPlayer */ -#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_GetMaxFoodSaturationLevel00 -static int tolua_AllToLua_cPlayer_GetMaxFoodSaturationLevel00(lua_State* tolua_S) +/* method: GetFoodExhaustionLevel of class cPlayer */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_GetFoodExhaustionLevel00 +static int tolua_AllToLua_cPlayer_GetFoodExhaustionLevel00(lua_State* tolua_S) { #ifndef TOLUA_RELEASE tolua_Error tolua_err; if ( - !tolua_isusertype(tolua_S,1,"cPlayer",0,&tolua_err) || + !tolua_isusertype(tolua_S,1,"const 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); + const cPlayer* self = (const cPlayer*) tolua_tousertype(tolua_S,1,0); #ifndef TOLUA_RELEASE - if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetMaxFoodSaturationLevel'", NULL); + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetFoodExhaustionLevel'", NULL); #endif { - float tolua_ret = (float) self->GetMaxFoodSaturationLevel(); + double tolua_ret = (double) self->GetFoodExhaustionLevel(); tolua_pushnumber(tolua_S,(lua_Number)tolua_ret); } } return 1; #ifndef TOLUA_RELEASE tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'GetMaxFoodSaturationLevel'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'GetFoodExhaustionLevel'.",&tolua_err); return 0; #endif } #endif //#ifndef TOLUA_DISABLE -/* method: GetFoodSaturationLevel of class cPlayer */ -#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_GetFoodSaturationLevel00 -static int tolua_AllToLua_cPlayer_GetFoodSaturationLevel00(lua_State* tolua_S) +/* method: GetFoodPoisonedTicksRemaining of class cPlayer */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_GetFoodPoisonedTicksRemaining00 +static int tolua_AllToLua_cPlayer_GetFoodPoisonedTicksRemaining00(lua_State* tolua_S) { #ifndef TOLUA_RELEASE tolua_Error tolua_err; if ( - !tolua_isusertype(tolua_S,1,"cPlayer",0,&tolua_err) || + !tolua_isusertype(tolua_S,1,"const 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); + const cPlayer* self = (const cPlayer*) tolua_tousertype(tolua_S,1,0); #ifndef TOLUA_RELEASE - if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetFoodSaturationLevel'", NULL); + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetFoodPoisonedTicksRemaining'", NULL); #endif { - float tolua_ret = (float) self->GetFoodSaturationLevel(); + int tolua_ret = (int) self->GetFoodPoisonedTicksRemaining(); tolua_pushnumber(tolua_S,(lua_Number)tolua_ret); } } return 1; #ifndef TOLUA_RELEASE tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'GetFoodSaturationLevel'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'GetFoodPoisonedTicksRemaining'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + +/* method: SetFoodLevel of class cPlayer */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_SetFoodLevel00 +static int tolua_AllToLua_cPlayer_SetFoodLevel00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"cPlayer",0,&tolua_err) || + !tolua_isnumber(tolua_S,2,0,&tolua_err) || + !tolua_isnoobj(tolua_S,3,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S,1,0); + int a_FoodLevel = ((int) tolua_tonumber(tolua_S,2,0)); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SetFoodLevel'", NULL); +#endif + { + self->SetFoodLevel(a_FoodLevel); + } + } + return 0; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'SetFoodLevel'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + +/* method: SetFoodSaturationLevel of class cPlayer */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_SetFoodSaturationLevel00 +static int tolua_AllToLua_cPlayer_SetFoodSaturationLevel00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"cPlayer",0,&tolua_err) || + !tolua_isnumber(tolua_S,2,0,&tolua_err) || + !tolua_isnoobj(tolua_S,3,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S,1,0); + double a_FoodSaturationLevel = ((double) tolua_tonumber(tolua_S,2,0)); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SetFoodSaturationLevel'", NULL); +#endif + { + self->SetFoodSaturationLevel(a_FoodSaturationLevel); + } + } + return 0; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'SetFoodSaturationLevel'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + +/* method: SetFoodTickTimer of class cPlayer */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_SetFoodTickTimer00 +static int tolua_AllToLua_cPlayer_SetFoodTickTimer00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"cPlayer",0,&tolua_err) || + !tolua_isnumber(tolua_S,2,0,&tolua_err) || + !tolua_isnoobj(tolua_S,3,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S,1,0); + int a_FoodTickTimer = ((int) tolua_tonumber(tolua_S,2,0)); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SetFoodTickTimer'", NULL); +#endif + { + self->SetFoodTickTimer(a_FoodTickTimer); + } + } + return 0; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'SetFoodTickTimer'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + +/* method: SetFoodExhaustionLevel of class cPlayer */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_SetFoodExhaustionLevel00 +static int tolua_AllToLua_cPlayer_SetFoodExhaustionLevel00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"cPlayer",0,&tolua_err) || + !tolua_isnumber(tolua_S,2,0,&tolua_err) || + !tolua_isnoobj(tolua_S,3,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S,1,0); + double a_FoodSaturationLevel = ((double) tolua_tonumber(tolua_S,2,0)); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SetFoodExhaustionLevel'", NULL); +#endif + { + self->SetFoodExhaustionLevel(a_FoodSaturationLevel); + } + } + return 0; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'SetFoodExhaustionLevel'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + +/* method: SetFoodPoisonedTicksRemaining of class cPlayer */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_SetFoodPoisonedTicksRemaining00 +static int tolua_AllToLua_cPlayer_SetFoodPoisonedTicksRemaining00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"cPlayer",0,&tolua_err) || + !tolua_isnumber(tolua_S,2,0,&tolua_err) || + !tolua_isnoobj(tolua_S,3,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S,1,0); + int a_FoodPoisonedTicksRemaining = ((int) tolua_tonumber(tolua_S,2,0)); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SetFoodPoisonedTicksRemaining'", NULL); +#endif + { + self->SetFoodPoisonedTicksRemaining(a_FoodPoisonedTicksRemaining); + } + } + return 0; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'SetFoodPoisonedTicksRemaining'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + +/* method: Feed of class cPlayer */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_Feed00 +static int tolua_AllToLua_cPlayer_Feed00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"cPlayer",0,&tolua_err) || + !tolua_isnumber(tolua_S,2,0,&tolua_err) || + !tolua_isnumber(tolua_S,3,0,&tolua_err) || + !tolua_isnoobj(tolua_S,4,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S,1,0); + int a_Food = ((int) tolua_tonumber(tolua_S,2,0)); + double a_Saturation = ((double) tolua_tonumber(tolua_S,3,0)); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'Feed'", NULL); +#endif + { + bool tolua_ret = (bool) self->Feed(a_Food,a_Saturation); + tolua_pushboolean(tolua_S,(bool)tolua_ret); + } + } + return 1; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'Feed'.",&tolua_err); return 0; #endif } @@ -9291,7 +9521,7 @@ static int tolua_AllToLua_cPlayer_AddFoodExhaustion00(lua_State* tolua_S) #endif { cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S,1,0); - float a_Exhaustion = ((float) tolua_tonumber(tolua_S,2,0)); + double a_Exhaustion = ((double) tolua_tonumber(tolua_S,2,0)); #ifndef TOLUA_RELEASE if (!self) tolua_error(tolua_S,"invalid 'self' in function 'AddFoodExhaustion'", NULL); #endif @@ -9308,6 +9538,39 @@ static int tolua_AllToLua_cPlayer_AddFoodExhaustion00(lua_State* tolua_S) } #endif //#ifndef TOLUA_DISABLE +/* method: FoodPoison of class cPlayer */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_FoodPoison00 +static int tolua_AllToLua_cPlayer_FoodPoison00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"cPlayer",0,&tolua_err) || + !tolua_isnumber(tolua_S,2,0,&tolua_err) || + !tolua_isnoobj(tolua_S,3,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S,1,0); + int a_NumTicks = ((int) tolua_tonumber(tolua_S,2,0)); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'FoodPoison'", NULL); +#endif + { + self->FoodPoison(a_NumTicks); + } + } + return 0; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'FoodPoison'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + /* method: Respawn of class cPlayer */ #ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_Respawn00 static int tolua_AllToLua_cPlayer_Respawn00(lua_State* tolua_S) @@ -28519,6 +28782,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S) tolua_function(tolua_S,"KilledBy",tolua_AllToLua_cEntity_KilledBy00); tolua_function(tolua_S,"Heal",tolua_AllToLua_cEntity_Heal00); tolua_function(tolua_S,"GetHealth",tolua_AllToLua_cEntity_GetHealth00); + tolua_function(tolua_S,"SetHealth",tolua_AllToLua_cEntity_SetHealth00); tolua_function(tolua_S,"SetMaxHealth",tolua_AllToLua_cEntity_SetMaxHealth00); tolua_function(tolua_S,"GetMaxHealth",tolua_AllToLua_cEntity_GetMaxHealth00); tolua_function(tolua_S,"StartBurning",tolua_AllToLua_cEntity_StartBurning00); @@ -28560,6 +28824,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S) tolua_cclass(tolua_S,"cPlayer","cPlayer","cPawn",NULL); tolua_beginmodule(tolua_S,"cPlayer"); tolua_constant(tolua_S,"MAX_HEALTH",cPlayer::MAX_HEALTH); + tolua_constant(tolua_S,"MAX_FOOD_LEVEL",cPlayer::MAX_FOOD_LEVEL); tolua_function(tolua_S,"Initialize",tolua_AllToLua_cPlayer_Initialize00); tolua_function(tolua_S,"GetEyeHeight",tolua_AllToLua_cPlayer_GetEyeHeight00); tolua_function(tolua_S,"GetEyePosition",tolua_AllToLua_cPlayer_GetEyePosition00); @@ -28590,12 +28855,19 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S) tolua_function(tolua_S,"GetColor",tolua_AllToLua_cPlayer_GetColor00); tolua_function(tolua_S,"TossItem",tolua_AllToLua_cPlayer_TossItem00); tolua_function(tolua_S,"Heal",tolua_AllToLua_cPlayer_Heal00); - tolua_function(tolua_S,"Feed",tolua_AllToLua_cPlayer_Feed00); - tolua_function(tolua_S,"GetMaxFoodLevel",tolua_AllToLua_cPlayer_GetMaxFoodLevel00); tolua_function(tolua_S,"GetFoodLevel",tolua_AllToLua_cPlayer_GetFoodLevel00); - tolua_function(tolua_S,"GetMaxFoodSaturationLevel",tolua_AllToLua_cPlayer_GetMaxFoodSaturationLevel00); tolua_function(tolua_S,"GetFoodSaturationLevel",tolua_AllToLua_cPlayer_GetFoodSaturationLevel00); + tolua_function(tolua_S,"GetFoodTickTimer",tolua_AllToLua_cPlayer_GetFoodTickTimer00); + tolua_function(tolua_S,"GetFoodExhaustionLevel",tolua_AllToLua_cPlayer_GetFoodExhaustionLevel00); + tolua_function(tolua_S,"GetFoodPoisonedTicksRemaining",tolua_AllToLua_cPlayer_GetFoodPoisonedTicksRemaining00); + tolua_function(tolua_S,"SetFoodLevel",tolua_AllToLua_cPlayer_SetFoodLevel00); + tolua_function(tolua_S,"SetFoodSaturationLevel",tolua_AllToLua_cPlayer_SetFoodSaturationLevel00); + tolua_function(tolua_S,"SetFoodTickTimer",tolua_AllToLua_cPlayer_SetFoodTickTimer00); + tolua_function(tolua_S,"SetFoodExhaustionLevel",tolua_AllToLua_cPlayer_SetFoodExhaustionLevel00); + tolua_function(tolua_S,"SetFoodPoisonedTicksRemaining",tolua_AllToLua_cPlayer_SetFoodPoisonedTicksRemaining00); + tolua_function(tolua_S,"Feed",tolua_AllToLua_cPlayer_Feed00); tolua_function(tolua_S,"AddFoodExhaustion",tolua_AllToLua_cPlayer_AddFoodExhaustion00); + tolua_function(tolua_S,"FoodPoison",tolua_AllToLua_cPlayer_FoodPoison00); tolua_function(tolua_S,"Respawn",tolua_AllToLua_cPlayer_Respawn00); tolua_function(tolua_S,"SetVisible",tolua_AllToLua_cPlayer_SetVisible00); tolua_function(tolua_S,"IsVisible",tolua_AllToLua_cPlayer_IsVisible00); diff --git a/source/Bindings.h b/source/Bindings.h index ec9ded740..a3a399bbc 100644 --- a/source/Bindings.h +++ b/source/Bindings.h @@ -1,6 +1,6 @@ /* ** Lua binding: AllToLua -** Generated automatically by tolua++-1.0.92 on 07/07/13 16:40:06. +** Generated automatically by tolua++-1.0.92 on 07/09/13 09:51:26. */ /* Exported function */ diff --git a/source/ClientHandle.cpp b/source/ClientHandle.cpp index 52f3b92ed..155eac38a 100644 --- a/source/ClientHandle.cpp +++ b/source/ClientHandle.cpp @@ -501,6 +501,13 @@ void cClientHandle::HandlePlayerPos(double a_PosX, double a_PosY, double a_PosZ, SendPlayerMoveLook(); return; } + + // If a jump just started, process food exhaustion: + if ((a_PosY > m_Player->GetPosY()) && !a_IsOnGround && m_Player->IsOnGround()) + { + m_Player->AddFoodExhaustion(m_Player->IsSprinting() ? 0.8 : 0.2); + } + m_Player->MoveTo(Pos); m_Player->SetStance(a_Stance); m_Player->SetTouchGround(a_IsOnGround); @@ -1054,6 +1061,7 @@ void cClientHandle::HandleUseEntity(int a_TargetEntityID, bool a_IsLeftClick) { // TODO: Let plugins interfere via a hook + // If it is a right click, call the entity's OnRightClicked() handler: if (!a_IsLeftClick) { class cRclkEntity : public cEntityCallback @@ -1062,7 +1070,7 @@ void cClientHandle::HandleUseEntity(int a_TargetEntityID, bool a_IsLeftClick) virtual bool Item(cEntity * a_Entity) override { a_Entity->OnRightClicked(m_Player); - return true; + return false; } public: cRclkEntity(cPlayer & a_Player) : m_Player(a_Player) {} @@ -1073,24 +1081,22 @@ void cClientHandle::HandleUseEntity(int a_TargetEntityID, bool a_IsLeftClick) return; } + // If it is a left click, attack the entity: class cDamageEntity : public cEntityCallback { virtual bool Item(cEntity * a_Entity) override { if (!a_Entity->GetWorld()->IsPVPEnabled()) { - // PVP is disabled - if (a_Entity->IsA("cPlayer") && m_Attacker->IsA("cPlayer")) + // PVP is disabled, disallow players hurting other players: + if (a_Entity->IsPlayer()) { // Player is hurting another player which is not allowed when PVP is disabled so ignore it return true; } } - if (a_Entity->IsA("cPawn")) - { - reinterpret_cast<cPawn *>(a_Entity)->TakeDamage(*m_Attacker); - } - return true; + a_Entity->TakeDamage(*m_Attacker); + return false; } public: cPawn * m_Attacker; @@ -1099,7 +1105,11 @@ void cClientHandle::HandleUseEntity(int a_TargetEntityID, bool a_IsLeftClick) Callback.m_Attacker = m_Player; cWorld * World = m_Player->GetWorld(); - World->DoWithEntityByID(a_TargetEntityID, Callback); + if (World->DoWithEntityByID(a_TargetEntityID, Callback)) + { + // Any kind of an attack implies food exhaustion + m_Player->AddFoodExhaustion(0.3); + } } diff --git a/source/Player.cpp b/source/Player.cpp index 35c0dcb83..c122f95dd 100644 --- a/source/Player.cpp +++ b/source/Player.cpp @@ -19,6 +19,7 @@ #include "OSSupport/MakeDir.h" #include "OSSupport/Timer.h" #include "MersenneTwister.h" +#include "Chunk.h" #include "Vector3d.h" #include "Vector3f.h" @@ -48,8 +49,11 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName) , m_TimeLastPickupCheck( 0.f ) , m_Color('-') , m_ClientHandle( a_Client ) - , m_FoodExhaustionLevel(0.f) + , m_FoodLevel(20) + , m_FoodSaturationLevel(5) , m_FoodTickTimer(0) + , m_FoodExhaustionLevel(0) + , m_FoodPoisonedTicksRemaining(0) , m_NormalMaxSpeed(0.1) , m_SprintingMaxSpeed(0.13) , m_IsCrouched(false) @@ -66,12 +70,6 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName) SetMaxHealth(20); - m_MaxFoodLevel = 20; - m_MaxFoodSaturationLevel = 20.f; - - m_FoodLevel = m_MaxFoodLevel; - m_FoodSaturationLevel = 5.f; - cTimer t1; m_LastPlayerListTime = t1.GetNowTime(); @@ -175,6 +173,9 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk) super::Tick(a_Dt, a_Chunk); if (m_bDirtyPosition) { + // Apply food exhaustion from movement: + ApplyFoodExhaustionFromMovement(a_Chunk); + cRoot::Get()->GetPluginManager()->CallHookPlayerMoving(*this); BroadcastMovementUpdate(m_ClientHandle); m_ClientHandle->StreamChunks(); @@ -184,46 +185,15 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk) BroadcastMovementUpdate(m_ClientHandle); } - if (m_Health > 0) // make sure player is alive + if (m_Health > 0) // make sure player is alive { m_World->CollectPickupsByPlayer(this); - // Handle Health: - m_FoodTickTimer++; - if (m_FoodTickTimer >= 80) - { - m_FoodTickTimer = 0; - - if (m_FoodLevel >= 17) - { - Heal(1); - } - else if (m_FoodLevel == 0) - { - TakeDamage(dtStarving, NULL, 1, 1, 0); - } - } - - // TODO: Increase Exhaustion level http://www.minecraftwiki.net/wiki/Hunger#Exhaustion_level_increase - if (m_FoodExhaustionLevel >= 4.f) - { - m_FoodExhaustionLevel -= 4.f; - - if (m_FoodSaturationLevel >= 1.f) - { - m_FoodSaturationLevel--; - } - else - { - m_FoodLevel = std::max(m_FoodLevel - 1, 0); - } - - SendHealth(); - } + HandleFood(); } - cTimer t1; // Send Player List (Once per m_LastPlayerListTime/1000 ms) + cTimer t1; if (m_LastPlayerListTime + cPlayer::PLAYER_LIST_TIME_MS <= t1.GetNowTime()) { m_World->SendPlayerList(this); @@ -237,6 +207,7 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk) void cPlayer::SetTouchGround(bool a_bTouchGround) { + // If just m_bTouchGround = a_bTouchGround; if (!m_bTouchGround) @@ -299,15 +270,61 @@ void cPlayer::Heal(int a_Health) -bool cPlayer::Feed(short a_Food, float a_Saturation) +void cPlayer::SetFoodLevel(int a_FoodLevel) +{ + m_FoodLevel = std::max(0, std::min(a_FoodLevel, (int)MAX_FOOD_LEVEL)); + SendHealth(); +} + + + + + +void cPlayer::SetFoodSaturationLevel(double a_FoodSaturationLevel) +{ + m_FoodSaturationLevel = std::max(0.0, std::min(a_FoodSaturationLevel, (double)m_FoodLevel)); +} + + + + + +void cPlayer::SetFoodTickTimer(int a_FoodTickTimer) +{ + m_FoodTickTimer = a_FoodTickTimer; +} + + + + + +void cPlayer::SetFoodExhaustionLevel(double a_FoodSaturationLevel) +{ + m_FoodExhaustionLevel = std::max(0.0, std::min(a_FoodSaturationLevel, 4.0)); +} + + + + + +void cPlayer::SetFoodPoisonedTicksRemaining(int a_FoodPoisonedTicksRemaining) { - if (m_FoodLevel >= GetMaxFoodLevel()) + m_FoodPoisonedTicksRemaining = a_FoodPoisonedTicksRemaining; +} + + + + + +bool cPlayer::Feed(int a_Food, double a_Saturation) +{ + if (m_FoodLevel >= MAX_FOOD_LEVEL) { return false; } - m_FoodLevel = std::min((short)(a_Food + m_FoodLevel), GetMaxFoodLevel()); - m_FoodSaturationLevel = std::min(m_FoodSaturationLevel + a_Saturation, GetMaxFoodSaturationLevel()); + m_FoodLevel = std::min(a_Food + m_FoodLevel, (int)MAX_FOOD_LEVEL); + m_FoodSaturationLevel = std::min(m_FoodSaturationLevel + a_Saturation, (double)m_FoodLevel); SendHealth(); return true; @@ -317,7 +334,22 @@ bool cPlayer::Feed(short a_Food, float a_Saturation) -void cPlayer::SendHealth() +void cPlayer::FoodPoison(int a_NumTicks) +{ + bool HasBeenFoodPoisoned = (m_FoodPoisonedTicksRemaining > 0); + m_FoodPoisonedTicksRemaining = std::max(m_FoodPoisonedTicksRemaining, a_NumTicks); + if (!HasBeenFoodPoisoned) + { + // TODO: Send the poisoning indication to the client - how? + SendHealth(); + } +} + + + + + +void cPlayer::SendHealth(void) { if (m_ClientHandle != NULL) { @@ -437,11 +469,8 @@ void cPlayer::DoTakeDamage(TakeDamageInfo & a_TDI) super::DoTakeDamage(a_TDI); - if (a_TDI.Attacker != NULL) - { - // Only increase hunger if being attacked by a mob - AddFoodExhaustion(0.3f); - } + // Any kind of damage adds food exhaustion + AddFoodExhaustion(0.3f); SendHealth(); } @@ -1034,13 +1063,14 @@ bool cPlayer::LoadFromDisk() cFile f; if (!f.Open(SourceFile, cFile::fmRead)) { + LOGWARNING("Cannot open player data file \"%s\" for reading", SourceFile.c_str()); return false; } AString buffer; if (f.ReadRestOfFile(buffer) != f.GetSize()) { - LOGERROR("ERROR READING FROM FILE \"%s\"", SourceFile.c_str()); + LOGWARNING("Cannot read player data from file \"%s\"", SourceFile.c_str()); return false; } f.Close(); @@ -1049,7 +1079,7 @@ bool cPlayer::LoadFromDisk() Json::Reader reader; if (!reader.parse(buffer, root, false)) { - LOGERROR("ERROR WHILE PARSING JSON FROM FILE %s", SourceFile.c_str()); + LOGWARNING("Cannot parse player data in file \"%s\", player will be reset", SourceFile.c_str()); } Json::Value & JSON_PlayerPosition = root["position"]; @@ -1058,6 +1088,10 @@ bool cPlayer::LoadFromDisk() 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"]; @@ -1068,9 +1102,12 @@ bool cPlayer::LoadFromDisk() SetRoll ((float)JSON_PlayerRotation[(unsigned int)2].asDouble()); } - m_Health = (short)root.get("health", 0 ).asInt(); - m_FoodLevel = (short)root.get("food", m_MaxFoodLevel ).asInt(); - m_FoodSaturationLevel = (float)root.get("foodSaturation", m_MaxFoodSaturationLevel ).asDouble(); + m_Health = root.get("health", 0).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_GameMode = (eGameMode) root.get("gamemode", eGameMode_NotSet).asInt(); @@ -1095,25 +1132,27 @@ bool cPlayer::SaveToDisk() // create the JSON data Json::Value JSON_PlayerPosition; - JSON_PlayerPosition.append( Json::Value( GetPosX() ) ); - JSON_PlayerPosition.append( Json::Value( GetPosY() ) ); - JSON_PlayerPosition.append( Json::Value( GetPosZ() ) ); + JSON_PlayerPosition.append(Json::Value(GetPosX())); + JSON_PlayerPosition.append(Json::Value(GetPosY())); + JSON_PlayerPosition.append(Json::Value(GetPosZ())); Json::Value JSON_PlayerRotation; - JSON_PlayerRotation.append( Json::Value( GetRotation() ) ); - JSON_PlayerRotation.append( Json::Value( GetPitch() ) ); - JSON_PlayerRotation.append( Json::Value( GetRoll() ) ); + JSON_PlayerRotation.append(Json::Value(GetRotation())); + JSON_PlayerRotation.append(Json::Value(GetPitch())); + JSON_PlayerRotation.append(Json::Value(GetRoll())); Json::Value JSON_Inventory; - m_Inventory.SaveToJson( JSON_Inventory ); + m_Inventory.SaveToJson(JSON_Inventory); Json::Value root; - root["position"] = JSON_PlayerPosition; - root["rotation"] = JSON_PlayerRotation; - root["inventory"] = JSON_Inventory; - root["health"] = m_Health; - root["food"] = m_FoodLevel; + root["position"] = JSON_PlayerPosition; + root["rotation"] = JSON_PlayerRotation; + root["inventory"] = JSON_Inventory; + root["health"] = m_Health; + root["food"] = m_FoodLevel; root["foodSaturation"] = m_FoodSaturationLevel; + root["foodTickTimer"] = m_FoodTickTimer; + root["foodExhaustion"] = m_FoodExhaustionLevel; root["world"] = GetWorld()->GetName(); if (m_GameMode == GetWorld()->GetGameMode()) @@ -1126,7 +1165,7 @@ bool cPlayer::SaveToDisk() } Json::StyledWriter writer; - std::string JsonData = writer.write( root ); + std::string JsonData = writer.write(root); AString SourceFile; Printf(SourceFile, "players/%s.json", m_PlayerName.c_str() ); @@ -1179,3 +1218,109 @@ void cPlayer::UseEquippedItem() + +void cPlayer::HandleFood(void) +{ + // Ref.: http://www.minecraftwiki.net/wiki/Hunger + + // Remember the food level before processing, for later comparison + int LastFoodLevel = m_FoodLevel; + + // Heal or damage, based on the food level, using the m_FoodTickTimer: + if ((m_FoodLevel > 17) || (m_FoodLevel <= 0)) + { + m_FoodTickTimer++; + if (m_FoodTickTimer >= 80) + { + m_FoodTickTimer = 0; + + if (m_FoodLevel >= 17) + { + // Regenerate health from food, incur 3 pts of food exhaustion: + Heal(1); + m_FoodExhaustionLevel += 3; + } + else if (m_FoodLevel <= 0) + { + // Damage from starving + TakeDamage(dtStarving, NULL, 1, 1, 0); + } + } + } + + // Apply food poisoning food exhaustion: + if (m_FoodPoisonedTicksRemaining > 0) + { + m_FoodPoisonedTicksRemaining--; + m_FoodExhaustionLevel += 0.025; // 0.5 per second = 0.025 per tick + } + + // Apply food exhaustion that has accumulated: + if (m_FoodExhaustionLevel >= 4) + { + m_FoodExhaustionLevel -= 4; + + if (m_FoodSaturationLevel >= 1) + { + m_FoodSaturationLevel -= 1; + } + else + { + m_FoodLevel = std::max(m_FoodLevel - 1, 0); + } + } + + if (m_FoodLevel != LastFoodLevel) + { + SendHealth(); + } +} + + + + + +void cPlayer::ApplyFoodExhaustionFromMovement(cChunk & a_Chunk) +{ + // Calculate the distance travelled, update the last pos: + Vector3d Movement(GetPosition() - m_LastFoodPos); + m_LastFoodPos = GetPosition(); + + // If riding anything, apply no food exhaustion + if (m_AttachedTo != NULL) + { + return; + } + + // Get the type of block the player's standing in: + BLOCKTYPE BlockIn; + int RelX = (int)floor(m_LastPosX) - a_Chunk.GetPosX() * cChunkDef::Width; + int RelY = (int)floor(m_LastPosY + 0.1); + int RelZ = (int)floor(m_LastPosZ) - a_Chunk.GetPosZ() * cChunkDef::Width; + // Use Unbounded, because we're being called *after* processing super::Tick(), which could have changed our chunk + VERIFY(a_Chunk.UnboundedRelGetBlockType(RelX, RelY, RelZ, BlockIn)); + + // Apply the exhaustion based on distance travelled: + double BaseExhaustion = Movement.Length(); + LOGD("Movement: %.03f m", BaseExhaustion); + if (IsSprinting()) + { + // 0.1 pt per meter sprinted + BaseExhaustion = BaseExhaustion * 0.1; + } + else if (IsBlockWater(BlockIn)) + { + // 0.015 pt per meter swum + BaseExhaustion = BaseExhaustion * 0.015; + } + else + { + // 0.01 pt per meter walked / sneaked + BaseExhaustion = BaseExhaustion * 0.01; + } + m_FoodExhaustionLevel += BaseExhaustion; +} + + + + diff --git a/source/Player.h b/source/Player.h index ea293297a..fed222157 100644 --- a/source/Player.h +++ b/source/Player.h @@ -27,6 +27,7 @@ public: enum { MAX_HEALTH = 20, + MAX_FOOD_LEVEL = 20, } ; // tolua_end @@ -127,16 +128,30 @@ public: void Heal( int a_Health ); // tolua_export - /// Returns true if any food has been consumed, false if player "full" - bool Feed(short a_Food, float a_Saturation); // tolua_export - - short GetMaxFoodLevel() { return m_MaxFoodLevel; } // tolua_export - short GetFoodLevel() { return m_FoodLevel; } // tolua_export + // tolua_begin + + int GetFoodLevel (void) const { return m_FoodLevel; } + double GetFoodSaturationLevel (void) const { return m_FoodSaturationLevel; } + int GetFoodTickTimer (void) const { return m_FoodTickTimer; } + double GetFoodExhaustionLevel (void) const { return m_FoodExhaustionLevel; } + int GetFoodPoisonedTicksRemaining(void) const { return m_FoodPoisonedTicksRemaining; } + + void SetFoodLevel (int a_FoodLevel); + void SetFoodSaturationLevel (double a_FoodSaturationLevel); + void SetFoodTickTimer (int a_FoodTickTimer); + void SetFoodExhaustionLevel (double a_FoodSaturationLevel); + void SetFoodPoisonedTicksRemaining(int a_FoodPoisonedTicksRemaining); - float GetMaxFoodSaturationLevel() { return m_MaxFoodSaturationLevel; } // tolua_export - float GetFoodSaturationLevel() { return m_FoodSaturationLevel; } // tolua_export + /// Adds to FoodLevel and FoodSaturationLevel, returns true if any food has been consumed, false if player "full" + bool Feed(int a_Food, double a_Saturation); - void AddFoodExhaustion(float a_Exhaustion) { m_FoodExhaustionLevel += a_Exhaustion; } // tolua_export + /// Adds the specified exhaustion to m_FoodExhaustion. Expects only positive values. + void AddFoodExhaustion(double a_Exhaustion) { m_FoodExhaustionLevel += a_Exhaustion; } + + /// Starts the food poisoning for the specified amount of ticks; if already foodpoisoned, sets FoodPoisonedTicksRemaining to the larger of the two + void FoodPoison(int a_NumTicks); + + // tolua_end virtual void KilledBy(cEntity * a_Killer) override; @@ -213,13 +228,25 @@ protected: bool m_bVisible; - short m_FoodLevel; - short m_MaxFoodLevel; - float m_FoodSaturationLevel; - float m_MaxFoodSaturationLevel; - float m_FoodExhaustionLevel; - char m_FoodTickTimer; - + // Food-related variables: + /// Represents the food bar, one point equals half a "drumstick" + int m_FoodLevel; + + /// "Overcharge" for the m_FoodLevel; is depleted before m_FoodLevel + double m_FoodSaturationLevel; + + /// Count-up to the healing or damaging action, based on m_FoodLevel + int m_FoodTickTimer; + + /// A "buffer" which adds up hunger before it is substracted from m_FoodSaturationLevel or m_FoodLevel. Each action adds a little + double m_FoodExhaustionLevel; + + /// Number of ticks remaining for the foodpoisoning effect; zero if not foodpoisoned + int m_FoodPoisonedTicksRemaining; + + /// Last position that has been recorded for food-related processing: + Vector3d m_LastFoodPos; + float m_LastJumpHeight; float m_LastGroundHeight; bool m_bTouchGround; @@ -264,6 +291,11 @@ protected: /// Filters out damage for creative mode virtual void DoTakeDamage(TakeDamageInfo & TDI) override; + /// Called in each tick to handle food-related processing + void HandleFood(void); + + /// Adds food exhaustion based on the difference between Pos and LastPos, sprinting status and swimming (in water block) + void ApplyFoodExhaustionFromMovement(cChunk & a_Chunk); } ; // tolua_export diff --git a/source/Protocol/Protocol125.cpp b/source/Protocol/Protocol125.cpp index 97c193e97..fddf7d324 100644 --- a/source/Protocol/Protocol125.cpp +++ b/source/Protocol/Protocol125.cpp @@ -469,7 +469,7 @@ void cProtocol125::SendHealth(void) WriteByte (PACKET_UPDATE_HEALTH);
WriteShort((short)m_Client->GetPlayer()->GetHealth());
WriteShort(m_Client->GetPlayer()->GetFoodLevel());
- WriteFloat(m_Client->GetPlayer()->GetFoodSaturationLevel());
+ WriteFloat((float)m_Client->GetPlayer()->GetFoodSaturationLevel());
Flush();
}
|