Files
QuartZ-dump/GlobalShared/OcTree/OcTreeHandler.cs
2024-12-29 21:15:58 +01:00

140 lines
5.2 KiB
C#

using System.Collections.Generic;
using System.Linq;
using Global.Patches;
using Global.Shared.API;
using Global.Shared.Events;
using Global.Shared.OcTree.Data;
using Global.Shared.Plugin;
using Sandbox.Game.Entities;
using VRage.Game.Components;
using VRage.Game.Entity;
using VRage.Game.ModAPI;
namespace Global.Shared.OcTree
{
public class OcTreeHandler
{
public GenericOcTree<GridData> GridTree { get; private set; }
public GenericOcTree<ControllableEntityData> CharacterTree { get; private set; }
internal void Init()
{
var cfg = GlobalInstance.Config;
var offset = cfg.CenterPosition;
var x = cfg.Size;
var y = cfg.Size;
var z = cfg.Size;
GridTree = new GenericOcTree<GridData>(offset.X - x, offset.Y - y, offset.Z - z, x * 2, y * 2, z * 2,
cfg.Capacity, cfg.MaxDepth);
CharacterTree =
new GenericOcTree<ControllableEntityData>(offset.X - x, offset.Y - y, offset.Z - z, x * 2, y * 2, z * 2,
cfg.Capacity, cfg.MaxDepth);
BlockEvents.OnPlayerControlAcquired += AddControllableEntity;
BlockEvents.OnPlayerControlReleased += RemoveControllableEntity;
}
public IGridData AddGrid(MyCubeGrid grid)
{
var bigOwner = grid.BigOwners.Count == 0 ? "No Owner!" : grid.BigOwners.First().ToString();
// check if grid is new subgrid
if (MyMechanicalConnectionBlockBasePatch.IsCreatingSubPart)
{
GlobalInstance.Log.Trace(
$"Grid is subgrid, ignoring {grid.DisplayName} {grid.PositionComp.GetPosition()} {bigOwner}");
return null;
}
if (!GridTree.Contains(grid.EntityId))
{
var grids = grid.GetGridGroup(GridLinkTypeEnum.Mechanical).GetGrids(new List<IMyCubeGrid>());
var largestGrid = grid;
if (grids.Count > 1)
foreach (var g in grids.Cast<MyCubeGrid>())
if (g.BlocksCount > largestGrid.BlocksCount)
largestGrid = g;
grid = largestGrid;
//GlobalInstance.Log.Info(
//$"Adding grid to OcTree: {grid.EntityId} {grid.DisplayName} {grid.PositionComp.GetPosition()}");
var data = new GridData(grid);
grid.PositionComp.OnPositionChanged += Grid_OnPositionChanged;
grid.OnMarkForClose += RemoveGrid;
grid.OnTeleported += Grid_OnChanged;
GridTree.Insert(data);
grid.OnConnectionChanged += Grid_OnConnectionChanged;
GridEvents.GridCreated?.Invoke(grid);
return data;
}
GlobalInstance.Log.Debug(
$"Attempted to add grid to OcTree that already exists, {grid.DisplayName} {grid.PositionComp.GetPosition()} {bigOwner}");
var existing = GridTree[grid.EntityId];
if (existing != null) return existing;
GridTree.Remove(grid.EntityId);
return AddGrid(grid);
}
public void AddControllableEntity(IMyControllableEntity entity)
{
if (entity.ControllerInfo?.Controller?.Player == null && !(entity is IMyCharacter))
//GlobalInstance.Log.Info($"Entity is not controlled {entity.Entity.EntityId} {entity.Entity.DisplayName}");
return;
//GlobalInstance.Log.Debug($"AddControllableEntity {entity.Entity.EntityId} {entity.Entity.DisplayName}");
entity.Entity.OnMarkForClose += RemoveControllableEntity;
var data = new ControllableEntityData(entity);
if (!CharacterTree.Contains(entity.Entity.EntityId)) CharacterTree.Insert(data);
}
public void RemoveControllableEntity(IMyControllableEntity entity)
{
RemoveControllableEntity((MyEntity)entity);
}
public void RemoveControllableEntity(MyEntity entity)
{
//GlobalInstance.Log.Debug("RemoveControllableEntity");
CharacterTree.Remove(entity.EntityId);
}
private void Grid_OnConnectionChanged(MyCubeGrid arg1, GridLinkTypeEnum arg2)
{
if (arg2 != GridLinkTypeEnum.Mechanical) return;
GridTree.Update(arg1.EntityId);
}
internal void RemoveGrid(MyEntity grid)
{
GlobalInstance.Log.Debug($"Removing grid from OcTree: {grid.EntityId} {grid.DisplayName}");
GridEvents.GridRemoved?.Invoke(grid as MyCubeGrid);
grid.PositionComp.OnPositionChanged -= Grid_OnPositionChanged;
grid.OnMarkForClose -= RemoveGrid;
grid.OnTeleported -= Grid_OnChanged;
GridTree.Remove(grid.EntityId);
}
private void Grid_OnChanged(MyEntity obj)
{
GridTree.Update(obj.EntityId);
}
private void Grid_OnPositionChanged(MyPositionComponentBase obj)
{
if (!(obj.Entity is MyCubeGrid grid)) return;
if (grid.Closed || grid.MarkedForClose) return;
GridTree.Update(grid.EntityId);
}
}
}