1
0

Merge branch 'master' into PreventNewWarnings

This commit is contained in:
tycho
2015-05-24 17:27:05 +01:00
12 changed files with 497 additions and 197 deletions

View File

@@ -1,39 +1,27 @@
language: cpp
compiler: clang
compiler:
- clang
- gcc
before_install:
# - if [ "$TRAVIS_MCSERVER_BUILD_TYPE" == "COVERAGE" ]; then sudo pip install cpp_coveralls; fi
# g++4.8
- sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
- sudo apt-get update -qq
install:
# g++4.8 and clang
- sudo apt-get install -qq g++-4.8
- sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 90
- sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 90
# lua, needed for style checking and possibly later on for bindings generation
- sudo apt-get install -qq lua5.1
# g++4.8
- if [ "$CXX" == "g++" ]; then export CXX="g++-4.8"; export CC="gcc-4.8"; fi
# Build MCServer
script: ./CIbuild.sh
#after_success:
# - ./uploadCoverage.sh
env:
- TRAVIS_MCSERVER_BUILD_TYPE=RELEASE MCSERVER_PATH=./MCServer
- TRAVIS_MCSERVER_BUILD_TYPE=DEBUG MCSERVER_PATH=./MCServer_debug
#matrix:
# include:
# - compiler: gcc
# env: TRAVIS_MCSERVER_BUILD_TYPE=COVERAGE MCSERVER_PATH=./MCServer
# Notification Settings
notifications:
email:
on_success: change

View File

@@ -24,9 +24,10 @@ p-mcgowan
rs2k
SafwatHalaby (Safwat Halaby)
SamJBarney
Seadragon91 (Lukas Pioch)
Sofapriester
SphinxC0re
STR_Warrior
NiLSPACE (formerly STR_Warrior)
structinf (xdot)
Sxw1212
Taugeshtu
@@ -35,7 +36,7 @@ tonibm19
UltraCoderRU
WebFreak001
worktycho
xoft
xoft (Mattes Dolak/madmaxoft on GH)
Yeeeeezus (Donated AlchemistVillage prefabs)
Please add yourself to this list if you contribute to MCServer.

View File

@@ -815,7 +815,7 @@ rawrabbit=411
cookedrabbit=412
rabbitstew=413
rabbitsoup=413
rabbitsfood=414
rabbitsfoot=414
rabbithide=415
armorstand=416
ironhorsearmor=417

View File

@@ -22,7 +22,11 @@ For Windows, you just need to download a file and extract it:
- [Windows 32 bit](http://builds.cuberite.org/job/MCServer%20Windows%20x86/lastSuccessfulBuild/artifact/Install/MCServer.zip)
- [Windows 64 bit](http://builds.cuberite.org/job/MCServer%20Windows%20x64/lastSuccessfulBuild/artifact/Install/MCServer.zip)
For other operating systems you need to download and compile yourself. There is also an archive of binary builds on the buildserver: http://builds.cuberite.org
For other operating systems you need to download and compile yourself. This can be done either manually, or with this automatic script:
bash -c "$(wget -O - https://raw.githubusercontent.com/mc-server/MCServer/master/compile.sh)"
There is also an archive of binary builds on the buildserver: http://builds.cuberite.org
Compiling the server yourself has other benefits: you may get better performance performance (1.5-3x as fast) and it supports more operating systems. See the [COMPILING.md](https://github.com/mc-server/MCServer/blob/master/COMPILING.md) file for more details.

199
compile.sh Executable file
View File

@@ -0,0 +1,199 @@
#|| goto :windows_detected
# Do we already have a repo?
if [[ -d .git && -f easyinstall.sh && -f MakeLuaAPI.cmd ]]; then # A good enough indicator that we're in the MCServer git repo.
cd ../
echo "MCServer repository detected. This should make the process faster, especially if you compiled before."
fi
# Error functions.
function error
{
echo
echo "-----------------"
echo "Script aborted, reason:"
echo $1
exit -1
}
function missingDepsExit
{
echo
echo "Please install the dependencies, then come back."
echo
exit -2
}
# Echo: Greetings.
echo
echo "Hello, this script will download and compile Cuberite/MCServer."
echo "On subsequent runs, it will update your MCServer."
echo "The compilation and download will occur in the current directory."
echo "If you're updating, you should run <Path to MCServer>/MCServer/compile.sh"
echo "Compiling from source takes time, but it usually generates better executables."
echo "If you prefer ready-to-use binaries or if you want more info, please visit:"
echo "http://cuberite.org/"
echo "http://mc-server.org/"
MISSING_PROGRAMS=""
# Compiler check.
GCC_EXISTS=0
CLANG_EXISTS=0
g++ --help > /dev/null 2> /dev/null && GCC_EXISTS=1
clang --help > /dev/null 2> /dev/null && CLANG_EXISTS=1
if [[ $GCC_EXISTS == 0 && $CLANG_EXISTS == 0 ]]; then
MISSING_PROGRAMS="gcc g++"
fi
# Depdendency check.
while read program; do
$program --help > /dev/null 2> /dev/null || MISSING_PROGRAMS="$MISSING_PROGRAMS $program"
done <<"EOF"
git
make
cmake
EOF
if [[ $MISSING_PROGRAMS != "" ]]; then
echo
echo "-----------------"
echo "You have missing compilation dependencies:"
echo $MISSING_PROGRAMS
echo
# apt-get guide.
apt-get --help > /dev/null 2> /dev/null && \
echo "You can install the missing depndencies via:" && \
echo -n "sudo apt-get install " && echo $MISSING_PROGRAMS && missingDepsExit
# yum guide.
yum --help > /dev/null 2> /dev/null && \
echo "You can install the missing depndencies via:" && \
echo -n "sudo yum install " && echo $MISSING_PROGRAMS && missingDepsExit
# rpm guide.
rpm --help > /dev/null 2> /dev/null && \
echo "You can install the missing depndencies via:" && \
echo -n "sudo rpm -i " && echo $MISSING_PROGRAMS && missingDepsExit
# pacman guide.
pacman --help > /dev/null 2> /dev/null && \
echo "You can install the missing depndencies via:" && \
echo -n "sudo pacman -S " && echo $MISSING_PROGRAMS && missingDepsExit
missingDepsExit
fi
exit
# Echo: Branch choice.
echo
echo "You can choose between 2 branches:"
echo "* (S)Stable: (Coming soon) Choose the stable branch if you want the most reliable server."
echo " As of now, Stable is not yet available, please use testing instead."
echo
echo "* (T)Testing: The testing branch is less stable,"
echo " but using it and finding and reporting bugs helps us a lot!"
echo
echo "* (D)Dev: The least stable of the three. (Master branch)"
echo " Choose the development branch if you are feeling adventurous and"
echo " want to try new, bleeding edge features."
echo
# Input: Branch choice.
echo -n "Choose the branch (s/t/d): "
read BRANCH
if [[ ($BRANCH == "s") || ($BRANCH == "S" ) ]]; then
#BRANCH="stable"
error "We don't have a stable branch yet, please use testing, sorry."
elif [[ ($BRANCH == "t") || ($BRANCH == "T" ) ]]; then
BRANCH="testing"
elif [[ ($BRANCH == "d") || ($BRANCH == "D" ) ]]; then
BRANCH="master"
else
error "Unrecognized user input."
fi
# Echo: Compile mode choice.
echo
echo "Choose compile mode:"
echo "* (N)Normal: Compiles normally."
echo
echo "* (D)Debug: Compiles in debug mode. Makes your console and crashes much more verbose."
echo " But it costs performance."
echo
echo "Note that the script will connect to the internet in order to fetch code after this step."
echo "It will then compile your program."
echo
# Input: Compile mode choice.
echo -n "Choose compile mode: (n/d): "
read BUILDTYPE
if [[ ($BUILDTYPE == "d") || ($BUILDTYPE == "D") ]]; then
BUILDTYPE="Debug"
elif [[ ($BUILDTYPE == "n") || ($BUILDTYPE == "N") ]]; then
BUILDTYPE="Release"
else
error "Unrecognized user input."
fi
# Echo: Downloading began.
echo
echo " --- Downloading MCServer's source code from the $BRANCH branch..."
# Git: Clone.
if [ ! -d MCServer ]; then
echo " --- Looks like your first run, cloning the whole code..."
git clone https://github.com/mc-server/MCServer.git
fi
# Git: Fetch.
pushd MCServer
echo " --- Updating the $BRANCH branch..."
git fetch origin $BRANCH || error "git fetch failed"
git checkout $BRANCH || error "git checkout failed"
git merge origin/$BRANCH || error "git merge failed"
# Git: Submodules.
echo " --- Updating submodules..."
git submodule init
git submodule update
# Cmake.
echo " --- Running cmake..."
popd
if [ ! -d build-mcserver ]; then mkdir build-mcserver; fi
pushd build-mcserver
cmake ../MCServer/ -DCMAKE_BUILD_TYPE=$BUILDTYPE || error "cmake failed"
# Make.
echo " --- Compiling..."
make -j`nproc` || error "Compiling failed"
echo
# Echo: Compilation complete.
popd
pushd MCServer/MCServer
echo
echo "-----------------"
echo "Compilation done!"
echo
echo "Cuberite awaits you at:"
echo "`pwd`/MCServer"
echo
echo "Enjoy :)"
popd
exit 0
:windows_detected
echo "This script is not available for Windows yet, sorry."
echo "You can still download the Windows binaries from: http://mc-server.org"

View File

@@ -94,7 +94,7 @@ cPlayer::cPlayer(cClientHandlePtr a_Client, const AString & a_PlayerName) :
SetMaxHealth(MAX_HEALTH);
m_Health = MAX_HEALTH;
m_LastPlayerListTime = std::chrono::steady_clock::now();
m_PlayerName = a_PlayerName;
@@ -106,7 +106,7 @@ cPlayer::cPlayer(cClientHandlePtr a_Client, const AString & a_PlayerName) :
SetPosY(World->GetSpawnY());
SetPosZ(World->GetSpawnZ());
SetBedPos(Vector3i(static_cast<int>(World->GetSpawnX()), static_cast<int>(World->GetSpawnY()), static_cast<int>(World->GetSpawnZ())));
LOGD("Player \"%s\" is connecting for the first time, spawning at default world spawn {%.2f, %.2f, %.2f}",
a_PlayerName.c_str(), GetPosX(), GetPosY(), GetPosZ()
);
@@ -135,7 +135,7 @@ cPlayer::cPlayer(cClientHandlePtr a_Client, const AString & a_PlayerName) :
m_IsFlying = true;
m_bVisible = false;
}
cRoot::Get()->GetServer()->PlayerCreated(this);
}
@@ -152,17 +152,17 @@ cPlayer::~cPlayer(void)
}
LOGD("Deleting cPlayer \"%s\" at %p, ID %d", GetName().c_str(), this, GetUniqueID());
// Notify the server that the player is being destroyed
cRoot::Get()->GetServer()->PlayerDestroying(this);
SaveToDisk();
m_ClientHandle = nullptr;
delete m_InventoryWindow;
m_InventoryWindow = nullptr;
LOGD("Player %p deleted", this);
}
@@ -208,7 +208,7 @@ void cPlayer::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
m_ClientHandle = nullptr;
return;
}
if (!m_ClientHandle->IsPlaying())
{
// We're not yet in the game, ignore everything
@@ -217,21 +217,21 @@ void cPlayer::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
}
m_Stats.AddValue(statMinutesPlayed, 1);
if (!a_Chunk.IsValid())
{
// This may happen if the cPlayer is created before the chunks have the chance of being loaded / generated (#83)
return;
}
super::Tick(a_Dt, a_Chunk);
// Handle charging the bow:
if (m_IsChargingBow)
{
m_BowCharge += 1;
}
// Handle updating experience
if (m_bDirtyExperience)
{
@@ -243,7 +243,7 @@ void cPlayer::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
// Apply food exhaustion from movement:
ApplyFoodExhaustionFromMovement();
if (cRoot::Get()->GetPluginManager()->CallHookPlayerMoving(*this, m_LastPos, GetPosition()))
{
CanMove = false;
@@ -264,10 +264,10 @@ void cPlayer::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
FinishEating();
}
HandleFood();
}
if (m_IsFishing)
{
HandleFloater();
@@ -467,7 +467,7 @@ void cPlayer::SetTouchGround(bool a_bTouchGround)
{
return;
}
m_bTouchGround = a_bTouchGround;
if (!m_bTouchGround)
@@ -516,7 +516,7 @@ void cPlayer::SetTouchGround(bool a_bTouchGround)
{
// cPlayer makes sure damage isn't applied in creative, no need to check here
TakeDamage(dtFalling, nullptr, Damage, Damage, 0);
// Fall particles
GetWorld()->BroadcastSoundParticleEffect(2006, POSX_TOINT, static_cast<int>(GetPosY()) - 1, POSZ_TOINT, Damage /* Used as particle effect speed modifier */);
}
@@ -548,7 +548,7 @@ void cPlayer::SetFoodLevel(int a_FoodLevel)
m_FoodSaturationLevel = 5.0;
return;
}
m_FoodLevel = FoodLevel;
SendHealth();
}
@@ -616,7 +616,7 @@ void cPlayer::StartEating(void)
{
// Set the timer:
m_EatingFinishTick = m_World->GetWorldAge() + EATING_TICKS;
// Send the packets:
m_World->BroadcastEntityAnimation(*this, 3);
m_World->BroadcastEntityMetadata(*this);
@@ -630,7 +630,7 @@ void cPlayer::FinishEating(void)
{
// Reset the timer:
m_EatingFinishTick = -1;
// Send the packets:
m_ClientHandle->SendEntityStatus(*this, esPlayerEatingAccepted);
m_World->BroadcastEntityMetadata(*this);
@@ -764,7 +764,7 @@ void cPlayer::SetSprintingMaxSpeed(double a_Speed)
void cPlayer::SetFlyingMaxSpeed(double a_Speed)
{
m_FlyingMaxSpeed = a_Speed;
// Update the flying speed, always:
m_ClientHandle->SendPlayerAbilities();
}
@@ -776,7 +776,7 @@ void cPlayer::SetFlyingMaxSpeed(double a_Speed)
void cPlayer::SetCrouch(bool a_IsCrouched)
{
// Set the crouch status, broadcast to all visible players
if (a_IsCrouched == m_IsCrouched)
{
// No change
@@ -797,7 +797,7 @@ void cPlayer::SetSprint(bool a_IsSprinting)
// No change
return;
}
m_IsSprinting = a_IsSprinting;
m_ClientHandle->SendPlayerMaxSpeed();
}
@@ -883,7 +883,7 @@ bool cPlayer::DoTakeDamage(TakeDamageInfo & a_TDI)
}
}
}
if (super::DoTakeDamage(a_TDI))
{
// Any kind of damage adds food exhaustion
@@ -1012,7 +1012,7 @@ void cPlayer::Respawn(void)
m_Health = GetMaxHealth();
SetInvulnerableTicks(20);
// Reset food level:
m_FoodLevel = MAX_FOOD_LEVEL;
m_FoodSaturationLevel = 5.0;
@@ -1024,7 +1024,7 @@ void cPlayer::Respawn(void)
// ToDo: send score to client? How?
m_ClientHandle->SendRespawn(GetWorld()->GetDimension(), true);
// Extinguish the fire:
StopBurning();
@@ -1158,7 +1158,7 @@ void cPlayer::CloseWindow(bool a_CanRefuse)
m_CurrentWindow = m_InventoryWindow;
return;
}
if (m_CurrentWindow->ClosedByPlayer(*this, a_CanRefuse) || !a_CanRefuse)
{
// Close accepted, go back to inventory window (the default):
@@ -1196,30 +1196,17 @@ void cPlayer::SetGameMode(eGameMode a_GameMode)
LOGWARNING("%s: Setting invalid gamemode: %d", GetName().c_str(), a_GameMode);
return;
}
if (m_GameMode == a_GameMode)
{
// Gamemode already set
return;
}
m_GameMode = a_GameMode;
m_ClientHandle->SendGameMode(a_GameMode);
if (!(IsGameModeCreative() || IsGameModeSpectator()))
{
SetFlying(false);
SetCanFly(false);
}
if (IsGameModeSpectator() && IsVisible())
{
SetVisible(false);
}
else if (!IsVisible())
{
SetVisible(true);
}
SetCapabilities();
m_World->BroadcastPlayerListUpdateGameMode(*this);
}
@@ -1231,6 +1218,30 @@ void cPlayer::SetGameMode(eGameMode a_GameMode)
void cPlayer::LoginSetGameMode( eGameMode a_GameMode)
{
m_GameMode = a_GameMode;
SetCapabilities();
}
void cPlayer::SetCapabilities()
{
if (!IsGameModeCreative() || IsGameModeSpectator())
{
SetFlying(false);
SetCanFly(false);
}
if (IsGameModeSpectator())
{
SetVisible(false);
}
else
{
SetVisible(true);
}
}
@@ -1322,12 +1333,12 @@ void cPlayer::SendRotation(double a_YawDegrees, double a_PitchDegrees)
Vector3d cPlayer::GetThrowStartPos(void) const
{
Vector3d res = GetEyePosition();
// Adjust the position to be just outside the player's bounding box:
res.x += 0.16 * cos(GetPitch());
res.y += -0.1;
res.z += 0.16 * sin(GetPitch());
return res;
}
@@ -1339,9 +1350,9 @@ Vector3d cPlayer::GetThrowSpeed(double a_SpeedCoeff) const
{
Vector3d res = GetLookVector();
res.Normalize();
// TODO: Add a slight random change (+-0.0075 in each direction)
return res * a_SpeedCoeff;
}
@@ -1386,13 +1397,13 @@ void cPlayer::MoveTo( const Vector3d & a_NewPos)
}
return;
}
// TODO: should do some checks to see if player is not moving through terrain
// TODO: Official server refuses position packets too far away from each other, kicking "hacked" clients; we should, too
Vector3d DeltaPos = a_NewPos - GetPosition();
UpdateMovementStats(DeltaPos);
SetPosition( a_NewPos);
SetStance(a_NewPos.y + 1.62);
}
@@ -1427,7 +1438,7 @@ bool cPlayer::HasPermission(const AString & a_Permission)
// Empty permission request is always granted
return true;
}
AStringVector Split = StringSplit(a_Permission, ".");
// Iterate over all restrictions; if any matches, then return failure:
@@ -1599,7 +1610,7 @@ void cPlayer::TossItems(const cItems & a_Items)
{
return;
}
m_Stats.AddValue(statItemsDropped, (StatValue)a_Items.Size());
double vX = 0, vY = 0, vZ = 0;
@@ -1621,7 +1632,7 @@ bool cPlayer::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn)
// Don't move to same world
return false;
}
// Ask the plugins if the player is allowed to changing the world
if (cRoot::Get()->GetPluginManager()->CallHookEntityChangingWorld(*this, *a_World))
{
@@ -1658,7 +1669,7 @@ bool cPlayer::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn)
// Broadcast the player into the new world.
a_World->BroadcastSpawnEntity(*this);
// Player changed the world, call the hook
cRoot::Get()->GetPluginManager()->CallHookEntityChangedWorld(*this, *OldWorld);
@@ -1678,7 +1689,7 @@ bool cPlayer::LoadFromDisk(cWorldPtr & a_World)
{
return true;
}
// Load from the offline UUID file, if allowed:
AString OfflineUUID = cClientHandle::GenerateOfflineUUID(GetName());
const char * OfflineUsage = " (unused)";
@@ -1690,7 +1701,7 @@ bool cPlayer::LoadFromDisk(cWorldPtr & a_World)
return true;
}
}
// Load from the old-style name-based file, if allowed:
if (cRoot::Get()->GetServer()->ShouldLoadNamedPlayerData())
{
@@ -1705,7 +1716,7 @@ bool cPlayer::LoadFromDisk(cWorldPtr & a_World)
return true;
}
}
// None of the files loaded successfully
LOG("Player data file not found for %s (%s, offline %s%s), will be reset to defaults.",
GetName().c_str(), m_UUID.c_str(), OfflineUUID.c_str(), OfflineUsage
@@ -1782,7 +1793,7 @@ bool cPlayer::LoadFromFile(const AString & a_FileName, cWorldPtr & a_World)
{
m_CanFly = true;
}
m_Inventory.LoadFromJson(root["inventory"]);
cEnderChestEntity::LoadFromJson(root["enderchestinventory"], m_EnderChestContents);
@@ -1801,11 +1812,11 @@ bool cPlayer::LoadFromFile(const AString & a_FileName, cWorldPtr & a_World)
// We use the default world name (like bukkit) because stats are shared between dimensions / worlds.
cStatSerializer StatSerializer(cRoot::Get()->GetDefaultWorld()->GetName(), GetName(), &m_Stats);
StatSerializer.Load();
LOGD("Player %s was read from file \"%s\", spawning at {%.2f, %.2f, %.2f} in world \"%s\"",
GetName().c_str(), a_FileName.c_str(), GetPosX(), GetPosY(), GetPosZ(), a_World->GetName().c_str()
);
return true;
}
@@ -2161,7 +2172,7 @@ void cPlayer::ApplyFoodExhaustionFromMovement()
{
return;
}
// Calculate the distance travelled, update the last pos:
Vector3d Movement(GetPosition() - m_LastPos);
Movement.y = 0; // Only take XZ movement into account
@@ -2364,7 +2375,7 @@ AString cPlayer::GetUUIDFileName(const AString & a_UUID)
{
AString UUID = cMojangAPI::MakeUUIDDashed(a_UUID);
ASSERT(UUID.length() == 36);
AString res("players/");
res.append(UUID, 0, 2);
res.push_back('/');
@@ -2372,7 +2383,3 @@ AString cPlayer::GetUUIDFileName(const AString & a_UUID)
res.append(".json");
return res;
}

View File

@@ -26,42 +26,42 @@ class cPlayer :
public cPawn
{
typedef cPawn super;
public:
static const int MAX_HEALTH;
static const int MAX_FOOD_LEVEL;
/** Number of ticks it takes to eat an item */
static const int EATING_TICKS;
// tolua_end
CLASS_PROTODEF(cPlayer)
cPlayer(cClientHandlePtr a_Client, const AString & a_PlayerName);
virtual ~cPlayer();
virtual void SpawnOn(cClientHandle & a_Client) override;
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
virtual void HandlePhysics(std::chrono::milliseconds a_Dt, cChunk &) override { UNUSED(a_Dt); }
/** Returns the curently equipped weapon; empty item if none */
virtual cItem GetEquippedWeapon(void) const override { return m_Inventory.GetEquippedItem(); }
/** Returns the currently equipped helmet; empty item if none */
virtual cItem GetEquippedHelmet(void) const override { return m_Inventory.GetEquippedHelmet(); }
/** Returns the currently equipped chestplate; empty item if none */
virtual cItem GetEquippedChestplate(void) const override { return m_Inventory.GetEquippedChestplate(); }
/** Returns the currently equipped leggings; empty item if none */
virtual cItem GetEquippedLeggings(void) const override { return m_Inventory.GetEquippedLeggings(); }
/** Returns the currently equipped boots; empty item if none */
virtual cItem GetEquippedBoots(void) const override { return m_Inventory.GetEquippedBoots(); }
@@ -104,16 +104,16 @@ public:
static int CalcLevelFromXp(int a_CurrentXp);
// tolua_end
/** Starts charging the equipped bow */
void StartChargingBow(void);
/** Finishes charging the current bow. Returns the number of ticks for which the bow has been charged */
int FinishChargingBow(void);
/** Cancels the current bow charging */
void CancelChargingBow(void);
/** Returns true if the player is currently charging the bow */
bool IsChargingBow(void) const { return m_IsChargingBow; }
@@ -128,7 +128,7 @@ public:
/** Gets the contents of the player's associated enderchest */
cItemGrid & GetEnderChestContents(void) { return m_EnderChestContents; }
inline const cItem & GetEquippedItem(void) const { return GetInventory().GetEquippedItem(); } // tolua_export
/** Returns whether the player is climbing (ladders, vines etc.) */
@@ -137,43 +137,49 @@ public:
virtual void TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ) override;
// tolua_begin
/** Sends the "look" packet to the player, forcing them to set their rotation to the specified values.
a_YawDegrees is clipped to range [-180, +180),
a_PitchDegrees is clipped to range [-180, +180) but the client only uses [-90, +90]
*/
void SendRotation(double a_YawDegrees, double a_PitchDegrees);
/** Returns the position where projectiles thrown by this player should start, player eye position + adjustment */
Vector3d GetThrowStartPos(void) const;
/** Returns the initial speed vector of a throw, with a 3D length of a_SpeedCoeff. */
Vector3d GetThrowSpeed(double a_SpeedCoeff) const;
/** Returns the current gamemode. Partly OBSOLETE, you should use IsGameModeXXX() functions wherever applicable */
eGameMode GetGameMode(void) const { return m_GameMode; }
/** Returns the current effective gamemode (inherited gamemode is resolved before returning) */
eGameMode GetEffectiveGameMode(void) const { return (m_GameMode == gmNotSet) ? m_World->GetGameMode() : m_GameMode; }
/** Sets the gamemode for the player.
The gamemode may be gmNotSet, in that case the player inherits the world's gamemode.
Updates the gamemode on the client (sends the packet)
*/
void SetGameMode(eGameMode a_GameMode);
// Sets the current gamemode, doesn't check validity, doesn't send update packets to client
void LoginSetGameMode(eGameMode a_GameMode);
// Updates player's capabilities - flying, visibility, etc. from their gamemode.
void SetCapabilities();
/** Returns true if the player is in Creative mode, either explicitly, or by inheriting from current world */
bool IsGameModeCreative(void) const;
/** Returns true if the player is in Survival mode, either explicitly, or by inheriting from current world */
bool IsGameModeSurvival(void) const;
/** Returns true if the player is in Adventure mode, either explicitly, or by inheriting from current world */
bool IsGameModeAdventure(void) const;
/** Returns true if the player is in Spectator mode, either explicitly, or by inheriting from current world */
bool IsGameModeSpectator(void) const;
AString GetIP(void) const { return m_IP; } // tolua_export
/** Returns the associated team, nullptr if none */
@@ -195,11 +201,8 @@ public:
If the achievement has been already awarded to the player, this method will just increment the stat counter.
Returns the _new_ stat value. (0 = Could not award achievement) */
unsigned int AwardAchievement(const eStatistic a_Ach);
void SetIP(const AString & a_IP);
// Sets the current gamemode, doesn't check validity, doesn't send update packets to client
void LoginSetGameMode(eGameMode a_GameMode);
/** Forces the player to move in the given direction.
@deprecated Use SetSpeed instead. */
@@ -210,15 +213,15 @@ public:
cWindow * GetWindow(void) { return m_CurrentWindow; } // tolua_export
const cWindow * GetWindow(void) const { return m_CurrentWindow; }
/** Opens the specified window; closes the current one first using CloseWindow() */
void OpenWindow(cWindow * a_Window); // Exported in ManualBindings.cpp
// tolua_begin
/** Closes the current window, resets current window to m_InventoryWindow. A plugin may refuse the closing if a_CanRefuse is true */
void CloseWindow(bool a_CanRefuse = true);
/** Closes the current window if it matches the specified ID, resets current window to m_InventoryWindow */
void CloseWindowIfID(char a_WindowID, bool a_CanRefuse = true);
@@ -243,7 +246,7 @@ public:
const AString & GetName(void) const { return m_PlayerName; }
void SetName(const AString & a_Name) { m_PlayerName = a_Name; }
// tolua_end
bool HasPermission(const AString & a_Permission); // tolua_export
@@ -260,7 +263,7 @@ public:
const AStringVector & GetRestrictions(void) const { return m_Restrictions; } // Exported in ManualBindings.cpp
// tolua_begin
/** Returns the full color code to use for this player, based on their rank.
The returned value either is empty, or includes the cChatColor::Delimiter. */
AString GetColor(void) const;
@@ -279,15 +282,15 @@ public:
/** Heals the player by the specified amount of HPs (positive only); sends health update */
virtual void Heal(int a_Health) override;
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; }
/** Returns true if the player is satiated, i. e. their foodlevel is at the max and they cannot eat anymore */
bool IsSatiated(void) const { return (m_FoodLevel >= MAX_FOOD_LEVEL); }
void SetFoodLevel (int a_FoodLevel);
void SetFoodSaturationLevel (double a_FoodSaturationLevel);
void SetFoodTickTimer (int a_FoodTickTimer);
@@ -298,10 +301,10 @@ public:
/** Adds the specified exhaustion to m_FoodExhaustion. Expects only positive values. */
void AddFoodExhaustion(double a_Exhaustion);
/** Returns true if the player is currently in the process of eating the currently equipped item */
bool IsEating(void) const { return (m_EatingFinishTick >= 0); }
/** Returns true if the player is currently flying. */
bool IsFlying(void) const { return m_IsFlying; }
@@ -329,16 +332,16 @@ public:
GetWorld()->BroadcastEntityAnimation(*this, 2);
}
}
/** Starts eating the currently equipped item. Resets the eating timer and sends the proper animation packet */
void StartEating(void);
/** Finishes eating the currently equipped item. Consumes the item, updates health and broadcasts the packets */
void FinishEating(void);
/** Aborts the current eating operation */
void AbortEating(void);
virtual void KilledBy(TakeDamageInfo & a_TDI) override;
virtual void Killed(cEntity * a_Victim) override;
@@ -356,69 +359,69 @@ public:
bool SaveToDisk(void);
typedef cWorld * cWorldPtr;
/** Loads the player data from the disk file
Sets a_World to the world where the player will spawn, based on the stored world name or the default world by calling LoadFromFile()
Returns true on success, false on failure
*/
bool LoadFromDisk(cWorldPtr & a_World);
/** Loads the player data from the specified file
Sets a_World to the world where the player will spawn, based on the stored world name or the default world
Returns true on success, false on failure
*/
bool LoadFromFile(const AString & a_FileName, cWorldPtr & a_World);
const AString & GetLoadedWorldName() { return m_LoadedWorldName; }
void UseEquippedItem(int a_Amount = 1);
void SendHealth(void);
void SendExperience(void);
/** In UI windows, get the item that the player is dragging */
cItem & GetDraggingItem(void) {return m_DraggingItem; }
// In UI windows, when inventory-painting:
/** Clears the list of slots that are being inventory-painted. To be used by cWindow only */
void ClearInventoryPaintSlots(void);
/** Adds a slot to the list for inventory painting. To be used by cWindow only */
void AddInventoryPaintSlot(int a_SlotNum);
/** Returns the list of slots currently stored for inventory painting. To be used by cWindow only */
const cSlotNums & GetInventoryPaintSlots(void) const;
// tolua_begin
/** Returns the current relative maximum speed (takes current sprinting / flying state into account) */
double GetMaxSpeed(void) const;
/** Gets the normal relative maximum speed */
double GetNormalMaxSpeed(void) const { return m_NormalMaxSpeed; }
/** Gets the sprinting relative maximum speed */
double GetSprintingMaxSpeed(void) const { return m_SprintingMaxSpeed; }
/** Gets the flying relative maximum speed */
double GetFlyingMaxSpeed(void) const { return m_FlyingMaxSpeed; }
/** Sets the normal relative maximum speed. Sends the update to player, if needed. */
void SetNormalMaxSpeed(double a_Speed);
/** Sets the sprinting relative maximum speed. Sends the update to player, if needed. */
void SetSprintingMaxSpeed(double a_Speed);
/** Sets the flying relative maximum speed. Sends the update to player, if needed. */
void SetFlyingMaxSpeed(double a_Speed);
/** Sets the crouch status, broadcasts to all visible players */
void SetCrouch(bool a_IsCrouched);
/** Starts or stops sprinting, sends the max speed update to the client, if needed */
void SetSprint(bool a_IsSprinting);
/** Flags the player as flying */
void SetFlying(bool a_IsFlying);
@@ -442,17 +445,17 @@ public:
/** Sets the player's bed (home) position */
void SetBedPos(const Vector3i & a_Pos) { m_LastBedPos = a_Pos; }
// tolua_end
/** Update movement-related statistics. */
void UpdateMovementStats(const Vector3d & a_DeltaPos);
// tolua_begin
/** Returns wheter the player can fly or not. */
virtual bool CanFly(void) const { return m_CanFly; }
/** Returns the UUID (short format) that has been read from the client, or empty string if not available. */
const AString & GetUUID(void) const { return m_UUID; }
@@ -492,7 +495,7 @@ public:
/** Called by cClientHandle when the client is being destroyed.
The player removes its m_ClientHandle ownership so that the ClientHandle gets deleted. */
void RemoveClientHandle(void);
protected:
typedef std::vector<std::vector<AString> > AStringVectorVector;
@@ -535,16 +538,16 @@ protected:
// 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;
float m_LastJumpHeight;
float m_LastGroundHeight;
bool m_bTouchGround;
@@ -564,31 +567,31 @@ protected:
eGameMode m_GameMode;
AString m_IP;
/** The item being dragged by the cursor while in a UI window */
cItem m_DraggingItem;
std::chrono::steady_clock::time_point m_LastPlayerListTime;
cClientHandlePtr m_ClientHandle;
cSlotNums m_InventoryPaintSlots;
/** Max speed, relative to the game default.
1 means regular speed, 2 means twice as fast, 0.5 means half-speed.
Default value is 1. */
double m_NormalMaxSpeed;
/** Max speed, relative to the game default max speed, when sprinting.
1 means regular speed, 2 means twice as fast, 0.5 means half-speed.
Default value is 1.3. */
double m_SprintingMaxSpeed;
/** Max speed, relative to the game default flying max speed, when flying.
1 means regular speed, 2 means twice as fast, 0.5 means half-speed.
Default value is 1. */
double m_FlyingMaxSpeed;
bool m_IsCrouched;
bool m_IsSprinting;
bool m_IsFlying;
@@ -629,7 +632,7 @@ protected:
Will not apply food penalties if found to be true; will set to false after processing
*/
bool m_bIsTeleporting;
/** The short UUID (no dashes) of the player, as read from the ClientHandle.
If no ClientHandle is given, the UUID is initialized to empty. */
AString m_UUID;
@@ -649,7 +652,7 @@ protected:
/** Stops players from burning in creative mode */
virtual void TickBurning(cChunk & a_Chunk) override;
/** Called in each tick to handle food-related processing */
void HandleFood(void);
@@ -666,7 +669,3 @@ protected:
This can be used both for online and offline UUIDs. */
AString GetUUIDFileName(const AString & a_UUID);
} ; // tolua_export

View File

@@ -1259,7 +1259,7 @@ bool cFinishGenPassiveMobs::TrySpawnAnimals(cChunkDesc & a_ChunkDesc, int a_RelX
}
if (
(BlockUnderFeet != E_BLOCK_GRASS) &&
((AnimalToSpawn == mtSheep) || (AnimalToSpawn == mtChicken) || (AnimalToSpawn == mtPig))
((AnimalToSpawn == mtWolf) || (AnimalToSpawn == mtRabbit) || (AnimalToSpawn == mtCow) || (AnimalToSpawn == mtSheep) || (AnimalToSpawn == mtChicken) || (AnimalToSpawn == mtPig))
)
{
return false;

View File

@@ -80,6 +80,13 @@ public:
return false;
}
// Check to see if destination block is too far away
// Reach Distance Multiplayer = 5 Blocks
if ((BlockPos.x - a_Player->GetPosX() > 5) || (BlockPos.z - a_Player->GetPosZ() > 5))
{
return false;
}
// Remove water / lava block (unless plugins disagree)
if (!a_Player->PlaceBlock(BlockPos.x, BlockPos.y, BlockPos.z, E_BLOCK_AIR, 0))
{
@@ -126,6 +133,13 @@ public:
{
return false;
}
// Check to see if destination block is too far away
// Reach Distance Multiplayer = 5 Blocks
if ((BlockPos.x - a_Player->GetPosX() > 5) || (BlockPos.z - a_Player->GetPosZ() > 5))
{
return false;
}
if (a_Player->GetGameMode() != gmCreative)
{

View File

@@ -169,7 +169,7 @@ bool cMonster::TickPathFinding(cChunk & a_Chunk)
m_NoPathToTarget = false;
m_NoMoreWayPoints = false;
m_PathFinderDestination = m_FinalDestination;
m_Path = new cPath(a_Chunk, GetPosition().Floor(), m_PathFinderDestination.Floor(), 20);
m_Path = new cPath(a_Chunk, GetPosition(), m_PathFinderDestination, 20, GetWidth(), GetHeight());
}
switch (m_Path->Step(a_Chunk))
@@ -183,7 +183,7 @@ bool cMonster::TickPathFinding(cChunk & a_Chunk)
case ePathFinderStatus::PATH_NOT_FOUND:
{
ResetPathFinding(); // Try to calculate a path again.
StopMovingToPosition(); // Try to calculate a path again.
// Note that the next time may succeed, e.g. if a player breaks a barrier.
break;
}
@@ -203,7 +203,7 @@ bool cMonster::TickPathFinding(cChunk & a_Chunk)
{
if ((m_Path->IsFirstPoint() || ReachedNextWaypoint()))
{
m_NextWayPointPosition = Vector3d(0.5, 0, 0.5) + m_Path->GetNextPoint();
m_NextWayPointPosition = m_Path->GetNextPoint();
m_GiveUpCounter = 40; // Give up after 40 ticks (2 seconds) if failed to reach m_NextWayPointPosition.
}
}

View File

@@ -6,6 +6,7 @@
#include "Path.h"
#include "../Chunk.h"
#define JUMP_G_COST 20
#define DISTANCE_MANHATTAN 0 // 1: More speed, a bit less accuracy 0: Max accuracy, less speed.
#define HEURISTICS_ONLY 0 // 1: Much more speed, much less accurate.
@@ -31,12 +32,11 @@ bool compareHeuristics::operator()(cPathCell * & a_Cell1, cPathCell * & a_Cell2)
/* cPath implementation */
cPath::cPath(
cChunk & a_Chunk,
const Vector3i & a_StartingPoint, const Vector3i & a_EndingPoint, int a_MaxSteps,
const Vector3d & a_StartingPoint, const Vector3d & a_EndingPoint, int a_MaxSteps,
double a_BoundingBoxWidth, double a_BoundingBoxHeight,
int a_MaxUp, int a_MaxDown
) :
m_Destination(a_EndingPoint.Floor()),
m_Source(a_StartingPoint.Floor()),
m_CurrentPoint(0), // GetNextPoint increments this to 1, but that's fine, since the first cell is always a_StartingPoint
m_Chunk(&a_Chunk),
m_BadChunkFound(false)
@@ -44,6 +44,21 @@ cPath::cPath(
// TODO: if src not walkable OR dest not walkable, then abort.
// Borrow a new "isWalkable" from ProcessIfWalkable, make ProcessIfWalkable also call isWalkable
a_BoundingBoxWidth = 1; // Until we improve physics, if ever.
m_BoundingBoxWidth = ceil(a_BoundingBoxWidth);
m_BoundingBoxHeight = ceil(a_BoundingBoxHeight);
m_HalfWidth = a_BoundingBoxWidth / 2;
int HalfWidthInt = a_BoundingBoxWidth / 2;
m_Source.x = floor(a_StartingPoint.x - HalfWidthInt);
m_Source.y = floor(a_StartingPoint.y);
m_Source.z = floor(a_StartingPoint.z - HalfWidthInt);
m_Destination.x = floor(a_EndingPoint.x - HalfWidthInt);
m_Destination.y = floor(a_EndingPoint.y);
m_Destination.z = floor(a_EndingPoint.z - HalfWidthInt);
if (GetCell(m_Source)->m_IsSolid || GetCell(m_Destination)->m_IsSolid)
{
m_Status = ePathFinderStatus::PATH_NOT_FOUND;
@@ -148,7 +163,7 @@ bool cPath::IsSolid(const Vector3i & a_Location)
}
if (BlockType == E_BLOCK_STATIONARY_WATER)
{
GetCell(a_Location + Vector3i(0, -1, 0))->m_IsSolid = true; // Mobs will always think that the fence is 2 blocks high and therefore won't jump over.
GetCell(a_Location + Vector3i(0, -1, 0))->m_IsSolid = true;
}
return cBlockInfo::IsSolid(BlockType);
@@ -179,7 +194,7 @@ bool cPath::Step_Internal()
// Calculation not finished yet.
// Check if we have a new NearestPoint.
// TODO I don't like this that much, there should be a smarter way.
if ((m_Destination - CurrentCell->m_Location).Length() < 5)
{
if (m_Rand.NextInt(4) == 0)
@@ -193,21 +208,43 @@ bool cPath::Step_Internal()
}
// process a currentCell by inspecting all neighbors.
// Check North, South, East, West on all 3 different heights.
int i;
for (i = -1; i <= 1; ++i)
// Check North, South, East, West on our height.
ProcessIfWalkable(CurrentCell->m_Location + Vector3i(1, 0, 0), CurrentCell, 10);
ProcessIfWalkable(CurrentCell->m_Location + Vector3i(-1, 0, 0), CurrentCell, 10);
ProcessIfWalkable(CurrentCell->m_Location + Vector3i(0, 0, 1), CurrentCell, 10);
ProcessIfWalkable(CurrentCell->m_Location + Vector3i(0, 0, -1), CurrentCell, 10);
// Check diagonals on XY plane.
for (int x = -1; x <= 1; x += 2)
{
ProcessIfWalkable(CurrentCell->m_Location + Vector3i(1, i, 0), CurrentCell, 10);
ProcessIfWalkable(CurrentCell->m_Location + Vector3i(-1, i, 0), CurrentCell, 10);
ProcessIfWalkable(CurrentCell->m_Location + Vector3i(0, i, 1), CurrentCell, 10);
ProcessIfWalkable(CurrentCell->m_Location + Vector3i(0, i, -1), CurrentCell, 10);
if (GetCell(CurrentCell->m_Location + Vector3i(x, 0, 0))->m_IsSolid) // If there's a solid our east / west.
{
ProcessIfWalkable(CurrentCell->m_Location + Vector3i(x, 1, 0), CurrentCell, JUMP_G_COST); // Check east / west-up.
}
else
{
ProcessIfWalkable(CurrentCell->m_Location + Vector3i(x, -1, 0), CurrentCell, 14); // Else check east / west-down.
}
}
// Check diagonals on mob's height only.
int x, z;
for (x = -1; x <= 1; x += 2)
// Check diagonals on the YZ plane.
for (int z = -1; z <= 1; z += 2)
{
for (z = -1; z <= 1; z += 2)
if (GetCell(CurrentCell->m_Location + Vector3i(0, 0, z))->m_IsSolid) // If there's a solid our east / west.
{
ProcessIfWalkable(CurrentCell->m_Location + Vector3i(0, 1, z), CurrentCell, JUMP_G_COST); // Check east / west-up.
}
else
{
ProcessIfWalkable(CurrentCell->m_Location + Vector3i(0, -1, z), CurrentCell, 14); // Else check east / west-down.
}
}
// Check diagonals on the XZ plane. (Normal diagonals, this plane is special because of gravity, etc)
for (int x = -1; x <= 1; x += 2)
{
for (int z = -1; z <= 1; z += 2)
{
// This condition prevents diagonal corner cutting.
if (!GetCell(CurrentCell->m_Location + Vector3i(x, 0, 0))->m_IsSolid && !GetCell(CurrentCell->m_Location + Vector3i(0, 0, z))->m_IsSolid)
@@ -320,7 +357,53 @@ si::setBlock((Ret)->m_Location.x, (Ret)->m_Location.y, (Ret)->m_Location.z, debu
void cPath::ProcessIfWalkable(const Vector3i & a_Location, cPathCell * a_Parent, int a_Cost)
{
cPathCell * cell = GetCell(a_Location);
if (!cell->m_IsSolid && GetCell(a_Location + Vector3i(0, -1, 0))->m_IsSolid && !GetCell(a_Location + Vector3i(0, 1, 0))->m_IsSolid)
int x, y, z;
// Make sure we fit in the position.
for (y = 0; y < m_BoundingBoxHeight; ++y)
{
for (x = 0; x < m_BoundingBoxWidth; ++x)
{
for (z = 0; z < m_BoundingBoxWidth; ++z)
{
if (GetCell(a_Location + Vector3i(x, y, z))->m_IsSolid)
{
return;
}
}
}
}
/*y =-1;
for (x = 0; x < m_BoundingBoxWidth; ++x)
{
for (z = 0; z < m_BoundingBoxWidth; ++z)
{
if (!GetCell(a_Location + Vector3i(x, y, z))->m_IsSolid)
{
return;
}
}
}
ProcessCell(cell, a_Parent, a_Cost);*/
// Make sure there's at least 1 piece of solid below us.
bool GroundFlag = false;
y =-1;
for (x = 0; x < m_BoundingBoxWidth; ++x)
{
for (z = 0; z < m_BoundingBoxWidth; ++z)
{
if (GetCell(a_Location + Vector3i(x, y, z))->m_IsSolid)
{
GroundFlag = true;
break;
}
}
}
if (GroundFlag)
{
ProcessCell(cell, a_Parent, a_Cost);
}

View File

@@ -68,8 +68,8 @@ public:
@param a_MaxSteps The maximum steps before giving up. */
cPath(
cChunk & a_Chunk,
const Vector3i & a_StartingPoint, const Vector3i & a_EndingPoint, int a_MaxSteps,
double a_BoundingBoxWidth = 1, double a_BoundingBoxHeight = 2,
const Vector3d & a_StartingPoint, const Vector3d & a_EndingPoint, int a_MaxSteps,
double a_BoundingBoxWidth, double a_BoundingBoxHeight,
int a_MaxUp = 1, int a_MaxDown = 1
);
@@ -89,10 +89,11 @@ public:
/* Point retrieval functions, inlined for performance. */
/** Returns the next point in the path. */
inline Vector3i GetNextPoint()
inline Vector3d GetNextPoint()
{
ASSERT(m_Status == ePathFinderStatus::PATH_FOUND);
return m_PathPoints[m_PathPoints.size() - 1 - (++m_CurrentPoint)];
Vector3i Point = m_PathPoints[m_PathPoints.size() - 1 - (++m_CurrentPoint)];
return Vector3d(Point.x + m_HalfWidth, Point.y, Point.z + m_HalfWidth);
}
/** Checks whether this is the last point or not. Never call getnextPoint when this is true. */
inline bool IsLastPoint()
@@ -106,11 +107,12 @@ public:
return (m_CurrentPoint == 0);
}
/** Get the point at a_index. Remark: Internally, the indexes are reversed. */
inline Vector3i GetPoint(size_t a_index)
inline Vector3d GetPoint(size_t a_index)
{
ASSERT(m_Status == ePathFinderStatus::PATH_FOUND);
ASSERT(a_index < m_PathPoints.size());
return m_PathPoints[m_PathPoints.size() - 1 - a_index];
Vector3i Point = m_PathPoints[m_PathPoints.size() - 1 - a_index];
return Vector3d(Point.x + m_HalfWidth, Point.y, Point.z + m_HalfWidth);
}
/** Returns the total number of points this path has. */
inline size_t GetPointCount()
@@ -161,6 +163,9 @@ private:
std::unordered_map<Vector3i, cPathCell, VectorHasher> m_Map;
Vector3i m_Destination;
Vector3i m_Source;
int m_BoundingBoxWidth;
int m_BoundingBoxHeight;
double m_HalfWidth;
int m_StepsLeft;
cPathCell * m_NearestPointToTarget;
cFastRandom m_Rand;