@Preston SaveGameErrors/Exceptions kannst um im Logfile des Playfields sehen - aber ich versuche mal da was einfacheres ein zu bauen
I do something wrong with the IScriptModData rootObject. The .dll calling savegamescript: Code: public static void Main(IScriptModData rootObject){ //Scripts.CpuBoxFill.Run(rootObject); // reads item requests from vessels and try to refill it (much logic/security conditions) //Scripts.CpuBoxPurge.Run(rootObject); // gather all items from defined containers/vessels (much logic/security conditions) //Scripts.CpuBoxSort.Run(rootObject); // reads levels and items needs and try to preserve the item count for specified containers //Scripts.CpuStatBox.Run(rootObject); // draws container fill levels Scripts.CpuStatCpu.Run(rootObject); // draws processor device health information //Scripts.CpuStatDev.Run(rootObject); // draws defective devices //Scripts.CpuStatDock.Run(rootObject); // draws docked vessel data //Scripts.CpuStatL.Run(rootObject); // draws information overview for bigger displays //Scripts.CpuStatS.Run(rootObject); // draws compact information overview for smaller displays //Scripts.CpuStatThr.Run(rootObject); // draws thruster health information //Scripts.CpuStatWpn.Run(rootObject); // draws weapon health information //Scripts.CpuStatHll.Run(rootObject); // draws a structure damage overview scheme } //Scripts.CpuStatCpu.Run(CsRoot,E); Scripts.CpuStatHll.Run(CsRoot,E); The playfield log shows no compiler error and this script is running (partly). The call-version out of Main with direct usage of the fields "CsRoot" und "E" works perfectly fine. The .dll functions do what they should. But the Main-method version using the rootObject does simply nothing. No Lcd output and also no visible exception or failure at all. The rootObject is .dll-internal split into the known fields: Code: private static IScriptModData root = null; private static ICsScriptFunctions CsRoot = null; private static IEntityData E = null; private static IPlayfieldData P = null; private static void Init(IScriptModData rootObject) { if (root == null) { root = rootObject; CsRoot = rootObject.CsRoot; E = rootObject.E; P = rootObject.P; if (rootObject is IScriptSaveGameRootData data) { ItemGroups.SetFileRootPath(Path.Combine(data.MainScriptPath, "..")); } } } and used like this: Code: /.... public static void Run(IScriptModData rootObject) { Init(rootObject); // without structure powered and without "processing device" the scrip should "sleep" IBlockData[] deviceProcessors = CsRoot.Devices(E.S, sProcessorName); if (E.S.IsPowerd && deviceProcessors != null && deviceProcessors.Count() > 0) { //.... I assume that there are runtime-exceptions. Probably null-pointer ones. But without the savegame logging I will not identify them. Thanks for adding a log function.
Es wäre cool, wenn man den Debuglevel in der Console einstellen könnte. Und die Ausgaben dann dort erfolgen würden. Das API würde beides hergeben.
Version 5.9.1: Log SaveGameScriptsErrors in file all you need is "ScriptTrackingError": true, in the Configuration.json file PS: Fehler in der Console auszugeben hat das "Problem" das dies über das Netz geht und auch Spieler erreicht die keine Berechtigung haben dies zu sehen, da z.B. SafeGameScripte ja dem ServerAdmin vorbehalten sind welcher noch über dem InGameAdmin steht
Yep Code: ... finally { if (!string.IsNullOrEmpty(exceptionMessage)) { Log?.Invoke($"C# Run [{root.ScriptId}]:{exceptionMessage}", LogLevel.Error); if (EmpyrionScripting.Configuration.Current.ScriptTrackingError) { File.WriteAllText(root is ScriptSaveGameRootData saveGameRoot ? EmpyrionScripting.GetTrackingFileName(saveGameRoot) : EmpyrionScripting.GetTrackingFileName(root.E.GetCurrent(), root.Script.GetHashCode().ToString()) + ".error", exceptionMessage); } } }
Hmmmm, then: Houston, we have a problem. The script outputs nothing to the lcds if it uses the IScriptModData instead of CsRoot. With CsRoot without "Main" the script works fine. If no Exception is thrown, what could be the reason that the script does nothing but the Mod Runtine "thinks" all is fine? I tried to simple-access a Lcd and I try also to use "Console" to generate a step by step log. But nothing. All outputs I know seem to have the same problem. I think because they are all based on the rootObject while within Main. I will later write a simple .dll with rootObject to isolate the problem. Below is my actual .dll if some feels giddy to have a look.
I wrote a simple outputting test .dll using lcd access and console. The concole outputs should go to the right lcd. The lcd output should go to the left lcd. Errors should go to the right lcd or script tracking. But "nothing" happens: Code: using System; using System.Linq; using Eleon.Modding; using EmpyrionScripting.Interface; namespace CallTestLib { public static class TestClass { public static void Run(IScriptModData rootObject) { rootObject.Console.WriteLine("ConsoleOut01: " + DateTime.Now.ToString()); ICsScriptFunctions CsRoot = rootObject.CsRoot; IEntityData E = rootObject.E; rootObject.Console.WriteLine("ConsoleOut02: " + DateTime.Now.ToString()); IBlockData[] deviceProcessors = CsRoot.Devices(E.S, "C#:*"); if (E.S.IsPowerd && deviceProcessors != null && deviceProcessors.Count() > 0) { rootObject.Console.WriteLine("ConsoleOut03: " + DateTime.Now.ToString()); ILcd outputLcd = CsRoot.GetDevices<ILcd>(CsRoot.Devices(E.S, "DispCpuState")).FirstOrDefault(); outputLcd.SetText("DeviceOut01: " + DateTime.Now.ToString()); rootObject.Console.WriteLine("ConsoleOut04: " + DateTime.Now.ToString()); } } } }
I Ich schaue mir das mal an. Bei SafeGameScripten ist es zur Zeit so, das diese für die Struktur aufgerufen werden und nicht an ein LCD gekoppelt sind, somit gehen Console.Write Befehle ins Leere und mann muss sie selber auf ein LCD leiten. Ich werde heute das noch einbauen das solche Ausgaben auf ein LCD mit dem gleichen Namen wie das SaveganeScript ausgegeben werden wenn ein solches existiert - also z.B. CargoScript.cs -> CargoScript als LCD Name
Ich habe schon vermutet, dass "Console.WriteLine" nicht weiß wohin mit der Ausgabe. Aber das "selber auf ein LCD leiten" versucht meine CallTestLib.dll ja auch. Das funktioniert ja auch nicht. Wenn ich statt dem IScriptModData Objekt das ICsScriptFunctions Objekt (außerhalb von Main) an meine Lib übergebe, erreiche ich mit "GetDevices" auch die Lcds wieder. Irgendwas läuft da mit dem an die "Main" übergebenen Objekt schief. Wie macht denn der Script Compiler aus dem IScriptModData Objekt das ICsScriptFunctions Objekt "CsRoot", welches ingame zur Verfügung steht? Vielleicht erzeuge ich mein internes CsRoot-Objekt falsch?
Version 5.9.2: - SaveGameScripte: LCD output on LCD Named as filename without extension eg: "C:\steamcmd\empyrion\Saves\Games\Default\Mods\EmpyrionScripting\Scripts\CargoTeleporter.cs" -> LCD name: CargoTeleporter..... - CsRoot.Root added - Exception and output on target lcd @Preston this is with your DLL ;-)
I'm really sorry but I seem to have the talent to find unusual issues. -.- I try to write a adaption of your floor-script and struggled about a block position problem. My loops over the structure block positions between "E.S.MinPos" and "E.S.MaxPos" do not find any valid block. Therefore I write a simple output test to compare the real block positions with the areas which do "MinPos" and "MaxPos" return: Code: //......... public static void Run(IScriptModData root) { //Script Content Data ICsScriptFunctions CsRoot = root.CsRoot; IEntityData E = root.E; root.Console.WriteLine("Structure: " + E.Name); root.Console.WriteLine("MinPos: " + E.S.MinPos); root.Console.WriteLine("MaxPos: " + E.S.MaxPos); root.Console.WriteLine("LcdPos: " + CsRoot.Devices(E.S, "EgsEsExtension").FirstOrDefault().Position); //......... This is the result: As you can see in the lcd output and although in the di-display the lcd is out of the limits which "MinPos" and "MaxPos" return. From the code snippet I would say the underlying structure Object should be the same. And therefore I do not understand why the display can be outside the limits.
Min/Max bezieht sich (leider aus historischen Gründen) auf einen virtuellen Mittelpunkt x: 0 y:128 z:0 d.h. du musst auf das y noch 128 drauf addieren um die "echte" Blockposition zu bekommen :-(
Ich nehme mal an das "Y" die Höhe ist? nicht "Z"? Wenn ich mir die Positionen so anschaue, würde ich sagen Min/Max hat "recht" und die tatsächliche Position ist falsch. Meine Basis ist keine 141 Blöcke hoch. Aber meine Basis ist höher als breit und tief. Die Werte von Min/Max sind realistischer....hmmmm.
Genau X/Z ist die horizontale Ebene und Y die Höhe ... die 128 kommen aus den grauen Vorzeiten von Empyrion und sind leider nie "refactored" worden so das man einen "normalen" Nullpunkt gehabt hätte :-(
Hallo, Ich habe Schwierigkeiten auf einem Server Savegame Scripts zum laufen zu bekommen... (incl. dem AcriveRadar Script) Folgende Fragen hätte ich da: Wo ligt bei einem Server die Config? Gibt es eine Config Option das ganze einzuschalten? Wie schalte ich Fehlermeldungen ein? Muss ich den Server neu starten wenn ich etwas an einem Script ändere? Und noch eine Frage zum Scripting selber: kann ich irgendwie rausfinden ob ein Konstructor/Lebensmittel-Prozessor grade etwas tut? Danke für das Coole Mod und jede Hilfe! Michael
Im savegamepath, abhängig von deiner Servereinstellung, liegen alle für dich als "Anwender" relevanten Dateien. Configs, Permissions, Scripte, Logs, usw. z.B.: D:\GameServerBackUps\Empyrion\Games\(savegamename)\Mods\EmpyrionScripting Mit den Initialwerten in Configuration.json läuft alles. Configuration.json --> "ScriptTracking" und "ScriptErrorTracking" auf "true" Dann enstehen im Savegamepath neue dateien. Die Ingame Fehlermeldungen auf den Lcds sind aber auch ohne diese Einstellung "an". Jein Die Mod überwacht alle Dateien und "startet sich automatisch neu" wenn sich eine Datei ändert. Allerdings scheint Eleon mit dem Update 1.x ein paar Instabilitäten eingebaut zu haben. Bei mir hängt sich die Mod gelegentlich bei Änderungen an den Dateien auf und ich muss den Server dann doch neu starten. Soweit ich weiß ist das Interface für die Konstruktoren noch nicht fertig.
OK, ich hab jetzt die ersten savegame scripts laufen und gleich neue Fragen: Ist der Aktualisierungs-Intervall fest (scheint immer 10s zu sein) oder kann der schwanken? Kann ich irgendwie mit der Zeit rechnen? sowas wie vergangene Sekunden seit X? Läuft das Script auf dem Server weiter wenn ich offline bin?
Der Intervall steht standardmäßig auf 10000ms und kann in der Configuration.json verändert werden. Da die Scripts den Server nicht behindern sollen, werden sie im Backgroundworker verarbeitet, welcher nicht deterministisch ist. Es können also auch mal 11000ms werden. Wenn du es genauer brauchst, muss du mit der C# Klasse "DateTime" arbeiten. Das Script läuft Playfield bezogen. Abhängig von der Einstellung deines Server(leer-Playfield-Verarbeitung) läuft das Script also weiter.