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