コード例 #1
0
        private void DestroyGrownMushrooms()
        {
            mushroomsDiedTotalDays = Api.World.Calendar.TotalDays;
            foreach (var offset in grownMushroomOffsets)
            {
                BlockPos pos   = Pos.AddCopy(offset);
                var      block = Api.World.BlockAccessor.GetBlock(pos);
                if (block.Variant["mushroom"] == mushroomBlock.Variant["mushroom"])
                {
                    Api.World.BlockAccessor.SetBlock(0, pos);
                }
            }

            grownMushroomOffsets = new Vec3i[0];
        }
コード例 #2
0
        public bool nearToClaimedLand()
        {
            int              rad       = (int)Math.Ceiling(BlastRadius);
            Cuboidi          exploArea = new Cuboidi(Pos.AddCopy(-rad, -rad, -rad), Pos.AddCopy(rad, rad, rad));
            List <LandClaim> claims    = (Api as ICoreServerAPI).WorldManager.SaveGame.LandClaims;

            for (int i = 0; i < claims.Count; i++)
            {
                if (claims[i].Intersects(exploArea))
                {
                    return(true);
                }
            }
            return(false);
        }
コード例 #3
0
 private void SelectLeakingLog()
 {
     foreach (int i in new int[] { -1, 1 })
     {
         int[] vectorX = { i, 0, 0 };
         int[] vectorZ = { 0, 0, i };
         foreach (int[] j in new int[][] { vectorX, vectorZ })
         {
             BlockPos blockPos     = Pos.AddCopy(j[0], j[1], j[2]);
             Block    leakingBlock = Api.World.BlockAccessor.GetBlock(blockPos);
             if (CheckLeakingLogBlock(leakingBlock, false))
             {
                 LeakingLogBlockPos = blockPos;
                 UpdateTransientProps(blockPos);
             }
         }
     }
 }
コード例 #4
0
        internal void InteractDebug()
        {
            if (RootOff.Y != 0)
            {
                return;
            }

            var rootBe = (Api.World.BlockAccessor.GetBlockEntity(Pos.AddCopy(RootOff)) as BlockEntityFruitTreeBranch)?.GetBehavior <FruitTreeRootBH>();

            if (rootBe != null)
            {
                foreach (var val in rootBe.propsByType)
                {
                    val.Value.State = (EnumFruitTreeState)(((int)val.Value.State + 1) % ((int)EnumFruitTreeState.Dead));
                }
            }

            MarkDirty(true);
        }
コード例 #5
0
ファイル: BEChute.cs プロジェクト: curquhart/vssurvivalmod
        private void MoveItem(float dt)
        {
            for (int d = 0; d < 6; d++)
            {
                if (inventory.IsEmpty)
                {
                    break;                        //don't need to check for output if we don't have anything to output.
                }
                if (DirectionalMask[d] && d != 4) //means we're dealing with an output face if this is true.  Also no going back up.
                {
                } //Checking for Up
            } //

            if (DirectionalMask[4])
            {
                //pull.
                BlockEntity target = Api.World.BlockAccessor.GetBlockEntity(Pos.AddCopy(BlockFacing.UP));
            } //checking for UP
        }
コード例 #6
0
        private void OnTick(float dt)
        {
            if (Api.Side == EnumAppSide.Server)
            {
                remainingBurnDuration -= dt;

                if (remainingBurnDuration <= 0)
                {
                    BlockPos fuelPos   = Pos.AddCopy(fromFacing.Opposite);
                    Block    fuelBlock = Api.World.BlockAccessor.GetBlock(fuelPos);

                    if (canBurn(fuelBlock, fuelPos))
                    {
                        TrySpreadTo(fuelPos, fromFacing);
                    }

                    Api.World.BlockAccessor.SetBlock(0, Pos);
                    Api.World.BlockAccessor.RemoveBlockEntity(Pos); // Sometimes block entities don't get removed properly o.O
                    Api.World.BlockAccessor.TriggerNeighbourBlockUpdate(Pos);
                    return;
                }

                float spreadChance = (TimePassed - 2.5f) / 450f;

                if (((ICoreServerAPI)Api).Server.Config.AllowFireSpread && spreadChance > Api.World.Rand.NextDouble())
                {
                    TrySpreadFire();
                }
            }

            if (Api.Side == EnumAppSide.Client)
            {
                int index = Math.Min(fireBlock.ParticleProperties.Length - 1, Api.World.Rand.Next(fireBlock.ParticleProperties.Length + 1));
                AdvancedParticleProperties particles = fireBlock.ParticleProperties[index];
                particles.basePos = RandomBlockPos(Api.World.BlockAccessor, Pos.AddCopy(fromFacing.Opposite), neibBlock, fromFacing);

                particles.Quantity.avg     = 0.75f;
                particles.TerrainCollision = false;
                Api.World.SpawnParticles(particles);
                particles.Quantity.avg = 0;
            }
        }
コード例 #7
0
        void TriggerPileChanged()
        {
            if (Api.Side != EnumAppSide.Server)
            {
                return;
            }

            int maxSteepness = 4;

            BlockCoalPile belowcoalpile = Api.World.BlockAccessor.GetBlock(Pos.DownCopy()) as BlockCoalPile;
            int           belowwlayers  = belowcoalpile == null ? 0 : belowcoalpile.GetLayercount(Api.World, Pos.DownCopy());

            foreach (var face in BlockFacing.HORIZONTALS)
            {
                BlockPos      npos                 = Pos.AddCopy(face);
                Block         nblock               = Api.World.BlockAccessor.GetBlock(npos);
                BlockCoalPile nblockcoalpile       = Api.World.BlockAccessor.GetBlock(npos) as BlockCoalPile;
                int           nblockcoalpilelayers = nblockcoalpile == null ? 0 : nblockcoalpile.GetLayercount(Api.World, npos);

                // When should it collapse?
                // When there layers > 3 and nearby is air or replacable
                // When nearby is coal and herelayers - neiblayers > 3
                // When there is coal below us, the neighbour below us is coal, nearby is air or replaceable, and owncoal+belowcoal - neibbelowcoal > 3

                int layerdiff = Math.Max(nblock.Replaceable > 6000 ? Math.Max(0, Layers - maxSteepness) : 0, (nblockcoalpile != null ? Layers - nblockcoalpilelayers - maxSteepness : 0));

                if (belowwlayers > 0)
                {
                    BlockCoalPile nbelowblockcoalpile = Api.World.BlockAccessor.GetBlock(npos.DownCopy()) as BlockCoalPile;
                    int           nbelowwlayers       = nbelowblockcoalpile == null ? 0 : nbelowblockcoalpile.GetLayercount(Api.World, npos.DownCopy());
                    layerdiff = Math.Max(layerdiff, (nbelowblockcoalpile != null ? Layers + belowwlayers - nbelowwlayers - maxSteepness : 0));
                }

                if (Api.World.Rand.NextDouble() < layerdiff / (float)maxSteepness)
                {
                    if (TryPartialCollapse(npos.UpCopy(), 2))
                    {
                        return;
                    }
                }
            }
        }
コード例 #8
0
        private void TrySpawnPumpkin(double curTotalHours)
        {
            foreach (BlockFacing facing in BlockFacing.HORIZONTALS)
            {
                BlockPos candidatePos = Pos.AddCopy(facing);
                Block    block        = Api.World.BlockAccessor.GetBlock(candidatePos);
                if (!CanReplace(block))
                {
                    continue;
                }

                Block supportBlock = Api.World.BlockAccessor.GetBlock(candidatePos.DownCopy());
                if (CanSupportPumpkin(supportBlock))
                {
                    Api.World.BlockAccessor.SetBlock(pumpkinBlock.BlockId, candidatePos);
                    pumpkinTotalHoursForNextStage[facing] = curTotalHours + pumpkinHoursToGrow;
                    return;
                }
            }
        }
コード例 #9
0
        private void CheckValidToggleAndNotObstructed()
        {
            targetAnvil = Api.World.BlockAccessor.GetBlockEntity(anvilPos) as BlockEntityAnvil;

            obstructed = false;
            if (renderer != null)
            {
                renderer.Obstructed = false;
            }

            mptoggle = Api.World.BlockAccessor.GetBlockEntity(togglePos)?.GetBehavior <BEBehaviorMPToggle>();
            if (mptoggle?.ValidHammerBase(Pos) == false)
            {
                mptoggle   = null;
                obstructed = true;
                if (renderer != null)
                {
                    renderer.Obstructed = true;
                }
                return;
            }

            BlockPos npos = Pos.AddCopy(0, 1, 0);

            for (int i = 0; i < 3; i++)
            {
                Block     block     = Api.World.BlockAccessor.GetBlock(npos);
                Cuboidf[] collboxes = block.GetCollisionBoxes(Api.World.BlockAccessor, npos);
                if (collboxes != null && collboxes.Length > 0)
                {
                    obstructed = true;
                    if (renderer != null)
                    {
                        renderer.Obstructed = true;
                    }
                    break;
                }

                npos.Add(facing.Normali);
            }
        }
コード例 #10
0
ファイル: BECoalPile.cs プロジェクト: curquhart/vssurvivalmod
        private bool TestCokable()
        {
            var bl = Api.World.BlockAccessor;

            bool haveDoor = false;

            foreach (var facing in BlockFacing.HORIZONTALS)
            {
                Block block = bl.GetBlock(Pos.AddCopy(facing));
                haveDoor |= block is BlockCokeOvenDoor && block.Variant["state"] == "closed";
            }

            int brickCount = 0;

            bl.WalkBlocks(Pos.AddCopy(-1, -1, -1), Pos.AddCopy(1, 1, 1), (block, pos) =>
            {
                brickCount += block.Attributes?["cokeOvenViable"].AsBool(true) == true ? 1 : 0;
            });

            return(haveDoor && brickCount >= 9 + 7 + 7 && bl.GetBlock(Pos.UpCopy()).Attributes?["cokeOvenViable"].AsBool(true) == true);
        }
コード例 #11
0
        public override void Initialize(ICoreAPI api)
        {
            base.Initialize(api);
            Shape  = Block.Shape;
            Facing = BlockFacing.FromCode(Block.Variant["side"]);
            this.transmissionPos = Pos.AddCopy(Facing);

            manager = Api.ModLoader.GetModSystem <MechanicalPowerMod>();
            manager.AddDeviceForRender(this);

            AxisSign = new int[3] {
                0, 0, 0
            };
            switch (Facing.Index)
            {
            case 0:
                AxisSign[0] = -1;
                hinge       = new Vec3f(0.5f, 0f, 0.375f);
                break;

            case 2:
                AxisSign[0] = 1;
                hinge       = new Vec3f(0.5f, 0f, 0.625f);
                break;

            case 1:
                AxisSign[2] = -1;
                hinge       = new Vec3f(0.625f, 0f, 0.5f);
                break;

            default:
                AxisSign[2] = 1;
                break;
            }

            if (api.World.Side == EnumAppSide.Client)
            {
                RegisterGameTickListener(OnClientGameTick, 16);
            }
        }
コード例 #12
0
ファイル: EnergyDuct.cs プロジェクト: Niker323/VS-mods
 public void InitializeEnergyPoint(ICoreAPI api)
 {
     if (api.World.Side == EnumAppSide.Server)
     {
         foreach (BlockFacing face in BlockFacing.ALLFACES)
         {
             BlockPos pos = Pos.AddCopy(face);
             BlockEntityEnergyDuct block = api.World.BlockAccessor.GetBlockEntity(pos) as BlockEntityEnergyDuct;
             if (block != null)
             {
                 if (core == null)
                 {
                     if (block.core == null)
                     {
                         core = new EnergyDuctCore(MyMiniLib.GetAttributeInt(Block, "transfer", 500));
                         core.ducts.Add(this);
                     }
                     else
                     {
                         core = block.core;
                         core.ducts.Add(this);
                     }
                 }
                 else
                 {
                     if (core != block.core && block.core != null)
                     {
                         core = core.CombineCores(block.core);
                     }
                 }
             }
         }
         if (core == null)
         {
             core = new EnergyDuctCore(MyMiniLib.GetAttributeInt(Block, "transfer", 500));
             core.ducts.Add(this);
         }
     }
 }
コード例 #13
0
        private bool TestCokable()
        {
            var bl = Api.World.BlockAccessor;

            bool haveDoor = false;

            foreach (var facing in BlockFacing.HORIZONTALS)
            {
                Block block = bl.GetBlock(Pos.AddCopy(facing));
                haveDoor |= block is BlockCokeOvenDoor && block.Variant["state"] == "closed";
            }

            int centerCount = 0;
            int cornerCount = 0;

            bl.WalkBlocks(Pos.AddCopy(-1, -1, -1), Pos.AddCopy(1, 1, 1), (block, pos) =>
            {
                int dx      = Math.Abs(Pos.X - pos.X);
                int dz      = Math.Abs(Pos.Z - pos.Z);
                bool corner = dx == 1 && dz == 1;

                bool viable = block.Attributes?["cokeOvenViable"].AsBool(true) == true;
                if (viable)
                {
                    centerCount += !corner ? 1 : 0;
                    cornerCount += corner ? 1 : 0;
                }
            });

            // bottom: 5 center, 4 corner
            // mid: 3 center, 1 door, 4 corner
            // top: 5 center, 4 corner
            // 13 center, 12 corner. Allow 4 corner blocks to be missing

            return(haveDoor && centerCount >= 12 && cornerCount >= 8 && bl.GetBlock(Pos.UpCopy()).Attributes?["cokeOvenViable"].AsBool(true) == true);
        }
コード例 #14
0
        private void onServerTick(float dt)
        {
            bool isFruiting = grownMushroomOffsets.Length > 0;

            if (isFruiting && props.DieWhenTempBelow > -99)
            {
                var conds = Api.World.BlockAccessor.GetClimateAt(Pos, EnumGetClimateMode.ForSuppliedDate_TemperatureOnly, Api.World.Calendar.TotalDays);
                if (conds == null)
                {
                    return;
                }
                if (props.DieWhenTempBelow > conds.Temperature)
                {
                    DestroyGrownMushrooms();
                    return;
                }
            }

            if (props.DieAfterFruiting && isFruiting && mushroomsGrownTotalDays + fruitingDays < Api.World.Calendar.TotalDays)
            {
                DestroyGrownMushrooms();
                return;
            }

            if (!isFruiting)
            {
                lastUpdateTotalDays = Math.Max(lastUpdateTotalDays, Api.World.Calendar.TotalDays - 50); // Don't check more than 50 days into the past

                while (Api.World.Calendar.TotalDays - lastUpdateTotalDays > 1)
                {
                    var conds = Api.World.BlockAccessor.GetClimateAt(Pos, EnumGetClimateMode.ForSuppliedDate_TemperatureOnly, lastUpdateTotalDays + 0.5);
                    if (conds == null)
                    {
                        return;
                    }

                    if (conds.Temperature > 5)
                    {
                        mushroomsGrowingDays += Api.World.Calendar.TotalDays - lastUpdateTotalDays;
                    }

                    lastUpdateTotalDays++;
                }

                if (mushroomsGrowingDays > growingDays)
                {
                    growMushrooms(Api.World.BlockAccessor, MyceliumSystem.rndn);
                    mushroomsGrowingDays = 0;
                }
            }
            else
            {
                if (Api.World.Calendar.TotalDays - lastUpdateTotalDays > 0.1)
                {
                    lastUpdateTotalDays = Api.World.Calendar.TotalDays;

                    for (int i = 0; i < grownMushroomOffsets.Length; i++)
                    {
                        var offset = grownMushroomOffsets[i];
                        var pos    = Pos.AddCopy(offset);
                        var chunk  = Api.World.BlockAccessor.GetChunkAtBlockPos(pos);
                        if (chunk == null)
                        {
                            return;
                        }

                        if (!Api.World.BlockAccessor.GetBlock(pos).Code.Equals(mushroomBlockCode))
                        {
                            grownMushroomOffsets = grownMushroomOffsets.RemoveEntry(i);
                            i--;
                        }
                    }
                }
            }
        }
コード例 #15
0
        private void onBurnTick(float dt)
        {
            if (firepitStage == 6 && !IsBurning)
            {
                GetBehavior <BEBehaviorFirepitAmbient>()?.ToggleAmbientSounds(false);
                firepitStage++;
                MarkDirty(true);
            }

            if (IsBurning)
            {
                heatLiquid(dt);
            }

            double dh = Api.World.Calendar.TotalHours - lastTickTotalHours;

            if (dh > 0.1f)
            {
                if (IsBurning)
                {
                    fuelHours -= (float)dh;
                }
                lastTickTotalHours = Api.World.Calendar.TotalHours;
            }


            var props = DistProps;

            if (InputStackTemp >= 75 && props != null)
            {
                distillationAccum += dt * props.Ratio;

                if (distillationAccum >= 0.2f)
                {
                    distillationAccum -= 0.2f;

                    for (int i = 0; i < 4; i++)
                    {
                        BlockEntityCondenser becd = Api.World.BlockAccessor.GetBlockEntity(Pos.AddCopy(BlockFacing.HORIZONTALS[i])) as BlockEntityCondenser;
                        if (becd != null)
                        {
                            props?.DistilledStack.Resolve(Api.World, "distillationprops");
                            if (becd.ReceiveDistillate(inventory[0], props))
                            {
                                break;
                            }
                        }
                    }
                }
            }
        }
コード例 #16
0
ファイル: BEBeehive.cs プロジェクト: curquhart/vssurvivalmod
        private void OnScanForEmptySkep(float dt)
        {
            if (Api.Side == EnumAppSide.Client)
            {
                return;
            }
            if (Api.World.Calendar.TotalHours < cooldownUntilTotalHours)
            {
                return;
            }

            if (scanIteration == 0)
            {
                scanQuantityNearbyFlowers = 0;
                scanQuantityNearbyHives   = 0;
                scanEmptySkeps.Clear();
            }

            // Let's count/collect 3 things in a 20x20x20 cube
            // 1. All positions of empty skeps
            // 2. Amount of living beehives (skeps or wild)
            // 3. Amount of flowers

            // Default Spread speed: Once every 4 in game days * factor
            // Don't spread at all if 3 * livinghives + 3 > flowers

            // factor = Clamped(livinghives / Math.Sqrt(flowers - 3 * livinghives - 3), 1, 1000)
            // After spreading: 4 extra days cooldown

            int minX = -8 + 8 * (scanIteration / 2);
            int minZ = -8 + 8 * (scanIteration % 2);
            int size = 8;

            Block emptySkepN = Api.World.GetBlock(new AssetLocation("skep-empty-north"));
            Block emptySkepE = Api.World.GetBlock(new AssetLocation("skep-empty-east"));
            Block emptySkepS = Api.World.GetBlock(new AssetLocation("skep-empty-south"));
            Block emptySkepW = Api.World.GetBlock(new AssetLocation("skep-empty-west"));

            Block fullSkepN = Api.World.GetBlock(new AssetLocation("skep-populated-north"));
            Block fullSkepE = Api.World.GetBlock(new AssetLocation("skep-populated-east"));
            Block fullSkepS = Api.World.GetBlock(new AssetLocation("skep-populated-south"));
            Block fullSkepW = Api.World.GetBlock(new AssetLocation("skep-populated-west"));


            Block wildhive1 = Api.World.GetBlock(new AssetLocation("wildbeehive-medium"));
            Block wildhive2 = Api.World.GetBlock(new AssetLocation("wildbeehive-large"));


            Api.World.BlockAccessor.WalkBlocks(Pos.AddCopy(minX, -5, minZ), Pos.AddCopy(minX + size - 1, 5, minZ + size - 1), (block, pos) =>
            {
                if (block.Id == 0)
                {
                    return;
                }

                if (block.Attributes?.IsTrue("beeFeed") == true)
                {
                    scanQuantityNearbyFlowers++;
                }

                if (block == emptySkepN || block == emptySkepE || block == emptySkepS || block == emptySkepW)
                {
                    scanEmptySkeps.Add(pos.Copy());
                }
                if (block == fullSkepN || block == fullSkepE || block == fullSkepS || block == fullSkepW || block == wildhive1 || block == wildhive2)
                {
                    scanQuantityNearbyHives++;
                }
            });

            scanIteration++;

            if (scanIteration == 4)
            {
                scanIteration = 0;
                OnScanComplete();
            }
        }
コード例 #17
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);
        }
コード例 #18
0
        private void onServerTick3s(float dt)
        {
            BlockPos coalPilePos      = Pos.DownCopy(2);
            BlockPos othercoalPilePos = coalPilePos.AddCopy(blockScs.Orientation.Opposite);

            bool beforeReceiveHeat       = receivesHeat;
            bool beforeStructureComplete = structureComplete;

            if (!receivesHeat)
            {
                totalHoursLastUpdate = Api.World.Calendar.TotalHours;
            }

            BlockEntityCoalPile becp = Api.World.BlockAccessor.GetBlockEntity(coalPilePos) as BlockEntityCoalPile;
            float leftHeatHoursLeft  = (becp != null && becp.IsBurning) ? becp.GetHoursLeft(totalHoursLastUpdate) : 0f;

            becp = Api.World.BlockAccessor.GetBlockEntity(othercoalPilePos) as BlockEntityCoalPile;
            float rightHeatHoursLeft = (becp != null && becp.IsBurning) ? becp.GetHoursLeft(totalHoursLastUpdate) : 0f;

            receivesHeat = leftHeatHoursLeft > 0 && rightHeatHoursLeft > 0;


            if (processComplete || !IsFull || !hasLid())
            {
                return;
            }

            MultiblockStructure msInUse  = null;
            BlockPos            posInUse = null;

            structureComplete = false;
            if (ms.InCompleteBlockCount(Api.World, Pos) == 0)
            {
                msInUse           = ms;
                posInUse          = Pos;
                structureComplete = true;
            }
            else if (msOpp.InCompleteBlockCount(Api.World, Pos.AddCopy(blockScs.Orientation.Opposite)) == 0)
            {
                msInUse           = msOpp;
                posInUse          = Pos.AddCopy(blockScs.Orientation.Opposite);
                structureComplete = true;
            }

            if (beforeReceiveHeat != receivesHeat || beforeStructureComplete != structureComplete)
            {
                MarkDirty();
            }

            if (receivesHeat)
            {
                if (!structureComplete)
                {
                    return;
                }

                double hoursPassed       = Api.World.Calendar.TotalHours - totalHoursLastUpdate;
                double heatHoursReceived = Math.Max(0, Math.Min(hoursPassed, Math.Min(leftHeatHoursLeft, rightHeatHoursLeft)));

                progress            += heatHoursReceived / 160f;
                totalHoursLastUpdate = Api.World.Calendar.TotalHours;
                MarkDirty();
            }

            if (progress >= 1.0)
            {
                int stacksize = inv[1].Itemstack.StackSize;

                JsonItemStack jstack = inv[1].Itemstack.ItemAttributes?["carburizableProps"]["carburizedOutput"].AsObject <JsonItemStack>(null, Block.Code.Domain);
                if (jstack.Resolve(Api.World, "carburizable output"))
                {
                    inv[0].Itemstack.StackSize -= 8;
                    inv[1].Itemstack            = jstack.ResolvedItemstack.Clone();
                    inv[1].Itemstack.StackSize  = stacksize;
                }
                MarkDirty();

                msInUse.WalkMatchingBlocks(Api.World, posInUse, (block, pos) =>
                {
                    float resis = block.Attributes?["heatResistance"].AsFloat(1) ?? 1;

                    if (Api.World.Rand.NextDouble() > resis)
                    {
                        Block nowblock = Api.World.GetBlock(block.CodeWithVariant("state", "damaged"));
                        Api.World.BlockAccessor.SetBlock(nowblock.Id, pos);
                    }
                });

                processComplete = true;
            }
        }
コード例 #19
0
        private void onBurningTickServer(float dt)
        {
            facings.Shuffle(Api.World.Rand);

            foreach (var val in facings)
            {
                BlockPos npos = Pos.AddCopy(val);

                /*var combprops = Api.World.BlockAccessor.GetBlock(npos).CombustibleProps;
                 * if (combprops != null)
                 * {
                 *  Api.World.BlockAccessor.SetBlock(Api.World.GetBlock(new AssetLocation("fire")).BlockId, npos);
                 *  BlockEntityFire befire = byEntity.World.BlockAccessor.GetBlockEntity(bpos) as BlockEntityFire;
                 *  if (befire != null) befire.Init(blockSel.Face, (byEntity as EntityPlayer).PlayerUID);
                 *
                 *  continue;
                 * }*/

                var becp = Api.World.BlockAccessor.GetBlockEntity(npos) as BlockEntityCoalPile;
                becp?.TryIgnite();

                if (becp != null)
                {
                    if (Api.World.Rand.NextDouble() < 0.75)
                    {
                        break;
                    }
                }
            }

            cokeConversionRate = inventory[0].Itemstack.ItemAttributes?["cokeConversionRate"].AsFloat(0) ?? 0;
            if (cokeConversionRate > 0)
            {
                if (isCokable = TestCokable())
                {
                    if (Api.World.Calendar.TotalHours - burnStartTotalHours > 12)
                    {
                        inventory[0].Itemstack = new ItemStack(Api.World.GetItem(new AssetLocation("coke")), (int)(inventory[0].StackSize * cokeConversionRate));
                        burning = false;
                        UnregisterGameTickListener(listenerId);
                        MarkDirty(true);
                    }
                    else
                    {
                        MarkDirty(false);
                    }

                    return;
                }
            }

            bool changed = false;

            while (Api.World.Calendar.TotalHours - burnStartTotalHours > BurnHoursPerLayer)
            {
                burnStartTotalHours += BurnHoursPerLayer;
                inventory[0].TakeOut(2);

                if (inventory[0].Empty)
                {
                    Api.World.BlockAccessor.SetBlock(0, Pos);
                    break;
                }
                else
                {
                    changed = true;
                }
            }

            if (changed)
            {
                MarkDirty(true);
            }
        }
コード例 #20
0
        private bool TryPushInto(BlockFacing outputFace)
        {
            BlockPos OutputPosition = Pos.AddCopy(outputFace);

            if (Api.World.BlockAccessor.GetBlockEntity(OutputPosition) is BlockEntityContainer beContainer)
            {
                ItemSlot sourceSlot = inventory.FirstOrDefault(slot => !slot.Empty);
                if ((sourceSlot?.Itemstack?.StackSize ?? 0) == 0)
                {
                    return(false);                                               //seems FirstOrDefault() method can sometimes give a slot with stacksize == 0, weird
                }
                int horTravelled = sourceSlot.Itemstack.Attributes.GetInt("chuteQHTravelled");
                int chuteDir     = sourceSlot.Itemstack.Attributes.GetInt("chuteDir");
                sourceSlot.Itemstack.Attributes.RemoveAttribute("chuteQHTravelled");
                sourceSlot.Itemstack.Attributes.RemoveAttribute("chuteDir");

                if (horTravelled >= 2)
                {
                    return(false);                    //chutes can't move items more than 1 block horizontally without a drop
                }
                ItemSlot            targetSlot = beContainer.Inventory.GetAutoPushIntoSlot(outputFace.Opposite, sourceSlot);
                BlockEntityItemFlow beFlow     = beContainer as BlockEntityItemFlow;

                if (targetSlot != null && (beFlow == null || targetSlot.Empty))
                {
                    int quantity = (int)itemFlowAccum;
                    ItemStackMoveOperation op = new ItemStackMoveOperation(Api.World, EnumMouseButton.Left, 0, EnumMergePriority.DirectMerge, quantity);

                    int qmoved = sourceSlot.TryPutInto(targetSlot, ref op);

                    if (qmoved > 0)
                    {
                        if (Api.World.Rand.NextDouble() < 0.2)
                        {
                            Api.World.PlaySoundAt(hopperTumble, Pos.X + 0.5, Pos.Y + 0.5, Pos.Z + 0.5, null, true, 8, 0.5f);
                        }

                        if (beFlow != null)
                        {
                            targetSlot.Itemstack.Attributes.SetInt("chuteQHTravelled", outputFace.IsHorizontal ? (horTravelled + 1) : 0);
                            targetSlot.Itemstack.Attributes.SetInt("chuteDir", outputFace.Index);
                        }
                        else
                        {
                            targetSlot.Itemstack.Attributes.RemoveAttribute("chuteQHTravelled");
                            targetSlot.Itemstack.Attributes.RemoveAttribute("chuteDir");
                        }

                        sourceSlot.MarkDirty();
                        targetSlot.MarkDirty();
                        MarkDirty(false);
                        beFlow?.MarkDirty(false);

                        itemFlowAccum -= qmoved;

                        return(true);
                    }
                    else
                    {
                        //If the push failed, re-apply original chuteDir so that the itemStack still has it for next push attempt
                        sourceSlot.Itemstack.Attributes.SetInt("chuteDir", chuteDir);
                    }
                }
            }

            return(false);
        }