public IngameChatLogic(Widget widget, OrderManager orderManager, World world, ModData modData, bool isMenuChat, Dictionary <string, MiniYaml> logicArgs) { this.orderManager = orderManager; modRules = modData.DefaultRules; this.isMenuChat = isMenuChat; this.world = world; var chatTraits = world.WorldActor.TraitsImplementing <INotifyChat>().ToArray(); var players = world.Players.Where(p => p != world.LocalPlayer && !p.NonCombatant && !p.IsBot); var isObserver = orderManager.LocalClient != null && orderManager.LocalClient.IsObserver; var alwaysDisabled = world.IsReplay || world.LobbyInfo.NonBotClients.Count() == 1; var disableTeamChat = alwaysDisabled || (world.LocalPlayer != null && !players.Any(p => p.IsAlliedWith(world.LocalPlayer))); var teamChat = !disableTeamChat; tabCompletion.Commands = chatTraits.OfType <ChatCommands>().SelectMany(x => x.Commands.Keys).ToList(); tabCompletion.Names = orderManager.LobbyInfo.Clients.Select(c => c.Name).Distinct().ToList(); if (logicArgs.TryGetValue("Templates", out var templateIds)) { foreach (var item in templateIds.Nodes) { var key = FieldLoader.GetValue <TextNotificationPool>("key", item.Key); templates[key] = Ui.LoadWidget(item.Value.Value, null, new WidgetArgs()); } } var chatPanel = (ContainerWidget)widget; chatOverlay = chatPanel.GetOrNull <ContainerWidget>("CHAT_OVERLAY"); if (chatOverlay != null) { chatOverlayDisplay = chatOverlay.Get <TextNotificationsDisplayWidget>("CHAT_DISPLAY"); chatOverlay.Visible = false; } chatChrome = chatPanel.Get <ContainerWidget>("CHAT_CHROME"); chatChrome.Visible = true; var chatMode = chatChrome.Get <ButtonWidget>("CHAT_MODE"); chatMode.GetText = () => teamChat && !disableTeamChat ? "Team" : "All"; chatMode.OnClick = () => teamChat ^= true; // Enable teamchat if we are a player and die, // or disable it when we are the only one left in the team if (!alwaysDisabled && world.LocalPlayer != null) { chatMode.IsDisabled = () => { if (world.IsGameOver || !chatEnabled) { return(true); } // The game is over for us, join spectator team chat if (world.LocalPlayer.WinState != WinState.Undefined) { disableTeamChat = false; return(disableTeamChat); } // If team chat isn't already disabled, check if we are the only living team member if (!disableTeamChat) { disableTeamChat = players.All(p => p.WinState != WinState.Undefined || !p.IsAlliedWith(world.LocalPlayer)); } return(disableTeamChat); }; } else { chatMode.IsDisabled = () => disableTeamChat || !chatEnabled; } // Disable team chat after the game ended world.GameOver += () => disableTeamChat = true; chatText = chatChrome.Get <TextFieldWidget>("CHAT_TEXTFIELD"); chatText.MaxLength = UnitOrders.ChatMessageMaxLength; chatText.OnEnterKey = _ => { var team = teamChat && !disableTeamChat; if (chatText.Text != "") { if (!chatText.Text.StartsWith("/", StringComparison.Ordinal)) { // This should never happen, but avoid a crash if it does somehow (chat will just stay open) if (!isObserver && orderManager.LocalClient == null && world.LocalPlayer == null) { return(true); } var teamNumber = 0U; if (team) { teamNumber = (isObserver || world.LocalPlayer.WinState != WinState.Undefined) ? uint.MaxValue : (uint)orderManager.LocalClient.Team; } orderManager.IssueOrder(Order.Chat(chatText.Text.Trim(), teamNumber)); } else if (chatTraits != null) { var text = chatText.Text.Trim(); var from = world.IsReplay ? null : orderManager.LocalClient.Name; foreach (var trait in chatTraits) { trait.OnChat(from, text); } } } chatText.Text = ""; if (!isMenuChat) { CloseChat(); } return(true); }; chatText.OnTabKey = e => { if (!chatMode.Key.IsActivatedBy(e) || chatMode.IsDisabled()) { chatText.Text = tabCompletion.Complete(chatText.Text); chatText.CursorPosition = chatText.Text.Length; } else { chatMode.OnKeyPress(e); } return(true); }; chatText.OnEscKey = _ => { if (!isMenuChat) { CloseChat(); } else { chatText.YieldKeyboardFocus(); } return(true); }; chatDisabledLabel = new CachedTransform <int, string>(x => x > 0 ? $"Chat available in {x} seconds..." : "Chat Disabled"); if (!isMenuChat) { var openTeamChatKey = new HotkeyReference(); if (logicArgs.TryGetValue("OpenTeamChatKey", out var hotkeyArg)) { openTeamChatKey = modData.Hotkeys[hotkeyArg.Value]; } var openGeneralChatKey = new HotkeyReference(); if (logicArgs.TryGetValue("OpenGeneralChatKey", out hotkeyArg)) { openGeneralChatKey = modData.Hotkeys[hotkeyArg.Value]; } var chatClose = chatChrome.Get <ButtonWidget>("CHAT_CLOSE"); chatClose.OnClick += CloseChat; chatPanel.OnKeyPress = e => { if (e.Event == KeyInputEvent.Up) { return(false); } if (!chatChrome.IsVisible() && (openTeamChatKey.IsActivatedBy(e) || openGeneralChatKey.IsActivatedBy(e))) { teamChat = !disableTeamChat && !openGeneralChatKey.IsActivatedBy(e); OpenChat(); return(true); } return(false); }; } chatScrollPanel = chatChrome.Get <ScrollPanelWidget>("CHAT_SCROLLPANEL"); chatScrollPanel.RemoveChildren(); chatScrollPanel.ScrollToBottom(); foreach (var notification in orderManager.NotificationsCache) { if (IsNotificationEligible(notification)) { AddNotification(notification, true); } } orderManager.AddTextNotification += AddNotificationWrapper; chatText.IsDisabled = () => !chatEnabled || (world.IsReplay && !Game.Settings.Debug.EnableDebugCommandsInReplays); if (!isMenuChat) { CloseChat(); var keyListener = chatChrome.Get <LogicKeyListenerWidget>("KEY_LISTENER"); keyListener.AddHandler(e => { if (e.Event == KeyInputEvent.Up || !chatText.IsDisabled()) { return(false); } if ((e.Key == Keycode.RETURN || e.Key == Keycode.KP_ENTER || e.Key == Keycode.ESCAPE) && e.Modifiers == Modifiers.None) { CloseChat(); return(true); } return(false); }); } if (logicArgs.TryGetValue("ChatLineSound", out var yaml)) { chatLineSound = yaml.Value; } }
void CheckInner(ModData modData, string[] namedKeys, Pair <string, string>[] checkWidgetFields, Dictionary <string, List <string> > customLintMethods, List <MiniYamlNode> nodes, string filename, MiniYamlNode parent, Action <string> emitError, Action <string> emitWarning) { foreach (var node in nodes) { if (node.Value == null) { continue; } foreach (var x in checkWidgetFields) { if (node.Key == x.Second && parent != null && parent.Key.StartsWith(x.First, StringComparison.Ordinal)) { // Keys are valid if they refer to a named key or can be parsed as a regular Hotkey. Hotkey unused; if (!namedKeys.Contains(node.Value.Value) && !Hotkey.TryParse(node.Value.Value, out unused)) { emitError("{0} refers to a Key named `{1}` that does not exist".F(node.Location, node.Value.Value)); } } } // Check runtime-defined hotkey names List <string> checkMethods; var widgetType = node.Key.Split('@')[0]; if (customLintMethods.TryGetValue(widgetType, out checkMethods)) { var type = modData.ObjectCreator.FindType(widgetType + "Widget"); var keyNames = checkMethods.SelectMany(m => (IEnumerable <string>)type.GetMethod(m).Invoke(null, new object[] { node, emitError, emitWarning })); Hotkey unused; foreach (var name in keyNames) { if (!namedKeys.Contains(name) && !Hotkey.TryParse(name, out unused)) { emitError("{0} refers to a Key named `{1}` that does not exist".F(node.Location, name)); } } } // Logic classes can declare the data key names that specify hotkeys if (node.Key == "Logic" && node.Value.Nodes.Any()) { var typeNames = FieldLoader.GetValue <string[]>(node.Key, node.Value.Value); var checkArgKeys = new List <string>(); foreach (var typeName in typeNames) { var type = Game.ModData.ObjectCreator.FindType(typeName); if (type == null) { continue; } checkArgKeys.AddRange(type.GetCustomAttributes <ChromeLogicArgsHotkeys>(true).SelectMany(x => x.LogicArgKeys)); } Hotkey unused; foreach (var n in node.Value.Nodes) { if (checkArgKeys.Contains(n.Key)) { if (!namedKeys.Contains(n.Value.Value) && !Hotkey.TryParse(n.Value.Value, out unused)) { emitError("{0} {1}:{2} refers to a Key named `{3}` that does not exist".F(filename, node.Value.Value, n.Key, n.Value.Value)); } } } } if (node.Value.Nodes != null) { CheckInner(modData, namedKeys, checkWidgetFields, customLintMethods, node.Value.Nodes, filename, node, emitError, emitWarning); } } }
static void ExtractFromPackage(ExtractionType type, string path, MiniYaml actionYaml, List <string> extractedFiles, Action <string> updateMessage) { var sourcePath = Path.Combine(path, actionYaml.Value); // Try as an absolute path if (!File.Exists(sourcePath)) { sourcePath = Platform.ResolvePath(actionYaml.Value); } using (var source = File.OpenRead(sourcePath)) { foreach (var node in actionYaml.Nodes) { var targetPath = Platform.ResolvePath(node.Key); if (File.Exists(targetPath)) { Log.Write("install", "Skipping installed file " + targetPath); continue; } var offsetNode = node.Value.Nodes.FirstOrDefault(n => n.Key == "Offset"); if (offsetNode == null) { Log.Write("install", "Skipping entry with missing Offset definition " + targetPath); continue; } var lengthNode = node.Value.Nodes.FirstOrDefault(n => n.Key == "Length"); if (lengthNode == null) { Log.Write("install", "Skipping entry with missing Length definition " + targetPath); continue; } var length = FieldLoader.GetValue <int>("Length", lengthNode.Value.Value); source.Position = FieldLoader.GetValue <int>("Offset", offsetNode.Value.Value); extractedFiles.Add(targetPath); Directory.CreateDirectory(Path.GetDirectoryName(targetPath)); var displayFilename = Path.GetFileName(Path.GetFileName(targetPath)); Action <long> onProgress = null; if (length < ShowPercentageThreshold) { updateMessage("Extracting " + displayFilename); } else { onProgress = b => updateMessage("Extracting " + displayFilename + " ({0}%)".F(100 * b / length)); } using (var target = File.OpenWrite(targetPath)) { Log.Write("install", "Extracting {0} -> {1}".F(sourcePath, targetPath)); if (type == ExtractionType.Blast) { Action <long, long> onBlastProgress = (read, _) => { if (onProgress != null) { onProgress(read); } }; Blast.Decompress(source, target, onBlastProgress); } else { CopyStream(source, target, length, onProgress); } } } } }
public Consideration(MiniYaml yaml) { FieldLoader.Load(this, yaml); }
public Sequence(SpriteLoader loader, string unit, string name, MiniYaml info) { var srcOverride = info.Value; Name = name; var d = info.ToDictionary(); var offset = float2.Zero; var blendMode = BlendMode.Alpha; try { if (d.ContainsKey("Start")) { Start = Exts.ParseIntegerInvariant(d["Start"].Value); } if (d.ContainsKey("Offset")) { offset = FieldLoader.GetValue <float2>("Offset", d["Offset"].Value); } if (d.ContainsKey("BlendMode")) { blendMode = FieldLoader.GetValue <BlendMode>("BlendMode", d["BlendMode"].Value); } // Apply offset to each sprite in the sequence // Different sequences may apply different offsets to the same frame sprites = loader.LoadAllSprites(srcOverride ?? unit).Select( s => new Sprite(s.sheet, s.bounds, s.offset + offset, s.channel, blendMode)).ToArray(); if (!d.ContainsKey("Length")) { Length = 1; } else if (d["Length"].Value == "*") { Length = sprites.Length - Start; } else { Length = Exts.ParseIntegerInvariant(d["Length"].Value); } if (d.ContainsKey("Stride")) { Stride = Exts.ParseIntegerInvariant(d["Stride"].Value); } else { Stride = Length; } if (d.ContainsKey("Facings")) { var f = Exts.ParseIntegerInvariant(d["Facings"].Value); Facings = Math.Abs(f); reverseFacings = f < 0; } else { Facings = 1; } if (d.ContainsKey("Tick")) { Tick = Exts.ParseIntegerInvariant(d["Tick"].Value); } else { Tick = 40; } if (d.ContainsKey("Transpose")) { transpose = bool.Parse(d["Transpose"].Value); } if (d.ContainsKey("Frames")) { Frames = Array.ConvertAll <string, int>(d["Frames"].Value.Split(','), Exts.ParseIntegerInvariant); } if (d.ContainsKey("ShadowStart")) { ShadowStart = Exts.ParseIntegerInvariant(d["ShadowStart"].Value); } else { ShadowStart = -1; } if (d.ContainsKey("ShadowZOffset")) { WRange r; if (WRange.TryParse(d["ShadowZOffset"].Value, out r)) { ShadowZOffset = r.Range; } } else { ShadowZOffset = -5; } if (d.ContainsKey("ZOffset")) { WRange r; if (WRange.TryParse(d["ZOffset"].Value, out r)) { ZOffset = r.Range; } } if (Length > Stride) { throw new InvalidOperationException( "{0}: Sequence {1}.{2}: Length must be <= stride" .F(info.Nodes[0].Location, unit, name)); } if (Start < 0 || Start + Facings * Stride > sprites.Length || ShadowStart + Facings * Stride > sprites.Length) { throw new InvalidOperationException( "{6}: Sequence {0}.{1} uses frames [{2}..{3}] of SHP `{4}`, but only 0..{5} actually exist" .F(unit, name, Start, Start + Facings * Stride - 1, srcOverride ?? unit, 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(unit, name, info.Nodes[0].Location, f)); } }
public ResourceTypeInfo(MiniYaml yaml) { FieldLoader.Load(this, yaml); }
public static Slot Deserialize(MiniYaml data) { return(FieldLoader.Load <Slot>(data)); }
public static T NodeValue <T>(this MiniYamlNode node) { return(FieldLoader.GetValue <T>(node.Key, node.Value.Value)); }
public void DropClient(Connection toDrop) { if (preConns.Contains(toDrop)) { preConns.Remove(toDrop); } else { conns.Remove(toDrop); var dropClient = lobbyInfo.Clients.FirstOrDefault(c1 => c1.Index == toDrop.PlayerIndex); if (dropClient == null) { return; } // Send disconnected order, even if still in the lobby SendMessage("{0} has disconnected.".F(dropClient.Name)); DispatchOrdersToClients(toDrop, 0, new ServerOrder("Disconnected", "").Serialize()); lobbyInfo.Clients.RemoveAll(c => c.Index == toDrop.PlayerIndex); // Client was the server admin // TODO: Reassign admin for game in progress via an order if (lobbyInfo.GlobalSettings.Dedicated && dropClient.IsAdmin && State == ServerState.WaitingPlayers) { // Remove any bots controlled by the admin lobbyInfo.Clients.RemoveAll(c => c.Bot != null && c.BotControllerClientIndex == toDrop.PlayerIndex); var nextAdmin = lobbyInfo.Clients.Where(c1 => c1.Bot == null) .OrderBy(c => c.Index).FirstOrDefault(); if (nextAdmin != null) { nextAdmin.IsAdmin = true; SendMessage("{0} is now the admin.".F(nextAdmin.Name)); } } DispatchOrders(toDrop, toDrop.MostRecentFrame, new byte[] { 0xbf }); if (!conns.Any()) { FieldLoader.Load(lobbyInfo.GlobalSettings, ModData.Manifest.LobbyDefaults); TempBans.Clear(); } if (conns.Any() || lobbyInfo.GlobalSettings.Dedicated) { SyncLobbyInfo(); } if (!lobbyInfo.GlobalSettings.Dedicated && dropClient.IsAdmin) { Shutdown(); } } try { toDrop.socket.Disconnect(false); } catch { } SetOrderLag(); }
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, "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 (Legacy)" : "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(); }); }
public PlayerReference(MiniYaml my) { FieldLoader.Load(this, my); }
public CommandBarLogic(Widget widget, World world, Dictionary <string, MiniYaml> logicArgs) { this.world = world; var highlightOnButtonPress = false; if (logicArgs.ContainsKey("HighlightOnButtonPress")) { highlightOnButtonPress = FieldLoader.GetValue <bool>("HighlightOnButtonPress", logicArgs["HighlightOnButtonPress"].Value); } var attackMoveButton = widget.GetOrNull <ButtonWidget>("ATTACK_MOVE"); if (attackMoveButton != null) { BindButtonIcon(attackMoveButton); attackMoveButton.IsDisabled = () => { UpdateStateIfNecessary(); return(attackMoveDisabled); }; attackMoveButton.IsHighlighted = () => world.OrderGenerator is AttackMoveOrderGenerator; Action <bool> toggle = allowCancel => { if (attackMoveButton.IsHighlighted()) { if (allowCancel) { world.CancelInputMode(); } } else { world.OrderGenerator = new AttackMoveOrderGenerator(selectedActors, Game.Settings.Game.MouseButtonPreference.Action); } }; attackMoveButton.OnClick = () => toggle(true); attackMoveButton.OnKeyPress = _ => toggle(false); } var forceMoveButton = widget.GetOrNull <ButtonWidget>("FORCE_MOVE"); if (forceMoveButton != null) { BindButtonIcon(forceMoveButton); forceMoveButton.IsDisabled = () => { UpdateStateIfNecessary(); return(forceMoveDisabled); }; forceMoveButton.IsHighlighted = () => !forceMoveButton.IsDisabled() && IsForceModifiersActive(Modifiers.Alt); forceMoveButton.OnClick = () => { if (forceMoveButton.IsHighlighted()) { world.CancelInputMode(); } else { world.OrderGenerator = new ForceModifiersOrderGenerator(Modifiers.Alt, true); } }; } var forceAttackButton = widget.GetOrNull <ButtonWidget>("FORCE_ATTACK"); if (forceAttackButton != null) { BindButtonIcon(forceAttackButton); forceAttackButton.IsDisabled = () => { UpdateStateIfNecessary(); return(forceAttackDisabled); }; forceAttackButton.IsHighlighted = () => !forceAttackButton.IsDisabled() && IsForceModifiersActive(Modifiers.Ctrl) && !(world.OrderGenerator is AttackMoveOrderGenerator); forceAttackButton.OnClick = () => { if (forceAttackButton.IsHighlighted()) { world.CancelInputMode(); } else { world.OrderGenerator = new ForceModifiersOrderGenerator(Modifiers.Ctrl, true); } }; } var guardButton = widget.GetOrNull <ButtonWidget>("GUARD"); if (guardButton != null) { BindButtonIcon(guardButton); guardButton.IsDisabled = () => { UpdateStateIfNecessary(); return(guardDisabled); }; guardButton.IsHighlighted = () => world.OrderGenerator is GenericSelectTarget && ((GenericSelectTarget)world.OrderGenerator).OrderName == "Guard"; Action <bool> toggle = allowCancel => { if (guardButton.IsHighlighted()) { if (allowCancel) { world.CancelInputMode(); } } else { world.OrderGenerator = new GuardOrderGenerator(selectedActors, "Guard", "guard", Game.Settings.Game.MouseButtonPreference.Action); } }; guardButton.OnClick = () => toggle(true); guardButton.OnKeyPress = _ => toggle(false); } var scatterButton = widget.GetOrNull <ButtonWidget>("SCATTER"); if (scatterButton != null) { BindButtonIcon(scatterButton); scatterButton.IsDisabled = () => { UpdateStateIfNecessary(); return(scatterDisabled); }; scatterButton.IsHighlighted = () => scatterHighlighted > 0; scatterButton.OnClick = () => { if (highlightOnButtonPress) { scatterHighlighted = 2; } PerformKeyboardOrderOnSelection(a => new Order("Scatter", a, false)); }; scatterButton.OnKeyPress = ki => { scatterHighlighted = 2; scatterButton.OnClick(); }; } var deployButton = widget.GetOrNull <ButtonWidget>("DEPLOY"); if (deployButton != null) { BindButtonIcon(deployButton); deployButton.IsDisabled = () => { UpdateStateIfNecessary(); return(!selectedDeploys.Any(pair => pair.Trait.CanIssueDeployOrder(pair.Actor))); }; deployButton.IsHighlighted = () => deployHighlighted > 0; deployButton.OnClick = () => { if (highlightOnButtonPress) { deployHighlighted = 2; } var queued = Game.GetModifierKeys().HasModifier(Modifiers.Shift); PerformDeployOrderOnSelection(queued); }; deployButton.OnKeyPress = ki => { deployHighlighted = 2; deployButton.OnClick(); }; } var stopButton = widget.GetOrNull <ButtonWidget>("STOP"); if (stopButton != null) { BindButtonIcon(stopButton); stopButton.IsDisabled = () => { UpdateStateIfNecessary(); return(stopDisabled); }; stopButton.IsHighlighted = () => stopHighlighted > 0; stopButton.OnClick = () => { if (highlightOnButtonPress) { stopHighlighted = 2; } PerformKeyboardOrderOnSelection(a => new Order("Stop", a, false)); }; stopButton.OnKeyPress = ki => { stopHighlighted = 2; stopButton.OnClick(); }; } var queueOrdersButton = widget.GetOrNull <ButtonWidget>("QUEUE_ORDERS"); if (queueOrdersButton != null) { BindButtonIcon(queueOrdersButton); queueOrdersButton.IsDisabled = () => { UpdateStateIfNecessary(); return(waypointModeDisabled); }; queueOrdersButton.IsHighlighted = () => !queueOrdersButton.IsDisabled() && IsForceModifiersActive(Modifiers.Shift); queueOrdersButton.OnClick = () => { if (queueOrdersButton.IsHighlighted()) { world.CancelInputMode(); } else { world.OrderGenerator = new ForceModifiersOrderGenerator(Modifiers.Shift, false); } }; } var keyOverrides = widget.GetOrNull <LogicKeyListenerWidget>("MODIFIER_OVERRIDES"); if (keyOverrides != null) { keyOverrides.AddHandler(e => { // HACK: allow attack move to be triggered if the ctrl key is pressed (assault move) var eNoCtrl = e; eNoCtrl.Modifiers &= ~Modifiers.Ctrl; if (attackMoveButton != null && !attackMoveDisabled && attackMoveButton.Key.IsActivatedBy(eNoCtrl)) { attackMoveButton.OnKeyPress(e); return(true); } // HACK: allow deploy to be triggered if the shift key is pressed (queued order) if (e.Modifiers.HasModifier(Modifiers.Shift) && e.Event == KeyInputEvent.Down) { var eNoShift = e; eNoShift.Modifiers &= ~Modifiers.Shift; if (deployButton != null && !deployButton.IsDisabled() && deployButton.Key.IsActivatedBy(eNoShift)) { deployButton.OnKeyPress(e); return(true); } } return(false); }); } }
static void Run(string[] args) { var arguments = new Arguments(args); var engineDirArg = arguments.GetValue("Engine.EngineDir", null); if (!string.IsNullOrEmpty(engineDirArg)) { Platform.OverrideEngineDir(engineDirArg); } var supportDirArg = arguments.GetValue("Engine.SupportDir", null); if (!string.IsNullOrEmpty(supportDirArg)) { Platform.OverrideSupportDir(supportDirArg); } Log.AddChannel("debug", "dedicated-debug.log", true); Log.AddChannel("perf", "dedicated-perf.log", true); Log.AddChannel("server", "dedicated-server.log", true); Log.AddChannel("nat", "dedicated-nat.log", true); Log.AddChannel("geoip", "dedicated-geoip.log", true); // Special case handling of Game.Mod argument: if it matches a real filesystem path // then we use this to override the mod search path, and replace it with the mod id var modID = arguments.GetValue("Game.Mod", null); var explicitModPaths = Array.Empty <string>(); if (modID != null && (File.Exists(modID) || Directory.Exists(modID))) { explicitModPaths = new[] { modID }; modID = Path.GetFileNameWithoutExtension(modID); } if (modID == null) { throw new InvalidOperationException("Game.Mod argument missing or mod could not be found."); } // HACK: The engine code assumes that Game.Settings is set. // This isn't nearly as bad as ModData, but is still not very nice. Game.InitializeSettings(arguments); var settings = Game.Settings.Server; Nat.Initialize(); var envModSearchPaths = Environment.GetEnvironmentVariable("MOD_SEARCH_PATHS"); var modSearchPaths = !string.IsNullOrWhiteSpace(envModSearchPaths) ? FieldLoader.GetValue <string[]>("MOD_SEARCH_PATHS", envModSearchPaths) : new[] { Path.Combine(Platform.EngineDir, "mods") }; var mods = new InstalledMods(modSearchPaths, explicitModPaths); Console.WriteLine("[{0}] Starting dedicated server for mod: {1}", DateTime.Now.ToString(settings.TimestampFormat), modID); while (true) { // HACK: The engine code *still* assumes that Game.ModData is set var modData = Game.ModData = new ModData(mods[modID], mods); modData.MapCache.LoadMaps(); settings.Map = modData.MapCache.ChooseInitialMap(settings.Map, new MersenneTwister()); var endpoints = new List <IPEndPoint> { new IPEndPoint(IPAddress.IPv6Any, settings.ListenPort), new IPEndPoint(IPAddress.Any, settings.ListenPort) }; var server = new Server(endpoints, settings, modData, ServerType.Dedicated); GC.Collect(); while (true) { Thread.Sleep(1000); if (server.State == ServerState.GameStarted && server.Conns.Count < 1) { Console.WriteLine("[{0}] No one is playing, shutting down...", DateTime.Now.ToString(settings.TimestampFormat)); server.Shutdown(); break; } } modData.Dispose(); Console.WriteLine("[{0}] Starting a new server instance...", DateTime.Now.ToString(settings.TimestampFormat)); } }
public void Initialize(MiniYaml yaml) { Initialize((int)FieldLoader.GetValue("value", typeof(int), yaml.Value)); }
void IUtilityCommand.Run(Utility utility, string[] args) { // HACK: The engine code assumes that Game.modData is set. Game.ModData = utility.ModData; var version = utility.ModData.Manifest.Metadata.Version; if (args.Length > 1) { version = args[1]; } Console.WriteLine( "This documentation is aimed at modders. It displays all traits with default values and developer commentary. " + "Please do not edit it directly, but add new `[Desc(\"String\")]` tags to the source code. This file has been " + "automatically generated for version {0} of OpenRA.", version); Console.WriteLine(); var doc = new StringBuilder(); var currentNamespace = ""; foreach (var t in Game.ModData.ObjectCreator.GetTypesImplementing <TraitInfo>().OrderBy(t => t.Namespace)) { if (t.ContainsGenericParameters || t.IsAbstract) { continue; // skip helpers like TraitInfo<T> } if (currentNamespace != t.Namespace) { currentNamespace = t.Namespace; doc.AppendLine(); doc.AppendLine($"## {currentNamespace}"); } var traitName = t.Name.EndsWith("Info") ? t.Name.Substring(0, t.Name.Length - 4) : t.Name; var traitDescLines = t.GetCustomAttributes <DescAttribute>(false).SelectMany(d => d.Lines); doc.AppendLine(); doc.AppendLine($"### {traitName}"); foreach (var line in traitDescLines) { doc.AppendLine(line); } var requires = RequiredTraitTypes(t); var reqCount = requires.Length; if (reqCount > 0) { if (t.HasAttribute <DescAttribute>()) { doc.AppendLine(); } doc.Append($"Requires trait{(reqCount > 1 ? "s" : "")}: "); var i = 0; foreach (var require in requires) { var n = require.Name; var name = n.EndsWith("Info") ? n.Remove(n.Length - 4, 4) : n; doc.Append($"[`{name}`](#{name.ToLowerInvariant()}){(i + 1 == reqCount ? ".\n" : ", ")}"); i++; } } var infos = FieldLoader.GetTypeLoadInfo(t); if (!infos.Any()) { continue; } doc.AppendLine("<table>"); doc.AppendLine("<tr><th>Property</th><th>Default Value</th><th>Type</th><th>Description</th></tr>"); var liveTraitInfo = Game.ModData.ObjectCreator.CreateBasic(t); foreach (var info in infos) { var fieldDescLines = info.Field.GetCustomAttributes <DescAttribute>(true).SelectMany(d => d.Lines); var fieldType = Util.FriendlyTypeName(info.Field.FieldType); var loadInfo = info.Field.GetCustomAttributes <FieldLoader.SerializeAttribute>(true).FirstOrDefault(); var defaultValue = loadInfo != null && loadInfo.Required ? "<em>(required)</em>" : FieldSaver.SaveField(liveTraitInfo, info.Field.Name).Value.Value; doc.Append($"<tr><td>{info.YamlName}</td><td>{defaultValue}</td><td>{fieldType}</td>"); doc.Append("<td>"); foreach (var line in fieldDescLines) { doc.Append(line + " "); } doc.AppendLine("</td></tr>"); } doc.AppendLine("</table>"); } Console.Write(doc.ToString()); }
public Server(IPEndPoint endpoint, string[] mods, ServerSettings settings, ModData modData) { Log.AddChannel("server", "server.log"); pState = ServerState.WaitingPlayers; listener = new TcpListener(endpoint); listener.Start(); var localEndpoint = (IPEndPoint)listener.LocalEndpoint; Ip = localEndpoint.Address; Port = localEndpoint.Port; Settings = settings; ModData = modData; randomSeed = (int)DateTime.Now.ToBinary(); if (Settings.AllowPortForward) { UPnP.ForwardPort(); } foreach (var trait in modData.Manifest.ServerTraits) { ServerTraits.Add(modData.ObjectCreator.CreateObject <ServerTrait>(trait)); } lobbyInfo = new Session(mods); lobbyInfo.GlobalSettings.RandomSeed = randomSeed; lobbyInfo.GlobalSettings.Map = settings.Map; lobbyInfo.GlobalSettings.ServerName = settings.Name; lobbyInfo.GlobalSettings.Dedicated = settings.Dedicated; FieldLoader.Load(lobbyInfo.GlobalSettings, modData.Manifest.LobbyDefaults); foreach (var t in ServerTraits.WithInterface <INotifyServerStart>()) { t.ServerStarted(this); } Log.Write("server", "Initial mods: "); foreach (var m in lobbyInfo.GlobalSettings.Mods) { Log.Write("server", "- {0}", m); } Log.Write("server", "Initial map: {0}", lobbyInfo.GlobalSettings.Map); new Thread(_ => { var timeout = ServerTraits.WithInterface <ITick>().Min(t => t.TickTimeout); for (;;) { var checkRead = new List <Socket>(); checkRead.Add(listener.Server); foreach (var c in conns) { checkRead.Add(c.socket); } foreach (var c in preConns) { checkRead.Add(c.socket); } Socket.Select(checkRead, null, null, timeout); if (State == ServerState.ShuttingDown) { EndGame(); break; } foreach (var s in checkRead) { if (s == listener.Server) { AcceptConnection(); } else if (preConns.Count > 0) { var p = preConns.SingleOrDefault(c => c.socket == s); if (p != null) { p.ReadData(this); } } else if (conns.Count > 0) { var conn = conns.SingleOrDefault(c => c.socket == s); if (conn != null) { conn.ReadData(this); } } } foreach (var t in ServerTraits.WithInterface <ITick>()) { t.Tick(this); } if (State == ServerState.ShuttingDown) { EndGame(); if (Settings.AllowPortForward) { UPnP.RemovePortforward(); } break; } } foreach (var t in ServerTraits.WithInterface <INotifyServerShutdown>()) { t.ServerShutdown(this); } preConns.Clear(); conns.Clear(); try { listener.Stop(); } catch { } }) { IsBackground = true }.Start(); }
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.MapPlayers.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], Race = "Random", SpawnPoint = 0, Team = 0, State = Session.ClientState.NotReady, BotControllerClientIndex = controllerClientIndex }; // Pick a random color for the bot HSLColor botColor; do { var hue = (byte)server.Random.Next(255); var sat = (byte)server.Random.Next(255); var lum = (byte)server.Random.Next(51, 255); botColor = new HSLColor(hue, sat, lum); } while (!ColorValidator.ValidatePlayerNewColor(server, botColor.RGB, bot.Index)); bot.Color = bot.PreferredColor = botColor; server.LobbyInfo.Clients.Add(bot); } else { // Change the type of the existing bot bot.Name = botType; bot.Bot = botType; } S.SyncClientToPlayerReference(bot, server.MapPlayers.Players[parts[0]]); server.SyncLobbyClients(); server.SyncLobbySlots(); return(true); } }, { "map", s => { if (!client.IsAdmin) { server.SendOrderTo(conn, "Message", "Only the host can change the map."); return(true); } if (server.ModData.MapCache[s].Status != MapStatus.Available) { server.SendOrderTo(conn, "Message", "Map was not found on server."); return(true); } server.LobbyInfo.GlobalSettings.Map = s; var oldSlots = server.LobbyInfo.Slots.Keys.ToArray(); LoadMap(server); SetDefaultDifficulty(server); // Reset client states foreach (var c in server.LobbyInfo.Clients) { c.State = Session.ClientState.Invalid; } // Reassign players into new slots based on their old slots: // - Observers remain as observers // - Players who now lack a slot are made observers // - Bots who now lack a slot are dropped var slots = server.LobbyInfo.Slots.Keys.ToArray(); var i = 0; foreach (var os in oldSlots) { var c = server.LobbyInfo.ClientInSlot(os); if (c == null) { continue; } c.SpawnPoint = 0; c.Slot = i < slots.Length ? slots[i++] : null; if (c.Slot != null) { // Remove Bot from slot if slot forbids bots if (c.Bot != null && !server.MapPlayers.Players[c.Slot].AllowBots) { server.LobbyInfo.Clients.Remove(c); } S.SyncClientToPlayerReference(c, server.MapPlayers.Players[c.Slot]); } else if (c.Bot != null) { server.LobbyInfo.Clients.Remove(c); } } foreach (var c in server.LobbyInfo.Clients) { // Validate if color is allowed and get an alternative it it isn't c.Color = c.PreferredColor = ColorValidator.ValidatePlayerColorAndGetAlternative(server, c.Color, c.Index, conn); } server.SyncLobbyInfo(); server.SendMessage("{0} changed the map to {1}.".F(client.Name, server.Map.Title)); return(true); } }, { "fragilealliance", s => { if (!client.IsAdmin) { server.SendOrderTo(conn, "Message", "Only the host can set that option."); return(true); } if (server.Map.Options.FragileAlliances.HasValue) { server.SendOrderTo(conn, "Message", "Map has disabled alliance configuration."); return(true); } bool.TryParse(s, out server.LobbyInfo.GlobalSettings.FragileAlliances); server.SyncLobbyGlobalSettings(); server.SendMessage("{0} {1} Diplomacy Changes." .F(client.Name, server.LobbyInfo.GlobalSettings.FragileAlliances ? "enabled" : "disabled")); return(true); } }, { "allowcheats", s => { if (!client.IsAdmin) { server.SendOrderTo(conn, "Message", "Only the host can set that option."); return(true); } if (server.Map.Options.Cheats.HasValue) { server.SendOrderTo(conn, "Message", "Map has disabled cheat configuration."); return(true); } bool.TryParse(s, out server.LobbyInfo.GlobalSettings.AllowCheats); server.SyncLobbyGlobalSettings(); server.SendMessage("{0} {1} Developer Cheats." .F(client.Name, server.LobbyInfo.GlobalSettings.AllowCheats ? "allowed" : "disallowed")); return(true); } }, { "shroud", s => { if (!client.IsAdmin) { server.SendOrderTo(conn, "Message", "Only the host can set that option."); return(true); } if (server.Map.Options.Shroud.HasValue) { server.SendOrderTo(conn, "Message", "Map has disabled shroud configuration."); return(true); } bool.TryParse(s, out server.LobbyInfo.GlobalSettings.Shroud); server.SyncLobbyGlobalSettings(); server.SendMessage("{0} {1} Shroud." .F(client.Name, server.LobbyInfo.GlobalSettings.Shroud ? "enabled" : "disabled")); return(true); } }, { "fog", s => { if (!client.IsAdmin) { server.SendOrderTo(conn, "Message", "Only the host can set that option."); return(true); } if (server.Map.Options.Fog.HasValue) { server.SendOrderTo(conn, "Message", "Map has disabled fog configuration."); return(true); } bool.TryParse(s, out server.LobbyInfo.GlobalSettings.Fog); server.SyncLobbyGlobalSettings(); server.SendMessage("{0} {1} Fog of War." .F(client.Name, server.LobbyInfo.GlobalSettings.Fog ? "enabled" : "disabled")); return(true); } }, { "assignteams", s => { if (!client.IsAdmin) { server.SendOrderTo(conn, "Message", "Only the host can set that option."); return(true); } int teamCount; if (!Exts.TryParseIntegerInvariant(s, out teamCount)) { server.SendOrderTo(conn, "Message", "Number of teams could not be parsed: {0}".F(s)); return(true); } var maxTeams = (server.LobbyInfo.Clients.Count(c => c.Slot != null) + 1) / 2; teamCount = teamCount.Clamp(0, maxTeams); var 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); } }, { "crates", s => { if (!client.IsAdmin) { server.SendOrderTo(conn, "Message", "Only the host can set that option."); return(true); } if (server.Map.Options.Crates.HasValue) { server.SendOrderTo(conn, "Message", "Map has disabled crate configuration."); return(true); } bool.TryParse(s, out server.LobbyInfo.GlobalSettings.Crates); server.SyncLobbyGlobalSettings(); server.SendMessage("{0} {1} Crates." .F(client.Name, server.LobbyInfo.GlobalSettings.Crates ? "enabled" : "disabled")); return(true); } }, { "creeps", s => { if (!client.IsAdmin) { server.SendOrderTo(conn, "Message", "Only the host can set that option."); return(true); } if (server.Map.Options.Creeps.HasValue) { server.SendOrderTo(conn, "Message", "Map has disabled Creeps spawning configuration."); return(true); } bool.TryParse(s, out server.LobbyInfo.GlobalSettings.Creeps); server.SyncLobbyGlobalSettings(); server.SendMessage("{0} {1} Creeps spawning." .F(client.Name, server.LobbyInfo.GlobalSettings.Creeps ? "enabled" : "disabled")); return(true); } }, { "allybuildradius", s => { if (!client.IsAdmin) { server.SendOrderTo(conn, "Message", "Only the host can set that option."); return(true); } if (server.Map.Options.AllyBuildRadius.HasValue) { server.SendOrderTo(conn, "Message", "Map has disabled ally build radius configuration."); return(true); } bool.TryParse(s, out server.LobbyInfo.GlobalSettings.AllyBuildRadius); server.SyncLobbyGlobalSettings(); server.SendMessage("{0} {1} Build off Allies' ConYards." .F(client.Name, server.LobbyInfo.GlobalSettings.AllyBuildRadius ? "enabled" : "disabled")); return(true); } }, { "difficulty", s => { if (!server.Map.Options.Difficulties.Any()) { return(true); } if (!client.IsAdmin) { server.SendOrderTo(conn, "Message", "Only the host can set that option."); return(true); } if (s != null && !server.Map.Options.Difficulties.Contains(s)) { server.SendOrderTo(conn, "Message", "Unsupported difficulty selected: {0}".F(s)); server.SendOrderTo(conn, "Message", "Supported difficulties: {0}".F(server.Map.Options.Difficulties.JoinWith(","))); return(true); } server.LobbyInfo.GlobalSettings.Difficulty = s; server.SyncLobbyGlobalSettings(); server.SendMessage("{0} changed difficulty to {1}.".F(client.Name, s)); return(true); } }, { "startingunits", s => { if (!client.IsAdmin) { server.SendOrderTo(conn, "Message", "Only the host can set that option."); return(true); } if (!server.Map.Options.ConfigurableStartingUnits) { server.SendOrderTo(conn, "Message", "Map has disabled start unit configuration."); return(true); } var startUnitsInfo = server.Map.Rules.Actors["world"].Traits.WithInterface <MPStartUnitsInfo>(); var selectedClass = startUnitsInfo.Where(u => u.Class == s).Select(u => u.ClassName).FirstOrDefault(); var className = selectedClass != null ? selectedClass : s; server.LobbyInfo.GlobalSettings.StartingUnitsClass = s; server.SyncLobbyGlobalSettings(); server.SendMessage("{0} changed Starting Units to {1}.".F(client.Name, className)); return(true); } }, { "startingcash", s => { if (!client.IsAdmin) { server.SendOrderTo(conn, "Message", "Only the host can set that option."); return(true); } if (server.Map.Options.StartingCash.HasValue) { server.SendOrderTo(conn, "Message", "Map has disabled cash configuration."); return(true); } server.LobbyInfo.GlobalSettings.StartingCash = Exts.ParseIntegerInvariant(s); server.SyncLobbyGlobalSettings(); server.SendMessage("{0} changed Starting Cash to ${1}.".F(client.Name, s)); return(true); } }, { "techlevel", s => { if (!client.IsAdmin) { server.SendOrderTo(conn, "Message", "Only the host can set that option."); return(true); } if (server.Map.Options.TechLevel != null) { server.SendOrderTo(conn, "Message", "Map has disabled Tech configuration."); return(true); } server.LobbyInfo.GlobalSettings.TechLevel = s; server.SyncLobbyInfo(); server.SendMessage("{0} changed Tech Level to {1}.".F(client.Name, s)); return(true); } }, { "kick", s => { if (!client.IsAdmin) { server.SendOrderTo(conn, "Message", "Only the host can kick players."); return(true); } var split = s.Split(' '); if (split.Length < 2) { server.SendOrderTo(conn, "Message", "Malformed kick command"); return(true); } int kickClientID; Exts.TryParseIntegerInvariant(split[0], out kickClientID); var kickConn = server.Conns.SingleOrDefault(c => server.GetClient(c) != null && server.GetClient(c).Index == kickClientID); if (kickConn == null) { server.SendOrderTo(conn, "Message", "Noone in that slot."); return(true); } var kickClient = server.GetClient(kickConn); Log.Write("server", "Kicking client {0}.", 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 => { Log.Write("server", "Player@{0} is now known as {1}.", conn.Socket.RemoteEndPoint, s); server.SendMessage("{0} is now known as {1}.".F(client.Name, s)); client.Name = s; server.SyncLobbyClients(); return(true); } }, { "race", s => { var parts = s.Split(' '); var targetClient = server.LobbyInfo.ClientWithIndex(Exts.ParseIntegerInvariant(parts[0])); // Only the host can change other client's info if (targetClient.Index != client.Index && !client.IsAdmin) { return(true); } // Map has disabled race changes if (server.LobbyInfo.Slots[targetClient.Slot].LockRace) { return(true); } targetClient.Race = 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.Value.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); } targetClient.SpawnPoint = spawnPoint; server.SyncLobbyClients(); return(true); } }, { "color", s => { var parts = s.Split(' '); var targetClient = server.LobbyInfo.ClientWithIndex(Exts.ParseIntegerInvariant(parts[0])); // Only the host can change other client's info if (targetClient.Index != client.Index && !client.IsAdmin) { return(true); } // Spectator or map has disabled color changes if (targetClient.Slot == null || server.LobbyInfo.Slots[targetClient.Slot].LockColor) { return(true); } var newHslColor = FieldLoader.GetValue <HSLColor>("(value)", parts[1]); // Validate if color is allowed and get an alternative it it isn't var altHslColor = ColorValidator.ValidatePlayerColorAndGetAlternative(server, newHslColor, targetClient.Index, conn); targetClient.Color = altHslColor; // Only update player's preferred color if new color is valid if (newHslColor == altHslColor) { targetClient.PreferredColor = altHslColor; } server.SyncLobbyClients(); return(true); } }, { "shortgame", s => { if (!client.IsAdmin) { server.SendOrderTo(conn, "Message", "Only the host can set that option."); return(true); } if (server.Map.Options.ShortGame.HasValue) { server.SendOrderTo(conn, "Message", "Map has disabled short game configuration."); return(true); } bool.TryParse(s, out server.LobbyInfo.GlobalSettings.ShortGame); server.SyncLobbyGlobalSettings(); server.SendMessage("{0} {1} Short Game." .F(client.Name, server.LobbyInfo.GlobalSettings.ShortGame ? "enabled" : "disabled")); 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)); }
public WeaponInfo(string name, MiniYaml content) { FieldLoader.Load(this, content); }
public static ClientPing Deserialize(MiniYaml data) { return(FieldLoader.Load <ClientPing>(data)); }
public WarheadInfo(MiniYaml yaml) { FieldLoader.Load(this, yaml); }
public AutoConnectInfo(MiniYaml my) { FieldLoader.Load(this, my); }
public CommandBarLogic(Widget widget, World world, Dictionary <string, MiniYaml> logicArgs) { this.world = world; var highlightOnButtonPress = false; if (logicArgs.ContainsKey("HighlightOnButtonPress")) { highlightOnButtonPress = FieldLoader.GetValue <bool>("HighlightOnButtonPress", logicArgs["HighlightOnButtonPress"].Value); } var attackMoveButton = widget.GetOrNull <ButtonWidget>("ATTACK_MOVE"); if (attackMoveButton != null) { WidgetUtils.BindButtonIcon(attackMoveButton); attackMoveButton.IsDisabled = () => { UpdateStateIfNecessary(); return(attackMoveDisabled); }; attackMoveButton.IsHighlighted = () => world.OrderGenerator is AttackMoveOrderGenerator; Action <bool> toggle = allowCancel => { if (attackMoveButton.IsHighlighted()) { if (allowCancel) { world.CancelInputMode(); } } else { world.OrderGenerator = new AttackMoveOrderGenerator(selectedActors, Game.Settings.Game.MouseButtonPreference.Action); } }; attackMoveButton.OnClick = () => toggle(true); attackMoveButton.OnKeyPress = _ => toggle(false); } var forceMoveButton = widget.GetOrNull <ButtonWidget>("FORCE_MOVE"); if (forceMoveButton != null) { WidgetUtils.BindButtonIcon(forceMoveButton); forceMoveButton.IsDisabled = () => { UpdateStateIfNecessary(); return(forceMoveDisabled); }; forceMoveButton.IsHighlighted = () => !forceMoveButton.IsDisabled() && IsForceModifiersActive(Modifiers.Alt); forceMoveButton.OnClick = () => { if (forceMoveButton.IsHighlighted()) { world.CancelInputMode(); } else { world.OrderGenerator = new ForceModifiersOrderGenerator(Modifiers.Alt, true); } }; } var forceAttackButton = widget.GetOrNull <ButtonWidget>("FORCE_ATTACK"); if (forceAttackButton != null) { WidgetUtils.BindButtonIcon(forceAttackButton); forceAttackButton.IsDisabled = () => { UpdateStateIfNecessary(); return(forceAttackDisabled); }; forceAttackButton.IsHighlighted = () => !forceAttackButton.IsDisabled() && IsForceModifiersActive(Modifiers.Ctrl) && !(world.OrderGenerator is AttackMoveOrderGenerator); forceAttackButton.OnClick = () => { if (forceAttackButton.IsHighlighted()) { world.CancelInputMode(); } else { world.OrderGenerator = new ForceModifiersOrderGenerator(Modifiers.Ctrl, true); } }; } var guardButton = widget.GetOrNull <ButtonWidget>("GUARD"); if (guardButton != null) { WidgetUtils.BindButtonIcon(guardButton); guardButton.IsDisabled = () => { UpdateStateIfNecessary(); return(guardDisabled); }; guardButton.IsHighlighted = () => world.OrderGenerator is GuardOrderGenerator; Action <bool> toggle = allowCancel => { if (guardButton.IsHighlighted()) { if (allowCancel) { world.CancelInputMode(); } } else { world.OrderGenerator = new GuardOrderGenerator(selectedActors, "Guard", "guard", Game.Settings.Game.MouseButtonPreference.Action); } }; guardButton.OnClick = () => toggle(true); guardButton.OnKeyPress = _ => toggle(false); } var scatterButton = widget.GetOrNull <ButtonWidget>("SCATTER"); if (scatterButton != null) { WidgetUtils.BindButtonIcon(scatterButton); scatterButton.IsDisabled = () => { UpdateStateIfNecessary(); return(scatterDisabled); }; scatterButton.IsHighlighted = () => scatterHighlighted > 0; scatterButton.OnClick = () => { if (highlightOnButtonPress) { scatterHighlighted = 2; } PerformKeyboardOrderOnSelection(a => new Order("Scatter", a, false)); }; scatterButton.OnKeyPress = ki => { scatterHighlighted = 2; scatterButton.OnClick(); }; } var deployButton = widget.GetOrNull <ButtonWidget>("DEPLOY"); if (deployButton != null) { WidgetUtils.BindButtonIcon(deployButton); deployButton.IsDisabled = () => { UpdateStateIfNecessary(); var queued = Game.GetModifierKeys().HasModifier(Modifiers.Shift); return(!selectedDeploys.Any(pair => pair.Trait.CanIssueDeployOrder(pair.Actor, queued))); }; deployButton.IsHighlighted = () => deployHighlighted > 0; deployButton.OnClick = () => { if (highlightOnButtonPress) { deployHighlighted = 2; } var queued = Game.GetModifierKeys().HasModifier(Modifiers.Shift); PerformDeployOrderOnSelection(queued); }; deployButton.OnKeyPress = ki => { deployHighlighted = 2; deployButton.OnClick(); }; } var stopButton = widget.GetOrNull <ButtonWidget>("STOP"); if (stopButton != null) { WidgetUtils.BindButtonIcon(stopButton); stopButton.IsDisabled = () => { UpdateStateIfNecessary(); return(stopDisabled); }; stopButton.IsHighlighted = () => stopHighlighted > 0; stopButton.OnClick = () => { if (highlightOnButtonPress) { stopHighlighted = 2; } PerformKeyboardOrderOnSelection(a => new Order("Stop", a, false)); }; stopButton.OnKeyPress = ki => { stopHighlighted = 2; stopButton.OnClick(); }; } var queueOrdersButton = widget.GetOrNull <ButtonWidget>("QUEUE_ORDERS"); if (queueOrdersButton != null) { WidgetUtils.BindButtonIcon(queueOrdersButton); queueOrdersButton.IsDisabled = () => { UpdateStateIfNecessary(); return(waypointModeDisabled); }; queueOrdersButton.IsHighlighted = () => !queueOrdersButton.IsDisabled() && IsForceModifiersActive(Modifiers.Shift); queueOrdersButton.OnClick = () => { if (queueOrdersButton.IsHighlighted()) { world.CancelInputMode(); } else { world.OrderGenerator = new ForceModifiersOrderGenerator(Modifiers.Shift, false); } }; } var keyOverrides = widget.GetOrNull <LogicKeyListenerWidget>("MODIFIER_OVERRIDES"); if (keyOverrides != null) { var noShiftButtons = new[] { guardButton, deployButton, attackMoveButton }; var keyUpButtons = new[] { guardButton, attackMoveButton }; keyOverrides.AddHandler(e => { // HACK: allow command buttons to be triggered if the shift (queue order modifier) key is held if (e.Modifiers.HasModifier(Modifiers.Shift)) { var eNoShift = e; eNoShift.Modifiers &= ~Modifiers.Shift; foreach (var b in noShiftButtons) { // Button is not used by this mod if (b == null) { continue; } // Button is not valid for this event if (b.IsDisabled() || !b.Key.IsActivatedBy(eNoShift)) { continue; } // Event is not valid for this button if (!(b.DisableKeyRepeat ^ e.IsRepeat) || (e.Event == KeyInputEvent.Up && !keyUpButtons.Contains(b))) { continue; } b.OnKeyPress(e); return(true); } } // HACK: Attack move can be triggered if the ctrl (assault move modifier) // or shift (queue order modifier) keys are pressed, on both key down and key up var eNoMods = e; eNoMods.Modifiers &= ~(Modifiers.Ctrl | Modifiers.Shift); if (attackMoveButton != null && !attackMoveDisabled && attackMoveButton.Key.IsActivatedBy(eNoMods)) { attackMoveButton.OnKeyPress(e); return(true); } return(false); }); } }
public SupportPowerDecision(MiniYaml yaml) { FieldLoader.Load(this, yaml); }
static object LoadActorList(MiniYaml y, string field) { return(y.NodesDict[field].Nodes.ToDictionary( t => t.Key, t => FieldLoader.GetValue <float>(field, t.Value.Value))); }
public AssetBrowserLogic(Widget widget, Action onExit, ModData modData, World world, Dictionary <string, MiniYaml> logicArgs) { this.world = world; this.modData = modData; panel = widget; var ticker = panel.GetOrNull <LogicTickerWidget>("ANIMATION_TICKER"); if (ticker != null) { ticker.OnTick = () => { if (animateFrames) { SelectNextFrame(); } }; } var sourceDropdown = panel.GetOrNull <DropDownButtonWidget>("SOURCE_SELECTOR"); if (sourceDropdown != null) { sourceDropdown.OnMouseDown = _ => ShowSourceDropdown(sourceDropdown); sourceDropdown.GetText = () => { var name = assetSource != null?Platform.UnresolvePath(assetSource.Name) : "All Packages"; if (name.Length > 15) { name = "..." + name.Substring(name.Length - 15); } return(name); }; } var spriteWidget = panel.GetOrNull <SpriteWidget>("SPRITE"); if (spriteWidget != null) { spriteWidget.GetSprite = () => currentSprites != null ? currentSprites[currentFrame] : null; currentPalette = spriteWidget.Palette; spriteWidget.GetPalette = () => currentPalette; spriteWidget.IsVisible = () => !isVideoLoaded && !IsErrorLabelVisible; } var playerWidget = panel.GetOrNull <VqaPlayerWidget>("PLAYER"); if (playerWidget != null) { playerWidget.IsVisible = () => isVideoLoaded && !IsErrorLabelVisible; } errorLabelWidget = panel.GetOrNull <LabelWidget>("ERROR"); if (errorLabelWidget != null) { errorFont = Game.Renderer.Fonts[errorLabelWidget.Font]; } var paletteDropDown = panel.GetOrNull <DropDownButtonWidget>("PALETTE_SELECTOR"); if (paletteDropDown != null) { paletteDropDown.OnMouseDown = _ => ShowPaletteDropdown(paletteDropDown, world); paletteDropDown.GetText = () => currentPalette; } var colorPreview = panel.GetOrNull <ColorPreviewManagerWidget>("COLOR_MANAGER"); if (colorPreview != null) { colorPreview.Color = Game.Settings.Player.Color; } var colorDropdown = panel.GetOrNull <DropDownButtonWidget>("COLOR"); if (colorDropdown != null) { colorDropdown.IsDisabled = () => currentPalette != colorPreview.PaletteName; colorDropdown.OnMouseDown = _ => ColorPickerLogic.ShowColorDropDown(colorDropdown, colorPreview, world); panel.Get <ColorBlockWidget>("COLORBLOCK").GetColor = () => Game.Settings.Player.Color.RGB; } filenameInput = panel.Get <TextFieldWidget>("FILENAME_INPUT"); filenameInput.OnTextEdited = () => ApplyFilter(filenameInput.Text); filenameInput.OnEscKey = filenameInput.YieldKeyboardFocus; var frameContainer = panel.GetOrNull("FRAME_SELECTOR"); if (frameContainer != null) { frameContainer.IsVisible = () => (currentSprites != null && currentSprites.Length > 1) || (isVideoLoaded && player != null && player.Video != null && player.Video.Frames > 1); } frameSlider = panel.Get <SliderWidget>("FRAME_SLIDER"); if (frameSlider != null) { frameSlider.OnChange += x => { if (!isVideoLoaded) { currentFrame = (int)Math.Round(x); } }; frameSlider.GetValue = () => isVideoLoaded ? player.Video.CurrentFrame : currentFrame; frameSlider.IsDisabled = () => isVideoLoaded; } var frameText = panel.GetOrNull <LabelWidget>("FRAME_COUNT"); if (frameText != null) { frameText.GetText = () => isVideoLoaded ? "{0} / {1}".F(player.Video.CurrentFrame + 1, player.Video.Frames) : "{0} / {1}".F(currentFrame, currentSprites.Length - 1); } var playButton = panel.GetOrNull <ButtonWidget>("BUTTON_PLAY"); if (playButton != null) { playButton.Key = new Hotkey(Keycode.SPACE, Modifiers.None); playButton.OnClick = () => { if (isVideoLoaded) { player.Play(); } else { animateFrames = true; } }; playButton.IsVisible = () => isVideoLoaded ? player.Paused : !animateFrames; } var pauseButton = panel.GetOrNull <ButtonWidget>("BUTTON_PAUSE"); if (pauseButton != null) { pauseButton.Key = new Hotkey(Keycode.SPACE, Modifiers.None); pauseButton.OnClick = () => { if (isVideoLoaded) { player.Pause(); } else { animateFrames = false; } }; pauseButton.IsVisible = () => isVideoLoaded ? !player.Paused : animateFrames; } var stopButton = panel.GetOrNull <ButtonWidget>("BUTTON_STOP"); if (stopButton != null) { stopButton.Key = new Hotkey(Keycode.RETURN, Modifiers.None); stopButton.OnClick = () => { if (isVideoLoaded) { player.Stop(); } else { frameSlider.Value = 0; currentFrame = 0; animateFrames = false; } }; } var nextButton = panel.GetOrNull <ButtonWidget>("BUTTON_NEXT"); if (nextButton != null) { nextButton.Key = new Hotkey(Keycode.RIGHT, Modifiers.None); nextButton.OnClick = () => { if (!isVideoLoaded) { nextButton.OnClick = SelectNextFrame; } }; nextButton.IsVisible = () => !isVideoLoaded; } var prevButton = panel.GetOrNull <ButtonWidget>("BUTTON_PREV"); if (prevButton != null) { prevButton.Key = new Hotkey(Keycode.LEFT, Modifiers.None); prevButton.OnClick = () => { if (!isVideoLoaded) { SelectPreviousFrame(); } }; prevButton.IsVisible = () => !isVideoLoaded; } if (logicArgs.ContainsKey("SupportedFormats")) { allowedExtensions = FieldLoader.GetValue <string[]>("SupportedFormats", logicArgs["SupportedFormats"].Value); } else { allowedExtensions = new string[0]; } acceptablePackages = modData.ModFiles.MountedPackages.Where(p => p.Contents.Any(c => allowedExtensions.Contains(Path.GetExtension(c).ToLowerInvariant()))); assetList = panel.Get <ScrollPanelWidget>("ASSET_LIST"); template = panel.Get <ScrollItemWidget>("ASSET_TEMPLATE"); PopulateAssetList(); var closeButton = panel.GetOrNull <ButtonWidget>("CLOSE_BUTTON"); if (closeButton != null) { closeButton.OnClick = () => { if (isVideoLoaded) { player.Stop(); } Ui.CloseWindow(); onExit(); } } ; } void SelectNextFrame() { currentFrame++; if (currentFrame >= currentSprites.Length) { currentFrame = 0; } } void SelectPreviousFrame() { currentFrame--; if (currentFrame < 0) { currentFrame = currentSprites.Length - 1; } } Dictionary <string, bool> assetVisByName = new Dictionary <string, bool>(); bool FilterAsset(string filename) { var filter = filenameInput.Text; if (string.IsNullOrWhiteSpace(filter)) { return(true); } if (filename.IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0) { return(true); } return(false); } void ApplyFilter(string filename) { assetVisByName.Clear(); assetList.Layout.AdjustChildren(); assetList.ScrollToTop(); // Select the first visible var firstVisible = assetVisByName.FirstOrDefault(kvp => kvp.Value); if (firstVisible.Key != null) { LoadAsset(firstVisible.Key); } } void AddAsset(ScrollPanelWidget list, string filepath, ScrollItemWidget template) { var filename = Path.GetFileName(filepath); var item = ScrollItemWidget.Setup(template, () => currentFilename == filename, () => { LoadAsset(filename); }); item.Get <LabelWidget>("TITLE").GetText = () => filepath; item.IsVisible = () => { bool visible; if (assetVisByName.TryGetValue(filepath, out visible)) { return(visible); } visible = FilterAsset(filepath); assetVisByName.Add(filepath, visible); return(visible); }; list.AddChild(item); } bool LoadAsset(string filename) { if (isVideoLoaded) { player.Stop(); player = null; isVideoLoaded = false; } if (string.IsNullOrEmpty(filename)) { return(false); } if (!modData.DefaultFileSystem.Exists(filename)) { return(false); } errorLabelWidget.Visible = false; try { if (Path.GetExtension(filename.ToLowerInvariant()) == ".vqa") { player = panel.Get <VqaPlayerWidget>("PLAYER"); currentFilename = filename; player.Load(filename); player.DrawOverlay = false; isVideoLoaded = true; frameSlider.MaximumValue = (float)player.Video.Frames - 1; frameSlider.Ticks = 0; return(true); } currentFilename = filename; currentSprites = world.Map.Rules.Sequences.SpriteCache[filename]; currentFrame = 0; frameSlider.MaximumValue = (float)currentSprites.Length - 1; frameSlider.Ticks = currentSprites.Length; } catch (Exception ex) { if (errorLabelWidget != null) { errorLabelWidget.Text = WidgetUtils.TruncateText(errorLabelWidget.Text.Replace("{filename}", filename), errorLabelWidget.Bounds.Width, errorFont); currentSprites = new Sprite[0]; errorLabelWidget.Visible = true; } Log.AddChannel("assetbrowser", "assetbrowser.log"); Log.Write("assetbrowser", "Error reading {0}:{3} {1}{3}{2}", filename, ex.Message, ex.StackTrace, Environment.NewLine); return(false); } return(true); } bool ShowSourceDropdown(DropDownButtonWidget dropdown) { Func <IReadOnlyPackage, ScrollItemWidget, ScrollItemWidget> setupItem = (source, itemTemplate) => { var item = ScrollItemWidget.Setup(itemTemplate, () => assetSource == source, () => { assetSource = source; PopulateAssetList(); }); item.Get <LabelWidget>("LABEL").GetText = () => source != null?Platform.UnresolvePath(source.Name) : "All Packages"; return(item); }; var sources = new[] { (IReadOnlyPackage)null }.Concat(acceptablePackages); dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 280, sources, setupItem); return(true); } void PopulateAssetList() { assetList.RemoveChildren(); availableShps.Clear(); var files = assetSource != null ? assetSource.Contents : modData.ModFiles.MountedPackages.SelectMany(f => f.Contents).Distinct(); foreach (var file in files.OrderBy(s => s)) { if (allowedExtensions.Any(ext => file.EndsWith(ext, true, CultureInfo.InvariantCulture))) { AddAsset(assetList, file, template); availableShps.Add(file); } } } bool ShowPaletteDropdown(DropDownButtonWidget dropdown, World world) { Func <string, ScrollItemWidget, ScrollItemWidget> setupItem = (name, itemTemplate) => { var item = ScrollItemWidget.Setup(itemTemplate, () => currentPalette == name, () => currentPalette = name); item.Get <LabelWidget>("LABEL").GetText = () => name; return(item); }; var palettes = world.WorldActor.TraitsImplementing <IProvidesAssetBrowserPalettes>() .SelectMany(p => p.PaletteNames); dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 280, palettes, setupItem); return(true); } }
internal static void ProcessOrder(OrderManager orderManager, World world, int clientId, Order order) { switch (order.OrderString) { // Server message case "Message": TextNotificationsManager.AddSystemLine(order.TargetString); break; // Client side translated server message case "LocalizedMessage": { if (string.IsNullOrEmpty(order.TargetString)) { break; } var yaml = MiniYaml.FromString(order.TargetString); foreach (var node in yaml) { var localizedMessage = new LocalizedMessage(node.Value); TextNotificationsManager.AddSystemLine(localizedMessage.Translate(Game.ModData)); } break; } case "DisableChatEntry": { // Order must originate from the server if (clientId != 0) { break; } // Server may send MaxValue to indicate that it is disabled until further notice if (order.ExtraData == uint.MaxValue) { TextNotificationsManager.ChatDisabledUntil = uint.MaxValue; } else { TextNotificationsManager.ChatDisabledUntil = Game.RunTime + order.ExtraData; } break; } case "Chat": { var client = orderManager.LobbyInfo.ClientWithIndex(clientId); if (client == null) { break; } // Cut chat messages to the hard limit to avoid exploits var message = order.TargetString; if (message.Length > ChatMessageMaxLength) { message = order.TargetString.Substring(0, ChatMessageMaxLength); } // ExtraData 0 means this is a normal chat order, everything else is team chat if (order.ExtraData == 0) { var p = world?.FindPlayerByClient(client); var suffix = (p != null && p.WinState == WinState.Lost) ? " (Dead)" : ""; suffix = client.IsObserver ? " (Spectator)" : suffix; if (orderManager.LocalClient != null && client != orderManager.LocalClient && client.Team > 0 && client.Team == orderManager.LocalClient.Team) { suffix += " (Ally)"; } TextNotificationsManager.AddChatLine(client.Name + suffix, message, client.Color); break; } // We are still in the lobby if (world == null) { var prefix = order.ExtraData == uint.MaxValue ? "[Spectators] " : "[Team] "; if (orderManager.LocalClient != null && client.Team == orderManager.LocalClient.Team) { TextNotificationsManager.AddChatLine(prefix + client.Name, message, client.Color); } break; } var player = world.FindPlayerByClient(client); var localClientIsObserver = world.IsReplay || (orderManager.LocalClient != null && orderManager.LocalClient.IsObserver) || (world.LocalPlayer != null && world.LocalPlayer.WinState != WinState.Undefined); // ExtraData gives us the team number, uint.MaxValue means Spectators if (order.ExtraData == uint.MaxValue && localClientIsObserver) { // Validate before adding the line if (client.IsObserver || (player != null && player.WinState != WinState.Undefined)) { TextNotificationsManager.AddChatLine("[Spectators] " + client.Name, message, client.Color); } break; } var valid = client.Team == order.ExtraData && player != null && player.WinState == WinState.Undefined; var isSameTeam = orderManager.LocalClient != null && order.ExtraData == orderManager.LocalClient.Team && world.LocalPlayer != null && world.LocalPlayer.WinState == WinState.Undefined; if (valid && (isSameTeam || world.IsReplay)) { TextNotificationsManager.AddChatLine("[Team" + (world.IsReplay ? " " + order.ExtraData : "") + "] " + client.Name, message, client.Color); } break; } case "StartGame": { if (Game.ModData.MapCache[orderManager.LobbyInfo.GlobalSettings.Map].Status != MapStatus.Available) { Game.Disconnect(); Game.LoadShellMap(); // TODO: After adding a startup error dialog, notify the replay load failure. break; } if (!string.IsNullOrEmpty(order.TargetString)) { var data = MiniYaml.FromString(order.TargetString); var saveLastOrdersFrame = data.FirstOrDefault(n => n.Key == "SaveLastOrdersFrame"); if (saveLastOrdersFrame != null) { orderManager.GameSaveLastFrame = FieldLoader.GetValue <int>("saveLastOrdersFrame", saveLastOrdersFrame.Value.Value); } var saveSyncFrame = data.FirstOrDefault(n => n.Key == "SaveSyncFrame"); if (saveSyncFrame != null) { orderManager.GameSaveLastSyncFrame = FieldLoader.GetValue <int>("SaveSyncFrame", saveSyncFrame.Value.Value); } } else { TextNotificationsManager.AddSystemLine("The game has started."); } Game.StartGame(orderManager.LobbyInfo.GlobalSettings.Map, WorldType.Regular); break; } case "SaveTraitData": { var data = MiniYaml.FromString(order.TargetString)[0]; var traitIndex = int.Parse(data.Key); world?.AddGameSaveTraitData(traitIndex, data.Value); break; } case "GameSaved": if (!orderManager.World.IsReplay) { TextNotificationsManager.AddSystemLine("Game saved"); } foreach (var nsr in orderManager.World.WorldActor.TraitsImplementing <INotifyGameSaved>()) { nsr.GameSaved(orderManager.World); } break; case "PauseGame": { var client = orderManager.LobbyInfo.ClientWithIndex(clientId); if (client != null) { var pause = order.TargetString == "Pause"; // Prevent injected unpause orders from restarting a finished game if (orderManager.World.PauseStateLocked && !pause) { break; } if (orderManager.World.Paused != pause && world != null && world.LobbyInfo.NonBotClients.Count() > 1) { var pausetext = $"The game is {(pause ? "paused" : "un-paused")} by {client.Name}"; TextNotificationsManager.AddSystemLine(pausetext); } orderManager.World.Paused = pause; orderManager.World.PredictedPaused = pause; } break; } case "HandshakeRequest": { // Switch to the server's mod if we need and are able to var mod = Game.ModData.Manifest; var request = HandshakeRequest.Deserialize(order.TargetString); var externalKey = ExternalMod.MakeKey(request.Mod, request.Version); if ((request.Mod != mod.Id || request.Version != mod.Metadata.Version) && Game.ExternalMods.TryGetValue(externalKey, out var external)) { // The ConnectionFailedLogic will prompt the user to switch mods CurrentServerSettings.ServerExternalMod = external; orderManager.Connection.Dispose(); break; } Game.Settings.Player.Name = Settings.SanitizedPlayerName(Game.Settings.Player.Name); Game.Settings.Save(); // Otherwise send the handshake with our current settings and let the server reject us var info = new Session.Client() { Name = Game.Settings.Player.Name, PreferredColor = Game.Settings.Player.Color, Color = Game.Settings.Player.Color, Faction = "Random", SpawnPoint = 0, Team = 0, State = Session.ClientState.Invalid }; var localProfile = Game.LocalPlayerProfile; var response = new HandshakeResponse() { Client = info, Mod = mod.Id, Version = mod.Metadata.Version, Password = CurrentServerSettings.Password, Fingerprint = localProfile.Fingerprint, OrdersProtocol = ProtocolVersion.Orders }; if (request.AuthToken != null && response.Fingerprint != null) { response.AuthSignature = localProfile.Sign(request.AuthToken); } orderManager.IssueOrder(new Order("HandshakeResponse", null, false) { Type = OrderType.Handshake, IsImmediate = true, TargetString = response.Serialize() }); break; } case "ServerError": { orderManager.ServerError = order.TargetString; orderManager.AuthenticationFailed = false; break; } case "AuthenticationError": { // The ConnectionFailedLogic will prompt the user for the password orderManager.ServerError = order.TargetString; orderManager.AuthenticationFailed = true; break; } case "SyncInfo": { orderManager.LobbyInfo = Session.Deserialize(order.TargetString); Game.SyncLobbyInfo(); break; } case "SyncLobbyClients": { var clients = new List <Session.Client>(); var nodes = MiniYaml.FromString(order.TargetString); foreach (var node in nodes) { var strings = node.Key.Split('@'); if (strings[0] == "Client") { clients.Add(Session.Client.Deserialize(node.Value)); } } orderManager.LobbyInfo.Clients = clients; Game.SyncLobbyInfo(); break; } case "SyncLobbySlots": { var slots = new Dictionary <string, Session.Slot>(); var nodes = MiniYaml.FromString(order.TargetString); foreach (var node in nodes) { var strings = node.Key.Split('@'); if (strings[0] == "Slot") { var slot = Session.Slot.Deserialize(node.Value); slots.Add(slot.PlayerReference, slot); } } orderManager.LobbyInfo.Slots = slots; Game.SyncLobbyInfo(); break; } case "SyncLobbyGlobalSettings": { var nodes = MiniYaml.FromString(order.TargetString); foreach (var node in nodes) { var strings = node.Key.Split('@'); if (strings[0] == "GlobalSettings") { orderManager.LobbyInfo.GlobalSettings = Session.Global.Deserialize(node.Value); } } Game.SyncLobbyInfo(); break; } case "SyncConnectionQuality": { var nodes = MiniYaml.FromString(order.TargetString); foreach (var node in nodes) { var strings = node.Key.Split('@'); if (strings[0] == "ConnectionQuality") { var client = orderManager.LobbyInfo.Clients.FirstOrDefault(c => c.Index == int.Parse(strings[1])); if (client != null) { client.ConnectionQuality = FieldLoader.GetValue <Session.ConnectionQuality>("ConnectionQuality", node.Value.Value); } } } break; } default: { if (world == null) { break; } if (order.GroupedActors == null) { ResolveOrder(order, world, orderManager, clientId); } else { foreach (var subject in order.GroupedActors) { ResolveOrder(Order.FromGroupedOrder(order, subject), world, orderManager, clientId); } } break; } } }
public bool InterpretCommand(S server, Connection conn, Session.Client client, string cmd) { if (server == null || conn == null || client == null || !ValidateCommand(server, conn, client, cmd)) { return(false); } var dict = new Dictionary <string, Func <string, bool> > { { "state", s => { var state = Session.ClientState.Invalid; if (!Enum <Session.ClientState> .TryParse(s, false, out state)) { server.SendOrderTo(conn, "Message", "Malformed state command"); return(true); } client.State = state; Log.Write("server", "Player @{0} is {1}", conn.Socket.RemoteEndPoint, client.State); server.SyncLobbyClients(); CheckAutoStart(server); return(true); } }, { "startgame", s => { if (!client.IsAdmin) { server.SendOrderTo(conn, "Message", "Only the host can start the game."); return(true); } if (server.LobbyInfo.Slots.Any(sl => sl.Value.Required && server.LobbyInfo.ClientInSlot(sl.Key) == null)) { server.SendOrderTo(conn, "Message", "Unable to start the game until required slots are full."); return(true); } if (!server.LobbyInfo.GlobalSettings.EnableSingleplayer && server.LobbyInfo.Clients.Where(c => c.Bot == null && c.Slot != null).Count() == 1) { server.SendOrderTo(conn, "Message", server.TwoHumansRequiredText); return(true); } server.StartGame(); return(true); } }, { "slot", s => { if (!server.LobbyInfo.Slots.ContainsKey(s)) { Log.Write("server", "Invalid slot: {0}", s); return(false); } var slot = server.LobbyInfo.Slots[s]; if (slot.Closed || server.LobbyInfo.ClientInSlot(s) != null) { return(false); } // If the previous slot had a locked spawn then we must not carry that to the new slot var oldSlot = client.Slot != null ? server.LobbyInfo.Slots[client.Slot] : null; if (oldSlot != null && oldSlot.LockSpawn) { client.SpawnPoint = 0; } client.Slot = s; S.SyncClientToPlayerReference(client, server.Map.Players.Players[s]); if (!slot.LockColor) { client.PreferredColor = client.Color = SanitizePlayerColor(server, client.Color, client.Index, conn); } server.SyncLobbyClients(); CheckAutoStart(server); return(true); } }, { "allow_spectators", s => { if (bool.TryParse(s, out server.LobbyInfo.GlobalSettings.AllowSpectators)) { server.SyncLobbyGlobalSettings(); return(true); } else { server.SendOrderTo(conn, "Message", "Malformed allow_spectate command"); return(true); } } }, { "spectate", s => { if (server.LobbyInfo.GlobalSettings.AllowSpectators || client.IsAdmin) { client.Slot = null; client.SpawnPoint = 0; client.Color = HSLColor.FromRGB(255, 255, 255); server.SyncLobbyClients(); CheckAutoStart(server); return(true); } else { return(false); } } }, { "slot_close", s => { if (!ValidateSlotCommand(server, conn, client, s, true)) { return(false); } // kick any player that's in the slot var occupant = server.LobbyInfo.ClientInSlot(s); if (occupant != null) { if (occupant.Bot != null) { server.LobbyInfo.Clients.Remove(occupant); server.SyncLobbyClients(); var ping = server.LobbyInfo.PingFromClient(occupant); if (ping != null) { server.LobbyInfo.ClientPings.Remove(ping); server.SyncClientPing(); } } else { var occupantConn = server.Conns.FirstOrDefault(c => c.PlayerIndex == occupant.Index); if (occupantConn != null) { server.SendOrderTo(occupantConn, "ServerError", "Your slot was closed by the host."); server.DropClient(occupantConn); } } } server.LobbyInfo.Slots[s].Closed = true; server.SyncLobbySlots(); return(true); } }, { "slot_open", s => { if (!ValidateSlotCommand(server, conn, client, s, true)) { return(false); } var slot = server.LobbyInfo.Slots[s]; slot.Closed = false; server.SyncLobbySlots(); // Slot may have a bot in it var occupant = server.LobbyInfo.ClientInSlot(s); if (occupant != null && occupant.Bot != null) { server.LobbyInfo.Clients.Remove(occupant); var ping = server.LobbyInfo.PingFromClient(occupant); if (ping != null) { server.LobbyInfo.ClientPings.Remove(ping); server.SyncClientPing(); } } server.SyncLobbyClients(); return(true); } }, { "slot_bot", s => { var parts = s.Split(' '); if (parts.Length < 3) { server.SendOrderTo(conn, "Message", "Malformed slot_bot command"); return(true); } if (!ValidateSlotCommand(server, conn, client, parts[0], true)) { return(false); } var slot = server.LobbyInfo.Slots[parts[0]]; var bot = server.LobbyInfo.ClientInSlot(parts[0]); int controllerClientIndex; if (!Exts.TryParseIntegerInvariant(parts[1], out controllerClientIndex)) { Log.Write("server", "Invalid bot controller client index: {0}", parts[1]); return(false); } var botType = parts.Skip(2).JoinWith(" "); // Invalid slot if (bot != null && bot.Bot == null) { server.SendOrderTo(conn, "Message", "Can't add bots to a slot with another client."); return(true); } slot.Closed = false; if (bot == null) { // Create a new bot bot = new Session.Client() { Index = server.ChooseFreePlayerIndex(), Name = botType, Bot = botType, Slot = parts[0], Faction = "Random", SpawnPoint = 0, Team = 0, State = Session.ClientState.NotReady, BotControllerClientIndex = controllerClientIndex }; // Pick a random color for the bot var validator = server.ModData.Manifest.Get <ColorValidator>(); var tileset = server.Map.Rules.TileSet; var terrainColors = tileset.TerrainInfo.Where(ti => ti.RestrictPlayerColor).Select(ti => ti.Color); var playerColors = server.LobbyInfo.Clients.Select(c => c.Color.RGB) .Concat(server.Map.Players.Players.Values.Select(p => p.Color.RGB)); bot.Color = bot.PreferredColor = validator.RandomValidColor(server.Random, terrainColors, playerColors); server.LobbyInfo.Clients.Add(bot); } else { // Change the type of the existing bot bot.Name = botType; bot.Bot = botType; } S.SyncClientToPlayerReference(bot, server.Map.Players.Players[parts[0]]); server.SyncLobbyClients(); server.SyncLobbySlots(); return(true); } }, { "map", s => { if (!client.IsAdmin) { server.SendOrderTo(conn, "Message", "Only the host can change the map."); return(true); } var lastMap = server.LobbyInfo.GlobalSettings.Map; Action <MapPreview> selectMap = map => { // Make sure the map hasn't changed in the meantime if (server.LobbyInfo.GlobalSettings.Map != lastMap) { return; } server.LobbyInfo.GlobalSettings.Map = map.Uid; var oldSlots = server.LobbyInfo.Slots.Keys.ToArray(); server.Map = server.ModData.MapCache[server.LobbyInfo.GlobalSettings.Map]; server.LobbyInfo.Slots = server.Map.Players.Players .Select(p => MakeSlotFromPlayerReference(p.Value)) .Where(ss => ss != null) .ToDictionary(ss => ss.PlayerReference, ss => ss); LoadMapSettings(server, server.LobbyInfo.GlobalSettings, server.Map.Rules); // Reset client states foreach (var c in server.LobbyInfo.Clients) { c.State = Session.ClientState.Invalid; } // Reassign players into new slots based on their old slots: // - Observers remain as observers // - Players who now lack a slot are made observers // - Bots who now lack a slot are dropped // - Bots who are not defined in the map rules are dropped var botNames = server.Map.Rules.Actors["player"].TraitInfos <IBotInfo>().Select(t => t.Name); var slots = server.LobbyInfo.Slots.Keys.ToArray(); var i = 0; foreach (var os in oldSlots) { var c = server.LobbyInfo.ClientInSlot(os); if (c == null) { continue; } c.SpawnPoint = 0; c.Slot = i < slots.Length ? slots[i++] : null; if (c.Slot != null) { // Remove Bot from slot if slot forbids bots if (c.Bot != null && (!server.Map.Players.Players[c.Slot].AllowBots || !botNames.Contains(c.Bot))) { server.LobbyInfo.Clients.Remove(c); } S.SyncClientToPlayerReference(c, server.Map.Players.Players[c.Slot]); } else if (c.Bot != null) { server.LobbyInfo.Clients.Remove(c); } } // Validate if color is allowed and get an alternative if it isn't foreach (var c in server.LobbyInfo.Clients) { if (c.Slot == null || (c.Slot != null && !server.LobbyInfo.Slots[c.Slot].LockColor)) { c.Color = c.PreferredColor = SanitizePlayerColor(server, c.Color, c.Index, conn); } } server.SyncLobbyInfo(); server.SendMessage("{0} changed the map to {1}.".F(client.Name, server.Map.Title)); if (server.Map.DefinesUnsafeCustomRules) { server.SendMessage("This map contains custom rules. Game experience may change."); } if (!server.LobbyInfo.GlobalSettings.EnableSingleplayer) { server.SendMessage(server.TwoHumansRequiredText); } else if (server.Map.Players.Players.Where(p => p.Value.Playable).All(p => !p.Value.AllowBots)) { server.SendMessage("Bots have been disabled on this map."); } var briefing = MissionBriefingOrDefault(server); if (briefing != null) { server.SendMessage(briefing); } }; Action queryFailed = () => server.SendOrderTo(conn, "Message", "Map was not found on server."); var m = server.ModData.MapCache[s]; if (m.Status == MapStatus.Available || m.Status == MapStatus.DownloadAvailable) { selectMap(m); } else if (server.Settings.QueryMapRepository) { server.SendOrderTo(conn, "Message", "Searching for map on the Resource Center..."); server.ModData.MapCache.QueryRemoteMapDetails(new[] { s }, selectMap, queryFailed); } else { queryFailed(); } return(true); } }, { "option", s => { if (!client.IsAdmin) { server.SendOrderTo(conn, "Message", "Only the host can change the configuration."); return(true); } var allOptions = server.Map.Rules.Actors["player"].TraitInfos <ILobbyOptions>() .Concat(server.Map.Rules.Actors["world"].TraitInfos <ILobbyOptions>()) .SelectMany(t => t.LobbyOptions(server.Map.Rules)); // Overwrite keys with duplicate ids var options = new Dictionary <string, LobbyOption>(); foreach (var o in allOptions) { options[o.Id] = o; } var split = s.Split(' '); LobbyOption option; if (split.Length < 2 || !options.TryGetValue(split[0], out option) || !option.Values.ContainsKey(split[1])) { server.SendOrderTo(conn, "Message", "Invalid configuration command."); return(true); } if (option.Locked) { server.SendOrderTo(conn, "Message", "{0} cannot be changed.".F(option.Name)); return(true); } var oo = server.LobbyInfo.GlobalSettings.LobbyOptions[option.Id]; if (oo.Value == split[1]) { return(true); } oo.Value = oo.PreferredValue = split[1]; if (option.Id == "gamespeed") { var speed = server.ModData.Manifest.Get <GameSpeeds>().Speeds[oo.Value]; server.LobbyInfo.GlobalSettings.Timestep = speed.Timestep; server.LobbyInfo.GlobalSettings.OrderLatency = speed.OrderLatency; } server.SyncLobbyGlobalSettings(); server.SendMessage(option.ValueChangedMessage(client.Name, split[1])); return(true); } }, { "assignteams", s => { if (!client.IsAdmin) { server.SendOrderTo(conn, "Message", "Only the host can set that option."); return(true); } int teamCount; if (!Exts.TryParseIntegerInvariant(s, out teamCount)) { server.SendOrderTo(conn, "Message", "Number of teams could not be parsed: {0}".F(s)); return(true); } var maxTeams = (server.LobbyInfo.Clients.Count(c => c.Slot != null) + 1) / 2; teamCount = teamCount.Clamp(0, maxTeams); var clients = server.LobbyInfo.Slots .Select(slot => server.LobbyInfo.ClientInSlot(slot.Key)) .Where(c => c != null && !server.LobbyInfo.Slots[c.Slot].LockTeam); var assigned = 0; var clientCount = clients.Count(); foreach (var player in clients) { // Free for all if (teamCount == 0) { player.Team = 0; } // Humans vs Bots else if (teamCount == 1) { player.Team = player.Bot == null ? 1 : 2; } else { player.Team = assigned++ *teamCount / clientCount + 1; } } server.SyncLobbyClients(); return(true); } }, { "kick", s => { if (!client.IsAdmin) { server.SendOrderTo(conn, "Message", "Only the host can kick players."); return(true); } var split = s.Split(' '); if (split.Length < 2) { server.SendOrderTo(conn, "Message", "Malformed kick command"); return(true); } int kickClientID; Exts.TryParseIntegerInvariant(split[0], out kickClientID); var kickConn = server.Conns.SingleOrDefault(c => server.GetClient(c) != null && server.GetClient(c).Index == kickClientID); if (kickConn == null) { server.SendOrderTo(conn, "Message", "No-one in that slot."); return(true); } var kickClient = server.GetClient(kickConn); Log.Write("server", "Kicking client {0}.", kickClientID); server.SendMessage("{0} kicked {1} from the server.".F(client.Name, kickClient.Name)); server.SendOrderTo(kickConn, "ServerError", "You have been kicked from the server."); server.DropClient(kickConn); bool tempBan; bool.TryParse(split[1], out tempBan); if (tempBan) { Log.Write("server", "Temporarily banning client {0} ({1}).", kickClientID, kickClient.IpAddress); server.SendMessage("{0} temporarily banned {1} from the server.".F(client.Name, kickClient.Name)); server.TempBans.Add(kickClient.IpAddress); } server.SyncLobbyClients(); server.SyncLobbySlots(); return(true); } }, { "name", s => { var sanitizedName = Settings.SanitizedPlayerName(s); if (sanitizedName == client.Name) { return(true); } Log.Write("server", "Player@{0} is now known as {1}.", conn.Socket.RemoteEndPoint, sanitizedName); server.SendMessage("{0} is now known as {1}.".F(client.Name, sanitizedName)); client.Name = sanitizedName; server.SyncLobbyClients(); return(true); } }, { "faction", s => { var parts = s.Split(' '); var targetClient = server.LobbyInfo.ClientWithIndex(Exts.ParseIntegerInvariant(parts[0])); // Only the host can change other client's info if (targetClient.Index != client.Index && !client.IsAdmin) { return(true); } // Map has disabled faction changes if (server.LobbyInfo.Slots[targetClient.Slot].LockFaction) { return(true); } var factions = server.Map.Rules.Actors["world"].TraitInfos <FactionInfo>() .Where(f => f.Selectable).Select(f => f.InternalName); if (!factions.Contains(parts[1])) { server.SendOrderTo(conn, "Message", "Invalid faction selected: {0}".F(parts[1])); server.SendOrderTo(conn, "Message", "Supported values: {0}".F(factions.JoinWith(", "))); return(true); } targetClient.Faction = parts[1]; server.SyncLobbyClients(); return(true); } }, { "team", s => { var parts = s.Split(' '); var targetClient = server.LobbyInfo.ClientWithIndex(Exts.ParseIntegerInvariant(parts[0])); // Only the host can change other client's info if (targetClient.Index != client.Index && !client.IsAdmin) { return(true); } // Map has disabled team changes if (server.LobbyInfo.Slots[targetClient.Slot].LockTeam) { return(true); } int team; if (!Exts.TryParseIntegerInvariant(parts[1], out team)) { Log.Write("server", "Invalid team: {0}", s); return(false); } targetClient.Team = team; server.SyncLobbyClients(); return(true); } }, { "spawn", s => { var parts = s.Split(' '); var targetClient = server.LobbyInfo.ClientWithIndex(Exts.ParseIntegerInvariant(parts[0])); // Only the host can change other client's info if (targetClient.Index != client.Index && !client.IsAdmin) { return(true); } // Spectators don't need a spawnpoint if (targetClient.Slot == null) { return(true); } // Map has disabled spawn changes if (server.LobbyInfo.Slots[targetClient.Slot].LockSpawn) { return(true); } int spawnPoint; if (!Exts.TryParseIntegerInvariant(parts[1], out spawnPoint) || spawnPoint <0 || spawnPoint> server.Map.SpawnPoints.Length) { Log.Write("server", "Invalid spawn point: {0}", parts[1]); return(true); } if (server.LobbyInfo.Clients.Where(cc => cc != client).Any(cc => (cc.SpawnPoint == spawnPoint) && (cc.SpawnPoint != 0))) { server.SendOrderTo(conn, "Message", "You cannot occupy the same spawn point as another player."); return(true); } // Check if any other slot has locked the requested spawn if (spawnPoint > 0) { var spawnLockedByAnotherSlot = server.LobbyInfo.Slots.Where(ss => ss.Value.LockSpawn).Any(ss => { var pr = PlayerReferenceForSlot(server, ss.Value); return(pr != null && pr.Spawn == spawnPoint); }); if (spawnLockedByAnotherSlot) { server.SendOrderTo(conn, "Message", "The spawn point is locked to another player slot."); return(true); } } targetClient.SpawnPoint = spawnPoint; server.SyncLobbyClients(); return(true); } }, { "color", s => { var parts = s.Split(' '); var targetClient = server.LobbyInfo.ClientWithIndex(Exts.ParseIntegerInvariant(parts[0])); // Only the host can change other client's info if (targetClient.Index != client.Index && !client.IsAdmin) { return(true); } // Spectator or map has disabled color changes if (targetClient.Slot == null || server.LobbyInfo.Slots[targetClient.Slot].LockColor) { return(true); } // Validate if color is allowed and get an alternative it isn't var newColor = FieldLoader.GetValue <HSLColor>("(value)", parts[1]); targetClient.Color = SanitizePlayerColor(server, newColor, targetClient.Index, conn); // Only update player's preferred color if new color is valid if (newColor == targetClient.Color) { targetClient.PreferredColor = targetClient.Color; } server.SyncLobbyClients(); return(true); } }, { "sync_lobby", s => { if (!client.IsAdmin) { server.SendOrderTo(conn, "Message", "Only the host can set lobby info"); return(true); } var lobbyInfo = Session.Deserialize(s); if (lobbyInfo == null) { server.SendOrderTo(conn, "Message", "Invalid Lobby Info Sent"); return(true); } server.LobbyInfo = lobbyInfo; server.SyncLobbyInfo(); return(true); } } }; var cmdName = cmd.Split(' ').First(); var cmdValue = cmd.Split(' ').Skip(1).JoinWith(" "); Func <string, bool> a; if (!dict.TryGetValue(cmdName, out a)) { return(false); } return(a(cmdValue)); }
void IUtilityCommand.Run(Utility utility, string[] args) { // HACK: The engine code assumes that Game.modData is set. Game.ModData = utility.ModData; var version = utility.ModData.Manifest.Metadata.Version; if (args.Length > 1) { version = args[1]; } Console.WriteLine( "This documentation is aimed at modders. It displays a template for weapon definitions " + "as well as its contained types (warheads and projectiles) with default values and developer commentary. " + "Please do not edit it directly, but add new `[Desc(\"String\")]` tags to the source code. This file has been " + "automatically generated for version {0} of OpenRA.", version); Console.WriteLine(); var doc = new StringBuilder(); var currentNamespace = ""; var objectCreator = utility.ModData.ObjectCreator; var weaponInfo = objectCreator.GetTypesImplementing <WeaponInfo>(); var warheads = objectCreator.GetTypesImplementing <IWarhead>().OrderBy(t => t.Namespace); var projectiles = objectCreator.GetTypesImplementing <IProjectileInfo>().OrderBy(t => t.Namespace); var weaponTypes = Enumerable.Concat(weaponInfo, Enumerable.Concat(projectiles, warheads)); foreach (var t in weaponTypes) { // skip helpers like TraitInfo<T> if (t.ContainsGenericParameters || t.IsAbstract) { continue; } if (currentNamespace != t.Namespace) { currentNamespace = t.Namespace; doc.AppendLine(); doc.AppendLine("## {0}".F(currentNamespace)); } var traitName = t.Name.EndsWith("Info") ? t.Name.Substring(0, t.Name.Length - 4) : t.Name; doc.AppendLine(); doc.AppendLine("### {0}".F(traitName)); var traitDescLines = t.GetCustomAttributes <DescAttribute>(false).SelectMany(d => d.Lines); foreach (var line in traitDescLines) { doc.AppendLine(line); } var infos = FieldLoader.GetTypeLoadInfo(t); if (!infos.Any()) { continue; } doc.AppendLine("<table>"); doc.AppendLine("<tr><th>Property</th><th>Default Value</th><th>Type</th><th>Description</th></tr>"); var liveTraitInfo = t == typeof(WeaponInfo) ? null : objectCreator.CreateBasic(t); foreach (var info in infos) { var fieldDescLines = info.Field.GetCustomAttributes <DescAttribute>(true).SelectMany(d => d.Lines); var fieldType = Util.FriendlyTypeName(info.Field.FieldType); var defaultValue = liveTraitInfo == null ? "" : FieldSaver.SaveField(liveTraitInfo, info.Field.Name).Value.Value; doc.Append("<tr><td>{0}</td><td>{1}</td><td>{2}</td>".F(info.YamlName, defaultValue, fieldType)); doc.Append("<td>"); foreach (var line in fieldDescLines) { doc.Append(line + " "); } doc.AppendLine("</td></tr>"); } doc.AppendLine("</table>"); } Console.Write(doc.ToString()); }
static void ExtractFromISCab(string path, MiniYaml actionYaml, List <string> extractedFiles, Action <string> updateMessage) { var sourcePath = Path.Combine(path, actionYaml.Value); // Try as an absolute path if (!File.Exists(sourcePath)) { sourcePath = Platform.ResolvePath(actionYaml.Value); } var volumeNode = actionYaml.Nodes.FirstOrDefault(n => n.Key == "Volumes"); if (volumeNode == null) { throw new InvalidDataException("extract-iscab entry doesn't define a Volumes node"); } var extractNode = actionYaml.Nodes.FirstOrDefault(n => n.Key == "Extract"); if (extractNode == null) { throw new InvalidDataException("extract-iscab entry doesn't define an Extract node"); } var volumes = new Dictionary <int, Stream>(); try { foreach (var node in volumeNode.Value.Nodes) { var volume = FieldLoader.GetValue <int>("(key)", node.Key); var stream = File.OpenRead(Path.Combine(path, node.Value.Value)); volumes.Add(volume, stream); } using (var source = File.OpenRead(sourcePath)) { var reader = new InstallShieldCABCompression(source, volumes); foreach (var node in extractNode.Value.Nodes) { var targetPath = Platform.ResolvePath(node.Key); if (File.Exists(targetPath)) { Log.Write("install", "Skipping installed file " + targetPath); continue; } extractedFiles.Add(targetPath); Directory.CreateDirectory(Path.GetDirectoryName(targetPath)); using (var target = File.OpenWrite(targetPath)) { Log.Write("install", "Extracting {0} -> {1}".F(sourcePath, targetPath)); var displayFilename = Path.GetFileName(Path.GetFileName(targetPath)); Action <int> onProgress = percent => updateMessage("Extracting {0} ({1}%)".F(displayFilename, percent)); reader.ExtractFile(node.Value.Value, target, onProgress); } } } } finally { foreach (var kv in volumes) { kv.Value.Dispose(); } } }
public static T Get <T>(string key) { return(FieldLoader.GetValue <T>(key, data[key])); }