Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Breaker manager optimisations #21

Merged
merged 13 commits into from
Jan 14, 2024
140 changes: 57 additions & 83 deletions Modules/Managers/BreakerManager.cs
Original file line number Diff line number Diff line change
@@ -1,112 +1,86 @@
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Entities;
using CounterStrikeSharp.API.Modules.Utils;

namespace RetakesPlugin.Modules.Managers;

public class BreakerManager
{
private readonly bool _shouldBreakBreakables;
private readonly bool _shouldOpenDoors;
private readonly List<(string designerName, string action)> _entityActions = new();

public BreakerManager(bool? shouldBreakBreakables, bool? shouldOpenDoors)
{
_shouldBreakBreakables = shouldBreakBreakables ?? false;
_shouldOpenDoors = shouldOpenDoors ?? false;
}

public void Handle()
{
if (_shouldBreakBreakables)
if (shouldBreakBreakables ?? false)
{
BreakBreakables();
_entityActions.AddRange(new List<(string designerName, string action)>
{
("func_breakable", "Break"),
("func_breakable_surf", "Break"),
("prop.breakable.01", "Break"),
("prop.breakable.02", "Break")
});

if (Server.MapName == "de_vertigo" || Server.MapName == "de_nuke")
{
_entityActions.Add(("prop_dynamic", "Break"));
}

if (Server.MapName == "de_nuke")
{
_entityActions.Add(("func_button", "Kill"));
}
}

if (_shouldOpenDoors)
if (shouldOpenDoors ?? false)
{
OpenDoors();
_entityActions.Add(("prop_door_rotating", "open"));
}
}

private static void BreakBreakables()
public void Handle()
{
var breakableEntities = new List<(string designerName, string action, Type entityType)>
{
("func_breakable", "Break", typeof(CBreakable)),
("func_breakable_surf", "Break", typeof(CBreakable)),
("prop.breakable.01", "Break", typeof(CBreakableProp)),
("prop.breakable.02", "Break", typeof(CBreakableProp))
};

breakableEntities.AddRange(
Utilities.FindAllEntitiesByDesignerName<CBreakable>("func_breakable")
.Select(entity => (entity.DesignerName, "Break", entity.GetType()))
);

breakableEntities.AddRange(
Utilities.FindAllEntitiesByDesignerName<CBreakable>("func_breakable_surf")
.Select(entity => (entity.DesignerName, "Break", entity.GetType()))
);

breakableEntities.AddRange(
Utilities.FindAllEntitiesByDesignerName<CBreakableProp>("prop_dynamic")
.Select(entity => (entity.DesignerName, "Break", entity.GetType()))
);

if (Server.MapName == "de_vertigo" || Server.MapName == "de_cache" || Server.MapName == "de_nuke")
if (_entityActions.Count == 0)
{
breakableEntities.Add(("prop_dynamic", "Break", typeof(CDynamicProp)));
return;
}

if (Server.MapName == "de_nuke")
{
breakableEntities.Add(("func_button", "Kill", typeof(CBaseButton)));
}

foreach (var (designerName, action, entityType) in breakableEntities)

var pEntity = new CEntityIdentity(EntitySystem.FirstActiveEntity);
for (; pEntity != null && pEntity.Handle != IntPtr.Zero; pEntity = pEntity.Next)
{
IEnumerable<object> entities = entityType switch
foreach (var (designerName, action) in _entityActions)
{
Type et when et == typeof(CBreakable) => Utilities.FindAllEntitiesByDesignerName<CBreakable>(
designerName),
Type et when et == typeof(CBreakableProp) => Utilities.FindAllEntitiesByDesignerName<CBreakableProp>(
designerName),
Type et when et == typeof(CDynamicProp) => Utilities.FindAllEntitiesByDesignerName<CDynamicProp>(
designerName),
Type et when et == typeof(CBaseButton) => Utilities.FindAllEntitiesByDesignerName<CBaseButton>(
designerName),
_ => throw new InvalidOperationException("Unsupported entity type")
};

foreach (var entity in entities)
{
if (entity is CBreakable breakable)
{
breakable.AcceptInput("Break");
}
else if (entity is CBreakableProp breakableProp)
if (pEntity.DesignerName != designerName)
{
breakableProp.AcceptInput("Break");
continue;
}
else if (entity is CDynamicProp dynamicProp)

switch (pEntity.DesignerName)
{
dynamicProp.AcceptInput("Break");
}
else if (entity is CBaseButton baseButton)
{
baseButton.AcceptInput("Break");
case "func_breakable":
case "func_breakable_surf":
new PointerTo<CBreakable>(pEntity.Handle).Value.AcceptInput(action);
break;

case "prop.breakable.01":
case "prop.breakable.02":
new PointerTo<CBreakableProp>(pEntity.Handle).Value.AcceptInput(action);
break;

case "prop_dynamic":
new PointerTo<CDynamicProp>(pEntity.Handle).Value.AcceptInput(action);
break;

case "func_button":
new PointerTo<CBaseButton>(pEntity.Handle).Value.AcceptInput(action);
break;

case "prop_door_rotating":
new PointerTo<CPropDoorRotating>(pEntity.Handle).Value.AcceptInput(action);
break;
}
break;
}
}
}

private static void OpenDoors()
{
// TODO: It'll probably be more efficient to do it during the entity loop above.
var doorEntities = Utilities.FindAllEntitiesByDesignerName<CPropDoorRotating>("prop_door_rotating");

foreach (var doorEntity in doorEntities)
{
doorEntity.AcceptInput("open");
}
}
}
}