Unrevert #10934
This commit is contained in:
@@ -1,7 +1,8 @@
|
|||||||
using Content.Shared.Damage;
|
using Content.Shared.Damage;
|
||||||
using Content.Server.Examine;
|
using Content.Server.Examine;
|
||||||
using Content.Shared.Verbs;
|
using Content.Shared.Verbs;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
using Content.Shared.Inventory;
|
||||||
|
|
||||||
namespace Content.Server.Armor
|
namespace Content.Server.Armor
|
||||||
{
|
{
|
||||||
@@ -14,13 +15,13 @@ namespace Content.Server.Armor
|
|||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
SubscribeLocalEvent<ArmorComponent, DamageModifyEvent>(OnDamageModify);
|
SubscribeLocalEvent<ArmorComponent, InventoryRelayedEvent<DamageModifyEvent>>(OnDamageModify);
|
||||||
SubscribeLocalEvent<ArmorComponent, GetVerbsEvent<ExamineVerb>>(OnArmorVerbExamine);
|
SubscribeLocalEvent<ArmorComponent, GetVerbsEvent<ExamineVerb>>(OnArmorVerbExamine);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDamageModify(EntityUid uid, ArmorComponent component, DamageModifyEvent args)
|
private void OnDamageModify(EntityUid uid, ArmorComponent component, InventoryRelayedEvent<DamageModifyEvent> args)
|
||||||
{
|
{
|
||||||
args.Damage = DamageSpecifier.ApplyModifierSet(args.Damage, component.Modifiers);
|
args.Args.Damage = DamageSpecifier.ApplyModifierSet(args.Args.Damage, component.Modifiers);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnArmorVerbExamine(EntityUid uid, ArmorComponent component, GetVerbsEvent<ExamineVerb> args)
|
private void OnArmorVerbExamine(EntityUid uid, ArmorComponent component, GetVerbsEvent<ExamineVerb> args)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using Content.Shared.Damage;
|
|||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
using Content.Shared.Explosion;
|
using Content.Shared.Explosion;
|
||||||
using Content.Shared.GameTicking;
|
using Content.Shared.GameTicking;
|
||||||
|
using Content.Shared.Inventory;
|
||||||
using Content.Shared.Throwing;
|
using Content.Shared.Throwing;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
@@ -63,6 +64,10 @@ public sealed partial class ExplosionSystem : EntitySystem
|
|||||||
SubscribeLocalEvent<GridRemovalEvent>(OnGridRemoved);
|
SubscribeLocalEvent<GridRemovalEvent>(OnGridRemoved);
|
||||||
SubscribeLocalEvent<GridStartupEvent>(OnGridStartup);
|
SubscribeLocalEvent<GridStartupEvent>(OnGridStartup);
|
||||||
SubscribeLocalEvent<ExplosionResistanceComponent, GetExplosionResistanceEvent>(OnGetResistance);
|
SubscribeLocalEvent<ExplosionResistanceComponent, GetExplosionResistanceEvent>(OnGetResistance);
|
||||||
|
|
||||||
|
// as long as explosion-resistance mice are never added, this should be fine (otherwise a mouse-hat will transfer it's power to the wearer).
|
||||||
|
SubscribeLocalEvent<ExplosionResistanceComponent, InventoryRelayedEvent<GetExplosionResistanceEvent>>((e, c, ev) => OnGetResistance(e, c, ev.Args));
|
||||||
|
|
||||||
SubscribeLocalEvent<TileChangedEvent>(OnTileChanged);
|
SubscribeLocalEvent<TileChangedEvent>(OnTileChanged);
|
||||||
|
|
||||||
SubscribeLocalEvent<RoundRestartCleanupEvent>(OnReset);
|
SubscribeLocalEvent<RoundRestartCleanupEvent>(OnReset);
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ namespace Content.Server.Inventory
|
|||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
SubscribeLocalEvent<InventoryComponent, ModifyChangedTemperatureEvent>(RelayInventoryEvent);
|
|
||||||
|
|
||||||
SubscribeLocalEvent<ClothingComponent, UseInHandEvent>(OnUseInHand);
|
SubscribeLocalEvent<ClothingComponent, UseInHandEvent>(OnUseInHand);
|
||||||
|
|
||||||
SubscribeNetworkEvent<OpenSlotStorageNetworkMessage>(OnOpenSlotStorage);
|
SubscribeNetworkEvent<OpenSlotStorageNetworkMessage>(OnOpenSlotStorage);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using Content.Shared.Alert;
|
|||||||
using Content.Shared.Damage;
|
using Content.Shared.Damage;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
using Content.Shared.Inventory;
|
using Content.Shared.Inventory;
|
||||||
|
using Content.Shared.Temperature;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
@@ -39,7 +40,7 @@ namespace Content.Server.Temperature.Systems
|
|||||||
SubscribeLocalEvent<TemperatureComponent, OnTemperatureChangeEvent>(EnqueueDamage);
|
SubscribeLocalEvent<TemperatureComponent, OnTemperatureChangeEvent>(EnqueueDamage);
|
||||||
SubscribeLocalEvent<TemperatureComponent, AtmosExposedUpdateEvent>(OnAtmosExposedUpdate);
|
SubscribeLocalEvent<TemperatureComponent, AtmosExposedUpdateEvent>(OnAtmosExposedUpdate);
|
||||||
SubscribeLocalEvent<AlertsComponent, OnTemperatureChangeEvent>(ServerAlert);
|
SubscribeLocalEvent<AlertsComponent, OnTemperatureChangeEvent>(ServerAlert);
|
||||||
SubscribeLocalEvent<TemperatureProtectionComponent, ModifyChangedTemperatureEvent>(OnTemperatureChangeAttempt);
|
SubscribeLocalEvent<TemperatureProtectionComponent, InventoryRelayedEvent<ModifyChangedTemperatureEvent>>(OnTemperatureChangeAttempt);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update(float frameTime)
|
public override void Update(float frameTime)
|
||||||
@@ -204,9 +205,9 @@ namespace Content.Server.Temperature.Systems
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnTemperatureChangeAttempt(EntityUid uid, TemperatureProtectionComponent component, ModifyChangedTemperatureEvent args)
|
private void OnTemperatureChangeAttempt(EntityUid uid, TemperatureProtectionComponent component, InventoryRelayedEvent<ModifyChangedTemperatureEvent> args)
|
||||||
{
|
{
|
||||||
args.TemperatureDelta *= component.Coefficient;
|
args.Args.TemperatureDelta *= component.Coefficient;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,16 +224,4 @@ namespace Content.Server.Temperature.Systems
|
|||||||
TemperatureDelta = delta;
|
TemperatureDelta = delta;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class ModifyChangedTemperatureEvent : EntityEventArgs, IInventoryRelayEvent
|
|
||||||
{
|
|
||||||
public SlotFlags TargetSlots { get; } = ~SlotFlags.POCKET;
|
|
||||||
|
|
||||||
public float TemperatureDelta;
|
|
||||||
|
|
||||||
public ModifyChangedTemperatureEvent(float temperature)
|
|
||||||
{
|
|
||||||
TemperatureDelta = temperature;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Shared.Examine;
|
using Content.Shared.Examine;
|
||||||
|
using Content.Shared.Inventory;
|
||||||
using Content.Shared.Movement.Systems;
|
using Content.Shared.Movement.Systems;
|
||||||
using Content.Shared.Verbs;
|
using Content.Shared.Verbs;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
@@ -19,7 +20,7 @@ public sealed class ClothingSpeedModifierSystem : EntitySystem
|
|||||||
|
|
||||||
SubscribeLocalEvent<ClothingSpeedModifierComponent, ComponentGetState>(OnGetState);
|
SubscribeLocalEvent<ClothingSpeedModifierComponent, ComponentGetState>(OnGetState);
|
||||||
SubscribeLocalEvent<ClothingSpeedModifierComponent, ComponentHandleState>(OnHandleState);
|
SubscribeLocalEvent<ClothingSpeedModifierComponent, ComponentHandleState>(OnHandleState);
|
||||||
SubscribeLocalEvent<ClothingSpeedModifierComponent, RefreshMovementSpeedModifiersEvent>(OnRefreshMoveSpeed);
|
SubscribeLocalEvent<ClothingSpeedModifierComponent, InventoryRelayedEvent<RefreshMovementSpeedModifiersEvent>>(OnRefreshMoveSpeed);
|
||||||
SubscribeLocalEvent<ClothingSpeedModifierComponent, GetVerbsEvent<ExamineVerb>>(OnClothingVerbExamine);
|
SubscribeLocalEvent<ClothingSpeedModifierComponent, GetVerbsEvent<ExamineVerb>>(OnClothingVerbExamine);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,12 +66,12 @@ public sealed class ClothingSpeedModifierSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnRefreshMoveSpeed(EntityUid uid, ClothingSpeedModifierComponent component, RefreshMovementSpeedModifiersEvent args)
|
private void OnRefreshMoveSpeed(EntityUid uid, ClothingSpeedModifierComponent component, InventoryRelayedEvent<RefreshMovementSpeedModifiersEvent> args)
|
||||||
{
|
{
|
||||||
if (!component.Enabled)
|
if (!component.Enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
args.ModifySpeed(component.WalkModifier, component.SprintModifier);
|
args.Args.ModifySpeed(component.WalkModifier, component.SprintModifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnClothingVerbExamine(EntityUid uid, ClothingSpeedModifierComponent component, GetVerbsEvent<ExamineVerb> args)
|
private void OnClothingVerbExamine(EntityUid uid, ClothingSpeedModifierComponent component, GetVerbsEvent<ExamineVerb> args)
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ public abstract class SharedMagbootsSystem : EntitySystem
|
|||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
SubscribeLocalEvent<MagbootsComponent, GetVerbsEvent<ActivationVerb>>(AddToggleVerb);
|
SubscribeLocalEvent<MagbootsComponent, GetVerbsEvent<ActivationVerb>>(AddToggleVerb);
|
||||||
SubscribeLocalEvent<MagbootsComponent, SlipAttemptEvent>(OnSlipAttempt);
|
SubscribeLocalEvent<MagbootsComponent, InventoryRelayedEvent<SlipAttemptEvent>>(OnSlipAttempt);
|
||||||
SubscribeLocalEvent<MagbootsComponent, GetItemActionsEvent>(OnGetActions);
|
SubscribeLocalEvent<MagbootsComponent, GetItemActionsEvent>(OnGetActions);
|
||||||
SubscribeLocalEvent<MagbootsComponent, ToggleActionEvent>(OnToggleAction);
|
SubscribeLocalEvent<MagbootsComponent, ToggleActionEvent>(OnToggleAction);
|
||||||
}
|
}
|
||||||
@@ -72,10 +72,10 @@ public abstract class SharedMagbootsSystem : EntitySystem
|
|||||||
args.Verbs.Add(verb);
|
args.Verbs.Add(verb);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSlipAttempt(EntityUid uid, MagbootsComponent component, SlipAttemptEvent args)
|
private void OnSlipAttempt(EntityUid uid, MagbootsComponent component, InventoryRelayedEvent<SlipAttemptEvent> args)
|
||||||
{
|
{
|
||||||
if (component.On)
|
if (component.On)
|
||||||
args.Cancel();
|
args.Args.Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnGetActions(EntityUid uid, MagbootsComponent component, GetItemActionsEvent args)
|
private void OnGetActions(EntityUid uid, MagbootsComponent component, GetItemActionsEvent args)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Content.Shared.Inventory;
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
namespace Content.Shared.Electrocution
|
namespace Content.Shared.Electrocution
|
||||||
@@ -9,6 +10,8 @@ namespace Content.Shared.Electrocution
|
|||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
SubscribeLocalEvent<InsulatedComponent, ElectrocutionAttemptEvent>(OnInsulatedElectrocutionAttempt);
|
SubscribeLocalEvent<InsulatedComponent, ElectrocutionAttemptEvent>(OnInsulatedElectrocutionAttempt);
|
||||||
|
// as long as legally distinct electric-mice are never added, this should be fine (otherwise a mouse-hat will transfer it's power to the wearer).
|
||||||
|
SubscribeLocalEvent<InsulatedComponent, InventoryRelayedEvent<ElectrocutionAttemptEvent>>((e, c, ev) => OnInsulatedElectrocutionAttempt(e, c, ev.Args));
|
||||||
SubscribeLocalEvent<InsulatedComponent, ComponentGetState>(OnInsulatedGetState);
|
SubscribeLocalEvent<InsulatedComponent, ComponentGetState>(OnInsulatedGetState);
|
||||||
SubscribeLocalEvent<InsulatedComponent, ComponentHandleState>(OnInsulatedHandleState);
|
SubscribeLocalEvent<InsulatedComponent, ComponentHandleState>(OnInsulatedHandleState);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Shared.IdentityManagement.Components;
|
using Content.Shared.IdentityManagement.Components;
|
||||||
|
using Content.Shared.Inventory;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
|
|
||||||
namespace Content.Shared.IdentityManagement;
|
namespace Content.Shared.IdentityManagement;
|
||||||
@@ -14,6 +15,7 @@ public abstract class SharedIdentitySystem : EntitySystem
|
|||||||
|
|
||||||
SubscribeLocalEvent<IdentityComponent, ComponentInit>(OnComponentInit);
|
SubscribeLocalEvent<IdentityComponent, ComponentInit>(OnComponentInit);
|
||||||
SubscribeLocalEvent<IdentityBlockerComponent, SeeIdentityAttemptEvent>(OnSeeIdentity);
|
SubscribeLocalEvent<IdentityBlockerComponent, SeeIdentityAttemptEvent>(OnSeeIdentity);
|
||||||
|
SubscribeLocalEvent<IdentityBlockerComponent, InventoryRelayedEvent<SeeIdentityAttemptEvent>>((e, c, ev) => OnSeeIdentity(e, c, ev.Args));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSeeIdentity(EntityUid uid, IdentityBlockerComponent component, SeeIdentityAttemptEvent args)
|
private void OnSeeIdentity(EntityUid uid, IdentityBlockerComponent component, SeeIdentityAttemptEvent args)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using Content.Shared.IdentityManagement.Components;
|
|||||||
using Content.Shared.Movement.Systems;
|
using Content.Shared.Movement.Systems;
|
||||||
using Content.Shared.Slippery;
|
using Content.Shared.Slippery;
|
||||||
using Content.Shared.Strip.Components;
|
using Content.Shared.Strip.Components;
|
||||||
|
using Content.Shared.Temperature;
|
||||||
|
|
||||||
namespace Content.Shared.Inventory;
|
namespace Content.Shared.Inventory;
|
||||||
|
|
||||||
@@ -19,19 +20,43 @@ public partial class InventorySystem
|
|||||||
SubscribeLocalEvent<InventoryComponent, GetExplosionResistanceEvent>(RelayInventoryEvent);
|
SubscribeLocalEvent<InventoryComponent, GetExplosionResistanceEvent>(RelayInventoryEvent);
|
||||||
SubscribeLocalEvent<InventoryComponent, BeforeStripEvent>(RelayInventoryEvent);
|
SubscribeLocalEvent<InventoryComponent, BeforeStripEvent>(RelayInventoryEvent);
|
||||||
SubscribeLocalEvent<InventoryComponent, SeeIdentityAttemptEvent>(RelayInventoryEvent);
|
SubscribeLocalEvent<InventoryComponent, SeeIdentityAttemptEvent>(RelayInventoryEvent);
|
||||||
|
SubscribeLocalEvent<InventoryComponent, ModifyChangedTemperatureEvent>(RelayInventoryEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void RelayInventoryEvent<T>(EntityUid uid, InventoryComponent component, T args) where T : EntityEventArgs, IInventoryRelayEvent
|
protected void RelayInventoryEvent<T>(EntityUid uid, InventoryComponent component, T args) where T : EntityEventArgs, IInventoryRelayEvent
|
||||||
{
|
{
|
||||||
|
if (args.TargetSlots == SlotFlags.NONE)
|
||||||
|
return;
|
||||||
|
|
||||||
var containerEnumerator = new ContainerSlotEnumerator(uid, component.TemplateId, _prototypeManager, this, args.TargetSlots);
|
var containerEnumerator = new ContainerSlotEnumerator(uid, component.TemplateId, _prototypeManager, this, args.TargetSlots);
|
||||||
|
var ev = new InventoryRelayedEvent<T>(args);
|
||||||
while (containerEnumerator.MoveNext(out var container))
|
while (containerEnumerator.MoveNext(out var container))
|
||||||
{
|
{
|
||||||
if (!container.ContainedEntity.HasValue) continue;
|
if (!container.ContainedEntity.HasValue) continue;
|
||||||
RaiseLocalEvent(container.ContainedEntity.Value, args, false);
|
RaiseLocalEvent(container.ContainedEntity.Value, ev, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event wrapper for relayed events.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This avoids nested inventory relays, and makes it easy to have certain events only handled by the initial
|
||||||
|
/// target entity. E.g. health based movement speed modifiers should not be handled by a hat, even if that hat
|
||||||
|
/// happens to be a dead mouse. Clothing that wishes to modify movement speed must subscribe to
|
||||||
|
/// InventoryRelayedEvent<RefreshMovementSpeedModifiersEvent>
|
||||||
|
/// </remarks>
|
||||||
|
public sealed class InventoryRelayedEvent<TEvent> : EntityEventArgs where TEvent : EntityEventArgs, IInventoryRelayEvent
|
||||||
|
{
|
||||||
|
public readonly TEvent Args;
|
||||||
|
|
||||||
|
public InventoryRelayedEvent(TEvent args)
|
||||||
|
{
|
||||||
|
Args = args;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Events that should be relayed to inventory slots should implement this interface.
|
/// Events that should be relayed to inventory slots should implement this interface.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ namespace Content.Shared.Slippery
|
|||||||
SubscribeLocalEvent<SlipperyComponent, StepTriggerAttemptEvent>(HandleAttemptCollide);
|
SubscribeLocalEvent<SlipperyComponent, StepTriggerAttemptEvent>(HandleAttemptCollide);
|
||||||
SubscribeLocalEvent<SlipperyComponent, StepTriggeredEvent>(HandleStepTrigger);
|
SubscribeLocalEvent<SlipperyComponent, StepTriggeredEvent>(HandleStepTrigger);
|
||||||
SubscribeLocalEvent<NoSlipComponent, SlipAttemptEvent>(OnNoSlipAttempt);
|
SubscribeLocalEvent<NoSlipComponent, SlipAttemptEvent>(OnNoSlipAttempt);
|
||||||
|
// as long as slip-resistant mice are never added, this should be fine (otherwise a mouse-hat will transfer it's power to the wearer).
|
||||||
|
SubscribeLocalEvent<NoSlipComponent, InventoryRelayedEvent<SlipAttemptEvent>>((e, c, ev) => OnNoSlipAttempt(e, c, ev.Args));
|
||||||
SubscribeLocalEvent<SlipperyComponent, ComponentGetState>(OnSlipperyGetState);
|
SubscribeLocalEvent<SlipperyComponent, ComponentGetState>(OnSlipperyGetState);
|
||||||
SubscribeLocalEvent<SlipperyComponent, ComponentHandleState>(OnSlipperyHandleState);
|
SubscribeLocalEvent<SlipperyComponent, ComponentHandleState>(OnSlipperyHandleState);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ public sealed class ThievingSystem : EntitySystem
|
|||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
SubscribeLocalEvent<ThievingComponent, BeforeStripEvent>(OnBeforeStrip);
|
SubscribeLocalEvent<ThievingComponent, BeforeStripEvent>(OnBeforeStrip);
|
||||||
|
SubscribeLocalEvent<ThievingComponent, InventoryRelayedEvent<BeforeStripEvent>>((e, c, ev) => OnBeforeStrip(e, c, ev.Args));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnBeforeStrip(EntityUid uid, ThievingComponent component, BeforeStripEvent args)
|
private void OnBeforeStrip(EntityUid uid, ThievingComponent component, BeforeStripEvent args)
|
||||||
|
|||||||
15
Content.Shared/Temperature/TemperatureEvents.cs
Normal file
15
Content.Shared/Temperature/TemperatureEvents.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using Content.Shared.Inventory;
|
||||||
|
|
||||||
|
namespace Content.Shared.Temperature;
|
||||||
|
|
||||||
|
public sealed class ModifyChangedTemperatureEvent : EntityEventArgs, IInventoryRelayEvent
|
||||||
|
{
|
||||||
|
public SlotFlags TargetSlots { get; } = ~SlotFlags.POCKET;
|
||||||
|
|
||||||
|
public float TemperatureDelta;
|
||||||
|
|
||||||
|
public ModifyChangedTemperatureEvent(float temperature)
|
||||||
|
{
|
||||||
|
TemperatureDelta = temperature;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user