diff options
Diffstat (limited to 'src')
29 files changed, 354 insertions, 242 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/PluginLua.h b/src/Bindings/PluginLua.h index 29f0319ab..a763cdfdf 100644 --- a/src/Bindings/PluginLua.h +++ b/src/Bindings/PluginLua.h @@ -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/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/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/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 f23d58ed1..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,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)) { @@ -1642,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); @@ -1662,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)"; @@ -1674,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()) { @@ -1689,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 @@ -1766,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); @@ -1785,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; } @@ -2145,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 @@ -2348,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('/'); @@ -2356,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 f5d961096..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)) @@ -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. } } diff --git a/src/Mobs/Path.cpp b/src/Mobs/Path.cpp index eba29be7e..6f3d43305 100644 --- a/src/Mobs/Path.cpp +++ b/src/Mobs/Path.cpp @@ -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); } diff --git a/src/Mobs/Path.h b/src/Mobs/Path.h index b296bbdf5..3b9c0400e 100644 --- a/src/Mobs/Path.h +++ b/src/Mobs/Path.h @@ -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 int 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; 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/Protocol/MojangAPI.cpp b/src/Protocol/MojangAPI.cpp index a12351286..110590359 100644 --- a/src/Protocol/MojangAPI.cpp +++ b/src/Protocol/MojangAPI.cpp @@ -459,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 7f0e3070a..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; 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; } |