Пример #1
0
        private void SubtractContents(FoodRecipePrototype recipe)
        {
            foreach (var recipeReagent in recipe.IngredientsReagents)
            {
                _solution.TryRemoveReagent(recipeReagent.Key, ReagentUnit.New(recipeReagent.Value));
            }

            foreach (var recipeSolid in recipe.IngredientsSolids)
            {
                for (var i = 0; i < recipeSolid.Value; i++)
                {
                    foreach (var item in _storage.ContainedEntities)
                    {
                        if (item.Prototype.ID == recipeSolid.Key)
                        {
                            _storage.Remove(item);
                            item.Delete();
                            break;
                        }
                    }
                }
            }
        }
        async Task <bool> IInteractUsing.InteractUsing(InteractUsingEventArgs eventArgs)
        {
            if (string.IsNullOrEmpty(_slice))
            {
                return(false);
            }
            if (!Owner.TryGetComponent(out SolutionContainerComponent? solution))
            {
                return(false);
            }
            if (!eventArgs.Using.TryGetComponent(out UtensilComponent? utensil) || !utensil.HasType(UtensilType.Knife))
            {
                return(false);
            }

            var itemToSpawn = Owner.EntityManager.SpawnEntity(_slice, Owner.Transform.Coordinates);

            if (eventArgs.User.TryGetComponent(out HandsComponent? handsComponent))
            {
                if (ContainerHelpers.IsInContainer(Owner))
                {
                    handsComponent.PutInHandOrDrop(itemToSpawn.GetComponent <ItemComponent>());
                }
            }

            EntitySystem.Get <AudioSystem>().PlayAtCoords(_sound, Owner.Transform.Coordinates,
                                                          AudioParams.Default.WithVolume(-2));

            Count--;
            if (Count < 1)
            {
                Owner.Delete();
                return(true);
            }
            solution.TryRemoveReagent("chem.Nutriment", solution.CurrentVolume / ReagentUnit.New(Count + 1));
            return(true);
        }
Пример #3
0
        public async Task SpaceNoPuddleTest()
        {
            var server = StartServerDummyTicker();

            await server.WaitIdleAsync();

            var      mapManager   = server.ResolveDependency <IMapManager>();
            var      pauseManager = server.ResolveDependency <IPauseManager>();
            IMapGrid grid         = null;

            // Build up test environment
            server.Post(() =>
            {
                var mapId = mapManager.CreateMap();

                pauseManager.AddUninitializedMap(mapId);

                var gridId = new GridId(1);

                if (!mapManager.TryGetGrid(gridId, out grid))
                {
                    grid = mapManager.CreateGrid(mapId, gridId);
                }
            });

            await server.WaitIdleAsync();

            server.Assert(() =>
            {
                var coordinates = grid.ToCoordinates();
                var solution    = new Solution("water", ReagentUnit.New(20));
                var puddle      = solution.SpillAt(coordinates, "PuddleSmear");
                Assert.Null(puddle);
            });

            await server.WaitIdleAsync();
        }
        /// <summary>
        /// Gets component data to be used to update the user interface client-side.
        /// </summary>
        /// <returns>Returns a <see cref="SharedReagentDispenserComponent.ReagentDispenserBoundUserInterfaceState"/></returns>
        private ReagentDispenserBoundUserInterfaceState GetUserInterfaceState()
        {
            var beaker = _beakerContainer.ContainedEntity;

            if (beaker == null)
            {
                return(new ReagentDispenserBoundUserInterfaceState(false, ReagentUnit.New(0), ReagentUnit.New(0),
                                                                   "", Inventory, Owner.Name, null, _dispenseAmount));
            }

            var solution = beaker.GetComponent <SolutionComponent>();

            return(new ReagentDispenserBoundUserInterfaceState(true, solution.CurrentVolume, solution.MaxVolume,
                                                               beaker.Name, Inventory, Owner.Name, solution.ReagentList.ToList(), _dispenseAmount));
        }
        public void ReagentUnitStringTests(string value, string expected)
        {
            var result = ReagentUnit.New(value);

            Assert.AreEqual(expected, $"{result}");
        }
Пример #6
0
 void IExposeData.ExposeData(ObjectSerializer serializer)
 {
     serializer.DataField(ref _metabolismRate, "rate", ReagentUnit.New(1));
     serializer.DataField(ref _hydrationFactor, "nutrimentFactor", 30.0f);
 }
 public void SetTransferAmount(ReagentUnit amount)
 {
     amount = ReagentUnit.New(Math.Clamp(amount.Int(), MinimumTransferAmount.Int(),
                                         MaximumTransferAmount.Int()));
     TransferAmount = amount;
 }
Пример #8
0
 public override void ExposeData(ObjectSerializer serializer)
 {
     base.ExposeData(serializer);
     serializer.DataField(ref _transferAmount, "transferAmount", ReagentUnit.New(0.5));
 }
 private void OnInit(EntityUid uid, PuddleComponent component, ComponentInit args)
 {
     var solution =  _solutionContainerSystem.EnsureSolution(uid, component.SolutionName);
     solution.MaxVolume = ReagentUnit.New(1000);
 }
 ReagentUnit IMetabolizable.Metabolize(IEntity solutionEntity, string reagentId, float tickTime)
 {
     return(ReagentUnit.New(MetabolismRate * tickTime));
 }
        private void TryCreatePackage(IEntity user, UiAction action, int pillAmount, int bottleAmount)
        {
            var random = IoCManager.Resolve <IRobustRandom>();

            if (action == UiAction.CreateBottles)
            {
                var individualVolume = BufferSolution.CurrentVolume / ReagentUnit.New(bottleAmount);
                var actualVolume     = ReagentUnit.Min(individualVolume, ReagentUnit.New(30));
                for (int i = 0; i < bottleAmount; i++)
                {
                    var bottle = Owner.EntityManager.SpawnEntity("bottle", Owner.Transform.GridPosition);

                    var bufferSolution = BufferSolution.Solution.SplitSolution(actualVolume);

                    bottle.TryGetComponent <SolutionComponent>(out var bottleSolution);
                    bottleSolution?.Solution.AddSolution(bufferSolution);

                    //Try to give them the bottle
                    if (user.TryGetComponent <HandsComponent>(out var hands) &&
                        bottle.TryGetComponent <ItemComponent>(out var item))
                    {
                        if (hands.CanPutInHand(item))
                        {
                            hands.PutInHand(item);
                            continue;
                        }
                    }

                    //Put it on the floor
                    bottle.Transform.GridPosition = user.Transform.GridPosition;
                    //Give it an offset
                    var x_negative = random.Prob(0.5f) ? -1 : 1;
                    var y_negative = random.Prob(0.5f) ? -1 : 1;
                    bottle.Transform.LocalPosition += new Vector2(random.NextFloat() * 0.2f * x_negative, random.NextFloat() * 0.2f * y_negative);
                }
            }
            else //Pills
            {
                var individualVolume = BufferSolution.CurrentVolume / ReagentUnit.New(pillAmount);
                var actualVolume     = ReagentUnit.Min(individualVolume, ReagentUnit.New(50));
                for (int i = 0; i < pillAmount; i++)
                {
                    var pill = Owner.EntityManager.SpawnEntity("pill", Owner.Transform.GridPosition);

                    var bufferSolution = BufferSolution.Solution.SplitSolution(actualVolume);

                    pill.TryGetComponent <SolutionComponent>(out var pillSolution);
                    pillSolution?.Solution.AddSolution(bufferSolution);

                    //Try to give them the bottle
                    if (user.TryGetComponent <HandsComponent>(out var hands) &&
                        pill.TryGetComponent <ItemComponent>(out var item))
                    {
                        if (hands.CanPutInHand(item))
                        {
                            hands.PutInHand(item);
                            continue;
                        }
                    }

                    //Put it on the floor
                    pill.Transform.GridPosition = user.Transform.GridPosition;
                    //Give it an offset
                    var x_negative = random.Prob(0.5f) ? -1 : 1;
                    var y_negative = random.Prob(0.5f) ? -1 : 1;
                    pill.Transform.LocalPosition += new Vector2(random.NextFloat() * 0.2f * x_negative, random.NextFloat() * 0.2f * y_negative);
                }
            }

            UpdateUserInterface();
        }
        /// <summary>
        /// Gets component data to be used to update the user interface client-side.
        /// </summary>
        /// <returns>Returns a <see cref="SharedChemMasterComponent.ChemMasterBoundUserInterfaceState"/></returns>
        private ChemMasterBoundUserInterfaceState GetUserInterfaceState()
        {
            var beaker = _beakerContainer.ContainedEntity;

            if (beaker == null)
            {
                return(new ChemMasterBoundUserInterfaceState(false, ReagentUnit.New(0), ReagentUnit.New(0),
                                                             "", Owner.Name, null, BufferSolution.ReagentList.ToList(), BufferModeTransfer, BufferSolution.CurrentVolume, BufferSolution.MaxVolume));
            }

            var solution = beaker.GetComponent <SolutionComponent>();

            return(new ChemMasterBoundUserInterfaceState(true, solution.CurrentVolume, solution.MaxVolume,
                                                         beaker.Name, Owner.Name, solution.ReagentList.ToList(), BufferSolution.ReagentList.ToList(), BufferModeTransfer, BufferSolution.CurrentVolume, BufferSolution.MaxVolume));
        }
 public void ExposeData(ObjectSerializer serializer)
 {
     serializer.DataField(ref _amount, "amount", ReagentUnit.New(1));
     serializer.DataField(ref _catalyst, "catalyst", false);
 }
Пример #14
0
        public async Task <bool> InteractUsing(InteractUsingEventArgs eventArgs)
        {
            var user      = eventArgs.User;
            var usingItem = eventArgs.Using;

            if (usingItem == null || usingItem.Deleted || !ActionBlockerSystem.CanInteract(user))
            {
                return(false);
            }

            if (usingItem.TryGetComponent(out SeedComponent? seeds))
            {
                if (Seed == null)
                {
                    if (seeds.Seed == null)
                    {
                        user.PopupMessageCursor(Loc.GetString("The packet seems to be empty. You throw it away."));
                        usingItem.Delete();
                        return(false);
                    }

                    user.PopupMessageCursor(Loc.GetString("You plant the {0} {1}.", seeds.Seed.SeedName, seeds.Seed.SeedNoun));

                    Seed       = seeds.Seed;
                    Dead       = false;
                    Age        = 1;
                    Health     = Seed.Endurance;
                    _lastCycle = _gameTiming.CurTime;

                    usingItem.Delete();

                    CheckLevelSanity();
                    UpdateSprite();

                    return(true);
                }

                user.PopupMessageCursor(Loc.GetString("The {0} already has seeds in it!", Owner.Name));
                return(false);
            }

            if (usingItem.HasComponent <HoeComponent>())
            {
                if (WeedLevel > 0)
                {
                    user.PopupMessageCursor(Loc.GetString("You remove the weeds from the {0}.", Owner.Name));
                    user.PopupMessageOtherClients(Loc.GetString("{0} starts uprooting the weeds.", user.Name));
                    WeedLevel = 0;
                    UpdateSprite();
                }
                else
                {
                    user.PopupMessageCursor(Loc.GetString("This plot is devoid of weeds! It doesn't need uprooting."));
                }

                return(true);
            }

            if (usingItem.TryGetComponent(out SolutionContainerComponent? solution) && solution.CanRemoveSolutions)
            {
                var amount  = 5f;
                var sprayed = false;

                if (usingItem.TryGetComponent(out SprayComponent? spray))
                {
                    sprayed = true;
                    amount  = 1f;
                    EntitySystem.Get <AudioSystem>().PlayFromEntity(spray.SpraySound, usingItem, AudioHelpers.WithVariation(0.125f));
                }

                var chemAmount = ReagentUnit.New(amount);

                var split = solution.Solution.SplitSolution(chemAmount <= solution.Solution.TotalVolume ? chemAmount : solution.Solution.TotalVolume);

                user.PopupMessageCursor(Loc.GetString(sprayed ? $"You spray {Owner.Name} with {usingItem.Name}." : $"You transfer {split.TotalVolume.ToString()}u to {Owner.Name}"));

                _solutionContainer?.TryAddSolution(split);

                SkipAging++; // We're forcing an update cycle, so one age hasn't passed.
                ForceUpdate = true;
                Update();

                return(true);
            }

            if (usingItem.HasComponent <PlantSampleTakerComponent>())
            {
                if (Seed == null)
                {
                    user.PopupMessageCursor(Loc.GetString("There is nothing to take a sample of!"));
                    return(false);
                }

                if (Sampled)
                {
                    user.PopupMessageCursor(Loc.GetString("This plant has already been sampled."));
                    return(false);
                }

                if (Dead)
                {
                    user.PopupMessageCursor(Loc.GetString("This plant is dead."));
                    return(false);
                }

                var seed = Seed.SpawnSeedPacket(user.Transform.Coordinates);
                seed.RandomOffset(0.25f);
                user.PopupMessageCursor(Loc.GetString($"You take a sample from the {Seed.DisplayName}."));
                Health -= (_random.Next(3, 5) * 10);

                if (_random.Prob(0.3f))
                {
                    Sampled = true;
                }

                // Just in case.
                CheckLevelSanity();
                SkipAging++; // We're forcing an update cycle, so one age hasn't passed.
                ForceUpdate = true;
                Update();

                return(true);
            }

            if (usingItem.HasComponent <BotanySharpComponent>())
            {
                return(DoHarvest(user));
            }

            return(false);
        }
        /// <summary>
        /// Update the container, buffer, and packaging panels.
        /// </summary>
        /// <param name="state">State data for the dispenser.</param>
        private void UpdatePanelInfo(ChemMasterBoundUserInterfaceState state)
        {
            var bufferModeTransfer = state.BufferModeTransfer;

            BufferTransferButton.Pressed = bufferModeTransfer;
            BufferDiscardButton.Pressed  = !bufferModeTransfer;

            ContainerInfo.Children.Clear();

            if (!state.HasBeaker)
            {
                ContainerInfo.Children.Add(new Label {
                    Text = Loc.GetString("chem-master-window-no-container-loaded-text")
                });
                return;
            }

            ContainerInfo.Children.Add(new BoxContainer // Name of the container and its fill status (Ex: 44/100u)
            {
                Orientation = LayoutOrientation.Horizontal,
                Children    =
                {
                    new Label {
                        Text = $"{state.ContainerName}: "
                    },
                    new Label
                    {
                        Text         = $"{state.BeakerCurrentVolume}/{state.BeakerMaxVolume}",
                        StyleClasses ={ StyleNano.StyleClassLabelSecondaryColor          }
                    }
                }
            });

            foreach (var reagent in state.ContainerReagents)
            {
                var name = Loc.GetString("chem-master-window-unknown-reagent-text");
                //Try to the prototype for the given reagent. This gives us it's name.
                if (_prototypeManager.TryIndex(reagent.ReagentId, out ReagentPrototype? proto))
                {
                    name = proto.Name;
                }

                if (proto != null)
                {
                    ContainerInfo.Children.Add(new BoxContainer
                    {
                        Orientation = LayoutOrientation.Horizontal,
                        Children    =
                        {
                            new Label   {
                                Text = $"{name}: "
                            },
                            new Label
                            {
                                Text         = $"{reagent.Quantity}u",
                                StyleClasses ={ StyleNano.StyleClassLabelSecondaryColor          }
                            },

                            //Padding
                            new Control {
                                HorizontalExpand = true
                            },

                            MakeChemButton("1", ReagentUnit.New(1), reagent.ReagentId, false, StyleBase.ButtonOpenRight),
                            MakeChemButton("5", ReagentUnit.New(5), reagent.ReagentId, false, StyleBase.ButtonOpenBoth),
                            MakeChemButton("10", ReagentUnit.New(10), reagent.ReagentId, false, StyleBase.ButtonOpenBoth),
                            MakeChemButton("25", ReagentUnit.New(25), reagent.ReagentId, false, StyleBase.ButtonOpenBoth),
                            MakeChemButton(Loc.GetString("chem-master-window-buffer-all-amount"), ReagentUnit.New(-1), reagent.ReagentId, false, StyleBase.ButtonOpenLeft),
                        }
                    });
                }
            }

            BufferInfo.Children.Clear();

            if (!state.BufferReagents.Any())
            {
                BufferInfo.Children.Add(new Label {
                    Text = Loc.GetString("chem-master-window-buffer-empty-text")
                });
                return;
            }

            var bufferHBox = new BoxContainer
            {
                Orientation = LayoutOrientation.Horizontal
            };

            BufferInfo.AddChild(bufferHBox);

            var bufferLabel = new Label {
                Text = $"{Loc.GetString("chem-master-window-buffer-label")} "
            };

            bufferHBox.AddChild(bufferLabel);
            var bufferVol = new Label
            {
                Text         = $"{state.BufferCurrentVolume}",
                StyleClasses = { StyleNano.StyleClassLabelSecondaryColor }
            };

            bufferHBox.AddChild(bufferVol);

            foreach (var reagent in state.BufferReagents)
            {
                var name = Loc.GetString("chem-master-window-unknown-reagent-text");
                //Try to the prototype for the given reagent. This gives us it's name.
                if (_prototypeManager.TryIndex(reagent.ReagentId, out ReagentPrototype? proto))
                {
                    name = proto.Name;
                }

                if (proto != null)
                {
                    BufferInfo.Children.Add(new BoxContainer
                    {
                        Orientation = LayoutOrientation.Horizontal,
                        //SizeFlagsHorizontal = SizeFlags.ShrinkEnd,
                        Children =
                        {
                            new Label   {
                                Text = $"{name}: "
                            },
                            new Label
                            {
                                Text         = $"{reagent.Quantity}u",
                                StyleClasses ={ StyleNano.StyleClassLabelSecondaryColor          }
                            },

                            //Padding
                            new Control {
                                HorizontalExpand = true
                            },

                            MakeChemButton("1", ReagentUnit.New(1), reagent.ReagentId, true, StyleBase.ButtonOpenRight),
                            MakeChemButton("5", ReagentUnit.New(5), reagent.ReagentId, true, StyleBase.ButtonOpenBoth),
                            MakeChemButton("10", ReagentUnit.New(10), reagent.ReagentId, true, StyleBase.ButtonOpenBoth),
                            MakeChemButton("25", ReagentUnit.New(25), reagent.ReagentId, true, StyleBase.ButtonOpenBoth),
                            MakeChemButton(Loc.GetString("chem-master-window-buffer-all-amount"), ReagentUnit.New(-1), reagent.ReagentId, true, StyleBase.ButtonOpenLeft),
                        }
                    });
                }
            }
        }
        public void ReagentUnitStringTests(string value, string expected)
        {
            var result = ReagentUnit.New(value);

            Assert.That($"{result}", Is.EqualTo(expected));
        }
Пример #17
0
        async Task <bool> IInteractUsing.InteractUsing(InteractUsingEventArgs eventArgs)
        {
            var user      = eventArgs.User;
            var usingItem = eventArgs.Using;

            if (usingItem == null || usingItem.Deleted || !EntitySystem.Get <ActionBlockerSystem>().CanInteract(user))
            {
                return(false);
            }

            if (usingItem.TryGetComponent(out SeedComponent? seeds))
            {
                if (Seed == null)
                {
                    if (seeds.Seed == null)
                    {
                        user.PopupMessageCursor(Loc.GetString("plant-holder-component-empty-seed-packet-message"));
                        usingItem.QueueDelete();
                        return(false);
                    }

                    user.PopupMessageCursor(Loc.GetString("plant-holder-component-plant-success-message",
                                                          ("seedName", seeds.Seed.SeedName),
                                                          ("seedNoun", seeds.Seed.SeedNoun)));

                    Seed       = seeds.Seed;
                    Dead       = false;
                    Age        = 1;
                    Health     = Seed.Endurance;
                    _lastCycle = _gameTiming.CurTime;

                    usingItem.QueueDelete();

                    CheckLevelSanity();
                    UpdateSprite();

                    return(true);
                }

                user.PopupMessageCursor(Loc.GetString("plant-holder-component-already-seeded-message", ("name", Owner.Name)));
                return(false);
            }

            if (usingItem.HasTag("Hoe"))
            {
                if (WeedLevel > 0)
                {
                    user.PopupMessageCursor(Loc.GetString("plant-holder-component-remove-weeds-message", ("name", Owner.Name)));
                    user.PopupMessageOtherClients(Loc.GetString("plant-holder-component-remove-weeds-others-message", ("otherName", user.Name)));
                    WeedLevel = 0;
                    UpdateSprite();
                }
                else
                {
                    user.PopupMessageCursor(Loc.GetString("plant-holder-component-no-weeds-message"));
                }

                return(true);
            }

            if (usingItem.HasTag("Shovel"))
            {
                if (Seed != null)
                {
                    user.PopupMessageCursor(Loc.GetString("plant-holder-component-remove-plant-message", ("name", Owner.Name)));
                    user.PopupMessageOtherClients(Loc.GetString("plant-holder-component-remove-plant-others-message", ("name", user.Name)));
                    RemovePlant();
                }
                else
                {
                    user.PopupMessageCursor(Loc.GetString("plant-holder-component-no-plant-message"));
                }

                return(true);
            }

            if (usingItem.TryGetComponent(out ISolutionInteractionsComponent? solution) && solution.CanDrain)
            {
                var amount  = ReagentUnit.New(5);
                var sprayed = false;

                if (usingItem.TryGetComponent(out SprayComponent? spray))
                {
                    sprayed = true;
                    amount  = ReagentUnit.New(1);

                    if (!string.IsNullOrEmpty(spray.SpraySound))
                    {
                        SoundSystem.Play(Filter.Pvs(usingItem), spray.SpraySound, usingItem, AudioHelpers.WithVariation(0.125f));
                    }
                }

                var split = solution.Drain(amount);
                if (split.TotalVolume == 0)
                {
                    user.PopupMessageCursor(Loc.GetString("plant-holder-component-empty-message", ("owner", usingItem)));
                    return(true);
                }

                user.PopupMessageCursor(Loc.GetString(sprayed ? "plant-holder-component-spray-message" : "plant-holder-component-transfer-message",
                                                      ("owner", Owner),
                                                      ("amount", split.TotalVolume)));

                _solutionContainer?.TryAddSolution(split);

                ForceUpdateByExternalCause();

                return(true);
            }

            if (usingItem.HasTag("PlantSampleTaker"))
            {
                if (Seed == null)
                {
                    user.PopupMessageCursor(Loc.GetString("plant-holder-component-nothing-to-sample-message"));
                    return(false);
                }

                if (Sampled)
                {
                    user.PopupMessageCursor(Loc.GetString("plant-holder-component-already-sampled-message"));
                    return(false);
                }

                if (Dead)
                {
                    user.PopupMessageCursor(Loc.GetString("plant-holder-component-dead-plant-message"));
                    return(false);
                }

                var seed = Seed.SpawnSeedPacket(user.Transform.Coordinates);
                seed.RandomOffset(0.25f);
                user.PopupMessageCursor(Loc.GetString("plant-holder-component-take-sample-message", ("seedName", Seed.DisplayName)));
                Health -= (_random.Next(3, 5) * 10);

                if (_random.Prob(0.3f))
                {
                    Sampled = true;
                }

                // Just in case.
                CheckLevelSanity();
                ForceUpdateByExternalCause();

                return(true);
            }

            if (usingItem.HasTag("BotanySharp"))
            {
                return(DoHarvest(user));
            }

            if (usingItem.HasComponent <ProduceComponent>())
            {
                user.PopupMessageCursor(Loc.GetString("plant-holder-component-compost-message",
                                                      ("owner", Owner),
                                                      ("usingItem", usingItem)));
                user.PopupMessageOtherClients(Loc.GetString("plant-holder-component-compost-others-message",
                                                            ("user", user),
                                                            ("usingItem", usingItem),
                                                            ("owner", Owner)));

                if (usingItem.TryGetComponent(out SolutionContainerComponent? solution2))
                {
                    // This deliberately discards overfill.
                    _solutionContainer?.TryAddSolution(solution2.SplitSolution(solution2.Solution.TotalVolume));

                    ForceUpdateByExternalCause();
                }

                usingItem.QueueDelete();

                return(true);
            }

            return(false);
        }
Пример #18
0
        async Task <bool> IInteractUsing.InteractUsing(InteractUsingEventArgs eventArgs)
        {
            var user      = eventArgs.User;
            var usingItem = eventArgs.Using;

            if (usingItem == null || usingItem.Deleted || !ActionBlockerSystem.CanInteract(user))
            {
                return(false);
            }

            if (usingItem.TryGetComponent(out SeedComponent? seeds))
            {
                if (Seed == null)
                {
                    if (seeds.Seed == null)
                    {
                        user.PopupMessageCursor(Loc.GetString("The packet seems to be empty. You throw it away."));
                        usingItem.Delete();
                        return(false);
                    }

                    user.PopupMessageCursor(Loc.GetString("You plant the {0} {1}.", seeds.Seed.SeedName, seeds.Seed.SeedNoun));

                    Seed       = seeds.Seed;
                    Dead       = false;
                    Age        = 1;
                    Health     = Seed.Endurance;
                    _lastCycle = _gameTiming.CurTime;

                    usingItem.Delete();

                    CheckLevelSanity();
                    UpdateSprite();

                    return(true);
                }

                user.PopupMessageCursor(Loc.GetString("The {0} already has seeds in it!", Owner.Name));
                return(false);
            }

            if (usingItem.HasTag("Hoe"))
            {
                if (WeedLevel > 0)
                {
                    user.PopupMessageCursor(Loc.GetString("You remove the weeds from the {0}.", Owner.Name));
                    user.PopupMessageOtherClients(Loc.GetString("{0} starts uprooting the weeds.", user.Name));
                    WeedLevel = 0;
                    UpdateSprite();
                }
                else
                {
                    user.PopupMessageCursor(Loc.GetString("This plot is devoid of weeds! It doesn't need uprooting."));
                }

                return(true);
            }

            if (usingItem.HasTag("Shovel"))
            {
                if (Seed != null)
                {
                    user.PopupMessageCursor(Loc.GetString("You remove the plant from the {0}.", Owner.Name));
                    user.PopupMessageOtherClients(Loc.GetString("{0} removes the plant.", user.Name));
                    RemovePlant();
                }
                else
                {
                    user.PopupMessageCursor(Loc.GetString("There is no plant to remove."));
                }

                return(true);
            }

            if (usingItem.TryGetComponent(out ISolutionInteractionsComponent? solution) && solution.CanDrain)
            {
                var amount  = ReagentUnit.New(5);
                var sprayed = false;

                if (usingItem.TryGetComponent(out SprayComponent? spray))
                {
                    sprayed = true;
                    amount  = ReagentUnit.New(1);

                    if (!string.IsNullOrEmpty(spray.SpraySound))
                    {
                        SoundSystem.Play(Filter.Pvs(usingItem), spray.SpraySound, usingItem, AudioHelpers.WithVariation(0.125f));
                    }
                }

                var split = solution.Drain(amount);
                if (split.TotalVolume == 0)
                {
                    user.PopupMessageCursor(Loc.GetString("{0:TheName} is empty!", usingItem));
                    return(true);
                }

                user.PopupMessageCursor(Loc.GetString(
                                            sprayed ? "You spray {0:TheName}" : "You transfer {1}u to {0:TheName}",
                                            Owner, split.TotalVolume));

                _solutionContainer?.TryAddSolution(split);

                ForceUpdateByExternalCause();

                return(true);
            }

            if (usingItem.HasTag("PlantSampleTaker"))
            {
                if (Seed == null)
                {
                    user.PopupMessageCursor(Loc.GetString("There is nothing to take a sample of!"));
                    return(false);
                }

                if (Sampled)
                {
                    user.PopupMessageCursor(Loc.GetString("This plant has already been sampled."));
                    return(false);
                }

                if (Dead)
                {
                    user.PopupMessageCursor(Loc.GetString("This plant is dead."));
                    return(false);
                }

                var seed = Seed.SpawnSeedPacket(user.Transform.Coordinates);
                seed.RandomOffset(0.25f);
                user.PopupMessageCursor(Loc.GetString($"You take a sample from the {Seed.DisplayName}."));
                Health -= (_random.Next(3, 5) * 10);

                if (_random.Prob(0.3f))
                {
                    Sampled = true;
                }

                // Just in case.
                CheckLevelSanity();
                ForceUpdateByExternalCause();

                return(true);
            }

            if (usingItem.HasTag("BotanySharp"))
            {
                return(DoHarvest(user));
            }

            if (usingItem.HasComponent <ProduceComponent>())
            {
                user.PopupMessageCursor(Loc.GetString("You compost {1:theName} into {0:theName}.", Owner, usingItem));
                user.PopupMessageOtherClients(Loc.GetString("{0:TheName} composts {1:theName} into {2:theName}.", user, usingItem, Owner));

                if (usingItem.TryGetComponent(out SolutionContainerComponent? solution2))
                {
                    // This deliberately discards overfill.
                    _solutionContainer?.TryAddSolution(solution2.SplitSolution(solution2.Solution.TotalVolume));

                    ForceUpdateByExternalCause();
                }

                usingItem.Delete();

                return(true);
            }

            return(false);
        }
Пример #19
0
        public async Task PuddlePauseTest()
        {
            var server = StartServer();

            await server.WaitIdleAsync();

            var sMapManager            = server.ResolveDependency <IMapManager>();
            var sPauseManager          = server.ResolveDependency <IPauseManager>();
            var sTileDefinitionManager = server.ResolveDependency <ITileDefinitionManager>();
            var sGameTiming            = server.ResolveDependency <IGameTiming>();
            var sEntityManager         = server.ResolveDependency <IEntityManager>();

            MapId             sMapId = default;
            IMapGrid          sGrid;
            GridId            sGridId      = default;
            IEntity           sGridEntity  = null;
            EntityCoordinates sCoordinates = default;

            // Spawn a paused map with one tile to spawn puddles on
            await server.WaitPost(() =>
            {
                sMapId = sMapManager.CreateMap();
                sPauseManager.SetMapPaused(sMapId, true);
                sGrid              = sMapManager.CreateGrid(sMapId);
                sGridId            = sGrid.Index;
                sGridEntity        = sEntityManager.GetEntity(sGrid.GridEntityId);
                sGridEntity.Paused = true; // See https://github.com/space-wizards/RobustToolbox/issues/1444

                var tileDefinition = sTileDefinitionManager["underplating"];
                var tile           = new Tile(tileDefinition.TileId);
                sCoordinates       = sGrid.ToCoordinates();

                sGrid.SetTile(sCoordinates, tile);
            });

            // Check that the map and grid are paused
            await server.WaitAssertion(() =>
            {
                Assert.True(sPauseManager.IsGridPaused(sGridId));
                Assert.True(sPauseManager.IsMapPaused(sMapId));
                Assert.True(sGridEntity.Paused);
            });

            float           sEvaporateTime        = default;
            PuddleComponent sPuddle               = null;
            Solution        solution              = null;
            ReagentUnit     sPuddleStartingVolume = default;

            // Spawn a puddle
            await server.WaitAssertion(() =>
            {
                var solution = new Solution("water", ReagentUnit.New(20));
                sPuddle      = solution.SpillAt(sCoordinates, "PuddleSmear");

                // Check that the puddle was created
                Assert.NotNull(sPuddle);

                sPuddle.Owner.Paused = true; // See https://github.com/space-wizards/RobustToolbox/issues/1445

                Assert.True(sPuddle.Owner.Paused);

                // Check that the puddle is going to evaporate
                Assert.Positive(sPuddle.EvaporateTime);

                // Should have a timer component added to it for evaporation
                Assert.True(sPuddle.Owner.TryGetComponent(out TimerComponent _));

                sEvaporateTime        = sPuddle.EvaporateTime;
                sPuddleStartingVolume = sPuddle.CurrentVolume;
            });

            // Wait enough time for it to evaporate if it was unpaused
            var sTimeToWait = (5 + (int)Math.Ceiling(sEvaporateTime * sGameTiming.TickRate)) * 2;
            await server.WaitRunTicks(sTimeToWait);

            // No evaporation due to being paused
            await server.WaitAssertion(() =>
            {
                Assert.True(sPuddle.Owner.Paused);
                Assert.True(sPuddle.Owner.TryGetComponent(out TimerComponent _));

                // Check that the puddle still exists
                Assert.False(sPuddle.Owner.Deleted);
            });

            // Unpause the map
            await server.WaitPost(() =>
            {
                sPauseManager.SetMapPaused(sMapId, false);
            });

            // Check that the map, grid and puddle are unpaused
            await server.WaitAssertion(() =>
            {
                Assert.False(sPauseManager.IsMapPaused(sMapId));
                Assert.False(sPauseManager.IsGridPaused(sGridId));
                Assert.False(sPuddle.Owner.Paused);

                // Check that the puddle still exists
                Assert.False(sPuddle.Owner.Deleted);
            });

            // Wait enough time for it to evaporate
            await server.WaitRunTicks(sTimeToWait);

            // Puddle evaporation should have ticked
            await server.WaitAssertion(() =>
            {
                // Check that the puddle is unpaused
                Assert.False(sPuddle.Owner.Paused);

                // Check that the puddle has evaporated some of its volume
                Assert.That(sPuddle.CurrentVolume, Is.LessThan(sPuddleStartingVolume));

                // If its new volume is zero it should have been deleted
                if (sPuddle.CurrentVolume == ReagentUnit.Zero)
                {
                    Assert.True(sPuddle.Deleted);
                }
            });
        }
Пример #20
0
 public override void ExposeData(ObjectSerializer serializer)
 {
     base.ExposeData(serializer);
     serializer.DataField(ref _initialMaxVolume, "maxVolume", ReagentUnit.New(250));
 }
            protected override void Activate(IEntity user, SolutionContainerComponent component)
            {
                if (!user.TryGetComponent <HandsComponent>(out var hands) || hands.GetActiveHand == null)
                {
                    return;
                }

                if (!hands.GetActiveHand.Owner.TryGetComponent <SolutionContainerComponent>(out var handSolutionComp) ||
                    !handSolutionComp.CanAddSolutions ||
                    !component.CanRemoveSolutions)
                {
                    return;
                }

                var transferQuantity = ReagentUnit.Min(handSolutionComp.MaxVolume - handSolutionComp.CurrentVolume, component.CurrentVolume, ReagentUnit.New(10));

                if (transferQuantity <= 0)
                {
                    return;
                }

                var transferSolution = component.SplitSolution(transferQuantity);

                handSolutionComp.TryAddSolution(transferSolution);
            }
        /// <summary>
        /// Handles ui messages from the client. For things such as button presses
        /// which interact with the world and require server action.
        /// </summary>
        /// <param name="obj">A user interface message from the client.</param>
        private void OnUiReceiveMessage(ServerBoundUserInterfaceMessage obj)
        {
            var msg        = (UiButtonPressedMessage)obj.Message;
            var needsPower = msg.Button switch
            {
                UiButton.Eject => false,
                _ => true,
            };

            if (!PlayerCanUseDispenser(obj.Session.AttachedEntity, needsPower))
            {
                return;
            }

            switch (msg.Button)
            {
            case UiButton.Eject:
                TryEject(obj.Session.AttachedEntity);
                break;

            case UiButton.Clear:
                TryClear();
                break;

            case UiButton.SetDispenseAmount1:
                _dispenseAmount = ReagentUnit.New(1);
                break;

            case UiButton.SetDispenseAmount5:
                _dispenseAmount = ReagentUnit.New(5);
                break;

            case UiButton.SetDispenseAmount10:
                _dispenseAmount = ReagentUnit.New(10);
                break;

            case UiButton.SetDispenseAmount25:
                _dispenseAmount = ReagentUnit.New(25);
                break;

            case UiButton.SetDispenseAmount50:
                _dispenseAmount = ReagentUnit.New(50);
                break;

            case UiButton.SetDispenseAmount100:
                _dispenseAmount = ReagentUnit.New(100);
                break;

            case UiButton.Dispense:
                if (HasBeaker)
                {
                    TryDispense(msg.DispenseIndex);
                }

                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            ClickSound();
        }