Пример #1
0
        private void Event_FileDrop(FileDropEvent ev)
        {
            FileInfo info  = null;
            long     bytes = 0;

            try
            {
                info  = new FileInfo(ev.Filename);
                bytes = info.Length;
            } catch (Exception ex)
            {
                capi.TriggerIngameError(this, "importfailed", string.Format("Unable to import schematic: ", ex));
                return;
            }

            if (ownWorkspace != null && ownWorkspace.ToolsEnabled && ownWorkspace.ToolName == "Import")
            {
                int schematicMaxUploadSizeKb = capi.Settings.Int.Get("schematicMaxUploadSizeKb", 150);

                // Limit the file size
                if (bytes / 1024 > schematicMaxUploadSizeKb)
                {
                    capi.TriggerIngameError(this, "schematictoolarge", Lang.Get("Importing of schematics above {0} KB disabled, adjust config schematicMaxUploadSizeKb to change.", schematicMaxUploadSizeKb));
                    return;
                }

                string         err       = null;
                BlockSchematic schematic = BlockSchematic.LoadFromFile(ev.Filename, ref err);
                if (err != null)
                {
                    capi.TriggerIngameError(this, "importerror", err);
                    return;
                }

                string json = "";
                using (TextReader textReader = new StreamReader(ev.Filename))
                {
                    json = textReader.ReadToEnd();
                    textReader.Close();
                }

                if (json.Length < 1024 * 100)
                {
                    capi.World.Player.ShowChatNotification(Lang.Get("Sending {0} bytes of schematicdata to the server...", json.Length));
                }
                else
                {
                    capi.World.Player.ShowChatNotification(Lang.Get("Sending {0} bytes of schematicdata to the server, this may take a while...", json.Length));
                }

                capi.Event.RegisterCallback((dt) =>
                {
                    clientChannel.SendPacket <SchematicJsonPacket>(new SchematicJsonPacket()
                    {
                        Filename = info.Name, JsonCode = json
                    });
                }, 20);
            }
        }
Пример #2
0
        public override void OnHeldInteractStart(ItemSlot slot, EntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel, bool firstEvent, ref EnumHandHandling handling)
        {
            if (blockSel != null)
            {
                var block = api.World.BlockAccessor.GetBlock(blockSel.Position);
                if (block.Attributes?.IsTrue("pieFormingSurface") == true)
                {
                    if (slot.StackSize >= 2)
                    {
                        BlockPie blockform = api.World.GetBlock(new AssetLocation("pie-raw")) as BlockPie;
                        blockform.TryPlacePie(byEntity, blockSel);
                    }
                    else
                    {
                        ICoreClientAPI capi = api as ICoreClientAPI;
                        if (capi != null)
                        {
                            capi.TriggerIngameError(this, "notpieable", Lang.Get("Need at least 2 dough"));
                        }
                    }

                    handling = EnumHandHandling.PreventDefault;
                    return;
                }
            }

            base.OnHeldInteractStart(slot, byEntity, blockSel, entitySel, firstEvent, ref handling);
        }
Пример #3
0
        public bool Interact(IPlayer player)
        {
            bool sneaking = player.WorldData.EntityControls.Sneak;

            if (sneaking)
            {
                int ic = structure.InCompleteBlockCount(Api.World, Pos);

                if (ic == 0)
                {
                    structure.ClearHighlights(Api.World, player);
                    return(true);
                }
                else
                {
                    structure.HighlightIncompleteParts(Api.World, player, Pos);
                    capi?.TriggerIngameError(this, "incomplete", Lang.Get("Structure is not complete, make sure the immediate area around the block is clear."));
                    return(false);
                }
            }
            else
            {
                return(false);
            }
        }
Пример #4
0
        private void onAuctionActionResponse(AuctionActionResponsePacket pkt)
        {
            if (pkt.ErrorCode != null)
            {
                capi.TriggerIngameError(this, pkt.ErrorCode, Lang.Get("auctionerror-" + pkt.ErrorCode));
                curTraderClient?.talkUtil.Talk(EnumTalkType.Complain);
            }
            else
            {
                if (pkt.Action == EnumAuctionAction.PurchaseAuction || (pkt.Action == EnumAuctionAction.RetrieveAuction && pkt.MoneyReceived))
                {
                    capi.Gui.PlaySound(new AssetLocation("sounds/effect/cashregister"), false, 0.25f);
                }

                curTraderClient?.talkUtil.Talk(EnumTalkType.Purchase);
            }
        }
Пример #5
0
        public virtual bool OnInteract(IPlayer byPlayer, BlockSelection bs)
        {
            ItemSlot slot = byPlayer.InventoryManager.ActiveHotbarSlot;

            if (slot.Empty)
            {
                if (TryTake(byPlayer))
                {
                    byPlayer.InventoryManager.BroadcastHotbarSlot();
                    return(true);
                }
                return(false);
            }
            else
            {
                CollectibleObject colObj = slot.Itemstack.Collectible;
                if (colObj.Attributes?.IsTrue("isFirewood") == true)
                {
                    if (TryFuel(slot))
                    {
                        AssetLocation sound = slot.Itemstack?.Block?.Sounds?.Place;
                        Api.World.PlaySoundAt(sound != null ? sound : new AssetLocation("sounds/player/build"), byPlayer.Entity, byPlayer, true, 16);
                        byPlayer.InventoryManager.BroadcastHotbarSlot();
                        (byPlayer as IClientPlayer)?.TriggerFpAnimation(EnumHandInteract.HeldItemInteract);
                        return(true);
                    }

                    return(false);
                }
                else if (colObj.Attributes?["bakingProperties"] != null || colObj.CombustibleProps?.SmeltingType == EnumSmeltType.Bake && colObj.CombustibleProps.MeltingPoint < maxBakingTemperatureAccepted)  //Can't meaningfully bake anything requiring heat over 260 in the basic clay oven
                {
                    if (slot.Itemstack.Equals(Api.World, lastRemoved, GlobalConstants.IgnoredStackAttributes) && !ovenInv[0].Empty)
                    {
                        if (TryTake(byPlayer))
                        {
                            byPlayer.InventoryManager.BroadcastHotbarSlot();
                            return(true);
                        }
                    }
                    else
                    {
                        if (TryPut(slot))
                        {
                            AssetLocation sound = slot.Itemstack?.Block?.Sounds?.Place;
                            Api.World.PlaySoundAt(sound != null ? sound : new AssetLocation("sounds/player/buildhigh"), byPlayer.Entity, byPlayer, true, 16);
                            byPlayer.InventoryManager.BroadcastHotbarSlot();
                            return(true);
                        }
                        else
                        {
                            if (slot.Itemstack.Block?.GetBehavior <BlockBehaviorCanIgnite>() == null)
                            {
                                ICoreClientAPI capi = Api as ICoreClientAPI;
                                if (capi != null && (slot.Empty || slot.Itemstack.Attributes.GetBool("bakeable", true) == false))
                                {
                                    capi.TriggerIngameError(this, "notbakeable", Lang.Get("This item is not bakeable."));
                                }
                                else if (capi != null && !slot.Empty)
                                {
                                    capi.TriggerIngameError(this, "notbakeable", burning ? Lang.Get("Wait until the fire is out") : Lang.Get("Oven is full"));
                                }

                                return(true);
                            }
                        }
                    }

                    return(false);
                }
                else if (TryTake(byPlayer))
                //TryTake with non-empty hotbar slot, filling available empty slots in player inventory
                {
                    byPlayer.InventoryManager.BroadcastHotbarSlot();
                    return(true);
                }
            }

            return(false);
        }
Пример #6
0
        private bool TryAddIngredientFrom(ItemSlot slot, IPlayer byPlayer = null)
        {
            var pieProps = slot.Itemstack.ItemAttributes?["inPieProperties"]?.AsObject <InPieProperties>(null, slot.Itemstack.Collectible.Code.Domain);

            if (pieProps == null)
            {
                if (byPlayer != null && capi != null)
                {
                    capi.TriggerIngameError(this, "notpieable", Lang.Get("This item can not be added to pies"));
                }
                return(false);
            }

            if (slot.StackSize < 2)
            {
                if (byPlayer != null && capi != null)
                {
                    capi.TriggerIngameError(this, "notpieable", Lang.Get("Need at least 2 items each"));
                }
                return(false);
            }

            var pieBlock = (inv[0].Itemstack.Block as BlockPie);

            if (pieBlock == null)
            {
                return(false);
            }

            ItemStack[] cStacks = pieBlock.GetContents(Api.World, inv[0].Itemstack);

            bool isFull     = cStacks[1] != null && cStacks[2] != null && cStacks[3] != null && cStacks[4] != null;
            bool hasFilling = cStacks[1] != null || cStacks[2] != null || cStacks[3] != null || cStacks[4] != null;

            if (isFull)
            {
                if (pieProps.PartType == EnumPiePartType.Crust)
                {
                    if (cStacks[5] == null)
                    {
                        cStacks[5] = slot.TakeOut(2);
                        pieBlock.SetContents(inv[0].Itemstack, cStacks);
                    }
                    else
                    {
                        ItemStack stack = inv[0].Itemstack;
                        stack.Attributes.SetInt("topCrustType", (stack.Attributes.GetInt("topCrustType") + 1) % 3);
                    }
                    return(true);
                }
                if (byPlayer != null && capi != null)
                {
                    capi.TriggerIngameError(this, "piefullfilling", Lang.Get("Can't add more filling - already completely filled pie"));
                }
                return(false);
            }

            if (pieProps.PartType != EnumPiePartType.Filling)
            {
                if (byPlayer != null && capi != null)
                {
                    capi.TriggerIngameError(this, "pieneedsfilling", Lang.Get("Need to add a filling next"));
                }
                return(false);
            }


            if (!hasFilling)
            {
                cStacks[1] = slot.TakeOut(2);
                pieBlock.SetContents(inv[0].Itemstack, cStacks);
                return(true);
            }

            var foodCats   = cStacks.Select(stack => stack?.Collectible.NutritionProps?.FoodCategory ?? stack?.ItemAttributes?["nutritionPropsWhenInMeal"]?.AsObject <FoodNutritionProperties>()?.FoodCategory ?? EnumFoodCategory.Vegetable).ToArray();
            var stackprops = cStacks.Select(stack => stack?.ItemAttributes["inPieProperties"]?.AsObject <InPieProperties>(null, stack.Collectible.Code.Domain)).ToArray();

            ItemStack        cstack  = slot.Itemstack;
            EnumFoodCategory foodCat = slot.Itemstack?.Collectible.NutritionProps?.FoodCategory ?? slot.Itemstack?.ItemAttributes?["nutritionPropsWhenInMeal"]?.AsObject <FoodNutritionProperties>()?.FoodCategory ?? EnumFoodCategory.Vegetable;

            bool equal         = true;
            bool foodCatEquals = true;

            for (int i = 1; equal && i < cStacks.Length - 1; i++)
            {
                if (cstack == null)
                {
                    continue;
                }

                equal         &= cStacks[i] == null || cstack.Equals(Api.World, cStacks[i], GlobalConstants.IgnoredStackAttributes);
                foodCatEquals &= cStacks[i] == null || foodCats[i] == foodCat;

                cstack  = cStacks[i];
                foodCat = foodCats[i];
            }

            int emptySlotIndex = 2 + (cStacks[2] != null ? 1 + (cStacks[3] != null ? 1 : 0) : 0);

            if (equal)
            {
                cStacks[emptySlotIndex] = slot.TakeOut(2);
                pieBlock.SetContents(inv[0].Itemstack, cStacks);
                return(true);
            }

            if (!foodCatEquals)
            {
                if (byPlayer != null && capi != null)
                {
                    capi.TriggerIngameError(this, "piefullfilling", Lang.Get("Can't mix fillings from different food categories"));
                }
                return(false);
            }
            else
            {
                if (!stackprops[1].AllowMixing)
                {
                    if (byPlayer != null && capi != null)
                    {
                        capi.TriggerIngameError(this, "piefullfilling", Lang.Get("You really want to mix these to ingredients?! That would taste horrible!"));
                    }
                    return(false);
                }

                cStacks[emptySlotIndex] = slot.TakeOut(2);
                pieBlock.SetContents(inv[0].Itemstack, cStacks);
                return(true);
            }
        }
Пример #7
0
        public bool Interact(IPlayer byPlayer, bool preferThis)
        {
            bool sneaking = byPlayer.WorldData.EntityControls.Sneak;

            int      damagedTiles    = 0;
            int      wrongTiles      = 0;
            int      incompleteCount = 0;
            BlockPos posMain         = Pos;

            // set up incompleteCount (etc) for both orientations and pick whichever is more complete
            if (sneaking)
            {
                int ic    = 0;
                int icOpp = int.MaxValue;
                int dt    = 0;
                int wt    = 0;
                int dtOpp = 0;
                int wtOpp = 0;

                ic = ms.InCompleteBlockCount(Api.World, Pos,
                                             (haveBlock, wantLoc) => { if (haveBlock.FirstCodePart() == "refractorybricks" && haveBlock.Variant["state"] == "damaged")
                                                                       {
                                                                           dt++;
                                                                       }
                                                                       else
                                                                       {
                                                                           wt++;
                                                                       } }
                                             );
                if (ic > 0 && blockScs.IsCompleteCoffin(Pos))
                {
                    icOpp = msOpp.InCompleteBlockCount(Api.World, Pos.AddCopy(blockScs.Orientation.Opposite),
                                                       (haveBlock, wantLoc) => { if (haveBlock.FirstCodePart() == "refractorybricks" && haveBlock.Variant["state"] == "damaged")
                                                                                 {
                                                                                     dtOpp++;
                                                                                 }
                                                                                 else
                                                                                 {
                                                                                     wtOpp++;
                                                                                 } }
                                                       );
                }

                // This logic aims to figure out which structure to show - if one is almost complete (3 wrong tiles or less) that one will be shown; preferThis has a preference if both are equally incomplete (newly placed stonecoffin) or if one is not much more complete than the other (allows for building errors of 1-3 tiles before the shown structure flips)
                if (wtOpp <= 3 && wt < wtOpp || wtOpp > 3 && wt < wtOpp - 3 || preferThis && wt <= wtOpp || preferThis && wt > 3 && wt <= wtOpp + 3)
                {
                    incompleteCount = ic;
                    damagedTiles    = dt;
                    wrongTiles      = wt;
                    if (ic > 0)
                    {
                        msHighlighted = ms;
                    }
                }
                else
                {
                    incompleteCount = icOpp;
                    damagedTiles    = dtOpp;
                    wrongTiles      = wtOpp;
                    msHighlighted   = msOpp;
                    posMain         = Pos.AddCopy(blockScs.Orientation.Opposite);
                }
            }

            if (sneaking && incompleteCount > 0)
            {
                if (wrongTiles > 0 && damagedTiles > 0)
                {
                    capi?.TriggerIngameError(this, "incomplete", Lang.Get("Structure is not complete, {0} blocks are missing or wrong, {1} tiles are damaged!", wrongTiles, damagedTiles));
                }
                else
                {
                    if (wrongTiles > 0)
                    {
                        capi?.TriggerIngameError(this, "incomplete", Lang.Get("Structure is not complete, {0} blocks are missing or wrong!", wrongTiles));
                    }
                    else
                    {
                        if (damagedTiles == 1)
                        {
                            capi?.TriggerIngameError(this, "incomplete", Lang.Get("Structure is not complete, {0} tile is damaged!", damagedTiles));
                        }
                        else
                        {
                            capi?.TriggerIngameError(this, "incomplete", Lang.Get("Structure is not complete, {0} tiles are damaged!", damagedTiles));
                        }
                    }
                }

                if (Api.Side == EnumAppSide.Client)
                {
                    msHighlighted.HighlightIncompleteParts(Api.World, byPlayer, posMain);
                }
                return(false);
            }
            else
            {
                if (Api.Side == EnumAppSide.Client)
                {
                    msHighlighted?.ClearHighlights(Api.World, byPlayer);
                }
            }

            if (!sneaking)
            {
                return(false);
            }

            if (!blockScs.IsCompleteCoffin(Pos))
            {
                capi?.TriggerIngameError(this, "incomplete", Lang.Get("Cannot fill an incomplete coffin, place the other half first"));
                return(false);
            }

            ItemSlot slot = byPlayer.InventoryManager.ActiveHotbarSlot;


            if (!slot.Empty)
            {
                if (IngotCount / 4 >= CoalLayerCount)
                {
                    return(AddCoal(slot));
                }
                else
                {
                    return(AddIngot(slot));
                }
            }

            return(true);
        }
Пример #8
0
        public bool TryCreateKiln(IWorldAccessor world, IPlayer byPlayer, BlockPos pos)
        {
            ItemSlot hotbarSlot = byPlayer.InventoryManager.ActiveHotbarSlot;

            if (hotbarSlot.Empty)
            {
                return(false);
            }

            BlockEntity be = world.BlockAccessor.GetBlockEntity(pos);

            if (be is BlockEntityGroundStorage beg)
            {
                if (!beg.OnTryCreateKiln())
                {
                    return(false);
                }

                ICoreClientAPI capi = api as ICoreClientAPI;
                bool           ok   = true;
                foreach (var face in BlockFacing.HORIZONTALS.Append(BlockFacing.DOWN))
                {
                    BlockPos npos  = pos.AddCopy(face);
                    Block    block = world.BlockAccessor.GetBlock(npos);
                    if (!block.CanAttachBlockAt(world.BlockAccessor, this, npos, face.Opposite))
                    {
                        capi?.TriggerIngameError(this, "notsolid", Lang.Get("Pit kilns need to be surrounded by solid, non-flammable blocks"));
                        ok = false;
                        break;
                    }
                    if (block.CombustibleProps != null)
                    {
                        capi?.TriggerIngameError(this, "notsolid", Lang.Get("Pit kilns need to be surrounded by solid, non-flammable blocks"));
                        ok = false;
                        break;
                    }
                }
                if (!ok)
                {
                    return(false);
                }

                Block upblock = world.BlockAccessor.GetBlock(pos.UpCopy());
                if (upblock.Replaceable < 6000)
                {
                    ok = false;
                    capi?.TriggerIngameError(this, "notairspace", Lang.Get("Pit kilns need one block of air space above them"));
                }
                if (!ok)
                {
                    return(false);
                }


                BuildStage[] buildStages = null;
                bool         found       = false;
                foreach (var val in BuildStagesByBlock)
                {
                    if (!beg.Inventory[0].Empty && WildcardUtil.Match(new AssetLocation(val.Key), beg.Inventory[0].Itemstack.Collectible.Code))
                    {
                        buildStages = val.Value;
                        found       = true;
                        break;
                    }
                }
                if (!found)
                {
                    BuildStagesByBlock.TryGetValue("*", out buildStages);
                }

                if (buildStages == null)
                {
                    return(false);
                }
                if (!hotbarSlot.Itemstack.Equals(world, buildStages[0].Materials[0].ItemStack, GlobalConstants.IgnoredStackAttributes) || hotbarSlot.StackSize < buildStages[0].Materials[0].ItemStack.StackSize)
                {
                    return(false);
                }



                var prevInv = beg.Inventory;

                world.BlockAccessor.SetBlock(Id, pos);

                var begs = world.BlockAccessor.GetBlockEntity(pos) as BlockEntityPitKiln;
                for (int i = 0; i < prevInv.Count; i++)
                {
                    begs.Inventory[i] = prevInv[i];
                }

                begs.OnCreated(byPlayer);
                begs.updateMeshes();
                begs.MarkDirty(true);


                return(true);
            }


            return(false);
        }
Пример #9
0
        public override void OnInteract(EntityAgent byEntity, ItemSlot slot, Vec3d hitPosition, EnumInteractMode mode)
        {
            if (mode != EnumInteractMode.Interact || !(byEntity is EntityPlayer))
            {
                base.OnInteract(byEntity, slot, hitPosition, mode);
                return;
            }

            if (!Alive)
            {
                return;
            }

            EntityPlayer entityplr = byEntity as EntityPlayer;
            IPlayer      player    = World.PlayerByUid(entityplr.PlayerUID);


            tradingWith = entityplr;


            if (World.Side == EnumAppSide.Client)
            {
                ICoreClientAPI capi = (ICoreClientAPI)Api;

                if (tradingWith.Pos.SquareDistanceTo(this.Pos) <= 5 && dlg?.IsOpened() != true)
                {
                    // Will break all kinds of things if we allow multiple concurrent of these dialogs
                    if (capi.Gui.OpenedGuis.FirstOrDefault(dlg => dlg is GuiDialogTrader && dlg.IsOpened()) == null)
                    {
                        capi.Network.SendEntityPacket(this.EntityId, 1001);
                        player.InventoryManager.OpenInventory(Inventory);

                        dlg = new GuiDialogTrader(Inventory, this, World.Api as ICoreClientAPI);
                        dlg.TryOpen();
                    }
                    else
                    {
                        capi.TriggerIngameError(this, "onlyonedialog", Lang.Get("Can only trade with one trader at a time"));
                    }
                }
                else
                {
                    // Ensure inventory promptly closed server-side if the client didn't open the GUI

                    capi.Network.SendPacketClient(capi.World.Player.InventoryManager.CloseInventory(Inventory));
                }

                talkUtil.Talk(EnumTalkType.Meet);
            }

            if (World.Side == EnumAppSide.Server)
            {
                // Make the trader walk towards the player
                AiTaskManager tmgr = GetBehavior <EntityBehaviorTaskAI>().TaskManager;
                tmgr.StopTask(typeof(AiTaskWander));

                AiTaskGotoEntity task = new AiTaskGotoEntity(this, entityplr);
                if (task.TargetReached())
                {
                    tmgr.ExecuteTask(new AiTaskLookAtEntity(this, entityplr), 1);
                }
                else
                {
                    tmgr.ExecuteTask(task, 1);
                }

                AnimManager.StartAnimation(new AnimationMetaData()
                {
                    Animation = "welcome", Code = "welcome", Weight = 10, EaseOutSpeed = 10000, EaseInSpeed = 10000
                });
                AnimManager.StopAnimation("idle");
            }
        }