Beispiel #1
0
 public void ServerStarted(S server)
 {
     if (!server.Ip.Equals(IPAddress.Loopback) && LanGameBeacon != null)
     {
         LanGameBeacon.Start();
     }
 }
Beispiel #2
0
        static void CheckAutoStart(S server)
        {
            var nonBotPlayers = server.LobbyInfo.NonBotPlayers;

            //Are all players and admin (could be spectating) ready?
            if (nonBotPlayers.Any(c => c.State != Session.ClientState.Ready) ||
                server.LobbyInfo.Clients.First(c => c.IsAdmin).State != Session.ClientState.Ready)
            {
                return;
            }

            //Does server have at least 2 human players?
            if (!server.LobbyInfo.GlobalSettings.EnableSinglePlayer && nonBotPlayers.Count() < 2)
            {
                return;
            }

            //Are the map conditions satisfied?
            if (server.LobbyInfo.Slots.Any(sl => sl.Value.Required && server.LobbyInfo.ClientInSlot(sl.Key) == null))
            {
                return;
            }

            server.StartGame();
        }
Beispiel #3
0
        void IEndGame.GameEnded(S server)
        {
            if (LanGameBeacon != null)
            {
                LanGameBeacon.Stop();
            }

            PublishGame(server);
        }
Beispiel #4
0
        static string MissionBriefingOrDefault(S server)
        {
            var missionData = server.Map.Rules.Actors["world"].TraitInfoOrDefault <MissionDataInfo>();

            if (missionData != null && !string.IsNullOrEmpty(missionData.Briefing))
            {
                return(missionData.Briefing.Replace("\\n", "\n"));
            }

            return(null);
        }
Beispiel #5
0
        public static int CreateLocalServer(string map)
        {
            var settings = new ServerSettings()
            {
                Name            = "Skirmish Game",
                Map             = map,
                AdvertiseOnline = false
            };

            server = new Server.Server(new IPEndPoint(IPAddress.Loopback, 0), settings, ModData, false);

            return(server.Port);
        }
Beispiel #6
0
        void INotifyServerEmpty.ServerEmpty(S server)
        {
            //Expire any temporary bans
            server.TempBans.Clear();

            //Re-enable spectators
            server.LobbyInfo.GlobalSettings.AllowSpectators = true;

            //Reset player slots
            server.LobbyInfo.Slots = server.Map.Players.Players.
                                     Select(p => MakeSlotFromPlayerReference(p.Value))
                                     .Where(ss => ss != null)
                                     .ToDictionary(ss => ss.PlayerReference, ss => ss);
        }
Beispiel #7
0
        static bool ValidateSlotCommand(S server, Connection conn, Session.Client client, string arg, bool requiresHost)
        {
            if (!server.LobbyInfo.Slots.ContainsKey(arg))
            {
                return(false);
            }

            if (requiresHost && !client.IsAdmin)
            {
                server.SendOrderTo(conn, "Message", "Only the host can do that");
                return(false);
            }
            return(true);
        }
Beispiel #8
0
        void PublishGame(S server)
        {
            //Cache the server info on the main thread to ensure data consistency;
            var gs = new GameServer(server);

            if (!isBusy && server.Settings.AdvertiseOnline)
            {
                UpdateMasterServer(server, gs.ToPOSTData(false));
            }

            if (LanGameBeacon != null)
            {
                LanGameBeacon.BeaconData = gs.ToPOSTData(true);
            }
        }
Beispiel #9
0
        public static bool ValidateCommand(S server, EW.Server.Connection conn, Session.Client client, string cmd)
        {
            if (server.State == ServerState.GameStarted)
            {
                server.SendOrderTo(conn, "Message", "Cannot change state when game started.({0})".F(cmd));
                return(false);
            }
            else if (client.State == Session.ClientState.Ready && !(cmd.StartsWith("state") || cmd == "startgame"))
            {
                server.SendOrderTo(conn, "Message", "Cannot change state when marked as ready.");
                return(false);
            }

            return(true);
        }
Beispiel #10
0
 void ITick.Tick(S server)
 {
     if ((WarGame.RunTime - lastPing > MasterPingInterval * 1000) || isInitialPing)
     {
         PublishGame(server);
     }
     else
     {
         lock (masterServerMessages)
             while (masterServerMessages.Count > 0)
             {
                 server.SendMessage(masterServerMessages.Dequeue());
             }
     }
 }
Beispiel #11
0
        public static void LoadMapSettings(S server, Session.Global gs, Ruleset rules)
        {
            var options = rules.Actors["player"].TraitInfos <ILobbyOptions>()
                          .Concat(rules.Actors["world"].TraitInfos <ILobbyOptions>())
                          .SelectMany(t => t.LobbyOptions(rules));

            foreach (var o in options)
            {
                var value          = o.DefaultValue;
                var preferredValue = o.DefaultValue;
                Session.LobbyOptionState state;
                if (gs.LobbyOptions.TryGetValue(o.Id, out state))
                {
                    // Propagate old state on map change
                    if (!o.IsLocked)
                    {
                        if (o.Values.Keys.Contains(state.PreferredValue))
                        {
                            value = state.PreferredValue;
                        }
                        else if (o.Values.Keys.Contains(state.Value))
                        {
                            value = state.Value;
                        }
                    }

                    preferredValue = state.PreferredValue;
                }
                else
                {
                    state = new Session.LobbyOptionState();
                }

                state.IsLocked        = o.IsLocked;
                state.Value           = value;
                state.PreferredValue  = preferredValue;
                gs.LobbyOptions[o.Id] = state;

                if (o.Id == "gamespeed")
                {
                    var speed = server.ModData.Manifest.Get <GameSpeeds>().Speeds[value];
                    gs.Timestep     = speed.Timestep;
                    gs.OrderLatency = speed.OrderLatency;
                }
            }
        }
Beispiel #12
0
        public void ServerStarted(S server)
        {
            var uid = server.LobbyInfo.GlobalSettings.Map;

            server.Map = server.ModData.MapCache[uid];
            if (server.Map.Status != MapStatus.Available)
            {
                throw new InvalidOperationException("Map {0} not found".F(uid));
            }

            server.LobbyInfo.Slots = server.Map.Players.Players.
                                     Select(p => MakeSlotFromPlayerReference(p.Value))
                                     .Where(s => s != null)
                                     .ToDictionary(s => s.PlayerReference, s => s);

            LoadMapSettings(server, server.LobbyInfo.GlobalSettings, server.Map.Rules);
        }
Beispiel #13
0
        static HSLColor SanitizePlayerColor(S server, HSLColor askedColor, int playerIndex, Connection connectionToEcho = null)
        {
            var validator = server.ModData.Manifest.Get <ColorValidator>();
            var askColor  = askedColor;

            Action <string> onError = message =>
            {
                if (connectionToEcho != null)
                {
                    server.SendOrderTo(connectionToEcho, "Message", message);
                }
            };

            var tileset       = server.Map.Rules.TileSet;
            var terrainColors = tileset.TerrainInfo.Where(ti => ti.RestrictPlayerColor).Select(ti => ti.Color).ToList();
            var playerColors  = server.LobbyInfo.Clients.Where(c => c.Index != playerIndex).Select(c => c.Color.RGB)
                                .Concat(server.Map.Players.Players.Values.Select(p => p.Color.RGB)).ToList();

            return(validator.MakeValid(askColor.RGB, server.Random, terrainColors, playerColors, onError));
        }
Beispiel #14
0
        void UpdateMasterServer(S server, string postData)
        {
            lastPing = WarGame.RunTime;
            isBusy   = true;

            Action a = () =>
            {
                try
                {
                    var endpoint = server.ModData.Manifest.Get <WebServices>().ServerAdvertise;
                    using (var wc = new WebClient())
                    {
                        wc.Proxy = null;
                        var masterResponseText = wc.UploadString(endpoint, postData);

                        if (isInitialPing)
                        {
                            //Log.Write("server", "Master server: " + masterResponseText);
                            var errorCode    = 0;
                            var errorMessage = string.Empty;

                            if (masterResponseText.Length > 0)
                            {
                                var regex = new Regex(@"^\[(?<code>\d+)\](?<message>.*)");
                                var match = regex.Match(masterResponseText);
                                errorMessage = match.Success && int.TryParse(match.Groups["code"].Value, out errorCode) ?
                                               match.Groups["message"].Value.Trim() : "Failed to parse error message";
                            }

                            isInitialPing = false;
                            lock (masterServerMessages)
                            {
                                masterServerMessages.Enqueue("Master server communication established.");
                                if (errorCode != 0)
                                {
                                    // Hardcoded error messages take precedence over the server-provided messages
                                    string message;
                                    if (!MasterServerErrors.TryGetValue(errorCode, out message))
                                    {
                                        message = errorMessage;
                                    }

                                    masterServerMessages.Enqueue("Warning: " + message);
                                    masterServerMessages.Enqueue("Game has not been advertised online.");
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    //Log.Write("server", ex.ToString());
                    lock (masterServerMessages)
                        masterServerMessages.Enqueue("Master server communication failed.");
                }

                isBusy = false;
            };

            a.BeginInvoke(null, null);
        }
Beispiel #15
0
        void ITick.Tick(S server)
        {
            if ((WarGame.RunTime - lastPing) > PingInterval || isInitialPing)
            {
                isInitialPing = false;
                lastPing      = WarGame.RunTime;

                //Ignore client timeout in singleplayer games to make debugging easier
                if (server.LobbyInfo.NonBotClients.Count() < 2 && !server.Dedicated)
                {
                    foreach (var c in server.Conns.ToList())
                    {
                        server.SendOrderTo(c, "Ping", WarGame.RunTime.ToString());
                    }
                }
                else
                {
                    foreach (var c in server.Conns.ToList())
                    {
                        if (c == null || c.Socket == null)
                        {
                            continue;
                        }

                        var client = server.GetClient(c);
                        if (client == null)
                        {
                            server.DropClient(c);
                            server.SendMessage("A player has been dropped after timing out.");
                            continue;
                        }

                        if (c.TimeSinceLastResponse < ConnTimeout)
                        {
                            server.SendOrderTo(c, "Ping", WarGame.RunTime.ToString());
                            if (!c.TimeoutMessageShown && c.TimeSinceLastResponse > PingInterval * 2)
                            {
                                server.SendMessage(client.Name + " is experiencing connection problems.");
                                c.TimeoutMessageShown = true;
                            }
                        }
                        else
                        {
                            server.SendMessage(client.Name + " has benn dropped after timing out.");
                            server.DropClient(c);
                        }
                    }
                }

                if (WarGame.RunTime - lastConnReport > ConnReportInterval)
                {
                    lastConnReport = WarGame.RunTime;

                    var timeouts = server.Conns.Where(c => c.TimeSinceLastResponse > ConnReportInterval && c.TimeSinceLastResponse < ConnTimeout).OrderBy(c => c.TimeSinceLastResponse);

                    foreach (var c in timeouts)
                    {
                        if (c == null || c.Socket == null)
                        {
                            continue;
                        }

                        var client = server.GetClient(c);
                        if (client != null)
                        {
                            server.SendMessage("{0} will be dropped in {1} seconds.".F(client.Name, (ConnTimeout - c.TimeSinceLastResponse) / 1000));
                        }
                    }
                }
            }
        }
Beispiel #16
0
        public bool InterpretCommand(S server, EW.Server.Connection conn, Session.Client client, string cmd)
        {
            if (server == null || conn == null || client == null || !ValidateCommand(server, conn, client, cmd))
            {
                return(false);
            }

            var dict = new Dictionary <string, Func <string, bool> >
            {
                {
                    "state",
                    s =>
                    {
                        var state = Session.ClientState.Invalid;
                        if (!Enum <Session.ClientState> .TryParse(s, false, out state))
                        {
                            server.SendOrderTo(conn, "Message", "Malformed state command");
                            return(true);
                        }
                        client.State = state;

                        server.SyncLobbyClients();
                        CheckAutoStart(server);
                        return(true);
                    }
                },
                {
                    "startgame",
                    s =>
                    {
                        if (!client.IsAdmin)
                        {
                            server.SendOrderTo(conn, "Message", "Only the host can start the game.");
                            return(true);
                        }

                        if (server.LobbyInfo.Slots.Any(sl => sl.Value.Required &&
                                                       server.LobbyInfo.ClientInSlot(sl.Key) == null))
                        {
                            server.SendOrderTo(conn, "Message", "Unable to start the game until required slots are full.");
                            return(true);
                        }

                        if (!server.LobbyInfo.GlobalSettings.EnableSinglePlayer && server.LobbyInfo.NonBotPlayers.Count() < 2)
                        {
                            server.SendOrderTo(conn, "Message", server.TwoHumansRequiredText);
                            return(true);
                        }

                        server.StartGame();
                        return(true);
                    }
                },
                {
                    "slot_bot",
                    s => {
                        var parts = s.Split(' ');

                        if (parts.Length < 3)
                        {
                            server.SendOrderTo(conn, "Message", " Malformed slot_bot command");
                            return(true);
                        }

                        if (!ValidateSlotCommand(server, conn, client, parts[0], true))
                        {
                            return(false);
                        }

                        var slot = server.LobbyInfo.Slots[parts[0]];
                        var bot  = server.LobbyInfo.ClientInSlot(parts[0]);
                        int controllerClientIndex;

                        if (!Exts.TryParseIntegerInvariant(parts[1], out controllerClientIndex))
                        {
                            return(false);
                        }
                        // Invalid slot

                        if (bot != null && bot.Bot == null)
                        {
                            server.SendOrderTo(conn, "Message", "Can't add bots to a slot with  another client");
                            return(true);
                        }

                        var botType = parts[2];
                        var botInfo = server.Map.Rules.Actors["player"].TraitInfos <IBotInfo>().FirstOrDefault(b => b.Type == botType);

                        if (botInfo == null)
                        {
                            server.SendOrderTo(conn, "Message", "Invalid bot type.");
                            return(true);
                        }

                        slot.Closed = false;
                        if (bot == null)
                        {
                            //Create a new bot
                            bot = new Session.Client()
                            {
                                Index      = server.ChooseFreePlayerIndex(),
                                Name       = botInfo.Name,
                                Bot        = botType,
                                Slot       = parts[0],
                                Faction    = "Random",
                                SpawnPoint = 0,
                                Team       = 0,
                                State      = Session.ClientState.NotReady,
                                BotControllerClientIndex = controllerClientIndex,
                            };

                            // Pick a random color for the bot
                            var validator     = server.ModData.Manifest.Get <ColorValidator>();
                            var tileset       = server.Map.Rules.TileSet;
                            var terrainColors = tileset.TerrainInfo.Where(ti => ti.RestrictPlayerColor).Select(ti => ti.Color);
                            var playerColors  = server.LobbyInfo.Clients.Select(c => c.Color.RGB)
                                                .Concat(server.Map.Players.Players.Values.Select(p => p.Color.RGB));

                            bot.Color = bot.PreferredColor = validator.RandomValidColor(server.Random, terrainColors, playerColors);

                            server.LobbyInfo.Clients.Add(bot);
                        }
                        else
                        {
                            // Change the type of the existing bot
                            bot.Name = botInfo.Name;
                            bot.Bot  = botType;
                        }

                        S.SyncClientToPlayerReference(bot, server.Map.Players.Players[parts[0]]);
                        server.SyncLobbyClients();
                        server.SyncLobbySlots();
                        return(true);
                    }
                },
                {
                    "map",
                    s =>
                    {
                        if (!client.IsAdmin)
                        {
                            server.SendOrderTo(conn, "Message", "Only the host can change the map.");
                            return(true);
                        }

                        var lastMap = server.LobbyInfo.GlobalSettings.Map;

                        Action <MapPreview> selectMap = map =>
                        {
                            if (server.LobbyInfo.GlobalSettings.Map != lastMap)
                            {
                                return;
                            }

                            server.LobbyInfo.GlobalSettings.Map = map.Uid;

                            var oldSlots = server.LobbyInfo.Slots.Keys.ToArray();
                            server.Map = server.ModData.MapCache[server.LobbyInfo.GlobalSettings.Map];

                            server.LobbyInfo.Slots = server.Map.Players.Players
                                                     .Select(p => MakeSlotFromPlayerReference(p.Value))
                                                     .Where(ss => ss != null)
                                                     .ToDictionary(ss => ss.PlayerReference, ss => ss);

                            LoadMapSettings(server, server.LobbyInfo.GlobalSettings, server.Map.Rules);

                            //Reset Client states.
                            foreach (var c in server.LobbyInfo.Clients)
                            {
                                c.State = Session.ClientState.Invalid;
                            }

                            var botTypes = server.Map.Rules.Actors["player"].TraitInfos <IBotInfo>().Select(t => t.Type);
                            var slots    = server.LobbyInfo.Slots.Keys.ToArray();
                            var i        = 0;
                            foreach (var os in oldSlots)
                            {
                                var c = server.LobbyInfo.ClientInSlot(os);
                                if (c == null)
                                {
                                    continue;
                                }

                                c.SpawnPoint = 0;
                                c.Slot       = i < slots.Length?slots[i++]:null;
                                if (c.Slot != null)
                                {
                                    if (c.Bot != null && (!server.Map.Players.Players[c.Slot].AllowBots || !botTypes.Contains(c.Bot)))
                                    {
                                        server.LobbyInfo.Clients.Remove(c);
                                    }

                                    S.SyncClientToPlayerReference(c, server.Map.Players.Players[c.Slot]);
                                }
                                else if (c.Bot != null)
                                {
                                    server.LobbyInfo.Clients.Remove(c);
                                }
                            }

                            foreach (var c in server.LobbyInfo.Clients)
                            {
                                if (c.Slot != null && !server.LobbyInfo.Slots[c.Slot].LockColor)
                                {
                                    c.Color = c.PreferredColor = SanitizePlayerColor(server, c.Color, c.Index, conn);
                                }
                            }

                            server.SyncLobbyInfo();

                            server.SendMessage("{0} changed the map to {1}.".F(client.Name, server.Map.Title));

                            if (!server.LobbyInfo.GlobalSettings.EnableSingleplayer)
                            {
                                server.SendMessage(server.TwoHumansRequiredText);
                            }
                            else if (server.Map.Players.Players.Where(p => p.Value.Playable).All(p => !p.Value.AllowBots))
                            {
                                server.SendMessage("Bots have been disabled on this map.");
                            }

                            var briefing = MissionBriefingOrDefault(server);
                            if (briefing != null)
                            {
                                server.SendMessage(briefing);
                            }
                        };

                        Action queryFailed = () =>
                                             server.SendOrderTo(conn, "Message", "Map was not found on server.");

                        var m = server.ModData.MapCache[s];
                        if (m.Status == MapStatus.Available || m.Status == MapStatus.DownloadAvailable)
                        {
                            selectMap(m);
                        }
                        else if (server.Settings.QueryMapRepository)
                        {
                        }
                        else
                        {
                            queryFailed();
                        }
                        return(true);
                    }
                }
            };

            var cmdName  = cmd.Split(' ').First();
            var cmdValue = cmd.Split(' ').Skip(1).JoinWith(" ");

            Func <string, bool> a;

            if (!dict.TryGetValue(cmdName, out a))
            {
                return(false);
            }

            return(a(cmdValue));
        }
Beispiel #17
0
 void IClientJoined.ClientJoined(S server, EW.Server.Connection conn)
 {
     var client = server.GetClient(conn);
 }
Beispiel #18
0
 void IStartGame.GameStarted(S server)
 {
     PublishGame(server);
 }
Beispiel #19
0
 void IClientJoined.ClientJoined(EW.Server.Server server, EW.Server.Connection conn)
 {
 }
Beispiel #20
0
 void INotifySyncLobbyInfo.LobbyInfoSynced(S server)
 {
     PublishGame(server);
 }