diff --git a/Content.IntegrationTests/GameTests.cs b/Content.IntegrationTests/GameTests.cs index 34e72c37f9..1e790f4e20 100644 --- a/Content.IntegrationTests/GameTests.cs +++ b/Content.IntegrationTests/GameTests.cs @@ -5,7 +5,6 @@ namespace Content.IntegrationTests; [TestFixture] public sealed class GameTests : ContentIntegrationTest { - /// /// Tests to make sure the IntegrationTest project does not runtime. /// diff --git a/DMCompiler/Compiler/CompilerError.cs b/DMCompiler/Compiler/CompilerError.cs index 223f02caa0..a4aa28f978 100644 --- a/DMCompiler/Compiler/CompilerError.cs +++ b/DMCompiler/Compiler/CompilerError.cs @@ -23,6 +23,7 @@ public enum WarningCode { DanglingOverride = 405, StaticOverride = 406, FinalOverride = 407, + // ReSharper disable once InconsistentNaming IAmATeaPot = 418, // TODO: Implement the HTCPC protocol for OD HardConstContext = 500, diff --git a/DMCompiler/Compiler/DM/AST/DMAST.Expression.cs b/DMCompiler/Compiler/DM/AST/DMAST.Expression.cs index 44f6e60fe3..ea1539f949 100644 --- a/DMCompiler/Compiler/DM/AST/DMAST.Expression.cs +++ b/DMCompiler/Compiler/DM/AST/DMAST.Expression.cs @@ -201,6 +201,7 @@ public abstract class Operation { /// The location of the operation. /// public required Location Location; + /// /// Whether we should short circuit if the expression we are accessing is null. /// @@ -212,6 +213,7 @@ public abstract class NamedOperation : Operation { /// Name of the identifier. /// public required string Identifier; + /// /// Whether we should check if the variable exists or not. /// @@ -247,7 +249,6 @@ public sealed class DMASTCallableProcIdentifier(Location location, string identi } public sealed class DMASTCallableSuper(Location location) : DMASTExpression(location), IDMASTCallable; - public sealed class DMASTCallableSelf(Location location) : DMASTExpression(location), IDMASTCallable; public sealed class DMASTScopeIdentifier( diff --git a/DMCompiler/Compiler/DM/DMParser.cs b/DMCompiler/Compiler/DM/DMParser.cs index 17c50a3b7e..3850f7aedd 100644 --- a/DMCompiler/Compiler/DM/DMParser.cs +++ b/DMCompiler/Compiler/DM/DMParser.cs @@ -195,6 +195,7 @@ public DMASTFile File() { if (statements.Count == 0) return null; } } while (Delimiter()); + Whitespace(); return statements; @@ -673,6 +674,7 @@ public DMASTFile File() { procStatements.Add(statement); } } while (Delimiter() || statement is DMASTProcStatementLabel); + Whitespace(); return (procStatements.Count > 0 ? procStatements : null, setStatements.Count > 0 ? setStatements : null); @@ -1518,6 +1520,7 @@ private DMASTProcStatementSwitch.SwitchCase[] SwitchInner() { Delimiter(); } while (Check(TokenType.DM_Comma)); + Whitespace(); ConsumeRightParenthesis(); Whitespace(); @@ -1837,7 +1840,6 @@ private void ExpressionTo(out DMASTExpression endRange, out DMASTExpression? ste DMASTExpression? value = ExpressionAssign(); while (value != null && Check(TokenType.DM_In)) { - Whitespace(); DMASTExpression? list = ExpressionAssign(); RequireExpression(ref list, "Expected a container to search in"); @@ -2349,6 +2351,7 @@ private bool Newline() { while (Check(TokenType.Newline)) { } + return hasNewline; } @@ -2800,7 +2803,6 @@ private void BracketWhitespace() { Compiler.Emit(WarningCode.BadToken, CurrentLoc, $"Only one type path can be used, ignoring {pathType}"); } - } while (Check(TokenType.DM_Bar)); if (parenthetical) { diff --git a/DMCompiler/Compiler/DMPreprocessor/DMPreprocessor.cs b/DMCompiler/Compiler/DMPreprocessor/DMPreprocessor.cs index 8ed167d0ab..81ae92f325 100644 --- a/DMCompiler/Compiler/DMPreprocessor/DMPreprocessor.cs +++ b/DMCompiler/Compiler/DMPreprocessor/DMPreprocessor.cs @@ -673,6 +673,7 @@ private void HandlePragmaDirective() { compiler.Emit(WarningCode.BadDirective, warningTypeToken.Location, "Runtime pragmas do not support directive: info"); return; } + compiler.SetPragma(warningCode, ErrorLevel.Notice); break; case "warning": @@ -681,6 +682,7 @@ private void HandlePragmaDirective() { compiler.Emit(WarningCode.BadDirective, warningTypeToken.Location, "Runtime pragmas do not support directive: warn"); return; } + compiler.SetPragma(warningCode, ErrorLevel.Warning); break; case "error": diff --git a/DMCompiler/Compiler/DMPreprocessor/DMPreprocessorLexer.cs b/DMCompiler/Compiler/DMPreprocessor/DMPreprocessorLexer.cs index 659cc3c03b..32b08a7b60 100644 --- a/DMCompiler/Compiler/DMPreprocessor/DMPreprocessorLexer.cs +++ b/DMCompiler/Compiler/DMPreprocessor/DMPreprocessorLexer.cs @@ -554,10 +554,10 @@ private bool TryMacroKeyword(string text, [NotNullWhen(true)] out Token? token) token = null; // maybe should use ref instead of out? return false; } + return true; } - /// /// Lex a string
///
diff --git a/OpenDreamClient/Interface/Controls/ControlGrid.cs b/OpenDreamClient/Interface/Controls/ControlGrid.cs index f7197e05ad..5510179a08 100644 --- a/OpenDreamClient/Interface/Controls/ControlGrid.cs +++ b/OpenDreamClient/Interface/Controls/ControlGrid.cs @@ -13,7 +13,6 @@ public ControlGrid(ControlDescriptor controlDescriptor, ControlWindow window) : protected override Control CreateUIElement() { _grid = new GridContainer() { - }; return _grid; diff --git a/OpenDreamClient/Interface/DMF/IDMFProperty.cs b/OpenDreamClient/Interface/DMF/IDMFProperty.cs index a39e8e6d65..1502b07ee7 100644 --- a/OpenDreamClient/Interface/DMF/IDMFProperty.cs +++ b/OpenDreamClient/Interface/DMF/IDMFProperty.cs @@ -522,8 +522,8 @@ public bool Equals(string comparison) { } #region Serializers -/// TLDR everything is a string passed to the constructor +/// TLDR everything is a string passed to the constructor [TypeSerializer] public sealed class DMFPropertyStringSerializer : ITypeSerializer, ITypeCopyCreator { public DMFPropertyString Read(ISerializationManager serializationManager, ValueDataNode node, diff --git a/OpenDreamClient/Interface/Descriptors/ControlDescriptors.cs b/OpenDreamClient/Interface/Descriptors/ControlDescriptors.cs index 8cf9bb896b..512d46f90f 100644 --- a/OpenDreamClient/Interface/Descriptors/ControlDescriptors.cs +++ b/OpenDreamClient/Interface/Descriptors/ControlDescriptors.cs @@ -10,43 +10,61 @@ namespace OpenDreamClient.Interface.Descriptors; public partial class ControlDescriptor : ElementDescriptor { [DataField("pos")] public DMFPropertyPos Pos = new(0, 0); + [DataField("size")] public DMFPropertySize Size = new(0, 0); + [DataField("anchor1")] public DMFPropertyPos? Anchor1; + [DataField("anchor2")] public DMFPropertyPos? Anchor2; [DataField("is-visible")] public DMFPropertyBool IsVisible = new(true); + [DataField("is-transparent")] public DMFPropertyBool IsTransparent = new(false); + [DataField("border")] public DMFPropertyString Border = new("none"); + [DataField("flash")] public DMFPropertyNum Flash = new(0); + [DataField("saved-params")] public DMFPropertyString SavedParams; //default varies + [DataField("text-color")] public DMFPropertyColor TextColor = new(Color.Black); + [DataField("background-color")] public DMFPropertyColor BackgroundColor = new(Color.Transparent); + [DataField("is-default")] public DMFPropertyBool IsDefault = new(false); + [DataField("is-disabled")] public DMFPropertyBool IsDisabled = new(false); + [DataField("focus")] public DMFPropertyBool Focus = new(false); + [DataField("drop-zone")] public DMFPropertyBool DropZone; //default varies + [DataField("right-click")] public DMFPropertyBool RightClick = new(false); + [DataField("font-family")] public DMFPropertyString FontFamily = new(""); + [DataField("font-size")] public DMFPropertyNum FontSize = new(0); + [DataField("font-style")] public DMFPropertyString FontStyle = new(""); + [DataField("on-size")] public DMFPropertyString OnSize = new(""); } @@ -54,42 +72,61 @@ public partial class ControlDescriptor : ElementDescriptor { public sealed partial class WindowDescriptor : ControlDescriptor { [DataField("can-minimize")] public DMFPropertyBool CanMinimize = new(true); + [DataField("can-resize")] public DMFPropertyBool CanResize = new(true); + [DataField("is-minimized")] public DMFPropertyBool IsMinimized = new(false); + [DataField("is-maximized")] public DMFPropertyBool IsMaximized = new(false); + [DataField("alpha")] public DMFPropertyNum Alpha = new(255); + [DataField("statusbar")] public DMFPropertyBool StatusBar = new(false); + [DataField("transparent-color")] public DMFPropertyColor TransparentColor = new(Color.Transparent); + [DataField("can-close")] public DMFPropertyBool CanClose = new(true); + [DataField("title")] public DMFPropertyString Title = new(""); + [DataField("titlebar")] public DMFPropertyBool TitleBar = new(true); + [DataField("icon")] public DMFPropertyString Icon = new(""); + [DataField("image")] public DMFPropertyString Image = new(""); + [DataField("image-mode")] public DMFPropertyString ImageMode = new("stretch"); + [DataField("keep-aspect")] public DMFPropertyBool KeepAspect = new(false); + [DataField("macro")] public DMFPropertyString Macro = new(""); + [DataField("menu")] public DMFPropertyString Menu = new(""); + [DataField("on-close")] public DMFPropertyString OnClose = new(""); + [DataField("can-scroll")] public DMFPropertyString CanScroll = new("none"); + [DataField("is-pane")] public DMFPropertyBool IsPane = new(false); + [DataField("on-status")] public DMFPropertyString OnStatus = new(""); @@ -174,29 +211,36 @@ public WindowDescriptor WithVisible(ISerializationManager serializationManager, public sealed partial class ControlDescriptorChild : ControlDescriptor { [DataField("lock")] public DMFPropertyString Lock = new("none"); + [DataField("is-vert")] public DMFPropertyBool IsVert = new(false); + [DataField("splitter")] public DMFPropertyNum Splitter = new(50f); + [DataField("show-splitter")] public DMFPropertyBool ShowSplitter = new(true); + [DataField("left")] public DMFPropertyString Left = new(""); + [DataField("right")] public DMFPropertyString Right = new(""); - - } public sealed partial class ControlDescriptorInput : ControlDescriptor { [DataField("multi-line")] public DMFPropertyBool MultiLine = new(false); + [DataField("is-password")] public DMFPropertyBool IsPassword = new(false); + [DataField("no-command")] public DMFPropertyBool NoCommand = new(false); + [DataField("text")] public DMFPropertyString Text = new(""); + [DataField("command")] public DMFPropertyString Command = new(""); } @@ -204,16 +248,22 @@ public sealed partial class ControlDescriptorInput : ControlDescriptor { public sealed partial class ControlDescriptorButton : ControlDescriptor { [DataField("is-flat")] public DMFPropertyBool IsFlat = new(false); + [DataField("is-checked")] public DMFPropertyBool IsChecked = new(false); + [DataField("group")] public DMFPropertyString Group = new(""); + [DataField("button-type")] public DMFPropertyString ButtonType = new("pushbutton"); + [DataField("text")] public DMFPropertyString Text = new(""); + [DataField("image")] public DMFPropertyString Image = new(""); + [DataField("command")] public DMFPropertyString Command = new(""); } @@ -221,16 +271,22 @@ public sealed partial class ControlDescriptorButton : ControlDescriptor { public sealed partial class ControlDescriptorOutput : ControlDescriptor { [DataField("legacy-size")] public DMFPropertyBool LegacySize = new(false); + [DataField("style")] public DMFPropertyString Style = new(""); + [DataField("max-lines")] public DMFPropertyNum MaxLines = new(1000); + [DataField("link-color")] public DMFPropertyColor LinkColor = new(Color.Blue); + [DataField("visited-color")] public DMFPropertyColor VisitedColor = new(Color.Purple); + [DataField("image")] public DMFPropertyString Image = new(""); + [DataField("enable-http-images")] public DMFPropertyBool EnableHttpImages = new(false); } @@ -238,64 +294,86 @@ public sealed partial class ControlDescriptorOutput : ControlDescriptor { public sealed partial class ControlDescriptorInfo : ControlDescriptor { [DataField("multi-line")] public DMFPropertyBool MultiLine = new(true); + [DataField("highlight-color")] public DMFPropertyColor HighlightColor = new(Color.Green); + [DataField("tab-text-color")] public DMFPropertyColor TabTextColor = new(Color.Transparent); + [DataField("tab-background-color")] public DMFPropertyColor TabBackgroundColor = new(Color.Transparent); + [DataField("prefix-color")] public DMFPropertyColor PrefixColor = new(Color.Transparent); + [DataField("suffix-color")] public DMFPropertyColor SuffixColor = new(Color.Transparent); + [DataField("allow-html")] public DMFPropertyBool AllowHtml = new(true); // Supposedly false by default, but it isn't if you're not using BYOND's default skin + [DataField("tab-font-family")] public DMFPropertyString TabFontFamily = new(""); + [DataField("tab-font-size")] public DMFPropertyNum TabFontSize = new(0); + [DataField("tab-font-style")] public DMFPropertyString TabFontStyle = new(""); + [DataField("on-show")] public DMFPropertyString OnShowCommand = new(""); + [DataField("on-hide")] public DMFPropertyString OnHideCommand = new(""); - } public sealed partial class ControlDescriptorMap : ControlDescriptor { [DataField("view-size")] public DMFPropertyNum ViewSize = new(0); + [DataField("style")] public DMFPropertyString Style = new(""); + [DataField("text-mode")] public DMFPropertyBool TextMode = new(false); + [DataField("icon-size")] public DMFPropertyNum IconSize = new(0); + [DataField("letterbox")] public DMFPropertyBool Letterbox = new(true); + [DataField("zoom")] public DMFPropertyNum Zoom = new(0); + [DataField("zoom-mode")] public DMFPropertyString ZoomMode = new("normal"); + [DataField("on-show")] public DMFPropertyString OnShowCommand = new(""); + [DataField("on-hide")] public DMFPropertyString OnHideCommand = new(""); - } public sealed partial class ControlDescriptorBrowser : ControlDescriptor { [DataField("show-history")] public DMFPropertyBool ShowHistory = new(false); + [DataField("show-url")] public DMFPropertyBool ShowUrl = new(false); + [DataField("use-title")] public DMFPropertyBool UseTitle = new(false); + [DataField("auto-format")] public DMFPropertyBool AutoFormat = new(true); + [DataField("on-show")] public DMFPropertyString OnShowCommand = new(""); + [DataField("on-hide")] public DMFPropertyString OnHideCommand = new(""); } @@ -303,14 +381,19 @@ public sealed partial class ControlDescriptorBrowser : ControlDescriptor { public sealed partial class ControlDescriptorLabel : ControlDescriptor { [DataField("text")] public DMFPropertyString Text = new(""); + [DataField("align")] public DMFPropertyString Align = new("center"); + [DataField("text-wrap")] public DMFPropertyBool TextWrap = new(false); + [DataField("image")] public DMFPropertyString Image = new(""); + [DataField("image-mode")] public DMFPropertyString ImageMode = new("stretch"); + [DataField("keep-aspect")] public DMFPropertyBool KeepAspect = new(false); } @@ -318,28 +401,40 @@ public sealed partial class ControlDescriptorLabel : ControlDescriptor { public sealed partial class ControlDescriptorGrid : ControlDescriptor { [DataField("cells")] public DMFPropertySize Cells = new(0,0); + [DataField("cell-span")] public DMFPropertySize CellSpan = new(1,1); + [DataField("is-list")] public DMFPropertyBool IsList = new(false); + [DataField("show-lines")] public DMFPropertyString ShowLines = new("both"); + [DataField("style")] public DMFPropertyString Style = new(""); + [DataField("highlight-color")] public DMFPropertyColor HighlightColor = new(Color.Green); + [DataField("line-color")] public DMFPropertyColor LineColor = new("#c0c0c0"); + [DataField("link-color")] public DMFPropertyColor LinkColor = new(Color.Blue); + [DataField("visited-color")] public DMFPropertyColor VisitedCOlor = new(Color.Purple); + [DataField("current-cell")] public DMFPropertySize CurrentCell = new(0,0); + [DataField("show-names")] public DMFPropertyBool ShowNames = new(true); + [DataField("small-icons")] public DMFPropertyBool SmallIcons = new(false); + [DataField("enable-http-images")] public DMFPropertyBool EnableHttpImages = new(false); } @@ -347,30 +442,39 @@ public sealed partial class ControlDescriptorGrid : ControlDescriptor { public sealed partial class ControlDescriptorTab : ControlDescriptor { [DataField("multi-line")] public DMFPropertyBool MultiLine = new(true); + [DataField("current-tab")] public DMFPropertyString CurrentTab = new(""); + [DataField("on-tab")] public DMFPropertyString OnTab = new(""); + [DataField("tabs")] public DMFPropertyString Tabs = new(""); } - public sealed partial class ControlDescriptorBar : ControlDescriptor { [DataField("width")] public DMFPropertyNum Width = new(10); //width of the progress bar in pixels. In the default EAST dir, this is more accurately thought of as "height" + [DataField("dir")] public DMFPropertyString Dir = new("east"); //valid values: north/east/south/west/clockwise/cw/counterclockwise/ccw + [DataField("angle1")] public DMFPropertyNum Angle1 = new(0); //start angle + [DataField("angle2")] public DMFPropertyNum Angle2 = new(180); //end angle + [DataField("bar-color")] public DMFPropertyColor BarColor = new(Color.Transparent); //insanely, the default causes the bar not to render regardless of value + [DataField("is-slider")] public DMFPropertyBool IsSlider = new(false); + [DataField("value")] public DMFPropertyNum Value = new(0f); //position of the progress bar + [DataField("on-change")] public DMFPropertyString OnChange = new(""); } diff --git a/OpenDreamClient/Interface/Descriptors/MacroDescriptors.cs b/OpenDreamClient/Interface/Descriptors/MacroDescriptors.cs index d89e194235..f413fbf65f 100644 --- a/OpenDreamClient/Interface/Descriptors/MacroDescriptors.cs +++ b/OpenDreamClient/Interface/Descriptors/MacroDescriptors.cs @@ -16,7 +16,6 @@ public MacroSetDescriptor(string id) { [UsedImplicitly] public MacroSetDescriptor() { - } public override MacroDescriptor CreateChildDescriptor(ISerializationManager serializationManager, MappingDataNode attributes) { diff --git a/OpenDreamClient/Interface/Descriptors/MenuDescriptors.cs b/OpenDreamClient/Interface/Descriptors/MenuDescriptors.cs index bcd2866ada..6f1e9fc8bd 100644 --- a/OpenDreamClient/Interface/Descriptors/MenuDescriptors.cs +++ b/OpenDreamClient/Interface/Descriptors/MenuDescriptors.cs @@ -16,7 +16,6 @@ public MenuDescriptor(string id) { [UsedImplicitly] public MenuDescriptor() { - } public override MenuElementDescriptor CreateChildDescriptor(ISerializationManager serializationManager, MappingDataNode attributes) { @@ -35,8 +34,6 @@ public override ElementDescriptor CreateCopy(ISerializationManager serialization } public sealed partial class MenuElementDescriptor : ElementDescriptor { - - [DataField("command")] public DMFPropertyString Command { get; private set; } @@ -51,6 +48,7 @@ public sealed partial class MenuElementDescriptor : ElementDescriptor { [DataField("group")] public DMFPropertyString Group { get; private set; } + [DataField("index")] public DMFPropertyNum Index { get; private set; } diff --git a/OpenDreamClient/Interface/InterfaceMacro.cs b/OpenDreamClient/Interface/InterfaceMacro.cs index 78cad5fdef..83fbdde174 100644 --- a/OpenDreamClient/Interface/InterfaceMacro.cs +++ b/OpenDreamClient/Interface/InterfaceMacro.cs @@ -300,14 +300,12 @@ private void FirstChanceKeyHandler(KeyEventArgs args, KeyEventType type) { return; } - string? keyName = ParsedKeybind.KeyToKeyName(args.Key); if (keyName == null) return; string command = Command.Replace("[[*]]", keyName); _interfaceManager.RunCommand(command); // args.Handle() omitted on purpose, in BYOND both the "specific" keybind and the ANY keybind are triggered - } private void OnMacroPress(ICommonSession? session) { @@ -327,7 +325,6 @@ private void OnMacroRelease(ICommonSession? session) { } else if (_isRelease) { _interfaceManager.RunCommand(Command); } - } private static KeyBindingRegistration? CreateMacroBinding(BoundKeyFunction function, ParsedKeybind keybind) { diff --git a/OpenDreamClient/Interface/Prompts/ColorPrompt.cs b/OpenDreamClient/Interface/Prompts/ColorPrompt.cs index 072f0ddee6..837e25b1ef 100644 --- a/OpenDreamClient/Interface/Prompts/ColorPrompt.cs +++ b/OpenDreamClient/Interface/Prompts/ColorPrompt.cs @@ -120,7 +120,6 @@ private static StyleBoxTexture MakeSliderOutline(Color color) { }; } - public static Stylesheet Make() { var sliderFillBox = MakeSliderFill(Color.FromHex("#3E6C45")); var sliderBackBox = MakeSliderOutline(PanelDark); diff --git a/OpenDreamClient/Rendering/DreamViewOverlay.cs b/OpenDreamClient/Rendering/DreamViewOverlay.cs index d2e6e470ae..fa86f7410e 100644 --- a/OpenDreamClient/Rendering/DreamViewOverlay.cs +++ b/OpenDreamClient/Rendering/DreamViewOverlay.cs @@ -785,6 +785,7 @@ public static Matrix3x2 CalculateDrawingMatrix(Matrix3x2 transform, Vector2 pixe } #region Render Toggle Commands + public sealed class ToggleScreenOverlayCommand : IConsoleCommand { // ReSharper disable once StringLiteralTypo public string Command => "togglescreenoverlay"; @@ -824,4 +825,5 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) { } } } + #endregion diff --git a/OpenDreamClient/States/MainMenu/MainMenuState.cs b/OpenDreamClient/States/MainMenu/MainMenuState.cs index 35cd0d27ad..00c68e823c 100644 --- a/OpenDreamClient/States/MainMenu/MainMenuState.cs +++ b/OpenDreamClient/States/MainMenu/MainMenuState.cs @@ -132,7 +132,6 @@ private void ParseAddress(string address, out string ip, out ushort port) { } } - private void _onConnectFailed(object? _, NetConnectFailArgs args) { _userInterfaceManager.Popup($"Failed to connect: {args.Reason}"); _netManager.ConnectFailed -= _onConnectFailed; diff --git a/OpenDreamRuntime/DreamConnection.cs b/OpenDreamRuntime/DreamConnection.cs index 6e0a446a74..bddc0d09c8 100644 --- a/OpenDreamRuntime/DreamConnection.cs +++ b/OpenDreamRuntime/DreamConnection.cs @@ -214,8 +214,8 @@ public void HandleMsgTopic(MsgTopic pTopic) { public void OutputDreamValue(DreamValue value) { if (value.TryGetValueAsDreamObject(out var outputObject)) { - ushort channel = (ushort)outputObject.GetVariable("channel").GetValueAsInteger(); - ushort volume = (ushort)outputObject.GetVariable("volume").GetValueAsInteger(); + ushort channel = (ushort)outputObject.GetVariable("channel").MustGetValueAsInteger(); + ushort volume = (ushort)outputObject.GetVariable("volume").MustGetValueAsInteger(); float offset = outputObject.GetVariable("offset").UnsafeGetValueAsFloat(); DreamValue file = outputObject.GetVariable("file"); @@ -391,7 +391,6 @@ public void HandleBrowseResourceRequest(string filename) { } else { _sawmill.Error($"Client({Session}) requested a browse_rsc file they had not been permitted to request ({filename})."); } - } public void Browse(string? body, string? options) { diff --git a/OpenDreamRuntime/DreamThread.cs b/OpenDreamRuntime/DreamThread.cs index a66dea78b4..3681049873 100644 --- a/OpenDreamRuntime/DreamThread.cs +++ b/OpenDreamRuntime/DreamThread.cs @@ -435,6 +435,7 @@ public void AppendStackTrace(StringBuilder builder) { else { _current.AppendStackFrame(builder); } + builder.AppendLine(); foreach (var frame in _stack) { diff --git a/OpenDreamRuntime/DreamValue.cs b/OpenDreamRuntime/DreamValue.cs index 0059fbed55..09567549bc 100644 --- a/OpenDreamRuntime/DreamValue.cs +++ b/OpenDreamRuntime/DreamValue.cs @@ -70,7 +70,7 @@ public static DreamValue False { //ReSharper disable once NotAccessedField.Local private readonly ProfilerMemory? _tracyMemoryId; //only used for strings, since everything else is a value type or handled in DreamObject #endif - + public DreamValue(string value) { DebugTools.Assert(value != null); Type = DreamValueType.String; @@ -134,11 +134,6 @@ public readonly override string ToString() { } } - [Obsolete("Deprecated. Use TryGetValueAsString() or MustGetValueAsString() instead.")] - public string GetValueAsString() { - return MustGetValueAsString(); - } - public readonly bool TryGetValueAsString([NotNullWhen(true)] out string? value) { if (Type == DreamValueType.String) { value = Unsafe.As(_refValue)!; @@ -161,12 +156,6 @@ private void ThrowInvalidCastString() { throw new InvalidCastException("Value " + this + " was not the expected type of string"); } - //Casts a float value to an integer - [Obsolete("Deprecated. Use TryGetValueAsInteger() or MustGetValueAsInteger() instead.")] - public int GetValueAsInteger() { - return MustGetValueAsInteger(); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly bool TryGetValueAsInteger(out int value) { value = (int)_floatValue; diff --git a/OpenDreamRuntime/Objects/DreamObject.cs b/OpenDreamRuntime/Objects/DreamObject.cs index f1706ca3ce..cbb2e086c8 100644 --- a/OpenDreamRuntime/Objects/DreamObject.cs +++ b/OpenDreamRuntime/Objects/DreamObject.cs @@ -84,6 +84,7 @@ private string? Tag { } } } + private string? _tag; public DreamObject(DreamObjectDefinition objectDefinition) { @@ -168,6 +169,7 @@ public bool IsSubtypeOf(TreeEntry ancestor) { } #region Variables + public virtual bool IsSaved(string name) { return ObjectDefinition.Variables.ContainsKey(name) && !ObjectDefinition.GlobalVariables.ContainsKey(name) @@ -271,9 +273,11 @@ public void SetVariableValue(string name, DreamValue value) { Variables ??= new(4); Variables[name] = value; } + #endregion Variables #region Proc Helpers + public DreamProc GetProc(string procName) { DebugTools.Assert(!Deleted, "Cannot call GetProc() on a deleted object"); @@ -317,9 +321,11 @@ public DreamValue SpawnProc(string procName, DreamObject? usr = null, params Dre var proc = GetProc(procName); return DreamThread.Run(proc, this, usr, arguments); } + #endregion Proc Helpers #region Name Helpers + // This could probably be placed elsewhere. Not sure where tho /// true if \proper noun formatting should be used, false if \improper public static bool StringIsProper(string str) { @@ -404,9 +410,11 @@ public string GetRawName() { return name; } + #endregion Name Helpers #region Operators + // + public virtual DreamValue OperatorAdd(DreamValue b, DMProcState state) { if (TryExecuteOperatorOverload(state, "operator+", new DreamProcArguments(b), out var result)) @@ -519,6 +527,7 @@ public virtual void OperatorIndexAssign(DreamValue index, DMProcState state, Dre throw new InvalidOperationException($"Cannot assign {value} to index {index} of {this}"); } + #endregion Operators private bool TryExecuteOperatorOverload( diff --git a/OpenDreamRuntime/Objects/DreamObjectDefinition.cs b/OpenDreamRuntime/Objects/DreamObjectDefinition.cs index 9ea9e5c1a5..3ba955b81e 100644 --- a/OpenDreamRuntime/Objects/DreamObjectDefinition.cs +++ b/OpenDreamRuntime/Objects/DreamObjectDefinition.cs @@ -35,6 +35,7 @@ public sealed class DreamObjectDefinition { public string Type => TreeEntry.Path; public DreamObjectDefinition? Parent => TreeEntry.ParentEntry?.ObjectDefinition; public int? InitializationProc; + public bool NoConstructors { get { if (_noConstructors is not { } res) @@ -51,10 +52,13 @@ public bool NoConstructors { // Maps variables from their name to their initial value. public readonly Dictionary Variables = new(); + // Maps /static variables from name to their index in the global variable table. public readonly Dictionary GlobalVariables = new(); + // Contains hashes of variables that are tagged /const. public HashSet? ConstVariables = null; + // Contains hashes of variables that are tagged /tmp. public HashSet? TmpVariables = null; diff --git a/OpenDreamRuntime/Objects/Types/DreamObjectException.cs b/OpenDreamRuntime/Objects/Types/DreamObjectException.cs index 9a13b2a527..2338b53db0 100644 --- a/OpenDreamRuntime/Objects/Types/DreamObjectException.cs +++ b/OpenDreamRuntime/Objects/Types/DreamObjectException.cs @@ -26,7 +26,6 @@ protected override void SetVar(string varName, DreamValue value) { base.SetVar(varName, value); return; } - } protected override bool TryGetVar(string varName, out DreamValue value) { diff --git a/OpenDreamRuntime/Objects/Types/DreamObjectMatrix.cs b/OpenDreamRuntime/Objects/Types/DreamObjectMatrix.cs index a4b3e3d7c4..9a6447292b 100644 --- a/OpenDreamRuntime/Objects/Types/DreamObjectMatrix.cs +++ b/OpenDreamRuntime/Objects/Types/DreamObjectMatrix.cs @@ -10,7 +10,6 @@ public sealed class DreamObjectMatrix : DreamObject { // TODO: Store a/b/c/d/e/f as fields instead of as DM vars public DreamObjectMatrix(DreamObjectDefinition objectDefinition) : base(objectDefinition) { - } public override void Initialize(DreamProcArguments args) { @@ -196,6 +195,7 @@ public override DreamValue OperatorEquivalent(DreamValue b) { if (!leftValue.Equals(rightValue)) return DreamValue.False; } + return DreamValue.True; } @@ -256,6 +256,7 @@ public override DreamValue OperatorRemove(DreamValue b) { return base.OperatorRemove(b); } + #endregion Operators #region Helpers @@ -446,6 +447,7 @@ public static void AddMatrix(DreamObjectMatrix lMatrix, DreamObjectMatrix rMatri } catch (InvalidCastException) { throw new InvalidOperationException($"Invalid matrices '{lMatrix}' and '{rMatrix}' cannot be added."); } + lMatrix.SetVariableValue("a", new DreamValue(lA + rA)); lMatrix.SetVariableValue("b", new DreamValue(lB + rB)); lMatrix.SetVariableValue("c", new DreamValue(lC + rC)); @@ -486,6 +488,7 @@ public static void SubtractMatrix(DreamObjectMatrix lMatrix, DreamObjectMatrix r } catch (InvalidCastException) { throw new InvalidOperationException($"Invalid matrices '{lMatrix}' and '{rMatrix}' cannot be subtracted."); } + lMatrix.SetVariableValue("a", new DreamValue(lA - rA)); lMatrix.SetVariableValue("b", new DreamValue(lB - rB)); lMatrix.SetVariableValue("c", new DreamValue(lC - rC)); @@ -526,6 +529,7 @@ public static void MultiplyMatrix(DreamObjectMatrix lMatrix, DreamObjectMatrix r } catch (InvalidCastException) { throw new InvalidOperationException($"Invalid matrices '{lMatrix}' and '{rMatrix}' cannot be multiplied."); } + lMatrix.SetVariableValue("a", new DreamValue(lA*rA + lD*rB)); lMatrix.SetVariableValue("b", new DreamValue(lB*rA + lE*rB)); lMatrix.SetVariableValue("c", new DreamValue(lC*rA + lF*rB + rC)); @@ -533,5 +537,6 @@ public static void MultiplyMatrix(DreamObjectMatrix lMatrix, DreamObjectMatrix r lMatrix.SetVariableValue("e", new DreamValue(lB*rD + lE*rE)); lMatrix.SetVariableValue("f", new DreamValue(lC*rD + lF*rE + rF)); } + #endregion Helpers } diff --git a/OpenDreamRuntime/Objects/Types/DreamObjectSavefile.cs b/OpenDreamRuntime/Objects/Types/DreamObjectSavefile.cs index 7ac3c1c77d..184c4c79e7 100644 --- a/OpenDreamRuntime/Objects/Types/DreamObjectSavefile.cs +++ b/OpenDreamRuntime/Objects/Types/DreamObjectSavefile.cs @@ -9,7 +9,6 @@ namespace OpenDreamRuntime.Objects.Types; - public sealed class DreamObjectSavefile : DreamObject { private readonly DreamObjectTree _objectTree; @@ -25,8 +24,8 @@ public sealed class DreamObjectSavefile : DreamObject { private static ISawmill? _sawmill; - public override bool ShouldCallNew => false; + /// /// Temporary savefiles should be deleted when the DreamObjectSavefile is deleted. Temporary savefiles can be created by creating a new savefile datum with a null filename or an entry in the world's resource cache /// @@ -78,7 +77,6 @@ public string CurrentPath { } } - public DreamObjectSavefile(DreamObjectDefinition objectDefinition) : base(objectDefinition) { CurrentDir = _rootNode = new SFDreamDir(); _objectTree ??= objectDefinition.ObjectTree; @@ -109,6 +107,7 @@ public override void Initialize(DreamProcArguments args) { Resource = null; throw new InvalidDataException($"Error parsing savefile {filename}: Is the savefile corrupted or using a BYOND version? BYOND savefiles are not compatible with OpenDream. Details: {e}"); } + SavefileDirectories.Add(filename, _rootNode); } else { //_rootNode is created in constructor @@ -179,16 +178,19 @@ protected override void SetVar(string varName, DreamValue value) { foreach(var key in CurrentDir.Keys) { newCurrentDir[key] = CurrentDir[key]; } + CurrentDir.Clear(); parentDir[CurrentPath.Split("/").Last()] = newCurrentDir; } else { CurrentDir.Clear(); } } + _eof = true; } else { _eof = false; } + break; default: throw new Exception($"Cannot set var \"{varName}\" on savefiles"); @@ -236,6 +238,7 @@ public static void FlushAllUpdates() { _sawmill.Error($"Error flushing savefile {savefile.Resource!.ResourcePath}: {e}"); } } + SavefilesToFlush.Clear(); } @@ -287,8 +290,10 @@ private SFDreamJsonValue SeekTo(string to, bool createPath=false) { else return tempDir; } + tempDir = newDir; } + return tempDir; } @@ -313,6 +318,7 @@ public void RenameAndNullSavefileValue(string index, string newIndex){ foreach(var key in value.Keys) { newDir[key] = value[key]; } + CurrentDir[newIndex] = newDir; SavefilesToFlush.Add(this); } @@ -337,6 +343,7 @@ public void SetSavefileValue(string? index, DreamValue value) { } else { CurrentDir = _rootNode = newCurrentDir; } + SavefilesToFlush.Add(this); return; } @@ -351,6 +358,7 @@ public void SetSavefileValue(string? index, DreamValue value) { newValue[key] = oldValue[key]; } } + CurrentDir[index] = newValue; } else { string oldPath = CurrentPath; @@ -358,6 +366,7 @@ public void SetSavefileValue(string? index, DreamValue value) { SetSavefileValue(pathArray[pathArray.Length - 1], value); CurrentPath = oldPath; } + SavefilesToFlush.Add(this); } @@ -376,6 +385,7 @@ public DreamValue DeserializeJsonValue(SFDreamJsonValue value) { else l.AddValue(DeserializeJsonValue(sfDreamListValue.AssocKeys[i])); } + return new DreamValue(l); case SFDreamObjectPathValue sfDreamObjectPath: SFDreamJsonValue storedObjectVars = sfDreamObjectPath; @@ -393,6 +403,7 @@ public DreamValue DeserializeJsonValue(SFDreamJsonValue value) { continue; resultObj.SetVariable(key, DeserializeJsonValue(storedObjectVars[key])); } + resultObj.InitSpawn(new DreamProcArguments()); resultObj.SpawnProc("Read", null, [new DreamValue(this)]); return new DreamValue(resultObj); @@ -407,6 +418,7 @@ public DreamValue DeserializeJsonValue(SFDreamJsonValue value) { case SFDreamPrimitive sfDreamPrimitive: return sfDreamPrimitive.Value; } + return DreamValue.Null; } @@ -542,6 +554,7 @@ private uint CalculateCrc32(byte[] data){ crc >>= 1; } } + return ~crc; } @@ -567,21 +580,25 @@ public SFDreamJsonValue this[string key] { get => _nodes[key]; set => _nodes[key] = value; } + public bool TryGetValue(string key, [MaybeNullWhen(false)] out SFDreamJsonValue value) => _nodes.TryGetValue(key, out value); + [JsonIgnore] public Dictionary.KeyCollection Keys => _nodes.Keys; + [JsonIgnore] public int Count => _nodes.Count; + public void Clear() => _nodes.Clear(); public bool Remove(string key) => _nodes.Remove(key); public bool ContainsKey(string key) => _nodes.ContainsKey(key); - } /// /// Dummy type for directories /// public sealed class SFDreamDir : SFDreamJsonValue; + /// /// Standard DM types except objects and type paths /// @@ -589,6 +606,7 @@ public sealed class SFDreamPrimitive : SFDreamJsonValue { [JsonInclude] public DreamValue Value = DreamValue.Null; } + /// /// Standard DM type paths /// @@ -603,6 +621,7 @@ public sealed class SFDreamType : SFDreamJsonValue { public sealed class SFDreamListValue : SFDreamJsonValue { [JsonInclude] public List AssocKeys = new(); + [JsonInclude] public List? AssocData; } @@ -621,18 +640,22 @@ public sealed class SFDreamObjectPathValue : SFDreamJsonValue { public sealed class SFDreamFileValue : SFDreamJsonValue { [JsonInclude] public string? Name; + [JsonInclude] public string? Ext; + [JsonInclude] public required int Length; + [JsonInclude] public uint Crc32 = 0x00000000; + [JsonInclude] public string Encoding = "base64"; + [JsonInclude] public required string Data; } #endregion - } diff --git a/OpenDreamRuntime/Objects/Types/DreamObjectSound.cs b/OpenDreamRuntime/Objects/Types/DreamObjectSound.cs index 9757585270..41149bcf08 100644 --- a/OpenDreamRuntime/Objects/Types/DreamObjectSound.cs +++ b/OpenDreamRuntime/Objects/Types/DreamObjectSound.cs @@ -2,6 +2,5 @@ public sealed class DreamObjectSound : DreamObject { public DreamObjectSound(DreamObjectDefinition objectDefinition) : base(objectDefinition) { - } } diff --git a/OpenDreamRuntime/Procs/DMOpcodeHandlers.cs b/OpenDreamRuntime/Procs/DMOpcodeHandlers.cs index 85e652d479..a1a6e48914 100644 --- a/OpenDreamRuntime/Procs/DMOpcodeHandlers.cs +++ b/OpenDreamRuntime/Procs/DMOpcodeHandlers.cs @@ -2411,7 +2411,7 @@ public static ProcStatus BrowseResource(DMProcState state) { throw new Exception("Invalid browse_rsc() recipient"); } - connection?.BrowseResource(file, filename.IsNull ? Path.GetFileName(file.ResourcePath) : filename.GetValueAsString()); + connection?.BrowseResource(file, filename.IsNull ? Path.GetFileName(file.ResourcePath) : filename.MustGetValueAsString()); return ProcStatus.Continue; } @@ -2429,7 +2429,7 @@ public static ProcStatus DeleteObject(DMProcState state) { } public static ProcStatus OutputControl(DMProcState state) { - string control = state.Pop().GetValueAsString(); + string control = state.Pop().MustGetValueAsString(); string message = state.Pop().Stringify(); if (!state.Pop().TryGetValueAsDreamObject(out var receiver) || receiver == null) return ProcStatus.Continue; diff --git a/OpenDreamRuntime/Procs/DebugAdapter/Protocol/RequestExceptionInfo.cs b/OpenDreamRuntime/Procs/DebugAdapter/Protocol/RequestExceptionInfo.cs index 72fd1c48e2..f00e2d9281 100644 --- a/OpenDreamRuntime/Procs/DebugAdapter/Protocol/RequestExceptionInfo.cs +++ b/OpenDreamRuntime/Procs/DebugAdapter/Protocol/RequestExceptionInfo.cs @@ -30,6 +30,7 @@ public sealed class ExceptionInfoResponse { * Mode that caused the exception notification to be raised. */ [JsonPropertyName("breakMode")] public required string BreakMode { get; set; } + // enum ExceptionBreakMode, no custom values public const string BreakModeNever = "never"; public const string BreakModeAlways = "always"; diff --git a/OpenDreamRuntime/Procs/DebugAdapter/Protocol/RequestVariables.cs b/OpenDreamRuntime/Procs/DebugAdapter/Protocol/RequestVariables.cs index 37913f8cad..e3240c7204 100644 --- a/OpenDreamRuntime/Procs/DebugAdapter/Protocol/RequestVariables.cs +++ b/OpenDreamRuntime/Procs/DebugAdapter/Protocol/RequestVariables.cs @@ -20,6 +20,7 @@ public sealed class RequestVariablesArguments { * Values: 'indexed', 'named' */ [JsonPropertyName("filter")] public string? Filter { get; set; } + public const string FilterIndexed = "indexed"; public const string FilterNamed = "named"; diff --git a/OpenDreamRuntime/Procs/DebugAdapter/Protocol/Scope.cs b/OpenDreamRuntime/Procs/DebugAdapter/Protocol/Scope.cs index 7215b049be..ebb8ff497c 100644 --- a/OpenDreamRuntime/Procs/DebugAdapter/Protocol/Scope.cs +++ b/OpenDreamRuntime/Procs/DebugAdapter/Protocol/Scope.cs @@ -20,6 +20,7 @@ public sealed class Scope { * etc. */ [JsonPropertyName("presentationHint")] public string? PresentationHint { get; set; } + public const string PresentationHintArguments = "arguments"; public const string PresentationHintLocals = "locals"; public const string PresentationHintRegisters = "registers"; diff --git a/OpenDreamRuntime/Procs/DebugAdapter/Protocol/StackFrame.cs b/OpenDreamRuntime/Procs/DebugAdapter/Protocol/StackFrame.cs index bffc36a82e..b0421c3654 100644 --- a/OpenDreamRuntime/Procs/DebugAdapter/Protocol/StackFrame.cs +++ b/OpenDreamRuntime/Procs/DebugAdapter/Protocol/StackFrame.cs @@ -72,6 +72,7 @@ public sealed class StackFrame { * Values: 'normal', 'label', 'subtle' */ [JsonPropertyName("presentationHint")] public string? PresentationHint { get; set; } + public const string PresentationHintNormal = "normal"; public const string PresentationHintLabel = "label"; public const string PresentationHintSubtle = "subtle"; diff --git a/OpenDreamRuntime/Procs/DebugAdapter/Protocol/SteppingGranularity.cs b/OpenDreamRuntime/Procs/DebugAdapter/Protocol/SteppingGranularity.cs index c494b32f2e..b410b47eef 100644 --- a/OpenDreamRuntime/Procs/DebugAdapter/Protocol/SteppingGranularity.cs +++ b/OpenDreamRuntime/Procs/DebugAdapter/Protocol/SteppingGranularity.cs @@ -5,8 +5,10 @@ public static class SteppingGranularity { // The meaning of a statement is determined by the adapter and it may be considered equivalent to a line. // For example ‘for(int i = 0; i < 10; i++)’ could be considered to have 3 statements ‘int i = 0’, ‘i < 10’, and ‘i++’. public const string Statement = "statement"; + // The step should allow the program to run until the current source line has executed. public const string Line = "line"; + // The step should allow one instruction to execute (e.g. one x86 instruction). public const string Instruction = "instruction"; } diff --git a/OpenDreamRuntime/Procs/DebugAdapter/Protocol/StoppedEvent.cs b/OpenDreamRuntime/Procs/DebugAdapter/Protocol/StoppedEvent.cs index e618c62fc1..67276331a5 100644 --- a/OpenDreamRuntime/Procs/DebugAdapter/Protocol/StoppedEvent.cs +++ b/OpenDreamRuntime/Procs/DebugAdapter/Protocol/StoppedEvent.cs @@ -13,6 +13,7 @@ public sealed class StoppedEvent : IEvent { * 'function breakpoint', 'data breakpoint', 'instruction breakpoint', etc. */ [JsonPropertyName("reason")] public required string Reason { get; set; } + public const string ReasonStep = "step"; public const string ReasonBreakpoint = "breakpoint"; public const string ReasonException = "exception"; diff --git a/OpenDreamRuntime/Procs/DebugAdapter/Protocol/VariablePresentationHint.cs b/OpenDreamRuntime/Procs/DebugAdapter/Protocol/VariablePresentationHint.cs index f4c950b3c0..7b1f636577 100644 --- a/OpenDreamRuntime/Procs/DebugAdapter/Protocol/VariablePresentationHint.cs +++ b/OpenDreamRuntime/Procs/DebugAdapter/Protocol/VariablePresentationHint.cs @@ -27,6 +27,7 @@ public sealed class VariablePresentationHint { * etc. */ [JsonPropertyName("kind")] public string? Kind { get; set; } + public const string KindProperty = "property"; public const string KindMethod = "method"; public const string KindClass = "class"; @@ -57,6 +58,7 @@ public sealed class VariablePresentationHint { * etc. */ [JsonPropertyName("attributes")] public IEnumerable? Attributes { get; set; } + public const string AttributeStatic = "static"; public const string AttributeConstant = "constant"; public const string AttributeReadOnly = "readOnly"; @@ -72,6 +74,7 @@ public sealed class VariablePresentationHint { * Values: 'public', 'private', 'protected', 'internal', 'final', etc. */ [JsonPropertyName("visibility")] public string? Visiblity { get; set; } + public const string VisibilityPublic = "public"; public const string VisibilityPrivate = "private"; public const string VisibilityProtected = "protected"; diff --git a/OpenDreamRuntime/Procs/Native/DreamProcNativeHelpers.cs b/OpenDreamRuntime/Procs/Native/DreamProcNativeHelpers.cs index 70bc2c820f..dd63096614 100644 --- a/OpenDreamRuntime/Procs/Native/DreamProcNativeHelpers.cs +++ b/OpenDreamRuntime/Procs/Native/DreamProcNativeHelpers.cs @@ -70,6 +70,7 @@ public static IEnumerable MakeViewSpiral(DreamObjectAtom center if (mapMgr.TryGetTurfAt((startingCrossX+i, centerPos.Y - d), centerPos.Z, out var crissTurf)) { yield return crissTurf; } + //the cross if (mapMgr.TryGetTurfAt((startingCrossX + i, centerPos.Y + d), centerPos.Z, out var crossTurf)) { yield return crossTurf; @@ -346,6 +347,7 @@ public static bool IsObjectVisible(AtomManager atomManager, DreamObjectTree obje return false; } } + return true; } @@ -381,6 +383,7 @@ public static bool TryParseColorMatrix(DreamList list, out ColorMatrix matrix) { } } } + return true; case 9: // list(rr,rg,rb, gr,gg,gb, br,bg,bb) for (var row = 0; row < listArray.Count && row < 3; ++row) { @@ -390,6 +393,7 @@ public static bool TryParseColorMatrix(DreamList list, out ColorMatrix matrix) { listArray[offset + 2].MustGetValueAsFloat(), 0f); } + return true; case 12: // list(rr,rg,rb, gr,gg,gb, br,bg,bb, cr,cg,cb) for (var row = 0; row < listArray.Count && row < 3; ++row) { @@ -399,6 +403,7 @@ public static bool TryParseColorMatrix(DreamList list, out ColorMatrix matrix) { listArray[offset + 2].MustGetValueAsFloat(), 0f); } + //We skip over the alpha row in this one. It's kinda wonky. matrix.SetRow(4, listArray[9].MustGetValueAsFloat(), listArray[10].MustGetValueAsFloat(), @@ -414,6 +419,7 @@ public static bool TryParseColorMatrix(DreamList list, out ColorMatrix matrix) { listArray[offset + 2].MustGetValueAsFloat(), listArray[offset + 3].MustGetValueAsFloat()); } + return true; case 20: // list(rr, rg, rb, ra, gr, gg, gb, ga, br, bg, bb, ba, ar, ag, ab, aa, cr, cg, cb, ca) for (var row = 0; row < listArray.Count && row < 5; ++row) { @@ -423,6 +429,7 @@ public static bool TryParseColorMatrix(DreamList list, out ColorMatrix matrix) { listArray[offset + 2].MustGetValueAsFloat(), listArray[offset + 3].MustGetValueAsFloat()); } + return true; default: return false; diff --git a/OpenDreamRuntime/Procs/Native/DreamProcNativeMatrix.cs b/OpenDreamRuntime/Procs/Native/DreamProcNativeMatrix.cs index aaecbbea1f..576c106e6a 100644 --- a/OpenDreamRuntime/Procs/Native/DreamProcNativeMatrix.cs +++ b/OpenDreamRuntime/Procs/Native/DreamProcNativeMatrix.cs @@ -3,8 +3,8 @@ using DreamValueTypeFlag = OpenDreamRuntime.DreamValue.DreamValueTypeFlag; namespace OpenDreamRuntime.Procs.Native; -internal static class DreamProcNativeMatrix { +internal static class DreamProcNativeMatrix { [DreamProc("Add")] [DreamProcParameter("Matrix2", Type = DreamValueTypeFlag.DreamObject)] public static DreamValue NativeProc_Add(NativeProc.Bundle bundle, DreamObject? src, DreamObject? usr) { @@ -13,11 +13,11 @@ public static DreamValue NativeProc_Add(NativeProc.Bundle bundle, DreamObject? s DreamObjectMatrix.AddMatrix((DreamObjectMatrix)src!, matrixArg); return new DreamValue(src!); } + // On invalid input, throw runtime throw new Exception($"Invalid matrix for addition: {possibleMatrix.ToString()}"); } - [DreamProc("Invert")] public static DreamValue NativeProc_Invert(NativeProc.Bundle bundle, DreamObject? src, DreamObject? usr) { if (!DreamObjectMatrix.TryInvert((DreamObjectMatrix)src!)) { @@ -35,15 +35,18 @@ public static DreamValue NativeProc_Multiply(NativeProc.Bundle bundle, DreamObje DreamObjectMatrix.MultiplyMatrix((DreamObjectMatrix)src!, matrixArg); return new DreamValue(src!); } + // The other valid call is with a number "n" if (possibleMatrix.TryGetValueAsFloat(out float n)) { DreamObjectMatrix.ScaleMatrix((DreamObjectMatrix)src!, n, n); return new DreamValue(src!); } + // Special case: If null was passed, return src if (possibleMatrix.Equals(DreamValue.Null)) { return new DreamValue(src!); } + // Give up and turn the input into the zero matrix on invalid input DreamObjectMatrix.ScaleMatrix((DreamObjectMatrix)src!, 0, 0); return new DreamValue(src!); @@ -69,11 +72,11 @@ public static DreamValue NativeProc_Subtract(NativeProc.Bundle bundle, DreamObje DreamObjectMatrix.SubtractMatrix((DreamObjectMatrix)src!, matrixArg); return new DreamValue(src!); } + // On invalid input, throw runtime throw new Exception($"Invalid matrix for subtraction: {possibleMatrix.ToString()}"); } - [DreamProc("Translate")] [DreamProcParameter("x", Type = DreamValueTypeFlag.Float)] [DreamProcParameter("y", Type = DreamValueTypeFlag.Float)] @@ -109,6 +112,7 @@ public static DreamValue NativeProc_Turn(NativeProc.Bundle bundle, DreamObject? if (!angleArg.TryGetValueAsFloat(out float angle)) { return new DreamValue(src!); // Defaults to input on invalid angle } + return _NativeProc_TurnInternal(bundle.ObjectTree, (DreamObjectMatrix)src!, angle); } diff --git a/OpenDreamRuntime/Procs/Native/DreamProcNativeRegex.cs b/OpenDreamRuntime/Procs/Native/DreamProcNativeRegex.cs index 87713618fe..57dc9dde77 100644 --- a/OpenDreamRuntime/Procs/Native/DreamProcNativeRegex.cs +++ b/OpenDreamRuntime/Procs/Native/DreamProcNativeRegex.cs @@ -18,7 +18,7 @@ public static DreamValue NativeProc_Find(NativeProc.Bundle bundle, DreamObject? } int next = GetNext(src!, bundle.GetArgument(1, "start"), dreamRegex.IsGlobal, haystackString); - int end = bundle.GetArgument(2, "end").GetValueAsInteger(); + int end = bundle.GetArgument(2, "end").MustGetValueAsInteger(); dreamRegex.SetVariable("text", haystack); @@ -114,8 +114,8 @@ DreamValue DoTextReplace(string replacement) { public static DreamValue NativeProc_Replace(NativeProc.Bundle bundle, DreamObject? src, DreamObject? usr) { DreamValue haystack = bundle.GetArgument(0, "haystack"); DreamValue replacement = bundle.GetArgument(1, "replacement"); - int start = bundle.GetArgument(2, "start").GetValueAsInteger(); - int end = bundle.GetArgument(3, "end").GetValueAsInteger(); + int start = bundle.GetArgument(2, "start").MustGetValueAsInteger(); + int end = bundle.GetArgument(3, "end").MustGetValueAsInteger(); return RegexReplace(src, haystack, replacement, start, end); } @@ -125,12 +125,12 @@ private static int GetNext(DreamObject regexInstance, DreamValue startParam, boo if (isGlobal && regexInstance.GetVariable("text").TryGetValueAsString(out string? lastHaystack) && lastHaystack == haystackString) { DreamValue nextVar = regexInstance.GetVariable("next"); - return (!nextVar.IsNull) ? nextVar.GetValueAsInteger() : 1; + return (!nextVar.IsNull) ? nextVar.MustGetValueAsInteger() : 1; } else { return 1; } } else { - return startParam.GetValueAsInteger(); + return startParam.MustGetValueAsInteger(); } } } diff --git a/OpenDreamRuntime/Procs/Native/DreamProcNativeRoot.cs b/OpenDreamRuntime/Procs/Native/DreamProcNativeRoot.cs index 25f6d67819..ce430ef60a 100644 --- a/OpenDreamRuntime/Procs/Native/DreamProcNativeRoot.cs +++ b/OpenDreamRuntime/Procs/Native/DreamProcNativeRoot.cs @@ -982,8 +982,8 @@ public static DreamValue NativeProc_findlasttextEx(NativeProc.Bundle bundle, Dre return new DreamValue(failCount == 2 ? 1 : 0); } - int start = bundle.GetArgument(2, "Start").GetValueAsInteger(); //1-indexed - int end = bundle.GetArgument(3, "End").GetValueAsInteger(); //1-indexed + int start = bundle.GetArgument(2, "Start").MustGetValueAsInteger(); //1-indexed + int end = bundle.GetArgument(3, "End").MustGetValueAsInteger(); //1-indexed int actualstart; int actualcount; @@ -2258,7 +2258,7 @@ public static DreamValue NativeProc_replacetext(NativeProc.Bundle bundle, DreamO DreamValue needle = bundle.GetArgument(1, "Needle"); DreamValue replacementArg = bundle.GetArgument(2, "Replacement"); bundle.GetArgument(3, "Start").TryGetValueAsInteger(out var start); //1-indexed - int end = bundle.GetArgument(4, "End").GetValueAsInteger(); //1-indexed + int end = bundle.GetArgument(4, "End").MustGetValueAsInteger(); //1-indexed if (needle.TryGetValueAsDreamObject(out var regexObject)) { // According to the docs, this is the same as /regex.Replace() @@ -2351,8 +2351,8 @@ public static DreamValue NativeProc_replacetextEx(NativeProc.Bundle bundle, Drea return new DreamValue(result.ToString()); } - int start = bundle.GetArgument(3, "Start").GetValueAsInteger(); //1-indexed - int end = bundle.GetArgument(4, "End").GetValueAsInteger(); //1-indexed + int start = bundle.GetArgument(3, "Start").MustGetValueAsInteger(); //1-indexed + int end = bundle.GetArgument(4, "End").MustGetValueAsInteger(); //1-indexed if (start == 0) { // Return unmodified return new(text); @@ -2870,7 +2870,7 @@ public static DreamValue NativeProc_stat(NativeProc.Bundle bundle, DreamObject? [DreamProcParameter("Name")] [DreamProcParameter("Value")] public static DreamValue NativeProc_statpanel(NativeProc.Bundle bundle, DreamObject? src, DreamObject? usr) { - string panel = bundle.GetArgument(0, "Panel").GetValueAsString(); + string panel = bundle.GetArgument(0, "Panel").MustGetValueAsString(); DreamValue name = bundle.GetArgument(1, "Name"); DreamValue value = bundle.GetArgument(2, "Value"); @@ -3607,7 +3607,7 @@ public static DreamValue NativeProc_winset(NativeProc.Bundle bundle, DreamObject DreamValue player = bundle.GetArgument(0, "player"); DreamValue controlId = bundle.GetArgument(1, "control_id"); DreamValue winsetParams = bundle.GetArgument(2, "params"); - string? winsetControlId = (!controlId.IsNull) ? controlId.GetValueAsString() : null; + string? winsetControlId = (!controlId.IsNull) ? controlId.MustGetValueAsString() : null; DreamConnection? connection = null; if (player.TryGetValueAsDreamObject(out var mob)) { diff --git a/OpenDreamRuntime/Procs/Native/DreamProcNativeSavefile.cs b/OpenDreamRuntime/Procs/Native/DreamProcNativeSavefile.cs index 6513591624..c5b599f4e6 100644 --- a/OpenDreamRuntime/Procs/Native/DreamProcNativeSavefile.cs +++ b/OpenDreamRuntime/Procs/Native/DreamProcNativeSavefile.cs @@ -11,7 +11,6 @@ internal static class DreamProcNativeSavefile { [DreamProcParameter("path", Type = DreamValueTypeFlag.String)] [DreamProcParameter("file", Type = DreamValueTypeFlag.String | DreamValueTypeFlag.DreamResource)] public static DreamValue NativeProc_ExportText(NativeProc.Bundle bundle, DreamObject? src, DreamObject? usr) { - var savefile = (DreamObjectSavefile)src!; DreamValue path = bundle.GetArgument(0, "path"); DreamValue file = bundle.GetArgument(1, "file"); @@ -33,6 +32,7 @@ public static DreamValue NativeProc_ExportText(NativeProc.Bundle bundle, DreamOb throw new ArgumentException($"Invalid file value {file}"); } } + return new DreamValue(result); } @@ -44,6 +44,7 @@ private static string ExportTextInternal(DreamObjectSavefile savefile, int inden key = "."; indent = 0; //either way, set indent to 0 so we know we're not at the start anymore } + switch(value) { case DreamObjectSavefile.SFDreamPrimitive primitiveValue: if(primitiveValue.Value.IsNull) @@ -56,6 +57,7 @@ private static string ExportTextInternal(DreamObjectSavefile savefile, int inden result += $"{new string('\t', indent)}{key} = {primitiveValue.Value.MustGetValueAsFloat()}\n"; break; } + break; case DreamObjectSavefile.SFDreamFileValue fileValue: result += $"{new string('\t', indent)}{key} = \nfiledata(\""; @@ -93,6 +95,7 @@ private static string ExportTextInternal(DreamObjectSavefile savefile, int inden result += ExportTextInternal(savefile, indent + 1); savefile.CurrentPath = "../"; } + return result; } @@ -107,6 +110,7 @@ private static string ExportTextInternalListFormat(DreamObjectSavefile.SFDreamJs case DreamValue.DreamValueType.Float: return $"{primitiveValue.Value.MustGetValueAsFloat()}"; } + throw new NotImplementedException($"Unhandled list entry type {listEntry} in ExportTextInternalListFormat()"); case DreamObjectSavefile.SFDreamObjectPathValue objectValue: return $"object(\"{objectValue.Path}\")"; @@ -122,13 +126,13 @@ private static string ExportTextInternalListFormat(DreamObjectSavefile.SFDreamJs result += ExportTextInternalListFormat(listValue.AssocKeys[i]); result += ","; } + result = result.TrimEnd(','); result += ")"; return result; default: throw new NotImplementedException($"Unhandled list entry type {listEntry} in ExportTextInternalListFormat()"); } - } [DreamProc("Flush")] diff --git a/OpenDreamRuntime/Procs/ProcScheduler.Delays.cs b/OpenDreamRuntime/Procs/ProcScheduler.Delays.cs index 39d1fc3ca3..5857d42f07 100644 --- a/OpenDreamRuntime/Procs/ProcScheduler.Delays.cs +++ b/OpenDreamRuntime/Procs/ProcScheduler.Delays.cs @@ -57,7 +57,6 @@ public Task CreateDelayTicks(int ticks) { return tcs.Task; } - /// /// Insert a ticker into the queue to maintain sorted order /// diff --git a/OpenDreamRuntime/Procs/ProcScheduler.cs b/OpenDreamRuntime/Procs/ProcScheduler.cs index f4ae1566d5..8a4e397f67 100644 --- a/OpenDreamRuntime/Procs/ProcScheduler.cs +++ b/OpenDreamRuntime/Procs/ProcScheduler.cs @@ -69,11 +69,13 @@ public IEnumerable InspectThreads() { if (_current?.Thread is not null) { yield return _current.Thread; } + foreach (var state in _scheduled) { if (state.Thread == null) continue; yield return state.Thread; } + foreach (var state in _sleeping) { if (state.Thread == null) continue; diff --git a/OpenDreamShared/Network/Messages/MsgBrowseResource.cs b/OpenDreamShared/Network/Messages/MsgBrowseResource.cs index b2ca8e2870..49524ed64c 100644 --- a/OpenDreamShared/Network/Messages/MsgBrowseResource.cs +++ b/OpenDreamShared/Network/Messages/MsgBrowseResource.cs @@ -3,6 +3,7 @@ using Robust.Shared.Serialization; namespace OpenDreamShared.Network.Messages; + public sealed class MsgBrowseResource : NetMessage { // TODO: Browse should be on its own channel or something. public override MsgGroups MsgGroup => MsgGroups.EntityEvent; diff --git a/OpenDreamShared/Network/Messages/MsgBrowseResourceRequest.cs b/OpenDreamShared/Network/Messages/MsgBrowseResourceRequest.cs index f860e5724e..e4a262d70e 100644 --- a/OpenDreamShared/Network/Messages/MsgBrowseResourceRequest.cs +++ b/OpenDreamShared/Network/Messages/MsgBrowseResourceRequest.cs @@ -3,6 +3,7 @@ using Robust.Shared.Serialization; namespace OpenDreamShared.Network.Messages; + public sealed class MsgBrowseResourceRequest : NetMessage { // TODO: Browse should be on its own channel or something. public override MsgGroups MsgGroup => MsgGroups.EntityEvent; diff --git a/OpenDreamShared/Network/Messages/MsgBrowseResourceResponse.cs b/OpenDreamShared/Network/Messages/MsgBrowseResourceResponse.cs index 4f954737a0..3fecf32809 100644 --- a/OpenDreamShared/Network/Messages/MsgBrowseResourceResponse.cs +++ b/OpenDreamShared/Network/Messages/MsgBrowseResourceResponse.cs @@ -3,6 +3,7 @@ using Robust.Shared.Serialization; namespace OpenDreamShared.Network.Messages; + public sealed class MsgBrowseResourceResponse : NetMessage { // TODO: Browse should be on its own channel or something. public override MsgGroups MsgGroup => MsgGroups.EntityEvent; diff --git a/OpenDreamShared/Network/Messages/MsgSound.cs b/OpenDreamShared/Network/Messages/MsgSound.cs index b2e4f05c7b..1c399ac6e2 100644 --- a/OpenDreamShared/Network/Messages/MsgSound.cs +++ b/OpenDreamShared/Network/Messages/MsgSound.cs @@ -16,6 +16,7 @@ public enum FormatType : byte { public ushort Volume; public float Offset; public int? ResourceId; + public FormatType? Format; // TODO: This should probably be sent along with the sound resource instead somehow //TODO: Frequency and friends diff --git a/OpenDreamShared/Resources/DMIParser.cs b/OpenDreamShared/Resources/DMIParser.cs index 445d68c77f..617f4e3ff7 100644 --- a/OpenDreamShared/Resources/DMIParser.cs +++ b/OpenDreamShared/Resources/DMIParser.cs @@ -132,6 +132,7 @@ public void ExportAsText(StringBuilder text) { if (i != frames.Length - 1) text.Append(','); } + text.AppendLine(); } diff --git a/OpenDreamShared/SharedOpenDreamIoC.cs b/OpenDreamShared/SharedOpenDreamIoC.cs index 82c6934b59..e75320db10 100644 --- a/OpenDreamShared/SharedOpenDreamIoC.cs +++ b/OpenDreamShared/SharedOpenDreamIoC.cs @@ -1,9 +1,6 @@ namespace OpenDreamShared { public static class SharedOpenDreamIoC { public static void Register() { - } } - - }