//will check and see if there is an appropriate heated block in order to generator power bool CheckHeat() { //find heated blocks - firepits, furnaces, burning coal piles heated = false; BlockPos bp = Pos.Copy().Offset(heatFace); BlockEntity checkblock = Api.World.BlockAccessor.GetBlockEntity(bp); if (checkblock == null) { return(false); } //check for hot firepit var checkFirePit = checkblock as BlockEntityFirepit; if (checkFirePit != null) { if (checkFirePit.furnaceTemperature >= requiredHeat) { heated = true; return(true); } } //check for coal piles: Note need to add check for how hot var checkCoalPile = checkblock as BlockEntityCoalPile; if (checkCoalPile != null) { if (checkCoalPile.IsBurning) { heated = true; return(true); } } return(false); }
void TryStart() { BlockPos bp = Pos.Copy().Offset(rmInputFace); BlockEntity checkblock = Api.World.BlockAccessor.GetBlockEntity(bp); deviceState = enDeviceState.MATERIALHOLD; if (Api.World is IServerWorldAccessor) { workingitem = null; var inputContainer = checkblock as BlockEntityContainer; if (inputContainer == null) { return; } if (inputContainer.Inventory.Empty) { return; } for (int c = 0; c < inputContainer.Inventory.Count; c++) { ItemSlot checkslot = inputContainer.Inventory[c]; if (checkslot == null) { continue; } if (checkslot.StackSize == 0) { continue; } Item checkitem = checkslot.Itemstack.Item; Block checkiblock = checkslot.Itemstack.Block; if (checkitem == null && checkiblock == null) { continue; } CollectibleObject co; if (checkitem != null) { co = checkitem as CollectibleObject; } else { co = checkiblock as CollectibleObject; } if (!MacerationRecipe.CanMacerate(co, Api, MachineName)) { continue; } workingitem = co; //Item has been set, need to pull one item from the stack deviceState = enDeviceState.RUNNING; checkslot.TakeOut(1); checkslot.MarkDirty(); break; } } }
protected void transferEnergy(BlockFacing side, float dt) { BlockPos outPos = Pos.Copy().Offset(side); BlockEntity tileEntity = Api.World.BlockAccessor.GetBlockEntity(outPos); if (tileEntity == null) { return; } if (!(tileEntity is IFluxStorage)) { return; } if (tileEntity is IEnergyPoint && ((IEnergyPoint)tileEntity).GetCore() == GetCore()) { return; } float eout = Math.Min(MyMiniLib.GetAttributeInt(Block, "transfer", 500) * dt, core.storage.getEnergyStored() * dt); eout = ((IFluxStorage)tileEntity).receiveEnergy(side.Opposite, eout, false, dt); if (tileEntity is IEnergyPoint && eout > 0) { ((IEnergyPoint)tileEntity).AddSkipSide(side.Opposite); } core.storage.modifyEnergyStored(-eout); }
protected override void DoDeviceComplete() { deviceState = enDeviceState.IDLE; BlockPos bp = Pos.Copy().Offset(outputFace); BlockEntity checkblock = Api.World.BlockAccessor.GetBlockEntity(bp); var outputContainer = checkblock as BlockEntityContainer; if (Api.World is IServerWorldAccessor) { DummyInventory dummy = new DummyInventory(Api); List <ItemStack> outputitems = MacerationRecipe.GetMacerate(workingitem, Api, MachineName); foreach (ItemStack outitem in outputitems) { if (outitem == null) { continue; } dummy[0].Itemstack = outitem; //no output conatiner, spitout stuff if (outputContainer != null) { bool stoptrying = false; int safetycounter = 0; while (!stoptrying) { WeightedSlot tryoutput = outputContainer.Inventory.GetBestSuitedSlot(dummy[0]); if (tryoutput.slot != null) { ItemStackMoveOperation op = new ItemStackMoveOperation(Api.World, EnumMouseButton.Left, 0, EnumMergePriority.DirectMerge, dummy[0].StackSize); dummy[0].TryPutInto(tryoutput.slot, ref op); tryoutput.slot.MarkDirty(); if (dummy[0] == null) { stoptrying = true; } else if (dummy[0].StackSize == 0) { stoptrying = true; } } else { stoptrying = true; } safetycounter++; if (safetycounter > 24) { stoptrying = true; } } } Vec3d pos = bp.ToVec3d(); dummy.DropAll(pos); } } }
protected override void DoDeviceComplete() { deviceState = enDeviceState.IDLE; string userecipe = recipe; if (ingredient_subtype != "") { userecipe += "-" + ingredient_subtype; } Block outputBlock = Api.World.GetBlock(new AssetLocation(userecipe)); Item outputItem = Api.World.GetItem(new AssetLocation(userecipe)); if (outputBlock == null && outputItem == null) { deviceState = enDeviceState.ERROR; return; } ItemStack outputStack; if (outputBlock != null) { outputStack = new ItemStack(outputBlock, outputQuantity); } else { outputStack = new ItemStack(outputItem, outputQuantity); } dummy[0].Itemstack = outputStack; outputStack.Collectible.SetTemperature(Api.World, outputStack, lastheatreading); BlockPos bp = Pos.Copy().Offset(outputFace); BlockEntity checkblock = Api.World.BlockAccessor.GetBlockEntity(bp); var outputContainer = checkblock as BlockEntityContainer; if (outputContainer != null) { WeightedSlot tryoutput = outputContainer.Inventory.GetBestSuitedSlot(dummy[0]); if (tryoutput.slot != null) { ItemStackMoveOperation op = new ItemStackMoveOperation(Api.World, EnumMouseButton.Left, 0, EnumMergePriority.DirectMerge, outputQuantity); dummy[0].TryPutInto(tryoutput.slot, ref op); } } if (!dummy.Empty) { //If no storage then spill on the ground Vec3d pos = Pos.ToVec3d(); dummy.DropAll(pos); } Api.World.PlaySoundAt(new AssetLocation("sounds/doorslide"), Pos.X, Pos.Y, Pos.Z, null, false, 8, 1); if (Api.World.Side == EnumAppSide.Client && animUtil != null) { animUtil.StopAnimation(Pos.ToString() + animationName); } }
protected void FetchMaterial() { internalQuantity = Math.Min(internalQuantity, inputQuantity); //this shouldn't be necessary Item rm = Api.World.GetItem(new AssetLocation(ingredient)); if (rm == null) { deviceState = enDeviceState.ERROR; return; } BlockPos bp = Pos.Copy().Offset(rmInputFace); BlockEntity checkblock = Api.World.BlockAccessor.GetBlockEntity(bp); var inputContainer = checkblock as BlockEntityContainer; if (inputContainer == null) { return; } if (inputContainer.Inventory.Empty) { return; } for (int c = 0; c < inputContainer.Inventory.Count; c++) { ItemSlot checkslot = inputContainer.Inventory[c]; if (checkslot == null) { continue; } if (checkslot.StackSize == 0) { continue; } bool match = false; if (checkslot.Itemstack.Item != null && checkslot.Itemstack.Item.FirstCodePart() == rm.FirstCodePart()) { match = true; } else if (checkslot.Itemstack.Block != null && checkslot.Itemstack.Block.FirstCodePart() == rm.FirstCodePart()) { match = true; } if (match) { int reqQty = Math.Min(checkslot.StackSize, inputQuantity - internalQuantity); checkslot.TakeOut(reqQty); internalQuantity += reqQty; checkslot.MarkDirty(); } } return; }
public void TryIgnite(IPlayer byPlayer) { BurningUntilTotalHours = Api.World.Calendar.TotalHours + BurnTimeHours; var bh = GetBehavior <BEBehaviorBurning>(); Lit = true; bh.OnFirePlaced(Pos.UpCopy(), Pos.Copy(), byPlayer?.PlayerUID); Api.World.BlockAccessor.ExchangeBlock(Block.Id, Pos); // Forces a relight of this block MarkDirty(true); }
private void exitChunkLoaded(BlockPos exitPos) { BlockStaticTranslocator exitBlock = Api.World.BlockAccessor.GetBlock(exitPos) as BlockStaticTranslocator; if (exitBlock == null) { // Cheap hax: Pre v1.10 chunks do not have translocators at the same location and maybe future versions will also have a changed location // So let's still try to find something useful in the chunk we generated, with any luck we come across an old one. exitPos = HasExitPoint(exitPos); if (exitPos != null) { exitBlock = Api.World.BlockAccessor.GetBlock(exitPos) as BlockStaticTranslocator; } } if (exitBlock != null && !exitBlock.Repaired) { // Repair it Api.World.BlockAccessor.SetBlock(ownBlock.Id, exitPos); BlockEntityStaticTranslocator beExit = Api.World.BlockAccessor.GetBlockEntity(exitPos) as BlockEntityStaticTranslocator; // Connect remote beExit.tpLocation = Pos.Copy(); beExit.canTeleport = true; beExit.findNextChunk = false; beExit.activated = true; if (!beExit.FullyRepaired) { beExit.repairState = 4; beExit.setupGameTickers(); } Api.World.BlockAccessor.MarkBlockEntityDirty(exitPos); Api.World.BlockAccessor.MarkBlockDirty(exitPos); Api.World.Logger.Debug("Connected translocator at {0} (chunkpos: {2}) to my location: {1}", exitPos, Pos, exitPos / 32); // Connect self MarkDirty(true); tpLocation = exitPos; canTeleport = true; } else { Api.World.Logger.Warning("Translocator: Regen chunk but broken translocator is gone. Structure generation perhaps seed not consistent? May also just be pre-v1.10 chunk, so probably nothing to worry about. Searching again..."); findNextChunk = true; } }
protected void transferEnergy(BlockFacing side, float dt) { BlockPos outPos = Pos.Copy().Offset(side); BlockEntity tileEntity = Api.World.BlockAccessor.GetBlockEntity(outPos); if (tileEntity == null) { return; } if (!(tileEntity is IFluxStorage)) { return; } float eout = Math.Min(energyStorage.getLimitExtract() * dt, energyStorage.getEnergyStored() * dt); energyStorage.modifyEnergyStored(-((IFluxStorage)tileEntity).receiveEnergy(side.Opposite, eout, false, dt)); }
protected virtual void FindOutputConnections() { //BlockFacing probably has useful stuff to do this right foreach (BlockFacing bf in distributionFaces) { BlockPos bp = Pos.Copy().Offset(bf); BlockEntity checkblock = Api.World.BlockAccessor.GetBlockEntity(bp); var bee = checkblock as IElectricity; if (bee == null) { continue; } if (bee.TryInputConnection(this) && !outputConnections.Contains(bee)) { outputConnections.Add(bee); } } }
public override void Initialize(ICoreAPI api) { var bh = GetBehavior <BEBehaviorBurning>(); // Make sure the kiln doesn't burn longer than intended (e.g. when exported from an old world and imported into a new world) if (Lit) { BurningUntilTotalHours = Math.Min(api.World.Calendar.TotalHours + BurnTimeHours, BurningUntilTotalHours); } bh.OnFireTick = (dt) => { if (api.World.Calendar.TotalHours >= BurningUntilTotalHours) { if (IsAreaLoaded()) // Wait until nearby chunks area loaded before firing fully { OnFired(); } } }; bh.OnFireDeath = KillFire; bh.ShouldBurn = () => Lit; bh.OnCanBurn = (pos) => { if (pos == Pos && !Lit && IsComplete) { return(true); } Block block = Api.World.BlockAccessor.GetBlock(pos); Block upblock = Api.World.BlockAccessor.GetBlock(Pos.UpCopy()); return(block?.CombustibleProps != null && block.CombustibleProps.BurnDuration > 0 && (!IsAreaLoaded() || upblock.Replaceable >= 6000)); }; base.Initialize(api); DetermineBuildStages(); bh.FuelPos = Pos.Copy(); bh.FirePos = Pos.UpCopy(); }
public virtual float GetPerishRate() { BlockPos sealevelpos = Pos.Copy(); sealevelpos.Y = Api.World.SeaLevel; ClimateCondition cond = Api.World.BlockAccessor.GetClimateAt(sealevelpos); if (cond == null) { return(1); } float soilTempWeight = 0f; if (room.ExitCount == 0) { soilTempWeight = 0.5f + 0.5f * (1 - GameMath.Clamp((float)room.NonCoolingWallCount / Math.Max(1, room.CoolingWallCount), 0, 1)); } int lightlevel = Api.World.BlockAccessor.GetLightLevel(Pos, EnumLightLevelType.OnlySunLight); // light level above 12 makes it additionally warmer, especially when part of a cellar float airTemp = cond.Temperature + GameMath.Clamp(lightlevel - 11, 0, 10) * (1f + 5 * soilTempWeight); // Lets say deep soil temperature is a constant 5°C float cellarTemp = 5; // How good of a cellar it is depends on how much rock or soil was used on he cellars walls float hereTemp = GameMath.Lerp(airTemp, cellarTemp, soilTempWeight); // For fairness lets say if its colder outside, use that temp instead hereTemp = Math.Min(hereTemp, airTemp); // Some neat curve to turn the temperature into a spoilage rate // http://fooplot.com/#W3sidHlwZSI6MCwiZXEiOiJtYXgoMC4xLG1pbigyLjUsM14oeC8xOS0xLjIpKS0wLjEpIiwiY29sb3IiOiIjMDAwMDAwIn0seyJ0eXBlIjoxMDAwLCJ3aW5kb3ciOlsiLTIwIiwiNDAiLCIwIiwiMyJdLCJncmlkIjpbIjIuNSIsIjAuMjUiXX1d // max(0.1, min(2.5, 3^(x/15 - 1.2))-0.1) float rate = Math.Max(0.1f, Math.Min(2.4f, (float)Math.Pow(3, hereTemp / 19 - 1.2) - 0.1f)); return(rate); }
protected override void DoDeviceComplete() { deviceState = enDeviceState.IDLE; Block outputItem = Api.World.GetBlock(new AssetLocation(recipe)); if (outputItem == null) { deviceState = enDeviceState.ERROR; return; } ItemStack outputStack = new ItemStack(outputItem, outputQuantiy); dummy[0].Itemstack = outputStack; BlockPos bp = Pos.Copy().Offset(outputFace); BlockEntity checkblock = Api.World.BlockAccessor.GetBlockEntity(bp); var outputContainer = checkblock as BlockEntityContainer; if (outputContainer != null) { WeightedSlot tryoutput = outputContainer.Inventory.GetBestSuitedSlot(dummy[0]); if (tryoutput != null) { ItemStackMoveOperation op = new ItemStackMoveOperation(Api.World, EnumMouseButton.Left, 0, EnumMergePriority.DirectMerge, outputQuantiy); int qmoved = dummy[0].TryPutInto(tryoutput.slot, ref op); } } if (!dummy.Empty) { //If no storage then spill on the ground Vec3d pos = Pos.ToVec3d(); dummy.DropAll(pos); } Api.World.PlaySoundAt(new AssetLocation("sounds/doorslide"), Pos.X, Pos.Y, Pos.Z, null, false, 8, 1); if (Api.World.Side == EnumAppSide.Client && animUtil != null) { animUtil.StopAnimation("process"); } }
private static List <Pos> GenShape(int cells) { var pos = new Pos(0, 0); var res = new List <Pos> { }; for (var i = 0; i < cells; i++) { res.Add(pos); pos = pos.Copy(); if (UnityEngine.Random.value > 0.5f) { pos.X++; } else { pos.Y++; } } return(res); }
protected void transferEnergy(BlockFacing side, float dt) { if (sideConfig[side] != IOEnergySideConfig.OUTPUT) { return; } BlockPos outPos = Pos.Copy().Offset(side); BlockEntity tileEntity = Api.World.BlockAccessor.GetBlockEntity(outPos); if (tileEntity == null) { return; } if (!(tileEntity is IFluxStorage)) { return; } float eout = Math.Min(MyMiniLib.GetAttributeInt(Block, "transfer", 10000) * dt, energyStorage.getEnergyStored() * dt); energyStorage.modifyEnergyStored(-((IFluxStorage)tileEntity).receiveEnergy(side.Opposite, eout, false, dt)); }
public void OnTick(float df) { //check for an IElectricty block below, and if it has power mark true // flag block to update if necessary bool currentstate = false; BlockPos bp = Pos.Copy().Offset(BlockFacing.DOWN); BlockEntity checkblock = Api.World.BlockAccessor.GetBlockEntity(bp); var bee = checkblock as IElectricity; if (bee != null) { if (bee.IsPowered) { currentstate = true; } } if (laststate != currentstate) { laststate = currentstate; MarkDirty(true); } //update the block }
public void MakeAutonomousMove() { Room room = findRoom(); Room heroRoom = Dungeon.Hero.findRoom(); bool heroInNextRoom = false; if (room == heroRoom) { target = Dungeon.Hero.Pos.Copy(); Console.WriteLine(""); } else { foreach (KeyValuePair <Point, Room> pair in room.Doors) { if (pair.Value == heroRoom) { heroInNextRoom = true; target = pair.Key; break; } } } /* if (!heroInNextRoom) { * if (target.X != -1000) { * * } * int numberOfDoors = room.Doors.Count; * var random = new Random(); * if (numberOfDoors == 1) * { * target = room.Doors[1]; * }; * } */ if (Pos.Copy() == target) { if (heroRoom.isInside(new Point(target.X + 1, target.Y))) { target = new Point(target.X + 1, target.Y); } else if (heroRoom.isInside(new Point(target.X, target.Y + 1))) { target = new Point(target.X, target.Y + 1); } else if (heroRoom.isInside(new Point(target.X - 1, target.Y))) { target = new Point(target.X - 1, target.Y); } else if (heroRoom.isInside(new Point(target.X, target.Y - 1))) { target = new Point(target.X, target.Y - 1); } } if (target.X == -1000) { return; } Point oldPos = Pos; int distNorth = Math.Abs(target.X - Pos.X) + Math.Abs(target.Y - Pos.Y - 1); int distSouth = Math.Abs(target.X - Pos.X) + Math.Abs(target.Y - Pos.Y + 1); int distWest = Math.Abs(target.X - Pos.X - 1) + Math.Abs(target.Y - Pos.Y); int distEast = Math.Abs(target.X - Pos.X + 1) + Math.Abs(target.Y - Pos.Y); if (heroInNextRoom) { target = new Point(-1000, -1000); } int min = Math.Min(Math.Min(distNorth, distSouth), Math.Min(distEast, distWest)); Direction dir; if (min == distNorth) { dir = Direction.SOUTH; } else if (min == distSouth) { dir = Direction.NORTH; } else if (min == distWest) { dir = Direction.EAST; } else { dir = Direction.WEST; } TryMove(dir); previousDoor = target.Copy(); if (Dungeon.Hero.Pos == Pos) { Dungeon.Hero.TakeDamage(GetDamageLevel()); Console.WriteLine("Hero health at {0}", Dungeon.Hero.Health); if (!Dungeon.Hero.IsDead()) { Pos = oldPos; } else { Console.WriteLine("GAME OVER"); } } }
protected void FetchMaterial() { internalQuantity = Math.Min(internalQuantity, inputQuantity); //this shouldn't be necessary BlockPos bp = Pos.Copy().Offset(rmInputFace); BlockEntity checkblock = Api.World.BlockAccessor.GetBlockEntity(bp); var inputContainer = checkblock as BlockEntityContainer; if (inputContainer == null) { return; } if (inputContainer.Inventory.Empty) { return; } for (int c = 0; c < inputContainer.Inventory.Count; c++) { ItemSlot checkslot = inputContainer.Inventory[c]; if (checkslot == null) { continue; } if (checkslot.StackSize < inputQuantity) { continue; } bool match = false; Item checkitem = checkslot.Itemstack.Item; Block checkiblock = checkslot.Itemstack.Block; ingredient_subtype = ""; if (checkitem == null && checkiblock == null) { continue; } if (checkitem != null) { string fcp = checkitem.FirstCodePart().ToString(); string lcp = checkitem.LastCodePart().ToString(); //no materials list so we don't need check for subtypes if (checkitem.Code.ToString() == ingredient) { match = true; } else if (checkitem.FirstCodePart() == ingredient && (materials == null || materials.Length == 0)) { match = true; } else if (checkitem.FirstCodePart().ToString() == ingredient && materials.Contains(checkitem.LastCodePart().ToString())) { match = true; ingredient_subtype = checkitem.LastCodePart(); } } else if (checkiblock != null) { if (checkiblock.Code.ToString() == ingredient) { match = true; } else if (checkiblock.FirstCodePart().ToString() == ingredient && (materials == null || materials.Length == 0)) { match = true; } else if (checkiblock.FirstCodePart().ToString() == ingredient && materials.Contains(checkiblock.LastCodePart().ToString())) { match = true; ingredient_subtype = checkiblock.LastCodePart(); } } if (match) { bool heatok = true; lastheatreading = checkslot.Itemstack.Collectible.GetTemperature(Api.World, checkslot.Itemstack); if (heatRequirement > 0 && lastheatreading < heatRequirement) { heatok = false; } if (heatok) { int reqQty = Math.Min(checkslot.StackSize, inputQuantity - internalQuantity); checkslot.TakeOut(reqQty); internalQuantity += reqQty; checkslot.MarkDirty(); } } } return; }
internal void UpdateVoxel(IPlayer byPlayer, ItemSlot itemslot, Vec3i voxelPos, BlockFacing facing, bool isBreak) { if (!Api.World.Claims.TryAccess(byPlayer, Pos, EnumBlockAccessFlags.Use)) { MarkDirty(true, byPlayer); return; } EnumChiselMode mode = GetChiselMode(byPlayer); bool wasChanged = false; byte[] lightHsv = this.LightHsv; switch (mode) { case EnumChiselMode.Rename: IClientWorldAccessor clientWorld = (IClientWorldAccessor)Api.World; string prevName = BlockName; GuiDialogBlockEntityTextInput dlg = new GuiDialogBlockEntityTextInput(Lang.Get("Block name"), Pos, BlockName, Api as ICoreClientAPI, 500); dlg.OnTextChanged = (text) => BlockName = text; dlg.OnCloseCancel = () => BlockName = prevName; dlg.TryOpen(); break; case EnumChiselMode.Flip: FlipVoxels(Block.SuggestedHVOrientation(byPlayer, new BlockSelection() { Position = Pos.Copy(), HitPosition = new Vec3d(voxelPos.X / 16.0, voxelPos.Y / 16.0, voxelPos.Z / 16.0) })[0]); wasChanged = true; break; case EnumChiselMode.Rotate: RotateModel(isBreak ? 90 : -90, null); wasChanged = true; break; default: int size = GetChiselSize(byPlayer); Vec3i addAtPos = voxelPos.Clone().Add(size * facing.Normali.X, size * facing.Normali.Y, size * facing.Normali.Z); if (isBreak) { wasChanged = SetVoxel(voxelPos, false, byPlayer, nowmaterialIndex); } else { if (addAtPos.X >= 0 && addAtPos.X < 16 && addAtPos.Y >= 0 && addAtPos.Y < 16 && addAtPos.Z >= 0 && addAtPos.Z < 16) { wasChanged = SetVoxel(addAtPos, true, byPlayer, nowmaterialIndex); } } break; } if (!wasChanged) { return; } if (Api.Side == EnumAppSide.Client) { RegenMesh(); } RegenSelectionBoxes(byPlayer); MarkDirty(true, byPlayer); // Send a custom network packet for server side, because // serverside blockselection index is inaccurate if (Api.Side == EnumAppSide.Client) { SendUseOverPacket(byPlayer, voxelPos, facing, isBreak); } double posx = Pos.X + voxelPos.X / 16f; double posy = Pos.Y + voxelPos.Y / 16f; double posz = Pos.Z + voxelPos.Z / 16f; Api.World.PlaySoundAt(new AssetLocation("sounds/player/knap" + (Api.World.Rand.Next(2) > 0 ? 1 : 2)), posx, posy, posz, byPlayer, true, 12, 1); if (byPlayer.WorldData.CurrentGameMode != EnumGameMode.Creative && Api.World.Rand.Next(3) == 0) { itemslot.Itemstack?.Collectible.DamageItem(Api.World, byPlayer.Entity, itemslot); } if (VoxelCuboids.Count == 0) { Api.World.BlockAccessor.SetBlock(0, Pos); Api.World.BlockAccessor.RemoveBlockLight(LightHsv, Pos); return; } }
//will check and see if there's enough water, and will use water if necessary bool CheckWater() { //find a block with water //if there is water check and see if it's time to use up some water //assume if we had water before (or just started) that there is water //TODO - need to add haswater, lastwaterused to treeattributes double nextwater = lastwaterused + waterUsePeriod; double currenttime = Api.World.Calendar.TotalHours; if (currenttime < nextwater && haswater) { return(true); } haswater = false; lastwaterused = currenttime; BlockPos bp = Pos.Copy().Offset(waterFace); BlockEntity checkblock = Api.World.BlockAccessor.GetBlockEntity(bp); if (checkblock == null) { haswater = false; return(false); } var checkcontainer = checkblock as BlockEntityContainer; if (checkcontainer != null) { for (int c = 0; c < checkcontainer.Inventory.Count; c++) { ItemSlot checkslot = checkcontainer.Inventory[c]; if (checkslot == null) { continue; } if (checkslot.StackSize == 0) { continue; } bool match = false; if (checkslot.Itemstack.Item != null && checkslot.Itemstack.Item.Code.ToString().Contains("waterportion")) { match = true; } if (match && checkslot.StackSize > 0) { checkslot.TakeOut(1); if (checkslot.StackSize < 5) { Api.World.PlaySoundAt(new AssetLocation("sounds/waterslosh"), Pos.X, Pos.Y, Pos.Z, null, false, 8, 1); } else { Api.World.PlaySoundAt(new AssetLocation("sounds/steamburst"), Pos.X, Pos.Y, Pos.Z, null, false, 8, 1); } checkslot.MarkDirty(); haswater = true; break; } } } return(haswater); }
public virtual bool DoGeneratePower() { if (!isOn) { return(false); } if (!usesFuel) { return(true); } //if we don't use fuel, we can make power if (capacitor == capacitance && !usesFuelWhileOn) { return(false); } //not necessary to generate power if (fueled && fuelCounter < fuelTicks) //on going burning of current fuel item { fuelCounter++; return(true); } //Now we begin trying to fuel fueled = false; fuelCounter = 0; BlockPos bp = Pos.Copy().Offset(fuelHopperFace); BlockEntity checkblock = Api.World.BlockAccessor.GetBlockEntity(bp); var inputContainer = checkblock as BlockEntityContainer; if (inputContainer == null) { return(false); } //no fuel container at all if (inputContainer.Inventory.Empty) { return(false); } //the fuel container is empty //check each inventory slot in the container for (int c = 0; c < inputContainer.Inventory.Count; c++) { ItemSlot checkslot = inputContainer.Inventory[c]; if (checkslot == null) { continue; } if (checkslot.StackSize == 0) { continue; } bool match = false; if (checkslot.Itemstack.Item != null && fuelCodes.Contains(checkslot.Itemstack.Item.Code.ToString())) { match = true; } else if (checkslot.Itemstack.Block != null && fuelCodes.Contains(checkslot.Itemstack.Block.Code.ToString())) { match = true; } if (match && checkslot.StackSize > 0) { checkslot.TakeOut(1); checkslot.MarkDirty(); fueled = true; } } return(fueled); }
public virtual float GetPerishRate() { // ##TODO: for performance the cond.Temperature can be saved in a field for each BlockEntityContainer, worldgen climage values at a position will not change // ##TODO: for performance, perishRate can be cached instead of being re-calculated for each separate slot which is updated BlockPos sealevelpos = Pos.Copy(); sealevelpos.Y = Api.World.SeaLevel; // ##TODO: this ought to be season specific, i.e. perishrate should rise on a hot summer day ClimateCondition cond = Api.World.BlockAccessor.GetClimateAt(sealevelpos); if (cond == null) { return(1); } if (room == null) { room = roomReg.GetRoomForPosition(Pos); } float soilTempWeight = 0f; float skyLightProportion = (float)room.SkylightCount / Math.Max(1, room.SkylightCount + room.NonSkylightCount); // avoid any risk of divide by zero if (room.IsSmallRoom) { soilTempWeight = 1f; // If there's too much skylight, it's less cellar-like soilTempWeight -= 0.4f * skyLightProportion; // If non-cooling blocks exceed cooling blocks, it's less cellar-like soilTempWeight -= 0.5f * GameMath.Clamp((float)room.NonCoolingWallCount / Math.Max(1, room.CoolingWallCount), 0f, 1f); } int lightlevel = Api.World.BlockAccessor.GetLightLevel(Pos, EnumLightLevelType.OnlySunLight); // light level above 12 makes it additionally warmer, especially when part of a cellar or a greenhouse float lightImportance = 0.1f; // light in small fully enclosed rooms has a big impact if (room.IsSmallRoom) { lightImportance += 0.3f * soilTempWeight + 1.75f * skyLightProportion; } // light in large most enclosed rooms (e.g. houses, greenhouses) has medium impact else if (room.ExitCount <= 0.1f * (room.CoolingWallCount + room.NonCoolingWallCount)) { lightImportance += 1.25f * skyLightProportion; } // light outside rooms (e.g. chests on world surface) has low impact but still warms them above base air temperature else { lightImportance += 0.5f * skyLightProportion; } lightImportance = GameMath.Clamp(lightImportance, 0f, 1.5f); float airTemp = cond.Temperature + GameMath.Clamp(lightlevel - 11, 0, 10) * lightImportance; // Lets say deep soil temperature is a constant 5°C // ##TODO: this ought to depend on worldgen climate: in the Arctic for example, deep soil temperature is going to be lower ... // ##TODO: this ought to be based on depth below worldgen original world surface float cellarTemp = 5; // How good of a cellar it is depends on how much rock or soil was used on he cellars walls float hereTemp = GameMath.Lerp(airTemp, cellarTemp, soilTempWeight); // For fairness lets say if its colder outside, use that temp instead hereTemp = Math.Min(hereTemp, airTemp); // Some neat curve to turn the temperature into a spoilage rate // http://fooplot.com/#W3sidHlwZSI6MCwiZXEiOiJtYXgoMC4xLG1pbigyLjUsM14oeC8xOS0xLjIpKS0wLjEpIiwiY29sb3IiOiIjMDAwMDAwIn0seyJ0eXBlIjoxMDAwLCJ3aW5kb3ciOlsiLTIwIiwiNDAiLCIwIiwiMyJdLCJncmlkIjpbIjIuNSIsIjAuMjUiXX1d // max(0.1, min(2.5, 3^(x/15 - 1.2))-0.1) float rate = Math.Max(0.1f, Math.Min(2.4f, (float)Math.Pow(3, hereTemp / 19 - 1.2) - 0.1f)); return(rate); }