private static int MoveItem(IScriptRootData root, IItemsSource S, string N, IStructureData targetStructure, int count, int?maxLimit) { var target = targetStructure?.GetCurrent()?.GetDevice <Eleon.Modding.IContainer>(N); if (target == null) { Log($"TargetNoFound: {S.Id} #{S.Count} => {N}", LogLevel.Debug); return(count); } if (!targetStructure.ContainerSource.TryGetValue(N, out var targetData)) { Log($"TargetDataNoFound: {S.Id} #{S.Count} => {N}", LogLevel.Debug); return(count); } var tryMoveCount = maxLimit.HasValue ? Math.Max(0, Math.Min(count, maxLimit.Value - target.GetTotalItems(S.Id))) : count; using var locked = WeakCreateDeviceLock(root, root.GetCurrentPlayfield(), targetStructure.GetCurrent(), targetData.Position); if (!locked.Success) { Log($"DeviceIsLocked (Target): {S.Id} #{S.Count} => {targetData.CustomName}", LogLevel.Debug); return(count); } return(maxLimit.HasValue ? target.AddItems(S.Id, tryMoveCount) + (count - tryMoveCount) : target.AddItems(S.Id, tryMoveCount)); }
static void DeconstructPart(TextWriter output, IScriptRootData root, IStructure S, DeconstructData deconstructData, IContainer target, VectorInt3 targetPos, string N) { IDeviceLock locked = null; var startTime = DateTime.Now; var maxMilliSeconds = EmpyrionScripting.Configuration.Current.InGameScriptsIntervallMS; try { for (; deconstructData.Y >= deconstructData.MinPos.y; deconstructData.Y--) { for (; deconstructData.X <= deconstructData.MaxPos.x; deconstructData.X++) { for (; deconstructData.Z <= deconstructData.MaxPos.z; deconstructData.Z++) { deconstructData.CheckedBlocks++; var block = S.GetBlock(deconstructData.X, 128 + deconstructData.Y, deconstructData.Z); if (block != null) { block.Get(out var blockType, out _, out _, out _); if (blockType > 0 && blockType != PlayerCoreType) { locked = locked ?? CreateDeviceLock(EmpyrionScripting.ModApi?.Playfield, root.E.S.GetCurrent(), targetPos); if (!locked.Success) { deconstructData.CheckedBlocks--; output.WriteLine($"Container '{N}' is locked"); return; } if (target.AddItems(blockType, 1) > 0) { deconstructData.CheckedBlocks--; output.WriteLine($"Container '{N}' is full"); return; } block.Set(0); deconstructData.RemovedBlocks++; if (deconstructData.RemovedBlocks > 100 && deconstructData.RemovedBlocks % 100 == 0 && (DateTime.Now - startTime).TotalMilliseconds > maxMilliSeconds) { return; } } } } deconstructData.Z = deconstructData.MinPos.z; } deconstructData.X = deconstructData.MinPos.x; } } finally { locked?.Dispose(); } }
public void Add(IScriptRootData data) { if (WaitForExec.TryAdd(data.ScriptId, data)) { ExecQueue.Enqueue(data); } else { lock (ExecQueue) WaitForExec.AddOrUpdate(data.ScriptId, data, (i, d) => data); } }
public static IList <string> Scroll(IScriptRootData root, string content, int lines, int delay, int step) { var textlines = content.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); var outputLines = new List <string>(textlines); var overlapp = textlines.Length - lines; if (overlapp > 0) { var skip = root.CycleCounter / delay * step % textlines.Length; outputLines = textlines.Skip(skip).Take(lines).ToList(); outputLines.AddRange(textlines.Take(skip + lines - textlines.Length)); } return(outputLines); }
public bool ExecNext() { var found = false; IScriptRootData data = null; lock (ExecQueue) found = ExecQueue.TryDequeue(out data); if (!found) { return(false); } if (!ThreadPool.QueueUserWorkItem(ExecScript, data)) { Log($"EmpyrionScripting Mod: ExecNext NorThreadPoolFree {data.ScriptId}", LogLevel.Debug); return(false); } return(true); }
public void Add(IScriptRootData data) { if (ScriptNeedsMainThread.TryGetValue(data.ScriptId, out var needMainThread)) { data.ScriptNeedsMainThread = needMainThread; } else { ScriptNeedsMainThread.TryAdd(data.ScriptId, false); } if (WaitForExec.TryAdd(data.ScriptId, data)) { ExecQueue.Enqueue(data.ScriptId); } else { WaitForExec.AddOrUpdate(data.ScriptId, data, (scriptId, oldData) => data); } }
private static void AddTargetsAndDisplayType(IScriptRootData data, string targets) { if (targets.StartsWith("[")) { var typeEnd = targets.IndexOf(']'); if (typeEnd > 0) { var s = targets.Substring(1, typeEnd - 1); var appendAtEnd = s.EndsWith("+"); int.TryParse(appendAtEnd ? s.Substring(0, s.Length - 1) : s.Substring(1), out int Lines); data.DisplayType = new DisplayOutputConfiguration() { AppendAtEnd = appendAtEnd, Lines = Lines }; targets = targets.Substring(typeEnd + 1); } } data.LcdTargets.AddRange(data.E.S.AllCustomDeviceNames.GetUniqueNames(targets).Where(N => !N.StartsWith(ScriptKeyword))); }
public WeakDeviceLock(IScriptRootData root, IPlayfield playfield, IStructure structure, VectorInt3 position) { try { if (!root.ScriptWithinMainThread) { root.ScriptNeedsMainThread = true; return; } if (!root.DeviceLockAllowed || root.TimeLimitReached) { return; } Success = !playfield.IsStructureDeviceLocked(structure.Id, position); } catch (Exception error) { throw new Exception($"WeakDeviceLock:failed on Playfield:{playfield?.Name} at Id:{structure.Id} on {position} with: {error}"); } }
public DeviceLock(IScriptRootData root, IPlayfield playfield, IStructure structure, VectorInt3 position) { var witherror = false; try { if (!root.ScriptWithinMainThread) { root.ScriptNeedsMainThread = true; return; } if (!root.DeviceLockAllowed || root.TimeLimitReached) { return; } if (playfield.IsStructureDeviceLocked(structure.Id, position)) { return; } var lockkey = $"{structure.Id}#{position.x}#{position.y}#{position.z}"; var e = new AutoResetEvent(false); playfield.LockStructureDevice(structure.Id, position, true, (id, pos, success) => { if (id != structure.Id || pos != position) { return; } if (witherror) { Log($"Lock:Callback:Error {playfield.Name} {structure.Id} {position}", LogLevel.Debug); playfield.LockStructureDevice(structure.Id, position, false, null); } else { Success = success; e.Set(); } }); witherror = !e.WaitOne(10000); if (witherror) { Log($"Lock:WaitOne:Error {playfield.Name} {structure.Id} {position}", LogLevel.Debug); } if (Success) { unlockAction = () => { e.Reset(); playfield.LockStructureDevice(structure.Id, position, false, (id, pos, s) => { if (id != structure.Id || pos != position) { return; } e.Set(); }); if (!e.WaitOne(10000)) { Log($"Unlock:Timeout {playfield.Name} {structure.Id} {position}", LogLevel.Debug); } } } ; } catch (Exception error) { witherror = true; throw new Exception($"DeviceLock:failed on Playfield:{playfield?.Name} at Id:{structure.Id} on {position} with: {error}"); } }
public CsScriptFunctions(IScriptRootData root) { ScriptRoot = root; }
public ConsoleMock(IScriptRootData root) { Root = root; }
static void ProcessBlockPart(TextWriter output, IScriptRootData root, IStructure S, ProcessBlockData processBlockData, IContainer target, VectorInt3 targetPos, string N, int replaceId, Tuple <int, int>[] list, Func <IContainer, int, bool> processBlock) { IDeviceLock locked = null; try { for (; processBlockData.Y >= processBlockData.MinPos.y; processBlockData.Y--) { for (; processBlockData.X <= processBlockData.MaxPos.x; processBlockData.X++) { for (; processBlockData.Z <= processBlockData.MaxPos.z; processBlockData.Z++) { processBlockData.CheckedBlocks++; var block = S.GetBlock(processBlockData.X, 128 + processBlockData.Y, processBlockData.Z); if (block != null) { block.Get(out var blockType, out _, out _, out _); if (list != null && list.Length > 0 && !list.Any(L => L.Item1 <= blockType && L.Item2 >= blockType)) { blockType = 0; } if (blockType > 0 && blockType != PlayerCoreType) { if (EmpyrionScripting.Configuration.Current?.DeconstructBlockSubstitution != null && EmpyrionScripting.Configuration.Current.DeconstructBlockSubstitution.TryGetValue(blockType, out var substituteTo)) { blockType = substituteTo; } if (blockType > 0 && N != null) { locked = locked ?? WeakCreateDeviceLock(root, root.GetCurrentPlayfield(), root.E.S.GetCurrent(), targetPos); if (!locked.Success) { processBlockData.CheckedBlocks--; output.WriteLine($"Container '{N}' is locked"); return; } if (processBlock(target, blockType)) { processBlockData.CheckedBlocks--; output.WriteLine($"Container '{N}' is full"); return; } } block.Set(replaceId); processBlockData.RemovedBlocks++; if (processBlockData.RemovedBlocks > 100 && processBlockData.RemovedBlocks % 100 == 0 && root.TimeLimitReached) { return; } } } } processBlockData.Z = processBlockData.MinPos.z; } processBlockData.X = processBlockData.MinPos.x; } } finally { locked?.Dispose(); } }
public static IList <IItemMoveInfo> Fill(IScriptRootData root, IItemsData item, IStructureData structure, StructureTankType type, int maxLimit) { if (!root.DeviceLockAllowed) { Log($"Fill: NoLockAllowed({root.ScriptId}): {root.CycleCounter} % {EmpyrionScripting.Configuration.Current.DeviceLockOnlyAllowedEveryXCycles}", LogLevel.Debug); return(ItemMoveInfo.Empty); } var specialTransfer = type switch { StructureTankType.Oxygen => structure.OxygenTank, StructureTankType.Fuel => structure.FuelTank, StructureTankType.Pentaxid => structure.PentaxidTank, _ => null, }; if (specialTransfer == null || !specialTransfer.AllowedItem(item.Id)) { return(ItemMoveInfo.Empty); } Log($"Fill Total: #{item.Source.Count}", LogLevel.Debug); var moveInfos = new List <IItemMoveInfo>(); lock (moveLock) item.Source .ForEach(S => { using var locked = WeakCreateDeviceLock(root, root.GetCurrentPlayfield(), S.E?.S.GetCurrent(), S.Position); if (!locked.Success) { Log($"DeviceIsLocked (Source): {S.Id} #{S.Count} => {S.CustomName}", LogLevel.Debug); return; } var count = specialTransfer.ItemsNeededForFill(S.Id, maxLimit); if (count > 0) { count -= S.Container.RemoveItems(S.Id, count); Log($"Move(RemoveItems): {S.CustomName} {S.Id} #{S.Count}->{count}", LogLevel.Debug); } ItemMoveInfo currentMoveInfo = null; if (count > 0) { var startCount = count; count = specialTransfer.AddItems(S.Id, count); if (startCount != count) { moveInfos.Add(currentMoveInfo = new ItemMoveInfo() { Id = S.Id, Count = startCount - count, SourceE = S.E, Source = S.CustomName, DestinationE = structure.E, Destination = type.ToString(), }); } } ; if (count > 0) { count = S.Container.AddItems(S.Id, count); } if (count > 0 && currentMoveInfo != null) { root.GetPlayfieldScriptData().MoveLostItems.Enqueue(new ItemMoveInfo() { Id = S.Id, Count = count, SourceE = S.E, Source = S.CustomName, }); currentMoveInfo.Error = $"{{fill}} error lost #{count} of item {S.Id} in container {S.CustomName} -> add to retry list"; } }, () => root.TimeLimitReached); return(moveInfos); }
public static IList <IItemMoveInfo> Move(IScriptRootData root, IItemsData item, IStructureData structure, string namesSearch, int?maxLimit) { if (!root.DeviceLockAllowed) { Log($"Move: NoLockAllowed({root.ScriptId}): {root.CycleCounter} % {EmpyrionScripting.Configuration.Current.DeviceLockOnlyAllowedEveryXCycles}", LogLevel.Debug); return(ItemMoveInfo.Empty); } if (root.TimeLimitReached) { Log($"Move: TimeLimitReached({root.ScriptId})", LogLevel.Debug); return(ItemMoveInfo.Empty); } var uniqueNames = structure.AllCustomDeviceNames.GetUniqueNames(namesSearch); if (!uniqueNames.Any()) { Log($"NoDevicesFound: {namesSearch}", LogLevel.Debug); return(ItemMoveInfo.Empty); } var moveInfos = new List <IItemMoveInfo>(); lock (moveLock) item.Source .ForEach(S => { using var locked = WeakCreateDeviceLock(root, root.GetCurrentPlayfield(), S.E?.S.GetCurrent(), S.Position); if (!locked.Success) { Log($"DeviceIsLocked (Source): {S.Id} #{S.Count} => {S.CustomName}", LogLevel.Debug); return; } var count = S.Count; count -= S.Container.RemoveItems(S.Id, count); Log($"Move(RemoveItems): {S.CustomName} {S.Id} #{S.Count}->{count}", LogLevel.Debug); ItemMoveInfo currentMoveInfo = null; if (count > 0) { uniqueNames .Where(N => N != S.CustomName) .ForEach(N => { var startCount = count; count = MoveItem(root, S, N, structure, count, maxLimit); if (startCount != count) { var movedCount = startCount - count; moveInfos.Add(currentMoveInfo = new ItemMoveInfo() { Id = S.Id, Count = movedCount, SourceE = S.E, Source = S.CustomName, DestinationE = structure.E, Destination = N, }); Log($"Move(AddItems): {S.CustomName} {S.Id} #{S.Count}->{startCount - count}", LogLevel.Debug); // Für diesen Scriptdurchlauf dieses Item aus der Verarbeitung nehmen S.Count -= movedCount; } ; }, () => root.TimeLimitReached); } if (count > 0) { var retoureCount = count; count = S.Container.AddItems(S.Id, retoureCount); Log($"Move(retoure): {S.CustomName} {retoureCount} -> {count}", LogLevel.Debug); } if (count > 0) { root.GetPlayfieldScriptData().MoveLostItems.Enqueue(new ItemMoveInfo() { Id = S.Id, Count = count, SourceE = S.E, Source = S.CustomName, }); currentMoveInfo.Error = $"{{move}} error lost #{count} of item {S.Id} in container {S.CustomName} -> add to retry list"; } }, () => root.TimeLimitReached); return(moveInfos); }