/// <inheritdoc /> public void DispatchMessage(ChatChannel channel, string text, PlayerIndex?index = null, EntityUid?entityUid = null) { var msg = BuildChatMessage(channel, text, index, entityUid); _network.ServerSendToAll(msg); }
public async Task AirConsistencyTest() { // --- Setup await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings { NoClient = true, ExtraPrototypes = Prototypes }); var server = pairTracker.Pair.Server; await server.WaitIdleAsync(); var mapLoader = server.ResolveDependency <IMapLoader>(); var mapManager = server.ResolveDependency <IMapManager>(); var entityManager = server.ResolveDependency <IEntityManager>(); RespiratorSystem respSys = default; MetabolizerSystem metaSys = default; MapId mapId; EntityUid? grid = null; SharedBodyComponent body = default; EntityUid human = default; GridAtmosphereComponent relevantAtmos = default; float startingMoles = 0.0f; var testMapName = "Maps/Test/Breathing/3by3-20oxy-80nit.yml"; await server.WaitPost(() => { mapId = mapManager.CreateMap(); grid = mapLoader.LoadBlueprint(mapId, testMapName).gridId; }); Assert.NotNull(grid, $"Test blueprint {testMapName} not found."); float GetMapMoles() { var totalMapMoles = 0.0f; foreach (var tile in relevantAtmos.Tiles.Values) { totalMapMoles += tile.Air?.TotalMoles ?? 0.0f; } return(totalMapMoles); } await server.WaitAssertion(() => { var coords = new Vector2(0.5f, -1f); var coordinates = new EntityCoordinates(grid.Value, coords); human = entityManager.SpawnEntity("HumanBodyDummy", coordinates); respSys = EntitySystem.Get <RespiratorSystem>(); metaSys = EntitySystem.Get <MetabolizerSystem>(); relevantAtmos = entityManager.GetComponent <GridAtmosphereComponent>(grid.Value); startingMoles = GetMapMoles(); Assert.True(entityManager.TryGetComponent(human, out body)); Assert.True(entityManager.HasComponent <RespiratorComponent>(human)); }); // --- End setup var inhaleCycles = 100; for (var i = 0; i < inhaleCycles; i++) { await server.WaitAssertion(() => { // inhale respSys.Update(2.0f); Assert.That(GetMapMoles(), Is.LessThan(startingMoles)); // metabolize + exhale metaSys.Update(1.0f); metaSys.Update(1.0f); respSys.Update(2.0f); Assert.That(GetMapMoles(), Is.EqualTo(startingMoles).Within(0.0001)); }); } await pairTracker.CleanReturnAsync(); }
public GetInteractionVerbsEvent(EntityUid user, EntityUid target, EntityUid? @using, SharedHandsComponent?hands, bool canInteract, bool canAccess) : base(user, target, @using, hands, canInteract, canAccess) { }
protected abstract void PlaySound(EntityUid gun, string?sound, EntityUid?user = null);
protected abstract void CreateEffect(EffectSystemMessage message, EntityUid?user = null);
public PullableComponentState(EntityUid?puller) { Puller = puller; }
public void SetEntity(EntityUid uid) { EntityUid = uid; RoleEntity.Text = $"{uid}"; }
/// <summary> /// Raises a number of events in order to get all verbs of the given type(s) defined in local systems. This /// does not request verbs from the server. /// </summary> public SortedSet <Verb> GetLocalVerbs(EntityUid target, EntityUid user, List <Type> types, bool force = false) { SortedSet <Verb> verbs = new(); // accessibility checks bool canAccess = false; if (force || target == user) { canAccess = true; } else if (EntityManager.EntityExists(target) && _interactionSystem.InRangeUnobstructed(user, target)) { if (ContainerSystem.IsInSameOrParentContainer(user, target)) { canAccess = true; } else { // the item might be in a backpack that the user has open canAccess = _interactionSystem.CanAccessViaStorage(user, target); } } // A large number of verbs need to check action blockers. Instead of repeatedly having each system individually // call ActionBlocker checks, just cache it for the verb request. var canInteract = force || _actionBlockerSystem.CanInteract(user, target); EntityUid? @using = null; if (TryComp(user, out SharedHandsComponent? hands) && (force || _actionBlockerSystem.CanUseHeldEntity(user))) { @using = hands.ActiveHandEntity; // Check whether the "Held" entity is a virtual pull entity. If yes, set that as the entity being "Used". // This allows you to do things like buckle a dragged person onto a surgery table, without click-dragging // their sprite. if (TryComp(@using, out HandVirtualItemComponent? pull)) { @using = pull.BlockingEntity; } } if (types.Contains(typeof(InteractionVerb))) { var verbEvent = new GetVerbsEvent <InteractionVerb>(user, target, @using, hands, canInteract, canAccess); RaiseLocalEvent(target, verbEvent); verbs.UnionWith(verbEvent.Verbs); } if (types.Contains(typeof(UtilityVerb)) && @using != null && @using != target) { var verbEvent = new GetVerbsEvent <UtilityVerb>(user, target, @using, hands, canInteract, canAccess); RaiseLocalEvent(@using.Value, verbEvent); // directed at used, not at target verbs.UnionWith(verbEvent.Verbs); } if (types.Contains(typeof(AlternativeVerb))) { var verbEvent = new GetVerbsEvent <AlternativeVerb>(user, target, @using, hands, canInteract, canAccess); RaiseLocalEvent(target, verbEvent); verbs.UnionWith(verbEvent.Verbs); } if (types.Contains(typeof(ActivationVerb))) { var verbEvent = new GetVerbsEvent <ActivationVerb>(user, target, @using, hands, canInteract, canAccess); RaiseLocalEvent(target, verbEvent); verbs.UnionWith(verbEvent.Verbs); } if (types.Contains(typeof(ExamineVerb))) { var verbEvent = new GetVerbsEvent <ExamineVerb>(user, target, @using, hands, canInteract, canAccess); RaiseLocalEvent(target, verbEvent); verbs.UnionWith(verbEvent.Verbs); } // generic verbs if (types.Contains(typeof(Verb))) { var verbEvent = new GetVerbsEvent <Verb>(user, target, @using, hands, canInteract, canAccess); RaiseLocalEvent(target, verbEvent); verbs.UnionWith(verbEvent.Verbs); } return(verbs); }
IEntity IClientEntityManagerInternal.CreateEntity(string?prototypeName, EntityUid?uid) { return(base.CreateEntity(prototypeName, uid)); }
private void HandlePlayerAttached(PlayerAttachSysMessage message) { _attachedEntity = message.AttachedEntity; }
public bool CanHarvest(SeedData proto, EntityUid?held = null) { return(!proto.Ligneous || proto.Ligneous && held != null && HasComp <SharpComponent>(held)); }
public UplinkAccountData(EntityUid?dataAccountHolder, int dataBalance) { DataAccountHolder = dataAccountHolder; DataBalance = dataBalance; }
public void RequestRoundEnd(EntityUid?requester = null, bool checkCooldown = true) { RequestRoundEnd(DefaultCountdownDuration, requester, checkCooldown); }
private MsgChat BuildChatMessage(ChatChannel channel, string text, PlayerIndex?index, EntityUid?entityUid) { var message = _network.CreateNetMessage <MsgChat>(); message.Channel = channel; message.Text = text; message.Index = index; message.EntityId = entityUid; return(message); }
public override void DoAttack(EntityUid user, EntityCoordinates coordinates, bool wideAttack, EntityUid?target = null) { // TODO PREDICTION move server-side interaction logic into the shared system for interaction prediction. if (!ValidateInteractAndFace(user, coordinates)) { return; } if (!_actionBlockerSystem.CanAttack(user, target)) { return; } if (!wideAttack) { // Check if interacted entity is in the same container, the direct child, or direct parent of the user. if (target != null && !Deleted(target.Value) && !user.IsInSameOrParentContainer(target.Value) && !CanAccessViaStorage(user, target.Value)) { Logger.WarningS("system.interaction", $"User entity {ToPrettyString(user):user} clicked on object {ToPrettyString(target.Value):target} that isn't the parent, child, or in the same container"); return; } // TODO: Replace with body attack range when we get something like arm length or telekinesis or something. if (!user.InRangeUnobstructed(coordinates, ignoreInsideBlocker: true)) { return; } } // Verify user has a hand, and find what object they are currently holding in their active hand if (TryComp(user, out HandsComponent? hands)) { var item = hands.GetActiveHandItem?.Owner; if (item != null && !Deleted(item.Value)) { if (wideAttack) { var ev = new WideAttackEvent(item.Value, user, coordinates); RaiseLocalEvent(item.Value, ev, false); if (ev.Handled) { _adminLogSystem.Add(LogType.AttackArmedWide, LogImpact.Medium, $"{ToPrettyString(user):user} wide attacked with {ToPrettyString(item.Value):used} at {coordinates}"); return; } } else { var ev = new ClickAttackEvent(item.Value, user, coordinates, target); RaiseLocalEvent(item.Value, ev, false); if (ev.Handled) { if (target != null) { _adminLogSystem.Add(LogType.AttackArmedClick, LogImpact.Medium, $"{ToPrettyString(user):user} attacked {ToPrettyString(target.Value):target} with {ToPrettyString(item.Value):used} at {coordinates}"); } else { _adminLogSystem.Add(LogType.AttackArmedClick, LogImpact.Medium, $"{ToPrettyString(user):user} attacked with {ToPrettyString(item.Value):used} at {coordinates}"); } return; } } } else if (!wideAttack && target != null && HasComp <SharedItemComponent>(target.Value)) { // We pick up items if our hand is empty, even if we're in combat mode. InteractHand(user, target.Value); return; } } // TODO: Make this saner? // Attempt to do unarmed combat. We don't check for handled just because at this point it doesn't matter. if (wideAttack) { var ev = new WideAttackEvent(user, user, coordinates); RaiseLocalEvent(user, ev, false); if (ev.Handled) { _adminLogSystem.Add(LogType.AttackUnarmedWide, $"{ToPrettyString(user):user} wide attacked at {coordinates}"); } } else { var ev = new ClickAttackEvent(user, user, coordinates, target); RaiseLocalEvent(user, ev, false); if (ev.Handled) { if (target != null) { _adminLogSystem.Add(LogType.AttackUnarmedClick, LogImpact.Medium, $"{ToPrettyString(user):user} attacked {ToPrettyString(target.Value):target} at {coordinates}"); } else { _adminLogSystem.Add(LogType.AttackUnarmedClick, LogImpact.Medium, $"{ToPrettyString(user):user} attacked at {coordinates}"); } } } }
public WearableAnimatedSpriteComponentState(bool isCurrentlyWorn, bool isCurrentlyCarried, bool visible, DrawDepth drawDepth, string name, string currentAnimation, bool loop, EntityUid?masterUid) : base(visible, drawDepth, name, currentAnimation, loop, masterUid, NetIDs.WEARABLE_ANIMATED_SPRITE) { IsCurrentlyWorn = isCurrentlyWorn; IsCurrentlyCarried = isCurrentlyCarried; }
/// <summary> /// Constructs a new state snapshot of a TransformComponent. /// </summary> /// <param name="position">Current position offset of the entity.</param> /// <param name="rotation">Current direction offset of the entity.</param> /// <param name="parentID">Current parent transform of this entity.</param> public TransformComponentState(Vector2 localPosition, GridId gridId, MapId mapId, Angle rotation, EntityUid?parentID) : base(NetIDs.TRANSFORM) { LocalPosition = localPosition; GridID = gridId; MapID = mapId; Rotation = rotation; ParentID = parentID; }
public PilotComponentState(EntityUid?uid) { Console = uid; }
public StopPullingEvent(EntityUid?uid = null) { User = uid; }
public ElectrocutedEvent(EntityUid targetUid, EntityUid?sourceUid, float siemensCoefficient) { TargetUid = targetUid; SourceUid = sourceUid; SiemensCoefficient = siemensCoefficient; }
public abstract void Shoot( GunComponent gun, List <IShootable> ammo, EntityCoordinates fromCoordinates, EntityCoordinates toCoordinates, EntityUid?user = null);
public void Execute(IConsoleShell shell, string argStr, string[] args) { if (args.Length < 1) { shell.WriteError(Loc.GetString("shell-wrong-arguments-number")); return; } // Get player entity if (!IoCManager.Resolve <IPlayerManager>().TryGetSessionByUsername(args[0], out var session)) { shell.WriteLine(Loc.GetString("shell-target-player-does-not-exist")); return; } if (session.AttachedEntity is not { } user) { shell.WriteLine(Loc.GetString("Selected player doesn't controll any entity")); return; } // Get target item EntityUid?uplinkEntity = null; var entityManager = IoCManager.Resolve <IEntityManager>(); if (args.Length >= 2) { if (!int.TryParse(args[1], out var itemID)) { shell.WriteLine(Loc.GetString("shell-entity-uid-must-be-number")); return; } var eUid = new EntityUid(itemID); if (!eUid.IsValid() || !entityManager.EntityExists(eUid)) { shell.WriteLine(Loc.GetString("shell-invalid-entity-id")); return; } uplinkEntity = eUid; } // Get TC count var configManager = IoCManager.Resolve <IConfigurationManager>(); var tcCount = configManager.GetCVar(CCVars.TraitorStartingBalance); // Get account var uplinkAccount = new UplinkAccount(tcCount, user); var accounts = entityManager.EntitySysManager.GetEntitySystem <UplinkAccountsSystem>(); accounts.AddNewAccount(uplinkAccount); // Finally add uplink if (!entityManager.EntitySysManager.GetEntitySystem <UplinkSystem>() .AddUplink(user, uplinkAccount, uplinkEntity)) { shell.WriteLine(Loc.GetString("Failed to add uplink to the player")); return; } }
protected abstract void Popup(string message, EntityUid?uid, EntityUid?user);
/// <summary> /// Equips an ID card and PDA onto the given entity. /// </summary> /// <param name="entity">Entity to load out.</param> /// <param name="characterName">Character name to use for the ID.</param> /// <param name="jobPrototype">Job prototype to use for the PDA and ID.</param> /// <param name="station">The station this player is being spawned on.</param> public void EquipIdCard(EntityUid entity, string characterName, JobPrototype jobPrototype, EntityUid?station) { if (!_inventorySystem.TryGetSlotEntity(entity, "id", out var idUid)) { return; } if (!EntityManager.TryGetComponent(idUid, out PDAComponent? pdaComponent) || pdaComponent.ContainedID == null) { return; } var card = pdaComponent.ContainedID; var cardId = card.Owner; _cardSystem.TryChangeFullName(cardId, characterName, card); _cardSystem.TryChangeJobTitle(cardId, jobPrototype.Name, card); var extendedAccess = false; if (station != null) { var data = Comp <StationJobsComponent>(station.Value); extendedAccess = data.ExtendedAccess; } _accessSystem.SetAccessToJob(cardId, jobPrototype, extendedAccess); _pdaSystem.SetOwner(pdaComponent, characterName); }
public abstract void PickupAnimation(EntityUid item, EntityCoordinates initialPosition, Vector2 finalPosition, EntityUid?exclude);
public PlayerSpawningEvent(Job?job, HumanoidCharacterProfile?humanoidCharacterProfile, EntityUid?station) { Job = job; HumanoidCharacterProfile = humanoidCharacterProfile; Station = station; }
/// <summary> /// Raises a number of events in order to get all verbs of the given type(s) defined in local systems. This /// does not request verbs from the server. /// </summary> public virtual Dictionary <VerbType, SortedSet <Verb> > GetLocalVerbs(EntityUid target, EntityUid user, VerbType verbTypes, bool force = false) { Dictionary <VerbType, SortedSet <Verb> > verbs = new(); // accessibility checks bool canAccess = false; if (force || target == user) { canAccess = true; } else if (EntityManager.EntityExists(target) && _interactionSystem.InRangeUnobstructed(user, target, ignoreInsideBlocker: true)) { if (user.IsInSameOrParentContainer(target)) { canAccess = true; } else { // the item might be in a backpack that the user has open canAccess = _interactionSystem.CanAccessViaStorage(user, target); } } // A large number of verbs need to check action blockers. Instead of repeatedly having each system individually // call ActionBlocker checks, just cache it for the verb request. var canInteract = force || _actionBlockerSystem.CanInteract(user); EntityUid? @using = null; if (TryComp(user, out SharedHandsComponent? hands) && (force || _actionBlockerSystem.CanUse(user))) { hands.TryGetActiveHeldEntity(out @using); // Check whether the "Held" entity is a virtual pull entity. If yes, set that as the entity being "Used". // This allows you to do things like buckle a dragged person onto a surgery table, without click-dragging // their sprite. if (TryComp(@using, out HandVirtualItemComponent? pull)) { @using = pull.BlockingEntity; } } if ((verbTypes & VerbType.Interaction) == VerbType.Interaction) { GetInteractionVerbsEvent getVerbEvent = new(user, target, @using, hands, canInteract, canAccess); RaiseLocalEvent(target, getVerbEvent); verbs.Add(VerbType.Interaction, getVerbEvent.Verbs); } if ((verbTypes & VerbType.Activation) == VerbType.Activation) { GetActivationVerbsEvent getVerbEvent = new(user, target, @using, hands, canInteract, canAccess); RaiseLocalEvent(target, getVerbEvent); verbs.Add(VerbType.Activation, getVerbEvent.Verbs); } if ((verbTypes & VerbType.Alternative) == VerbType.Alternative) { GetAlternativeVerbsEvent getVerbEvent = new(user, target, @using, hands, canInteract, canAccess); RaiseLocalEvent(target, getVerbEvent); verbs.Add(VerbType.Alternative, getVerbEvent.Verbs); } if ((verbTypes & VerbType.Other) == VerbType.Other) { GetOtherVerbsEvent getVerbEvent = new(user, target, @using, hands, canInteract, canAccess); RaiseLocalEvent(target, getVerbEvent); verbs.Add(VerbType.Other, getVerbEvent.Verbs); } return(verbs); }
/// <summary> /// Will have two behaviors, either "uses" the used entity at range on the target entity if it is capable of accepting that action /// Or it will use the used entity itself on the position clicked, regardless of what was there /// </summary> public override async Task <bool> InteractUsingRanged(EntityUid user, EntityUid used, EntityUid?target, EntityCoordinates clickLocation, bool inRangeUnobstructed) { // TODO PREDICTION move server-side interaction logic into the shared system for interaction prediction. if (InteractDoBefore(user, used, inRangeUnobstructed ? target : null, clickLocation, false)) { return(true); } if (target != null) { var rangedMsg = new RangedInteractEvent(user, used, target.Value, clickLocation); RaiseLocalEvent(target.Value, rangedMsg); if (rangedMsg.Handled) { return(true); } var rangedInteractions = AllComps <IRangedInteract>(target.Value).ToList(); var rangedInteractionEventArgs = new RangedInteractEventArgs(user, used, clickLocation); // See if we have a ranged interaction foreach (var t in rangedInteractions) { // If an InteractUsingRanged returns a status completion we finish our interaction #pragma warning disable 618 if (t.RangedInteract(rangedInteractionEventArgs)) #pragma warning restore 618 { return(true); } } } return(await InteractDoAfter(user, used, inRangeUnobstructed?target : null, clickLocation, false)); }
public void PerformAction(EntityUid uid, EntityUid?userUid, IEntityManager entityManager) { if (!entityManager.TryGetComponent(uid, out ContainerManagerComponent? containerManager)) { Logger.Warning($"Machine frame entity {uid} did not have a container manager! Aborting build machine action."); return; } if (!entityManager.TryGetComponent(uid, out MachineFrameComponent? machineFrame)) { Logger.Warning($"Machine frame entity {uid} did not have a machine frame component! Aborting build machine action."); return; } if (!machineFrame.IsComplete) { Logger.Warning($"Machine frame entity {uid} doesn't have all required parts to be built! Aborting build machine action."); return; } if (!containerManager.TryGetContainer(MachineFrameComponent.BoardContainer, out var entBoardContainer)) { Logger.Warning($"Machine frame entity {uid} did not have the '{MachineFrameComponent.BoardContainer}' container! Aborting build machine action."); return; } if (!containerManager.TryGetContainer(MachineFrameComponent.PartContainer, out var entPartContainer)) { Logger.Warning($"Machine frame entity {uid} did not have the '{MachineFrameComponent.PartContainer}' container! Aborting build machine action."); return; } if (entBoardContainer.ContainedEntities.Count != 1) { Logger.Warning($"Machine frame entity {uid} did not have exactly one item in the '{MachineFrameComponent.BoardContainer}' container! Aborting build machine action."); } var board = entBoardContainer.ContainedEntities[0]; if (!board.TryGetComponent(out MachineBoardComponent? boardComponent)) { Logger.Warning($"Machine frame entity {uid} had an invalid entity in container \"{MachineFrameComponent.BoardContainer}\"! Aborting build machine action."); return; } entBoardContainer.Remove(board); var transform = entityManager.GetComponent <ITransformComponent>(uid); var machine = entityManager.SpawnEntity(boardComponent.Prototype, transform.Coordinates); machine.Transform.LocalRotation = transform.LocalRotation; var boardContainer = machine.EnsureContainer <Container>(MachineFrameComponent.BoardContainer, out var existed); if (existed) { // Clean that up... boardContainer.CleanContainer(); } var partContainer = machine.EnsureContainer <Container>(MachineFrameComponent.PartContainer, out existed); if (existed) { // Clean that up, too... partContainer.CleanContainer(); } boardContainer.Insert(board); // Now we insert all parts. foreach (var part in entPartContainer.ContainedEntities.ToArray()) { entPartContainer.ForceRemove(part); partContainer.Insert(part); } var constructionSystem = entityManager.EntitySysManager.GetEntitySystem <ConstructionSystem>(); if (machine.TryGetComponent(out ConstructionComponent? construction)) { // We only add these two container. If some construction needs to take other containers into account, fix this. constructionSystem.AddContainer(machine.Uid, MachineFrameComponent.BoardContainer, construction); constructionSystem.AddContainer(machine.Uid, MachineFrameComponent.PartContainer, construction); } if (machine.TryGetComponent(out MachineComponent? machineComp)) { machineComp.RefreshParts(); } entityManager.DeleteEntity(uid); }
/// <inheritdoc /> public void DispatchMessage(List <INetChannel> clients, ChatChannel channel, string text, PlayerIndex?index = null, EntityUid?entityUid = null) { var msg = BuildChatMessage(channel, text, index, entityUid); _network.ServerSendToMany(msg, clients); }