Esempio n. 1
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
                          var hue = (byte)server.Random.Next(255);
                          var sat = (byte)server.Random.Next(255);
                          var lum = (byte)server.Random.Next(51, 255);
                          bot.Color = bot.PreferredColor = new HSLColor(hue, sat, lum);

                          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();
                      int 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);
                          }
                      }

                      server.SyncLobbyInfo();
                      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();
                      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();
                      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();
                      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();
                      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();
                      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();
                      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();
                      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);
                      }

                      server.LobbyInfo.GlobalSettings.StartingUnitsClass = s;
                      server.SyncLobbyGlobalSettings();
                      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();

                      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();
                      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 kickConnIP = server.GetClient(kickConn).IpAddress;

                      Log.Write("server", "Kicking client {0} as requested", kickClientID);
                      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, kickConnIP);
                          server.TempBans.Add(kickConnIP);
                      }

                      server.SyncLobbyClients();
                      server.SyncLobbySlots();
                      return(true);
                  } },
                { "name",
                  s =>
                  {
                      Log.Write("server", "Player@{0} is now known as {1}", conn.socket.RemoteEndPoint, 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 ci = parts[1].Split(',').Select(cc => Exts.ParseIntegerInvariant(cc)).ToArray();
                      targetClient.Color = targetClient.PreferredColor = new HSLColor((byte)ci[0], (byte)ci[1], (byte)ci[2]);
                      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));
        }
Esempio n. 2
0
        public override bool Produce(Actor self, ActorInfo producee, string productionType, TypeDictionary inits, int refundableValue)
        {
            if (IsTraitDisabled || IsTraitPaused)
            {
                return(false);
            }

            var info         = (ProductionAirdropInfo)Info;
            var owner        = self.Owner;
            var map          = owner.World.Map;
            var aircraftInfo = self.World.Map.Rules.Actors[info.ActorType].TraitInfo <AircraftInfo>();
            var mpStart      = owner.World.WorldActor.TraitOrDefault <MPStartLocations>();

            CPos   startPos;
            CPos   endPos;
            WAngle spawnFacing;

            if (info.BaselineSpawn && mpStart != null)
            {
                var spawn    = mpStart.Start[owner];
                var bounds   = map.Bounds;
                var center   = new MPos(bounds.Left + bounds.Width / 2, bounds.Top + bounds.Height / 2).ToCPos(map);
                var spawnVec = spawn - center;
                startPos = spawn + spawnVec * (Exts.ISqrt((bounds.Height * bounds.Height + bounds.Width * bounds.Width) / (4 * spawnVec.LengthSquared)));
                endPos   = startPos;
                var spawnDirection = new WVec((self.Location - startPos).X, (self.Location - startPos).Y, 0);
                spawnFacing = spawnDirection.Yaw;
            }
            else
            {
                // Start a fixed distance away: the width of the map.
                // This makes the production timing independent of spawnpoint
                var loc = self.Location.ToMPos(map);
                startPos    = new MPos(loc.U + map.Bounds.Width, loc.V).ToCPos(map);
                endPos      = new MPos(map.Bounds.Left, loc.V).ToCPos(map);
                spawnFacing = info.Facing;
            }

            // Assume a single exit point for simplicity
            var exit = self.Info.TraitInfos <ExitInfo>().First();

            foreach (var tower in self.TraitsImplementing <INotifyDelivery>())
            {
                tower.IncomingDelivery(self);
            }

            owner.World.AddFrameEndTask(w =>
            {
                if (!self.IsInWorld || self.IsDead)
                {
                    owner.PlayerActor.Trait <PlayerResources>().GiveCash(refundableValue);
                    return;
                }

                var actor = w.CreateActor(info.ActorType, new TypeDictionary
                {
                    new CenterPositionInit(w.Map.CenterOfCell(startPos) + new WVec(WDist.Zero, WDist.Zero, aircraftInfo.CruiseAltitude)),
                    new OwnerInit(owner),
                    new FacingInit(spawnFacing)
                });

                var exitCell = self.Location + exit.ExitCell;
                actor.QueueActivity(new Land(actor, Target.FromActor(self), WDist.Zero, WVec.Zero, info.Facing, clearCells: new CPos[1] {
                    exitCell
                }));
                actor.QueueActivity(new CallFunc(() =>
                {
                    if (!self.IsInWorld || self.IsDead)
                    {
                        owner.PlayerActor.Trait <PlayerResources>().GiveCash(refundableValue);
                        return;
                    }

                    foreach (var cargo in self.TraitsImplementing <INotifyDelivery>())
                    {
                        cargo.Delivered(self);
                    }

                    self.World.AddFrameEndTask(ww => DoProduction(self, producee, exit, productionType, inits));
                    Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", info.ReadyAudio, self.Owner.Faction.InternalName);
                }));

                actor.QueueActivity(new FlyOffMap(actor, Target.FromCell(w, endPos)));
                actor.QueueActivity(new RemoveSelf());
            });

            return(true);
        }
Esempio n. 3
0
        public override void Draw()
        {
            var scaleBy  = 100.0f;
            var provided = GetProvided();
            var used     = GetUsed();
            var max      = Math.Max(provided, used);

            while (max >= scaleBy)
            {
                scaleBy *= 2;
            }

            var providedFrac = providedLerp.Update(provided / scaleBy);
            var usedFrac     = usedLerp.Update(used / scaleBy);

            var b         = RenderBounds;
            var indicator = ChromeProvider.GetImage(IndicatorCollection, IndicatorImage);

            var color = GetBarColor();

            if (Orientation == ResourceBarOrientation.Vertical)
            {
                if (Style == ResourceBarStyle.Bevelled)
                {
                    var colorDark = Exts.ColorLerp(0.25f, color, Color.Black);
                    for (var i = 0; i < b.Height; i++)
                    {
                        color = (i - 1 < b.Height / 2) ? color : colorDark;
                        var bottom = new float2(b.Left + i, b.Bottom);
                        var top    = new float2(b.Left + i, b.Bottom + providedFrac * b.Height);

                        // Indent corners
                        if ((i == 0 || i == b.Width - 1) && providedFrac * b.Height > 1)
                        {
                            bottom.Y += 1;
                            top.Y    -= 1;
                        }

                        Game.Renderer.LineRenderer.DrawLine(bottom, top, color, color);
                    }
                }
                else
                {
                    Game.Renderer.LineRenderer.FillRect(new Rectangle(b.X, (int)float2.Lerp(b.Bottom, b.Top, providedFrac),
                                                                      b.Width, (int)(providedFrac * b.Height)), color);
                }

                var x = (b.Left + b.Right - indicator.size.X) / 2;
                var y = float2.Lerp(b.Bottom, b.Top, usedFrac) - indicator.size.Y / 2;
                Game.Renderer.RgbaSpriteRenderer.DrawSprite(indicator, new float2(x, y));
            }
            else
            {
                if (Style == ResourceBarStyle.Bevelled)
                {
                    var colorDark = Exts.ColorLerp(0.25f, color, Color.Black);
                    for (var i = 0; i < b.Height; i++)
                    {
                        color = (i - 1 < b.Height / 2) ? color : colorDark;
                        var left  = new float2(b.Left, b.Top + i);
                        var right = new float2(b.Left + providedFrac * b.Width, b.Top + i);

                        // Indent corners
                        if ((i == 0 || i == b.Height - 1) && providedFrac * b.Width > 1)
                        {
                            left.X  += 1;
                            right.X -= 1;
                        }

                        Game.Renderer.LineRenderer.DrawLine(left, right, color, color);
                    }
                }
                else
                {
                    Game.Renderer.LineRenderer.FillRect(new Rectangle(b.X, b.Y, (int)(providedFrac * b.Width), b.Height), color);
                }

                var x = float2.Lerp(b.Left, b.Right, usedFrac) - indicator.size.X / 2;
                var y = (b.Bottom + b.Top - indicator.size.Y) / 2;
                Game.Renderer.RgbaSpriteRenderer.DrawSprite(indicator, new float2(x, y));
            }
        }
Esempio n. 4
0
        public override void Draw()
        {
            if (video == null)
            {
                return;
            }

            if (!stopped && !paused)
            {
                int nextFrame;
                if (video.HasAudio && !Game.Sound.DummyEngine)
                {
                    nextFrame = (int)float2.Lerp(0, video.FrameCount, Game.Sound.VideoSeekPosition * invLength);
                }
                else
                {
                    nextFrame = video.CurrentFrameIndex + 1;
                }

                // Without the 2nd check the sound playback sometimes ends before the final frame is displayed which causes the player to be stuck on the first frame
                if (nextFrame > video.FrameCount || nextFrame < video.CurrentFrameIndex)
                {
                    Stop();
                    return;
                }

                var skippedFrames = 0;
                while (nextFrame > video.CurrentFrameIndex)
                {
                    video.AdvanceFrame();
                    videoSprite.Sheet.GetTexture().SetData(video.CurrentFrameData, textureSize, textureSize);
                    skippedFrames++;
                }

                if (skippedFrames > 1)
                {
                    Log.Write("perf", $"{nameof(VideoPlayerWidget)}: {cachedVideoFileName} skipped {skippedFrames} frames at position {video.CurrentFrameIndex}");
                }
            }

            WidgetUtils.DrawSprite(videoSprite, videoOrigin, videoSize);

            if (DrawOverlay)
            {
                // Create the scan line grid to render over the video
                // To avoid aliasing, this must be an integer number of screen pixels.
                // A few complications to be aware of:
                // - The video may have a different aspect ratio to the widget RenderBounds
                // - The RenderBounds coordinates may be a non-integer scale of the screen pixel size
                // - The screen pixel size may change while the video is playing back
                //   (user moves a window between displays with different DPI on macOS)
                var scale = Game.Renderer.WindowScale;
                if (overlaySheet == null || overlayScale != scale)
                {
                    overlaySheet?.Dispose();

                    // Calculate the scan line height by converting the video scale (copied from Open()) to screen
                    // pixels, halving it (scan lines cover half the pixel height), and rounding to the nearest integer.
                    var videoScale    = Math.Min((float)RenderBounds.Width / video.Width, RenderBounds.Height / (video.Height * AspectRatio));
                    var halfRowHeight = (int)(videoScale * scale / 2 + 0.5f);

                    // The overlay can be minimally stored in a 1px column which is stretched to cover the full screen
                    var overlayHeight    = (int)(RenderBounds.Height * scale / halfRowHeight);
                    var overlaySheetSize = new Size(1, Exts.NextPowerOf2(overlayHeight));
                    var overlay          = new byte[4 * Exts.NextPowerOf2(overlayHeight)];
                    overlaySheet = new Sheet(SheetType.BGRA, overlaySheetSize);

                    // Every second pixel is the scan line - set alpha to 128 to make the lines less harsh
                    for (var i = 3; i < 4 * overlayHeight; i += 8)
                    {
                        overlay[i] = 128;
                    }

                    overlaySheet.GetTexture().SetData(overlay, overlaySheetSize.Width, overlaySheetSize.Height);
                    overlaySprite = new Sprite(overlaySheet, new Rectangle(0, 0, 1, overlayHeight), TextureChannel.RGBA);

                    // Overlay origin must be rounded to the nearest screen pixel to prevent aliasing
                    overlayOrigin = new float2((int)(RenderBounds.X * scale + 0.5f), (int)(RenderBounds.Y * scale + 0.5f)) / scale;
                    overlaySize   = new float2(RenderBounds.Width, overlayHeight * halfRowHeight / scale);
                    overlayScale  = scale;
                }

                WidgetUtils.DrawSprite(overlaySprite, overlayOrigin, overlaySize);
            }
        }
Esempio n. 5
0
 public Production(ProductionInfo info, Actor self)
 {
     Info = info;
     rp   = Exts.Lazy(() => self.IsDead() ? null : self.TraitOrDefault <RallyPoint>());
 }
Esempio n. 6
0
        public TestSampledRegression(double _dnu)
        {
            {
                TestName     = "Модель семплированной регрессии";
                TestFileName = "SampledRegression";

                Vector <double> a = Exts.Vector(0.3, 0.4, 0.7);
                Vector <double> b = Exts.Vector(1.4, 3.0, 3.0);
                Vector <double> c = Exts.Vector(0.9, 1.5, 2.5);
                Vector <double> d = Exts.Vector(0.33, 0.37, 0.3);
                Vector <double> m = Exts.Vector(b[0] / (1 - a[0]), b[1] / (1 - a[1]), b[2] / (1 - a[2]));
                Vector <double> S = Exts.Vector(c[0] / Math.Sqrt(1 - a[0] * a[0]), c[1] / Math.Sqrt(1 - a[1] * a[1]), c[2] / Math.Sqrt(1 - a[2] * a[2]));

                Func <double, int> I = x =>
                {
                    if (x < 3)
                    {
                        return(0);
                    }
                    else if (x < 7)
                    {
                        return(1);
                    }
                    else
                    {
                        return(2);
                    }
                };

                Vector <double> mW = Exts.Vector(0); Matrix <double> dW = Exts.Diag(1.0);
                Vector <double> mNu = Exts.Vector(0); Matrix <double> dNu = Exts.Diag(_dnu);
                Vector <double> mEta = Exts.Vector(0); Matrix <double> dEta = Exts.Diag(1.0);
                Func <int, Vector <double>, Vector <double> > phi1 = (s, x) => Exts.Vector(a[I(x[0])] * x[0] + b[I(x[0])]);
                Func <int, Vector <double>, Matrix <double> > phi2 = (s, x) => Exts.Matrix(c[I(x[0])]);
                Func <int, Vector <double>, Vector <double> > psi  = (s, x) => Exts.Vector(x[0]);

                //Phi1_latex = new string[] { @"a^T e(x_t) x_t + b^T e(x_t)" };
                //Phi2_latex = new string[][] { new string[] { @"c^T e(x_t)" } };
                //Psi1_latex = new string[] { @"x_t" };

                //P_W = @"\mathcal{N}\left(" + mW.ToLatex() + ", " + dW.ToLatex() + @"\right)";
                //P_Nu = @"\mathcal{N}\left(" + mNu.ToLatex() + ", " + dNu.ToLatex() + @"\right)";
                //P_Eta = @"\mathcal{N}\left(" + mEta.ToLatex() + ", " + dEta.ToLatex() + @"\right)";

                Normal[] NormalW = new Normal[1] {
                    new Normal(mW[0], Math.Sqrt(dW[0, 0]))
                };
                Normal[] NormalNu = new Normal[1] {
                    new Normal(mNu[0], Math.Sqrt(dNu[0, 0]))
                };
                Normal[] NormalEta = new Normal[1] {
                    new Normal(mEta[0], Math.Sqrt(dEta[0, 0]))
                };

                //Expression<Func<int, Vector<double>, Vector<double>>> expr = (s, x) => Vector(x[0] / (1 + x[0] * x[0]), x[1] / (1 + x[1] * x[1])); ;

                Phi1 = phi1;
                Phi2 = phi2;
                Psi1 = psi;
                //Xi = (s, x) => phi1(s, x) + phi2(s, x) * mW;
                Xi = (s, x) =>
                {
                    double num = 0;
                    double den = 0;
                    for (int i = 0; i < a.Count; i++)
                    {
                        num += d[i] * Normal.PDF(m[i], S[i], x[0]) * (a[i] * x[0] + b[i]);
                        den += d[i] * Normal.PDF(m[i], S[i], x[0]);
                    }
                    return(Exts.Vector(num / den));
                };
                Zeta   = (s, x, y, k) => y - psi(s, x) - mNu;
                W      = (s) => Exts.Vector(NormalW[0].Sample());
                Nu     = (s) => Exts.Vector(NormalNu[0].Sample());
                DW     = dW;
                DNu    = dNu;
                X0     = () => Exts.Vector(NormalEta[0].Sample());
                X0Hat  = mEta;
                DX0Hat = dEta;
            }
        }
Esempio n. 7
0
        int HomingInnerTick(int predClfDist, int diffClfMslHgt, int relTarHorDist, int lastHtChg, int lastHt,
                            int nxtRelTarHorDist, int relTarHgt, int vFacing, bool targetPassedBy)
        {
            int desiredVFacing = vFacing;

            // Incline coming up -> attempt to reach the incline so that after predClfDist
            // the height above the terrain is positive but as close to 0 as possible
            // Also, never change horizontal facing and never travel backwards
            // Possible techniques to avoid close cliffs are deceleration, turning
            // as sharply as possible to travel directly upwards and then returning
            // to zero vertical facing as low as possible while still not hitting the
            // high terrain. A last technique (and the preferred one, normally used when
            // the missile hasn't been fired near a cliff) is simply finding the smallest
            // vertical facing that allows for a smooth climb to the new terrain's height
            // and coming in at predClfDist at exactly zero vertical facing
            if (info.TerrainHeightAware && diffClfMslHgt >= 0 && !allowPassBy)
            {
                desiredVFacing = IncreaseAltitude(predClfDist, diffClfMslHgt, relTarHorDist, vFacing);
            }
            else if (relTarHorDist <= 3 * loopRadius || state == States.Hitting)
            {
                // No longer travel at cruise altitude
                state = States.Hitting;

                if (lastHt >= targetPosition.Z)
                {
                    allowPassBy = true;
                }

                if (!allowPassBy && (lastHt < targetPosition.Z || targetPassedBy))
                {
                    // Aim for the target
                    var vDist = new WVec(-relTarHgt, -relTarHorDist, 0);
                    desiredVFacing = (sbyte)vDist.HorizontalLengthSquared != 0 ? vDist.Yaw.Facing : vFacing;

                    // Do not accept -1  as valid vertical facing since it is usually a numerical error
                    // and will lead to premature descent and crashing into the ground
                    if (desiredVFacing == -1)
                    {
                        desiredVFacing = 0;
                    }

                    // If the target has been passed by, limit the absolute value of
                    // vertical facing by the maximum vertical rate of turn
                    // Do this because the missile will be looping horizontally
                    // and thus needs smaller vertical facings so as not
                    // to hit the ground prematurely
                    if (targetPassedBy)
                    {
                        desiredVFacing = desiredVFacing.Clamp(-info.VerticalRateOfTurn.Facing, info.VerticalRateOfTurn.Facing);
                    }
                    else if (lastHt == 0)
                    {                     // Before the target is passed by, missile speed should be changed
                        // Target's height above loop's center
                        var tarHgt = (loopRadius * WAngle.FromFacing(vFacing).Cos() / 1024 - System.Math.Abs(relTarHgt)).Clamp(0, loopRadius);

                        // Target's horizontal distance from loop's center
                        var tarDist = Exts.ISqrt(loopRadius * loopRadius - tarHgt * tarHgt);

                        // Missile's horizontal distance from loop's center
                        var missDist = loopRadius * WAngle.FromFacing(vFacing).Sin() / 1024;

                        // If the current height does not permit the missile
                        // to hit the target before passing it by, lower speed
                        // Otherwise, increase speed
                        if (relTarHorDist <= tarDist - System.Math.Sign(relTarHgt) * missDist)
                        {
                            ChangeSpeed(-1);
                        }
                        else
                        {
                            ChangeSpeed();
                        }
                    }
                }
                else if (allowPassBy || (lastHt != 0 && relTarHorDist - lastHtChg < loopRadius))
                {
                    // Only activate this part if target too close to cliff
                    allowPassBy = true;

                    // Vector from missile's current position pointing to the loop's center
                    var radius = new WVec(loopRadius, 0, 0)
                                 .Rotate(new WRot(WAngle.Zero, WAngle.Zero, WAngle.FromFacing(64 - vFacing)));

                    // Vector from loop's center to incline top hardcoded in height buffer zone
                    var edgeVector = new WVec(lastHtChg, lastHt - pos.Z, 0) - radius;

                    if (!targetPassedBy)
                    {
                        // Climb to critical height
                        if (relTarHorDist > 2 * loopRadius)
                        {
                            // Target's distance from cliff
                            var d1 = relTarHorDist - lastHtChg;
                            if (d1 < 0)
                            {
                                d1 = 0;
                            }
                            if (d1 > 2 * loopRadius)
                            {
                                return(0);
                            }

                            // Find critical height at which the missile must be once it is at one loopRadius
                            // away from the target
                            var h1 = loopRadius - Exts.ISqrt(d1 * (2 * loopRadius - d1)) - (pos.Z - lastHt);

                            if (h1 > loopRadius * (1024 - WAngle.FromFacing(vFacing).Cos()) / 1024)
                            {
                                desiredVFacing = WAngle.ArcTan(Exts.ISqrt(h1 * (2 * loopRadius - h1)), loopRadius - h1).Angle >> 2;
                            }
                            else
                            {
                                desiredVFacing = 0;
                            }

                            // TODO: deceleration checks!!!
                        }
                        else
                        {
                            // Avoid the cliff edge
                            if (info.TerrainHeightAware && edgeVector.Length > loopRadius && lastHt > targetPosition.Z)
                            {
                                int vFac;
                                for (vFac = vFacing + 1; vFac <= vFacing + info.VerticalRateOfTurn.Facing - 1; vFac++)
                                {
                                    // Vector from missile's current position pointing to the loop's center
                                    radius = new WVec(loopRadius, 0, 0)
                                             .Rotate(new WRot(WAngle.Zero, WAngle.Zero, WAngle.FromFacing(64 - vFac)));

                                    // Vector from loop's center to incline top + 64 hardcoded in height buffer zone
                                    edgeVector = new WVec(lastHtChg, lastHt - pos.Z, 0) - radius;
                                    if (edgeVector.Length <= loopRadius)
                                    {
                                        break;
                                    }
                                }

                                desiredVFacing = vFac;
                            }
                            else
                            {
                                // Aim for the target
                                var vDist = new WVec(-relTarHgt, -relTarHorDist, 0);
                                desiredVFacing = (sbyte)vDist.HorizontalLengthSquared != 0 ? vDist.Yaw.Facing : vFacing;
                                if (desiredVFacing < 0 && info.VerticalRateOfTurn.Facing < (sbyte)vFacing)
                                {
                                    desiredVFacing = 0;
                                }
                            }
                        }
                    }
                    else
                    {
                        // Aim for the target
                        var vDist = new WVec(-relTarHgt, relTarHorDist, 0);
                        desiredVFacing = (sbyte)vDist.HorizontalLengthSquared != 0 ? vDist.Yaw.Facing : vFacing;
                        if (desiredVFacing < 0 && info.VerticalRateOfTurn.Facing < (sbyte)vFacing)
                        {
                            desiredVFacing = 0;
                        }
                    }
                }
                else
                {
                    // Aim to attain cruise altitude as soon as possible while having the absolute value
                    // of vertical facing bound by the maximum vertical rate of turn
                    var vDist = new WVec(-diffClfMslHgt - info.CruiseAltitude.Length, -speed, 0);
                    desiredVFacing = (sbyte)vDist.HorizontalLengthSquared != 0 ? vDist.Yaw.Facing : vFacing;

                    // If the missile is launched above CruiseAltitude, it has to descend instead of climbing
                    if (-diffClfMslHgt > info.CruiseAltitude.Length)
                    {
                        desiredVFacing = -desiredVFacing;
                    }

                    desiredVFacing = desiredVFacing.Clamp(-info.VerticalRateOfTurn.Facing, info.VerticalRateOfTurn.Facing);

                    ChangeSpeed();
                }
            }
            else
            {
                // Aim to attain cruise altitude as soon as possible while having the absolute value
                // of vertical facing bound by the maximum vertical rate of turn
                var vDist = new WVec(-diffClfMslHgt - info.CruiseAltitude.Length, -speed, 0);
                desiredVFacing = (sbyte)vDist.HorizontalLengthSquared != 0 ? vDist.Yaw.Facing : vFacing;

                // If the missile is launched above CruiseAltitude, it has to descend instead of climbing
                if (-diffClfMslHgt > info.CruiseAltitude.Length)
                {
                    desiredVFacing = -desiredVFacing;
                }

                desiredVFacing = desiredVFacing.Clamp(-info.VerticalRateOfTurn.Facing, info.VerticalRateOfTurn.Facing);

                ChangeSpeed();
            }

            return(desiredVFacing);
        }
Esempio n. 8
0
 public Power(Actor self, PowerInfo info)
     : base(info)
 {
     PlayerPower    = self.Owner.PlayerActor.Trait <PowerManager>();
     powerModifiers = Exts.Lazy(() => self.TraitsImplementing <IPowerModifier>().ToArray());
 }
Esempio n. 9
0
 public LabelForInputWidget()
     : base()
 {
     inputWidget = Exts.Lazy(() => Parent.Get <InputWidget>(For));
     textColor   = new CachedTransform <bool, Color>(disabled => disabled ? TextDisabledColor : TextColor);
 }
Esempio n. 10
0
 public LabelWithTooltipWidget(World world)
     : base()
 {
     tooltipContainer = Exts.Lazy(() =>
                                  Ui.Root.Get <TooltipContainerWidget>(TooltipContainer));
 }
Esempio n. 11
0
 public EditorViewportControllerWidget(World world, WorldRenderer worldRenderer)
 {
     this.worldRenderer = worldRenderer;
     tooltipContainer   = Exts.Lazy(() => Ui.Root.Get <TooltipContainerWidget>(TooltipContainer));
     CurrentBrush       = DefaultBrush = new EditorDefaultBrush(this, worldRenderer);
 }
Esempio n. 12
0
        static bool SlotBot(S server, Connection conn, Session.Client client, string 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);
            }

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

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

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

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

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

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

            S.SyncClientToPlayerReference(bot, server.Map.Players.Players[parts[0]]);
            server.SyncLobbyClients();
            server.SyncLobbySlots();

            return(true);
        }
Esempio n. 13
0
        public VqaReader(Stream stream)
        {
            this.stream = stream;

            // Decode FORM chunk
            if (stream.ReadASCII(4) != "FORM")
            {
                throw new InvalidDataException("Invalid vqa (invalid FORM section)");
            }
            /*var length = */ stream.ReadUInt32();

            if (stream.ReadASCII(8) != "WVQAVQHD")
            {
                throw new InvalidDataException("Invalid vqa (not WVQAVQHD)");
            }
            /* var length = */ stream.ReadUInt32();

            /*var version = */ stream.ReadUInt16();
            /*var flags = */ stream.ReadUInt16();
            Frames = stream.ReadUInt16();
            Width  = stream.ReadUInt16();
            Height = stream.ReadUInt16();

            blockWidth  = stream.ReadUInt8();
            blockHeight = stream.ReadUInt8();
            Framerate   = stream.ReadUInt8();
            cbParts     = stream.ReadUInt8();
            blocks      = new int2(Width / blockWidth, Height / blockHeight);

            numColors = stream.ReadUInt16();
            /*var maxBlocks = */ stream.ReadUInt16();
            /*var unknown1 = */ stream.ReadUInt16();
            /*var unknown2 = */ stream.ReadUInt32();

            // Audio
            /*var freq = */ stream.ReadUInt16();
            /*var channels = */ stream.ReadByte();
            /*var bits = */ stream.ReadByte();
            /*var unknown3 = */ stream.ReadBytes(14);

            var frameSize = Exts.NextPowerOf2(Math.Max(Width, Height));

            cbf       = new byte[Width * Height];
            cbp       = new byte[Width * Height];
            palette   = new uint[numColors];
            origData  = new byte[2 * blocks.X * blocks.Y];
            frameData = new uint[frameSize, frameSize];

            var type = stream.ReadASCII(4);

            if (type != "FINF")
            {
                stream.Seek(27, SeekOrigin.Current);
                type = stream.ReadASCII(4);
            }

            /*var length = */ stream.ReadUInt16();
            /*var unknown4 = */ stream.ReadUInt16();

            // Frame offsets
            offsets = new UInt32[Frames];
            for (var i = 0; i < Frames; i++)
            {
                offsets[i] = stream.ReadUInt32();
                if (offsets[i] > 0x40000000)
                {
                    offsets[i] -= 0x40000000;
                }
                offsets[i] <<= 1;
            }

            CollectAudioData();

            Reset();
        }
Esempio n. 14
0
        public override void Draw()
        {
            if (world.LocalPlayer == null)
            {
                return;
            }
            if (world.LocalPlayer.WinState != WinState.Undefined)
            {
                return;
            }

            var radarBin = Ui.Root.GetWidget <RadarBinWidget>(RadarBin);

            powerCollection = "power-" + world.LocalPlayer.Country.Race;

            // Nothing to draw
            if (power.PowerProvided == 0 && power.PowerDrained == 0)
            {
                return;
            }

            // Draw bar horizontally
            var barStart = powerOrigin + radarBin.RadarOrigin;
            var barEnd   = barStart + new float2(powerSize.Width, 0);

            float powerScaleBy = 100;
            var   maxPower     = Math.Max(power.PowerProvided, power.PowerDrained);

            while (maxPower >= powerScaleBy)
            {
                powerScaleBy *= 2;
            }

            // Current power supply
            var powerLevelTemp = barStart.X + (barEnd.X - barStart.X) * (power.PowerProvided / powerScaleBy);

            lastPowerProvidedPos = float2.Lerp(lastPowerProvidedPos.GetValueOrDefault(powerLevelTemp), powerLevelTemp, PowerBarLerpFactor);
            var powerLevel = new float2(lastPowerProvidedPos.Value, barStart.Y);

            var color = GetPowerColor(power);

            var colorDark = Exts.ColorLerp(0.25f, color, Color.Black);

            for (int i = 0; i < powerSize.Height; i++)
            {
                color = (i - 1 < powerSize.Height / 2) ? color : colorDark;
                var leftOffset  = new float2(0, i);
                var rightOffset = new float2(0, i);
                // Indent corners
                if ((i == 0 || i == powerSize.Height - 1) && powerLevel.X - barStart.X > 1)
                {
                    leftOffset.X  += 1;
                    rightOffset.X -= 1;
                }
                Game.Renderer.LineRenderer.DrawLine(barStart + leftOffset, powerLevel + rightOffset, color, color);
            }

            // Power usage indicator
            var indicator        = ChromeProvider.GetImage(powerCollection, "power-indicator");
            var powerDrainedTemp = barStart.X + (barEnd.X - barStart.X) * (power.PowerDrained / powerScaleBy);

            lastPowerDrainedPos = float2.Lerp(lastPowerDrainedPos.GetValueOrDefault(powerDrainedTemp), powerDrainedTemp, PowerBarLerpFactor);
            var powerDrainLevel = new float2(lastPowerDrainedPos.Value - indicator.size.X / 2, barStart.Y - 1);

            Game.Renderer.RgbaSpriteRenderer.DrawSprite(indicator, powerDrainLevel);
        }
Esempio n. 15
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();
        }
Esempio n. 16
0
 protected LabelForInputWidget(LabelForInputWidget other)
     : base(other)
 {
     inputWidget = Exts.Lazy(() => Parent.Get <InputWidget>(other.For));
     textColor   = new CachedTransform <bool, Color>(disabled => disabled ? TextDisabledColor : TextColor);
 }
Esempio n. 17
0
        Action InitDisplayPanel(Widget panel)
        {
            var ds = Game.Settings.Graphics;
            var gs = Game.Settings.Game;

            BindCheckboxPref(panel, "HARDWARECURSORS_CHECKBOX", ds, "HardwareCursors");
            BindCheckboxPref(panel, "PIXELDOUBLE_CHECKBOX", ds, "PixelDouble");
            BindCheckboxPref(panel, "CURSORDOUBLE_CHECKBOX", ds, "CursorDouble");
            BindCheckboxPref(panel, "FRAME_LIMIT_CHECKBOX", ds, "CapFramerate");
            BindCheckboxPref(panel, "SHOW_SHELLMAP", gs, "ShowShellmap");
            BindCheckboxPref(panel, "DISPLAY_TARGET_LINES_CHECKBOX", gs, "DrawTargetLine");
            BindCheckboxPref(panel, "PLAYER_STANCE_COLORS_CHECKBOX", gs, "UsePlayerStanceColors");

            var languageDropDownButton = panel.Get <DropDownButtonWidget>("LANGUAGE_DROPDOWNBUTTON");

            languageDropDownButton.OnMouseDown = _ => ShowLanguageDropdown(languageDropDownButton, modData.Languages);
            languageDropDownButton.GetText     = () => FieldLoader.Translate(ds.Language);

            var windowModeDropdown = panel.Get <DropDownButtonWidget>("MODE_DROPDOWN");

            windowModeDropdown.OnMouseDown = _ => ShowWindowModeDropdown(windowModeDropdown, ds);
            windowModeDropdown.GetText     = () => ds.Mode == WindowMode.Windowed ?
                                             "Windowed" : ds.Mode == WindowMode.Fullscreen ? "Fullscreen" : "Pseudo-Fullscreen";

            var statusBarsDropDown = panel.Get <DropDownButtonWidget>("STATUS_BAR_DROPDOWN");

            statusBarsDropDown.OnMouseDown = _ => ShowStatusBarsDropdown(statusBarsDropDown, gs);
            statusBarsDropDown.GetText     = () => gs.StatusBars.ToString() == "Standard" ?
                                             "Standard" : gs.StatusBars.ToString() == "DamageShow" ? "Show On Damage" : "Always Show";

            // Update zoom immediately
            var pixelDoubleCheckbox = panel.Get <CheckboxWidget>("PIXELDOUBLE_CHECKBOX");
            var pixelDoubleOnClick  = pixelDoubleCheckbox.OnClick;

            pixelDoubleCheckbox.OnClick = () =>
            {
                pixelDoubleOnClick();
                worldRenderer.Viewport.Zoom = ds.PixelDouble ? 2 : 1;
            };

            // Cursor doubling is only supported with software cursors and when pixel doubling is enabled
            var cursorDoubleCheckbox = panel.Get <CheckboxWidget>("CURSORDOUBLE_CHECKBOX");

            cursorDoubleCheckbox.IsDisabled = () => !ds.PixelDouble || Game.Cursor is HardwareCursor;

            var cursorDoubleIsChecked = cursorDoubleCheckbox.IsChecked;

            cursorDoubleCheckbox.IsChecked = () => !cursorDoubleCheckbox.IsDisabled() && cursorDoubleIsChecked();

            panel.Get("WINDOW_RESOLUTION").IsVisible = () => ds.Mode == WindowMode.Windowed;
            var windowWidth = panel.Get <TextFieldWidget>("WINDOW_WIDTH");

            windowWidth.Text = ds.WindowedSize.X.ToString();

            var windowHeight = panel.Get <TextFieldWidget>("WINDOW_HEIGHT");

            windowHeight.Text = ds.WindowedSize.Y.ToString();

            var frameLimitTextfield = panel.Get <TextFieldWidget>("FRAME_LIMIT_TEXTFIELD");

            frameLimitTextfield.Text = ds.MaxFramerate.ToString();
            var escPressed = false;

            frameLimitTextfield.OnLoseFocus = () =>
            {
                if (escPressed)
                {
                    escPressed = false;
                    return;
                }

                int fps;
                Exts.TryParseIntegerInvariant(frameLimitTextfield.Text, out fps);
                ds.MaxFramerate          = fps.Clamp(1, 1000);
                frameLimitTextfield.Text = ds.MaxFramerate.ToString();
            };

            frameLimitTextfield.OnEnterKey = () => { frameLimitTextfield.YieldKeyboardFocus(); return(true); };
            frameLimitTextfield.OnEscKey   = () =>
            {
                frameLimitTextfield.Text = ds.MaxFramerate.ToString();
                escPressed = true;
                frameLimitTextfield.YieldKeyboardFocus();
                return(true);
            };

            frameLimitTextfield.IsDisabled = () => !ds.CapFramerate;

            // Player profile
            var ps = Game.Settings.Player;

            var nameTextfield = panel.Get <TextFieldWidget>("PLAYERNAME");

            nameTextfield.IsDisabled  = () => worldRenderer.World.Type != WorldType.Shellmap;
            nameTextfield.Text        = Settings.SanitizedPlayerName(ps.Name);
            nameTextfield.OnLoseFocus = () =>
            {
                if (escPressed)
                {
                    escPressed = false;
                    return;
                }

                nameTextfield.Text = nameTextfield.Text.Trim();
                if (nameTextfield.Text.Length == 0)
                {
                    nameTextfield.Text = Settings.SanitizedPlayerName(ps.Name);
                }
                else
                {
                    nameTextfield.Text = Settings.SanitizedPlayerName(nameTextfield.Text);
                    ps.Name            = nameTextfield.Text;
                }
            };

            nameTextfield.OnEnterKey = () => { nameTextfield.YieldKeyboardFocus(); return(true); };
            nameTextfield.OnEscKey   = () =>
            {
                nameTextfield.Text = Settings.SanitizedPlayerName(ps.Name);
                escPressed         = true;
                nameTextfield.YieldKeyboardFocus();
                return(true);
            };

            var colorPreview = panel.Get <ColorPreviewManagerWidget>("COLOR_MANAGER");

            colorPreview.Color = ps.Color;

            var colorDropdown = panel.Get <DropDownButtonWidget>("PLAYERCOLOR");

            colorDropdown.IsDisabled  = () => worldRenderer.World.Type != WorldType.Shellmap;
            colorDropdown.OnMouseDown = _ => ColorPickerLogic.ShowColorDropDown(colorDropdown, colorPreview, worldRenderer.World);
            colorDropdown.Get <ColorBlockWidget>("COLORBLOCK").GetColor = () => ps.Color.RGB;

            return(() =>
            {
                int x, y;
                Exts.TryParseIntegerInvariant(windowWidth.Text, out x);
                Exts.TryParseIntegerInvariant(windowHeight.Text, out y);
                ds.WindowedSize = new int2(x, y);
                frameLimitTextfield.YieldKeyboardFocus();
                nameTextfield.YieldKeyboardFocus();
            });
        }
Esempio n. 18
0
        public DefaultSpriteSequence(ModData modData, TileSet tileSet, SpriteCache cache, ISpriteSequenceLoader loader, string sequence, string animation, MiniYaml info)
        {
            Name   = animation;
            Loader = loader;
            var d = info.ToDictionary();

            try
            {
                Start         = LoadField <int>(d, "Start", 0);
                ShadowStart   = LoadField <int>(d, "ShadowStart", -1);
                ShadowZOffset = LoadField <WDist>(d, "ShadowZOffset", DefaultShadowSpriteZOffset).Length;
                ZOffset       = LoadField <WDist>(d, "ZOffset", WDist.Zero).Length;
                Tick          = LoadField <int>(d, "Tick", 40);
                transpose     = LoadField <bool>(d, "Transpose", false);
                Frames        = LoadField <int[]>(d, "Frames", null);

                Facings = LoadField <int>(d, "Facings", 1);
                if (Facings < 0)
                {
                    reverseFacings = true;
                    Facings        = -Facings;
                }

                var offset    = LoadField <float2>(d, "Offset", float2.Zero);
                var blendMode = LoadField <BlendMode>(d, "BlendMode", BlendMode.Alpha);

                MiniYaml combine;
                if (d.TryGetValue("Combine", out combine))
                {
                    var combined = Enumerable.Empty <Sprite>();
                    foreach (var sub in combine.Nodes)
                    {
                        var sd = sub.Value.ToDictionary();

                        // Allow per-sprite offset, start, and length
                        var subStart  = LoadField <int>(sd, "Start", 0);
                        var subOffset = LoadField <float2>(sd, "Offset", float2.Zero);

                        var subSrc     = GetSpriteSrc(modData, tileSet, sequence, animation, sub.Key, sd);
                        var subSprites = cache[subSrc].Select(
                            s => new Sprite(s.Sheet, s.Bounds, s.Offset + subOffset + offset, s.Channel, blendMode));

                        var      subLength = 0;
                        MiniYaml subLengthYaml;
                        if (sd.TryGetValue("Length", out subLengthYaml) && subLengthYaml.Value == "*")
                        {
                            subLength = subSprites.Count() - subStart;
                        }
                        else
                        {
                            subLength = LoadField <int>(sd, "Length", 1);
                        }

                        combined = combined.Concat(subSprites.Skip(subStart).Take(subLength));
                    }

                    sprites = combined.ToArray();
                }
                else
                {
                    // Apply offset to each sprite in the sequence
                    // Different sequences may apply different offsets to the same frame
                    var src = GetSpriteSrc(modData, tileSet, sequence, animation, info.Value, d);
                    sprites = cache[src].Select(
                        s => new Sprite(s.Sheet, s.Bounds, s.Offset + offset, s.Channel, blendMode)).ToArray();
                }

                MiniYaml length;
                if (d.TryGetValue("Length", out length) && length.Value == "*")
                {
                    Length = sprites.Length - Start;
                }
                else
                {
                    Length = LoadField <int>(d, "Length", 1);
                }

                // Plays the animation forwards, and then in reverse
                if (LoadField <bool>(d, "Reverses", false))
                {
                    var frames = Frames ?? Exts.MakeArray(Length, i => Start + i);
                    Frames = frames.Concat(frames.Skip(1).Take(frames.Length - 2).Reverse()).ToArray();
                    Length = 2 * Length - 2;
                }

                Stride = LoadField <int>(d, "Stride", Length);

                if (Length > Stride)
                {
                    throw new InvalidOperationException(
                              "{0}: Sequence {1}.{2}: Length must be <= stride"
                              .F(info.Nodes[0].Location, sequence, animation));
                }

                if (Start < 0 || Start + Facings * Stride > sprites.Length)
                {
                    throw new InvalidOperationException(
                              "{5}: Sequence {0}.{1} uses frames [{2}..{3}], but only 0..{4} actually exist"
                              .F(sequence, animation, Start, Start + Facings * Stride - 1, sprites.Length - 1,
                                 info.Nodes[0].Location));
                }

                if (ShadowStart + Facings * Stride > sprites.Length)
                {
                    throw new InvalidOperationException(
                              "{5}: Sequence {0}.{1}'s shadow frames use frames [{2}..{3}], but only [0..{4}] actually exist"
                              .F(sequence, animation, ShadowStart, ShadowStart + Facings * Stride - 1, sprites.Length - 1,
                                 info.Nodes[0].Location));
                }
            }
            catch (FormatException f)
            {
                throw new FormatException("Failed to parse sequences for {0}.{1} at {2}:\n{3}".F(sequence, animation, info.Nodes[0].Location, f));
            }
        }
Esempio n. 19
0
        int IncreaseAltitude(int predClfDist, int diffClfMslHgt, int relTarHorDist, int vFacing)
        {
            var desiredVFacing = vFacing;

            // If missile is below incline top height and facing downwards, bring back
            // its vertical facing above zero as soon as possible
            if ((sbyte)vFacing < 0)
            {
                desiredVFacing = info.VerticalRateOfTurn.Facing;
            }

            // Missile will climb around incline top if bringing vertical facing
            // down to zero on an arc of radius loopRadius
            else if (IsNearInclineTop(vFacing, loopRadius, predClfDist) &&
                     WillClimbAroundInclineTop(vFacing, loopRadius, predClfDist, diffClfMslHgt, speed))
            {
                desiredVFacing = 0;
            }

            // Missile will not climb terrAltDiff w-units within hHeightChange w-units
            // all the while ending the ascent with vertical facing 0
            else if (!WillClimbWithinDistance(vFacing, loopRadius, predClfDist, diffClfMslHgt))
            {
                // Find smallest vertical facing, attainable in the next tick,
                // for which the missile will be able to climb terrAltDiff w-units
                // within hHeightChange w-units all the while ending the ascent
                // with vertical facing 0
                for (var vFac = System.Math.Min(vFacing + info.VerticalRateOfTurn.Facing - 1, 63); vFac >= vFacing; vFac--)
                {
                    if (!WillClimbWithinDistance(vFac, loopRadius, predClfDist, diffClfMslHgt) &&
                        !(predClfDist <= loopRadius * (1024 - WAngle.FromFacing(vFac).Sin()) / 1024 &&
                          WillClimbAroundInclineTop(vFac, loopRadius, predClfDist, diffClfMslHgt, speed)))
                    {
                        desiredVFacing = vFac + 1;
                        break;
                    }
                }
            }

            // Attained height after ascent as predicted from upper part of incline surmounting manoeuvre
            var predAttHght = loopRadius * (1024 - WAngle.FromFacing(vFacing).Cos()) / 1024 - diffClfMslHgt;

            // Should the missile be slowed down in order to make it more maneuverable
            var slowDown = info.Acceleration.Length != 0 &&          // Possible to decelerate
                           ((desiredVFacing != 0 // Lower part of incline surmounting manoeuvre

                                                 // Incline will be hit before vertical facing attains 64
                             && (predClfDist <= loopRadius * (1024 - WAngle.FromFacing(vFacing).Sin()) / 1024

                                 // When evaluating this the incline will be *not* be hit before vertical facing attains 64
                                 // At current speed target too close to hit without passing it by
                                 || relTarHorDist <= 2 * loopRadius * (2048 - WAngle.FromFacing(vFacing).Sin()) / 1024 - predClfDist))

                            || (desiredVFacing == 0 &&          // Upper part of incline surmounting manoeuvre
                                relTarHorDist <= loopRadius * WAngle.FromFacing(vFacing).Sin() / 1024
                                + Exts.ISqrt(predAttHght * (2 * loopRadius - predAttHght))));                         // Target too close to hit at current speed

            if (slowDown)
            {
                ChangeSpeed(-1);
            }

            return(desiredVFacing);
        }
Esempio n. 20
0
        public Theater(TileSet tileset, Action <uint, string> onMissingImage = null)
        {
            this.tileset = tileset;
            var allocated = false;

            Func <Sheet> allocate = () =>
            {
                if (allocated)
                {
                    throw new SheetOverflowException("Terrain sheet overflow. Try increasing the tileset SheetSize parameter.");
                }
                allocated = true;

                return(new Sheet(SheetType.Indexed, new Size(tileset.SheetSize, tileset.SheetSize)));
            };

            random = new MersenneTwister();

            var frameCache = new FrameCache(Game.ModData.DefaultFileSystem, Game.ModData.SpriteLoaders);

            foreach (var t in tileset.Templates)
            {
                var variants = new List <Sprite[]>();

                foreach (var i in t.Value.Images)
                {
                    ISpriteFrame[] allFrames;
                    if (onMissingImage != null)
                    {
                        try
                        {
                            allFrames = frameCache[i];
                        }
                        catch (FileNotFoundException)
                        {
                            onMissingImage(t.Key, i);
                            continue;
                        }
                    }
                    else
                    {
                        allFrames = frameCache[i];
                    }

                    var frameCount = tileset.EnableDepth ? allFrames.Length / 2 : allFrames.Length;
                    var indices    = t.Value.Frames != null ? t.Value.Frames : Exts.MakeArray(t.Value.TilesCount, j => j);

                    var start = indices.Min();
                    var end   = indices.Max();
                    if (start < 0 || end >= frameCount)
                    {
                        throw new YamlException("Template `{0}` uses frames [{1}..{2}] of {3}, but only [0..{4}] actually exist"
                                                .F(t.Key, start, end, i, frameCount - 1));
                    }

                    variants.Add(indices.Select(j =>
                    {
                        var f    = allFrames[j];
                        var tile = t.Value.Contains(j) ? t.Value[j] : null;

                        // The internal z axis is inverted from expectation (negative is closer)
                        var zOffset = tile != null ? -tile.ZOffset : 0;
                        var zRamp   = tile != null ? tile.ZRamp : 1f;
                        var offset  = new float3(f.Offset, zOffset);
                        var type    = SheetBuilder.FrameTypeToSheetType(f.Type);

                        // Defer SheetBuilder creation until we know what type of frames we are loading!
                        // TODO: Support mixed indexed and BGRA frames
                        if (sheetBuilder == null)
                        {
                            sheetBuilder = new SheetBuilder(SheetBuilder.FrameTypeToSheetType(f.Type), allocate);
                        }
                        else if (type != sheetBuilder.Type)
                        {
                            throw new YamlException("Sprite type mismatch. Terrain sprites must all be either Indexed or RGBA.");
                        }

                        var s = sheetBuilder.Allocate(f.Size, zRamp, offset);
                        Util.FastCopyIntoChannel(s, f.Data);

                        if (tileset.EnableDepth)
                        {
                            var ss = sheetBuilder.Allocate(f.Size, zRamp, offset);
                            Util.FastCopyIntoChannel(ss, allFrames[j + frameCount].Data);

                            // s and ss are guaranteed to use the same sheet
                            // because of the custom terrain sheet allocation
                            s = new SpriteWithSecondaryData(s, s.Sheet, ss.Bounds, ss.Channel);
                        }

                        return(s);
                    }).ToArray());
                }

                var allSprites = variants.SelectMany(s => s);

                // Ignore the offsets baked into R8 sprites
                if (tileset.IgnoreTileSpriteOffsets)
                {
                    allSprites = allSprites.Select(s => new Sprite(s.Sheet, s.Bounds, s.ZRamp, new float3(float2.Zero, s.Offset.Z), s.Channel, s.BlendMode));
                }

                if (onMissingImage != null && !variants.Any())
                {
                    continue;
                }

                templates.Add(t.Value.Id, new TheaterTemplate(allSprites.ToArray(), variants.First().Count(), t.Value.Images.Length));
            }

            // 1x1px transparent tile
            missingTile = sheetBuilder.Add(new byte[sheetBuilder.Type == SheetType.BGRA ? 4 : 1], new Size(1, 1));

            Sheet.ReleaseBuffer();
        }
 public ClientTooltipRegionWidget()
 {
     tooltipContainer = Exts.Lazy(() => Ui.Root.Get <TooltipContainerWidget>(TooltipContainer));
 }
Esempio n. 22
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.NonBotPlayers.Count() < 2)
                      {
                          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.Team       = 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);
                      }

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

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

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

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

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

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

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

                      var lastMap = server.LobbyInfo.GlobalSettings.Map;
                      Action <MapPreview> selectMap = map =>
                      {
                          // 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 botTypes = server.Map.Rules.Actors["player"].TraitInfos <IBotInfo>().Select(t => t.Type);
                          var slots    = server.LobbyInfo.Slots.Keys.ToArray();
                          var i        = 0;
                          foreach (var os in oldSlots)
                          {
                              var c = server.LobbyInfo.ClientInSlot(os);
                              if (c == null)
                              {
                                  continue;
                              }

                              c.SpawnPoint = 0;
                              c.Slot       = i < slots.Length ? slots[i++] : null;
                              if (c.Slot != null)
                              {
                                  // Remove Bot from slot if slot forbids bots
                                  if (c.Bot != null && (!server.Map.Players.Players[c.Slot].AllowBots || !botTypes.Contains(c.Bot)))
                                  {
                                      server.LobbyInfo.Clients.Remove(c);
                                  }
                                  S.SyncClientToPlayerReference(c, server.Map.Players.Players[c.Slot]);
                              }
                              else if (c.Bot != null)
                              {
                                  server.LobbyInfo.Clients.Remove(c);
                              }
                          }

                          // Validate if color is allowed and get an alternative if it isn't
                          foreach (var c in server.LobbyInfo.Clients)
                          {
                              if (c.Slot != null && !server.LobbyInfo.Slots[c.Slot].LockColor)
                              {
                                  c.Color = c.PreferredColor = SanitizePlayerColor(server, c.Color, c.Index, conn);
                              }
                          }

                          server.SyncLobbyInfo();

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

                          if (server.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...");
                          var mapRepository = server.ModData.Manifest.Get <WebServices>().MapRepository;
                          server.ModData.MapCache.QueryRemoteMapDetails(mapRepository, 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.IsLocked)
                      {
                          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));
        }
Esempio n. 23
0
 public ProductionParadrop(ActorInitializer init, ProductionParadropInfo info)
     : base(init, info)
 {
     rp = Exts.Lazy(() => init.Self.IsDead ? null : init.Self.TraitOrDefault <RallyPoint>());
 }
Esempio n. 24
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();
            }
        }
 public Production(ActorInitializer init, ProductionInfo info)
     : base(info)
 {
     rp      = Exts.Lazy(() => init.Self.IsDead ? null : init.Self.TraitOrDefault <RallyPoint>());
     Faction = init.Contains <FactionInit>() ? init.Get <FactionInit, string>() : init.Self.Owner.Faction.InternalName;
 }
Esempio n. 26
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(',');
                    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(facing));
                    }

                    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.ActorDefinitions.Add(new MiniYamlNode("Actor" + actorCount++, actor.Save()));
                    }
                }
                catch (Exception)
                {
                    errorHandler("Malformed actor definition: `{0}`".F(s));
                }
            }
        }
Esempio n. 27
0
 public ResourceBarWidget(World world)
 {
     tooltipContainer = Exts.Lazy(() =>
                                  Ui.Root.Get <TooltipContainerWidget>(TooltipContainer));
 }
Esempio n. 28
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, ""));
     }
 }
Esempio n. 29
0
        public DefaultSpriteSequence(ModData modData, string tileSet, SpriteCache cache, ISpriteSequenceLoader loader, string sequence, string animation, MiniYaml info)
        {
            this.sequence = sequence;
            Name          = animation;
            Loader        = loader;
            var d = info.ToDictionary();

            try
            {
                Start           = LoadField(d, "Start", 0);
                ShadowStart     = LoadField(d, "ShadowStart", -1);
                ShadowZOffset   = LoadField(d, "ShadowZOffset", DefaultShadowSpriteZOffset).Length;
                ZOffset         = LoadField(d, "ZOffset", WDist.Zero).Length;
                ZRamp           = LoadField(d, "ZRamp", 0);
                Tick            = LoadField(d, "Tick", 40);
                transpose       = LoadField(d, "Transpose", false);
                Frames          = LoadField <int[]>(d, "Frames", null);
                IgnoreWorldTint = LoadField(d, "IgnoreWorldTint", false);

                var flipX = LoadField(d, "FlipX", false);
                var flipY = LoadField(d, "FlipY", false);

                Facings = LoadField(d, "Facings", 1);
                if (Facings < 0)
                {
                    reverseFacings = true;
                    Facings        = -Facings;
                }

                var offset    = LoadField(d, "Offset", float3.Zero);
                var blendMode = LoadField(d, "BlendMode", BlendMode.Alpha);

                Func <int, IEnumerable <int> > getUsedFrames = frameCount =>
                {
                    if (d.TryGetValue("Length", out var length) && length.Value == "*")
                    {
                        Length = Frames != null ? Frames.Length : frameCount - Start;
                    }
                    else
                    {
                        Length = LoadField(d, "Length", 1);
                    }

                    // Plays the animation forwards, and then in reverse
                    if (LoadField(d, "Reverses", false))
                    {
                        var frames = Frames != null?Frames.Skip(Start).Take(Length).ToArray() : Exts.MakeArray(Length, i => Start + i);

                        Frames = frames.Concat(frames.Skip(1).Take(Length - 2).Reverse()).ToArray();
                        Length = 2 * Length - 2;
                        Start  = 0;
                    }

                    Stride = LoadField(d, "Stride", Length);

                    if (Length > Stride)
                    {
                        throw new YamlException("Sequence {0}.{1}: Length must be <= stride"
                                                .F(sequence, animation));
                    }

                    if (Frames != null && Length > Frames.Length)
                    {
                        throw new YamlException("Sequence {0}.{1}: Length must be <= Frames.Length"
                                                .F(sequence, animation));
                    }

                    var end = Start + (Facings - 1) * Stride + Length - 1;
                    if (Frames != null)
                    {
                        foreach (var f in Frames)
                        {
                            if (f < 0 || f >= frameCount)
                            {
                                throw new YamlException("Sequence {0}.{1} defines a Frames override that references frame {2}, but only [{3}..{4}] actually exist"
                                                        .F(sequence, animation, f, Start, end));
                            }
                        }

                        if (Start < 0 || end >= Frames.Length)
                        {
                            throw new YamlException("Sequence {0}.{1} uses indices [{2}..{3}] of the Frames list, but only {4} frames are defined"
                                                    .F(sequence, animation, Start, end, Frames.Length));
                        }
                    }
                    else if (Start < 0 || end >= frameCount)
                    {
                        throw new YamlException("Sequence {0}.{1} uses frames [{2}..{3}], but only [0..{4}] actually exist"
                                                .F(sequence, animation, Start, end, frameCount - 1));
                    }

                    if (ShadowStart >= 0 && ShadowStart + (Facings - 1) * Stride + Length > frameCount)
                    {
                        throw new YamlException("Sequence {0}.{1}'s shadow frames use frames [{2}..{3}], but only [0..{4}] actually exist"
                                                .F(sequence, animation, ShadowStart, ShadowStart + (Facings - 1) * Stride + Length - 1, frameCount - 1));
                    }

                    var usedFrames = new List <int>();
                    for (var facing = 0; facing < Facings; facing++)
                    {
                        for (var frame = 0; frame < Length; frame++)
                        {
                            var i = transpose ? (frame % Length) * Facings + facing :
                                    (facing * Stride) + (frame % Length);

                            usedFrames.Add(Frames != null ? Frames[i] : Start + i);
                        }
                    }

                    if (ShadowStart >= 0)
                    {
                        return(usedFrames.Concat(usedFrames.Select(i => i + ShadowStart - Start)));
                    }

                    return(usedFrames);
                };

                if (d.TryGetValue("Combine", out var combine))
                {
                    var combined = Enumerable.Empty <Sprite>();
                    foreach (var sub in combine.Nodes)
                    {
                        var sd = sub.Value.ToDictionary();

                        // Allow per-sprite offset, flipping, start, and length
                        var subStart  = LoadField(sd, "Start", 0);
                        var subOffset = LoadField(sd, "Offset", float3.Zero);
                        var subFlipX  = LoadField(sd, "FlipX", false);
                        var subFlipY  = LoadField(sd, "FlipY", false);
                        var subFrames = LoadField <int[]>(sd, "Frames", null);
                        var subLength = 0;

                        Func <int, IEnumerable <int> > subGetUsedFrames = subFrameCount =>
                        {
                            if (sd.TryGetValue("Length", out var subLengthYaml) && subLengthYaml.Value == "*")
                            {
                                subLength = subFrames != null ? subFrames.Length : subFrameCount - subStart;
                            }
                            else
                            {
                                subLength = LoadField(sd, "Length", 1);
                            }

                            return(subFrames != null?subFrames.Skip(subStart).Take(subLength) : Enumerable.Range(subStart, subLength));
                        };

                        var subSrc     = GetSpriteSrc(modData, tileSet, sequence, animation, sub.Key, sd);
                        var subSprites = cache[subSrc, subGetUsedFrames].Select(
                            s => s != null ? new Sprite(s.Sheet,
                                                        FlipRectangle(s.Bounds, subFlipX, subFlipY), ZRamp,
                                                        new float3(subFlipX ? -s.Offset.X : s.Offset.X, subFlipY ? -s.Offset.Y : s.Offset.Y, s.Offset.Z) + subOffset + offset,
                                                        s.Channel, blendMode) : null).ToList();

                        var frames = subFrames != null?subFrames.Skip(subStart).Take(subLength).ToArray() : Exts.MakeArray(subLength, i => subStart + i);

                        combined = combined.Concat(frames.Select(i => subSprites[i]));
                    }

                    sprites = combined.ToArray();
                    getUsedFrames(sprites.Length);
                }
                else
                {
                    // Apply offset to each sprite in the sequence
                    // Different sequences may apply different offsets to the same frame
                    var src = GetSpriteSrc(modData, tileSet, sequence, animation, info.Value, d);
                    sprites = cache[src, getUsedFrames].Select(
                        s => s != null ? new Sprite(s.Sheet,
                                                    FlipRectangle(s.Bounds, flipX, flipY), ZRamp,
                                                    new float3(flipX ? -s.Offset.X : s.Offset.X, flipY ? -s.Offset.Y : s.Offset.Y, s.Offset.Z) + offset,
                                                    s.Channel, blendMode) : null).ToArray();
                }

                var depthSprite = LoadField <string>(d, "DepthSprite", null);
                if (!string.IsNullOrEmpty(depthSprite))
                {
                    var depthSpriteFrame = LoadField(d, "DepthSpriteFrame", 0);
                    var depthOffset      = LoadField(d, "DepthSpriteOffset", float2.Zero);
                    Func <int, IEnumerable <int> > getDepthFrame = _ => new int[] { depthSpriteFrame };
                    var ds = cache[depthSprite, getDepthFrame][depthSpriteFrame];

                    sprites = sprites.Select(s =>
                    {
                        if (s == null)
                        {
                            return(null);
                        }

                        var cw = (ds.Bounds.Left + ds.Bounds.Right) / 2 + (int)(s.Offset.X + depthOffset.X);
                        var ch = (ds.Bounds.Top + ds.Bounds.Bottom) / 2 + (int)(s.Offset.Y + depthOffset.Y);
                        var w  = s.Bounds.Width / 2;
                        var h  = s.Bounds.Height / 2;

                        var r = Rectangle.FromLTRB(cw - w, ch - h, cw + w, ch + h);
                        return(new SpriteWithSecondaryData(s, ds.Sheet, r, ds.Channel));
                    }).ToArray();
                }

                var exportPalette = LoadField <string>(d, "EmbeddedPalette", null);
                if (exportPalette != null)
                {
                    var src = GetSpriteSrc(modData, tileSet, sequence, animation, info.Value, d);

                    var metadata = cache.FrameMetadata(src);
                    var i        = Frames != null ? Frames[0] : Start;
                    var palettes = metadata != null?metadata.GetOrDefault <EmbeddedSpritePalette>() : null;

                    if (palettes == null || !palettes.TryGetPaletteForFrame(i, out EmbeddedPalette))
                    {
                        throw new YamlException("Cannot export palettes from {0}: frame {1} does not define an embedded palette".F(src, i));
                    }
                }

                var boundSprites = SpriteBounds(sprites, Frames, Start, Facings, Length, Stride, transpose);
                if (ShadowStart > 0)
                {
                    boundSprites = boundSprites.Concat(SpriteBounds(sprites, Frames, ShadowStart, Facings, Length, Stride, transpose));
                }

                Bounds = boundSprites.Union();
            }
            catch (FormatException f)
            {
                throw new FormatException("Failed to parse sequences for {0}.{1} at {2}:\n{3}".F(sequence, animation, info.Nodes[0].Location, f));
            }
        }
Esempio n. 30
0
 public SequenceProvider(SequenceCache cache, Map map)
 {
     this.sequences   = Exts.Lazy(() => cache.LoadSequences(map));
     this.SpriteCache = cache.SpriteCache;
 }