예제 #1
0
    protected override void enqueueTextMessage(InTextMessage message, bool to_plugin = true)
    {
        //Dequeue an old text message if there are a lot of messages backed up
        if (textMessageQueue.Count >= MAX_TEXT_MESSAGE_QUEUE)
        {
            InTextMessage old_message;
            textMessageQueue.TryDequeue(out old_message);
        }

        textMessageQueue.Enqueue(message);

        base.enqueueTextMessage(message, to_plugin);
    }
예제 #2
0
    protected void handleInteropMessage(KLFCommon.PluginInteropMessageID id, byte[] data)
    {
        switch (id)
        {

            case KLFCommon.PluginInteropMessageID.CHAT_SEND:

                if (data != null)
                {
                    String line = encoder.GetString(data);

                    InTextMessage message = new InTextMessage();
                    message.fromServer = false;
                    message.message = "[" + clientSettings.username + "] " + line;
                    enqueueTextMessage(message, false);

                    handleChatInput(line);
                }

                break;

            case KLFCommon.PluginInteropMessageID.PLUGIN_DATA:

                String new_watch_player_name = String.Empty;

                if (data != null && data.Length >= 9)
                {
                    UnicodeEncoding encoder = new UnicodeEncoding();
                    int index = 0;

                    //Read current activity status
                    bool in_flight = data[index] != 0;
                    index++;

                    //Read current game title
                    int current_game_title_length = KLFCommon.intFromBytes(data, index);
                    index += 4;

                    currentGameTitle = encoder.GetString(data, index, current_game_title_length);
                    index += current_game_title_length;

                    //Send the activity status to the server
                    if (in_flight)
                        sendMessageTCP(KLFCommon.ClientMessageID.ACTIVITY_UPDATE_IN_FLIGHT, null);
                    else
                        sendMessageTCP(KLFCommon.ClientMessageID.ACTIVITY_UPDATE_IN_GAME, null);
                }
                break;

            case KLFCommon.PluginInteropMessageID.PRIMARY_PLUGIN_UPDATE:
                sendPluginUpdate(data, true);
                break;

            case KLFCommon.PluginInteropMessageID.SECONDARY_PLUGIN_UPDATE:
                sendPluginUpdate(data, false);
                break;

            case KLFCommon.PluginInteropMessageID.SCREENSHOT_SHARE:

                if (data != null)
                {
                    lock (screenshotOutLock)
                    {
                        queuedOutScreenshot = data;
                    }
                }

                break;

            case KLFCommon.PluginInteropMessageID.SCREENSHOT_WATCH_UPDATE:
                if (data != null && data.Length >= 8)
                {
                    int index = KLFCommon.intFromBytes(data, 0);
                    int current_index = KLFCommon.intFromBytes(data, 4);
                    String name = encoder.GetString(data, 8, data.Length - 8);

                    if (watchPlayerName != name || watchPlayerIndex != index)
                    {
                        watchPlayerName = name;
                        watchPlayerIndex = index;

                        //Look in the screenshot cache for the requested screenshot
                        Screenshot cached = getCachedScreenshot(watchPlayerIndex, watchPlayerName);
                        if (cached != null)
                            sendClientInteropMessage(KLFCommon.ClientInteropMessageID.SCREENSHOT_RECEIVE, cached.toByteArray());

                        sendScreenshotWatchPlayerMessage((cached == null), current_index, watchPlayerIndex, watchPlayerName);
                    }
                }
                break;

        }
    }
예제 #3
0
    protected void handleMessage(KLFCommon.ServerMessageID id, byte[] data)
    {
        switch (id)
        {
            case KLFCommon.ServerMessageID.HANDSHAKE:

                Int32 protocol_version = KLFCommon.intFromBytes(data);

                if (data.Length >= 8)
                {
                    Int32 server_version_length = KLFCommon.intFromBytes(data, 4);

                    if (data.Length >= 12 + server_version_length)
                    {
                        String server_version = encoder.GetString(data, 8, server_version_length);
                        clientID = KLFCommon.intFromBytes(data, 8 + server_version_length);

                        Console.WriteLine("Handshake received. Server is running version: " + server_version);
                    }
                }

                //End the session if the protocol versions don't match
                if (protocol_version != KLFCommon.NET_PROTOCOL_VERSION)
                {
                    Console.WriteLine("Server version is incompatible with client version.");
                    endSession = true;
                    intentionalConnectionEnd = true;
                }
                else
                {
                    sendHandshakeMessage(); //Reply to the handshake
                    lock (udpTimestampLock)
                    {
                        lastUDPMessageSendTime = stopwatch.ElapsedMilliseconds;
                    }
                    handshakeCompleted = true;
                }

                break;

            case KLFCommon.ServerMessageID.HANDSHAKE_REFUSAL:

                String refusal_message = encoder.GetString(data, 0, data.Length);

                endSession = true;
                intentionalConnectionEnd = true;

                enqueuePluginChatMessage("Server refused connection. Reason: " + refusal_message, true);

                break;

            case KLFCommon.ServerMessageID.SERVER_MESSAGE:
            case KLFCommon.ServerMessageID.TEXT_MESSAGE:

                if (data != null)
                {

                    InTextMessage in_message = new InTextMessage();

                    in_message.fromServer = (id == KLFCommon.ServerMessageID.SERVER_MESSAGE);
                    in_message.message = encoder.GetString(data, 0, data.Length);

                    //Queue the message
                    enqueueTextMessage(in_message);
                }

                break;

            case KLFCommon.ServerMessageID.PLUGIN_UPDATE:

            if (data != null)
                    sendClientInteropMessage(KLFCommon.ClientInteropMessageID.PLUGIN_UPDATE, data);

                break;

            case KLFCommon.ServerMessageID.SERVER_SETTINGS:

                lock (serverSettingsLock)
                {
                    if (data != null && data.Length >= KLFCommon.SERVER_SETTINGS_LENGTH && handshakeCompleted)
                    {

                        updateInterval = KLFCommon.intFromBytes(data, 0);
                        screenshotInterval = KLFCommon.intFromBytes(data, 4);

                        lock (clientDataLock)
                        {
                            int new_screenshot_height = KLFCommon.intFromBytes(data, 8);
                            if (screenshotSettings.maxHeight != new_screenshot_height)
                            {
                                screenshotSettings.maxHeight = new_screenshot_height;
                                lastClientDataChangeTime = stopwatch.ElapsedMilliseconds;
                                enqueueTextMessage("Screenshot Height has been set to " + screenshotSettings.maxHeight);
                            }

                            if (inactiveShipsPerUpdate != data[12])
                            {
                                inactiveShipsPerUpdate = data[12];
                                lastClientDataChangeTime = stopwatch.ElapsedMilliseconds;
                            }
                        }
                    }
                }

                break;

            case KLFCommon.ServerMessageID.SCREENSHOT_SHARE:
                if (data != null && data.Length > 0 && data.Length < screenshotSettings.maxNumBytes
                    && watchPlayerName.Length > 0)
                {
                    //Cache the screenshot
                    Screenshot screenshot = new Screenshot();
                    screenshot.setFromByteArray(data);
                    cacheScreenshot(screenshot);

                    //Send the screenshot to the client
                    sendClientInteropMessage(KLFCommon.ClientInteropMessageID.SCREENSHOT_RECEIVE, data);
                }
                break;

            case KLFCommon.ServerMessageID.CONNECTION_END:

                if (data != null)
                {
                    String message = encoder.GetString(data, 0, data.Length);

                    endSession = true;

                    //If the reason is not a timeout, connection end is intentional
                    intentionalConnectionEnd = message.ToLower() != "timeout";

                    enqueuePluginChatMessage("Server closed the connection: " + message, true);
                }

                break;

            case KLFCommon.ServerMessageID.UDP_ACKNOWLEDGE:
                lock (udpTimestampLock)
                {
                    lastUDPAckReceiveTime = stopwatch.ElapsedMilliseconds;
                }
                break;

            case KLFCommon.ServerMessageID.CRAFT_FILE:

                if (data != null && data.Length > 4)
                {
                    //Read craft name length
                    byte craft_type = data[0];
                    int craft_name_length = KLFCommon.intFromBytes(data, 1);
                    if (craft_name_length < data.Length - 5)
                    {
                        //Read craft name
                        String craft_name = encoder.GetString(data, 5, craft_name_length);

                        //Read craft bytes
                        byte[] craft_bytes = new byte[data.Length - craft_name_length - 5];
                        Array.Copy(data, 5 + craft_name_length, craft_bytes, 0, craft_bytes.Length);

                        //Write the craft to a file
                        String filename = getCraftFilename(craft_name, craft_type);
                        if (filename != null)
                        {
                            try
                            {
                                File.WriteAllBytes(filename, craft_bytes);
                                enqueueTextMessage("Received craft file: " + craft_name);
                            }
                            catch
                            {
                                enqueueTextMessage("Error saving received craft file: " + craft_name);
                            }
                        }
                        else
                            enqueueTextMessage("Unable to save received craft file.");
                    }
                }

                break;

            case KLFCommon.ServerMessageID.PING_REPLY:
                if (pingStopwatch.IsRunning)
                {
                    enqueueTextMessage("Ping Reply: " + pingStopwatch.ElapsedMilliseconds + "ms");
                    pingStopwatch.Stop();
                    pingStopwatch.Reset();
                }
                break;
        }
    }
예제 #4
0
 protected void enqueueTextMessage(String message, bool from_server = false, bool to_plugin = true)
 {
     InTextMessage text_message = new InTextMessage();
     text_message.message = message;
     text_message.fromServer = from_server;
     enqueueTextMessage(text_message, to_plugin);
 }
예제 #5
0
 protected virtual void enqueueTextMessage(InTextMessage message, bool to_plugin = true)
 {
     if (to_plugin)
     {
         if (message.fromServer)
             enqueuePluginChatMessage("[Server] " + message.message, false);
         else
             enqueuePluginChatMessage(message.message);
     }
 }
예제 #6
0
        static void handleMessage(KMPCommon.ServerMessageID id, byte[] data)
        {
            //LogAndShare("Message ID: " + id.ToString() + " data: " + (data == null ? "0" : System.Text.Encoding.ASCII.GetString(data)));
            switch (id)
            {
                case KMPCommon.ServerMessageID.HANDSHAKE:
                    Int32 protocol_version = KMPCommon.intFromBytes(data);

                    if (data.Length >= 8)
                    {
                        Int32 server_version_length = KMPCommon.intFromBytes(data, 4);

                        if (data.Length >= 12 + server_version_length)
                        {
                            String server_version = encoder.GetString(data, 8, server_version_length);
                            clientID = KMPCommon.intFromBytes(data, 8 + server_version_length);
                            gameManager.gameMode = KMPCommon.intFromBytes(data, 12 + server_version_length);
                            int kmpModControl_length = KMPCommon.intFromBytes(data, 16 + server_version_length);
                            kmpModControl_bytes = new byte[kmpModControl_length];
                            Array.Copy(data, 20 + server_version_length, kmpModControl_bytes, 0, kmpModControl_length);

                            SetMessage("Handshake received. Server version: " + server_version);
                        }
                    }

                    //End the session if the protocol versions don't match
                    if (protocol_version != KMPCommon.NET_PROTOCOL_VERSION)
                    {
                        endSession = true;
                        intentionalConnectionEnd = true;
                        gameManager.disconnect("Your client is incompatible with this server");
                    }
                    else
                    {
                        if (!modCheck(kmpModControl_bytes))
                        {
                            endSession = true;
                            intentionalConnectionEnd = true;
                            gameManager.disconnect(modMismatchError);
                        }
                        else
                        {
                            sendHandshakeMessage(); //Reply to the handshake
                            lock (udpTimestampLock)
                            {
                                lastUDPMessageSendTime = stopwatch.ElapsedMilliseconds;
                            }
                            handshakeCompleted = true;
                        }
                    }

                    break;

                case KMPCommon.ServerMessageID.HANDSHAKE_REFUSAL:

                    String refusal_message = encoder.GetString(data, 0, data.Length);

                    endSession = true;
                    intentionalConnectionEnd = true;

                    enqueuePluginChatMessage("Server refused connection. Reason: " + refusal_message, true);

                    break;

                case KMPCommon.ServerMessageID.SERVER_MESSAGE:
                case KMPCommon.ServerMessageID.TEXT_MESSAGE:

                    if (data != null)
                    {

                        InTextMessage in_message = new InTextMessage();

                        in_message.fromServer = (id == KMPCommon.ServerMessageID.SERVER_MESSAGE);
                        in_message.isMOTD = (id == KMPCommon.ServerMessageID.MOTD_MESSAGE);
                        in_message.message = encoder.GetString(data, 0, data.Length);
                        if (in_message.message.Contains(" has shared a screenshot.")) {
                            int screenshotSharePlayerNameIndex = in_message.message.IndexOf(" has shared a screenshot.");
                            string screenshotSharePlayerName = in_message.message.Substring(0, screenshotSharePlayerNameIndex);
                            if (screenshotSharePlayerName != username) {
                                bool listPlayerNameInScreenshotsWaiting = false;
                                foreach (string listPlayer in screenshotsWaiting)
                                {
                                    if (listPlayer == screenshotSharePlayerName) {
                                        listPlayerNameInScreenshotsWaiting = true;
                                    }
                                }
                                if (listPlayerNameInScreenshotsWaiting == false)
                                {
                                    screenshotsWaiting.Add(screenshotSharePlayerName);
                                }
                            }
                        }

                        if (in_message.message.Contains(" has disconnected : ")) {
                            int quitPlayerNameIndex = in_message.message.IndexOf(" has disconnected : ");
                            string quitPlayerName = in_message.message.Substring(0, quitPlayerNameIndex);
                            if (quitPlayerName != username) {
                                bool listPlayerNameInScreenshotsWaiting = false;
                                foreach (string listPlayer in screenshotsWaiting)
                                {
                                    if (listPlayer == quitPlayerName) {
                                        listPlayerNameInScreenshotsWaiting = true;
                                    }
                                }
                                if (listPlayerNameInScreenshotsWaiting)
                                {
                                    screenshotsWaiting.Remove(quitPlayerName);
                                }
                            }
                        }

                        //Queue the message
                        enqueueTextMessage(in_message);
                    }

                    break;

                case KMPCommon.ServerMessageID.MOTD_MESSAGE:

                    if (data != null)
                    {
                        InTextMessage in_message = new InTextMessage();
                        in_message.fromServer = (id == KMPCommon.ServerMessageID.SERVER_MESSAGE);
                        in_message.isMOTD = (id == KMPCommon.ServerMessageID.MOTD_MESSAGE);
                        in_message.message = encoder.GetString(data, 0, data.Length);

                        enqueueTextMessage(in_message);
                    }

                    break;

                case KMPCommon.ServerMessageID.PLUGIN_UPDATE:

                    if (data != null)
                        enqueueClientInteropMessage(KMPCommon.ClientInteropMessageID.PLUGIN_UPDATE, data);

                    break;

                case KMPCommon.ServerMessageID.SCENARIO_UPDATE:

                    if (data != null)
                        enqueueClientInteropMessage(KMPCommon.ClientInteropMessageID.SCENARIO_UPDATE, data);

                    break;

                case KMPCommon.ServerMessageID.SERVER_SETTINGS:

                    lock (serverSettingsLock)
                    {
                        if (data != null && data.Length >= KMPCommon.SERVER_SETTINGS_LENGTH && handshakeCompleted)
                        {

                            updateInterval = KMPCommon.intFromBytes(data, 0);
                            screenshotInterval = KMPCommon.intFromBytes(data, 4);

                            lock (clientDataLock)
                            {
                                int new_screenshot_height = KMPCommon.intFromBytes(data, 8);
                                if (screenshotSettings.maxHeight != new_screenshot_height)
                                {
                                    screenshotSettings.maxHeight = new_screenshot_height;
                                    lastClientDataChangeTime = stopwatch.ElapsedMilliseconds;
                                    enqueueTextMessage("Screenshot Height has been set to " + screenshotSettings.maxHeight);
                                }

                                gameManager.safetyBubbleRadius = BitConverter.ToDouble(data, 12);

                                if (inactiveShipsPerUpdate != data[20])
                                {
                                    inactiveShipsPerUpdate = data[20];
                                    lastClientDataChangeTime = stopwatch.ElapsedMilliseconds;
                                }
                                gameManager.gameCheatsEnabled = Convert.ToBoolean(data[21]);
                                gameManager.gameArrr = Convert.ToBoolean(data[22]);
                                //partList, requiredModList, shaList, resourceList and resourceControlMode

                            }

                            receivedSettings = true;
                            /*
                            Log.Debug("Update interval: " + updateInterval);
                            Log.Debug("Screenshot interval: " + screenshotInterval);
                            Log.Debug("Inactive ships per update: " + inactiveShipsPerUpdate);
                             */
                        }
                    }

                    break;

                case KMPCommon.ServerMessageID.SCREENSHOT_SHARE:

                    if (data != null && data.Length > 0 && data.Length < screenshotSettings.maxNumBytes
                        && watchPlayerName.Length > 0 && watchPlayerName != username)
                    {
                        enqueueClientInteropMessage(KMPCommon.ClientInteropMessageID.SCREENSHOT_RECEIVE, data);
                    }
                    break;

                case KMPCommon.ServerMessageID.CONNECTION_END:
                    if (data != null)
                    {
                        String message = encoder.GetString(data, 0, data.Length);

                        gameManager.disconnect(message);
                        clearConnectionState();

                        //If the reason is not a timeout, connection end is intentional
                        intentionalConnectionEnd = message.ToLower() != "timeout";
                        enqueuePluginChatMessage("Server closed the connection: " + message, true);

                        SetMessage("Disconnected from server: " + message);
                    }
                    else
                    {
                        gameManager.disconnect();
                        clearConnectionState();
                        SetMessage("Disconnected from server");
                    }

                    break;

                case KMPCommon.ServerMessageID.UDP_ACKNOWLEDGE:
                    lock (udpTimestampLock)
                    {
                        lastUDPAckReceiveTime = stopwatch.ElapsedMilliseconds;
                    }
                    break;

                case KMPCommon.ServerMessageID.CRAFT_FILE:

                    if (data != null && data.Length > 8)
                    {
                        //Read craft name length
                        KMPCommon.CraftType craft_type = (KMPCommon.CraftType)KMPCommon.intFromBytes(data, 0);
                        int craft_name_length = KMPCommon.intFromBytes(data, 4);
                        if (craft_name_length < data.Length - 8)
                        {
                            //Read craft name
                            String craft_name = encoder.GetString(data, 8, craft_name_length);

                            //Read craft bytes
                            byte[] craft_bytes = new byte[data.Length - craft_name_length - 8];
                            Array.Copy(data, 8 + craft_name_length, craft_bytes, 0, craft_bytes.Length);

                            //Write the craft to a file
                            String filename = getCraftFilename(craft_name, craft_type);
                            if (filename != null)
                            {
                                try
                                {
                                    //KSP.IO.File.WriteAllBytes<KMPClientMain>(craft_bytes, filename);
                                    System.IO.File.WriteAllBytes(filename, craft_bytes);
                                    enqueueTextMessage("Received craft file: " + craft_name);
                                }
                                catch (Exception e)
                                {
                                    Log.Debug("Exception thrown in handleMessage(), catch 1, Exception: {0}", e.ToString());
                                    enqueueTextMessage("Error saving received craft file: " + craft_name);
                                }
                            }
                            else
                                enqueueTextMessage("Unable to save received craft file.");
                        }
                    }

                    break;

                case KMPCommon.ServerMessageID.PING_REPLY:
                    if (pingStopwatch.IsRunning)
                    {
                        enqueueTextMessage("Ping Reply: " + pingStopwatch.ElapsedMilliseconds + "ms");
                        lastPing = pingStopwatch.ElapsedMilliseconds;
                        pingStopwatch.Stop();
                        pingStopwatch.Reset();
                    }
                    break;

                case KMPCommon.ServerMessageID.SYNC:
                    if (data != null) gameManager.targetTick = BitConverter.ToDouble(data, 0) + Convert.ToDouble(lastPing);

                    break;
                case KMPCommon.ServerMessageID.SYNC_COMPLETE:
                    gameManager.HandleSyncCompleted();
                    break;
                case KMPCommon.ServerMessageID.SPLIT_MESSAGE:
            handleSplitMessage(data);
                    break;
            }
        }
예제 #7
0
        static void enqueueTextMessage(InTextMessage message, bool to_plugin = true)
        {
            //Dequeue an old text message if there are a lot of messages backed up
            if (textMessageQueue.Count >= MAX_TEXT_MESSAGE_QUEUE)
            {
                textMessageQueue.Dequeue();
            }

            textMessageQueue.Enqueue(message);

            if (to_plugin)
            {
                if (message.fromServer)
                    enqueuePluginChatMessage("[Server] " + message.message, false);
                else if (message.isMOTD)
                    enqueuePluginChatMessage("[MOTD] " + message.message, false);
                else
                    enqueuePluginChatMessage(message.message);
            }
        }
예제 #8
0
        static void handleMessage(KLFCommon.ServerMessageID id, byte[] data)
        {
            ASCIIEncoding encoder = new ASCIIEncoding();

            switch (id)
            {
                case KLFCommon.ServerMessageID.HANDSHAKE:

                    Int32 protocol_version = KLFCommon.intFromBytes(data);
                    String server_version = encoder.GetString(data, 4, data.Length - 4);

                    Console.WriteLine("Handshake received. Server is running version: "+server_version);

                    //End the session if the protocol versions don't match
                    if (protocol_version != KLFCommon.NET_PROTOCOL_VERSION)
                    {
                        Console.WriteLine("Server version is incompatible with client version. Ending session.");
                        endSession = true;
                    }
                    else
                    {
                        tcpSendMutex.WaitOne();
                        sendHandshakeMessage(); //Reply to the handshake
                        tcpSendMutex.ReleaseMutex();
                    }

                    break;

                case KLFCommon.ServerMessageID.HANDSHAKE_REFUSAL:

                    String refusal_message = encoder.GetString(data, 0, data.Length);
                    Console.WriteLine("Server refused connection. Reason: " + refusal_message);
                    endSession = true;

                    break;

                case KLFCommon.ServerMessageID.SERVER_MESSAGE:

                    InTextMessage in_message = new InTextMessage();

                    in_message.fromServer = true;
                    in_message.message = encoder.GetString(data, 0, data.Length);

                    //Queue the message
                    textMessageQueueMutex.WaitOne();
                    enqueueTextMessage(in_message);
                    textMessageQueueMutex.ReleaseMutex();

                    break;

                case KLFCommon.ServerMessageID.TEXT_MESSAGE:

                    in_message = new InTextMessage();

                    in_message.fromServer = false;
                    in_message.message = encoder.GetString(data, 0, data.Length);

                    //Queue the message
                    textMessageQueueMutex.WaitOne();
                    enqueueTextMessage(in_message);
                    textMessageQueueMutex.ReleaseMutex();

                    break;

                case KLFCommon.ServerMessageID.PLUGIN_UPDATE:

                    //Add the update the queue
                    pluginUpdateInMutex.WaitOne();

                    pluginUpdateInQueue.Enqueue(data);

                    pluginUpdateInMutex.ReleaseMutex();

                    break;

                case KLFCommon.ServerMessageID.SERVER_SETTINGS:

                    serverSettingsMutex.WaitOne();
                    updateInterval = KLFCommon.intFromBytes(data, 0);
                    maxQueuedUpdates = KLFCommon.intFromBytes(data, 4);
                    serverSettingsMutex.ReleaseMutex();

                    break;
            }
        }
예제 #9
0
        static void handleInteropMessage(KMPCommon.PluginInteropMessageID id, byte[] data)
        {
            switch (id)
            {

                case KMPCommon.PluginInteropMessageID.CHAT_SEND:
                    if (data != null)
                    {
                        String line = encoder.GetString(data);

                        InTextMessage message = new InTextMessage();
                        message.fromServer = false;
                        message.isMOTD = false;
                        message.message = "[" + username + "] " + line;
                        enqueueTextMessage(message, false);

                        handleChatInput(line);
                    }

                    break;

                case KMPCommon.PluginInteropMessageID.PLUGIN_DATA:
                    String new_watch_player_name = String.Empty;

                    if (data != null && data.Length >= 9)
                    {
                        UnicodeEncoding encoder = new UnicodeEncoding();
                        int index = 0;

                        //Read current activity status
                        bool in_flight = data[index] != 0;
                        index++;

                        //Read current game title
                        int current_game_title_length = KMPCommon.intFromBytes(data, index);
                        index += 4;

                        currentGameTitle = encoder.GetString(data, index, current_game_title_length);
                        index += current_game_title_length;

                        //Read the watch player name
                        int watch_player_name_length = KMPCommon.intFromBytes(data, index);
                        index += 4;

                        new_watch_player_name = encoder.GetString(data, index, watch_player_name_length);
                        index += watch_player_name_length;

                        //Send the activity status to the server
                        if (in_flight)
                            queueOutgoingMessage(KMPCommon.ClientMessageID.ACTIVITY_UPDATE_IN_FLIGHT, null);
                        else
                            queueOutgoingMessage(KMPCommon.ClientMessageID.ACTIVITY_UPDATE_IN_GAME, null);
                    }

                    if (watchPlayerName != new_watch_player_name)
                    {
                        watchPlayerName = new_watch_player_name;

                        if (watchPlayerName == username && lastSharedScreenshot != null)
                            enqueueClientInteropMessage(KMPCommon.ClientInteropMessageID.SCREENSHOT_RECEIVE, lastSharedScreenshot);

                        sendScreenshotWatchPlayerMessage(watchPlayerName);
                    }
                    break;

                case KMPCommon.PluginInteropMessageID.PRIMARY_PLUGIN_UPDATE:
                    sendPluginUpdate(data, true);
                    break;

                case KMPCommon.PluginInteropMessageID.SECONDARY_PLUGIN_UPDATE:
                    sendPluginUpdate(data, false);
                    break;

                case KMPCommon.PluginInteropMessageID.SCENARIO_UPDATE:
                    sendScenarioUpdate(data);
                    break;

                case KMPCommon.PluginInteropMessageID.SCREENSHOT_SHARE:
                    if (data != null)
                    {
                        lock (screenshotOutLock)
                        {
                            queuedOutScreenshot = data;
                        }
                    }

                    break;
                case KMPCommon.PluginInteropMessageID.WARPING:
                    queueOutgoingMessage(KMPCommon.ClientMessageID.WARPING, data);
                    break;
                case KMPCommon.PluginInteropMessageID.SSYNC:
                    queueOutgoingMessage(KMPCommon.ClientMessageID.SSYNC, data);
                    break;
            }
        }
        static void handleMessage(KMPCommon.ServerMessageID id, byte[] data)
        {
            //LogAndShare("Message ID: " + id.ToString() + " data: " + (data == null ? "0" : System.Text.Encoding.ASCII.GetString(data)));
            switch (id)
            {
                case KMPCommon.ServerMessageID.HANDSHAKE:
                    Int32 protocol_version = KMPCommon.intFromBytes(data);

                    if (data.Length >= 8)
                    {
                        Int32 server_version_length = KMPCommon.intFromBytes(data, 4);

                        if (data.Length >= 12 + server_version_length)
                        {
                            String server_version = encoder.GetString(data, 8, server_version_length);
                            clientID = KMPCommon.intFromBytes(data, 8 + server_version_length);

                            SetMessage("Handshake received. Server version: " + server_version);
                        }
                    }

                    //End the session if the protocol versions don't match
                    if (protocol_version != KMPCommon.NET_PROTOCOL_VERSION)
                    {
                        endSession = true;
                        intentionalConnectionEnd = true;
                    }
                    else
                    {
                        sendHandshakeMessage(); //Reply to the handshake
                        lock (udpTimestampLock)
                        {
                            lastUDPMessageSendTime = stopwatch.ElapsedMilliseconds;
                        }
                        handshakeCompleted = true;
                    }

                    break;

                case KMPCommon.ServerMessageID.HANDSHAKE_REFUSAL:

                    String refusal_message = encoder.GetString(data, 0, data.Length);

                    endSession = true;
                    intentionalConnectionEnd = true;

                    enqueuePluginChatMessage("Server refused connection. Reason: " + refusal_message, true);

                    break;

                case KMPCommon.ServerMessageID.SERVER_MESSAGE:
                case KMPCommon.ServerMessageID.TEXT_MESSAGE:

                    if (data != null)
                    {

                        InTextMessage in_message = new InTextMessage();

                        in_message.fromServer = (id == KMPCommon.ServerMessageID.SERVER_MESSAGE);
                        in_message.message = encoder.GetString(data, 0, data.Length);

                        //Queue the message
                        enqueueTextMessage(in_message);
                    }

                    break;

                case KMPCommon.ServerMessageID.PLUGIN_UPDATE:

                    if (data != null)
                        enqueueClientInteropMessage(KMPCommon.ClientInteropMessageID.PLUGIN_UPDATE, data);

                    break;

                case KMPCommon.ServerMessageID.SERVER_SETTINGS:

                    lock (serverSettingsLock)
                    {
                        if (data != null && data.Length >= KMPCommon.SERVER_SETTINGS_LENGTH && handshakeCompleted)
                        {

                            updateInterval = KMPCommon.intFromBytes(data, 0);
                            screenshotInterval = KMPCommon.intFromBytes(data, 4);

                            lock (clientDataLock)
                            {
                                int new_screenshot_height = KMPCommon.intFromBytes(data, 8);
                                if (screenshotSettings.maxHeight != new_screenshot_height)
                                {
                                    screenshotSettings.maxHeight = new_screenshot_height;
                                    lastClientDataChangeTime = stopwatch.ElapsedMilliseconds;
                                    enqueueTextMessage("Screenshot Height has been set to " + screenshotSettings.maxHeight);
                                }

                                if (inactiveShipsPerUpdate != data[12])
                                {
                                    inactiveShipsPerUpdate = data[12];
                                    lastClientDataChangeTime = stopwatch.ElapsedMilliseconds;
                                }
                            }

                            receivedSettings = true;
                            /*
                            UnityEngine.Debug.Log("Update interval: " + updateInterval);
                            UnityEngine.Debug.Log("Screenshot interval: " + screenshotInterval);
                            UnityEngine.Debug.Log("Inactive ships per update: " + inactiveShipsPerUpdate);
                             */
                        }
                    }

                    break;

                case KMPCommon.ServerMessageID.SCREENSHOT_SHARE:

                    if (data != null && data.Length > 0 && data.Length < screenshotSettings.maxNumBytes
                        && watchPlayerName.Length > 0 && watchPlayerName != username)
                    {
                        enqueueClientInteropMessage(KMPCommon.ClientInteropMessageID.SCREENSHOT_RECEIVE, data);
                    }
                    break;

                case KMPCommon.ServerMessageID.CONNECTION_END:

                    gameManager.disconnect();
                    if (data != null)
                    {
                        String message = encoder.GetString(data, 0, data.Length);

                        endSession = true;
                        handshakeCompleted = false;
                        receivedSettings = false;
                        //If the reason is not a timeout, connection end is intentional
                        intentionalConnectionEnd = message.ToLower() != "timeout";
                        enqueuePluginChatMessage("Server closed the connection: " + message, true);
                        clearConnectionState();
                        SetMessage("Disconnected from server: " + message);
                        gameManager.disconnect(message);
                    }
                    else
                    {
                        clearConnectionState();
                        SetMessage("Disconnected from server");
                        gameManager.disconnect();
                    }

                    break;

                case KMPCommon.ServerMessageID.UDP_ACKNOWLEDGE:
                    lock (udpTimestampLock)
                    {
                        lastUDPAckReceiveTime = stopwatch.ElapsedMilliseconds;
                    }
                    break;

                case KMPCommon.ServerMessageID.CRAFT_FILE:

                    if (data != null && data.Length > 4)
                    {
                        //Read craft name length
                        byte craft_type = data[0];
                        int craft_name_length = KMPCommon.intFromBytes(data, 1);
                        if (craft_name_length < data.Length - 5)
                        {
                            //Read craft name
                            String craft_name = encoder.GetString(data, 5, craft_name_length);

                            //Read craft bytes
                            byte[] craft_bytes = new byte[data.Length - craft_name_length - 5];
                            Array.Copy(data, 5 + craft_name_length, craft_bytes, 0, craft_bytes.Length);

                            //Write the craft to a file
                            String filename = getCraftFilename(craft_name, craft_type);
                            if (filename != null)
                            {
                                try
                                {
                                    //KSP.IO.File.WriteAllBytes<KMPClientMain>(craft_bytes, filename);
                                    System.IO.File.WriteAllBytes(filename,craft_bytes);
                                    enqueueTextMessage("Received craft file: " + craft_name);
                                }
                                catch
                                {
                                    enqueueTextMessage("Error saving received craft file: " + craft_name);
                                }
                            }
                            else
                                enqueueTextMessage("Unable to save received craft file.");
                        }
                    }

                    break;

                case KMPCommon.ServerMessageID.PING_REPLY:
                    if (pingStopwatch.IsRunning)
                    {
                        enqueueTextMessage("Ping Reply: " + pingStopwatch.ElapsedMilliseconds + "ms");
                        lastPing = pingStopwatch.ElapsedMilliseconds;
                        pingStopwatch.Stop();
                        pingStopwatch.Reset();
                    }
                    break;

                case KMPCommon.ServerMessageID.SYNC:
                    if (data != null) gameManager.targetTick = BitConverter.ToDouble(data,0) + Convert.ToDouble(lastPing);

                    break;
                case KMPCommon.ServerMessageID.SYNC_COMPLETE:
                    gameManager.HandleSyncCompleted();
                    break;
            }
        }
예제 #11
0
        static void enqueueTextMessage(InTextMessage message)
        {
            //Dequeue an old text message if there are a lot of messages backed up
            if (textMessageQueue.Count >= MAX_TEXT_MESSAGE_QUEUE)
                textMessageQueue.Dequeue();

            textMessageQueue.Enqueue(message);
        }
예제 #12
0
    protected void HandleMessage(KLFCommon.ServerMessageID id, byte[] data)
    {
        switch (id)
        {
        case KLFCommon.ServerMessageID.Handshake:
            Int32 protocolVersion = KLFCommon.BytesToInt(data);
            if (data.Length >= 8)
            {
                Int32 server_version_length = KLFCommon.BytesToInt(data, 4);
                if (data.Length >= 12 + server_version_length)
                {
                    String server_version = Encoder.GetString(data, 8, server_version_length);
                    ClientID = KLFCommon.BytesToInt(data, 8 + server_version_length);
                    Console.WriteLine("Handshake received. Server is running version: " + server_version);
                }
            }
            //End the session if the protocol versions don't match
            if (protocolVersion != KLFCommon.NetProtocolVersion)
            {
                Console.WriteLine("Server version is incompatible with client version.");
                EndSession = true;
                IntentionalConnectionEnd = true;
            }
            else
            {
                SendHandshakeMessage(); //Reply to the handshake
                lock (UdpTimestampLock)
                {
                    LastUdpMessageSendTime = ClientStopwatch.ElapsedMilliseconds;
                }
                HandshakeComplete = true;
            }
            break;

        case KLFCommon.ServerMessageID.HandshakeRefusal:
            String refusal_message = Encoder.GetString(data, 0, data.Length);
            EndSession = true;
            IntentionalConnectionEnd = true;
            EnqueuePluginChatMessage("Server refused connection. Reason: " + refusal_message, true);
            break;

        case KLFCommon.ServerMessageID.ServerMessage:
        case KLFCommon.ServerMessageID.TextMessage:
            if (data != null)
            {
                InTextMessage inMessage = new InTextMessage();
                inMessage.FromServer = (id == KLFCommon.ServerMessageID.ServerMessage);
                inMessage.message = Encoder.GetString(data, 0, data.Length);
                //Queue the message
                EnqueueTextMessage(inMessage);
            }
            break;

        case KLFCommon.ServerMessageID.PluginUpdate:
            if (data != null)
                SendClientInteropMessage(KLFCommon.ClientInteropMessageID.PluginUpdate, data);
            break;

        case KLFCommon.ServerMessageID.ServerSettings:
            lock (ServerSettingsLock)
            {
                if (data != null && data.Length >= KLFCommon.ServerSettingsLength && HandshakeComplete)
                {
                    UpdateInterval = KLFCommon.BytesToInt(data, 0);
                    ScreenshotInterval = KLFCommon.BytesToInt(data, 4);
                    lock (ClientDataLock)
                    {
                        int new_screenshot_height = KLFCommon.BytesToInt(data, 8);
                        if (ScreenshotConfiguration.MaxHeight != new_screenshot_height)
                        {
                            ScreenshotConfiguration.MaxHeight = new_screenshot_height;
                            LastClientDataChangeTime = ClientStopwatch.ElapsedMilliseconds;
                            EnqueueTextMessage("Screenshot Height has been set to " + ScreenshotConfiguration.MaxHeight);
                        }
                        if (InactiveShipsPerUpdate != data[12])
                        {
                            InactiveShipsPerUpdate = data[12];
                            LastClientDataChangeTime = ClientStopwatch.ElapsedMilliseconds;
                        }
                    }
                }
            }
            break;

        case KLFCommon.ServerMessageID.ScreenshotShare:
            if (data != null
            && data.Length > 0
            && data.Length < ScreenshotConfiguration.MaxNumBytes
            && WatchPlayerName.Length > 0)
            {
                //Cache the screenshot
                Screenshot screenshot = new Screenshot();
                screenshot.SetFromByteArray(data);
                CacheScreenshot(screenshot);
                //Send the screenshot to the client
                SendClientInteropMessage(KLFCommon.ClientInteropMessageID.ScreenshotReceive, data);
            }
            break;

        case KLFCommon.ServerMessageID.ConnectionEnd:
            if (data != null)
            {
                String message = Encoder.GetString(data, 0, data.Length);
                EndSession = true;
                //If the reason is not a timeout, connection end is intentional
                IntentionalConnectionEnd = message.ToLower() != "timeout";
                EnqueuePluginChatMessage("Server closed the connection: " + message, true);
            }

            break;

        case KLFCommon.ServerMessageID.UdpAcknowledge:
            lock (UdpTimestampLock)
            {
                LastUdpAckReceiveTime = ClientStopwatch.ElapsedMilliseconds;
            }
            break;

        case KLFCommon.ServerMessageID.CraftFile:
            if (data != null && data.Length > 4)
            {
                //Read craft name length
                byte craftType = data[0];
                int craftName_length = KLFCommon.BytesToInt(data, 1);
                if (craftName_length < data.Length - 5)
                {
                    //Read craft name
                    String craftName = Encoder.GetString(data, 5, craftName_length);
                    //Read craft bytes
                    byte[] craft_bytes = new byte[data.Length - craftName_length - 5];
                    Array.Copy(data, 5 + craftName_length, craft_bytes, 0, craft_bytes.Length);
                    //Write the craft to a file
                    String filename = GetCraftFilename(craftName, craftType);
                    if (filename != null)
                    {
                        try
                        {
                            File.WriteAllBytes(filename, craft_bytes);
                            EnqueueTextMessage("Received craft file: " + craftName);
                        }
                        catch
                        {
                            EnqueueTextMessage("Error saving received craft file: " + craftName);
                        }
                    }
                    else
                        EnqueueTextMessage("Unable to save received craft file.");
                }
            }
            break;

        case KLFCommon.ServerMessageID.PingReply:
            if (PingStopwatch.IsRunning)
            {
                EnqueueTextMessage("Ping Reply: " + PingStopwatch.ElapsedMilliseconds + "ms");
                PingStopwatch.Stop();
                PingStopwatch.Reset();
            }
            break;
        }
    }
예제 #13
0
    protected void HandleInteropMessage(KLFCommon.PluginInteropMessageID id, byte[] data)
    {
        switch (id)
        {
            case KLFCommon.PluginInteropMessageID.ChatSend:
                if (data != null)
                {
                    String line = Encoder.GetString(data);
                    InTextMessage message = new InTextMessage();
                    message.FromServer = false;
                    message.message = "[" + ClientConfiguration.Username + "] " + line;
                    EnqueueTextMessage(message, false);
                    HandleChatInput(line);
                }
                break;

            case KLFCommon.PluginInteropMessageID.PluginData:
                //String new_watch_player_name = String.Empty;
                if (data != null && data.Length >= 9)
                {
                    int index = 0;
                    //Read current activity status
                    bool inFlight = data[index] != 0;
                    index++;
                    //Read current game title
                    int CurrentGameTitleLength = KLFCommon.BytesToInt(data, index);
                    index += 4;
                    CurrentGameTitle = Encoder.GetString(data, index, CurrentGameTitleLength);
                    index += CurrentGameTitleLength;
                    //Send the activity status to the server
                    if (inFlight)
                        SendMessageTcp(KLFCommon.ClientMessageID.ActivityUpdateInFlight, null);
                    else
                        SendMessageTcp(KLFCommon.ClientMessageID.ActivityUpdateInFlight, null);
                }
                break;

            case KLFCommon.PluginInteropMessageID.PrimaryPluginUpdate:
                SendPluginUpdate(data, true);
                break;

            case KLFCommon.PluginInteropMessageID.SecondaryPluginUpdate:
                SendPluginUpdate(data, false);
                break;

            case KLFCommon.PluginInteropMessageID.ScreenshotShare:
                if (data != null)
                {
                    lock (ScreenshotOutLock)
                    {
                        QueuedOutScreenshot = data;
                    }
                }
                break;

            case KLFCommon.PluginInteropMessageID.ScreenshotWatchUpdate:
                if (data != null && data.Length >= 8)
                {
                    int index = KLFCommon.BytesToInt(data, 0);
                    int currentIndex = KLFCommon.BytesToInt(data, 4);
                    String name = Encoder.GetString(data, 8, data.Length - 8);
                    if (WatchPlayerName != name || WatchPlayerIndex != index)
                    {
                        WatchPlayerName = name;
                        WatchPlayerIndex = index;
                        //Look in the screenshot cache for the requested screenshot
                        Screenshot cached = getCachedScreenshot(WatchPlayerIndex, WatchPlayerName);
                        if (cached != null)
                            SendClientInteropMessage(KLFCommon.ClientInteropMessageID.ScreenshotReceive, cached.ToByteArray());
                        SendScreenshotWatchPlayerMessage((cached == null), currentIndex, WatchPlayerIndex, WatchPlayerName);
                    }
                }
                break;
        }
    }
예제 #14
0
 protected virtual void EnqueueTextMessage(InTextMessage message, bool toPlugin = true)
 {
     if (toPlugin)
         if (message.FromServer)
             EnqueuePluginChatMessage("[Server] " + message.message, false);
         else
             EnqueuePluginChatMessage(message.message);
 }
예제 #15
0
 protected void EnqueueTextMessage(String message, bool FromServer = false, bool toPlugin = true)
 {
     InTextMessage textMessage = new InTextMessage();
     textMessage.message = message;
     textMessage.FromServer = FromServer;
     EnqueueTextMessage(textMessage, toPlugin);
 }
예제 #16
0
 protected override void EnqueueTextMessage(InTextMessage message, bool toPlugin = true)
 {
     //Dequeue an old text message if there are a lot of messages backed up
     if (TextMessageQueue.Count >= MaxTextMessageQueue)
     {
         InTextMessage oldMessage;
         TextMessageQueue.TryDequeue(out oldMessage);
     }
     TextMessageQueue.Enqueue(message);
     base.EnqueueTextMessage(message, toPlugin);
 }