Jump to content

Guild Comment fix


Recommended Posts

  • Active Member

 

.png

 

This is the hidden content, please

Alternative download links →

This is the hidden content, please
or
This is the hidden content, please
 or 
This is the hidden content, please

 

Changelogs

Version 3.

  • Fix quest pick in quest 
  • Fix delayed desc kick
  • Now it works stable without problems in version 3

Version 2. 

  • Now, the players cannot delete messange other people's 
  • In 4 failures the server kick you

@ TMP4 @ Abel(Tiger)  

Version 1.

  • Normal fix guild comment
  • Metin2 Dev 50
  • kekw 1
  • Lmao 1
  • Good 8
  • Love 16
Link to comment
Share on other sites

  • Active Member
15 minutes ago, Abel(Tiger) said:

😂

1. The fix I posted is done because you can spam the database with queries.
2. With your "fix" you can delete all coments from the guild with no permissions :)))
 

They are automatically deleted  after 12 message you check

Link to comment
Share on other sites

  • Contributor
35 minutes ago, Draveniou1 said:

They are automatically deleted  after 12 message you check

With your "fix" abusers got +1 query to spam, even if it's just a delete query.

Fixing the possibility of the flood and delete old unnecessary comments is 2 seperate things to do. @ Abel(Tiger) did the first, you did the second.

And yes, Abel is right because you're not checking any permission, if someone sends a packet on his own (cheat), he can delete other's messages without the required guild permission.

Also you did hella lot uneceserry work. If you want to delete older comments, why don't you just do it after the insert? Why do you need a seperate packet?

Edited by TMP4
Link to comment
Share on other sites

  • Active Member
5 minutes ago, TMP4 said:

With your "fix" abusers got +1 query to spam, even if it's just a delete query.

Fixing the possibility of the flood and delete old unnecessary comments is 2 seperate things to do. @ Abel(Tiger) did the first, you did the second.

And yes, Abel is right because you're not checking any permission, if someone sends a packet on his own (cheat), he can delete other's messages without the required guild permission.

Also you did hella lot uneceserry work. If you want to delete older comments, why don't you just do it after the insert? Why do you need a seperate packet?

-With your "fix" abusers got +1 query to spam, even if it's just a delete query.

- We can easy add check query 

-------------

-Fixing the possibility of the flood and delete old unnecessary comments is 2 seperate things to do. @ Abel(Tiger) did the first, you did the second.

- We can easily in the 2 failed attempts the player leaves the server

 

---------------

 

-And yes, Abel is right because you're not checking any permission, if someone sends a packet on his own (cheat), he can delete other's messages without the required guild permission.

you can easily check the player I will try to do them this

  • kekw 1
Link to comment
Share on other sites

Or maybe something like that instead no ?

 

void CGuild::AddComment(LPCHARACTER ch, const std::string& str)
{
    if (str.length() > GUILD_COMMENT_MAX_LEN || str.length() == 0) // Added string null verification
        return;

    char text[GUILD_COMMENT_MAX_LEN * 2 + 1];
    DBManager::instance().EscapeString(text, sizeof(text), str.c_str(), str.length());

    // Fetch the number of existing comments and delete the oldest one if there are 12 comments.
    DBManager::instance().FuncQuery(std::bind(&CGuild::HandleCommentCount, this, ch, text, std::placeholders::_1),
        "SELECT COUNT(*), MIN(time) FROM guild_comment%s WHERE guild_id = %u",
        get_table_postfix(), m_data.guild_id);
}

void CGuild::HandleCommentCount(LPCHARACTER ch, const char* text, MYSQL_RES* result)
{
    MYSQL_ROW row = mysql_fetch_row(result);

    if (!row)
        return;

    int commentCount = 0;
    sscanf(row[0], "%d", &commentCount);

    if (commentCount >= 12) {
        // Delete the oldest comment
        DBManager::instance().Query("DELETE FROM guild_comment%s WHERE guild_id = %u AND time = '%s'",
            get_table_postfix(), m_data.guild_id, row[1]);
    }

    // Insert the new comment
    DBManager::instance().FuncAfterQuery(void_bind(std::bind1st(std::mem_fun(&CGuild::RefreshCommentForce), this), ch->GetPlayerID()),
        "INSERT INTO guild_comment%s(guild_id, name, notice, content, time) VALUES(%u, '%s', %d, '%s', NOW())",
        get_table_postfix(), m_data.guild_id, ch->GetName(), (text[0] == '!') ? 1 : 0, text);
}

 

  • kekw 1
  • Good 1
Link to comment
Share on other sites

  • Active Member
8 minutes ago, PetePeter said:

Or maybe something like that instead no ?

 

void CGuild::AddComment(LPCHARACTER ch, const std::string& str)
{
    if (str.length() > GUILD_COMMENT_MAX_LEN || str.length() == 0) // Added string null verification
        return;

    char text[GUILD_COMMENT_MAX_LEN * 2 + 1];
    DBManager::instance().EscapeString(text, sizeof(text), str.c_str(), str.length());

    // Fetch the number of existing comments and delete the oldest one if there are 12 comments.
    DBManager::instance().FuncQuery(std::bind(&CGuild::HandleCommentCount, this, ch, text, std::placeholders::_1),
        "SELECT COUNT(*), MIN(time) FROM guild_comment%s WHERE guild_id = %u",
        get_table_postfix(), m_data.guild_id);
}

void CGuild::HandleCommentCount(LPCHARACTER ch, const char* text, MYSQL_RES* result)
{
    MYSQL_ROW row = mysql_fetch_row(result);

    if (!row)
        return;

    int commentCount = 0;
    sscanf(row[0], "%d", &commentCount);

    if (commentCount >= 12) {
        // Delete the oldest comment
        DBManager::instance().Query("DELETE FROM guild_comment%s WHERE guild_id = %u AND time = '%s'",
            get_table_postfix(), m_data.guild_id, row[1]);
    }

    // Insert the new comment
    DBManager::instance().FuncAfterQuery(void_bind(std::bind1st(std::mem_fun(&CGuild::RefreshCommentForce), this), ch->GetPlayerID()),
        "INSERT INTO guild_comment%s(guild_id, name, notice, content, time) VALUES(%u, '%s', %d, '%s', NOW())",
        get_table_postfix(), m_data.guild_id, ch->GetName(), (text[0] == '!') ? 1 : 0, text);
}

 

I had thought about it too  

the problem is that mysql will always answer the player's queries 

and does not eat kick from the game

it could be with mine version 1 

better there should be a count as they mentioned @ Abel(Tiger) and @ TMP4

  • kekw 1
Link to comment
Share on other sites

2 hours ago, Draveniou1 said:

My post updated

i add version 3 full fix 

Changelog

1. Fix quest pick in quest 

2. Fix delayed desc kick

Now it works stable without problems in version 3

 

thanks a lot

Did you recheck your code ? Here is a possible solution:

 

void CGuild::DeleteComment(LPCHARACTER ch, DWORD comment_id)
{
    const int maxAttempts = 3;
    const int resetIntervalMinutes = 10;  // Change this to the desired interval in minutes

    time_t currentTime = time(0);
    int attempts = ch->GetQuestFlag("Newfixxed.Newguildcomment");
    time_t lastAttemptTime = ch->GetQuestFlag("Newfixxed.LastAttemptTime");

    // If the user's last attempt was longer than the reset interval ago, reset their attempts
    if (difftime(currentTime, lastAttemptTime) >= resetIntervalMinutes * 60)
    {
        attempts = 0;
    }

    // Check if the user has reached the maximum number of attempts
    if (attempts >= maxAttempts)
    {
        ch->GetDesc()->DelayedDisconnect(0);
        return;
    }

    std::unique_ptr<SQLMsg> pmsg;

    // Execute the appropriate query based on the user's guild grade
    if (GetMember(ch->GetPlayerID())->grade == GUILD_LEADER_GRADE)
    {
        pmsg.reset(DBManager::instance().DirectQuery("DELETE FROM guild_comment WHERE id = %u AND guild_id = %u", comment_id, m_data.guild_id));
    }
    else
    {
        pmsg.reset(DBManager::instance().DirectQuery("DELETE FROM guild_comment WHERE id = %u AND guild_id = %u AND name = '%s'", comment_id, m_data.guild_id, ch->GetName()));
    }

    uint32_t affectedRows = pmsg->Get()->uiAffectedRows;

    // Check if the comment was successfully deleted
    if (affectedRows == 0 || affectedRows == (uint32_t)-1)
    {
        ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<길드> 삭제할 수 없는 글입니다."));
    }
    else
    {
        RefreshCommentForce(ch->GetPlayerID());
    }

    // Update the user's attempt count and last attempt time
    ch->SetQuestFlag("Newfixxed.Newguildcomment", attempts + 1);
    ch->SetQuestFlag("Newfixxed.LastAttemptTime", currentTime);
}

 

  • kekw 1
Link to comment
Share on other sites

  • Active Member
2 hours ago, PetePeter said:

Did you recheck your code ? Here is a possible solution:

 

void CGuild::DeleteComment(LPCHARACTER ch, DWORD comment_id)
{
    const int maxAttempts = 3;
    const int resetIntervalMinutes = 10;  // Change this to the desired interval in minutes

    time_t currentTime = time(0);
    int attempts = ch->GetQuestFlag("Newfixxed.Newguildcomment");
    time_t lastAttemptTime = ch->GetQuestFlag("Newfixxed.LastAttemptTime");

    // If the user's last attempt was longer than the reset interval ago, reset their attempts
    if (difftime(currentTime, lastAttemptTime) >= resetIntervalMinutes * 60)
    {
        attempts = 0;
    }

    // Check if the user has reached the maximum number of attempts
    if (attempts >= maxAttempts)
    {
        ch->GetDesc()->DelayedDisconnect(0);
        return;
    }

    std::unique_ptr<SQLMsg> pmsg;

    // Execute the appropriate query based on the user's guild grade
    if (GetMember(ch->GetPlayerID())->grade == GUILD_LEADER_GRADE)
    {
        pmsg.reset(DBManager::instance().DirectQuery("DELETE FROM guild_comment WHERE id = %u AND guild_id = %u", comment_id, m_data.guild_id));
    }
    else
    {
        pmsg.reset(DBManager::instance().DirectQuery("DELETE FROM guild_comment WHERE id = %u AND guild_id = %u AND name = '%s'", comment_id, m_data.guild_id, ch->GetName()));
    }

    uint32_t affectedRows = pmsg->Get()->uiAffectedRows;

    // Check if the comment was successfully deleted
    if (affectedRows == 0 || affectedRows == (uint32_t)-1)
    {
        ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<길드> 삭제할 수 없는 글입니다."));
    }
    else
    {
        RefreshCommentForce(ch->GetPlayerID());
    }

    // Update the user's attempt count and last attempt time
    ch->SetQuestFlag("Newfixxed.Newguildcomment", attempts + 1);
    ch->SetQuestFlag("Newfixxed.LastAttemptTime", currentTime);
}

 

I don't want to use time_t I prefer the normal one because if I wanted time I have 5000 solutions with times

i will use the normal way is better

  • kekw 1
Link to comment
Share on other sites

It's not about "normal" ways.
 

1. You didn't add any return to the function after the player is kicked, so the rest of the function is executed normally
2. You never reset the counter, it's only reset after a kick as the script continue his path and reach the "if (NewFixGuildCommente >= 3)" again
3. (Optionnal) Consider using smart pointers (like std::unique_ptr) instead of raw pointers for better memory management and exception safety. I know the sql function is not made by you, but if we edit this function we can optimise everything also


 

Edited by PetePeter
  • kekw 1
  • Love 2
Link to comment
Share on other sites

  • Active Member
23 hours ago, PetePeter said:

It's not about "normal" ways.
 

1. You didn't add any return to the function after the player is kicked, so the rest of the function is executed normally
2. You never reset the counter, it's only reset after a kick as the script continue his path and reach the "if (NewFixGuildCommente >= 3)" again
3. (Optionnal) Consider using smart pointers (like std::unique_ptr) instead of raw pointers for better memory management and exception safety. I know the sql function is not made by you, but if we edit this function we can optimise everything also


 

I don't want a timer

if at the same time 90-160 players add the timer then the game that has low connection and you will send a message to the company to solve your problem 

I have 50 methods with a timer, do you think I'm stupid not to set a timer? 

 

one tip: Don't set timers to do something 

Timer = lag's problem's server 

 

 

He doesn't have a professional mind, man, we're dealing with you, speak for yourself -> 0% professionalism @PetePeter

 

  • kekw 3
Link to comment
Share on other sites

  • Honorable Member

Without timers, or quest flags (persistent memory):

mRyLnkK.png

XtKYCfa.png

This is the hidden content, please
 (enumtype branch)

This is the hidden content, please

It stores something like 10 bytes per player (when they use it) in an std::unordered_map (hash map with O(1) access time). It's only stored in memory, and not shared to other cores (it's irrelevant for this case).

Edited by Metin2 Dev International
Core X - External 2 Internal
  • Metin2 Dev 36
  • Good 4
  • Love 1
  • Love 12
Link to comment
Share on other sites

Announcements



  • Similar Content

  • Similar Content

  • Similar Content

  • Tags

  • Activity

    1. 113

      Ulthar SF V2 (TMP4 Base)

    2. 2

      Feeding game source to LLM

    3. 0

      Target Information System

    4. 2

      Feeding game source to LLM

    5. 2

      anti exp explanation pls

    6. 2

      Feeding game source to LLM

    7. 2

      anti exp explanation pls

  • Recently Browsing

    • No registered users viewing this page.
×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.