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

[Port] Surgery Fixes #965

Merged
merged 7 commits into from
Dec 7, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions Content.Client/Inventory/ClientInventorySystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ public override void Initialize()

SubscribeLocalEvent<InventorySlotsComponent, LocalPlayerAttachedEvent>(OnPlayerAttached);
SubscribeLocalEvent<InventorySlotsComponent, LocalPlayerDetachedEvent>(OnPlayerDetached);
SubscribeLocalEvent<InventorySlotsComponent, RefreshInventorySlotsEvent>(OnRefreshInventorySlots);
SubscribeLocalEvent<InventoryComponent, ComponentShutdown>(OnShutdown);

SubscribeLocalEvent<InventorySlotsComponent, DidEquipEvent>((_, comp, args) =>
Expand Down Expand Up @@ -182,15 +181,6 @@ public void UpdateSlot(EntityUid owner, InventorySlotsComponent component, strin
EntitySlotUpdate?.Invoke(newData);
}

public void OnRefreshInventorySlots(EntityUid owner, InventorySlotsComponent component, RefreshInventorySlotsEvent args)
{
if (!component.SlotData.TryGetValue(args.SlotName, out var slotData)
|| _playerManager.LocalEntity != owner)
return;

OnSlotRemoved?.Invoke(slotData);
}

public bool TryAddSlotDef(EntityUid owner, InventorySlotsComponent component, SlotDefinition newSlotDef)
{
SlotData newSlotData = newSlotDef; //convert to slotData
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ public DefaultGameScreen()

Chat.OnResized += ChatOnResized;
Chat.OnChatResizeFinish += ChatOnResizeFinish;

MainViewport.OnResized += ResizeActionContainer;
MainViewport.OnResized += ResizeAlertsContainer;
Inventory.OnResized += ResizeActionContainer;
}

Expand All @@ -37,6 +37,12 @@ private void ResizeActionContainer()
Actions.ActionsContainer.MaxGridHeight = MainViewport.Size.Y - indent;
}

private void ResizeAlertsContainer()
{
float indent = Chat.Size.Y + Targeting.Size.Y + 120;
Alerts.AlertContainer.MaxGridHeight = Math.Max(MainViewport.Size.Y - indent, 1);
}

private void ChatOnResizeFinish(Vector2 _)
{
var marginBottom = Chat.GetValue<float>(MarginBottomProperty);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
MinSize="64 64">
<GridContainer Columns="1" HorizontalAlignment="Right" VerticalAlignment="Top">
<PanelContainer >
<BoxContainer Name="AlertContainer" Access="Public" Orientation="Vertical" />
<GridContainer Name="AlertContainer" Columns="1" HorizontalAlignment="Right" VerticalAlignment="Center" Access="Public" />
</PanelContainer>
<partStatus:PartStatusControl Name="PartStatus" Access="Protected"/>
</GridContainer>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public sealed partial class AlertsUI : UIWidget
public AlertsUI()
{
RobustXamlLoader.Load(this);
LayoutContainer.SetGrowHorizontal(this, LayoutContainer.GrowDirection.Begin);
}

public void SyncControls(AlertsSystem alertsSystem,
Expand Down
46 changes: 29 additions & 17 deletions Content.Server/Backmen/Surgery/SurgerySystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
using Content.Shared.Backmen.Surgery.Tools;
using Content.Shared.Bed.Sleep;
using Content.Shared.Medical.Surgery;
using Content.Shared.Verbs;

namespace Content.Server.Backmen.Surgery;

Expand All @@ -42,7 +43,7 @@ public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<SurgeryToolComponent, AfterInteractEvent>(OnToolAfterInteract);
SubscribeLocalEvent<SurgeryToolComponent, GetVerbsEvent<UtilityVerb>>(OnUtilityVerb);
SubscribeLocalEvent<SurgeryTargetComponent, SurgeryStepDamageEvent>(OnSurgeryStepDamage);
// You might be wondering "why aren't we using StepEvent for these two?" reason being that StepEvent fires off regardless of success on the previous functions
// so this would heal entities even if you had a used or incorrect organ.
Expand Down Expand Up @@ -101,30 +102,41 @@ private void SetDamage(EntityUid body,
targetPart: _body.GetTargetBodyPart(partComp));
}

private void OnToolAfterInteract(Entity<SurgeryToolComponent> ent, ref AfterInteractEvent args)
private void AttemptStartSurgery(Entity<SurgeryToolComponent> ent, EntityUid user, EntityUid target)
{
var user = args.User;
if (args.Handled
|| !args.CanReach
|| args.Target == null
|| !HasComp<SurgeryTargetComponent>(args.Target)
|| !TryComp<SurgeryTargetComponent>(args.User, out var surgery)
|| !surgery.CanOperate
|| !IsLyingDown(args.Target.Value, args.User))
{
if (!IsLyingDown(target, user))
return;
}

if (user == args.Target && !_config.GetCVar(Shared.Backmen.CCVar.CCVars.CanOperateOnSelf))
if (user == target && !_config.GetCVar(Shared.Backmen.CCVar.CCVars.CanOperateOnSelf))
{
_popup.PopupEntity(Loc.GetString("surgery-error-self-surgery"), user, user);
return;
}

args.Handled = true;
_ui.OpenUi(args.Target.Value, SurgeryUIKey.Key, user);
Log.Debug("UI opened");
RefreshUI(args.Target.Value);
_ui.OpenUi(target, SurgeryUIKey.Key, user);
RefreshUI(target);
}

private void OnUtilityVerb(Entity<SurgeryToolComponent> ent, ref GetVerbsEvent<UtilityVerb> args)
{
if (!args.CanInteract
|| !args.CanAccess
|| !HasComp<SurgeryTargetComponent>(args.Target))
return;

var user = args.User;
var target = args.Target;

var verb = new UtilityVerb()
{
Act = () => AttemptStartSurgery(ent, user, target),
Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Specific/Medical/Surgery/scalpel.rsi/"), "scalpel"),
Text = Loc.GetString("surgery-verb-text"),
Message = Loc.GetString("surgery-verb-message"),
DoContactInteraction = true
};

args.Verbs.Add(verb);
}

private void OnSurgeryStepDamage(Entity<SurgeryTargetComponent> ent, ref SurgeryStepDamageEvent args) =>
Expand Down
5 changes: 4 additions & 1 deletion Content.Server/Body/Commands/AddHandCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,10 @@ public void Execute(IConsoleShell shell, string argStr, string[] args)
if (attachAt == default)
attachAt = bodySystem.GetBodyChildren(entity, body).First();

var slotId = part.GetHashCode().ToString();
// Shitmed Change Start
var slotId = $"{part.Symmetry.ToString().ToLower()} {part.GetHashCode().ToString()}";
part.SlotId = part.GetHashCode().ToString();
// Shitmed Change End
Comment on lines +136 to +139
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Проверьте надежность генерации идентификаторов слотов

Текущая реализация генерации slotId и SlotId использует GetHashCode(), что может привести к коллизиям. GetHashCode() не гарантирует уникальность между запусками приложения.

Предлагаю следующие изменения:

-            var slotId = $"{part.Symmetry.ToString().ToLower()} {part.GetHashCode().ToString()}";
-            part.SlotId = part.GetHashCode().ToString();
+            var uniqueId = Guid.NewGuid().ToString("N").Substring(0, 8);
+            var slotId = $"{part.Symmetry.ToString().ToLower()}_{uniqueId}";
+            part.SlotId = uniqueId;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Shitmed Change Start
var slotId = $"{part.Symmetry.ToString().ToLower()} {part.GetHashCode().ToString()}";
part.SlotId = part.GetHashCode().ToString();
// Shitmed Change End
// Shitmed Change Start
var uniqueId = Guid.NewGuid().ToString("N").Substring(0, 8);
var slotId = $"{part.Symmetry.ToString().ToLower()}_{uniqueId}";
part.SlotId = uniqueId;
// Shitmed Change End

Comment on lines +136 to +139
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Критическая проблема: Несоответствие идентификаторов слота и части тела

Обнаружено несоответствие между генерируемыми идентификаторами:

  • Для слота используется формат: "{symmetry} {hashCode}"
  • Для части тела используется только: "{hashCode}"

Это несоответствие может привести к ошибкам при попытке прикрепления части тела.

Предлагаемое исправление:

-            var slotId = $"{part.Symmetry.ToString().ToLower()} {part.GetHashCode().ToString()}";
-            part.SlotId = part.GetHashCode().ToString();
+            var hashCode = part.GetHashCode().ToString();
+            var slotId = $"{part.Symmetry.ToString().ToLower()} {hashCode}";
+            part.SlotId = slotId;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Shitmed Change Start
var slotId = $"{part.Symmetry.ToString().ToLower()} {part.GetHashCode().ToString()}";
part.SlotId = part.GetHashCode().ToString();
// Shitmed Change End
// Shitmed Change Start
var hashCode = part.GetHashCode().ToString();
var slotId = $"{part.Symmetry.ToString().ToLower()} {hashCode}";
part.SlotId = slotId;
// Shitmed Change End

Comment on lines +136 to +139
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Критическая проблема: Небезопасное использование GetHashCode()

Использование GetHashCode() для генерации идентификаторов слотов может привести к проблемам, так как:

  • Значения хэш-кода могут меняться между запусками программы
  • Это может привести к несогласованности при сохранении/загрузке состояния игры

Предлагаемое решение:

-            var slotId = $"{part.Symmetry.ToString().ToLower()} {part.GetHashCode().ToString()}";
-            part.SlotId = part.GetHashCode().ToString();
+            var slotId = $"{part.Symmetry.ToString().ToLower()}_{Guid.NewGuid():N}";
+            part.SlotId = slotId;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Shitmed Change Start
var slotId = $"{part.Symmetry.ToString().ToLower()} {part.GetHashCode().ToString()}";
part.SlotId = part.GetHashCode().ToString();
// Shitmed Change End
// Shitmed Change Start
var slotId = $"{part.Symmetry.ToString().ToLower()}_{Guid.NewGuid():N}";
part.SlotId = slotId;
// Shitmed Change End


if (!bodySystem.TryCreatePartSlotAndAttach(attachAt.Id, slotId, hand, BodyPartType.Hand, attachAt.Component, part))
{
Expand Down
9 changes: 8 additions & 1 deletion Content.Server/Body/Commands/AttachBodyPartCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,15 @@ public void Execute(IConsoleShell shell, string argStr, string[] args)
return;
}

var slotId = $"AttachBodyPartVerb-{partUid}";
// Shitmed Change Start
var slotId = "";
if (part.Symmetry != BodyPartSymmetry.None)
slotId = $"{part.Symmetry.ToString().ToLower()} {part.GetHashCode().ToString()}";
else
slotId = $"{part.GetHashCode().ToString()}";
Comment on lines +102 to +106
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Несогласованность в генерации идентификаторов

В коде присутствует несогласованность между генерацией slotId и присвоением part.SlotId:

  • slotId использует комбинацию симметрии и хеш-кода
  • part.SlotId использует только хеш-код

Это может привести к проблемам при сопоставлении слотов и частей тела.

Предлагаемое исправление:

 var slotId = "";
 if (part.Symmetry != BodyPartSymmetry.None)
     slotId = $"{part.Symmetry.ToString().ToLower()} {part.GetHashCode().ToString()}";
 else
     slotId = $"{part.GetHashCode().ToString()}";

-part.SlotId = part.GetHashCode().ToString();
+part.SlotId = slotId;

Also applies to: 108-108

Comment on lines +102 to +106
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Улучшите генерацию идентификаторов слотов

Текущая реализация генерации slotId имеет несколько потенциальных проблем:

  1. Использование GetHashCode() может привести к коллизиям
  2. Конкатенация строк может быть неэффективной
  3. Отсутствует валидация сгенерированного ID

Предлагаю следующие изменения:

-            var slotId = "";
-            if (part.Symmetry != BodyPartSymmetry.None)
-                slotId = $"{part.Symmetry.ToString().ToLower()} {part.GetHashCode().ToString()}";
-            else
-                slotId = $"{part.GetHashCode().ToString()}";
+            var slotId = part.Symmetry != BodyPartSymmetry.None
+                ? $"{part.Symmetry.ToString().ToLower()}_{part.GetType().Name}_{Guid.NewGuid()}"
+                : $"{part.GetType().Name}_{Guid.NewGuid()}";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
var slotId = "";
if (part.Symmetry != BodyPartSymmetry.None)
slotId = $"{part.Symmetry.ToString().ToLower()} {part.GetHashCode().ToString()}";
else
slotId = $"{part.GetHashCode().ToString()}";
var slotId = part.Symmetry != BodyPartSymmetry.None
? $"{part.Symmetry.ToString().ToLower()}_{part.GetType().Name}_{Guid.NewGuid()}"
: $"{part.GetType().Name}_{Guid.NewGuid()}";


part.SlotId = part.GetHashCode().ToString();
// Shitmed Change End
Comment on lines +101 to +109
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Необходимо улучшить генерацию идентификаторов слотов

Текущая реализация имеет несколько проблем:

  1. Использование GetHashCode() для генерации идентификаторов может привести к коллизиям между запусками
  2. Комментарий "Shitmed Change" непрофессионален

Предлагаю следующие изменения:

-            // Shitmed Change Start
-            var slotId = "";
-            if (part.Symmetry != BodyPartSymmetry.None)
-                slotId = $"{part.Symmetry.ToString().ToLower()} {part.GetHashCode().ToString()}";
-            else
-                slotId = $"{part.GetHashCode().ToString()}";
-
-            part.SlotId = part.GetHashCode().ToString();
-            // Shitmed Change End
+            var slotId = part.Symmetry != BodyPartSymmetry.None
+                ? $"{part.Symmetry.ToString().ToLower()}_{Guid.NewGuid():N}"
+                : Guid.NewGuid().ToString("N");
+            
+            part.SlotId = slotId;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Shitmed Change Start
var slotId = "";
if (part.Symmetry != BodyPartSymmetry.None)
slotId = $"{part.Symmetry.ToString().ToLower()} {part.GetHashCode().ToString()}";
else
slotId = $"{part.GetHashCode().ToString()}";
part.SlotId = part.GetHashCode().ToString();
// Shitmed Change End
var slotId = part.Symmetry != BodyPartSymmetry.None
? $"{part.Symmetry.ToString().ToLower()}_{Guid.NewGuid():N}"
: Guid.NewGuid().ToString("N");
part.SlotId = slotId;

// ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
if (body.RootContainer.ContainedEntity != null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,4 @@ public sealed partial class BodyPartAppearanceComponent : Component
/// </summary>
[DataField, AutoNetworkedField]
public Color? EyeColor { get; set; }

[DataField, AutoNetworkedField]
public EntityUid? OriginalBody { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,20 @@ private void OnPartAppearanceStartup(EntityUid uid, BodyPartAppearanceComponent

return;

if (part.OriginalBody == null
|| TerminatingOrDeleted(part.OriginalBody.Value)
|| !TryComp(part.OriginalBody.Value, out HumanoidAppearanceComponent? bodyAppearance))
if (part.BaseLayerId != null)
{
component.ID = part.BaseLayerId;
component.Type = relevantLayer;
return;
}

if (part.Body is not { Valid: true } body
|| !TryComp(body, out HumanoidAppearanceComponent? bodyAppearance))
return;

var customLayers = bodyAppearance.CustomBaseLayers;
var spriteLayers = bodyAppearance.BaseLayers;
component.Type = relevantLayer;
component.OriginalBody = part.OriginalBody.Value;

part.Species = bodyAppearance.Species;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using Content.Shared.Backmen.Surgery.Steps.Parts;
using Content.Shared.Damage.Prototypes;
using Content.Shared.FixedPoint;
using Content.Shared.Inventory;

// ReSharper disable once CheckNamespace
namespace Content.Shared.Body.Systems;
Expand Down Expand Up @@ -181,23 +182,20 @@ private void OnBodyDamageModify(Entity<BodyComponent> bodyEnt, ref DamageModifyE
if (args.TargetPart != null)
{
var (targetType, _) = ConvertTargetBodyPart(args.TargetPart.Value);
args.Damage = args.Damage * GetPartDamageModifier(targetType);
args.Damage *= GetPartDamageModifier(targetType);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Изменена логика модификации урона

Модификация урона теперь учитывает инвентарь, что может привести к неожиданному поведению при отсутствии компонента инвентаря. Рекомендуется:

  1. Добавить проверку на null для inventory
  2. Логировать случаи, когда модификация урона не может быть применена

Предлагаемые изменения:

- if (partEnt.Comp.Body != null
-     && TryComp(partEnt.Comp.Body.Value, out InventoryComponent? inventory))
-     _inventory.RelayEvent((partEnt.Comp.Body.Value, inventory), ref args);
+ if (partEnt.Comp.Body != null)
+ {
+     if (TryComp(partEnt.Comp.Body.Value, out InventoryComponent? inventory))
+     {
+         _inventory.RelayEvent((partEnt.Comp.Body.Value, inventory), ref args);
+     }
+     else
+     {
+         Log.Debug($"No inventory component found for body {partEnt.Comp.Body.Value}");
+     }
+ }

Also applies to: 192-193, 198-198

}
}

private void OnPartDamageModify(Entity<BodyPartComponent> partEnt, ref DamageModifyEvent args)
{
if (partEnt.Comp.Body != null
&& TryComp(partEnt.Comp.Body.Value, out DamageableComponent? damageable)
&& damageable.DamageModifierSetId != null
&& _prototypeManager.TryIndex<DamageModifierSetPrototype>(damageable.DamageModifierSetId, out var modifierSet))
// TODO: We need to add a check to see if the given armor covers this part to cancel or not.
args.Damage = DamageSpecifier.ApplyModifierSet(args.Damage, modifierSet);
&& TryComp(partEnt.Comp.Body.Value, out InventoryComponent? inventory))
_inventory.RelayEvent((partEnt.Comp.Body.Value, inventory), ref args);

if (_prototypeManager.TryIndex<DamageModifierSetPrototype>("PartDamage", out var partModifierSet))
args.Damage = DamageSpecifier.ApplyModifierSet(args.Damage, partModifierSet);

args.Damage = args.Damage * GetPartDamageModifier(partEnt.Comp.PartType);
args.Damage *= GetPartDamageModifier(partEnt.Comp.PartType);
}

private bool TryChangePartDamage(EntityUid entity,
Expand Down Expand Up @@ -300,7 +298,7 @@ private static TargetBodyPart GetRandomPartSpread(IRobustRandom random, ushort t

/// This should be called after body part damage was changed.
/// </summary>
protected void CheckBodyPart(
public void CheckBodyPart(
Entity<BodyPartComponent> partEnt,
TargetBodyPart? targetPart,
bool severed,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@ private void CreatePart(EntityUid uid, GenerateChildPartComponent component)
component.Active = true;
Dirty(childPart, childPartComp);
}

_bodySystem.ChangeSlotState((uid, partComp), false);
}

// Still unusued, gotta figure out what I want to do with this function outside of fuckery with mantis blades.
Expand All @@ -60,7 +58,7 @@ private void DeletePart(EntityUid uid, GenerateChildPartComponent component)
if (!TryComp(uid, out BodyPartComponent? partComp))
return;

_bodySystem.ChangeSlotState((uid, partComp), true);
_bodySystem.DropSlotContents((uid, partComp));
var ev = new BodyPartDroppedEvent((uid, partComp));
RaiseLocalEvent(uid, ref ev);
QueueDel(uid);
Expand Down
10 changes: 10 additions & 0 deletions Content.Shared/Backmen/Surgery/SanitizedComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;

namespace Content.Shared.Backmen.Surgery;

/// <summary>
/// Prevents the entity from causing toxin damage to entities it does surgery on.
/// </summary>
[RegisterComponent, NetworkedComponent]
public sealed partial class SanitizedComponent : Component { }
13 changes: 8 additions & 5 deletions Content.Shared/Backmen/Surgery/SharedSurgerySystem.Steps.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using Content.Shared.Popups;
using Robust.Shared.Prototypes;
using System.Linq;
using Content.Shared.Backmen.Surgery;
using Content.Shared.Backmen.Mood;
using Content.Shared.Backmen.Surgery.Body.Events;
using Content.Shared.Backmen.Surgery.Body.Organs;
Expand All @@ -23,7 +24,6 @@
using Content.Shared.Backmen.Surgery.Steps.Parts;
using Content.Shared.Backmen.Surgery.Tools;
using Content.Shared.Containers.ItemSlots;
using Content.Shared.Medical.Surgery;
using AmputateAttemptEvent = Content.Shared.Body.Events.AmputateAttemptEvent;

namespace Content.Shared.Backmen.Surgery;
Expand Down Expand Up @@ -127,11 +127,14 @@ private void OnToolStep(Entity<SurgeryStepComponent> ent, ref SurgeryStepEvent a
RaiseLocalEvent(args.Body, new MoodEffectEvent("SurgeryPain"));

if (!_inventory.TryGetSlotEntity(args.User, "gloves", out var _)
|| !_inventory.TryGetSlotEntity(args.User, "mask", out var _))
|| !_inventory.TryGetSlotEntity(args.User, "mask", out var _))
{
var sepsis = new DamageSpecifier(_prototypes.Index<DamageTypePrototype>("Poison"), 5);
var ev = new SurgeryStepDamageEvent(args.User, args.Body, args.Part, args.Surgery, sepsis, 0.5f);
RaiseLocalEvent(args.Body, ref ev);
if (!HasComp<SanitizedComponent>(args.User))
{
var sepsis = new DamageSpecifier(_prototypes.Index<DamageTypePrototype>("Poison"), 5);
var ev = new SurgeryStepDamageEvent(args.User, args.Body, args.Part, args.Surgery, sepsis, 0.5f);
RaiseLocalEvent(args.Body, ref ev);
}
Comment on lines +130 to +137
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Проверьте логику применения урона от сепсиса

Текущая реализация имеет несколько проблем:

  1. Урон от сепсиса применяется только если у пользователя нет перчаток ИЛИ маски, что может быть слишком строго
  2. Фиксированное значение урона (5) лучше вынести в константу

Предлагаемые изменения:

-if (!_inventory.TryGetSlotEntity(args.User, "gloves", out var _)
-    || !_inventory.TryGetSlotEntity(args.User, "mask", out var _))
+private const float SEPSIS_DAMAGE = 5f;
+
+if (!_inventory.TryGetSlotEntity(args.User, "gloves", out var _) &&
+    !_inventory.TryGetSlotEntity(args.User, "mask", out var _))
{
    if (!HasComp<SanitizedComponent>(args.User))
    {
-        var sepsis = new DamageSpecifier(_prototypes.Index<DamageTypePrototype>("Poison"), 5);
+        var sepsis = new DamageSpecifier(_prototypes.Index<DamageTypePrototype>("Poison"), SEPSIS_DAMAGE);
        var ev = new SurgeryStepDamageEvent(args.User, args.Body, args.Part, args.Surgery, sepsis, 0.5f);
        RaiseLocalEvent(args.Body, ref ev);
    }
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
|| !_inventory.TryGetSlotEntity(args.User, "mask", out var _))
{
var sepsis = new DamageSpecifier(_prototypes.Index<DamageTypePrototype>("Poison"), 5);
var ev = new SurgeryStepDamageEvent(args.User, args.Body, args.Part, args.Surgery, sepsis, 0.5f);
RaiseLocalEvent(args.Body, ref ev);
if (!HasComp<SanitizedComponent>(args.User))
{
var sepsis = new DamageSpecifier(_prototypes.Index<DamageTypePrototype>("Poison"), 5);
var ev = new SurgeryStepDamageEvent(args.User, args.Body, args.Part, args.Surgery, sepsis, 0.5f);
RaiseLocalEvent(args.Body, ref ev);
}
private const float SEPSIS_DAMAGE = 5f;
if (!_inventory.TryGetSlotEntity(args.User, "gloves", out var _) &&
!_inventory.TryGetSlotEntity(args.User, "mask", out var _))
{
if (!HasComp<SanitizedComponent>(args.User))
{
var sepsis = new DamageSpecifier(_prototypes.Index<DamageTypePrototype>("Poison"), SEPSIS_DAMAGE);
var ev = new SurgeryStepDamageEvent(args.User, args.Body, args.Part, args.Surgery, sepsis, 0.5f);
RaiseLocalEvent(args.Body, ref ev);
}
}

}
}

Expand Down
10 changes: 0 additions & 10 deletions Content.Shared/Backmen/Targeting/Events.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,3 @@ public TargetIntegrityChangeEvent(NetEntity uid, bool refreshUi = true)
RefreshUi = refreshUi;
}
}

public sealed class RefreshInventorySlotsEvent : EntityEventArgs
{
public string SlotName { get; }

public RefreshInventorySlotsEvent(string slotName)
{
SlotName = slotName;
}
}
10 changes: 5 additions & 5 deletions Content.Shared/Body/Part/BodyPartComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
namespace Content.Shared.Body.Part;

[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
[Access(typeof(SharedBodySystem))]
//[Access(typeof(SharedBodySystem))]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

⚠️ Potential issue

Удаление атрибута [Access] может привести к проблемам безопасности

На основе анализа кодовой базы:

  • SharedBodySystem является основной системой для работы с BodyPartComponent, что подтверждается множеством частичных классов и зависимостей
  • Обнаружен прямой доступ к компоненту из BurnBodyBehavior, что указывает на потенциальные риски при снятии ограничений доступа
  • Компонент активно используется в различных подсистемах, включая хирургию и управление телом

Рекомендуется:

  • Сохранить атрибут [Access] для обеспечения контролируемого доступа к компоненту
  • Если требуется доступ из других систем, лучше реализовать его через SharedBodySystem
🔗 Analysis chain

Внимание: Проверьте необходимость отключения ограничения доступа!

Комментирование атрибута [Access] может привести к нежелательному доступу к компоненту из других систем.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Поиск использования BodyPartComponent в других системах
ast-grep --pattern 'class $_ {
  $$$
  private $_($_ : BodyPartComponent)
  $$$
}'

Length of output: 84


Script:

#!/bin/bash
# Поиск использования BodyPartComponent в системах
rg -l "BodyPartComponent" --type cs

# Поиск прямых обращений к BodyPartComponent
rg "BodyPartComponent\." --type cs -A 2

# Поиск систем, которые используют BodyPartComponent
ast-grep --pattern 'class $_System {
  $$$
  BodyPartComponent
  $$$
}'

Length of output: 1896


Script:

#!/bin/bash
# Проверяем, используется ли SharedBodySystem как основная система для работы с BodyPartComponent
rg "class SharedBodySystem" --type cs -A 5

# Проверяем, есть ли другие системы с прямым доступом к BodyPartComponent
rg "GetComponent<BodyPartComponent>" --type cs

# Проверяем атрибуты доступа у других компонентов в той же области
rg "\[Access\]" --type cs --glob "Content.Shared/Body/**"

Length of output: 3780

public sealed partial class BodyPartComponent : Component, ISurgeryToolComponent
{
// Need to set this on container changes as it may be several transform parents up the hierarchy.
Expand All @@ -22,9 +22,6 @@ public sealed partial class BodyPartComponent : Component, ISurgeryToolComponent
[DataField, AutoNetworkedField]
public EntityUid? Body;

[DataField, AutoNetworkedField]
public EntityUid? OriginalBody;

[DataField, AutoNetworkedField]
public BodyPartSlot? ParentSlot;

Expand All @@ -38,6 +35,9 @@ public sealed partial class BodyPartComponent : Component, ISurgeryToolComponent
[DataField, AlwaysPushInheritance]
public string ToolName { get; set; } = "A body part";

[DataField, AlwaysPushInheritance]
public string SlotId { get; set; } = "";

Comment on lines +38 to +40
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Необходимо документировать назначение SlotId

Добавлено новое свойство SlotId, но отсутствует документация о его назначении и использовании. Также стоит проверить инициализацию этого поля в существующем коде.

Предлагаю добавить документацию:

+    /// <summary>
+    ///     Уникальный идентификатор слота для данной части тела.
+    ///     Используется для определения позиции части тела в родительском объекте.
+    /// </summary>
     [DataField, AlwaysPushInheritance]
     public string SlotId { get; set; } = "";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
[DataField, AlwaysPushInheritance]
public string SlotId { get; set; } = "";
/// <summary>
/// Уникальный идентификатор слота для данной части тела.
/// Используется для определения позиции части тела в родительском объекте.
/// </summary>
[DataField, AlwaysPushInheritance]
public string SlotId { get; set; } = "";

[DataField, AutoNetworkedField]
public bool? Used { get; set; } = null;

Expand Down Expand Up @@ -153,7 +153,7 @@ public sealed partial class BodyPartComponent : Component, ISurgeryToolComponent
public bool IsVital;

[DataField, AutoNetworkedField]
public BodyPartSymmetry Symmetry = BodyPartSymmetry.None;
public BodyPartSymmetry Symmetry { get; set; } = BodyPartSymmetry.None;

/// <summary>
/// When attached, the part will ensure these components on the entity, and delete them on removal.
Expand Down
Loading
Loading