Beispiel #1
0
        public void growthMonitior(float dt)
        {
            //Determines if the plant is ready to blossom
            if (Api.World.BlockAccessor.GetBlock(Pos.DownCopy()).Id != 0)
            {
                return;
            }
            Room room = rmaker?.GetRoomForPosition(Pos);

            greenhouse = (room != null && room.SkylightCount > room.NonSkylightCount && room.ExitCount == 0);

            if (blossomAt > Api.World.Calendar.TotalHours)
            {
                return;
            }
            float temperature = Api.World.BlockAccessor.GetClimateAt(Pos, EnumGetClimateMode.NowValues).Temperature;

            if ((temperature < minTemp || temperature > maxTemp) && !greenhouse)
            {
                blossomAt += 18;
                return;
            }

            Block         self      = Api.World.BlockAccessor.GetBlock(Pos);
            AssetLocation plantCode = self.CodeWithPart("section", 1);
            Block         plant     = Api.World.GetBlock(plantCode);

            Api.World.BlockAccessor.SetBlock(plant.Id, Pos);
            Api.World.BlockAccessor.SetBlock(self.Id, Pos.DownCopy());
        }
Beispiel #2
0
        public override void Initialize(ICoreAPI api)
        {
            base.Initialize(api);

            if (api.Side.IsServer())
            {
                RegisterGameTickListener(dt =>
                {
                    SimpleParticleProperties props = Pos.DownCopy().TemporalEffectAtPos(api);
                    props.MinPos.Add(0, 0.5, 0);
                    api.World.SpawnParticles(props);
                    List <IPlayer> intruders = new List <IPlayer>();

                    if (cooldown && api.World.GetPlayersAround(Pos.ToVec3d(), 13, 13).Any(e => {
                        if (e.PlayerUID == OwnerUID || OwnerUID == null || OwnerUID == "")
                        {
                            return(false);
                        }

                        intruders.Add(e);
                        return(true);
                    }))
                    {
                        LimitCheck();
                        cooldown = false;
                        foreach (var val in intruders)
                        {
                            Breakins.Add(val.PlayerName + " is inside the radius of " + Pos.RelativeToSpawn(api.World).ToVec3i() + " at " + val.Entity.LocalPos.XYZInt.ToBlockPos().RelativeToSpawn(api.World));
                            MarkDirty();
                        }
                        RegisterDelayedCallback(dt2 => cooldown = true, 5000);
                    }
                }, 30);
            }
        }
        public void InitTreeRoot(string treeType, bool callInitialize, ItemStack parentPlantStack = null)
        {
            if (initialized)
            {
                return;
            }
            initialized = true;
            GrowthDir   = BlockFacing.UP;
            PartType    = parentPlantStack?.Collectible.Variant["type"] == "cutting" ? EnumTreePartType.Cutting : EnumTreePartType.Branch;
            RootOff     = new Vec3i();
            TreeType    = treeType;

            if (PartType == EnumTreePartType.Cutting && parentPlantStack != null)
            {
                var  belowBe         = Api.World.BlockAccessor.GetBlockEntity(Pos.DownCopy()) as BlockEntityFruitTreeBranch;
                bool soilBelow       = Api.World.BlockAccessor.GetBlock(Pos.DownCopy()).Fertility > 0;
                bool verticalGrowDir = soilBelow || belowBe != null;

                if (!verticalGrowDir)
                {
                    foreach (var facing in BlockFacing.HORIZONTALS)
                    {
                        var nbe = Api.World.BlockAccessor.GetBlockEntity(Pos.AddCopy(facing)) as BlockEntityFruitTreeBranch;
                        if (nbe != null)
                        {
                            GrowthDir = facing.Opposite;
                            RootOff   = nbe.RootOff.AddCopy(facing);
                            var rootBh = Api.World.BlockAccessor.GetBlockEntity(Pos.AddCopy(RootOff)).GetBehavior <FruitTreeRootBH>();
                            rootBh.RegisterTreeType(treeType);
                            rootBh.propsByType[TreeType].OnFruitingStateChange += RootBh_OnFruitingStateChange;
                            GenMesh();
                        }
                    }
                }
            }


            updateProperties();

            initCustomBehaviors(parentPlantStack, callInitialize);

            var bh = GetBehavior <FruitTreeGrowingBranchBH>();

            if (bh != null)
            {
                bh.VDrive = 3 + (float)Api.World.Rand.NextDouble();
                bh.HDrive = 1;

                if (treeType != null && RootOff?.IsZero == true)
                {
                    var props = GetBehavior <FruitTreeRootBH>().propsByType[TreeType];
                    bh.HDrive *= props.RootSizeMul;
                    bh.VDrive *= props.RootSizeMul;
                }
            }
        }
Beispiel #4
0
        private void UpdateTube(float dt)
        {
            //setup the north mask
            BlockEntityContainer check = Api.World.BlockAccessor.GetBlockEntity(Pos.NorthCopy()) as BlockEntityContainer;

            if (check != null)
            {
                AttachmentMask[0] = check.Inventory is InventoryGeneric;
            }

            //setup the attachment mask
            check = Api.World.BlockAccessor.GetBlockEntity(Pos.SouthCopy()) as BlockEntityContainer;
            if (check != null)
            {
                AttachmentMask[1] = check.Inventory is InventoryGeneric;
            }

            //setup the attachment mask
            check = Api.World.BlockAccessor.GetBlockEntity(Pos.EastCopy()) as BlockEntityContainer;
            if (check != null)
            {
                AttachmentMask[2] = check.Inventory is InventoryGeneric;
            }

            //setup the attachment mask
            check = Api.World.BlockAccessor.GetBlockEntity(Pos.WestCopy()) as BlockEntityContainer;
            if (check != null)
            {
                AttachmentMask[3] = check.Inventory is InventoryGeneric;
            }

            //setup the attachment mask
            check = Api.World.BlockAccessor.GetBlockEntity(Pos.UpCopy()) as BlockEntityContainer;
            if (check != null)
            {
                AttachmentMask[4] = check.Inventory is InventoryGeneric;
            }

            //setup the attachment mask
            check = Api.World.BlockAccessor.GetBlockEntity(Pos.DownCopy()) as BlockEntityContainer;
            if (check != null)
            {
                AttachmentMask[5] = check.Inventory is InventoryGeneric;
            }

            //Elbow default is West and Up
            //3way default is West, South and Up
            //4way default is west, east, south and Up
            //5 way default is NOT down.
            //6 way is yes.
            //cross default is up east down west
            //straight default is east-west
            //T default is East, west, up

            //orient from west as the origin (-x)
        }
        public override void Initialize(ICoreAPI api)
        {
            base.Initialize(api);

            inv.LateInitialize(InventoryClassName + "-" + Pos, api);

            capi = api as ICoreClientAPI;

            if (api.Side == EnumAppSide.Client)
            {
                RegisterGameTickListener(onClientTick50ms, 50);
            }
            else
            {
                RegisterGameTickListener(onServerTick1s, 1000);
            }


            ms    = Block.Attributes["multiblockStructure"].AsObject <MultiblockStructure>();
            msOpp = Block.Attributes["multiblockStructure"].AsObject <MultiblockStructure>();
            int rotYDeg    = 0;
            int rotYDegOpp = 180;

            if (Block.Variant["side"] == "east")   //BlockStoneCoffin only has a BE on north and east variants
            {
                rotYDeg    = 270;
                rotYDegOpp = 90;
            }

            ms.InitForUse(rotYDeg);
            msOpp.InitForUse(rotYDegOpp);

            blockScs = Block as BlockStoneCoffinSection;
            updateSelectiveElements();



            particlePositions[0] = Pos.DownCopy(2);
            particlePositions[1] = particlePositions[0].AddCopy(blockScs.Orientation.Opposite);

            particlePositions[2] = Pos.AddCopy(blockScs.Orientation.GetCW());
            particlePositions[3] = Pos.AddCopy(blockScs.Orientation.GetCCW());

            particlePositions[4] = Pos.AddCopy(blockScs.Orientation.GetCW()).Add(blockScs.Orientation.Opposite);
            particlePositions[5] = Pos.AddCopy(blockScs.Orientation.GetCCW()).Add(blockScs.Orientation.Opposite);

            particlePositions[6] = Pos.UpCopy(1).Add(blockScs.Orientation.Opposite);

            inv.SetSecondaryPos(Pos.AddCopy(blockScs.Orientation.Opposite));
        }
Beispiel #6
0
        private void GenSnowMesh()
        {
            if (SnowCuboids.Count > 0 && SnowLevel > 0)
            {
                SnowMesh = CreateMesh(Api as ICoreClientAPI, SnowCuboids, new int[] { snowLayerBlockId }, Pos);
                SnowMesh.Translate(0, 1 / 16f, 0);

                if (Api.World.BlockAccessor.GetBlock(Pos.DownCopy()).SideSolid[BlockFacing.UP.Index])
                {
                    SnowMesh.AddMeshData(CreateMesh(Api as ICoreClientAPI, GroundSnowCuboids, new int[] { snowLayerBlockId }, Pos));
                }
            }
            else
            {
                SnowMesh = null;
            }
        }
Beispiel #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;
                    }
                }
            }
        }
Beispiel #8
0
        private void OurCheckGrow(float dt)
        {
            if (Api.World.Calendar.TotalHours < totalHoursTillGrowth)
            {
                return;
            }


            string treeCode = Api.World.BlockAccessor.GetBlock(Pos).Variant["wood"];

            string treeGenCode = null;

            if (!FixedTreeGenMapping.TryGetValue(treeCode, out treeGenCode))
            {
                Api.Event.UnregisterGameTickListener(growListenerId);
                return;
            }

            AssetLocation  code = new AssetLocation(treeGenCode);
            ICoreServerAPI sapi = Api as ICoreServerAPI;

            ITreeGenerator gen = null;

            if (!sapi.World.TreeGenerators.TryGetValue(code, out gen))
            {
                Api.Event.UnregisterGameTickListener(growListenerId);
                return;
            }

            Api.World.BlockAccessor.SetBlock(0, Pos);
            Api.World.BulkBlockAccessor.ReadFromStagedByDefault = true;
            float size = 0.6f + (float)Api.World.Rand.NextDouble() * 0.5f;

            sapi.World.TreeGenerators[code].GrowTree(Api.World.BulkBlockAccessor, Pos.DownCopy(), size);

            Api.World.BulkBlockAccessor.Commit();
        }
        private void CheckGrow(float dt)
        {
            if (Api.World.Calendar.TotalHours < totalHoursTillGrowth)
            {
                return;
            }

            ClimateCondition conds = Api.World.BlockAccessor.GetClimateAt(Pos, EnumGetClimateMode.NowValues);

            if (conds == null || conds.Temperature < 5)
            {
                return;
            }

            if (conds.Temperature < 0)
            {
                totalHoursTillGrowth = Api.World.Calendar.TotalHours + (float)Api.World.Rand.NextDouble() * 72 * GrowthRateMod;
                return;
            }

            if (stage == EnumTreeGrowthStage.Seed)
            {
                stage = EnumTreeGrowthStage.Sapling;
                totalHoursTillGrowth = Api.World.Calendar.TotalHours + nextStageDaysRnd.nextFloat(1, Api.World.Rand) * 24 * GrowthRateMod;
                MarkDirty(true);
                return;
            }

            int chunksize = Api.World.BlockAccessor.ChunkSize;

            foreach (BlockFacing facing in BlockFacing.HORIZONTALS)
            {
                Vec3i dir = facing.Normali;
                int   x   = Pos.X + dir.X * chunksize;
                int   z   = Pos.Z + dir.Z * chunksize;

                // Not at world edge and chunk is not loaded? We must be at the edge of loaded chunks. Wait until more chunks are generated
                if (Api.World.BlockAccessor.IsValidPos(x, Pos.Y, z) && Api.World.BlockAccessor.GetChunkAtBlockPos(x, Pos.Y, z) == null)
                {
                    return;
                }
            }

            Block  block       = Api.World.BlockAccessor.GetBlock(Pos);
            string treeGenCode = block.Attributes?["treeGen"].AsString(null);

            if (treeGenCode == null)
            {
                Api.Event.UnregisterGameTickListener(growListenerId);
                return;
            }

            AssetLocation  code = new AssetLocation(treeGenCode);
            ICoreServerAPI sapi = Api as ICoreServerAPI;

            ITreeGenerator gen;

            if (!sapi.World.TreeGenerators.TryGetValue(code, out gen))
            {
                Api.Event.UnregisterGameTickListener(growListenerId);
                return;
            }

            Api.World.BlockAccessor.SetBlock(0, Pos);
            Api.World.BulkBlockAccessor.ReadFromStagedByDefault = true;
            float size = 0.6f + (float)Api.World.Rand.NextDouble() * 0.5f;

            sapi.World.TreeGenerators[code].GrowTree(Api.World.BulkBlockAccessor, Pos.DownCopy(), true, size, 0, 0);

            Api.World.BulkBlockAccessor.Commit();
        }
Beispiel #10
0
        private void OnEvery250Ms(float dt)
        {
            // Random checks for breaking this block if heavy entity above and unsupported below

            IWorldAccessor world = Api.World;
            Vec3d          pos3d = center.AddCopy(Pos);
            BlockPos       down  = Pos.DownCopy();

            // If this block is unsupported, do an entity weight + block breaking check
            if (!CheckSupport(world.BlockAccessor, down))
            {
                Entity[] entities = world.GetEntitiesAround(pos3d, 1.0f, 1.5f, (e) => (e?.Properties.Weight > WEIGHTLIMIT));
                for (int i = 0; i < entities.Length; i++)
                {
                    Entity    entity = entities[i];
                    Cuboidd   eBox   = new Cuboidd();
                    EntityPos pos    = entity.Pos;
                    eBox.Set(entity.SelectionBox).Translate(pos.X, pos.Y, pos.Z);

                    Cuboidf bBox = new Cuboidf();
                    bBox.Set(this.Block.CollisionBoxes[0]);
                    bBox.Translate(Pos.X, Pos.Y, Pos.Z);

                    // Check entity yPos actually intersects with this block (approximately)
                    if (eBox.MinY <= bBox.MaxY + 0.01 && eBox.MinY >= bBox.MinY - 0.01)
                    {
                        // Check whether supported enough on any surrounding side
                        bool checkSouth = eBox.MaxZ > bBox.Z2;
                        bool checkNorth = eBox.MinZ < bBox.Z1;
                        bool checkWest  = eBox.MinX < bBox.X1;
                        bool checkEast  = eBox.MinZ > bBox.X2;

                        bool           supported = false;
                        IBlockAccessor access    = world.BlockAccessor;
                        if (checkEast)
                        {
                            supported |= CheckSupport(access, down.EastCopy());
                        }
                        if (checkEast && checkNorth)
                        {
                            supported |= CheckSupport(access, down.EastCopy().North());
                        }
                        if (checkEast && checkSouth)
                        {
                            supported |= CheckSupport(access, down.EastCopy().South());
                        }
                        if (checkWest)
                        {
                            supported |= CheckSupport(access, down.WestCopy());
                        }
                        if (checkWest && checkNorth)
                        {
                            supported |= CheckSupport(access, down.WestCopy().North());
                        }
                        if (checkWest && checkSouth)
                        {
                            supported |= CheckSupport(access, down.WestCopy().South());
                        }
                        if (checkNorth)
                        {
                            supported |= CheckSupport(access, down.NorthCopy());
                        }
                        if (checkSouth)
                        {
                            supported |= CheckSupport(access, down.SouthCopy());
                        }

                        if (!supported)
                        {
                            // Break the block and the entity will fall :)

                            // ## TODO
                        }
                    }
                }
            }

            return;
        }
        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;
            }
        }