Created
May 22, 2020 16:09
-
-
Save spectras/2527493bcd32dc66eb52fab500e1d7c8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Sandbox.Game.EntityComponents; | |
using Sandbox.ModAPI.Ingame; | |
using Sandbox.ModAPI.Interfaces; | |
using SpaceEngineers.Game.ModAPI.Ingame; | |
using System.Collections.Generic; | |
using System.Collections; | |
using System.Linq; | |
using System.Text; | |
using System; | |
using VRage.Collections; | |
using VRage.Game.Components; | |
using VRage.Game.GUI.TextPanel; | |
using VRage.Game.ModAPI.Ingame.Utilities; | |
using VRage.Game.ModAPI.Ingame; | |
using VRage.Game.ObjectBuilders.Definitions; | |
using VRage.Game; | |
using VRage; | |
using VRageMath; | |
using Sandbox.Game.Screens.Helpers; | |
using EmptyKeys.UserInterface.Generated.EditFactionIconView_Bindings; | |
using System.Xml; | |
namespace IngameScript | |
{ | |
partial class Program | |
{ | |
public partial class RecycleRange : ISubProgram | |
{ | |
List<IMySensorBlock> ShipSensors; | |
List<IMyMotorStator> Doors; | |
List<IMyLightingBlock> DoorLights; | |
List<IMyShipGrinder> Grinders; | |
// List<IMyTerminalBlock> Containers; | |
// IMyTextSurface Display; | |
// List<IMyFunctionalBlock> ActivityIndicators; | |
// List<IMyFunctionalBlock> ErrorIndicators; | |
// List<IMyFunctionalBlock> WorkingIndicators; | |
public readonly string SectionName; | |
public ITextStream Logger; | |
public UpdateFrequency UpdateFrequency { get; private set; } | |
State CurrentState; | |
public RecycleRange(string sectionName, ITextStream logger) | |
{ | |
ShipSensors = new List<IMySensorBlock>(); | |
// Containers = new List<IMyTerminalBlock>(); | |
Doors = new List<IMyMotorStator>(); | |
DoorLights = new List<IMyLightingBlock>(); | |
Grinders = new List<IMyShipGrinder>(); | |
SectionName = sectionName; | |
Logger = logger; | |
CurrentState = null; | |
UpdateFrequency = UpdateFrequency.None; | |
} | |
public void Rescan(IMyGridTerminalSystem grid, IMyTerminalBlock me) | |
{ | |
Logger.Write("Rescanning...\n"); | |
Func<IMyTerminalBlock, bool> onMyGrid = (block => block.IsSameConstructAs(me)); | |
util.GetBlocksWithSection<IMySensorBlock>(grid, SectionName, ShipSensors, onMyGrid); | |
util.GetBlocksWithSection<IMyMotorStator>(grid, SectionName, Doors, block => onMyGrid(block) && block.Torque > 0.0); | |
util.GetBlocksWithSection<IMyLightingBlock>(grid, SectionName, DoorLights, onMyGrid); | |
grid.GetBlocksOfType<IMyShipGrinder>(Grinders, onMyGrid); | |
foreach (var sensor in ShipSensors) { Logger.Write($"ShipSensor: {sensor.CustomName}\n"); } | |
foreach (var door in Doors) { Logger.Write($"Door: {door.CustomName}\n"); } | |
foreach (var light in DoorLights) { Logger.Write($"DoorLight: {light.CustomName}\n"); } | |
Logger.Write($"Found {Grinders.Count} grinders\n"); | |
} | |
public void Reset() | |
{ | |
if (CurrentState != null) { CurrentState.Leave(this); } | |
CurrentState = new IdleState(); | |
CurrentState.Enter(this); | |
Logger.Write("Reset to idle state\n"); | |
} | |
public void Main(string argument, UpdateType source) | |
{ | |
State newState = null; | |
if ((source & UpdateType.Terminal) != 0 || (source & UpdateType.Trigger) != 0) { | |
newState = CurrentState.OnCommand(this, argument); | |
} | |
if ((source & UpdateType.Update100) != 0) { | |
newState = CurrentState.OnUpdate(this, source); | |
} | |
if (newState != CurrentState) { | |
Logger.Write($"Switching to {newState}\n"); | |
CurrentState.Leave(this); | |
newState.Enter(this); | |
CurrentState = newState; | |
} | |
} | |
void StartDoors() | |
{ | |
foreach (var door in Doors) { | |
door.TargetVelocityRPM = -door.TargetVelocityRPM; | |
door.RotorLock = false; | |
door.Enabled = true; | |
} | |
foreach (var light in DoorLights) { | |
light.BlinkIntervalSeconds = 2.0f; // todo make it configurable | |
light.BlinkLength = 20.0f; // allow color change too | |
} | |
} | |
void StopDoors() | |
{ | |
foreach (var door in Doors) { | |
door.RotorLock = true; | |
door.Enabled = false; | |
} | |
foreach (var light in DoorLights) { | |
light.BlinkIntervalSeconds = 0.0f; // todo color change too | |
} | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Sandbox.Game.EntityComponents; | |
using Sandbox.ModAPI.Ingame; | |
using Sandbox.ModAPI.Interfaces; | |
using SpaceEngineers.Game.ModAPI.Ingame; | |
using System.Collections.Generic; | |
using System.Collections; | |
using System.Linq; | |
using System.Text; | |
using System; | |
using VRage.Collections; | |
using VRage.Game.Components; | |
using VRage.Game.GUI.TextPanel; | |
using VRage.Game.ModAPI.Ingame.Utilities; | |
using VRage.Game.ModAPI.Ingame; | |
using VRage.Game.ObjectBuilders.Definitions; | |
using VRage.Game; | |
using VRage; | |
using VRageMath; | |
namespace IngameScript | |
{ | |
partial class Program | |
{ | |
public partial class RecycleRange | |
{ | |
private const int ImmobilityCycles = 10; | |
private const float DoorEpsilon = 0.00628f; | |
abstract class State | |
{ | |
public virtual void Enter(RecycleRange station) { } | |
public virtual void Leave(RecycleRange station) { } | |
public virtual State OnCommand(RecycleRange station, string argument) { return this; } | |
public virtual State OnUpdate(RecycleRange station, UpdateType source) { return this; } | |
} | |
class IdleState : State | |
{ | |
public override void Enter(RecycleRange station) | |
{ | |
//TODO turn lights off | |
foreach (var sensor in station.ShipSensors) { | |
sensor.DetectPlayers = false; | |
sensor.DetectFloatingObjects = false; | |
sensor.DetectSmallShips = true; | |
sensor.DetectLargeShips = true; | |
sensor.DetectStations = false; | |
sensor.DetectSubgrids = false; | |
sensor.DetectAsteroids = false; | |
sensor.DetectOwner = true; | |
sensor.DetectFriendly = true; | |
sensor.DetectNeutral = true; | |
sensor.DetectEnemy = true; | |
sensor.Enabled = true; | |
} | |
} | |
public override void Leave(RecycleRange station) | |
{ | |
foreach (var sensor in station.ShipSensors) { sensor.Enabled = false; } | |
} | |
public override State OnCommand(RecycleRange station, string argument) | |
{ | |
if (argument == "load") { return new LoadingState(); } | |
return this; | |
} | |
} | |
class LoadingState : State | |
{ | |
public override void Enter(RecycleRange station) | |
{ | |
//TODO turn lights on | |
} | |
public override State OnCommand(RecycleRange station, string argument) | |
{ | |
if (argument == "start") { return new LockingState(); } | |
return this; | |
} | |
} | |
class LockingState : State | |
{ | |
public override void Enter(RecycleRange station) | |
{ | |
station.StartDoors(); | |
station.UpdateFrequency = UpdateFrequency.Update100; | |
} | |
public override void Leave(RecycleRange station) | |
{ | |
station.StopDoors(); | |
station.UpdateFrequency = UpdateFrequency.None; | |
} | |
public override State OnUpdate(RecycleRange station, UpdateType source) | |
{ | |
var inProgress = station.Doors.Exists(door => { | |
var angle = door.Angle; | |
return door.LowerLimitRad + DoorEpsilon < angle | |
&& angle < door.UpperLimitRad - DoorEpsilon; | |
}); | |
if (!inProgress) { return new ProcessingState(); } | |
return this; | |
} | |
public override State OnCommand(RecycleRange station, string argument) | |
{ | |
if (argument == "stop") { return new UnlockingState(); } | |
return this; | |
} | |
} | |
class ProcessingState : State | |
{ | |
class EntityInfo | |
{ | |
public Vector3D Position; | |
public int ChangeCycle; | |
} | |
private Dictionary<long, EntityInfo> Entities; | |
private int Cycle; | |
private List<MyDetectedEntityInfo> DetectedEntities; // cached to avoid allocating on all updates | |
public ProcessingState() | |
{ | |
Entities = new Dictionary<long, EntityInfo>(); | |
Cycle = 0; | |
DetectedEntities = new List<MyDetectedEntityInfo>(); | |
} | |
public override void Enter(RecycleRange station) | |
{ | |
foreach (var sensor in station.ShipSensors) { sensor.Enabled = true; } | |
foreach (var grinder in station.Grinders) { | |
grinder.UseConveyorSystem = true; | |
grinder.Enabled = true; | |
} | |
station.UpdateFrequency = UpdateFrequency.Update100; | |
} | |
public override void Leave(RecycleRange station) | |
{ | |
foreach (var sensor in station.ShipSensors) { sensor.Enabled = false; } | |
foreach (var grinder in station.Grinders) { grinder.Enabled = false; } | |
station.UpdateFrequency = UpdateFrequency.None; | |
} | |
public override State OnCommand(RecycleRange station, string argument) | |
{ | |
if (argument == "pause") { return new PausedState(); } | |
if (argument == "stop") { return new UnlockingState(); } | |
return this; | |
} | |
public override State OnUpdate(RecycleRange station, UpdateType source) | |
{ | |
EntityInfo info; | |
Cycle += 1; | |
int lastMoveCycle = 0; | |
foreach (var sensor in station.ShipSensors) { | |
sensor.DetectedEntities(DetectedEntities); | |
foreach (var entity in DetectedEntities) { | |
var position = entity.BoundingBox.Center; | |
if (!Entities.TryGetValue(entity.EntityId, out info)) { | |
info = new EntityInfo() { | |
Position = position, | |
ChangeCycle = Cycle | |
}; | |
station.Logger.Write($"Added entity {entity.EntityId}\n"); | |
Entities.Add(entity.EntityId, info); | |
lastMoveCycle = Cycle; | |
} else { | |
if (info.Position.Equals(position, 0.01)) { | |
lastMoveCycle = Math.Max(lastMoveCycle, info.ChangeCycle); | |
} else { | |
station.Logger.Write($"Live entity {entity.EntityId}\n"); | |
info.Position = position; | |
info.ChangeCycle = Cycle; | |
lastMoveCycle = Cycle; | |
} | |
} | |
} | |
DetectedEntities.Clear(); | |
} | |
station.Logger.Write($"Cycle: {Cycle}, last move: {lastMoveCycle}\n"); | |
if (Cycle > lastMoveCycle + ImmobilityCycles) { return new UnlockingState(); } | |
return this; | |
} | |
} | |
class PausedState : State | |
{ | |
public override State OnCommand(RecycleRange station, string argument) | |
{ | |
if (argument == "start") { return new ProcessingState(); } | |
if (argument == "stop") { return new UnlockingState(); } | |
return this; | |
} | |
} | |
class UnlockingState : State | |
{ | |
public override void Enter(RecycleRange station) | |
{ | |
station.StartDoors(); | |
station.UpdateFrequency = UpdateFrequency.Update100; | |
} | |
public override void Leave(RecycleRange station) | |
{ | |
station.StopDoors(); | |
station.UpdateFrequency = UpdateFrequency.None; | |
} | |
public override State OnUpdate(RecycleRange station, UpdateType source) | |
{ | |
var inProgress = station.Doors.Exists(door => { | |
var angle = door.Angle; | |
return door.LowerLimitRad + DoorEpsilon < angle | |
&& angle < door.UpperLimitRad - DoorEpsilon; | |
}); | |
if (!inProgress) { return new IdleState(); } | |
return this; | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment