using System; using System.Collections; using System.Collections.Generic; using System.Linq; using MessagePack; using Newtonsoft.Json; using Unity.Mathematics; using static Unity.Mathematics.math; [MessagePackObject, JsonObject(MemberSerialization.OptIn), EntityTypeRestriction(HullType.Ship), Order(-100)] public class MiningControllerData : ControllerData { public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item) { return new MiningController(context, this, entity, item); } } public class MiningController : ControllerBase, IBehavior, IPersistentBehavior, IInitializableBehavior { public override TaskType TaskType => TaskType.Mine; public BehaviorData Data => _data; private MiningControllerData _data; private GameContext _context; private Entity _entity; private Gear _item; private bool _taskStarted; private int _asteroid = -1; private MiningTool _miningTool; private Switch _toolSwitch; public MiningController(GameContext context, MiningControllerData data, Entity entity, Gear item) : base(context, data, entity) { _context = context; _data = data; _entity = entity; _item = item; } public new void Initialize() { _miningTool = _entity.GetBehavior(); _toolSwitch = _entity.GetSwitch(); base.Initialize(); } public new bool Update(float delta) { var miningTask = _context.Cache.Get(Task); if (miningTask != null) { if (!_taskStarted) { NextAsteroid(); _taskStarted = true; } else { if (!Moving) { if (_entity.OccupiedCapacity < _entity.Capacity - 1) { var asteroidTransform = Zone.GetAsteroidTransform(miningTask.Asteroids, _asteroid); if (length(_entity.Position - asteroidTransform.xy) - asteroidTransform.w > _miningTool.Range) { _entity.SetMessage("Moving to target asteroid."); MoveTo(() => Zone.GetAsteroidTransform(miningTask.Asteroids, _asteroid).xy, () => Zone.GetAsteroidVelocity(miningTask.Asteroids, _asteroid)); _toolSwitch.Activated = false; } else { if (Zone.AsteroidExists(miningTask.Asteroids, _asteroid)) { _miningTool.AsteroidBelt = miningTask.Asteroids; _miningTool.Asteroid = _asteroid; _toolSwitch.Activated = true; Aim.Objective = Zone.GetAsteroidTransform(miningTask.Asteroids, _asteroid).xy; Aim.Update(delta); } else NextAsteroid(); } } else { _entity.SetMessage("Out of cargo space. Returning home to offload cargo."); GoHome(OnArriveHome); } } } } return base.Update(delta); } private void OnArriveHome() { var homeEntity = _context.Cache.Get(HomeEntity); foreach (var item in _entity.Cargo .Select(id => _context.Cache.Get(id)) .Where(item => item is SimpleCommodity) .Cast() .ToArray()) { int quantity = min((int) ((homeEntity.Capacity - homeEntity.OccupiedCapacity) / item.ItemData.Size), item.Quantity); var newItem = _entity.RemoveCargo(item, quantity); homeEntity.AddCargo(newItem); if (quantity < item.Quantity) { homeEntity.SetMessage("Colony is out of cargo space. Closing Mining Task."); FinishTask(); _taskStarted = false; return; } } } private void NextAsteroid() { var miningTask = _context.Cache.Get(Task); _asteroid = Zone.NearestAsteroid(miningTask.Asteroids, _entity.Position); _entity.SetMessage("Selecting new asteroid."); } public PersistentBehaviorData Store() { return new MiningControllerPersistence { Task = Task }; } public void Restore(PersistentBehaviorData data) { var miningControllerPersistence = data as MiningControllerPersistence; Task = miningControllerPersistence.Task; } } public class MiningControllerPersistence : PersistentBehaviorData { [JsonProperty("task"), Key(0)] public Guid Task; }