using Content.Shared.IdentityManagement; using Content.Shared.Interaction; using Content.Shared.Lathe; using Content.Shared.Popups; using Content.Shared.Research.Components; using Content.Shared.Research.Prototypes; using Content.Shared.Whitelist; using Robust.Shared.Containers; using Robust.Shared.Prototypes; using System.Linq; namespace Content.Shared.Research.Systems; public sealed class BlueprintSystem : EntitySystem { [Dependency] private readonly SharedContainerSystem _container = default!; [Dependency] private readonly EntityWhitelistSystem _entityWhitelist = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; /// public override void Initialize() { SubscribeLocalEvent(OnStartup); SubscribeLocalEvent(OnAfterInteract); SubscribeLocalEvent(OnGetRecipes); } private void OnStartup(Entity ent, ref ComponentStartup args) { _container.EnsureContainer(ent, ent.Comp.ContainerId); } private void OnAfterInteract(Entity ent, ref AfterInteractUsingEvent args) { if (args.Handled || !args.CanReach || !TryComp(args.Used, out var blueprintComponent)) return; args.Handled = TryInsertBlueprint(ent, (args.Used, blueprintComponent), args.User); } private void OnGetRecipes(Entity ent, ref LatheGetRecipesEvent args) { var recipes = GetBlueprintRecipes(ent); foreach (var recipe in recipes) { args.Recipes.Add(recipe); } } public bool TryInsertBlueprint(Entity ent, Entity blueprint, EntityUid? user) { if (!CanInsertBlueprint(ent, blueprint, user)) return false; if (user is not null) { var userId = Identity.Entity(user.Value, EntityManager); var bpId = Identity.Entity(blueprint, EntityManager); var machineId = Identity.Entity(ent, EntityManager); var msg = Loc.GetString("blueprint-receiver-popup-insert", ("user", userId), ("blueprint", bpId), ("receiver", machineId)); _popup.PopupPredicted(msg, ent, user); } _container.Insert(blueprint.Owner, _container.GetContainer(ent, ent.Comp.ContainerId)); var ev = new TechnologyDatabaseModifiedEvent(blueprint.Comp.ProvidedRecipes.Select(it => it.Id).ToList()); RaiseLocalEvent(ent, ref ev); return true; } public bool CanInsertBlueprint(Entity ent, Entity blueprint, EntityUid? user) { if (_entityWhitelist.IsWhitelistFail(ent.Comp.Whitelist, blueprint)) { return false; } if (blueprint.Comp.ProvidedRecipes.Count == 0) { Log.Error($"Attempted to insert blueprint {ToPrettyString(blueprint)} with no recipes."); return false; } // Don't add new blueprints if there are no new recipes. var currentRecipes = GetBlueprintRecipes(ent); if (currentRecipes.Count != 0 && currentRecipes.IsSupersetOf(blueprint.Comp.ProvidedRecipes)) { _popup.PopupPredicted(Loc.GetString("blueprint-receiver-popup-recipe-exists"), ent, user); return false; } return _container.CanInsert(blueprint, _container.GetContainer(ent, ent.Comp.ContainerId)); } public HashSet> GetBlueprintRecipes(Entity ent) { var contained = _container.GetContainer(ent, ent.Comp.ContainerId); var recipes = new HashSet>(); foreach (var blueprint in contained.ContainedEntities) { if (!TryComp(blueprint, out var blueprintComponent)) continue; foreach (var provided in blueprintComponent.ProvidedRecipes) { recipes.Add(provided); } } return recipes; } }