Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

/locate command #150

Merged
merged 17 commits into from
Aug 18, 2024
Merged

/locate command #150

merged 17 commits into from
Aug 18, 2024

Conversation

balt-dev
Copy link
Contributor

Adds a /locate command to find where a player is without having to scroll through tab.

Note that this may add additional complexity to PR #101.

image

@balt-dev
Copy link
Contributor Author

Note that there's no formatting for now, since the command is fully resolved on the server! In order to change this, I'd probably need to factor out part of CelesteNet.Client.Components.CelesteNetPlayerListComponent.

@balt-dev
Copy link
Contributor Author

I'd make this a draft PR but I can't find the button :P

@balt-dev balt-dev closed this Jul 21, 2024
@balt-dev balt-dev reopened this Jul 21, 2024
@balt-dev
Copy link
Contributor Author

image
Much better!

@balt-dev
Copy link
Contributor Author

image
Here's how it handles the randomizer:

@RedFlames
Copy link
Collaborator

RedFlames commented Jul 21, 2024

Suggestion of a rewrite of your HandleLocate, although it's not perfect either 🤔
(And untested, I haven't actually tried to compile this)

        public void HandleLocate(DataChat chat) {
            // For some reason, using the actual target field always came up as null for me.
            // Instead, I'm opting to use the Player field, Because It Works :TM:
            var target = chat.Player;

            chat.Player = null;
            chat.Tag = "";

            if (player == null) {
                chat.Text = $"Target of /locate not found.";
                return;
            }
            DataPlayerState? state;
            if (Client?.Data?.TryGetBoundRef(target, out state) == false || state == null) {
                chat.Text = $"{target.FullName} isn't in game or is in another channel.";
                return;
            }

            // Abuse the player list representation to get a formatted version
            var fakeBlob = new BlobPlayer();
            Context.Get<CelesteNetPlayerListComponent>().GetState(fakeBlob, state);
            var location = fakeBlob.Location;
            string iconEmoji = "";

            if (location.Icon != null) {
                string emojiId = $"celestenet_SID_{location.SID}_";
                if (!Emoji.Registered.Contains(emojiId)) {
                    // We need to downscale the icon to fit in chat
                    MTexture? icon = 
                        (fakeBlob.LocationMode & LocationModes.Icons) != 0 && GFX.Gui.Has(location.Icon) 
                            ? GFX.Gui[location.Icon]
                            : null;
                    if (icon != null) {
                        float scale = 64f / icon.Height;

                        var tex = new MTexture(new MTexture(icon.Texture), icon.ClipRect) { ScaleFix = scale };
                        Emoji.Register(emojiId, tex);
                        Emoji.Fill(CelesteNetClientFont.Font);
                    }
                }
                if (Emoji.Registered.Contains(emojiId))
                    iconEmoji = $":{emojiId}:";
            }
            
            string locationName = location.Name;
            
            if (!string.IsNullOrEmpty(iconEmoji))
                locationName = $"{iconEmoji} {locationName}";
            
            if (!string.IsNullOrEmpty(location.Side))
                locationName += $" {location.Side}";
            
            chat.Text = $"{target.FullName} is in room '{location.Level}' of {locationName}.";
        }

In any case you need to take out the throw statement, I'm assuming that's come over from Server ChatModule's error handling stuff? :v
I also don't have your empty SID check taken into account here, hadn't seen that yet.

@balt-dev
Copy link
Contributor Author

Pushed the refactor, thanks

@balt-dev
Copy link
Contributor Author

@RedFlames review?

@balt-dev
Copy link
Contributor Author

I've fixed everything except the handshake thing, which I saw on Discord might take a bit of time.

@balt-dev
Copy link
Contributor Author

image
Here's an image of the latest commit in action!

@balt-dev
Copy link
Contributor Author

The unsupported client doesn't get /locate in the command list either.

@RedFlames
Copy link
Collaborator

I'm also fairly certain the CmdLocate doesn't need its ValidatePlayerSession because mostly that stuff should already be handled by the ParamPlayerSession when it gets parsed, but eh, also doesn't hurt or anything.

Anyways I think I'll merge this? And prepare to release a new client build with the recent stuff... #152 and all that. v2.4.0 milestone
(I think your other PR, the Pico8 Ghosts will still have to wait for later 🙂)

@RedFlames RedFlames added this to the v2.4.0 milestone Aug 9, 2024
…dshake, enum types would ToString to the names of the values rather than the underlying numeric type.

This changes it so that the value gets sent as the underlying type and then the server parses it by its TypeCode as normal.
… since the Player field of the DataChat is being (intentionally) mis-used.

Also, filtering the command list down before calling SendCommandList was wrong, since that function already does some filtering and can check for the required features as well.
@RedFlames
Copy link
Collaborator

Fixed those enum Options related issues, and a few more small things that I noticed.

Hopefully there isn't anything else we/I overlooked because I'm quite ready to merge this.

@RedFlames RedFlames merged commit 567bb00 into 0x0ade:main Aug 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants