summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Bindings/ManualBindings_World.cpp2
-rw-r--r--src/Bindings/Plugin.h2
-rw-r--r--src/Bindings/PluginLua.cpp6
-rw-r--r--src/Bindings/PluginLua.h4
-rw-r--r--src/Bindings/PluginManager.cpp6
-rw-r--r--src/Bindings/PluginManager.h4
-rw-r--r--src/BlockEntities/BlockEntityWithItems.h2
-rw-r--r--src/BlockEntities/NoteEntity.h2
-rw-r--r--src/Blocks/BlockDoor.cpp20
-rw-r--r--src/Blocks/BlockTorch.h5
-rw-r--r--src/Blocks/BlockVine.h2
-rw-r--r--src/Entities/Entity.cpp6
-rw-r--r--src/Entities/Minecart.h2
-rw-r--r--src/Entities/Player.cpp138
-rw-r--r--src/Entities/Player.h177
-rw-r--r--src/Generating/FinishGen.cpp2
-rw-r--r--src/Generating/TwoHeights.cpp2
-rw-r--r--src/Generating/VillageGen.cpp4
-rw-r--r--src/IniFile.h28
-rw-r--r--src/Items/ItemSign.h2
-rw-r--r--src/Mobs/AggressiveMonster.cpp6
-rw-r--r--src/Mobs/Horse.h2
-rw-r--r--src/Mobs/Monster.cpp9
-rw-r--r--src/Mobs/Path.cpp127
-rw-r--r--src/Mobs/Path.h27
-rw-r--r--src/Mobs/Wolf.h4
-rw-r--r--src/OverridesSettingsRepository.cpp2
-rw-r--r--src/PolarSSL++/BlockingSslClientSocket.cpp6
-rw-r--r--src/PolarSSL++/BlockingSslClientSocket.h5
-rw-r--r--src/PolarSSL++/SslContext.cpp2
-rw-r--r--src/Protocol/Authenticator.cpp8
-rw-r--r--src/Protocol/MojangAPI.cpp38
-rw-r--r--src/RCONServer.h2
-rw-r--r--src/Server.cpp2
-rw-r--r--src/UI/SlotArea.h2
-rw-r--r--src/World.cpp3
-rw-r--r--src/World.h8
-rw-r--r--src/main.cpp54
38 files changed, 448 insertions, 275 deletions
diff --git a/src/Bindings/ManualBindings_World.cpp b/src/Bindings/ManualBindings_World.cpp
index 3ee5ca498..5becbba92 100644
--- a/src/Bindings/ManualBindings_World.cpp
+++ b/src/Bindings/ManualBindings_World.cpp
@@ -530,7 +530,7 @@ static int tolua_cWorld_TryGetHeight(lua_State * tolua_S)
// Call the implementation:
int Height = 0;
bool res = self->TryGetHeight(BlockX, BlockZ, Height);
- L.Push(res ? 1 : 0);
+ L.Push(res);
if (res)
{
L.Push(Height);
diff --git a/src/Bindings/Plugin.h b/src/Bindings/Plugin.h
index b4bbfd802..1330bca0d 100644
--- a/src/Bindings/Plugin.h
+++ b/src/Bindings/Plugin.h
@@ -56,7 +56,7 @@ public:
virtual bool OnDisconnect (cClientHandle & a_Client, const AString & a_Reason) = 0;
virtual bool OnEntityAddEffect (cEntity & a_Entity, int a_EffectType, int a_EffectDurationTicks, int a_EffectIntensity, double a_DistanceModifier) = 0;
virtual bool OnEntityTeleport (cEntity & a_Entity, const Vector3d & a_OldPosition, const Vector3d & a_NewPosition) = 0;
- virtual bool OnEntityChangeWorld (cEntity & a_Entity, cWorld & a_World) = 0;
+ virtual bool OnEntityChangingWorld (cEntity & a_Entity, cWorld & a_World) = 0;
virtual bool OnEntityChangedWorld (cEntity & a_Entity, cWorld & a_World) = 0;
virtual bool OnExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand, cPluginManager::CommandResult & a_Result) = 0;
virtual bool OnExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) = 0;
diff --git a/src/Bindings/PluginLua.cpp b/src/Bindings/PluginLua.cpp
index a8be26f71..234bf579b 100644
--- a/src/Bindings/PluginLua.cpp
+++ b/src/Bindings/PluginLua.cpp
@@ -534,7 +534,7 @@ bool cPluginLua::OnEntityAddEffect(cEntity & a_Entity, int a_EffectType, int a_E
-bool cPluginLua::OnEntityChangeWorld(cEntity & a_Entity, cWorld & a_World)
+bool cPluginLua::OnEntityChangingWorld(cEntity & a_Entity, cWorld & a_World)
{
cCSLock Lock(m_CriticalSection);
if (!m_LuaState.IsValid())
@@ -542,7 +542,7 @@ bool cPluginLua::OnEntityChangeWorld(cEntity & a_Entity, cWorld & a_World)
return false;
}
bool res = false;
- cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_ENTITY_CHANGE_WORLD];
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_ENTITY_CHANGING_WORLD];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{
m_LuaState.Call((int)(**itr), &a_Entity, &a_World, cLuaState::Return, res);
@@ -1932,7 +1932,7 @@ const char * cPluginLua::GetHookFnName(int a_HookType)
case cPluginManager::HOOK_DISCONNECT: return "OnDisconnect";
case cPluginManager::HOOK_PLAYER_ANIMATION: return "OnPlayerAnimation";
case cPluginManager::HOOK_ENTITY_ADD_EFFECT: return "OnEntityAddEffect";
- case cPluginManager::HOOK_ENTITY_CHANGE_WORLD: return "OnEntityChangeWorld";
+ case cPluginManager::HOOK_ENTITY_CHANGING_WORLD: return "OnEntityChangingWorld";
case cPluginManager::HOOK_ENTITY_CHANGED_WORLD: return "OnEntityChangedWorld";
case cPluginManager::HOOK_ENTITY_TELEPORT: return "OnEntityTeleport";
case cPluginManager::HOOK_EXECUTE_COMMAND: return "OnExecuteCommand";
diff --git a/src/Bindings/PluginLua.h b/src/Bindings/PluginLua.h
index 533dc0331..a763cdfdf 100644
--- a/src/Bindings/PluginLua.h
+++ b/src/Bindings/PluginLua.h
@@ -115,7 +115,7 @@ public:
virtual bool OnCraftingNoRecipe (cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe) override;
virtual bool OnDisconnect (cClientHandle & a_Client, const AString & a_Reason) override;
virtual bool OnEntityAddEffect (cEntity & a_Entity, int a_EffectType, int a_EffectDurationTicks, int a_EffectIntensity, double a_DistanceModifier) override;
- virtual bool OnEntityChangeWorld (cEntity & a_Entity, cWorld & a_World) override;
+ virtual bool OnEntityChangingWorld (cEntity & a_Entity, cWorld & a_World) override;
virtual bool OnEntityChangedWorld (cEntity & a_Entity, cWorld & a_World) override;
virtual bool OnExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand, cPluginManager::CommandResult & a_Result) override;
virtual bool OnExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) override;
@@ -179,7 +179,7 @@ public:
bool CanAddOldStyleHook(int a_HookType);
// cWebPlugin overrides
- virtual const AString GetWebTitle(void) const {return GetName(); }
+ virtual const AString GetWebTitle(void) const override {return GetName(); }
virtual AString HandleWebRequest(const HTTPRequest & a_Request) override;
/** Adds a new web tab to webadmin.
diff --git a/src/Bindings/PluginManager.cpp b/src/Bindings/PluginManager.cpp
index 6fb6ef4fa..4dc3e20d3 100644
--- a/src/Bindings/PluginManager.cpp
+++ b/src/Bindings/PluginManager.cpp
@@ -525,14 +525,14 @@ bool cPluginManager::CallHookEntityTeleport(cEntity & a_Entity, const Vector3d &
-bool cPluginManager::CallHookEntityChangeWorld(cEntity & a_Entity, cWorld & a_World)
+bool cPluginManager::CallHookEntityChangingWorld(cEntity & a_Entity, cWorld & a_World)
{
- FIND_HOOK(HOOK_ENTITY_CHANGE_WORLD);
+ FIND_HOOK(HOOK_ENTITY_CHANGING_WORLD);
VERIFY_HOOK;
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
- if ((*itr)->OnEntityChangeWorld(a_Entity, a_World))
+ if ((*itr)->OnEntityChangingWorld(a_Entity, a_World))
{
return true;
}
diff --git a/src/Bindings/PluginManager.h b/src/Bindings/PluginManager.h
index e528c049f..6bcef87bf 100644
--- a/src/Bindings/PluginManager.h
+++ b/src/Bindings/PluginManager.h
@@ -86,7 +86,7 @@ public:
HOOK_DISCONNECT,
HOOK_PLAYER_ANIMATION,
HOOK_ENTITY_ADD_EFFECT,
- HOOK_ENTITY_CHANGE_WORLD,
+ HOOK_ENTITY_CHANGING_WORLD,
HOOK_ENTITY_CHANGED_WORLD,
HOOK_EXECUTE_COMMAND,
HOOK_EXPLODED,
@@ -203,7 +203,7 @@ public:
bool CallHookDisconnect (cClientHandle & a_Client, const AString & a_Reason);
bool CallHookEntityAddEffect (cEntity & a_Entity, int a_EffectType, int a_EffectDurationTicks, int a_EffectIntensity, double a_DistanceModifier);
bool CallHookEntityTeleport (cEntity & a_Entity, const Vector3d & a_OldPosition, const Vector3d & a_NewPosition);
- bool CallHookEntityChangeWorld (cEntity & a_Entity, cWorld & a_World);
+ bool CallHookEntityChangingWorld (cEntity & a_Entity, cWorld & a_World);
bool CallHookEntityChangedWorld (cEntity & a_Entity, cWorld & a_World);
bool CallHookExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand, CommandResult & a_Result); // If a_Player == nullptr, it is a console cmd
bool CallHookExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData);
diff --git a/src/BlockEntities/BlockEntityWithItems.h b/src/BlockEntities/BlockEntityWithItems.h
index 740dbca51..30a09bc02 100644
--- a/src/BlockEntities/BlockEntityWithItems.h
+++ b/src/BlockEntities/BlockEntityWithItems.h
@@ -76,7 +76,7 @@ protected:
cItemGrid m_Contents;
// cItemGrid::cListener overrides:
- virtual void OnSlotChanged(cItemGrid * a_Grid, int a_SlotNum)
+ virtual void OnSlotChanged(cItemGrid * a_Grid, int a_SlotNum) override
{
UNUSED(a_SlotNum);
ASSERT(a_Grid == &m_Contents);
diff --git a/src/BlockEntities/NoteEntity.h b/src/BlockEntities/NoteEntity.h
index d3f85e9d2..f350ef4c4 100644
--- a/src/BlockEntities/NoteEntity.h
+++ b/src/BlockEntities/NoteEntity.h
@@ -52,7 +52,7 @@ public:
virtual void UsedBy(cPlayer * a_Player) override;
virtual void SendTo(cClientHandle &) override {}
- virtual void SetRedstonePower(bool a_Value)
+ virtual void SetRedstonePower(bool a_Value) override
{
if (a_Value)
{
diff --git a/src/Blocks/BlockDoor.cpp b/src/Blocks/BlockDoor.cpp
index d13c8d657..a4e375cf0 100644
--- a/src/Blocks/BlockDoor.cpp
+++ b/src/Blocks/BlockDoor.cpp
@@ -50,10 +50,24 @@ void cBlockDoorHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterfac
UNUSED(a_CursorY);
UNUSED(a_CursorZ);
- if (a_ChunkInterface.GetBlock(a_BlockX, a_BlockY, a_BlockZ) == E_BLOCK_WOODEN_DOOR)
+ switch (a_ChunkInterface.GetBlock(a_BlockX, a_BlockY, a_BlockZ))
{
- ChangeDoor(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ);
- a_Player->GetWorld()->BroadcastSoundParticleEffect(1003, a_BlockX, a_BlockY, a_BlockZ, 0, a_Player->GetClientHandle());
+ default:
+ {
+ ASSERT(!"Unhandled door block type");
+ }
+ case E_BLOCK_ACACIA_DOOR:
+ case E_BLOCK_BIRCH_DOOR:
+ case E_BLOCK_DARK_OAK_DOOR:
+ case E_BLOCK_JUNGLE_DOOR:
+ case E_BLOCK_SPRUCE_DOOR:
+ case E_BLOCK_IRON_DOOR:
+ case E_BLOCK_WOODEN_DOOR:
+ {
+ ChangeDoor(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ);
+ a_Player->GetWorld()->BroadcastSoundParticleEffect(1003, a_BlockX, a_BlockY, a_BlockZ, 0, a_Player->GetClientHandle());
+ break;
+ }
}
}
diff --git a/src/Blocks/BlockTorch.h b/src/Blocks/BlockTorch.h
index d63df94cf..3abc572f3 100644
--- a/src/Blocks/BlockTorch.h
+++ b/src/Blocks/BlockTorch.h
@@ -103,6 +103,11 @@ public:
case E_BLOCK_STAINED_GLASS:
case E_BLOCK_FENCE:
case E_BLOCK_NETHER_BRICK_FENCE:
+ case E_BLOCK_SPRUCE_FENCE:
+ case E_BLOCK_BIRCH_FENCE:
+ case E_BLOCK_JUNGLE_FENCE:
+ case E_BLOCK_DARK_OAK_FENCE:
+ case E_BLOCK_ACACIA_FENCE:
case E_BLOCK_COBBLESTONE_WALL:
{
// Torches can only be placed on top of these blocks
diff --git a/src/Blocks/BlockVine.h b/src/Blocks/BlockVine.h
index 00d7a69b8..3d06a8223 100644
--- a/src/Blocks/BlockVine.h
+++ b/src/Blocks/BlockVine.h
@@ -177,7 +177,7 @@ public:
}
- virtual void OnUpdate(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_BlockPluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
+ virtual void OnUpdate(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_BlockPluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override
{
UNUSED(a_ChunkInterface);
UNUSED(a_WorldInterface);
diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp
index bc2b3e93e..dca44488b 100644
--- a/src/Entities/Entity.cpp
+++ b/src/Entities/Entity.cpp
@@ -1403,10 +1403,10 @@ bool cEntity::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn)
return false;
}
- // Ask the plugins if the entity is allowed to change the world
- if (cRoot::Get()->GetPluginManager()->CallHookEntityChangeWorld(*this, *a_World))
+ // Ask the plugins if the entity is allowed to changing the world
+ if (cRoot::Get()->GetPluginManager()->CallHookEntityChangingWorld(*this, *a_World))
{
- // A Plugin doesn't allow the entity to change the world
+ // A Plugin doesn't allow the entity to changing the world
return false;
}
diff --git a/src/Entities/Minecart.h b/src/Entities/Minecart.h
index d1736e9b9..05eaf16e9 100644
--- a/src/Entities/Minecart.h
+++ b/src/Entities/Minecart.h
@@ -135,7 +135,7 @@ protected:
virtual void Destroyed() override;
// cItemGrid::cListener overrides:
- virtual void OnSlotChanged(cItemGrid * a_Grid, int a_SlotNum)
+ virtual void OnSlotChanged(cItemGrid * a_Grid, int a_SlotNum) override
{
UNUSED(a_SlotNum);
ASSERT(a_Grid == &m_Contents);
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp
index 01ad26297..e3e3fac4f 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -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()
);
@@ -128,7 +128,14 @@ cPlayer::cPlayer(cClientHandlePtr a_Client, const AString & a_PlayerName) :
m_IsFlying = true;
}
}
-
+
+ if (m_GameMode == gmSpectator) // If player is reconnecting to the server in spectator mode
+ {
+ m_CanFly = true;
+ m_IsFlying = true;
+ m_bVisible = false;
+ }
+
cRoot::Get()->GetServer()->PlayerCreated(this);
}
@@ -145,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);
}
@@ -201,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
@@ -210,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)
{
@@ -236,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;
@@ -257,10 +264,10 @@ void cPlayer::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
FinishEating();
}
-
+
HandleFood();
}
-
+
if (m_IsFishing)
{
HandleFloater();
@@ -460,7 +467,7 @@ void cPlayer::SetTouchGround(bool a_bTouchGround)
{
return;
}
-
+
m_bTouchGround = a_bTouchGround;
if (!m_bTouchGround)
@@ -509,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 */);
}
@@ -541,7 +548,7 @@ void cPlayer::SetFoodLevel(int a_FoodLevel)
m_FoodSaturationLevel = 5.0;
return;
}
-
+
m_FoodLevel = FoodLevel;
SendHealth();
}
@@ -609,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);
@@ -623,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);
@@ -757,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();
}
@@ -769,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
@@ -790,7 +797,7 @@ void cPlayer::SetSprint(bool a_IsSprinting)
// No change
return;
}
-
+
m_IsSprinting = a_IsSprinting;
m_ClientHandle->SendPlayerMaxSpeed();
}
@@ -876,7 +883,7 @@ bool cPlayer::DoTakeDamage(TakeDamageInfo & a_TDI)
}
}
}
-
+
if (super::DoTakeDamage(a_TDI))
{
// Any kind of damage adds food exhaustion
@@ -1005,7 +1012,7 @@ void cPlayer::Respawn(void)
m_Health = GetMaxHealth();
SetInvulnerableTicks(20);
-
+
// Reset food level:
m_FoodLevel = MAX_FOOD_LEVEL;
m_FoodSaturationLevel = 5.0;
@@ -1017,7 +1024,7 @@ void cPlayer::Respawn(void)
// ToDo: send score to client? How?
m_ClientHandle->SendRespawn(GetWorld()->GetDimension(), true);
-
+
// Extinguish the fire:
StopBurning();
@@ -1151,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):
@@ -1189,21 +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);
- }
+ SetCapabilities();
m_World->BroadcastPlayerListUpdateGameMode(*this);
}
@@ -1215,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);
+ }
}
@@ -1306,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;
}
@@ -1323,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;
}
@@ -1370,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);
}
@@ -1411,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:
@@ -1583,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;
@@ -1605,10 +1632,11 @@ bool cPlayer::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn)
// Don't move to same world
return false;
}
-
- if (cRoot::Get()->GetPluginManager()->CallHookEntityChangeWorld(*this, *a_World))
+
+ // Ask the plugins if the player is allowed to changing the world
+ if (cRoot::Get()->GetPluginManager()->CallHookEntityChangingWorld(*this, *a_World))
{
- // A Plugin doesn't allow the player to change the world
+ // A Plugin doesn't allow the player to changing the world
return false;
}
@@ -1641,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);
@@ -1661,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)";
@@ -1673,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())
{
@@ -1688,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
@@ -1765,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);
@@ -1784,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;
}
@@ -2144,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
@@ -2347,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('/');
@@ -2355,7 +2383,3 @@ AString cPlayer::GetUUIDFileName(const AString & a_UUID)
res.append(".json");
return res;
}
-
-
-
-
diff --git a/src/Entities/Player.h b/src/Entities/Player.h
index a0cd9b1d6..a84fdd0c7 100644
--- a/src/Entities/Player.h
+++ b/src/Entities/Player.h
@@ -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; }
@@ -483,16 +486,16 @@ public:
bool PlaceBlocks(const sSetBlockVector & a_Blocks);
// cEntity overrides:
- virtual bool IsCrouched (void) const { return m_IsCrouched; }
- virtual bool IsSprinting(void) const { return m_IsSprinting; }
- virtual bool IsRclking (void) const { return IsEating() || IsChargingBow(); }
+ virtual bool IsCrouched (void) const override { return m_IsCrouched; }
+ virtual bool IsSprinting(void) const override { return m_IsSprinting; }
+ virtual bool IsRclking (void) const override { return IsEating() || IsChargingBow(); }
- virtual void Detach(void);
+ virtual void Detach(void) override;
/** 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;
@@ -642,14 +645,14 @@ protected:
void ResolvePermissions(void);
void ResolveGroups(void);
- virtual void Destroyed(void);
+ virtual void Destroyed(void) override;
/** Filters out damage for creative mode / friendly fire */
virtual bool DoTakeDamage(TakeDamageInfo & TDI) override;
/** 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
-
-
-
-
diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp
index 69ae59c18..c988224e6 100644
--- a/src/Generating/FinishGen.cpp
+++ b/src/Generating/FinishGen.cpp
@@ -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;
diff --git a/src/Generating/TwoHeights.cpp b/src/Generating/TwoHeights.cpp
index e75c301de..06c474458 100644
--- a/src/Generating/TwoHeights.cpp
+++ b/src/Generating/TwoHeights.cpp
@@ -69,7 +69,7 @@ public:
}
- virtual void InitializeShapeGen(cIniFile & a_IniFile)
+ virtual void InitializeShapeGen(cIniFile & a_IniFile) override
{
m_FrequencyX = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "TwoHeightsFrequencyX", 40));
m_FrequencyY = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "TwoHeightsFrequencyY", 40));
diff --git a/src/Generating/VillageGen.cpp b/src/Generating/VillageGen.cpp
index a3f8caa46..27146e757 100644
--- a/src/Generating/VillageGen.cpp
+++ b/src/Generating/VillageGen.cpp
@@ -259,13 +259,13 @@ protected:
// cPiecePool overrides:
- virtual cPieces GetPiecesWithConnector(int a_ConnectorType)
+ virtual cPieces GetPiecesWithConnector(int a_ConnectorType) override
{
return m_Prefabs.GetPiecesWithConnector(a_ConnectorType);
}
- virtual cPieces GetStartingPieces(void)
+ virtual cPieces GetStartingPieces(void) override
{
return m_Prefabs.GetStartingPieces();
}
diff --git a/src/IniFile.h b/src/IniFile.h
index 861be3800..2a4113fb4 100644
--- a/src/IniFile.h
+++ b/src/IniFile.h
@@ -89,7 +89,7 @@ public:
void Clear(void);
/** Returns true iff the specified value exists. */
- bool HasValue(const AString & a_KeyName, const AString & a_ValueName) const;
+ bool HasValue(const AString & a_KeyName, const AString & a_ValueName) const override;
/// Returns index of specified key, or noID if not found
int FindKey(const AString & keyname) const;
@@ -101,7 +101,7 @@ public:
int GetNumKeys(void) const { return (int)keys.size(); }
/// Add a key name
- int AddKeyName(const AString & keyname);
+ int AddKeyName(const AString & keyname) override;
// Returns key names by index.
AString GetKeyName(const int keyID) const;
@@ -117,7 +117,7 @@ public:
// Gets value of [keyname] valuename =.
// Overloaded to return string, int, and double.
// Returns defValue if key / value not found.
- AString GetValue (const AString & keyname, const AString & valuename, const AString & defValue = "") const;
+ AString GetValue (const AString & keyname, const AString & valuename, const AString & defValue = "") const override;
AString GetValue (const int keyID, const int valueID, const AString & defValue = "") const;
double GetValueF(const AString & keyname, const AString & valuename, const double defValue = 0) const;
int GetValueI(const AString & keyname, const AString & valuename, const int defValue = 0) const;
@@ -127,18 +127,18 @@ public:
}
// Gets the value; if not found, write the default to the INI file
- AString GetValueSet (const AString & keyname, const AString & valuename, const AString & defValue = "");
+ AString GetValueSet (const AString & keyname, const AString & valuename, const AString & defValue = "") override;
double GetValueSetF(const AString & keyname, const AString & valuename, const double defValue = 0.0);
- int GetValueSetI(const AString & keyname, const AString & valuename, const int defValue = 0);
- Int64 GetValueSetI(const AString & keyname, const AString & valuename, const Int64 defValue = 0);
- bool GetValueSetB(const AString & keyname, const AString & valuename, const bool defValue = false)
+ int GetValueSetI(const AString & keyname, const AString & valuename, const int defValue = 0) override;
+ Int64 GetValueSetI(const AString & keyname, const AString & valuename, const Int64 defValue = 0) override;
+ bool GetValueSetB(const AString & keyname, const AString & valuename, const bool defValue = false) override
{
return (GetValueSetI(keyname, valuename, defValue ? 1 : 0) != 0);
}
// Adds a new value to the specified key.
// If a value of the same name already exists, creates another one (non-standard INI file)
- void AddValue (const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value);
+ void AddValue (const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value) override;
void AddValueI(const AString & a_KeyName, const AString & a_ValueName, const int a_Value);
void AddValueB(const AString & a_KeyName, const AString & a_ValueName, const bool a_Value)
{
@@ -151,8 +151,8 @@ public:
// Returns true if value set, false otherwise.
// Overloaded to accept string, int, and double.
bool SetValue (const int keyID, const int valueID, const AString & value);
- bool SetValue (const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value, const bool a_CreateIfNotExists = true);
- bool SetValueI(const AString & a_KeyName, const AString & a_ValueName, const int a_Value, const bool a_CreateIfNotExists = true);
+ bool SetValue (const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value, const bool a_CreateIfNotExists = true) override;
+ bool SetValueI(const AString & a_KeyName, const AString & a_ValueName, const int a_Value, const bool a_CreateIfNotExists = true) override;
bool SetValueI(const AString & a_Keyname, const AString & a_ValueName, const Int64 a_Value, const bool a_CreateIfNotExists = true);
bool SetValueB(const AString & a_KeyName, const AString & a_ValueName, const bool a_Value, const bool a_CreateIfNotExists = true)
{
@@ -163,7 +163,7 @@ public:
// Deletes specified value.
// Returns true if value existed and deleted, false otherwise.
bool DeleteValueByID(const int keyID, const int valueID);
- bool DeleteValue(const AString & keyname, const AString & valuename);
+ bool DeleteValue(const AString & keyname, const AString & valuename) override;
// Deletes specified key and all values contained within.
// Returns true if key existed and deleted, false otherwise.
@@ -204,15 +204,15 @@ public:
bool AddKeyComment(const int keyID, const AString & comment);
/// Add a key comment
- bool AddKeyComment(const AString & keyname, const AString & comment);
+ bool AddKeyComment(const AString & keyname, const AString & comment) override;
/// Return a key comment
AString GetKeyComment(const int keyID, const int commentID) const;
- AString GetKeyComment(const AString & keyname, const int commentID) const;
+ AString GetKeyComment(const AString & keyname, const int commentID) const override;
// Delete a key comment.
bool DeleteKeyComment(const int keyID, const int commentID);
- bool DeleteKeyComment(const AString & keyname, const int commentID);
+ bool DeleteKeyComment(const AString & keyname, const int commentID) override;
// Delete all comments for a key.
bool DeleteKeyComments(const int keyID);
diff --git a/src/Items/ItemSign.h b/src/Items/ItemSign.h
index dabbdbba1..3da93e2f1 100644
--- a/src/Items/ItemSign.h
+++ b/src/Items/ItemSign.h
@@ -25,7 +25,7 @@ public:
cWorld & a_World, cPlayer & a_Player, const cItem & a_EquippedItem,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ
- )
+ ) override
{
// If the regular placement doesn't work, do no further processing:
if (!super::OnPlayerPlace(a_World, a_Player, a_EquippedItem, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ))
diff --git a/src/Mobs/AggressiveMonster.cpp b/src/Mobs/AggressiveMonster.cpp
index 055ff47d2..648599999 100644
--- a/src/Mobs/AggressiveMonster.cpp
+++ b/src/Mobs/AggressiveMonster.cpp
@@ -76,9 +76,11 @@ void cAggressiveMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
}
cTracer LineOfSight(GetWorld());
- Vector3d AttackDirection(m_Target->GetPosition() - GetPosition());
+ Vector3d MyHeadPosition = GetPosition() + Vector3d(0, GetHeight(), 0);
+ Vector3d AttackDirection(m_Target->GetPosition() + Vector3d(0, m_Target->GetHeight(), 0) - MyHeadPosition);
- if (ReachedFinalDestination() && !LineOfSight.Trace(GetPosition(), AttackDirection, (int)AttackDirection.Length()))
+
+ if (ReachedFinalDestination() && !LineOfSight.Trace(MyHeadPosition, AttackDirection, static_cast<int>(AttackDirection.Length())))
{
// Attack if reached destination, target isn't null, and have a clear line of sight to target (so won't attack through walls)
Attack(a_Dt);
diff --git a/src/Mobs/Horse.h b/src/Mobs/Horse.h
index be283705e..27168ebae 100644
--- a/src/Mobs/Horse.h
+++ b/src/Mobs/Horse.h
@@ -26,7 +26,7 @@ public:
bool IsEating (void) const {return m_bIsEating; }
bool IsRearing (void) const {return m_bIsRearing; }
bool IsMthOpen (void) const {return m_bIsMouthOpen; }
- bool IsTame (void) const {return m_bIsTame; }
+ bool IsTame (void) const override {return m_bIsTame; }
int GetHorseType (void) const {return m_Type; }
int GetHorseColor (void) const {return m_Color; }
int GetHorseStyle (void) const {return m_Style; }
diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp
index 2b00f6959..1da4124ed 100644
--- a/src/Mobs/Monster.cpp
+++ b/src/Mobs/Monster.cpp
@@ -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))
@@ -177,13 +177,14 @@ bool cMonster::TickPathFinding(cChunk & a_Chunk)
case ePathFinderStatus::NEARBY_FOUND:
{
m_NoPathToTarget = true;
- m_Path->AcceptNearbyPath();
+ m_PathFinderDestination = m_Path->AcceptNearbyPath();
break;
}
case ePathFinderStatus::PATH_NOT_FOUND:
{
- StopMovingToPosition(); // Give up pathfinding to that destination.
+ StopMovingToPosition(); // Try to calculate a path again.
+ // Note that the next time may succeed, e.g. if a player breaks a barrier.
break;
}
case ePathFinderStatus::CALCULATING:
@@ -202,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.
}
}
diff --git a/src/Mobs/Path.cpp b/src/Mobs/Path.cpp
index bf5e4ba5e..6f3d43305 100644
--- a/src/Mobs/Path.cpp
+++ b/src/Mobs/Path.cpp
@@ -6,6 +6,8 @@
#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.
#define CALCULATIONS_PER_STEP 10 // Higher means more CPU load but faster path calculations.
@@ -30,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)
@@ -43,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;
@@ -147,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);
@@ -178,28 +194,57 @@ bool cPath::Step_Internal()
// Calculation not finished yet.
// Check if we have a new NearestPoint.
- if (CurrentCell->m_H < m_NearestPointToTarget->m_H)
+ // 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)
+ {
+ m_NearestPointToTarget = CurrentCell;
+ }
+ }
+ else if (CurrentCell->m_H < m_NearestPointToTarget->m_H)
{
m_NearestPointToTarget = CurrentCell;
}
-
// 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 the YZ plane.
+ for (int 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 mob's height only.
- int x, z;
- for (x = -1; x <= 1; x += 2)
+ // 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 (z = -1; z <= 1; z += 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)
@@ -312,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);
}
diff --git a/src/Mobs/Path.h b/src/Mobs/Path.h
index acc56ef2d..3b9c0400e 100644
--- a/src/Mobs/Path.h
+++ b/src/Mobs/Path.h
@@ -1,16 +1,13 @@
#pragma once
-/* Wanna use the pathfinder? Put this in your header file:
-
-// Fwd: cPath
+/*
+// Needed Fwds: cPath
enum class ePathFinderStatus;
class cPath;
-
-Put this in your .cpp:
-#include "...Path.h"
*/
+#include "../FastRandom.h"
#ifdef COMPILING_PATHFIND_DEBUGGER
/* Note: the COMPILING_PATHFIND_DEBUGGER flag is used by Native / WiseOldMan95 to debug
this class outside of MCServer. This preprocessor flag is never set when compiling MCServer. */
@@ -71,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
);
@@ -92,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()
@@ -109,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 int GetPointCount()
@@ -164,8 +163,12 @@ 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;
/* Control fields */
ePathFinderStatus m_Status;
diff --git a/src/Mobs/Wolf.h b/src/Mobs/Wolf.h
index 73ffb55c2..5de83acd8 100644
--- a/src/Mobs/Wolf.h
+++ b/src/Mobs/Wolf.h
@@ -25,8 +25,8 @@ public:
virtual void Attack(std::chrono::milliseconds a_Dt) override;
// Get functions
- bool IsSitting (void) const { return m_IsSitting; }
- bool IsTame (void) const { return m_IsTame; }
+ bool IsSitting (void) const override { return m_IsSitting; }
+ bool IsTame (void) const override { return m_IsTame; }
bool IsBegging (void) const { return m_IsBegging; }
bool IsAngry (void) const { return m_IsAngry; }
AString GetOwnerName (void) const { return m_OwnerName; }
diff --git a/src/OverridesSettingsRepository.cpp b/src/OverridesSettingsRepository.cpp
index 6defdd6b5..e63f2c44c 100644
--- a/src/OverridesSettingsRepository.cpp
+++ b/src/OverridesSettingsRepository.cpp
@@ -260,7 +260,7 @@ bool cOverridesSettingsRepository::DeleteValue(const AString & a_KeyName, const
}
else
{
- return m_Overrides->DeleteValue(a_KeyName, a_ValueName);
+ return m_Main->DeleteValue(a_KeyName, a_ValueName);
}
}
diff --git a/src/PolarSSL++/BlockingSslClientSocket.cpp b/src/PolarSSL++/BlockingSslClientSocket.cpp
index 821125b31..f5ad2f08c 100644
--- a/src/PolarSSL++/BlockingSslClientSocket.cpp
+++ b/src/PolarSSL++/BlockingSslClientSocket.cpp
@@ -54,19 +54,19 @@ class cBlockingSslClientSocketLinkCallbacks:
}
- virtual void OnReceivedData(const char * a_Data, size_t a_Length)
+ virtual void OnReceivedData(const char * a_Data, size_t a_Length) override
{
m_Socket.OnReceivedData(a_Data, a_Length);
}
- virtual void OnRemoteClosed(void)
+ virtual void OnRemoteClosed(void) override
{
m_Socket.OnDisconnected();
}
- virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg)
+ virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override
{
m_Socket.OnDisconnected();
}
diff --git a/src/PolarSSL++/BlockingSslClientSocket.h b/src/PolarSSL++/BlockingSslClientSocket.h
index 319e82bf2..462ee95a7 100644
--- a/src/PolarSSL++/BlockingSslClientSocket.h
+++ b/src/PolarSSL++/BlockingSslClientSocket.h
@@ -21,6 +21,11 @@ class cBlockingSslClientSocket :
{
public:
cBlockingSslClientSocket(void);
+
+ ~cBlockingSslClientSocket(void)
+ {
+ Disconnect();
+ }
/** Connects to the specified server and performs SSL handshake.
Returns true if successful, false on failure. Sets internal error text on failure. */
diff --git a/src/PolarSSL++/SslContext.cpp b/src/PolarSSL++/SslContext.cpp
index 4c7fd4a23..5ac4bc227 100644
--- a/src/PolarSSL++/SslContext.cpp
+++ b/src/PolarSSL++/SslContext.cpp
@@ -152,7 +152,7 @@ void cSslContext::SetCACerts(const cX509CertPtr & a_CACert, const AString & a_Ex
m_CACerts = a_CACert;
// Set the trusted CA root cert store:
- ssl_set_authmode(&m_Ssl, SSL_VERIFY_OPTIONAL);
+ ssl_set_authmode(&m_Ssl, SSL_VERIFY_REQUIRED);
ssl_set_ca_chain(&m_Ssl, m_CACerts->GetInternal(), nullptr, m_ExpectedPeerName.empty() ? nullptr : m_ExpectedPeerName.c_str());
}
diff --git a/src/Protocol/Authenticator.cpp b/src/Protocol/Authenticator.cpp
index 294b6e9be..bfbe5028d 100644
--- a/src/Protocol/Authenticator.cpp
+++ b/src/Protocol/Authenticator.cpp
@@ -19,6 +19,10 @@
#define DEFAULT_AUTH_SERVER "sessionserver.mojang.com"
#define DEFAULT_AUTH_ADDRESS "/session/minecraft/hasJoined?username=%USERNAME%&serverId=%SERVERID%"
+
+
+
+
cAuthenticator::cAuthenticator(void) :
super("cAuthenticator"),
m_Server(DEFAULT_AUTH_SERVER),
@@ -267,3 +271,7 @@ bool cAuthenticator::GetPlayerProperties(const AString & a_UUID, Json::Value & a
return true;
}
*/
+
+
+
+
diff --git a/src/Protocol/MojangAPI.cpp b/src/Protocol/MojangAPI.cpp
index 51b8e90e7..110590359 100644
--- a/src/Protocol/MojangAPI.cpp
+++ b/src/Protocol/MojangAPI.cpp
@@ -38,12 +38,36 @@ const int MAX_PER_QUERY = 100;
-/** This is the data of the root certs for Starfield Technologies, the CA that signed sessionserver.mojang.com's cert:
-Downloaded from http://certs.starfieldtech.com/repository/ */
-static const AString & StarfieldCACert(void)
+/** Returns the CA certificates that should be trusted for Mojang-related connections. */
+static const AString & GetCACerts(void)
{
static const AString Cert(
- // G2 cert
+ // Equifax root CA cert
+ // Currently used for signing *.mojang.com's cert
+ // Exported from Mozilla Firefox's built-in CA repository
+ "-----BEGIN CERTIFICATE-----\n"
+ "MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV\n"
+ "UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy\n"
+ "dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1\n"
+ "MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx\n"
+ "dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B\n"
+ "AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f\n"
+ "BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A\n"
+ "cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC\n"
+ "AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ\n"
+ "MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm\n"
+ "aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw\n"
+ "ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj\n"
+ "IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF\n"
+ "MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA\n"
+ "A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y\n"
+ "7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh\n"
+ "1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4\n"
+ "-----END CERTIFICATE-----\n\n"
+
+ // Starfield G2 cert
+ // This is the data of the root certs for Starfield Technologies, the CA that used to sign sessionserver.mojang.com's cert
+ // Downloaded from http://certs.starfieldtech.com/repository/
"-----BEGIN CERTIFICATE-----\n"
"MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx\n"
"EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT\n"
@@ -67,7 +91,8 @@ static const AString & StarfieldCACert(void)
"pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1\n"
"mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0\n"
"-----END CERTIFICATE-----\n\n"
- // Original (G1) cert:
+
+ // Starfield original (G1) cert:
"-----BEGIN CERTIFICATE-----\n"
"MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl\n"
"MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp\n"
@@ -390,7 +415,7 @@ bool cMojangAPI::SecureRequest(const AString & a_ServerName, const AString & a_R
{
// Connect the socket:
cBlockingSslClientSocket Socket;
- Socket.SetTrustedRootCertsFromString(StarfieldCACert(), a_ServerName);
+ Socket.SetTrustedRootCertsFromString(GetCACerts(), a_ServerName);
if (!Socket.Connect(a_ServerName, 443))
{
LOGWARNING("%s: Can't connect to %s: %s", __FUNCTION__, a_ServerName.c_str(), Socket.GetLastErrorText().c_str());
@@ -434,7 +459,6 @@ bool cMojangAPI::SecureRequest(const AString & a_ServerName, const AString & a_R
a_Response.append((const char *)buf, (size_t)ret);
}
- Socket.Disconnect();
return true;
}
diff --git a/src/RCONServer.h b/src/RCONServer.h
index 81b019516..ecd936eeb 100644
--- a/src/RCONServer.h
+++ b/src/RCONServer.h
@@ -61,7 +61,7 @@ protected:
// cTCPLink::cCallbacks overrides:
- virtual void OnLinkCreated(cTCPLinkPtr a_Link);
+ virtual void OnLinkCreated(cTCPLinkPtr a_Link) override;
virtual void OnReceivedData(const char * a_Data, size_t a_Length) override;
virtual void OnRemoteClosed(void) override;
virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override;
diff --git a/src/Server.cpp b/src/Server.cpp
index 01d5a176a..fd3188b18 100644
--- a/src/Server.cpp
+++ b/src/Server.cpp
@@ -72,7 +72,7 @@ class cServerListenCallbacks:
virtual void OnAccepted(cTCPLink & a_Link) override {}
- virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg)
+ virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override
{
LOGWARNING("Cannot listen on port %d: %d (%s).", m_Port, a_ErrorCode, a_ErrorMsg.c_str());
}
diff --git a/src/UI/SlotArea.h b/src/UI/SlotArea.h
index f6a9972d6..664c6502c 100644
--- a/src/UI/SlotArea.h
+++ b/src/UI/SlotArea.h
@@ -239,7 +239,7 @@ public:
// cSlotAreaTemporary overrides:
virtual void Clicked (cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) override;
- virtual void DblClicked (cPlayer & a_Player, int a_SlotNum);
+ virtual void DblClicked (cPlayer & a_Player, int a_SlotNum) override;
virtual void OnPlayerRemoved(cPlayer & a_Player) override;
virtual void SetSlot (int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) override;
diff --git a/src/World.cpp b/src/World.cpp
index e93d6bb26..3c39de317 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -150,7 +150,7 @@ protected:
int m_LastReportChunkCount;
// cChunkCoordCallback override:
- virtual void Call(int a_ChunkX, int a_ChunkZ)
+ virtual void Call(int a_ChunkX, int a_ChunkZ) override
{
// Check if this was the last chunk:
m_NumPrepared += 1;
@@ -362,6 +362,7 @@ cWorld::~cWorld()
void cWorld::CastThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ)
{
BroadcastThunderbolt(a_BlockX, a_BlockY, a_BlockZ);
+ BroadcastSoundEffect("ambient.weather.thunder", a_BlockX, a_BlockY, a_BlockZ, 50, 1);
}
diff --git a/src/World.h b/src/World.h
index 6c0548ae6..2ecdd519c 100644
--- a/src/World.h
+++ b/src/World.h
@@ -203,10 +203,10 @@ public:
bool VillagersShouldHarvestCrops(void) const { return m_VillagersShouldHarvestCrops; }
- virtual eDimension GetDimension(void) const { return m_Dimension; }
+ virtual eDimension GetDimension(void) const override { return m_Dimension; }
/** Returns the world height at the specified coords; waits for the chunk to get loaded / generated */
- virtual int GetHeight(int a_BlockX, int a_BlockZ);
+ virtual int GetHeight(int a_BlockX, int a_BlockZ) override;
// tolua_end
@@ -253,7 +253,7 @@ public:
void BroadcastScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode);
void BroadcastScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode);
void BroadcastDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display);
- void BroadcastSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = nullptr); // tolua_export
+ void BroadcastSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = nullptr) override; // tolua_export
void BroadcastSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data, const cClientHandle * a_Exclude = nullptr); // tolua_export
void BroadcastSpawnEntity (cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr);
void BroadcastTeleportEntity (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr);
@@ -788,7 +788,7 @@ public:
bool IsWeatherWet(void) const { return !IsWeatherSunny(); }
/** Returns true if it is raining, stormy or snowing at the specified location. This takes into account biomes. */
- virtual bool IsWeatherWetAt(int a_BlockX, int a_BlockZ)
+ virtual bool IsWeatherWetAt(int a_BlockX, int a_BlockZ) override
{
return (IsWeatherWet() && !IsBiomeNoDownfall(GetBiomeAt(a_BlockX, a_BlockZ)));
}
diff --git a/src/main.cpp b/src/main.cpp
index 8a237b8ee..5cd057278 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -374,6 +374,14 @@ std::unique_ptr<cMemorySettingsRepository> parseArguments(int argc, char **argv)
TCLAP::MultiArg<int> portsArg("p", "port", "The port number the server should listen to", false, "port", cmd);
+ TCLAP::SwitchArg commLogArg("", "log-comm", "Log server client communications to file", cmd);
+
+ TCLAP::SwitchArg commLogInArg("", "log-comm-in", "Log inbound server client communications to file", cmd);
+
+ TCLAP::SwitchArg commLogOutArg("", "log-comm-out", "Log outbound server client communications to file", cmd);
+
+ TCLAP::SwitchArg noBufArg("", "no-output-buffering", "Disable output buffering", cmd);
+
cmd.parse(argc, argv);
auto repo = cpp14::make_unique<cMemorySettingsRepository>();
@@ -396,6 +404,22 @@ std::unique_ptr<cMemorySettingsRepository> parseArguments(int argc, char **argv)
}
}
+ if (commLogArg.getValue())
+ {
+ g_ShouldLogCommIn = true;
+ g_ShouldLogCommOut = true;
+ }
+ else
+ {
+ g_ShouldLogCommIn = commLogInArg.getValue();
+ g_ShouldLogCommOut = commLogOutArg.getValue();
+ }
+
+ if (noBufArg.getValue())
+ {
+ setvbuf(stdout, nullptr, _IONBF, 0);
+ }
+
repo->SetReadOnly();
return repo;
@@ -473,35 +497,7 @@ int main(int argc, char **argv)
for (int i = 0; i < argc; i++)
{
AString Arg(argv[i]);
- if (
- (NoCaseCompare(Arg, "/commlog") == 0) ||
- (NoCaseCompare(Arg, "/logcomm") == 0)
- )
- {
- g_ShouldLogCommIn = true;
- g_ShouldLogCommOut = true;
- }
- else if (
- (NoCaseCompare(Arg, "/commlogin") == 0) ||
- (NoCaseCompare(Arg, "/comminlog") == 0) ||
- (NoCaseCompare(Arg, "/logcommin") == 0)
- )
- {
- g_ShouldLogCommIn = true;
- }
- else if (
- (NoCaseCompare(Arg, "/commlogout") == 0) ||
- (NoCaseCompare(Arg, "/commoutlog") == 0) ||
- (NoCaseCompare(Arg, "/logcommout") == 0)
- )
- {
- g_ShouldLogCommOut = true;
- }
- else if (NoCaseCompare(Arg, "nooutbuf") == 0)
- {
- setvbuf(stdout, nullptr, _IONBF, 0);
- }
- else if (NoCaseCompare(Arg, "/service") == 0)
+ if (NoCaseCompare(Arg, "/service") == 0)
{
cRoot::m_RunAsService = true;
}