EOSERV Forum > EOSERV > Normal "say" chat map-wide instead of range-wide?
Page: << 1 2 >>
Normal "say" chat map-wide instead of range-wide?
Author Message
Post #202611 Normal "say" chat map-wide instead of range-wide?

I would like normal say/talk chat to be seen/heard across the entire current map, rather then the "SeeDistance" range.

I changing the server-side code so that it would send the talk packet to every character on the map, instead of just the characters in SeeDistance range:


With the above change, I notice that the client does get the talk packet when the characters are out of range/sight.

But it seems like the client has some hardcoded handling of the talk packet, and will only show the message in the chat log when the character is in range.

Any idea if it's possible to get around this or if I am missing something? It seems like the only solution, is to increase the SeeDistance to more then 11. But I'm sure this would decrease graphical and network performance.

---
Just your friendly neighborhood Programmer-Man!
7 years, 8 weeks ago
Post #202612 Re: Normal "say" chat map-wide instead of range-wide?

I may be wrong here, so take this with a pinch of salt..

The public chat message is different from the others, where the other chats send a name & message, this one sends a PlayerID and the message. I'd imagine your client needs to have a character it can use to identify which ID(character) is speaking.

In short: You need to increase map entrances for players so the client knows who's on the map.

7 years, 8 weeks ago
Post #202613 Re: Normal "say" chat map-wide instead of range-wide?

Just change the InRange check to from ->mapid == character ->mapid. That should spam your whole map as much as you want.

7 years, 8 weeks ago
Post #202614 Re: Normal "say" chat map-wide instead of range-wide?

Thanks for the help guys!

@Callum

Good point, that's what I assume is happening. I'm honestly not sure what you mean when you say:

"You need to increase map entrances for players so the client knows who's on the map."

Do you think what you are saying, is possible without a custom client?

@Apollo

I tried something similar, and unfortunately it doesn't work.

For testing, I changed the "bool Character::InRange(unsigned char x, unsigned char y) const" method to always return true.

It will send the talk packet to the clients, even when the range is beyond the default 11 tile range limit, but the client seems to have the range of "11" hardcoded.

When sending a talk packet to a client, when the other character is within the 11 tile range, it receives the client like so:


When the client receives a talk packet when the range is more than 11 tiles, it will send back some unknown packet instantly:


I believe any packet that's received from the client, that includes any action on a character out of range of 11 tiles, will be responded with an instant unknown send packet.

Also, if I leave the code as the default behavior (with the default SeeDistance value also), sending a talk packet out of range, is never received by the other client. That makes sense, I just wan't to report that the client is definitely receiving a talk packet when I alter the range handling, but the client doesn't want to handle it as expected.

So my assumption is that this isn't possible with a non-custom client.

Side note:

It's probably related that "SeeDistance" shouldn't be changed to anything other then "11" when used with a non-custom client:

## SeeDistance (number)
# Distance a client should be able to see players, NPCs and items
# Shouldn't be changed unless using a custom client which supports it
SeeDistance = 11


---
Just your friendly neighborhood Programmer-Man!
7 years, 8 weeks ago
Post #202615 Re: Normal "say" chat map-wide instead of range-wide?
Shilo posted: (2nd Mar 2017, 05:34 am)

Thanks for the help guys!

@Callum

Good point, that's what I assume is happening. I'm honestly not sure what you mean when you say:

"You need to increase map entrances for players so the client knows who's on the map."

Do you think what you are saying, is possible without a custom client?

@Apollo

I tried something similar, and unfortunately it doesn't work.

For testing, I changed the "bool Character::InRange(unsigned char x, unsigned char y) const" method to always return true.

It will send the talk packet to the clients, even when the range is beyond the default 11 tile range limit, but the client seems to have the range of "11" hardcoded.

When sending a talk packet to a client, when the other character is within the 11 tile range, it receives the client like so:


When the client receives a talk packet when the range is more than 11 tiles, it will send back some unknown packet instantly:


I believe any packet that's received from the client, that includes any action on a character out of range of 11 tiles, will be responded with an instant unknown send packet.

Also, if I leave the code as the default behavior (with the default SeeDistance value also), sending a talk packet out of range, is never received by the other client. That makes sense, I just wan't to report that the client is definitely receiving a talk packet when I alter the range handling, but the client doesn't want to handle it as expected.

So my assumption is that this isn't possible with a non-custom client.

Side note:

It's probably related that "SeeDistance" shouldn't be changed to anything other then "11" when used with a non-custom client:

## SeeDistance (number)
# Distance a client should be able to see players, NPCs and items
# Shouldn't be changed unless using a custom client which supports it
SeeDistance = 11



Yeah, you're completely right about this. The client doesn't know how to handle talk packets referencing character objects that don't "exist" clientside, it gets a smidge confused about what pid the server is talking about. The server just sends a number to represent the character talking, and the client only keeps track of those IDs for characters in-range/loaded on the client screen.
---
Want to learn to pixel?
Pixelsource.org
7 years, 8 weeks ago
Post #202616 Re: Normal "say" chat map-wide instead of range-wide?

"I'd imagine your client needs to have a character it can use to identify which ID(character) is speaking." But yeah, maybe I didn't explain to good.

Looking into the config it also says:

## SeeDistance (number)

# Distance a client should be able to see players, NPCs and items

# Shouldn't be changed unless using a custom client which supports it

7 years, 8 weeks ago
Post #202617 Re: Normal "say" chat map-wide instead of range-wide?

My bad, that should be from ->mapid != character ->mapid followed by continue. Using continue will skip the current check in the loop. The client will accept any packets you send. If you don't see it, the server didn't send it.

7 years, 8 weeks ago
Post #202619 Re: Normal "say" chat map-wide instead of range-wide?

Thank you for the help. I know how loops and continue works. I am 100% positive the server is sending the packets and 100% positive the clients are receiving the packets. The proof is in my screenshots. I assume the problem is that the client has hard-coded handling for the 11 tile "SeeDistance" and it must remove the characters from the map when they are out of range, thus making it so that the packets are never handled correctly.

Unless I am missing something, this feature isn't possible without modifying the client.

---
Just your friendly neighborhood Programmer-Man!
7 years, 8 weeks ago
Post #202648 Re: Normal "say" chat map-wide instead of range-wide?
Shilo posted: (2nd Mar 2017, 01:00 pm)

Thank you for the help. I know how loops and continue works. I am 100% positive the server is sending the packets and 100% positive the clients are receiving the packets. The proof is in my screenshots. I assume the problem is that the client has hard-coded handling for the 11 tile "SeeDistance" and it must remove the characters from the map when they are out of range, thus making it so that the packets are never handled correctly.

Unless I am missing something, this feature isn't possible without modifying the client.


Why not, can't you tell the client that out of range characters are in range (at the maximum distance away). Like pick an offset from a player to display out of range characters at (respecting map boundaries I think). Is out of range only when you no longer see them on your minimap? If so, the only side effect would be an artifact stack of players at a specific offset from your character on the minimap. Doesn't seem too bad.. (I dont think I have an EO on my computer right now to see what 11 tiles is)
---
I not hacker

“Everybody is a genius. But if you judge a fish by its ability to climb a tree, it will live its
whole life believing that it is stupid.” - Albert Einstein : Really Great Quote Ramy!
7 years, 7 weeks ago
Post #202664 Re: Normal "say" chat map-wide instead of range-wide?

I'm not sure how many times I have to express that i'm fairly positive that this is a restriction with the client and it's hardcoded. I tested it again and still ran into the same issue.

But I decided to go a different route, because there's really no other way I can do this. (Unless someone else can try it and prove me wrong)

When characters our out of the SeeDistance range of 11 tiles, it will send a private message to them, otherwise it will send a public message to them. This is definitely not optimal, but the only option I have.

I actually will disable this feature because it poses some user friendly issues, most noteably the "ding" sound. So I will just share it.

Here's the code:

## PublicChatEntireMap (number)
# When sending a public message, it will be received by everyone on the map. Not just the SeeDistance range of 11 tiles.
# Note: Due to client restrictions, characters beyond the SeeDistance range of 11 tiles will receive a private message.
PublicChatEntireMap = yes

void Map::Msg(Character *from, std::string message, bool echo)
{
    message = util::text_cap(message, static_cast<int>(this->world->config["ChatMaxWidth"]) - util::text_width(util::ucfirst(from->SourceName()) + "  "));

    PacketBuilder builder(PACKET_TALK, PACKET_PLAYER, 2 + message.length());
    builder.AddShort(from->PlayerID());
    builder.AddString(message);

    bool publicChatEntireMap = from->world->config["PublicChatEntireMap"];

    UTIL_FOREACH(this->characters, character)
    {
        if (!publicChatEntireMap && !from->InRange(character))
            continue;

        character->AddChatLog("", from->SourceName(), message);

        if (!echo && character == from)
            continue;

        if (!publicChatEntireMap || from->InRange(character)) {
            character->Send(builder);
        } else if (publicChatEntireMap) {
            character->Msg(from, message);
        }
    }
}
---
Just your friendly neighborhood Programmer-Man!
7 years, 7 weeks ago
Post #202665 Re: Normal "say" chat map-wide instead of range-wide?

What about a status message? I think they only show at the bottom of the client and in the sys tab, could try something like "name says:"

7 years, 7 weeks ago
Post #202667 Re: Normal "say" chat map-wide instead of range-wide?

@Callum Great suggestion!

I extended the system I had (too much).

I added support for every message type EOServ has.

Config:

## PublicChatEntireMapType (number)
# When sending a public message, it will be received by everyone on the map. Not just the SeeDistance range of 11 tiles.
# Note: Due to client restrictions, characters beyond the SeeDistance range of 11 tiles will receive a non-public message (specified below).
# 0 = Disabled, public messages will only be shown within the SeeDistance range of 11 tiles.
# 1 = Private message out of range characters.
# 2 = Party message out of range characters. Character has to be in a party to receive the message.
# 3 = Guild message out of range characters. Character has to be in a guild to receive the message.
# 4 = Global message out of range characters.
# 5 = Server message out of range characters.
# 6 = Announcement message out of range characters.
# 7 = Admin message out of range characters.
# 8 = Status message out of range characters.
# 9 = Status and global message out of range characters.
PublicChatEntireMapType = 9

map.cpp:

void Map::Msg(Character *from, std::string message, bool echo)
{
    message = util::text_cap(message, static_cast<int>(this->world->config["ChatMaxWidth"]) - util::text_width(util::ucfirst(from->SourceName()) + "  "));

    PacketBuilder builder(PACKET_TALK, PACKET_PLAYER, 2 + message.length());
    builder.AddShort(from->PlayerID());
    builder.AddString(message);

    int publicChatEntireMapType = static_cast<int>(from->world->config["PublicChatEntireMapType"]);
    // 0 = Disabled, public messages will only be shown within the SeeDistance range of 11 tiles.
    // 1 = Private message out of range characters.
    // 2 = Party message out of range characters. Character has to be in a party to receive the message.
    // 3 = Guild message out of range characters. Character has to be in a guild to receive the message.
    // 4 = Global message out of range characters.
    // 5 = Server message out of range characters.
    // 6 = Announcement message out of range characters.
    // 7 = Admin message out of range characters.
    // 8 = Status message out of range characters.
    // 9 = Status and global message out of range characters.

    UTIL_FOREACH(this->characters, character)
    {
        if (publicChatEntireMapType <= 0 && !from->InRange(character))
            continue;

        character->AddChatLog("", from->SourceName(), message);

        if (!echo && character == from)
            continue;

        if (publicChatEntireMapType <= 0 || from->InRange(character)) {
            character->Send(builder);
        } else if (publicChatEntireMapType > 0) {
            std::string from_name = from->SourceName();
            switch (publicChatEntireMapType) {
                case 1: { //Private message
                    PacketBuilder builder2(PACKET_TALK, PACKET_TELL, 2 + from_name.length() + message.length());
                    builder2.AddBreakString(from_name);
                    builder2.AddBreakString(message);
                    character->Send(builder2);
                    break;
                }
                case 2: { //Party message
                    PacketBuilder builder2(PACKET_TALK, PACKET_OPEN, 2 + message.length());
                    builder2.AddShort(from->PlayerID());
                    builder2.AddString(message);
                    character->Send(builder2);
                    break;
                }
                case 3: { //Guild message
                    PacketBuilder builder2(PACKET_TALK, PACKET_REQUEST, 2 + from_name.length() + message.length());
                    builder2.AddBreakString(from_name);
                    builder2.AddBreakString(message);
                    character->Send(builder2);
                    break;
                }
                case 4: { //Global message
                    PacketBuilder builder2(PACKET_TALK, PACKET_MSG, 2 + from_name.length() + message.length());
                    builder2.AddBreakString(from_name);
                    builder2.AddBreakString(message);
                    character->Send(builder2);
                    break;
                }
                case 5: { //Server message
                    message = util::text_cap(util::ucfirst(from_name) + " says: " + message, static_cast<int>(this->world->config["ChatMaxWidth"]) - util::text_width("Server  "));
                    PacketBuilder builder2(PACKET_TALK, PACKET_SERVER, message.length());
                    builder2.AddString(message);
                    character->Send(builder2);
                    break;
                }
                case 6: { //Announcement message
                    PacketBuilder builder2(PACKET_TALK, PACKET_ANNOUNCE, 2 + from_name.length() + message.length());
                    builder2.AddBreakString(from_name);
                    builder2.AddBreakString(message);
                    character->Send(builder2);
                    break;
                }
                case 7: { //Admin message
                    PacketBuilder builder2(PACKET_TALK, PACKET_ADMIN, 2 + from_name.length() + message.length());
                    builder2.AddBreakString(from_name);
                    builder2.AddBreakString(message);
                    character->Send(builder2);
                    break;
                }
                case 8: { //Status message
                    character->StatusMsg(util::ucfirst(from_name) + " says: " + message);
                    break;
                }
                case 9: { //Status and global message message
                    PacketBuilder builder2(PACKET_TALK, PACKET_MSG, 2 + from_name.length() + message.length());
                    builder2.AddBreakString(from_name);
                    builder2.AddBreakString(message);
                    character->Send(builder2);
                    character->StatusMsg(util::ucfirst(from_name) + " says: " + message);
                    break;
                }
            }
        }
    }
}

I think the only acceptable values are 4, 8 and 9 (Global and status messages).

---
Just your friendly neighborhood Programmer-Man!
7 years, 7 weeks ago
Post #202674 Re: Normal "say" chat map-wide instead of range-wide?


I suggest a switch statement instead of all those if else blocks.

Nice concept there. The status messages are probably the best method if this is an important feature for you.

---
Want to learn to pixel?
Pixelsource.org
7 years, 7 weeks ago
Post #202679 Re: Normal "say" chat map-wide instead of range-wide?

@Shilo did you ignore my comment? Is 11 tiles away visible on screen, or is it a bit off screen and still visible on map?

---
I not hacker

“Everybody is a genius. But if you judge a fish by its ability to climb a tree, it will live its
whole life believing that it is stupid.” - Albert Einstein : Really Great Quote Ramy!
7 years, 7 weeks ago
Post #202687 Re: Normal "say" chat map-wide instead of range-wide?

@Cirras

Good suggestion. I usually use switch statements, but my initial plan was to only have 3 values, not 9. So I opted to use an if statement. I updated the post with the switch statement.

@Hacker_Alex

Sorry, I wasn't ignoring your comment. I read your comment, but I'm not sure what exactly you are talking about. I assume I tried what you are speaking of, and tested every possible solution I could think of.

I believe between 10 and 11 tiles is when a character becomes off of the screen/viewport. So I assume the client automatically clears the characters from the map when they are 1 or 2+ tiles further then the viewport (12 tiles away from the center of the screen).

---
Just your friendly neighborhood Programmer-Man!
7 years, 7 weeks ago
Page: << 1 2 >>

EOSERV Forum > EOSERV > Normal "say" chat map-wide instead of range-wide?