1
0

Merge remote-tracking branch 'upstream/master'

Conflicts:
	source/Piston.cpp

Merge conflict?
This commit is contained in:
Tiger Wang 2013-08-14 12:03:13 +01:00
commit 77468f87b7
20 changed files with 464 additions and 185 deletions

12
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,12 @@
Code Stuff
----------
* No magic numbers, use named constants like E_ITEM...
* Please use tabs for indentation and spaces for alignment.
Copyright
---------
Your work should be licensed under the apache license, and you should add yourself to the CONTRIBUTORS file.
If your work is not licensed under the apache license, then it must be compatible and marked as such.

View File

@ -7,5 +7,8 @@ STR_Warrior
mgueydan
tigerw
bearbin
Lapayo
rs2k
Duralex
If you feel you have contributed enough to be included in this list, just put in a PR including yourself.

View File

@ -336,27 +336,3 @@ function HandleConsoleUnload(Split)
Out = Out .. "Num loaded chunks after: " .. cRoot:Get():GetTotalChunkCount();
return true, Out;
end
-- Helper functions:
--- Returns the list of players banned by name, separated by ", "
function BanListByName()
local NumValues = BannedPlayersIni:NumValues("Banned");
local Banned = {};
local KeyID = BannedPlayersIni:FindKey("Banned");
for i = 1, NumValues do
local PlayerName = BannedPlayersIni:ValueName(KeyID, i - 1);
if (BannedPlayersIni:GetValueB("Banned", PlayerName)) then
-- Player listed AND banned
table.insert(Banned, PlayerName);
end
end
return table.concat(Banned, ", ");
end
--- Returns the list of players banned by IP, separated by ", "
function BanListByIPs()
-- TODO: No IP ban implemented yet
return "";
end

View File

@ -0,0 +1,29 @@
function HandleDoCommand( Split, Player )
if #Split < 3 then
SendMessage( "Usage: /do <player> <command> [arguments]" )
return true
end
-- Get the command and arguments.
local newSplit = table.concat( Split, " ", 3 )
local pluginManager = cRoot:Get():GetPluginManager()
pluginManager:ExecuteCommand( Split[2], newSplit )
end
function HandleSudoCommand ( Split, Player )
if #Split < 3 then
SendMessage( "Usage: /sudo <player> <command> [arguments]" )
return true
end
-- Get the command and arguments.
local newSplit = table.concat( Split, " ", 3 )
local pluginManager = cRoot:Get():GetPluginManager()
pluginManager:ForceExecuteCommand( Split[2], newSplit )
end

View File

@ -1,3 +1,162 @@
function SetBackCoordinates( Player )
BackCoords[Player:GetName()] = Vector3i( Player:GetPosX(), Player:GetPosY(), Player:GetPosZ() )
end
end
function SendMessage(a_Player, a_Message)
if (g_UsePrefixes) then
a_Player:SendMessage(cChatColor.Yellow .. "[INFO] " .. cChatColor.White .. a_Message)
else
a_Player:SendMessage(cChatColor.Yellow .. a_Message)
end
end
function SendMessageSuccess(a_Player, a_Message)
if (g_UsePrefixes) then
a_Player:SendMessage(cChatColor.Green .. "[INFO] " .. cChatColor.White .. a_Message)
else
a_Player:SendMessage(cChatColor.Green .. a_Message)
end
end
function SendMessageFailure(a_Player, a_Message)
if (g_UsePrefixes) then
a_Player:SendMessage(cChatColor.Red .. "[INFO] " .. cChatColor.White .. a_Message)
else
a_Player:SendMessage(cChatColor.Red .. a_Message)
end
end
--- Returns the list of players banned by name, separated by ", "
function BanListByName()
local NumValues = BannedPlayersIni:NumValues("Banned");
local Banned = {};
local KeyID = BannedPlayersIni:FindKey("Banned");
for i = 1, NumValues do
local PlayerName = BannedPlayersIni:ValueName(KeyID, i - 1);
if (BannedPlayersIni:GetValueB("Banned", PlayerName)) then
-- Player listed AND banned
table.insert(Banned, PlayerName);
end
end
return table.concat(Banned, ", ");
end
--- Returns the list of players banned by IP, separated by ", "
function BanListByIPs()
-- TODO: No IP ban implemented yet
return "";
end
--- Kicks a player by name, with the specified reason; returns bool whether found and player's real name
function KickPlayer( PlayerName, Reason )
local RealName = ""
if (Reason == nil) then
Reason = "You have been kicked"
end
local FoundPlayerCallback = function( a_Player )
RealName = a_Player:GetName()
local Server = cRoot:Get():GetServer()
LOGINFO( "'" .. RealName .. "' is being kicked for ( "..Reason..") " )
Server:SendMessage("Kicking " .. RealName)
a_Player:GetClientHandle():Kick(Reason)
end
if not cRoot:Get():FindAndDoWithPlayer( PlayerName, FoundPlayerCallback ) then
-- Could not find player
return false
end
return true, RealName -- Player has been kicked
end
function ReturnColorFromChar( Split, char )
-- Check if the char represents a color. Else return nil.
if char == "0" then
return cChatColor.Black
elseif char == "1" then
return cChatColor.Navy
elseif char == "2" then
return cChatColor.Green
elseif char == "3" then
return cChatColor.Blue
elseif char == "4" then
return cChatColor.Red
elseif char == "5" then
return cChatColor.Purple
elseif char == "6" then
return cChatColor.Gold
elseif char == "7" then
return cChatColor.LightGray
elseif char == "8" then
return cChatColor.Gray
elseif char == "9" then
return cChatColor.DarkPurple
elseif char == "a" then
return cChatColor.LightGreen
elseif char == "b" then
return cChatColor.LightBlue
elseif char == "c" then
return cChatColor.Rose
elseif char == "d" then
return cChatColor.LightPurple
elseif char == "e" then
return cChatColor.Yellow
elseif char == "f" then
return cChatColor.White
elseif char == "k" then
return cChatColor.Random
elseif char == "l" then
return cChatColor.Bold
elseif char == "m" then
return cChatColor.Strikethrough
elseif char == "n" then
return cChatColor.Underlined
elseif char == "o" then
return cChatColor.Italic
elseif char == "r" then
return cChatColor.Plain
end
end
function CheckHardcore(Victim)
if HardCore == "true" then
if Victim:IsPlayer() == true then
local KilledPlayer = tolua.cast(Victim, "cPlayer")
BanPlayer(KilledPlayer:GetName(), "You died, haha. Good game, bro.")
end
end
end
-- Teleports a_SrcPlayer to a player named a_DstPlayerName; if a_TellDst is true, will send a notice to the destination player
function TeleportToPlayer( a_SrcPlayer, a_DstPlayerName, a_TellDst )
local teleport = function(OtherPlayer)
if OtherPlayer == a_SrcPlayer then
-- Asked to teleport to self?
SendMessageFailure( a_SrcPlayer, "Y' can't teleport to yerself!" )
else
SetBackCoordinates( a_SrcPlayer )
a_SrcPlayer:TeleportToEntity( OtherPlayer )
SendMessageSuccess( a_SrcPlayer, "You teleported to " .. OtherPlayer:GetName() .. "!" )
if (a_TellDst) then
SendMessage( OtherPlayer, Player:GetName().." teleported to you!" )
end
end
end
local World = a_SrcPlayer:GetWorld()
if not World:DoWithPlayer(a_DstPlayerName, teleport) then
SendMessageFailure( a_SrcPlayer, "Can't find player " .. a_DstPlayerName)
end
end

View File

@ -17,30 +17,3 @@ function HandleKickCommand( Split, Player )
return true
end
--- Kicks a player by name, with the specified reason; returns bool whether found and player's real name
function KickPlayer( PlayerName, Reason )
local RealName = ""
if (Reason == nil) then
Reason = "You have been kicked"
end
local FoundPlayerCallback = function( a_Player )
RealName = a_Player:GetName()
local Server = cRoot:Get():GetServer()
LOGINFO( "'" .. RealName .. "' is being kicked for ( "..Reason..") " )
Server:SendMessage("Kicking " .. RealName)
a_Player:GetClientHandle():Kick(Reason)
end
if not cRoot:Get():FindAndDoWithPlayer( PlayerName, FoundPlayerCallback ) then
-- Could not find player
return false
end
return true, RealName -- Player has been kicked
end

View File

@ -7,6 +7,11 @@ Messages = {}
Destination = {}
--END VARIABLES
-- Configuration
-- Use prefixes or not.
-- If set to true, messages are prefixed, e. g. "[FATAL]". If false, messages are colored.
g_UsePrefixes = true
--COMMENCE AWESOMENESS!
function Initialize( Plugin )
PLUGIN = Plugin
@ -62,6 +67,8 @@ function Initialize( Plugin )
PluginManager:BindCommand("/viewdistance", "core.viewdistance", HandleViewDistanceCommand, " [".. cClientHandle.MIN_VIEW_DISTANCE .."-".. cClientHandle.MAX_VIEW_DISTANCE .."] - Change your view distance")
PluginManager:BindCommand("/weather", "core.weather", HandleWeatherCommand, " ~ Change world weather")
PluginManager:BindCommand("/worlds", "core.worlds", HandleWorldsCommand, " - Shows a list of all the worlds")
PluginManager:BindCommand("/sudo", "core.sudo", HandleSudoCommand, " - Runs a command as a player, ignoring permissions")
PluginManager:BindCommand("/do", "core.do", HandleDoCommand, " - Runs a command as a player.")
InitConsoleCommands()

View File

@ -1,27 +0,0 @@
-- Use prefixes or not.
-- If set to true, messages are prefixed, e. g. "[FATAL]". If false, messages are colored.
g_UsePrefixes = true
function SendMessage(a_Player, a_Message)
if (g_UsePrefixes) then
a_Player:SendMessage(cChatColor.Yellow .. "[INFO] " .. cChatColor.White .. a_Message)
else
a_Player:SendMessage(cChatColor.Yellow .. a_Message)
end
end
function SendMessageSuccess(a_Player, a_Message)
if (g_UsePrefixes) then
a_Player:SendMessage(cChatColor.Green .. "[INFO] " .. cChatColor.White .. a_Message)
else
a_Player:SendMessage(cChatColor.Green .. a_Message)
end
end
function SendMessageFailure(a_Player, a_Message)
if (g_UsePrefixes) then
a_Player:SendMessage(cChatColor.Red .. "[INFO] " .. cChatColor.White .. a_Message)
else
a_Player:SendMessage(cChatColor.Red .. a_Message)
end
end

View File

@ -42,53 +42,3 @@ function ShowMOTDTo( Player )
end
end
function ReturnColorFromChar( Split, char )
-- Check if the char represents a color. Else return nil.
if char == "0" then
return cChatColor.Black
elseif char == "1" then
return cChatColor.Navy
elseif char == "2" then
return cChatColor.Green
elseif char == "3" then
return cChatColor.Blue
elseif char == "4" then
return cChatColor.Red
elseif char == "5" then
return cChatColor.Purple
elseif char == "6" then
return cChatColor.Gold
elseif char == "7" then
return cChatColor.LightGray
elseif char == "8" then
return cChatColor.Gray
elseif char == "9" then
return cChatColor.DarkPurple
elseif char == "a" then
return cChatColor.LightGreen
elseif char == "b" then
return cChatColor.LightBlue
elseif char == "c" then
return cChatColor.Rose
elseif char == "d" then
return cChatColor.LightPurple
elseif char == "e" then
return cChatColor.Yellow
elseif char == "f" then
return cChatColor.White
elseif char == "k" then
return cChatColor.Random
elseif char == "l" then
return cChatColor.Bold
elseif char == "m" then
return cChatColor.Strikethrough
elseif char == "n" then
return cChatColor.Underlined
elseif char == "o" then
return cChatColor.Italic
elseif char == "r" then
return cChatColor.Plain
end
end

View File

@ -44,7 +44,7 @@ function OnKilling(Victim, Killer)
elseif Killer:IsA("cMagmacube") then
Server:SendMessage( cChatColor.Red .. "[FATALITY] " .. cChatColor.White .. Victim:GetName() .. " was incinerated by a magmacube")
elseif Killer:IsA("cWolf") then
Server:SendMessage( cChatColor.Red .. "[FATALITY] " .. cChatColor.White .. Victim:GetName() .. " was savaged by a wolf")
Server:SendMessage( cChatColor.Red .. "[FATALITY] " .. cChatColor.White .. Victim:GetName() .. " was savaged by a wolf")
end
CheckHardcore(Victim)
return false
@ -54,12 +54,3 @@ function OnKilling(Victim, Killer)
CheckHardcore(Victim)
end
end
function CheckHardcore(Victim)
if HardCore == "true" then
if Victim:IsPlayer() == true then
local KilledPlayer = tolua.cast(Victim, "cPlayer")
BanPlayer(KilledPlayer:GetName(), "You died, haha. Good game, bro.")
end
end
end

View File

@ -72,29 +72,3 @@ function HandleTPAcceptCommand( Split, Player )
return true
end
-- Teleports a_SrcPlayer to a player named a_DstPlayerName; if a_TellDst is true, will send a notice to the destination player
function TeleportToPlayer( a_SrcPlayer, a_DstPlayerName, a_TellDst )
local teleport = function(OtherPlayer)
if OtherPlayer == a_SrcPlayer then
-- Asked to teleport to self?
SendMessageFailure( a_SrcPlayer, "Y' can't teleport to yerself!" )
else
SetBackCoordinates( a_SrcPlayer )
a_SrcPlayer:TeleportToEntity( OtherPlayer )
SendMessageSuccess( a_SrcPlayer, "You teleported to " .. OtherPlayer:GetName() .. "!" )
if (a_TellDst) then
SendMessage( OtherPlayer, Player:GetName().." teleported to you!" )
end
end
end
local World = a_SrcPlayer:GetWorld()
if not World:DoWithPlayer(a_DstPlayerName, teleport) then
SendMessageFailure( a_SrcPlayer, "Can't find player " .. a_DstPlayerName)
end
end

View File

@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2013 Alexander Harkness
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,20 @@
TransAPI
========
A plugin translation API for MCServer.
TransAPI is designed to be used with the [client library](https://github.com/bearbin/transapi-client), however there is also a stable API available for use.
API
---
GetLanguage ( cPlayer )
Returns the user's preferred language (or server default if not set). (ISO 639-1 language code)
GetConsoleLanguage ( )
Returns the preferred language for console text. (ISO 639-1 language code)
Commands
--------
* /language [lang] - Takes a language code (ISO 639-1) and sets the user's preferred language to that. (tranapi.setlang)

View File

@ -0,0 +1,91 @@
-- This plugin copyright Alexander Harkness 2013, licensed under the MIT license.
-- Configuration
g_ServerLang = "en"
g_ConsoleLang = "en"
-- Global Variables
g_Plugin = nil
g_PluginManager = nil
g_PluginDir = nil
g_UserData = nil
-- START WITH DA AWESOME!
function Initialize( Plugin )
-- Set up the globals.
g_Plugin = Plugin
g_PluginManager = cRoot:Get():GetPluginManager()
g_PluginDir = Plugin:GetDirectory()
-- Set up the plugin details.
Plugin:SetName( "TransAPI" )
Plugin:SetVersion( 1 )
-- This is the place for commands!
g_PluginManager:BindCommand("/language", "transapi.setlang", HandleLanguageCommand, " - Set your preferred language (use ISO 639-1)")
-- Load the userdata file.
g_UserData = cIniFile( g_PluginDir .. "/userdata.ini" )
if g_UserData ~= true then
LOGERROR( "TransAPI INI file could not be opened!" )
end
LOG( "Initialized " .. Plugin:GetName() .. " v." .. Plugin:GetVersion() )
return true
end
function GetLanguage( Player )
-- Returns a language to use.
if g_UserData:ReadFile() == true then
local userLang = g_UserData:GetValueSet( Player:GetName(), "language", "false" )
g_UserData:WriteFile()
end
if userLang == "false" then
return g_ServerLang
else
return userLang
end
end
function GetConsoleLanguage()
-- Return the language to use for console messages.
return g_ConsoleLang
end
function HandleLanguageCommand ( Split, Player )
-- If the user is not setting the language, tell them the currently selected one.
if #Split ~= 2 then
local userLang = g_UserData:GetValueSet( Player:GetName(), "language", "false" )
if userLang == "false" then
return g_ServerLang
else
return userLang
end
end
-- Set the language.
local success = g_UserData:SetValue( Player:GetName(), "language" Split[2] )
g_UserData:WriteFile()
if not success then
Player:SendMessage( "Language could not be set!" )
else
Player:SendMessage( "Language set!" )
end
return true
end
function OnDisable()
LOG( "Disabled TransAPI!" )
end

View File

@ -13,5 +13,5 @@ Color=2
Inherits=Default
[Default]
Permissions=core.build,core.help,core.playerlist,core.pluginlist,core.spawn
Color=7
Permissions=core.build,core.help,core.playerlist,core.pluginlist,core.spawn,transapi.setlang
Color=7

View File

@ -281,7 +281,8 @@ pillarquartzblock=155:2
quartzstairs=156
activatorrail=157
dropper=158
haybale=170
carpet=171
ironshovel=256
ironspade=256
ironpickaxe=257
@ -294,6 +295,7 @@ redapple=260
bow=261
arrow=262
coal=263
coalblock=173
charcoal=263:1
diamond=264
ironingot=265
@ -528,6 +530,7 @@ netherbrickitem=405
netherquartz=406
tntminecart=407
hopperminecart=408
lead=420
goldrecord=2256
greenrecord=2257
@ -541,3 +544,6 @@ stradrecord=2264
wardrecord=2265
11record=2266

View File

@ -18,6 +18,7 @@ DefaultWorld=world
Plugin=Core
Plugin=ChunkWorx
Plugin=ChatLog
Plugin=TransAPI
[Monsters]
AnimalsOn=0

View File

@ -0,0 +1,62 @@
// ConsoleColors.cpp
// Tests the various console color combinations
#include <stdio.h>
#include <stdlib.h>
/// Evaluates to the number of elements in an array (compile-time!)
#define ARRAYCOUNT(X) (sizeof(X) / sizeof(*(X)))
int main(void)
{
static const char * Attribs[] =
{
"0", // All attribs off
"1", // bold
"2", // faint
"7", // inverse
"1;7", // bold inverse
"2;7", // faint inverse
} ;
for (int i = 0; i < ARRAYCOUNT(Attribs); i++)
{
const char * Attrib = Attribs[i];
for (int fg = 30; fg <= 37; fg++)
{
for (int bg = 40; bg <= 47; bg++)
{
printf("\x1b[%s;%d;%dm %s;%d;%d ", Attrib, fg, bg, Attrib, fg, bg);
} // for bg
puts("\x1b[0m"); // Reset terminal back to normal colors for the newline
} // for fg
} // for i - Attribs[]
for (int i = 1; i < ARRAYCOUNT(Attribs); i++)
{
const char * Attrib = Attribs[i];
for (int fg = 30; fg <= 37; fg++)
{
for (int bg = 40; bg <= 47; bg++)
{
printf("\x1b[%d;%d;%sm %d;%d;%s ", fg, bg, Attrib, fg, bg, Attrib);
} // for bg
puts("\x1b[0m"); // Reset terminal back to normal colors for the newline
} // for fg
} // for i - Attribs[]
return 0;
}

View File

@ -21,11 +21,14 @@
*/
//Athar from http://www.cplusplus.com/forum/unices/60161/ helped with the sleep code.
extern bool g_BlockPistonBreakable[];
#define AddDir( x, y, z, dir, amount ) \
switch (dir) \
{ \
@ -132,6 +135,9 @@ void cPiston::ExtendPiston( int pistx, int pisty, int pistz )
/*
#ifdef _WIN32
// Sleeping here will play the piston animation on the client; however, it will block the entire server
// for the 100 ms, effectively dropping 2 game ticks per piston. This is very bad
// This needs to be handled using delayed scheduled tasks instead
Sleep(100);
#else
usleep(static_cast<useconds_t>(100)*1000);
@ -184,6 +190,10 @@ void cPiston::RetractPiston( int pistx, int pisty, int pistz )
}
/*
#ifdef _WIN32
// TODO: This code needs replacing
// Sleeping here will play the piston animation on the client; however, it will block the entire server
// for the 100 ms, effectively dropping 2 game ticks per piston. This is very bad
// This needs to be handled using delayed scheduled tasks instead
Sleep(100);
#else
usleep(static_cast<useconds_t>(100)*1000);
@ -197,6 +207,9 @@ void cPiston::RetractPiston( int pistx, int pisty, int pistz )
{
/*
#ifdef _WIN32
// Sleeping here will play the piston animation on the client; however, it will block the entire server
// for the 100 ms, effectively dropping 2 game ticks per piston. This is very bad
// This needs to be handled using delayed scheduled tasks instead
Sleep(100);
#else
usleep(static_cast<useconds_t>(100)*1000);

View File

@ -1322,7 +1322,7 @@ cPlayer::StringList cPlayer::GetResolvedPermissions()
void cPlayer::UseEquippedItem()
void cPlayer::UseEquippedItem(void)
{
if (GetGameMode() == gmCreative) // No damage in creative
{
@ -1332,29 +1332,39 @@ void cPlayer::UseEquippedItem()
GetInventory().DamageEquippedItem();
}
void cPlayer::SetSwimState(cChunk & a_Chunk)
{
int RelY = (int)floor(m_LastPosY + 0.1);
if ((RelY < 0) || (RelY >= cChunkDef::Height))
{
m_IsSwimming = false;
m_IsSubmerged = false;
return;
}
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;
// first we check if the player is swimming
// Check if the player is swimming:
// 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));
m_IsSwimming = IsBlockWater(BlockIn);
// now we check if the player is submerged
VERIFY(a_Chunk.UnboundedRelGetBlockType(RelX, RelY+1, RelZ, BlockIn));
// Check if the player is submerged:
VERIFY(a_Chunk.UnboundedRelGetBlockType(RelX, RelY + 1, RelZ, BlockIn));
m_IsSubmerged = IsBlockWater(BlockIn);
}
void cPlayer::HandleAir()
void cPlayer::HandleAir(void)
{
// Ref.: http://www.minecraftwiki.net/wiki/Chunk_format
// see if the player is /submerged/ water (block above is water)
@ -1363,22 +1373,28 @@ void cPlayer::HandleAir()
if (IsSubmerged())
{
// either reduce air level or damage player
if(m_AirLevel < 1)
if (m_AirLevel < 1)
{
if(m_AirTickTimer < 1)
if (m_AirTickTimer < 1)
{
// damage player
TakeDamage(dtDrowning, NULL, 1, 1, 0);
// reset timer
m_AirTickTimer = DROWNING_TICKS;
}else{
}
else
{
m_AirTickTimer -= 1;
}
}else{
}
else
{
// reduce air supply
m_AirLevel -= 1;
}
}else{
}
else
{
// set the air back to maximum
m_AirLevel = MAX_AIR_LEVEL;
m_AirTickTimer = DROWNING_TICKS;
@ -1386,6 +1402,9 @@ void cPlayer::HandleAir()
}
void cPlayer::HandleFood(void)
{
// Ref.: http://www.minecraftwiki.net/wiki/Hunger