How to implement /commands

profezzional
edited July 2016 in Photon Chat
I'm working with a browser-based Unity FPS called Warmerise. I'm trying to develop chat commands, mostly emotes. My plan is just simple text replacement based on user input. Example:

User inputs: /hi
Chat outputs: Hello! Profezzional greets everyone.

The emotes would be taken mostly from this list.
I'm new to C#, but I've been looking through the Photon Chat API scripts, and I have code for different commands. My thought is something like this (example for one command):
string msg = message;
if (msg[0] == '/') {
    if (msg.Substring(1, 3).Equals("hi")) {
        if (msg.Length < 5) {
            msg = "Hello! " + sender + " greets everyone.";
        }
        else if (msg[4] == ' ') {
            msg = "Hello! " + sender + " greets " + msg.Substring(5, msg.Length) + ".";		// if target player is specified
        }
    }
}
My problem is I can't figure out where to put this code. I've tried in publishMessage(channelName, message) [line 281 in ChatClient.cs], Add(sender, message) [line 50 in ChatChannel.cs], and in various methods in other chat scripts in the template for this game all of which were unsuccessful when I tested the modified versions in Unity. I think this is because the server it's running on isn't using this modified code, because I don't have access (and can't upload) to the server directly.

This seems possible with Photon Chat based on this thread, but I'm not sure how to implement it and I didn't want to revive that old thread.

Does anyone have any ideas?

Comments

  • JohnTube
    JohnTube mod
    edited July 2016
    Hi @profezzional,

    You should put your code in chat callbacks: OnGetMessages or OnPrivateMessage.
  • Hi @JohnTube,

    It makes sense that I would put it in OnGetMessages(), but I have 2 1/2 questions:
    1) All I have for OnGetMessages() is the method header in the IChatClientListener interface in the API. Is there a class file somewhere that I'm missing that has the method body for it? Or would I just create the method body there in the interface?

    2) Can you explain to me how the server interaction works? What I'm trying to figure out is how to test it locally, because the game dev isn't very communicative, and I'd like to be able to just send him a file when I'm done.

    2 1/2) Does this code have to be on the server, too? Or will it work if it's only on the local client (does the text replacement happen in the local app or on the server)?


    1. yes IChatClientListener should be implemented, how did you manage to work with ChatClient before w/o it? It must be provided in constructor!
    2. You can't test Photon Chat locally at the moment. You need Photon Cloud. The interaction is easy: subscribe to a channel, channel gets created if first subscriber, send data to all subscribers in channel, unsubscribe from channel, channel gets destroyed with last subscriber leaving. Which "game dev" are you talking about?
    3. No you do not need to modify server code. Custom logic should be on client only, server just relays/forwards messages to clients as is.
  • profezzional
    edited July 2016
    @JohnTube
    I'm not the developer of the game (Warmerise) I'm working with, so I don't have the entire code. The Warmerise developer (Max) basically made a "template" in Unity he calls FPS Kit that is a plug-and-play Unity project. When I build and run this Unity project, I can connect to servers, chat, etc.

    My friend who's making some custom maps for the game sent me this FPS Kit, but I only have the API scripts in it under a folder called "Plugins." I don't have the constructors; I don't know how/why it works without having them locally.

    I did find, however, some "example code" on this page, that has OnGetMessages(). Is that the full normal implementation of this method?

    When OnGetMessages() is called (when the server gets a new message), would it loop through all the messages in the array and evaluate them for text replacement? If so, is there a way to make that only happen once?
  • JohnTube
    JohnTube mod
    edited July 2016
    I will skip the part where I need to ask you how come people working on a same thing can't have minimum level of communication.

    Is that the full normal implementation of this method?

    That's just a basic useful example.

    (when the server gets a new message), would it loop through all the messages in the array and evaluate them for text replacement?

    Again, server is just a relay, a forwarder, a router, a proxy.

    If so, is there a way to make that only happen once?

    You need to parse received message in clients inside OnGetMessages and based on received command construct appropriate text string to show to player.

  • profezzional
    edited July 2016
    The game developer (Max) isn't very communicative. I've contacted him a couple times about it and he hasn't responded to me.

    I found another implementation of OnGetMessages() on this page. I gather from the comments there that the method body for OnGetMessages() is custom-made?

    I downloaded the .unity3d file from the game webpage, deobfuscated it (after a lot of work), and unpacked the assets.
    So inside the actual game files, the ONLY references to OnGetMessages() are in IChatClientListener,
    here, and when it is called in HandleChatMessagesEvent() [in Chat Client], here.

    If I need to provide the method body for OnGetMessages(), where would I put it?

    Could I just put the the "basic useful example" body on OnGetMessages(), along with my chat commands code, inside HandleChatMessagesEvent(), replacing the call to OnGetMessages() in line 563, like this?
  • I've contacted the game developer (Max) a couple times and he hasn't responded to me.

    I found another body of OnGetMessages() here. I gather from the comments on that page that the body of OnGetMessages() is custom-made?

    I got the .unity3d file from the game website, deobfuscated and unpacked it (after a lot of work), and looking in the actual game scripts, the only references to OnGetMessages() I have found are in IChatClientListener() here and where it's called in HandleChatMessagesEvent() here.

    It is possible that the method body of OnGetMessages() hasn't been written in this game? If so, where would I write it myself?

    Could I just avoid the call to OnGetMessages() altogether by putting the basic useful example version of the method body, along with my chat commands code, inside HandleChatMessagesEvent(), like this?
  • JohnTube
    JohnTube mod
    edited July 2016
    You should follow the tutorial in the first link. In the first code snippet of that tutorial, GameChatClient implements IChatClientListener interface and thus OnGetMessages() so you could do something like this:
    using ExitGames.Client.Photon.Chat;
    
    public class GameChatClient : MonoBehaviour, IChatClientListener {
    
    // TODO: refactor for more optimized command parsing
    private string getCommandFromMessage(string msg, string sender) {
    if (string.IsNullOrEmpty(msg) || string.IsNullOrEmpty(sender) { return null; } // TODO: log error
    if (msg[0] == '/') {
        if (msg.Substring(1, 3).Equals("hi")) {
            if (msg.Length < 5) {
                return string.Format("Hello! {0} greets everyone.", sender);
            }
            else if (msg[4] == ' ') {
                return string.Format("Hello! {0} greets {1}.", sender, msg.Substring(5, msg.Length));		// if target player is specified
            }
        }
    return string.Format("{0}: {1}", sender, msg);
    }
    
    public void OnGetMessages(string channelName, string[] senders, object[] messages) {
        int msgCount = messages.Length;
        for (int i = 0; i < msgCount; i++) { //go through each received msg
            string msg = messages[i] as string;
            if (string.IsNullOrEmpty(msg)) {continue;} // TODO: log error
            Debug.LogFormat("Received Command {0}", getCommandFromMessage(msg.Trim(), senders[i].Trim()));
        }
    }
    
    ...