示例#1
0
        void Join(GameServer server)
        {
            if (server == null || !server.CanJoin())
            {
                return;
            }

            var host = server.Address.Split(':')[0];
            var port = Exts.ParseIntegerInvariant(server.Address.Split(':')[1]);

            ConnectionLogic.Connect(host, port, "", OpenLobby, DoNothing);
        }
示例#2
0
		public void Run(ModData modData, string[] args)
		{
			// HACK: The engine code assumes that Game.modData is set.
			Game.modData = modData;

			var map = new Map(args[1]);
			var engineDate = Exts.ParseIntegerInvariant(args[2]);

			UpgradeRules.UpgradeWeaponRules(engineDate, ref map.WeaponDefinitions, null, 0);
			UpgradeRules.UpgradeActorRules(engineDate, ref map.RuleDefinitions, null, 0);
			map.Save(args[1]);
		}
示例#3
0
        static void SetBounds(Map map, IniSection mapSection)
        {
            var offsetX = Exts.ParseIntegerInvariant(mapSection.GetValue("X", "0"));
            var offsetY = Exts.ParseIntegerInvariant(mapSection.GetValue("Y", "0"));
            var width   = Exts.ParseIntegerInvariant(mapSection.GetValue("Width", "0"));
            var height  = Exts.ParseIntegerInvariant(mapSection.GetValue("Height", "0"));

            var tl = new PPos(offsetX, offsetY);
            var br = new PPos(offsetX + width - 1, offsetY + height - 1);

            map.SetBounds(tl, br);
        }
示例#4
0
        void LoadActors(IniFile file, string section)
        {
            foreach (var s in file.GetSection(section, true))
            {
                // Structures: num=owner,type,health,location,turret-facing,trigger
                // Units: num=owner,type,health,location,facing,action,trigger
                // Infantry: num=owner,type,health,location,subcell,action,facing,trigger
                try
                {
                    var parts = s.Value.Split(',');
                    var loc   = Exts.ParseIntegerInvariant(parts[3]);
                    if (parts[0] == "")
                    {
                        parts[0] = "Neutral";
                    }

                    if (!players.Contains(parts[0]))
                    {
                        players.Add(parts[0]);
                    }

                    var actor = new ActorReference(parts[1].ToLowerInvariant())
                    {
                        new LocationInit(new CPos(loc % mapSize, loc / mapSize)),
                        new OwnerInit(parts[0]),
                        new HealthInit(float.Parse(parts[2], NumberFormatInfo.InvariantInfo) / 256),
                        new FacingInit((section == "INFANTRY")
                                                        ? Exts.ParseIntegerInvariant(parts[6])
                                                        : Exts.ParseIntegerInvariant(parts[4])),
                    };

                    if (section == "INFANTRY")
                    {
                        actor.Add(new SubCellInit(Exts.ParseIntegerInvariant(parts[4])));
                    }

                    if (!rules.Actors.ContainsKey(parts[1].ToLowerInvariant()))
                    {
                        errorHandler("Ignoring unknown actor type: `{0}`".F(parts[1].ToLowerInvariant()));
                    }
                    else
                    {
                        map.Actors.Value.Add("Actor" + actorCount++, actor);
                    }
                }
                catch (Exception)
                {
                    errorHandler("Malformed actor definition: `{0}`".F(s));
                }
            }
        }
示例#5
0
        static bool ClearPlayerSpawn(S server, Connection conn, Session.Client client, string s)
        {
            var spawnPoint = Exts.ParseIntegerInvariant(s);

            if (spawnPoint == 0)
            {
                return(true);
            }

            var existingClient = server.LobbyInfo.Clients.FirstOrDefault(cc => cc.SpawnPoint == spawnPoint);

            if (client != existingClient && !client.IsAdmin)
            {
                server.SendOrderTo(conn, "Message", "Only admins can clear spawn points.");
                return(true);
            }

            // Clearing a selected spawn point removes the player
            if (existingClient != null)
            {
                // Prevent a map-defined lock spawn from being affected
                if (existingClient.Slot != null && server.LobbyInfo.Slots[existingClient.Slot].LockSpawn)
                {
                    return(true);
                }

                existingClient.SpawnPoint = 0;
                if (existingClient.State == Session.ClientState.Ready)
                {
                    existingClient.State = Session.ClientState.NotReady;
                }

                server.SyncLobbyClients();
                return(true);
            }

            // Clearing an empty spawn point prevents it from being selected
            // Clearing a disabled spawn restores it for use
            if (!server.LobbyInfo.DisabledSpawnPoints.Contains(spawnPoint))
            {
                server.LobbyInfo.DisabledSpawnPoints.Add(spawnPoint);
            }
            else
            {
                server.LobbyInfo.DisabledSpawnPoints.Remove(spawnPoint);
            }

            server.SyncLobbyInfo();
            return(true);
        }
示例#6
0
        public void StartGame(Arguments args)
        {
            Launch = new LaunchArguments(args);
            Ui.ResetAll();
            Game.Settings.Save();

            // Join a server directly
            var connect = Launch.GetConnectAddress();

            if (!string.IsNullOrEmpty(connect))
            {
                var parts = connect.Split(':');

                if (parts.Length == 2)
                {
                    var host = parts[0];
                    var port = Exts.ParseIntegerInvariant(parts[1]);
                    Game.LoadShellMap();
                    Game.RemoteDirectConnect(host, port);
                    return;
                }
            }

            // Load a replay directly
            if (!string.IsNullOrEmpty(Launch.Replay))
            {
                var replayMeta = ReplayMetadata.Read(Launch.Replay);
                if (ReplayUtils.PromptConfirmReplayCompatibility(replayMeta, Game.LoadShellMap))
                {
                    Game.JoinReplay(Launch.Replay);
                }

                if (replayMeta != null)
                {
                    var mod = replayMeta.GameInfo.Mod;
                    if (mod != null && mod != Game.ModData.Manifest.Mod.Id && ModMetadata.AllMods.ContainsKey(mod))
                    {
                        Game.InitializeMod(mod, args);
                    }
                }

                return;
            }

            Game.LoadShellMap();
            Game.Settings.Save();
        }
示例#7
0
        public void WorldLoaded(World w, WorldRenderer wr)
        {
            var first = smudges.First().Value.First();
            var sheet = first.Sheet;

            if (smudges.Values.Any(sprites => sprites.Any(s => s.Sheet != sheet)))
            {
                throw new InvalidDataException("Resource sprites span multiple sheets. Try loading their sequences earlier.");
            }

            var blendMode = first.BlendMode;

            if (smudges.Values.Any(sprites => sprites.Any(s => s.BlendMode != blendMode)))
            {
                throw new InvalidDataException("Smudges specify different blend modes. "
                                               + "Try using different smudge types for smudges that use different blend modes.");
            }

            render = new TerrainSpriteLayer(w, wr, sheet, blendMode, wr.Palette(Info.Palette), wr.World.Type != WorldType.Editor);

            // Add map smudges
            foreach (var s in w.Map.SmudgeDefinitions)
            {
                var name = s.Key;
                var vals = name.Split(' ');
                var type = vals[0];

                if (!smudges.ContainsKey(type))
                {
                    continue;
                }

                var loc   = vals[1].Split(',');
                var cell  = new CPos(Exts.ParseIntegerInvariant(loc[0]), Exts.ParseIntegerInvariant(loc[1]));
                var depth = Exts.ParseIntegerInvariant(vals[2]);

                var smudge = new Smudge
                {
                    Type   = type,
                    Depth  = depth,
                    Sprite = smudges[type][depth]
                };

                tiles.Add(cell, smudge);
                render.Update(cell, smudge.Sprite);
            }
        }
示例#8
0
        public void Run(ModData modData, string[] args)
        {
            // HACK: The engine code assumes that Game.modData is set.
            Game.ModData = modData;

            // HACK: We know that maps can only be oramap or folders, which are ReadWrite
            var package = modData.ModFiles.OpenPackage(args[1], new Folder(".")) as IReadWritePackage;

            if (package == null)
            {
                throw new FileNotFoundException(args[1]);
            }

            var engineDate = Exts.ParseIntegerInvariant(args[2]);

            UpgradeMap(modData, package, engineDate);
        }
示例#9
0
        public DirectConnectLogic(Widget widget, Action onExit, Action openLobby, ConnectionTarget directConnectEndPoint)
        {
            var panel     = widget;
            var ipField   = panel.Get <TextFieldWidget>("IP");
            var portField = panel.Get <TextFieldWidget>("PORT");

            var text = Game.Settings.Player.LastServer;
            var last = text.LastIndexOf(':');

            if (last < 0)
            {
                ipField.Text   = "localhost";
                portField.Text = "1234";
            }
            else
            {
                ipField.Text   = text.Substring(0, last);
                portField.Text = text.Substring(last + 1);
            }

            panel.Get <ButtonWidget>("JOIN_BUTTON").OnClick = () =>
            {
                var port = Exts.WithDefault(1234, () => Exts.ParseIntegerInvariant(portField.Text));

                Game.Settings.Player.LastServer = "{0}:{1}".F(ipField.Text, port);
                Game.Settings.Save();

                ConnectionLogic.Connect(new ConnectionTarget(ipField.Text, port), "", () => { Ui.CloseWindow(); openLobby(); }, DoNothing);
            };

            panel.Get <ButtonWidget>("BACK_BUTTON").OnClick = () => { Ui.CloseWindow(); onExit(); };

            if (directConnectEndPoint != null)
            {
                // The connection window must be opened at the end of the tick for the widget hierarchy to
                // work out, but we also want to prevent the server browser from flashing visible for one tick.
                widget.Visible = false;
                Game.RunAfterTick(() =>
                {
                    ConnectionLogic.Connect(directConnectEndPoint, "", () => { Ui.CloseWindow(); openLobby(); }, DoNothing);
                    widget.Visible = true;
                });
            }
        }
示例#10
0
        public CursorSequence(FrameCache cache, string name, string cursorSrc, string palette, MiniYaml info)
        {
            var d = info.ToDictionary();

            Start   = Exts.ParseIntegerInvariant(d["Start"].Value);
            Palette = palette;
            Name    = name;

            if ((d.ContainsKey("Length") && d["Length"].Value == "*") || (d.ContainsKey("End") && d["End"].Value == "*"))
            {
                Length = Frames.Length - Start;
            }
            else if (d.ContainsKey("Length"))
            {
                Length = Exts.ParseIntegerInvariant(d["Length"].Value);
            }
            else if (d.ContainsKey("End"))
            {
                Length = Exts.ParseIntegerInvariant(d["End"].Value) - Start;
            }
            else
            {
                Length = 1;
            }

            Frames = cache[cursorSrc]
                     .Skip(Start)
                     .Take(Length)
                     .ToArray();

            if (d.ContainsKey("X"))
            {
                int x;
                Exts.TryParseIntegerInvariant(d["X"].Value, out x);
                Hotspot = Hotspot.WithX(x);
            }

            if (d.ContainsKey("Y"))
            {
                int y;
                Exts.TryParseIntegerInvariant(d["Y"].Value, out y);
                Hotspot = Hotspot.WithY(y);
            }
        }
示例#11
0
        public void OnNumeric(NumericLine line)
        {
            switch (line.Numeric)
            {
            case NumericCommand.RPL_WELCOME:
                new User(line.Message.Substring(line.Message.LastIndexOf(' ') + 1)).CopyTo(this);
                break;

            case NumericCommand.RPL_NAMREPLY:
            {
                var channel   = line.GetChannel();
                var nicknames = line.Message.Replace("~", "").Replace("&", "").Replace("@", "").Replace("%", "").Replace("+", "").Split(' ');

                foreach (var nickname in nicknames.Where(n => !channel.Users.ContainsKey(n)))
                {
                    channel.Users.Add(nickname, new User {
                            Nickname = nickname
                        });
                }
            }
            break;

            case NumericCommand.RPL_TOPIC:
                line.GetChannel().Topic.Message = line.Message;
                break;

            case NumericCommand.RPL_TOPICWHOTIME:
            {
                var topic = line.GetChannel().Topic;
                topic.Author = new User(line[4]);
                topic.Time   = IrcUtils.DateTimeFromUnixTime(Exts.ParseIntegerInvariant(line[5]));
            }
            break;

            case NumericCommand.ERR_NICKNAMEINUSE:
                if (line.Target == "*")                         // no nickname set yet
                {
                    Client.SetNickname(Client.Nickname + new Random().Next(10000, 99999));
                }
                break;
            }
        }
示例#12
0
        public void WorldLoaded(World w, WorldRenderer wr)
        {
            world   = w;
            tiles   = new Dictionary <CPos, Smudge>();
            dirty   = new Dictionary <CPos, Smudge>();
            smudges = new Dictionary <string, Sprite[]>();

            var types = world.Map.SequenceProvider.Sequences(Info.Sequence);

            foreach (var t in types)
            {
                var seq     = world.Map.SequenceProvider.GetSequence(Info.Sequence, t);
                var sprites = Exts.MakeArray(seq.Length, x => seq.GetSprite(x));
                smudges.Add(t, sprites);
            }

            // Add map smudges
            foreach (var s in w.Map.SmudgeDefinitions)
            {
                var name = s.Key;
                var vals = name.Split(' ');
                var type = vals[0];

                if (!smudges.ContainsKey(type))
                {
                    continue;
                }

                var loc   = vals[1].Split(',');
                var cell  = new CPos(Exts.ParseIntegerInvariant(loc[0]), Exts.ParseIntegerInvariant(loc[1]));
                var depth = Exts.ParseIntegerInvariant(vals[2]);

                var smudge = new Smudge
                {
                    Type   = type,
                    Depth  = depth,
                    Sprite = smudges[type][depth]
                };

                tiles.Add(cell, smudge);
            }
        }
示例#13
0
        internal static void TryUpdateHSLColor(ref string value)
        {
            if (value.Length == 0)
            {
                return;
            }

            try
            {
                var parts = value.Split(',');
                if (parts.Length == 3 || parts.Length == 4)
                {
                    value = FieldSaver.FormatValue(new HSLColor(
                                                       (byte)Exts.ParseIntegerInvariant(parts[0]).Clamp(0, 255),
                                                       (byte)Exts.ParseIntegerInvariant(parts[1]).Clamp(0, 255),
                                                       (byte)Exts.ParseIntegerInvariant(parts[2]).Clamp(0, 255)));
                }
            }
            catch { }
        }
示例#14
0
        void ReadCncTrees(IniFile file)
        {
            var terrain = file.GetSection("TERRAIN", true);

            if (terrain == null)
            {
                return;
            }

            foreach (var kv in terrain)
            {
                var loc = Exts.ParseIntegerInvariant(kv.Key);
                map.Actors.Value.Add("Actor" + actorCount++,
                                     new ActorReference(kv.Value.Split(',')[0].ToLowerInvariant())
                {
                    new LocationInit(new CPos(loc % mapSize, loc / mapSize)),
                    new OwnerInit("Neutral")
                });
            }
        }
示例#15
0
        void ReadRATrees(IniFile file)
        {
            var terrain = file.GetSection("TERRAIN", true);

            if (terrain == null)
            {
                return;
            }

            foreach (var kv in terrain)
            {
                var loc = Exts.ParseIntegerInvariant(kv.Key);
                var ar  = new ActorReference(kv.Value.ToLowerInvariant())
                {
                    new LocationInit(new CPos(loc % mapSize, loc / mapSize)),
                    new OwnerInit("Neutral")
                };

                map.ActorDefinitions.Add(new MiniYamlNode("Actor" + actorCount++, ar.Save()));
            }
        }
示例#16
0
        void IUtilityCommand.Run(Utility utility, string[] args)
        {
            // HACK: The engine code assumes that Game.modData is set.
            var modData = Game.ModData = utility.ModData;

            var engineDate = Exts.ParseIntegerInvariant(args[1]);

            if (engineDate < UpgradeRules.MinimumSupportedVersion)
            {
                Console.WriteLine("Unsupported engine version. Use the release-{0} utility to update to that version, and then try again",
                                  UpgradeRules.MinimumSupportedVersion);
                return;
            }

            ProcessYaml("Rules", modData.Manifest.Rules, modData, engineDate, UpgradeRules.UpgradeActorRules);
            ProcessYaml("Weapons", modData.Manifest.Weapons, modData, engineDate, UpgradeRules.UpgradeWeaponRules);
            ProcessYaml("Sequences", modData.Manifest.Sequences, modData, engineDate, UpgradeRules.UpgradeSequences);
            ProcessYaml("Tilesets", modData.Manifest.TileSets, modData, engineDate, UpgradeRules.UpgradeTileset);
            ProcessYaml("Cursors", modData.Manifest.Cursors, modData, engineDate, UpgradeRules.UpgradeCursors);
            ProcessYaml("Chrome Metrics", modData.Manifest.ChromeMetrics, modData, engineDate, UpgradeRules.UpgradeChromeMetrics);
            ProcessYaml("Chrome Layout", modData.Manifest.ChromeLayout, modData, engineDate, UpgradeRules.UpgradeChromeLayout);

            // The map cache won't be valid if there was a map format upgrade, so walk the map packages manually
            // Only upgrade system maps - user maps must be updated manually using --upgrade-map
            Console.WriteLine("Processing System Maps:");
            foreach (var map in modData.MapCache.EnumerateMapsWithoutCaching())
            {
                try
                {
                    Console.WriteLine(map.Package.Name);
                    UpgradeMapCommand.UpgradeMap(modData, (IReadWritePackage)map.Package, engineDate);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Failed to upgrade map {0}", map);
                    Console.WriteLine("Error was: {0}", e.ToString());
                }
            }
        }
示例#17
0
        static bool Handicap(S server, Connection conn, Session.Client client, string s)
        {
            lock (server.LobbyInfo)
            {
                var parts        = s.Split(' ');
                var targetClient = server.LobbyInfo.ClientWithIndex(Exts.ParseIntegerInvariant(parts[0]));

                // Only the host can change other client's info
                if (targetClient.Index != client.Index && !client.IsAdmin)
                {
                    return(true);
                }

                // Map has disabled handicap changes
                if (server.LobbyInfo.Slots[targetClient.Slot].LockHandicap)
                {
                    return(true);
                }

                if (!Exts.TryParseIntegerInvariant(parts[1], out var handicap))
                {
                    Log.Write("server", "Invalid handicap: {0}", s);
                    return(false);
                }

                // Handicaps may be set between 0 - 95% in steps of 5%
                var options = Enumerable.Range(0, 20).Select(i => 5 * i);
                if (!options.Contains(handicap))
                {
                    Log.Write("server", "Invalid handicap: {0}", s);
                    return(false);
                }

                targetClient.Handicap = handicap;
                server.SyncLobbyClients();

                return(true);
            }
        }
示例#18
0
        void ReadTrees(IniFile file)
        {
            var terrain = file.GetSection("TERRAIN", true);

            if (terrain == null)
            {
                return;
            }

            foreach (var kv in terrain)
            {
                var loc       = Exts.ParseIntegerInvariant(kv.Key);
                var treeActor = ParseTreeActor(kv.Value);

                var ar = new ActorReference(treeActor)
                {
                    new LocationInit(ParseActorLocation(treeActor, loc)),
                    new OwnerInit("Neutral")
                };

                var actorCount = Map.ActorDefinitions.Count;
                Map.ActorDefinitions.Add(new MiniYamlNode("Actor" + actorCount++, ar.Save()));
            }
        }
示例#19
0
        public DirectConnectLogic(Widget widget, Action onExit, Action openLobby)
        {
            var panel     = widget;
            var ipField   = panel.Get <TextFieldWidget>("IP");
            var portField = panel.Get <TextFieldWidget>("PORT");

            var last = Game.Settings.Player.LastServer.Split(':');

            ipField.Text   = last.Length > 1 ? last[0] : "localhost";
            portField.Text = last.Length == 2 ? last[1] : "1234";

            panel.Get <ButtonWidget>("JOIN_BUTTON").OnClick = () =>
            {
                var port = Exts.WithDefault(1234, () => Exts.ParseIntegerInvariant(portField.Text));

                Game.Settings.Player.LastServer = "{0}:{1}".F(ipField.Text, port);
                Game.Settings.Save();

                Ui.CloseWindow();
                ConnectionLogic.Connect(ipField.Text, port, "", openLobby, onExit);
            };

            panel.Get <ButtonWidget>("BACK_BUTTON").OnClick = () => { Ui.CloseWindow(); onExit(); };
        }
示例#20
0
        internal static void UpgradeMapFormat(ModData modData, IReadWritePackage package)
        {
            if (package == null)
            {
                return;
            }

            var yamlStream = package.GetStream("map.yaml");

            if (yamlStream == null)
            {
                return;
            }

            var yaml      = new MiniYaml(null, MiniYaml.FromStream(yamlStream, package.Name));
            var nd        = yaml.ToDictionary();
            var mapFormat = FieldLoader.GetValue <int>("MapFormat", nd["MapFormat"].Value);

            if (mapFormat < 6)
            {
                throw new InvalidDataException("Map format {0} is not supported.\n File: {1}".F(mapFormat, package.Name));
            }

            // Format 6 -> 7 combined the Selectable and UseAsShellmap flags into the Class enum
            if (mapFormat < 7)
            {
                MiniYaml useAsShellmap;
                if (nd.TryGetValue("UseAsShellmap", out useAsShellmap) && bool.Parse(useAsShellmap.Value))
                {
                    yaml.Nodes.Add(new MiniYamlNode("Visibility", new MiniYaml("Shellmap")));
                }
                else if (nd["Type"].Value == "Mission" || nd["Type"].Value == "Campaign")
                {
                    yaml.Nodes.Add(new MiniYamlNode("Visibility", new MiniYaml("MissionSelector")));
                }
            }

            // Format 7 -> 8 replaced normalized HSL triples with rgb(a) hex colors
            if (mapFormat < 8)
            {
                var players = yaml.Nodes.FirstOrDefault(n => n.Key == "Players");
                if (players != null)
                {
                    bool noteHexColors = false;
                    bool noteColorRamp = false;
                    foreach (var player in players.Value.Nodes)
                    {
                        var colorRampNode = player.Value.Nodes.FirstOrDefault(n => n.Key == "ColorRamp");
                        if (colorRampNode != null)
                        {
                            Color dummy;
                            var   parts = colorRampNode.Value.Value.Split(',');
                            if (parts.Length == 3 || parts.Length == 4)
                            {
                                // Try to convert old normalized HSL value to a rgb hex color
                                try
                                {
                                    HSLColor color = new HSLColor(
                                        (byte)Exts.ParseIntegerInvariant(parts[0].Trim()).Clamp(0, 255),
                                        (byte)Exts.ParseIntegerInvariant(parts[1].Trim()).Clamp(0, 255),
                                        (byte)Exts.ParseIntegerInvariant(parts[2].Trim()).Clamp(0, 255));
                                    colorRampNode.Value.Value = FieldSaver.FormatValue(color);
                                    noteHexColors             = true;
                                }
                                catch (Exception)
                                {
                                    throw new InvalidDataException("Invalid ColorRamp value.\n File: " + package.Name);
                                }
                            }
                            else if (parts.Length != 1 || !HSLColor.TryParseRGB(parts[0], out dummy))
                            {
                                throw new InvalidDataException("Invalid ColorRamp value.\n File: " + package.Name);
                            }

                            colorRampNode.Key = "Color";
                            noteColorRamp     = true;
                        }
                    }

                    if (noteHexColors)
                    {
                        Console.WriteLine("ColorRamp is now called Color and uses rgb(a) hex value - rrggbb[aa].");
                    }
                    else if (noteColorRamp)
                    {
                        Console.WriteLine("ColorRamp is now called Color.");
                    }
                }
            }

            // Format 8 -> 9 moved map options and videos from the map file itself to traits
            if (mapFormat < 9)
            {
                var rules     = yaml.Nodes.FirstOrDefault(n => n.Key == "Rules");
                var worldNode = rules.Value.Nodes.FirstOrDefault(n => n.Key == "World");
                if (worldNode == null)
                {
                    worldNode = new MiniYamlNode("World", new MiniYaml("", new List <MiniYamlNode>()));
                }

                var playerNode = rules.Value.Nodes.FirstOrDefault(n => n.Key == "Player");
                if (playerNode == null)
                {
                    playerNode = new MiniYamlNode("Player", new MiniYaml("", new List <MiniYamlNode>()));
                }

                var visibilityNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Visibility");
                if (visibilityNode != null)
                {
                    var visibility = FieldLoader.GetValue <MapVisibility>("Visibility", visibilityNode.Value.Value);
                    if (visibility.HasFlag(MapVisibility.MissionSelector))
                    {
                        var missionData = new MiniYamlNode("MissionData", new MiniYaml("", new List <MiniYamlNode>()));
                        worldNode.Value.Nodes.Add(missionData);

                        var description = yaml.Nodes.FirstOrDefault(n => n.Key == "Description");
                        if (description != null)
                        {
                            missionData.Value.Nodes.Add(new MiniYamlNode("Briefing", description.Value.Value));
                        }

                        var videos = yaml.Nodes.FirstOrDefault(n => n.Key == "Videos");
                        if (videos != null && videos.Value.Nodes.Any())
                        {
                            var backgroundVideo = videos.Value.Nodes.FirstOrDefault(n => n.Key == "BackgroundInfo");
                            if (backgroundVideo != null)
                            {
                                missionData.Value.Nodes.Add(new MiniYamlNode("BackgroundVideo", backgroundVideo.Value.Value));
                            }

                            var briefingVideo = videos.Value.Nodes.FirstOrDefault(n => n.Key == "Briefing");
                            if (briefingVideo != null)
                            {
                                missionData.Value.Nodes.Add(new MiniYamlNode("BriefingVideo", briefingVideo.Value.Value));
                            }

                            var startVideo = videos.Value.Nodes.FirstOrDefault(n => n.Key == "GameStart");
                            if (startVideo != null)
                            {
                                missionData.Value.Nodes.Add(new MiniYamlNode("StartVideo", startVideo.Value.Value));
                            }

                            var winVideo = videos.Value.Nodes.FirstOrDefault(n => n.Key == "GameWon");
                            if (winVideo != null)
                            {
                                missionData.Value.Nodes.Add(new MiniYamlNode("WinVideo", winVideo.Value.Value));
                            }

                            var lossVideo = videos.Value.Nodes.FirstOrDefault(n => n.Key == "GameLost");
                            if (lossVideo != null)
                            {
                                missionData.Value.Nodes.Add(new MiniYamlNode("LossVideo", lossVideo.Value.Value));
                            }
                        }
                    }
                }

                var mapOptions = yaml.Nodes.FirstOrDefault(n => n.Key == "Options");
                if (mapOptions != null)
                {
                    var cheats = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "Cheats");
                    if (cheats != null)
                    {
                        worldNode.Value.Nodes.Add(new MiniYamlNode("DeveloperMode", new MiniYaml("", new List <MiniYamlNode>()
                        {
                            new MiniYamlNode("Locked", "True"),
                            new MiniYamlNode("Enabled", cheats.Value.Value)
                        })));
                    }

                    var crates = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "Crates");
                    if (crates != null && !worldNode.Value.Nodes.Any(n => n.Key == "-CrateSpawner"))
                    {
                        if (!FieldLoader.GetValue <bool>("crates", crates.Value.Value))
                        {
                            worldNode.Value.Nodes.Add(new MiniYamlNode("-CrateSpawner", new MiniYaml("")));
                        }
                    }

                    var creeps = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "Creeps");
                    if (creeps != null)
                    {
                        worldNode.Value.Nodes.Add(new MiniYamlNode("MapCreeps", new MiniYaml("", new List <MiniYamlNode>()
                        {
                            new MiniYamlNode("Locked", "True"),
                            new MiniYamlNode("Enabled", creeps.Value.Value)
                        })));
                    }

                    var fog    = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "Fog");
                    var shroud = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "Shroud");
                    if (fog != null || shroud != null)
                    {
                        var shroudNode = new MiniYamlNode("Shroud", new MiniYaml("", new List <MiniYamlNode>()));
                        playerNode.Value.Nodes.Add(shroudNode);

                        if (fog != null)
                        {
                            shroudNode.Value.Nodes.Add(new MiniYamlNode("FogLocked", "True"));
                            shroudNode.Value.Nodes.Add(new MiniYamlNode("FogEnabled", fog.Value.Value));
                        }

                        if (shroud != null)
                        {
                            var enabled = FieldLoader.GetValue <bool>("shroud", shroud.Value.Value);
                            shroudNode.Value.Nodes.Add(new MiniYamlNode("ExploredMapLocked", "True"));
                            shroudNode.Value.Nodes.Add(new MiniYamlNode("ExploredMapEnabled", FieldSaver.FormatValue(!enabled)));
                        }
                    }

                    var allyBuildRadius = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "AllyBuildRadius");
                    if (allyBuildRadius != null)
                    {
                        worldNode.Value.Nodes.Add(new MiniYamlNode("MapBuildRadius", new MiniYaml("", new List <MiniYamlNode>()
                        {
                            new MiniYamlNode("AllyBuildRadiusLocked", "True"),
                            new MiniYamlNode("AllyBuildRadiusEnabled", allyBuildRadius.Value.Value)
                        })));
                    }

                    var startingCash = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "StartingCash");
                    if (startingCash != null)
                    {
                        playerNode.Value.Nodes.Add(new MiniYamlNode("PlayerResources", new MiniYaml("", new List <MiniYamlNode>()
                        {
                            new MiniYamlNode("DefaultCashLocked", "True"),
                            new MiniYamlNode("DefaultCash", startingCash.Value.Value)
                        })));
                    }

                    var startingUnits = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "ConfigurableStartingUnits");
                    if (startingUnits != null && !worldNode.Value.Nodes.Any(n => n.Key == "-SpawnMPUnits"))
                    {
                        worldNode.Value.Nodes.Add(new MiniYamlNode("SpawnMPUnits", new MiniYaml("", new List <MiniYamlNode>()
                        {
                            new MiniYamlNode("Locked", "True"),
                        })));
                    }

                    var techLevel    = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "TechLevel");
                    var difficulties = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "Difficulties");
                    var shortGame    = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "ShortGame");
                    if (techLevel != null || difficulties != null || shortGame != null)
                    {
                        var optionsNode = new MiniYamlNode("MapOptions", new MiniYaml("", new List <MiniYamlNode>()));
                        worldNode.Value.Nodes.Add(optionsNode);

                        if (techLevel != null)
                        {
                            optionsNode.Value.Nodes.Add(new MiniYamlNode("TechLevelLocked", "True"));
                            optionsNode.Value.Nodes.Add(new MiniYamlNode("TechLevel", techLevel.Value.Value));
                        }

                        if (difficulties != null)
                        {
                            optionsNode.Value.Nodes.Add(new MiniYamlNode("Difficulties", difficulties.Value.Value));
                        }

                        if (shortGame != null)
                        {
                            optionsNode.Value.Nodes.Add(new MiniYamlNode("ShortGameLocked", "True"));
                            optionsNode.Value.Nodes.Add(new MiniYamlNode("ShortGameEnabled", shortGame.Value.Value));
                        }
                    }
                }

                if (worldNode.Value.Nodes.Any() && !rules.Value.Nodes.Contains(worldNode))
                {
                    rules.Value.Nodes.Add(worldNode);
                }

                if (playerNode.Value.Nodes.Any() && !rules.Value.Nodes.Contains(playerNode))
                {
                    rules.Value.Nodes.Add(playerNode);
                }
            }

            // Format 9 -> 10 moved smudges to SmudgeLayer, and uses map.png for all maps
            if (mapFormat < 10)
            {
                ExtractSmudges(yaml);
                if (package.Contains("map.png"))
                {
                    yaml.Nodes.Add(new MiniYamlNode("LockPreview", new MiniYaml("True")));
                }
            }

            // Format 10 -> 11 replaced the single map type field with a list of categories
            if (mapFormat < 11)
            {
                var type = yaml.Nodes.First(n => n.Key == "Type");
                yaml.Nodes.Add(new MiniYamlNode("Categories", type.Value));
                yaml.Nodes.Remove(type);
            }

            if (mapFormat < Map.SupportedMapFormat)
            {
                yaml.Nodes.First(n => n.Key == "MapFormat").Value = new MiniYaml(Map.SupportedMapFormat.ToString());
                Console.WriteLine("Converted {0} to MapFormat {1}.", package.Name, Map.SupportedMapFormat);
            }

            package.Update("map.yaml", Encoding.UTF8.GetBytes(yaml.Nodes.WriteToString()));
        }
示例#21
0
        public bool InterpretCommand(S 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;

                      Log.Write("server", "Player @{0} is {1}",
                                conn.Socket.RemoteEndPoint, client.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.Clients.Where(c => c.Bot == null && c.Slot != null).Count() == 1)
                      {
                          server.SendOrderTo(conn, "Message", server.TwoHumansRequiredText);
                          return(true);
                      }

                      server.StartGame();
                      return(true);
                  } },
                { "slot",
                  s =>
                  {
                      if (!server.LobbyInfo.Slots.ContainsKey(s))
                      {
                          Log.Write("server", "Invalid slot: {0}", s);
                          return(false);
                      }

                      var slot = server.LobbyInfo.Slots[s];

                      if (slot.Closed || server.LobbyInfo.ClientInSlot(s) != null)
                      {
                          return(false);
                      }

                      // If the previous slot had a locked spawn then we must not carry that to the new slot
                      var oldSlot = client.Slot != null ? server.LobbyInfo.Slots[client.Slot] : null;
                      if (oldSlot != null && oldSlot.LockSpawn)
                      {
                          client.SpawnPoint = 0;
                      }

                      client.Slot = s;
                      S.SyncClientToPlayerReference(client, server.Map.Players.Players[s]);

                      if (!slot.LockColor)
                      {
                          client.PreferredColor = client.Color = SanitizePlayerColor(server, client.Color, client.Index, conn);
                      }

                      server.SyncLobbyClients();
                      CheckAutoStart(server);

                      return(true);
                  } },
                { "allow_spectators",
                  s =>
                  {
                      if (bool.TryParse(s, out server.LobbyInfo.GlobalSettings.AllowSpectators))
                      {
                          server.SyncLobbyGlobalSettings();
                          return(true);
                      }
                      else
                      {
                          server.SendOrderTo(conn, "Message", "Malformed allow_spectate command");
                          return(true);
                      }
                  } },
                { "spectate",
                  s =>
                  {
                      if (server.LobbyInfo.GlobalSettings.AllowSpectators || client.IsAdmin)
                      {
                          client.Slot       = null;
                          client.SpawnPoint = 0;
                          client.Color      = HSLColor.FromRGB(255, 255, 255);
                          server.SyncLobbyClients();
                          CheckAutoStart(server);
                          return(true);
                      }
                      else
                      {
                          return(false);
                      }
                  } },
                { "slot_close",
                  s =>
                  {
                      if (!ValidateSlotCommand(server, conn, client, s, true))
                      {
                          return(false);
                      }

                      // kick any player that's in the slot
                      var occupant = server.LobbyInfo.ClientInSlot(s);
                      if (occupant != null)
                      {
                          if (occupant.Bot != null)
                          {
                              server.LobbyInfo.Clients.Remove(occupant);
                              server.SyncLobbyClients();
                              var ping = server.LobbyInfo.PingFromClient(occupant);
                              if (ping != null)
                              {
                                  server.LobbyInfo.ClientPings.Remove(ping);
                                  server.SyncClientPing();
                              }
                          }
                          else
                          {
                              var occupantConn = server.Conns.FirstOrDefault(c => c.PlayerIndex == occupant.Index);
                              if (occupantConn != null)
                              {
                                  server.SendOrderTo(occupantConn, "ServerError", "Your slot was closed by the host.");
                                  server.DropClient(occupantConn);
                              }
                          }
                      }

                      server.LobbyInfo.Slots[s].Closed = true;
                      server.SyncLobbySlots();
                      return(true);
                  } },
                { "slot_open",
                  s =>
                  {
                      if (!ValidateSlotCommand(server, conn, client, s, true))
                      {
                          return(false);
                      }

                      var slot = server.LobbyInfo.Slots[s];
                      slot.Closed = false;
                      server.SyncLobbySlots();

                      // Slot may have a bot in it
                      var occupant = server.LobbyInfo.ClientInSlot(s);
                      if (occupant != null && occupant.Bot != null)
                      {
                          server.LobbyInfo.Clients.Remove(occupant);
                          var ping = server.LobbyInfo.PingFromClient(occupant);
                          if (ping != null)
                          {
                              server.LobbyInfo.ClientPings.Remove(ping);
                              server.SyncClientPing();
                          }
                      }

                      server.SyncLobbyClients();
                      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))
                      {
                          Log.Write("server", "Invalid bot controller client index: {0}", parts[1]);
                          return(false);
                      }

                      var botType = parts.Skip(2).JoinWith(" ");

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

                      slot.Closed = false;
                      if (bot == null)
                      {
                          // Create a new bot
                          bot = new Session.Client()
                          {
                              Index      = server.ChooseFreePlayerIndex(),
                              Name       = botType,
                              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 = botType;
                          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 =>
                      {
                          // Make sure the map hasn't changed in the meantime
                          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;
                          }

                          // Reassign players into new slots based on their old slots:
                          //  - Observers remain as observers
                          //  - Players who now lack a slot are made observers
                          //  - Bots who now lack a slot are dropped
                          //  - Bots who are not defined in the map rules are dropped
                          var botNames = server.Map.Rules.Actors["player"].TraitInfos <IBotInfo>().Select(t => t.Name);
                          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)
                              {
                                  // Remove Bot from slot if slot forbids bots
                                  if (c.Bot != null && (!server.Map.Players.Players[c.Slot].AllowBots || !botNames.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);
                              }
                          }

                          // Validate if color is allowed and get an alternative if it isn't
                          foreach (var c in server.LobbyInfo.Clients)
                          {
                              if (c.Slot == null || (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.Map.DefinesUnsafeCustomRules)
                          {
                              server.SendMessage("This map contains custom rules. Game experience may change.");
                          }

                          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)
                      {
                          server.SendOrderTo(conn, "Message", "Searching for map on the Resource Center...");
                          server.ModData.MapCache.QueryRemoteMapDetails(new[] { s }, selectMap, queryFailed);
                      }
                      else
                      {
                          queryFailed();
                      }

                      return(true);
                  } },
                { "option",
                  s =>
                  {
                      if (!client.IsAdmin)
                      {
                          server.SendOrderTo(conn, "Message", "Only the host can change the configuration.");
                          return(true);
                      }

                      var allOptions = server.Map.Rules.Actors["player"].TraitInfos <ILobbyOptions>()
                                       .Concat(server.Map.Rules.Actors["world"].TraitInfos <ILobbyOptions>())
                                       .SelectMany(t => t.LobbyOptions(server.Map.Rules));

                      // Overwrite keys with duplicate ids
                      var options = new Dictionary <string, LobbyOption>();
                      foreach (var o in allOptions)
                      {
                          options[o.Id] = o;
                      }

                      var         split = s.Split(' ');
                      LobbyOption option;
                      if (split.Length < 2 || !options.TryGetValue(split[0], out option) ||
                          !option.Values.ContainsKey(split[1]))
                      {
                          server.SendOrderTo(conn, "Message", "Invalid configuration command.");
                          return(true);
                      }

                      if (option.Locked)
                      {
                          server.SendOrderTo(conn, "Message", "{0} cannot be changed.".F(option.Name));
                          return(true);
                      }

                      var oo = server.LobbyInfo.GlobalSettings.LobbyOptions[option.Id];
                      if (oo.Value == split[1])
                      {
                          return(true);
                      }

                      oo.Value = oo.PreferredValue = split[1];

                      if (option.Id == "gamespeed")
                      {
                          var speed = server.ModData.Manifest.Get <GameSpeeds>().Speeds[oo.Value];
                          server.LobbyInfo.GlobalSettings.Timestep     = speed.Timestep;
                          server.LobbyInfo.GlobalSettings.OrderLatency = speed.OrderLatency;
                      }

                      server.SyncLobbyGlobalSettings();
                      server.SendMessage(option.ValueChangedMessage(client.Name, split[1]));

                      return(true);
                  } },
                { "assignteams",
                  s =>
                  {
                      if (!client.IsAdmin)
                      {
                          server.SendOrderTo(conn, "Message", "Only the host can set that option.");
                          return(true);
                      }

                      int teamCount;
                      if (!Exts.TryParseIntegerInvariant(s, out teamCount))
                      {
                          server.SendOrderTo(conn, "Message", "Number of teams could not be parsed: {0}".F(s));
                          return(true);
                      }

                      var maxTeams = (server.LobbyInfo.Clients.Count(c => c.Slot != null) + 1) / 2;
                      teamCount = teamCount.Clamp(0, maxTeams);
                      var clients = server.LobbyInfo.Slots
                                    .Select(slot => server.LobbyInfo.ClientInSlot(slot.Key))
                                    .Where(c => c != null && !server.LobbyInfo.Slots[c.Slot].LockTeam);

                      var assigned    = 0;
                      var clientCount = clients.Count();
                      foreach (var player in clients)
                      {
                          // Free for all
                          if (teamCount == 0)
                          {
                              player.Team = 0;
                          }

                          // Humans vs Bots
                          else if (teamCount == 1)
                          {
                              player.Team = player.Bot == null ? 1 : 2;
                          }
                          else
                          {
                              player.Team = assigned++ *teamCount / clientCount + 1;
                          }
                      }

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

                      var split = s.Split(' ');
                      if (split.Length < 2)
                      {
                          server.SendOrderTo(conn, "Message", "Malformed kick command");
                          return(true);
                      }

                      int kickClientID;
                      Exts.TryParseIntegerInvariant(split[0], out kickClientID);

                      var kickConn = server.Conns.SingleOrDefault(c => server.GetClient(c) != null && server.GetClient(c).Index == kickClientID);
                      if (kickConn == null)
                      {
                          server.SendOrderTo(conn, "Message", "No-one in that slot.");
                          return(true);
                      }

                      var kickClient = server.GetClient(kickConn);

                      Log.Write("server", "Kicking client {0}.", kickClientID);
                      server.SendMessage("{0} kicked {1} from the server.".F(client.Name, kickClient.Name));
                      server.SendOrderTo(kickConn, "ServerError", "You have been kicked from the server.");
                      server.DropClient(kickConn);

                      bool tempBan;
                      bool.TryParse(split[1], out tempBan);

                      if (tempBan)
                      {
                          Log.Write("server", "Temporarily banning client {0} ({1}).", kickClientID, kickClient.IpAddress);
                          server.SendMessage("{0} temporarily banned {1} from the server.".F(client.Name, kickClient.Name));
                          server.TempBans.Add(kickClient.IpAddress);
                      }

                      server.SyncLobbyClients();
                      server.SyncLobbySlots();

                      return(true);
                  } },
                { "name",
                  s =>
                  {
                      var sanitizedName = Settings.SanitizedPlayerName(s);
                      if (sanitizedName == client.Name)
                      {
                          return(true);
                      }

                      Log.Write("server", "Player@{0} is now known as {1}.", conn.Socket.RemoteEndPoint, sanitizedName);
                      server.SendMessage("{0} is now known as {1}.".F(client.Name, sanitizedName));
                      client.Name = sanitizedName;
                      server.SyncLobbyClients();
                      return(true);
                  } },
                { "faction",
                  s =>
                  {
                      var parts        = s.Split(' ');
                      var targetClient = server.LobbyInfo.ClientWithIndex(Exts.ParseIntegerInvariant(parts[0]));

                      // Only the host can change other client's info
                      if (targetClient.Index != client.Index && !client.IsAdmin)
                      {
                          return(true);
                      }

                      // Map has disabled faction changes
                      if (server.LobbyInfo.Slots[targetClient.Slot].LockFaction)
                      {
                          return(true);
                      }

                      var factions = server.Map.Rules.Actors["world"].TraitInfos <FactionInfo>()
                                     .Where(f => f.Selectable).Select(f => f.InternalName);

                      if (!factions.Contains(parts[1]))
                      {
                          server.SendOrderTo(conn, "Message", "Invalid faction selected: {0}".F(parts[1]));
                          server.SendOrderTo(conn, "Message", "Supported values: {0}".F(factions.JoinWith(", ")));
                          return(true);
                      }

                      targetClient.Faction = parts[1];
                      server.SyncLobbyClients();
                      return(true);
                  } },
                { "team",
                  s =>
                  {
                      var parts        = s.Split(' ');
                      var targetClient = server.LobbyInfo.ClientWithIndex(Exts.ParseIntegerInvariant(parts[0]));

                      // Only the host can change other client's info
                      if (targetClient.Index != client.Index && !client.IsAdmin)
                      {
                          return(true);
                      }

                      // Map has disabled team changes
                      if (server.LobbyInfo.Slots[targetClient.Slot].LockTeam)
                      {
                          return(true);
                      }

                      int team;
                      if (!Exts.TryParseIntegerInvariant(parts[1], out team))
                      {
                          Log.Write("server", "Invalid team: {0}", s);
                          return(false);
                      }

                      targetClient.Team = team;
                      server.SyncLobbyClients();
                      return(true);
                  } },
                { "spawn",
                  s =>
                  {
                      var parts        = s.Split(' ');
                      var targetClient = server.LobbyInfo.ClientWithIndex(Exts.ParseIntegerInvariant(parts[0]));

                      // Only the host can change other client's info
                      if (targetClient.Index != client.Index && !client.IsAdmin)
                      {
                          return(true);
                      }

                      // Spectators don't need a spawnpoint
                      if (targetClient.Slot == null)
                      {
                          return(true);
                      }

                      // Map has disabled spawn changes
                      if (server.LobbyInfo.Slots[targetClient.Slot].LockSpawn)
                      {
                          return(true);
                      }

                      int spawnPoint;
                      if (!Exts.TryParseIntegerInvariant(parts[1], out spawnPoint) ||
                          spawnPoint <0 || spawnPoint> server.Map.SpawnPoints.Length)
                      {
                          Log.Write("server", "Invalid spawn point: {0}", parts[1]);
                          return(true);
                      }

                      if (server.LobbyInfo.Clients.Where(cc => cc != client).Any(cc => (cc.SpawnPoint == spawnPoint) && (cc.SpawnPoint != 0)))
                      {
                          server.SendOrderTo(conn, "Message", "You cannot occupy the same spawn point as another player.");
                          return(true);
                      }

                      // Check if any other slot has locked the requested spawn
                      if (spawnPoint > 0)
                      {
                          var spawnLockedByAnotherSlot = server.LobbyInfo.Slots.Where(ss => ss.Value.LockSpawn).Any(ss =>
                            {
                                var pr = PlayerReferenceForSlot(server, ss.Value);
                                return(pr != null && pr.Spawn == spawnPoint);
                            });

                          if (spawnLockedByAnotherSlot)
                          {
                              server.SendOrderTo(conn, "Message", "The spawn point is locked to another player slot.");
                              return(true);
                          }
                      }

                      targetClient.SpawnPoint = spawnPoint;
                      server.SyncLobbyClients();
                      return(true);
                  } },
                { "color",
                  s =>
                  {
                      var parts        = s.Split(' ');
                      var targetClient = server.LobbyInfo.ClientWithIndex(Exts.ParseIntegerInvariant(parts[0]));

                      // Only the host can change other client's info
                      if (targetClient.Index != client.Index && !client.IsAdmin)
                      {
                          return(true);
                      }

                      // Spectator or map has disabled color changes
                      if (targetClient.Slot == null || server.LobbyInfo.Slots[targetClient.Slot].LockColor)
                      {
                          return(true);
                      }

                      // Validate if color is allowed and get an alternative it isn't
                      var newColor = FieldLoader.GetValue <HSLColor>("(value)", parts[1]);
                      targetClient.Color = SanitizePlayerColor(server, newColor, targetClient.Index, conn);

                      // Only update player's preferred color if new color is valid
                      if (newColor == targetClient.Color)
                      {
                          targetClient.PreferredColor = targetClient.Color;
                      }

                      server.SyncLobbyClients();
                      return(true);
                  } },
                { "sync_lobby",
                  s =>
                  {
                      if (!client.IsAdmin)
                      {
                          server.SendOrderTo(conn, "Message", "Only the host can set lobby info");
                          return(true);
                      }

                      var lobbyInfo = Session.Deserialize(s);
                      if (lobbyInfo == null)
                      {
                          server.SendOrderTo(conn, "Message", "Invalid Lobby Info Sent");
                          return(true);
                      }

                      server.LobbyInfo = lobbyInfo;

                      server.SyncLobbyInfo();
                      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));
        }
示例#22
0
        enum IniMapFormat { RedAlert = 3 }         // otherwise, cnc (2 variants exist, we don't care to differentiate)

        public void ConvertIniMap(string iniFile)
        {
            using (var stream = GlobalFileSystem.Open(iniFile))
            {
                var file            = new IniFile(stream);
                var basic           = file.GetSection("Basic");
                var mapSection      = file.GetSection("Map");
                var legacyMapFormat = (IniMapFormat)Exts.ParseIntegerInvariant(basic.GetValue("NewINIFormat", "0"));
                var offsetX         = Exts.ParseIntegerInvariant(mapSection.GetValue("X", "0"));
                var offsetY         = Exts.ParseIntegerInvariant(mapSection.GetValue("Y", "0"));
                var width           = Exts.ParseIntegerInvariant(mapSection.GetValue("Width", "0"));
                var height          = Exts.ParseIntegerInvariant(mapSection.GetValue("Height", "0"));
                mapSize = (legacyMapFormat == IniMapFormat.RedAlert) ? 128 : 64;

                var tileset = Truncate(mapSection.GetValue("Theater", "TEMPERAT"), 8);
                map = new Map(rules.TileSets[tileset], mapSize, mapSize)
                {
                    Title  = basic.GetValue("Name", Path.GetFileNameWithoutExtension(iniFile)),
                    Author = "Westwood Studios"
                };

                var tl = new PPos(offsetX, offsetY);
                var br = new PPos(offsetX + width - 1, offsetY + height - 1);
                map.SetBounds(tl, br);

                if (legacyMapFormat == IniMapFormat.RedAlert)
                {
                    UnpackRATileData(ReadPackedSection(file.GetSection("MapPack")));
                    UnpackRAOverlayData(ReadPackedSection(file.GetSection("OverlayPack")));
                    ReadRATrees(file);
                }
                else
                {
                    // CnC
                    using (var s = GlobalFileSystem.Open(iniFile.Substring(0, iniFile.Length - 4) + ".bin"))
                        UnpackCncTileData(s);
                    ReadCncOverlay(file);
                    ReadCncTrees(file);
                }

                LoadVideos(file, "BASIC");
                LoadActors(file, "STRUCTURES");
                LoadActors(file, "UNITS");
                LoadActors(file, "INFANTRY");
                LoadActors(file, "SHIPS");
                LoadSmudges(file, "SMUDGE");

                var wps = file.GetSection("Waypoints")
                          .Where(kv => Exts.ParseIntegerInvariant(kv.Value) > 0)
                          .Select(kv => Pair.New(Exts.ParseIntegerInvariant(kv.Key),
                                                 LocationFromMapOffset(Exts.ParseIntegerInvariant(kv.Value), mapSize)));

                // Add waypoint actors
                foreach (var kv in wps)
                {
                    if (kv.First <= 7)
                    {
                        var ar = new ActorReference("mpspawn")
                        {
                            new LocationInit((CPos)kv.Second),
                            new OwnerInit("Neutral")
                        };

                        map.ActorDefinitions.Add(new MiniYamlNode("Actor" + actorCount++, ar.Save()));
                    }
                    else
                    {
                        var ar = new ActorReference("waypoint")
                        {
                            new LocationInit((CPos)kv.Second),
                            new OwnerInit("Neutral")
                        };

                        map.ActorDefinitions.Add(new MiniYamlNode("waypoint" + kv.First, ar.Save()));
                    }
                }

                // Create default player definitions only if there are no players to import
                mapPlayers = new MapPlayers(map.Rules, (players.Count == 0) ? map.SpawnPoints.Value.Length : 0);
                foreach (var p in players)
                {
                    LoadPlayer(file, p, legacyMapFormat == IniMapFormat.RedAlert);
                }
                map.PlayerDefinitions = mapPlayers.ToMiniYaml();
            }
        }
示例#23
0
 void LoadSmudges(IniFile file, string section)
 {
     foreach (var s in file.GetSection(section, true))
     {
         // loc=type,loc,depth
         var parts = s.Value.Split(',');
         var loc   = Exts.ParseIntegerInvariant(parts[1]);
         map.Smudges.Value.Add(new SmudgeReference(parts[0].ToLowerInvariant(), new int2(loc % mapSize, loc / mapSize), Exts.ParseIntegerInvariant(parts[2])));
     }
 }
示例#24
0
 void LoadSmudges(IniFile file, string section)
 {
     foreach (var s in file.GetSection(section, true))
     {
         // loc=type,loc,depth
         var parts = s.Value.Split(',');
         var loc   = Exts.ParseIntegerInvariant(parts[1]);
         var key   = "{0} {1},{2} {3}".F(parts[0].ToLowerInvariant(), loc % mapSize, loc / mapSize, Exts.ParseIntegerInvariant(parts[2]));
         map.SmudgeDefinitions.Add(new MiniYamlNode(key, ""));
     }
 }
示例#25
0
        public bool InterpretCommand(S server, Connection conn, Session.Client client, string cmd)
        {
            if (!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;

                      Log.Write("server", "Player @{0} is {1}",
                                conn.socket.RemoteEndPoint, client.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);
                      }

                      server.StartGame();
                      return(true);
                  } },
                { "slot",
                  s =>
                  {
                      if (!server.LobbyInfo.Slots.ContainsKey(s))
                      {
                          Log.Write("server", "Invalid slot: {0}", s);
                          return(false);
                      }

                      var slot = server.LobbyInfo.Slots[s];

                      if (slot.Closed || server.LobbyInfo.ClientInSlot(s) != null)
                      {
                          return(false);
                      }

                      client.Slot = s;
                      S.SyncClientToPlayerReference(client, server.Map.Players[s]);
                      server.SyncLobbyClients();
                      CheckAutoStart(server);

                      return(true);
                  } },
                { "allow_spectators",
                  s =>
                  {
                      if (bool.TryParse(s, out server.LobbyInfo.GlobalSettings.AllowSpectators))
                      {
                          server.SyncLobbyGlobalSettings();
                          return(true);
                      }
                      else
                      {
                          server.SendOrderTo(conn, "Message", "Malformed allow_spectate command");
                          return(true);
                      }
                  } },
                { "spectate",
                  s =>
                  {
                      if (server.LobbyInfo.GlobalSettings.AllowSpectators || client.IsAdmin)
                      {
                          client.Slot       = null;
                          client.SpawnPoint = 0;
                          client.Color      = HSLColor.FromRGB(255, 255, 255);
                          server.SyncLobbyClients();
                          return(true);
                      }
                      else
                      {
                          return(false);
                      }
                  } },
                { "slot_close",
                  s =>
                  {
                      if (!ValidateSlotCommand(server, conn, client, s, true))
                      {
                          return(false);
                      }

                      // kick any player that's in the slot
                      var occupant = server.LobbyInfo.ClientInSlot(s);
                      if (occupant != null)
                      {
                          if (occupant.Bot != null)
                          {
                              server.LobbyInfo.Clients.Remove(occupant);
                              server.SyncLobbyClients();
                              var ping = server.LobbyInfo.PingFromClient(occupant);
                              server.LobbyInfo.ClientPings.Remove(ping);
                              server.SyncClientPing();
                          }
                          else
                          {
                              var occupantConn = server.Conns.FirstOrDefault(c => c.PlayerIndex == occupant.Index);
                              if (occupantConn != null)
                              {
                                  server.SendOrderTo(occupantConn, "ServerError", "Your slot was closed by the host");
                                  server.DropClient(occupantConn);
                              }
                          }
                      }

                      server.LobbyInfo.Slots[s].Closed = true;
                      server.SyncLobbySlots();
                      return(true);
                  } },
                { "slot_open",
                  s =>
                  {
                      if (!ValidateSlotCommand(server, conn, client, s, true))
                      {
                          return(false);
                      }

                      var slot = server.LobbyInfo.Slots[s];
                      slot.Closed = false;
                      server.SyncLobbySlots();

                      // Slot may have a bot in it
                      var occupant = server.LobbyInfo.ClientInSlot(s);
                      if (occupant != null && occupant.Bot != null)
                      {
                          server.LobbyInfo.Clients.Remove(occupant);
                          var ping = server.LobbyInfo.PingFromClient(occupant);
                          server.LobbyInfo.ClientPings.Remove(ping);
                      }

                      server.SyncLobbyClients();
                      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))
                      {
                          Log.Write("server", "Invalid bot controller client index: {0}", parts[1]);
                          return(false);
                      }

                      var botType = parts.Skip(2).JoinWith(" ");

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

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

                          // Pick a random color for the bot
                          HSLColor botColor;
                          do
                          {
                              var hue = (byte)server.Random.Next(255);
                              var sat = (byte)server.Random.Next(255);
                              var lum = (byte)server.Random.Next(51, 255);
                              botColor = new HSLColor(hue, sat, lum);
                          } while (!ColorValidator.ValidatePlayerNewColor(server, botColor.RGB, bot.Index));

                          bot.Color = bot.PreferredColor = botColor;

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

                      S.SyncClientToPlayerReference(bot, server.Map.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);
                      }

                      if (server.ModData.MapCache[s].Status != MapStatus.Available)
                      {
                          server.SendOrderTo(conn, "Message", "Map was not found on server");
                          return(true);
                      }

                      server.LobbyInfo.GlobalSettings.Map = s;

                      var oldSlots = server.LobbyInfo.Slots.Keys.ToArray();
                      LoadMap(server);
                      SetDefaultDifficulty(server);

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

                      // Reassign players into new slots based on their old slots:
                      //  - Observers remain as observers
                      //  - Players who now lack a slot are made observers
                      //  - Bots who now lack a slot are dropped
                      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)
                          {
                              // Remove Bot from slot if slot forbids bots
                              if (c.Bot != null && !server.Map.Players[c.Slot].AllowBots)
                              {
                                  server.LobbyInfo.Clients.Remove(c);
                              }
                              S.SyncClientToPlayerReference(c, server.Map.Players[c.Slot]);
                          }
                          else if (c.Bot != null)
                          {
                              server.LobbyInfo.Clients.Remove(c);
                          }
                      }

                      foreach (var c in server.LobbyInfo.Clients)
                      {
                          // Validate if color is allowed and get an alternative it it isn't
                          c.Color = c.PreferredColor = ColorValidator.ValidatePlayerColorAndGetAlternative(server, c.Color, c.Index, conn);
                      }

                      server.SyncLobbyInfo();

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

                      return(true);
                  } },
                { "fragilealliance",
                  s =>
                  {
                      if (!client.IsAdmin)
                      {
                          server.SendOrderTo(conn, "Message", "Only the host can set that option");
                          return(true);
                      }

                      if (server.Map.Options.FragileAlliances.HasValue)
                      {
                          server.SendOrderTo(conn, "Message", "Map has disabled alliance configuration");
                          return(true);
                      }

                      bool.TryParse(s, out server.LobbyInfo.GlobalSettings.FragileAlliances);
                      server.SyncLobbyGlobalSettings();
                      server.SendMessage("{0} {1} Diplomacy Changes."
                                         .F(client.Name, server.LobbyInfo.GlobalSettings.FragileAlliances ? "enabled" : "disabled"));

                      return(true);
                  } },
                { "allowcheats",
                  s =>
                  {
                      if (!client.IsAdmin)
                      {
                          server.SendOrderTo(conn, "Message", "Only the host can set that option");
                          return(true);
                      }

                      if (server.Map.Options.Cheats.HasValue)
                      {
                          server.SendOrderTo(conn, "Message", "Map has disabled cheat configuration");
                          return(true);
                      }

                      bool.TryParse(s, out server.LobbyInfo.GlobalSettings.AllowCheats);
                      server.SyncLobbyGlobalSettings();
                      server.SendMessage("{0} {1} Developer Cheats."
                                         .F(client.Name, server.LobbyInfo.GlobalSettings.AllowCheats ? "allowed" : "disallowed"));

                      return(true);
                  } },
                { "shroud",
                  s =>
                  {
                      if (!client.IsAdmin)
                      {
                          server.SendOrderTo(conn, "Message", "Only the host can set that option");
                          return(true);
                      }

                      if (server.Map.Options.Shroud.HasValue)
                      {
                          server.SendOrderTo(conn, "Message", "Map has disabled shroud configuration");
                          return(true);
                      }

                      bool.TryParse(s, out server.LobbyInfo.GlobalSettings.Shroud);
                      server.SyncLobbyGlobalSettings();
                      server.SendMessage("{0} {1} Shroud."
                                         .F(client.Name, server.LobbyInfo.GlobalSettings.Shroud ? "enabled" : "disabled"));

                      return(true);
                  } },
                { "fog",
                  s =>
                  {
                      if (!client.IsAdmin)
                      {
                          server.SendOrderTo(conn, "Message", "Only the host can set that option");
                          return(true);
                      }

                      if (server.Map.Options.Fog.HasValue)
                      {
                          server.SendOrderTo(conn, "Message", "Map has disabled fog configuration");
                          return(true);
                      }

                      bool.TryParse(s, out server.LobbyInfo.GlobalSettings.Fog);
                      server.SyncLobbyGlobalSettings();
                      server.SendMessage("{0} {1} Fog of War."
                                         .F(client.Name, server.LobbyInfo.GlobalSettings.Fog ? "enabled" : "disabled"));

                      return(true);
                  } },
                { "assignteams",
                  s =>
                  {
                      if (!client.IsAdmin)
                      {
                          server.SendOrderTo(conn, "Message", "Only the host can set that option");
                          return(true);
                      }

                      int teamCount;
                      if (!Exts.TryParseIntegerInvariant(s, out teamCount))
                      {
                          server.SendOrderTo(conn, "Message", "Number of teams could not be parsed: {0}".F(s));
                          return(true);
                      }

                      var maxTeams = (server.LobbyInfo.Clients.Count(c => c.Slot != null) + 1) / 2;
                      teamCount = teamCount.Clamp(0, maxTeams);
                      var players = server.LobbyInfo.Slots
                                    .Select(slot => server.LobbyInfo.ClientInSlot(slot.Key))
                                    .Where(c => c != null && !server.LobbyInfo.Slots[c.Slot].LockTeam);

                      var assigned    = 0;
                      var playerCount = players.Count();
                      foreach (var player in players)
                      {
                          // Free for all
                          if (teamCount == 0)
                          {
                              player.Team = 0;
                          }

                          // Humans vs Bots
                          else if (teamCount == 1)
                          {
                              player.Team = player.Bot == null ? 1 : 2;
                          }
                          else
                          {
                              player.Team = assigned++ *teamCount / playerCount + 1;
                          }
                      }

                      server.SyncLobbyClients();
                      return(true);
                  } },
                { "crates",
                  s =>
                  {
                      if (!client.IsAdmin)
                      {
                          server.SendOrderTo(conn, "Message", "Only the host can set that option");
                          return(true);
                      }

                      if (server.Map.Options.Crates.HasValue)
                      {
                          server.SendOrderTo(conn, "Message", "Map has disabled crate configuration");
                          return(true);
                      }

                      bool.TryParse(s, out server.LobbyInfo.GlobalSettings.Crates);
                      server.SyncLobbyGlobalSettings();
                      server.SendMessage("{0} {1} Crates Appear."
                                         .F(client.Name, server.LobbyInfo.GlobalSettings.Crates ? "enabled" : "disabled"));

                      return(true);
                  } },
                { "allybuildradius",
                  s =>
                  {
                      if (!client.IsAdmin)
                      {
                          server.SendOrderTo(conn, "Message", "Only the host can set that option");
                          return(true);
                      }

                      if (server.Map.Options.AllyBuildRadius.HasValue)
                      {
                          server.SendOrderTo(conn, "Message", "Map has disabled ally build radius configuration");
                          return(true);
                      }

                      bool.TryParse(s, out server.LobbyInfo.GlobalSettings.AllyBuildRadius);
                      server.SyncLobbyGlobalSettings();
                      server.SendMessage("{0} {1} Build off Ally ConYards."
                                         .F(client.Name, server.LobbyInfo.GlobalSettings.AllyBuildRadius ? "enabled" : "disabled"));

                      return(true);
                  } },
                { "difficulty",
                  s =>
                  {
                      if (!client.IsAdmin)
                      {
                          server.SendOrderTo(conn, "Message", "Only the host can set that option");
                          return(true);
                      }

                      if (s != null && !server.Map.Options.Difficulties.Contains(s))
                      {
                          server.SendOrderTo(conn, "Message", "Unsupported difficulty selected: {0}".F(s));
                          server.SendOrderTo(conn, "Message", "Supported difficulties: {0}".F(server.Map.Options.Difficulties.JoinWith(",")));
                          return(true);
                      }

                      server.LobbyInfo.GlobalSettings.Difficulty = s;
                      server.SyncLobbyGlobalSettings();
                      server.SendMessage("{0} changed difficulty to {1}.".F(client.Name, s));

                      return(true);
                  } },
                { "startingunits",
                  s =>
                  {
                      if (!client.IsAdmin)
                      {
                          server.SendOrderTo(conn, "Message", "Only the host can set that option");
                          return(true);
                      }

                      if (!server.Map.Options.ConfigurableStartingUnits)
                      {
                          server.SendOrderTo(conn, "Message", "Map has disabled start unit configuration");
                          return(true);
                      }

                      var startUnitsInfo = server.Map.Rules.Actors["world"].Traits.WithInterface <MPStartUnitsInfo>();
                      var selectedClass  = startUnitsInfo.Where(u => u.Class == s).Select(u => u.ClassName).FirstOrDefault();
                      var className      = selectedClass != null ? selectedClass : s;

                      server.LobbyInfo.GlobalSettings.StartingUnitsClass = s;
                      server.SyncLobbyGlobalSettings();
                      server.SendMessage("{0} changed Starting Units to {1}.".F(client.Name, className));

                      return(true);
                  } },
                { "startingcash",
                  s =>
                  {
                      if (!client.IsAdmin)
                      {
                          server.SendOrderTo(conn, "Message", "Only the host can set that option");
                          return(true);
                      }

                      if (server.Map.Options.StartingCash.HasValue)
                      {
                          server.SendOrderTo(conn, "Message", "Map has disabled cash configuration");
                          return(true);
                      }

                      server.LobbyInfo.GlobalSettings.StartingCash = Exts.ParseIntegerInvariant(s);
                      server.SyncLobbyGlobalSettings();
                      server.SendMessage("{0} changed Starting Cash to ${1}.".F(client.Name, s));

                      return(true);
                  } },
                { "techlevel",
                  s =>
                  {
                      if (!client.IsAdmin)
                      {
                          server.SendOrderTo(conn, "Message", "Only the host can set that option");
                          return(true);
                      }

                      if (server.Map.Options.TechLevel != null)
                      {
                          server.SendOrderTo(conn, "Message", "Map has disabled Tech configuration");
                          return(true);
                      }

                      server.LobbyInfo.GlobalSettings.TechLevel = s;
                      server.SyncLobbyInfo();
                      server.SendMessage("{0} changed Tech Level to {1}.".F(client.Name, s));

                      return(true);
                  } },
                { "kick",
                  s =>
                  {
                      if (!client.IsAdmin)
                      {
                          server.SendOrderTo(conn, "Message", "Only the host can kick players");
                          return(true);
                      }

                      var split = s.Split(' ');
                      if (split.Length < 2)
                      {
                          server.SendOrderTo(conn, "Message", "Malformed kick command");
                          return(true);
                      }

                      int kickClientID;
                      Exts.TryParseIntegerInvariant(split[0], out kickClientID);

                      var kickConn = server.Conns.SingleOrDefault(c => server.GetClient(c) != null && server.GetClient(c).Index == kickClientID);
                      if (kickConn == null)
                      {
                          server.SendOrderTo(conn, "Message", "Noone in that slot.");
                          return(true);
                      }

                      var kickClient = server.GetClient(kickConn);

                      Log.Write("server", "Kicking client {0} as requested", kickClientID);
                      server.SendMessage("{0} kicked {1} from the server.".F(client.Name, kickClient.Name));
                      server.SendOrderTo(kickConn, "ServerError", "You have been kicked from the server");
                      server.DropClient(kickConn);

                      bool tempBan;
                      bool.TryParse(split[1], out tempBan);

                      if (tempBan)
                      {
                          Log.Write("server", "Temporarily banning client {0} ({1}) as requested", kickClientID, kickClient.IpAddress);
                          server.SendMessage("{0} temporarily banned {1} from the server.".F(client.Name, kickClient.Name));
                          server.TempBans.Add(kickClient.IpAddress);
                      }

                      server.SyncLobbyClients();
                      server.SyncLobbySlots();

                      return(true);
                  } },
                { "name",
                  s =>
                  {
                      Log.Write("server", "Player@{0} is now known as {1}", conn.socket.RemoteEndPoint, s);
                      server.SendMessage("{0} is now known as {1}.".F(client.Name, s));
                      client.Name = s;
                      server.SyncLobbyClients();
                      return(true);
                  } },
                { "race",
                  s =>
                  {
                      var parts        = s.Split(' ');
                      var targetClient = server.LobbyInfo.ClientWithIndex(Exts.ParseIntegerInvariant(parts[0]));

                      // Only the host can change other client's info
                      if (targetClient.Index != client.Index && !client.IsAdmin)
                      {
                          return(true);
                      }

                      // Map has disabled race changes
                      if (server.LobbyInfo.Slots[targetClient.Slot].LockRace)
                      {
                          return(true);
                      }

                      targetClient.Country = parts[1];
                      server.SyncLobbyClients();
                      return(true);
                  } },
                { "team",
                  s =>
                  {
                      var parts        = s.Split(' ');
                      var targetClient = server.LobbyInfo.ClientWithIndex(Exts.ParseIntegerInvariant(parts[0]));

                      // Only the host can change other client's info
                      if (targetClient.Index != client.Index && !client.IsAdmin)
                      {
                          return(true);
                      }

                      // Map has disabled team changes
                      if (server.LobbyInfo.Slots[targetClient.Slot].LockTeam)
                      {
                          return(true);
                      }

                      int team;
                      if (!Exts.TryParseIntegerInvariant(parts[1], out team))
                      {
                          Log.Write("server", "Invalid team: {0}", s);
                          return(false);
                      }

                      targetClient.Team = team;
                      server.SyncLobbyClients();
                      return(true);
                  } },
                { "spawn",
                  s =>
                  {
                      var parts        = s.Split(' ');
                      var targetClient = server.LobbyInfo.ClientWithIndex(Exts.ParseIntegerInvariant(parts[0]));

                      // Only the host can change other client's info
                      if (targetClient.Index != client.Index && !client.IsAdmin)
                      {
                          return(true);
                      }

                      // Spectators don't need a spawnpoint
                      if (targetClient.Slot == null)
                      {
                          return(true);
                      }

                      // Map has disabled spawn changes
                      if (server.LobbyInfo.Slots[targetClient.Slot].LockSpawn)
                      {
                          return(true);
                      }

                      int spawnPoint;
                      if (!Exts.TryParseIntegerInvariant(parts[1], out spawnPoint) ||
                          spawnPoint <0 || spawnPoint> server.Map.GetSpawnPoints().Length)
                      {
                          Log.Write("server", "Invalid spawn point: {0}", parts[1]);
                          return(true);
                      }

                      if (server.LobbyInfo.Clients.Where(cc => cc != client).Any(cc => (cc.SpawnPoint == spawnPoint) && (cc.SpawnPoint != 0)))
                      {
                          server.SendOrderTo(conn, "Message", "You can't be at the same spawn point as another player");
                          return(true);
                      }

                      targetClient.SpawnPoint = spawnPoint;
                      server.SyncLobbyClients();
                      return(true);
                  } },
                { "color",
                  s =>
                  {
                      var parts        = s.Split(' ');
                      var targetClient = server.LobbyInfo.ClientWithIndex(Exts.ParseIntegerInvariant(parts[0]));

                      // Only the host can change other client's info
                      if (targetClient.Index != client.Index && !client.IsAdmin)
                      {
                          return(true);
                      }

                      // Spectator or map has disabled color changes
                      if (targetClient.Slot == null || server.LobbyInfo.Slots[targetClient.Slot].LockColor)
                      {
                          return(true);
                      }

                      var newHslColor = FieldLoader.GetValue <HSLColor>("(value)", parts[1]);

                      // Validate if color is allowed and get an alternative it it isn't
                      var altHslColor = ColorValidator.ValidatePlayerColorAndGetAlternative(server, newHslColor, targetClient.Index, conn);

                      targetClient.Color = altHslColor;

                      // Only update player's preferred color if new color is valid
                      if (newHslColor == altHslColor)
                      {
                          targetClient.PreferredColor = altHslColor;
                      }

                      server.SyncLobbyClients();
                      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));
        }
示例#26
0
        public void StartGame(Arguments args)
        {
            Launch = new LaunchArguments(args);
            Ui.ResetAll();
            Game.Settings.Save();

            if (Launch.Benchmark)
            {
                Log.AddChannel("cpu", "cpu.csv");
                Log.Write("cpu", "tick;time [ms]");

                Log.AddChannel("render", "render.csv");
                Log.Write("render", "frame;time [ms]");

                Console.WriteLine("Saving benchmark data into {0}".F(Path.Combine(Platform.SupportDir, "Logs")));

                Game.BenchmarkMode = true;
            }

            // Join a server directly
            var connect = Launch.GetConnectAddress();

            if (!string.IsNullOrEmpty(connect))
            {
                var parts = connect.Split(':');

                if (parts.Length == 2)
                {
                    var host = parts[0];
                    var port = Exts.ParseIntegerInvariant(parts[1]);
                    Game.LoadShellMap();
                    Game.RemoteDirectConnect(host, port);
                    return;
                }
            }

            // Load a replay directly
            if (!string.IsNullOrEmpty(Launch.Replay))
            {
                ReplayMetadata replayMeta = null;
                try
                {
                    replayMeta = ReplayMetadata.Read(Launch.Replay);
                }
                catch { }

                if (ReplayUtils.PromptConfirmReplayCompatibility(replayMeta, Game.LoadShellMap))
                {
                    Game.JoinReplay(Launch.Replay);
                }

                if (replayMeta != null)
                {
                    var mod = replayMeta.GameInfo.Mod;
                    if (mod != null && mod != Game.ModData.Manifest.Id && Game.Mods.ContainsKey(mod))
                    {
                        Game.InitializeMod(mod, args);
                    }
                }

                return;
            }

            Game.LoadShellMap();
            Game.Settings.Save();
        }
示例#27
0
        public static void LoadActors(IniFile file, string section, List <string> players, int mapSize, Map map)
        {
            foreach (var s in file.GetSection(section, true))
            {
                // Structures: num=owner,type,health,location,turret-facing,trigger
                // Units: num=owner,type,health,location,facing,action,trigger
                // Infantry: num=owner,type,health,location,subcell,action,facing,trigger
                try
                {
                    var parts = s.Value.Split(',');
                    if (parts[0] == "")
                    {
                        parts[0] = "Neutral";
                    }

                    if (!players.Contains(parts[0]))
                    {
                        players.Add(parts[0]);
                    }

                    var loc    = Exts.ParseIntegerInvariant(parts[3]);
                    var health = Exts.ParseIntegerInvariant(parts[2]) * 100 / 256;
                    var facing = (section == "INFANTRY") ? Exts.ParseIntegerInvariant(parts[6]) : Exts.ParseIntegerInvariant(parts[4]);

                    var actor = new ActorReference(parts[1].ToLowerInvariant())
                    {
                        new LocationInit(new CPos(loc % mapSize, loc / mapSize)),
                        new OwnerInit(parts[0]),
                    };

                    var initDict = actor.InitDict;
                    if (health != 100)
                    {
                        initDict.Add(new HealthInit(health));
                    }
                    if (facing != 0)
                    {
                        initDict.Add(new FacingInit(255 - facing));
                    }

                    if (section == "INFANTRY")
                    {
                        actor.Add(new SubCellInit(Exts.ParseIntegerInvariant(parts[4])));
                    }

                    var actorCount = map.ActorDefinitions.Count;

                    if (!map.Rules.Actors.ContainsKey(parts[1].ToLowerInvariant()))
                    {
                        Console.WriteLine("Ignoring unknown actor type: `{0}`".F(parts[1].ToLowerInvariant()));
                    }
                    else
                    {
                        map.ActorDefinitions.Add(new MiniYamlNode("Actor" + actorCount++, actor.Save()));
                    }
                }
                catch (Exception)
                {
                    Console.WriteLine("Malformed actor definition: `{0}`".F(s));
                }
            }
        }
        void IUtilityCommand.Run(Utility utility, string[] args)
        {
            // HACK: The engine code assumes that Game.modData is set.
            var modData = Game.ModData = utility.ModData;

            modData.MapCache.LoadMaps();

            var engineDate = Exts.ParseIntegerInvariant(args[1]);

            if (engineDate < UpgradeRules.MinimumSupportedVersion)
            {
                Console.WriteLine("Unsupported engine version. Use the release-{0} utility to update to that version, and then try again",
                                  UpgradeRules.MinimumSupportedVersion);
                return;
            }

            ProcessYaml("Rules", modData.Manifest.Rules, modData, engineDate, UpgradeRules.UpgradeActorRules);
            ProcessYaml("Weapons", modData.Manifest.Weapons, modData, engineDate, UpgradeRules.UpgradeWeaponRules);
            ProcessYaml("Sequences", modData.Manifest.Sequences, modData, engineDate, UpgradeRules.UpgradeSequences);
            ProcessYaml("Tilesets", modData.Manifest.TileSets, modData, engineDate, UpgradeRules.UpgradeTileset);
            ProcessYaml("Cursors", modData.Manifest.Cursors, modData, engineDate, UpgradeRules.UpgradeCursors);
            ProcessYaml("Chrome Metrics", modData.Manifest.ChromeMetrics, modData, engineDate, UpgradeRules.UpgradeChromeMetrics);
            ProcessYaml("Chrome Layout", modData.Manifest.ChromeLayout, modData, engineDate, UpgradeRules.UpgradeChromeLayout);

            // The map cache won't be valid if there was a map format upgrade, so walk the map packages manually
            // Only upgrade system maps - user maps must be updated manually using --upgrade-map
            Console.WriteLine("Processing Maps:");
            foreach (var kv in modData.Manifest.MapFolders)
            {
                var name           = kv.Key;
                var classification = string.IsNullOrEmpty(kv.Value)
                                        ? MapClassification.Unknown : Enum <MapClassification> .Parse(kv.Value);

                if (classification != MapClassification.System)
                {
                    continue;
                }

                var optional = name.StartsWith("~");
                if (optional)
                {
                    name = name.Substring(1);
                }

                try
                {
                    using (var package = (IReadWritePackage)modData.ModFiles.OpenPackage(name))
                    {
                        foreach (var map in package.Contents)
                        {
                            try
                            {
                                using (var mapPackage = package.OpenPackage(map, modData.ModFiles))
                                {
                                    if (mapPackage != null)
                                    {
                                        UpgradeMapCommand.UpgradeMap(modData, (IReadWritePackage)mapPackage, engineDate);
                                    }
                                }
                            }
                            catch (Exception e)
                            {
                                Console.WriteLine("Failed to upgrade map {0}", map);
                                Console.WriteLine("Error was: {0}", e.ToString());
                            }
                        }
                    }
                }
                catch { }
            }
        }
示例#29
0
        public void StartGame(Arguments args)
        {
            Ui.ResetAll();
            Game.Settings.Save();

            // Check whether the mod content is installed
            // TODO: The installation code has finally been beaten into shape, so we can
            // finally move it all into the planned "Manage Content" panel in the modchooser mod.
            var installData       = Game.ModData.Manifest.Get <ContentInstaller>();
            var installModContent = !installData.TestFiles.All(f => GlobalFileSystem.Exists(f));
            var installModMusic   = args != null && args.Contains("Install.Music");

            if (installModContent || installModMusic)
            {
                var widgetArgs = new WidgetArgs()
                {
                    { "continueLoading", () => Game.InitializeMod(Game.Settings.Game.Mod, args) },
                };

                if (installData.BackgroundWidget != null)
                {
                    Ui.LoadWidget(installData.BackgroundWidget, Ui.Root, widgetArgs);
                }

                var menu = installModContent ? installData.MenuWidget : installData.MusicMenuWidget;
                Ui.OpenWindow(menu, widgetArgs);

                return;
            }

            // Join a server directly
            var connect = string.Empty;

            if (args != null)
            {
                if (args.Contains("Launch.Connect"))
                {
                    connect = args.GetValue("Launch.Connect", null);
                }

                if (args.Contains("Launch.URI"))
                {
                    connect = args.GetValue("Launch.URI", null);
                    if (connect != null)
                    {
                        connect = connect.Replace("openra://", "");
                        connect = connect.TrimEnd('/');
                    }
                }
            }

            if (!string.IsNullOrEmpty(connect))
            {
                var parts = connect.Split(':');

                if (parts.Length == 2)
                {
                    var host = parts[0];
                    var port = Exts.ParseIntegerInvariant(parts[1]);
                    Game.LoadShellMap();
                    Game.RemoteDirectConnect(host, port);
                    return;
                }
            }

            // Load a replay directly
            var replayFilename = args != null?args.GetValue("Launch.Replay", null) : null;

            if (!string.IsNullOrEmpty(replayFilename))
            {
                var replayMeta = ReplayMetadata.Read(replayFilename);
                if (ReplayUtils.PromptConfirmReplayCompatibility(replayMeta, Game.LoadShellMap))
                {
                    Game.JoinReplay(replayFilename);
                }

                if (replayMeta != null)
                {
                    var mod = replayMeta.GameInfo.Mod;
                    if (mod != null && mod != Game.ModData.Manifest.Mod.Id && ModMetadata.AllMods.ContainsKey(mod))
                    {
                        Game.InitializeMod(mod, args);
                    }
                }

                return;
            }

            Game.LoadShellMap();
            Game.Settings.Save();
        }
示例#30
0
        enum IniMapFormat { RedAlert = 3 }         // otherwise, cnc (2 variants exist, we don't care to differentiate)

        public void ConvertIniMap(string iniFile)
        {
            var file            = new IniFile(GlobalFileSystem.Open(iniFile));
            var basic           = file.GetSection("Basic");
            var mapSection      = file.GetSection("Map");
            var legacyMapFormat = (IniMapFormat)Exts.ParseIntegerInvariant(basic.GetValue("NewINIFormat", "0"));
            var offsetX         = Exts.ParseIntegerInvariant(mapSection.GetValue("X", "0"));
            var offsetY         = Exts.ParseIntegerInvariant(mapSection.GetValue("Y", "0"));
            var width           = Exts.ParseIntegerInvariant(mapSection.GetValue("Width", "0"));
            var height          = Exts.ParseIntegerInvariant(mapSection.GetValue("Height", "0"));

            mapSize = (legacyMapFormat == IniMapFormat.RedAlert) ? 128 : 64;
            var size = new Size(mapSize, mapSize);

            var tileset = Truncate(mapSection.GetValue("Theater", "TEMPERAT"), 8);

            map            = Map.FromTileset(rules.TileSets[tileset]);
            map.Title      = basic.GetValue("Name", Path.GetFileNameWithoutExtension(iniFile));
            map.Author     = "Westwood Studios";
            map.MapSize.X  = mapSize;
            map.MapSize.Y  = mapSize;
            map.Bounds     = Rectangle.FromLTRB(offsetX, offsetY, offsetX + width, offsetY + height);
            map.Selectable = true;

            map.Smudges      = Exts.Lazy(() => new List <SmudgeReference>());
            map.Actors       = Exts.Lazy(() => new Dictionary <string, ActorReference>());
            map.MapResources = Exts.Lazy(() => new CellLayer <ResourceTile>(TileShape.Rectangle, size));
            map.MapTiles     = Exts.Lazy(() => new CellLayer <TerrainTile>(TileShape.Rectangle, size));

            map.Options = new MapOptions();

            if (legacyMapFormat == IniMapFormat.RedAlert)
            {
                UnpackRATileData(ReadPackedSection(file.GetSection("MapPack")));
                UnpackRAOverlayData(ReadPackedSection(file.GetSection("OverlayPack")));
                ReadRATrees(file);
            }
            else
            {
                // CnC
                using (var s = GlobalFileSystem.Open(iniFile.Substring(0, iniFile.Length - 4) + ".bin"))
                    UnpackCncTileData(s);
                ReadCncOverlay(file);
                ReadCncTrees(file);
            }

            LoadActors(file, "STRUCTURES");
            LoadActors(file, "UNITS");
            LoadActors(file, "INFANTRY");
            LoadSmudges(file, "SMUDGE");

            foreach (var p in players)
            {
                LoadPlayer(file, p, legacyMapFormat == IniMapFormat.RedAlert);
            }

            var wps = file.GetSection("Waypoints")
                      .Where(kv => Exts.ParseIntegerInvariant(kv.Value) > 0)
                      .Select(kv => Pair.New(Exts.ParseIntegerInvariant(kv.Key),
                                             LocationFromMapOffset(Exts.ParseIntegerInvariant(kv.Value), mapSize)))
                      .ToArray();

            // Add waypoint actors
            foreach (var kv in wps)
            {
                if (kv.First <= 7)
                {
                    var a = new ActorReference("mpspawn");
                    a.Add(new LocationInit((CPos)kv.Second));
                    a.Add(new OwnerInit("Neutral"));
                    map.Actors.Value.Add("Actor" + map.Actors.Value.Count.ToString(), a);
                }
                else
                {
                    var a = new ActorReference("waypoint");
                    a.Add(new LocationInit((CPos)kv.Second));
                    a.Add(new OwnerInit("Neutral"));
                    map.Actors.Value.Add("waypoint" + kv.First, a);
                }
            }
        }