コード例 #1
0
        /// <summary>
        /// Deserializes the alloy
        /// </summary>
        /// <param name="reader"></param>
        /// <param name="resolver"></param>
        public void FromBytes(BinaryReader reader, IWorldAccessor resolver)
        {
            Code        = reader.ReadString();
            Ingredients = new CookingRecipeIngredient[reader.ReadInt32()];

            for (int i = 0; i < Ingredients.Length; i++)
            {
                Ingredients[i] = new CookingRecipeIngredient();
                Ingredients[i].FromBytes(reader, resolver.ClassRegistry);
                Ingredients[i].Resolve(resolver, "[FromBytes]");
            }

            //NameComponentOrder = reader.ReadIntArray();

            if (!reader.ReadBoolean())
            {
                Shape = new CompositeShape()
                {
                    Base = new AssetLocation(reader.ReadString())
                };
            }

            PerishableProps = new TransitionableProperties();
            PerishableProps.FromBytes(reader, resolver.ClassRegistry);

            //     CanBeServedInto = new JsonItemStack();
            //     CanBeServedInto.FromBytes(reader, resolver.ClassRegistry);
            //     CanBeServedInto.Resolve(resolver, "[FromBytes]");
        }
コード例 #2
0
        private void OnEvery3Second(float dt)
        {
            if (!inventory[0].Empty && CurrentRecipe == null)
            {
                FindMatchingRecipe();
            }

            if (CurrentRecipe != null && Sealed && CurrentRecipe.SealHours > 0)
            {
                if (api.World.Calendar.TotalHours - SealedSinceTotalHours > CurrentRecipe.SealHours)
                {
                    ItemStack mixedStack = CurrentRecipe.Output.ResolvedItemstack.Clone();
                    mixedStack.StackSize = CurrentOutSize;

                    // Carry over freshness
                    TransitionableProperties perishProps = mixedStack.Collectible.GetTransitionableProperties(api.World, mixedStack, null)?[0];

                    if (perishProps != null)
                    {
                        ItemSlot[] slots = new ItemSlot[inventory.Count];
                        for (int i = 0; i < inventory.Count; i++)
                        {
                            slots[i] = inventory[i];
                        }
                        BlockCookingContainer.CarryOverFreshness(api, slots, new ItemStack[] { mixedStack }, perishProps);
                    }

                    if (BlockLiquidContainerBase.GetStackProps(mixedStack) != null)
                    {
                        inventory[0].Itemstack = null;
                        inventory[1].Itemstack = mixedStack;
                    }
                    else
                    {
                        inventory[1].Itemstack = null;
                        inventory[0].Itemstack = mixedStack;
                    }



                    inventory[0].MarkDirty();
                    inventory[1].MarkDirty();

                    MarkDirty(true);
                    api.World.BlockAccessor.MarkBlockEntityDirty(pos);
                    Sealed = false;
                }
            }
            else
            {
                Sealed = false;
                MarkDirty(true);
            }
        }
コード例 #3
0
        public override void DoSmelt(IWorldAccessor world, ISlotProvider cookingSlotsProvider, ItemSlot inputSlot, ItemSlot outputSlot)
        {
            ItemStack[]   stacks = GetCookingStacks(cookingSlotsProvider);
            CookingRecipe recipe = GetMatchingCookingRecipe(world, stacks);

            Block     block       = world.GetBlock(CodeWithVariant("type", "cooked"));
            ItemStack outputStack = new ItemStack(block);

            if (recipe != null)
            {
                int quantityServings = recipe.GetQuantityServings(stacks);

                for (int i = 0; i < stacks.Length; i++)
                {
                    CookingRecipeIngredient ingred = recipe.GetIngrendientFor(stacks[i]);
                    ItemStack cookedStack          = ingred.GetMatchingStack(stacks[i])?.CookedStack?.ResolvedItemstack.Clone();
                    if (cookedStack != null)
                    {
                        stacks[i] = cookedStack;
                    }
                }

                // Carry over and set perishable properties
                TransitionableProperties cookedPerishProps = recipe.PerishableProps.Clone();
                cookedPerishProps.TransitionedStack.Resolve(world, "cooking container perished stack");

                CarryOverFreshness(api, cookingSlotsProvider.Slots, stacks, cookedPerishProps);

                for (int i = 0; i < stacks.Length; i++)
                {
                    stacks[i].StackSize /= quantityServings; // whats this good for? Probably doesn't do anything meaningful
                }



                // Disabled. Let's sacrifice mergability for letting players select how meals should look and be named like
                //stacks = stacks.OrderBy(stack => stack.Collectible.Code.ToShortString()).ToArray(); // Required so that different arrangments of ingredients still create mergable meal bowls

                ((BlockCookedContainer)block).SetContents(recipe.Code, quantityServings, outputStack, stacks);

                outputStack.Collectible.SetTemperature(world, outputStack, GetIngredientsTemperature(world, stacks));
                outputSlot.Itemstack = outputStack;
                inputSlot.Itemstack  = null;

                for (int i = 0; i < cookingSlotsProvider.Slots.Length; i++)
                {
                    cookingSlotsProvider.Slots[i].Itemstack = null;
                }
                return;
            }
        }
コード例 #4
0
        public override ItemStack OnTransitionNow(ItemSlot slot, TransitionableProperties props)
        {
            ItemStack compassStack = base.OnTransitionNow(slot, props);
            var       x            = slot.Itemstack?.Attributes.TryGetInt("compass-target-x");
            var       z            = slot.Itemstack?.Attributes.TryGetInt("compass-target-z");

            if (x != null && z != null)
            {
                var targetPos = new BlockPos((int)x, 0, (int)z);
                var y         = ((ICoreServerAPI)api).World.BlockAccessor.GetTerrainMapheightAt(targetPos);
                targetPos.Y = y;
                (compassStack.Collectible as BlockCompass).SetTargetPos(compassStack, targetPos);
            }
            return(base.OnTransitionNow(slot, props));
        }
コード例 #5
0
        public override ItemStack OnTransitionNow(ItemSlot slot, TransitionableProperties props)
        {
            if (props.Type == EnumTransitionType.Ripen)
            {
                BlockPos pos = slot.Inventory.Pos;
                if (pos != null)
                {
                    Room room       = api.ModLoader.GetModSystem <RoomRegistry>().GetRoomForPosition(pos);
                    int  lightlevel = api.World.BlockAccessor.GetLightLevel(pos, EnumLightLevelType.OnlySunLight);

                    if (room.ExitCount > 0 && lightlevel < 2)
                    {
                        return(new ItemStack(api.World.GetItem(new AssetLocation("cheese-blue-4slice"))));
                    }
                }
            }

            return(base.OnTransitionNow(slot, props));
        }
コード例 #6
0
        public bool TryCraftNow(ICoreAPI api, double nowSealedHours, ItemSlot[] inputslots)
        {
            if (SealHours > 0 && nowSealedHours < SealHours)
            {
                return(false);
            }

            var matched = pairInput(inputslots);

            ItemStack mixedStack = Output.ResolvedItemstack.Clone();

            mixedStack.StackSize = getOutputSize(matched);

            if (mixedStack.StackSize < 0)
            {
                return(false);
            }

            // Carry over freshness
            TransitionableProperties[] props       = mixedStack.Collectible.GetTransitionableProperties(api.World, mixedStack, null);
            TransitionableProperties   perishProps = props != null && props.Length > 0 ? props[0] : null;

            if (perishProps != null)
            {
                CollectibleObject.CarryOverFreshness(api, inputslots, new ItemStack[] { mixedStack }, perishProps);
            }

            ItemStack remainStack = null;

            foreach (var val in matched)
            {
                if (val.Value.ConsumeQuantity != null)
                {
                    remainStack            = val.Key.Itemstack;
                    remainStack.StackSize -= (int)val.Value.ConsumeQuantity * (mixedStack.StackSize / Output.StackSize);
                    if (remainStack.StackSize <= 0)
                    {
                        remainStack = null;
                    }
                    break;
                }
            }

            // Slot 0: Input/Item slot
            // Slot 1: Liquid slot
            if (shouldBeInLiquidSlot(mixedStack))
            {
                inputslots[0].Itemstack = remainStack;
                inputslots[1].Itemstack = mixedStack;
            }
            else
            {
                inputslots[1].Itemstack = remainStack;
                inputslots[0].Itemstack = mixedStack;
            }

            inputslots[0].MarkDirty();
            inputslots[1].MarkDirty();

            return(true);
        }
コード例 #7
0
        public static string PerishableInfoCompact(ICoreAPI Api, ItemSlot contentSlot, float ripenRate, bool withStackName = true)
        {
            StringBuilder dsc = new StringBuilder();

            if (withStackName)
            {
                dsc.Append(contentSlot.Itemstack.GetName());
            }

            TransitionState[] transitionStates = contentSlot.Itemstack?.Collectible.UpdateAndGetTransitionStates(Api.World, contentSlot);

            if (transitionStates != null)
            {
                for (int i = 0; i < transitionStates.Length; i++)
                {
                    string comma = ", ";

                    TransitionState state = transitionStates[i];

                    TransitionableProperties prop = state.Props;
                    float perishRate = contentSlot.Itemstack.Collectible.GetTransitionRateMul(Api.World, contentSlot, prop.Type);

                    if (perishRate <= 0)
                    {
                        continue;
                    }

                    float transitionLevel = state.TransitionLevel;
                    float freshHoursLeft  = state.FreshHoursLeft / perishRate;

                    switch (prop.Type)
                    {
                    case EnumTransitionType.Perish:


                        if (transitionLevel > 0)
                        {
                            dsc.Append(comma + Lang.Get("{0}% spoiled", (int)Math.Round(transitionLevel * 100)));
                        }
                        else
                        {
                            double hoursPerday = Api.World.Calendar.HoursPerDay;

                            if (freshHoursLeft / hoursPerday >= Api.World.Calendar.DaysPerYear)
                            {
                                dsc.Append(comma + Lang.Get("fresh for {0} years", Math.Round(freshHoursLeft / hoursPerday / Api.World.Calendar.DaysPerYear, 1)));
                            }
                            else if (freshHoursLeft > hoursPerday)
                            {
                                dsc.Append(comma + Lang.Get("fresh for {0} days", Math.Round(freshHoursLeft / hoursPerday, 1)));
                            }
                            else
                            {
                                dsc.Append(comma + Lang.Get("fresh for {0} hours", Math.Round(freshHoursLeft, 1)));
                            }
                        }
                        break;

                    case EnumTransitionType.Ripen:

                        if (transitionLevel > 0)
                        {
                            dsc.Append(comma + Lang.Get("{1:0.#} days left to ripen ({0}%)", (int)Math.Round(transitionLevel * 100), (state.TransitionHours - state.TransitionedHours) / Api.World.Calendar.HoursPerDay / ripenRate));
                        }
                        else
                        {
                            double hoursPerday = Api.World.Calendar.HoursPerDay;

                            if (freshHoursLeft / hoursPerday >= Api.World.Calendar.DaysPerYear)
                            {
                                dsc.Append(comma + Lang.Get("will ripen in {0} years", Math.Round(freshHoursLeft / hoursPerday / Api.World.Calendar.DaysPerYear, 1)));
                            }
                            else if (freshHoursLeft > hoursPerday)
                            {
                                dsc.Append(comma + Lang.Get("will ripen in {0} days", Math.Round(freshHoursLeft / hoursPerday, 1)));
                            }
                            else
                            {
                                dsc.Append(comma + Lang.Get("will ripen in {0} hours", Math.Round(freshHoursLeft, 1)));
                            }
                        }
                        break;
                    }
                }
            }

            return(dsc.ToString());
        }
コード例 #8
0
        public string CrockInfoCompact(ItemSlot inSlot)
        {
            BlockMeal      mealblock = Api.World.GetBlock(new AssetLocation("bowl-meal")) as BlockMeal;
            BlockCrock     crock     = inSlot.Itemstack.Collectible as BlockCrock;
            IWorldAccessor world     = Api.World;

            CookingRecipe recipe = crock.GetCookingRecipe(world, inSlot.Itemstack);

            ItemStack[] stacks = crock.GetNonEmptyContents(world, inSlot.Itemstack);

            if (stacks == null || stacks.Length == 0)
            {
                return(Lang.Get("Empty Crock") + "\n");
            }

            StringBuilder dsc = new StringBuilder();

            if (recipe != null)
            {
                double servings = inSlot.Itemstack.Attributes.GetDecimal("quantityServings");

                if (recipe != null)
                {
                    if (servings == 1)
                    {
                        dsc.Append(Lang.Get("{0}x {1}.", servings, recipe.GetOutputName(world, stacks)));
                    }
                    else
                    {
                        dsc.Append(Lang.Get("{0}x {1}.", servings, recipe.GetOutputName(world, stacks)));
                    }
                }
            }
            else
            {
                int i = 0;
                foreach (var stack in stacks)
                {
                    if (stack == null)
                    {
                        continue;
                    }
                    if (i++ > 0)
                    {
                        dsc.Append(", ");
                    }
                    dsc.Append(stack.StackSize + "x " + stack.GetName());
                }

                dsc.Append(".");
            }

            DummyInventory dummyInv = new DummyInventory(Api);

            ItemSlot contentSlot = BlockCrock.GetDummySlotForFirstPerishableStack(Api.World, stacks, null, dummyInv);

            dummyInv.OnAcquireTransitionSpeed = (transType, stack, mul) =>
            {
                return(mul * crock.GetContainingTransitionModifierContained(world, inSlot, transType) * inv.GetTransitionSpeedMul(transType, stack));
            };


            TransitionState[] transitionStates = contentSlot.Itemstack?.Collectible.UpdateAndGetTransitionStates(Api.World, contentSlot);
            bool addNewLine = true;

            if (transitionStates != null)
            {
                for (int i = 0; i < transitionStates.Length; i++)
                {
                    TransitionState state = transitionStates[i];

                    TransitionableProperties prop = state.Props;
                    float perishRate = contentSlot.Itemstack.Collectible.GetTransitionRateMul(world, contentSlot, prop.Type);

                    if (perishRate <= 0)
                    {
                        continue;
                    }

                    addNewLine = false;
                    float transitionLevel = state.TransitionLevel;
                    float freshHoursLeft  = state.FreshHoursLeft / perishRate;

                    switch (prop.Type)
                    {
                    case EnumTransitionType.Perish:
                        if (transitionLevel > 0)
                        {
                            dsc.AppendLine(" " + Lang.Get("{0}% spoiled", (int)Math.Round(transitionLevel * 100)));
                        }
                        else
                        {
                            double hoursPerday = Api.World.Calendar.HoursPerDay;

                            if (freshHoursLeft / hoursPerday >= Api.World.Calendar.DaysPerYear)
                            {
                                dsc.AppendLine(" " + Lang.Get("Fresh for {0} years", Math.Round(freshHoursLeft / hoursPerday / Api.World.Calendar.DaysPerYear, 1)));
                            }

                            /*else if (freshHoursLeft / hoursPerday >= Api.World.Calendar.DaysPerMonth)  - confusing. 12 days per months and stuff..
                             * {
                             *  dsc.AppendLine(Lang.Get("<font color=\"orange\">Perishable.</font> Fresh for {0} months", Math.Round(freshHoursLeft / hoursPerday / Api.World.Calendar.DaysPerMonth, 1)));
                             * }*/
                            else if (freshHoursLeft > hoursPerday)
                            {
                                dsc.AppendLine(" " + Lang.Get("Fresh for {0} days", Math.Round(freshHoursLeft / hoursPerday, 1)));
                            }
                            else
                            {
                                dsc.AppendLine(" " + Lang.Get("Fresh for {0} hours", Math.Round(freshHoursLeft, 1)));
                            }
                        }
                        break;
                    }
                }
            }


            if (addNewLine)
            {
                dsc.AppendLine("");
            }

            return(dsc.ToString());
        }
コード例 #9
0
        public static string PerishableInfoCompact(ICoreAPI Api, ItemSlot contentSlot, float cureRate, bool withStackName = true)
        {
            if (contentSlot.Empty)
            {
                return("");
            }

            StringBuilder dsc = new StringBuilder();

            if (withStackName)
            {
                dsc.Append(contentSlot.Itemstack.GetName());
            }

            TransitionState[] transitionStates = contentSlot.Itemstack?.Collectible.UpdateAndGetTransitionStates(Api.World, contentSlot);

            bool nowSpoiling = false;

            if (transitionStates != null)
            {
                bool appendLine = false;
                foreach (TransitionState state in transitionStates)
                {
                    TransitionableProperties prop = state.Props;
                    float perishRate = contentSlot.Itemstack.Collectible.GetTransitionRateMul(Api.World, contentSlot, prop.Type);

                    float  transitionLevel     = state.TransitionLevel;
                    float  freshHoursLeft      = state.FreshHoursLeft / perishRate;
                    float  transitionHoursLeft = (state.TransitionHours - state.TransitionedHours) / 3;
                    double hoursPerday         = Api.World.Calendar.HoursPerDay;

                    switch (prop.Type)
                    {
                    case EnumTransitionType.Perish:

                        appendLine = true;

                        if (transitionLevel > 0f)
                        {
                            nowSpoiling = true;
                            dsc.Append(", " + Lang.Get("{0}% spoiled", new object[]
                            {
                                (int)Math.Round(transitionLevel * 100f)
                            }));
                        }
                        else
                        {
                            if (freshHoursLeft / hoursPerday >= Api.World.Calendar.DaysPerYear)
                            {
                                dsc.Append(", " + Lang.Get("fresh for {0} years", Math.Round(freshHoursLeft / hoursPerday / Api.World.Calendar.DaysPerYear, 1)));
                            }
                            else if (freshHoursLeft > hoursPerday)
                            {
                                dsc.Append(", " + Lang.Get("fresh for {0} days", Math.Round(freshHoursLeft / hoursPerday, 1)));
                            }
                            else
                            {
                                dsc.Append(", " + Lang.Get("fresh for {0} hours", Math.Round(freshHoursLeft, 1)));
                            }
                        }
                        break;

                    case EnumTransitionType.Dry:
                        if (nowSpoiling)
                        {
                            break;
                        }

                        appendLine = true;
                        if (transitionLevel > 0)
                        {
                            dsc.Append(", " + Lang.Get("{1:0.#} days left to dry ({0}%)", (int)Math.Round(transitionLevel * 100), transitionHoursLeft / hoursPerday));
                        }
                        else
                        {
                            if (transitionHoursLeft / hoursPerday >= Api.World.Calendar.DaysPerYear)
                            {
                                dsc.Append(", " + Lang.Get("will dry in {0} years", Math.Round(transitionHoursLeft / hoursPerday / Api.World.Calendar.DaysPerYear, 1)));
                            }
                            else if (transitionHoursLeft > hoursPerday)
                            {
                                dsc.Append(", " + Lang.Get("will dry in {0} days", Math.Round(transitionHoursLeft / hoursPerday, 1)));
                            }
                            else
                            {
                                dsc.Append(", " + Lang.Get("will dry in {0} hours", Math.Round(transitionHoursLeft, 1)));
                            }
                        }
                        break;

                    case EnumTransitionType.Cure:
                        if (nowSpoiling)
                        {
                            break;
                        }

                        appendLine = true;

                        if (transitionLevel > 0)
                        {
                            dsc.Append(", " + Lang.Get("{1:0.#} days left to cure ({0}%)", (int)Math.Round(transitionLevel * 100), transitionHoursLeft / hoursPerday / cureRate));
                        }
                        else
                        {
                            if (freshHoursLeft / hoursPerday >= Api.World.Calendar.DaysPerYear)
                            {
                                dsc.Append(", " + Lang.Get("will cure in {0} years", Math.Round(freshHoursLeft / hoursPerday / Api.World.Calendar.DaysPerYear, 1)));
                            }
                            else if (freshHoursLeft > hoursPerday)
                            {
                                dsc.Append(", " + Lang.Get("will cure in {0} days", Math.Round(freshHoursLeft / hoursPerday, 1)));
                            }
                            else
                            {
                                dsc.Append(", " + Lang.Get("will cure in {0} hours", Math.Round(freshHoursLeft, 1)));
                            }
                        }
                        break;
                    }
                }


                if (appendLine)
                {
                    dsc.AppendLine();
                }
            }

            return(dsc.ToString());
        }
コード例 #10
0
        public static void CarryOverFreshness(ICoreAPI api, ItemSlot[] inputSlots, ItemStack[] outStacks, TransitionableProperties perishProps)
        {
            float transitionedHoursRelative = 0;
            int   quantity = 0;

            for (int i = 0; i < inputSlots.Length; i++)
            {
                ItemSlot slot = inputSlots[i];
                if (slot.Empty)
                {
                    continue;
                }
                TransitionState state = slot.Itemstack.Collectible.UpdateAndGetTransitionState(api.World, slot, EnumTransitionType.Perish);
                if (state == null)
                {
                    continue;
                }

                quantity++;
                float val = state.TransitionedHours / (state.TransitionHours + state.FreshHours);

                transitionedHoursRelative += val;
            }

            transitionedHoursRelative /= Math.Max(1, quantity);

            for (int i = 0; i < outStacks.Length; i++)
            {
                if (!(outStacks[i].Attributes["transitionstate"] is ITreeAttribute))
                {
                    outStacks[i].Attributes["transitionstate"] = new TreeAttribute();
                }

                float transitionHours = perishProps.TransitionHours.nextFloat(1, api.World.Rand);
                float freshHours      = perishProps.FreshHours.nextFloat(1, api.World.Rand);

                ITreeAttribute attr = (ITreeAttribute)outStacks[i].Attributes["transitionstate"];
                attr.SetDouble("createdTotalHours", api.World.Calendar.TotalHours);
                attr.SetDouble("lastUpdatedTotalHours", api.World.Calendar.TotalHours);

                attr["freshHours"]        = new FloatArrayAttribute(new float[] { freshHours });
                attr["transitionHours"]   = new FloatArrayAttribute(new float[] { transitionHours });
                attr["transitionedHours"] = new FloatArrayAttribute(new float[] { Math.Max(0, transitionedHoursRelative * 0.8f * (transitionHours + freshHours) - 2) });
            }
        }