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); } }
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); }
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); } }
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); } }
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); }
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); } }
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); }
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); }
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"); } }