static void DrawModalWindow(string text, Func <bool> shouldShow, Action onCancel, string cancelButtonLabel) { string textWithEllipsis = $"{text}{MpUI.FixedEllipsis()}"; float textWidth = Text.CalcSize(textWithEllipsis).x; float windowWidth = Math.Max(240f, textWidth + 40f); float windowHeight = onCancel != null ? 100f : 75f; var rect = new Rect(0, 0, windowWidth, windowHeight).CenterOn(new Rect(0, 0, UI.screenWidth, UI.screenHeight)); Find.WindowStack.ImmediateWindow(ModalWindowId, rect, WindowLayer.Super, () => { if (!shouldShow()) { return; } var textRect = rect.AtZero(); if (onCancel != null) { textRect.yMin += 5f; textRect.height -= 50f; } Text.Anchor = TextAnchor.MiddleCenter; Text.Font = GameFont.Small; Widgets.Label(textRect, text); Text.Anchor = TextAnchor.UpperLeft; var cancelBtn = new Rect(0, textRect.yMax, 100f, 35f).CenteredOnXIn(textRect); if (onCancel != null && Widgets.ButtonText(cancelBtn, cancelButtonLabel)) { onCancel(); } }, absorbInputAroundWindow: true); }
public void HandleJoinData(ByteReader data) { Multiplayer.session.gameName = data.ReadString(); Multiplayer.session.playerId = data.ReadInt32(); var remoteInfo = new RemoteData { remoteRwVersion = data.ReadString(), remoteMpVersion = data.ReadString(), remoteAddress = Multiplayer.session.address, remotePort = Multiplayer.session.port, remoteSteamHost = Multiplayer.session.steamHost }; var defDiff = false; var defsData = new ByteReader(data.ReadPrefixedBytes()); foreach (var local in MultiplayerData.localDefInfos) { var status = (DefCheckStatus)defsData.ReadByte(); local.Value.status = status; if (status != DefCheckStatus.Ok) { defDiff = true; } } JoinData.ReadServerData(data.ReadPrefixedBytes(), remoteInfo); OnMainThread.Schedule(Complete, 0.3f); void Complete() { if (JoinData.CompareToLocal(remoteInfo) && !defDiff) { StartDownloading(); return; } if (defDiff) { Multiplayer.StopMultiplayer(); } var connectingWindow = Find.WindowStack.WindowOfType <BaseConnectingWindow>(); MpUI.ClearWindowStack(); var defDiffStr = "\n\n" + MultiplayerData.localDefInfos .Where(kv => kv.Value.status != DefCheckStatus.Ok) .Take(10) .Join(kv => $"{kv.Key}: {kv.Value.status}", "\n"); Find.WindowStack.Add(new JoinDataWindow(remoteInfo) { connectAnywayDisabled = defDiff ? "MpMismatchDefsDiff".Translate() + defDiffStr : null, connectAnywayCallback = () => { Find.WindowStack.Add(connectingWindow); StartDownloading(); } }); void StartDownloading() { connection.Send(Packets.Client_WorldRequest); subState = JoiningState.Waiting; } } }
private void DrawChat(Rect inRect) { MpUI.TryUnfocusCurrentNamedControl(this); Rect outRect = new Rect(0f, 0f, inRect.width, inRect.height - 30f); Rect viewRect = new Rect(0f, 0f, inRect.width - 16f, messagesHeight + 10f); float width = viewRect.width; Rect textField = new Rect(20f, outRect.yMax + 5f, width - 70f, 25f); GUI.BeginGroup(inRect); GUI.SetNextControlName("chat_input"); currentMsg = Widgets.TextField(textField, currentMsg); currentMsg = currentMsg.Substring(0, Math.Min(currentMsg.Length, ServerPlayingState.MaxChatMsgLength)); Widgets.BeginScrollView(outRect, ref chatScroll, viewRect); float yPos = 0; GUI.color = Color.white; int i = 0; foreach (ChatMsg msg in Multiplayer.session.messages) { float height = Text.CalcHeight(msg.Msg, width - 20f); float textWidth = Text.CalcSize(msg.Msg).x + 15; Rect msgRect = new Rect(20f, yPos, width - 20f, height); if (Mouse.IsOver(msgRect)) { GUI.DrawTexture(msgRect, SelectedMsg); if (msg.TimeStamp != null) { TooltipHandler.TipRegion(msgRect, msg.TimeStamp.ToString("yyyy-MM-dd HH:mm")); } } Color cursorColor = GUI.skin.settings.cursorColor; GUI.skin.settings.cursorColor = new Color(0, 0, 0, 0); msgRect.width = Math.Min(textWidth, msgRect.width); bool mouseOver = Mouse.IsOver(msgRect); if (mouseOver && msg.Clickable) { GUI.color = new Color(0.8f, 0.8f, 1); } GUI.SetNextControlName("chat_msg_" + i++); Widgets.TextArea(msgRect, msg.Msg, true); if (mouseOver && msg.Clickable) { GUI.color = Color.white; if (Event.current.type == EventType.MouseUp) { msg.Click(); } } GUI.skin.settings.cursorColor = cursorColor; yPos += height; } if (Event.current.type == EventType.Layout) { messagesHeight = yPos; } Widgets.EndScrollView(); if (Widgets.ButtonText(new Rect(textField.xMax + 5f, textField.y, 55f, textField.height), "MpChatSend".Translate())) { SendMsg(); } GUI.EndGroup(); if (!hasBeenFocused && Event.current.type == EventType.Repaint) { chatScroll.y = messagesHeight; GUI.FocusControl("chat_input"); TextEditor editor = (TextEditor)GUIUtility.GetStateObject(typeof(TextEditor), GUIUtility.keyboardControl); editor.OnFocus(); editor.MoveTextEnd(); hasBeenFocused = true; } }
private void DrawLan(Rect inRect) { using (MpStyle.Set(TextAnchor.MiddleCenter)) Widgets.Label(new Rect(inRect.x, 8f, inRect.width, 40), "MpLanSearching".Translate() + MpUI.FixedEllipsis()); inRect.yMin += 40f; float margin = 100; Rect outRect = new Rect(margin, inRect.yMin + 10, inRect.width - 2 * margin, inRect.height - 20); float height = servers.Count * 40; Rect viewRect = new Rect(0, 0, outRect.width - 16f, height); Widgets.BeginScrollView(outRect, ref lanScroll, viewRect, true); float y = 0; int i = 0; foreach (LanServer server in servers) { Rect entryRect = new Rect(0, y, viewRect.width, 40); if (i % 2 == 0) { Widgets.DrawAltRect(entryRect); } using (MpStyle.Set(TextAnchor.MiddleLeft)) Widgets.Label(entryRect.Right(5), "" + server.endpoint); Rect playButton = new Rect(entryRect.xMax - 75, entryRect.y + 5, 70, 40 - 10); if (Widgets.ButtonText(playButton, ">>")) { Close(false); Log.Message("Connecting to lan server"); var address = server.endpoint.Address.ToString(); var port = server.endpoint.Port; ClientUtil.TryConnectWithWindow(address, port); } y += entryRect.height; i++; } Widgets.EndScrollView(); }
private void DrawInfoButtons() { float x = 0; const string WebsiteLink = "https://rimworldmultiplayer.com"; const string DiscordLink = "https://discord.gg/n5E2cb2Y4Z"; bool Button(Texture2D icon, string labelKey, string tip, Color baseIconColor, float iconSize = 24f) { var label = labelKey.Translate(); var labelWidth = Text.CalcSize(label).x; var btn = new Rect(x, 0, 24 + 1 + labelWidth, 24); var mouseOver = Mouse.IsOver(btn); MouseoverSounds.DoRegion(btn); TooltipHandler.TipRegion(btn, tip); using (MpStyle.Set(mouseOver ? Color.yellow : baseIconColor)) { GUI.DrawTexture(new Rect(x += (24 - iconSize) / 2, (24 - iconSize) / 2, iconSize, iconSize), icon); x += 24; } x += 1; using (MpStyle.Set(mouseOver ? Color.yellow : Color.white)) using (MpStyle.Set(TextAnchor.MiddleCenter)) MpUI.Label(new Rect(x, 0, labelWidth, 24f), labelKey.Translate()); x += labelWidth; x += 10; return(Widgets.ButtonInvisible(btn)); } const string compatLabel = "MpCompatibilityButton"; const string compatLabelDesc = "MpCompatibilityButtonDesc"; if (Button(TexButton.ToggleLog, compatLabel, MpUtil.TranslateWithDoubleNewLines(compatLabelDesc, 2), Color.grey, 20)) { Find.WindowStack.Add(new ModCompatWindow(null, false, false, null)); } if (Button(MultiplayerStatic.WebsiteIcon, "MpWebsiteButton", "MpLinkButtonDesc".Translate() + " " + WebsiteLink, Color.grey, 20)) { Application.OpenURL(WebsiteLink); } if (Button(MultiplayerStatic.DiscordIcon, "MpDiscordButton", "MpLinkButtonDesc".Translate() + " " + DiscordLink, Color.white)) { Application.OpenURL(DiscordLink); } if (false) // todo { Button( TexButton.NewItem, "MpActiveConfigsButton", "MpActiveConfigsButtonDesc1".Translate("Player's game") + "\n\n" + "MpActiveConfigsButtonDesc2".Translate(), Color.grey, 20 ); } }
static void DrawTimelineWindow() { Rect rect = new Rect(0, 30f, UI.screenWidth - TimelineMargin * 2, TimelineHeight); Widgets.DrawBoxSolid(rect, new Color(0.6f, 0.6f, 0.6f, 0.8f)); int timerStart = Multiplayer.session.replayTimerStart >= 0 ? Multiplayer.session.replayTimerStart : Multiplayer.session.dataSnapshot.cachedAtTime; int timerEnd = Multiplayer.session.replayTimerEnd >= 0 ? Multiplayer.session.replayTimerEnd : TickPatch.tickUntil; int timeLen = timerEnd - timerStart; MpUI.DrawRotatedLine(new Vector2(rect.xMin + 2f, rect.center.y), TimelineHeight, 20f, 90f, Color.white); MpUI.DrawRotatedLine(new Vector2(rect.xMax - 2f, rect.center.y), TimelineHeight, 20f, 90f, Color.white); float progress = (TickPatch.Timer - timerStart) / (float)timeLen; float progressX = rect.xMin + progress * rect.width; MpUI.DrawRotatedLine(new Vector2((int)progressX, rect.center.y), TimelineHeight, 20f, 90f, Color.green); float mouseX = Event.current.mousePosition.x; ReplayEvent mouseEvent = null; foreach (var ev in Multiplayer.session.events) { if (ev.time < timerStart || ev.time > timerEnd) { continue; } var pointX = rect.xMin + (ev.time - timerStart) / (float)timeLen * rect.width; //GUI.DrawTexture(new Rect(pointX - 12f, rect.yMin - 24f, 24f, 24f), texture); MpUI.DrawRotatedLine(new Vector2(pointX, rect.center.y), TimelineHeight, 20f, 90f, ev.color); if (Mouse.IsOver(rect) && Math.Abs(mouseX - pointX) < 10) { mouseX = pointX; mouseEvent = ev; } } if (Mouse.IsOver(rect)) { float mouseProgress = (mouseX - rect.xMin) / rect.width; int mouseTimer = timerStart + (int)(timeLen * mouseProgress); MpUI.DrawRotatedLine(new Vector2(mouseX, rect.center.y), TimelineHeight, 15f, 90f, Color.blue); if (Event.current.type == EventType.MouseUp) { TickPatch.SetSimulation(mouseTimer, canESC: true); if (mouseTimer < TickPatch.Timer) { ClientJoiningState.ReloadGame(Multiplayer.session.dataSnapshot.mapData.Keys.ToList(), false, Multiplayer.GameComp.asyncTime); } } if (Event.current.isMouse) { Event.current.Use(); } string tooltip = $"Tick {mouseTimer}"; if (mouseEvent != null) { tooltip = $"{mouseEvent.name}\n{tooltip}"; } const int TickTipId = 215462143; TooltipHandler.TipRegion(rect, new TipSignal(tooltip, TickTipId)); // Remove delay between the mouseover and showing if (TooltipHandler.activeTips.TryGetValue(TickTipId, out ActiveTip tip)) { tip.firstTriggerTime = 0; } } if (TickPatch.Simulating) { float pct = (TickPatch.simulating.target.Value - timerStart) / (float)timeLen; float simulateToX = rect.xMin + rect.width * pct; MpUI.DrawRotatedLine(new Vector2(simulateToX, rect.center.y), TimelineHeight, 15f, 90f, Color.yellow); } }