public override void FromTreeAtributes(ITreeAttribute tree, IWorldAccessor worldAccessForResolve) { base.FromTreeAtributes(tree, worldAccessForResolve); long nowNetworkId = tree.GetLong("networkid"); if (worldAccessForResolve.Side == EnumAppSide.Client) { propagationDir = BlockFacing.ALLFACES[tree.GetInt("turnDirFromFacing")]; gearedRatio = tree.GetFloat("g"); if (NetworkId != nowNetworkId) //don't ever change network settings from tree on server side - networkId is not data to be saved (otherwise would mess up networks on chunk loading, if BE tree loaded after a BE has already had network assigned on the server by propagation from a neighbour) { NetworkId = 0; if (worldAccessForResolve.Side == EnumAppSide.Client) { NetworkId = nowNetworkId; if (NetworkId == 0) { LeaveNetwork(); network = null; } else if (manager != null) { network = manager.GetOrCreateNetwork(NetworkId); JoinNetwork(network); Blockentity.MarkDirty(); } } } } }
private void onTrackLoaded(ILoadedSound sound) { if (track == null) { sound?.Dispose(); return; } if (sound == null) { return; } track.Sound = sound; // Needed so that the music engine does not dispose the sound Api.Event.EnqueueMainThreadTask(() => track.loading = true, "settrackloading"); long longMsPassed = Api.World.ElapsedMilliseconds - startLoadingMs; handlerId = Blockentity.RegisterDelayedCallback((dt) => { if (sound.IsDisposed) { Api.World.Logger.Notification("firepit track is diposed? o.O"); } if (!wasStopped) { sound.Start(); } track.loading = false; }, (int)Math.Max(0, 500 - longMsPassed)); }
private void initSoundsAndTicking() { fuelBlock = Api.World.BlockAccessor.GetBlock(FuelPos); l1 = Blockentity.RegisterGameTickListener(OnTick, 25); if (Api.Side == EnumAppSide.Server) { l2 = Blockentity.RegisterGameTickListener(OnSlowServerTick, 1000); } wsys = Api.ModLoader.GetModSystem <WeatherSystemBase>(); if (ambientSound == null && Api.Side == EnumAppSide.Client) { ambientSound = ((IClientWorldAccessor)Api.World).LoadSound(new SoundParams() { Location = new AssetLocation("sounds/environment/fire.ogg"), ShouldLoop = true, Position = FirePos.ToVec3f().Add(0.5f, 0.25f, 0.5f), DisposeOnFinish = false, Volume = 1f }); if (ambientSound != null) { ambientSound.PlaybackPosition = ambientSound.SoundLengthSeconds * (float)Api.World.Rand.NextDouble(); ambientSound.Start(); } } particleFacing = BlockFacing.FromNormal(new Vec3i(FirePos.X - FuelPos.X, FirePos.Y - FuelPos.Y, FirePos.Z - FuelPos.Z)); }
public override void Initialize(ICoreAPI api, JsonObject properties) { base.Initialize(api, properties); //sound = new AssetLocation("game:sounds/effect/swoosh"); Blockentity.RegisterGameTickListener(CheckWaterSpeed, 1000); }
public override void Initialize(ICoreAPI api, JsonObject properties) { base.Initialize(api, properties); if (Api.Side == EnumAppSide.Server) { listenerId = Blockentity.RegisterGameTickListener(OnTick, callbackTimeMs + Api.World.Rand.Next(callbackTimeMs)); } stemBlock = Api.World.GetBlock(ownBe.Block.CodeWithVariant("type", "stem")); branchBlock = Api.World.GetBlock(ownBe.Block.CodeWithVariant("type", "branch")) as BlockFruitTreeBranch; leavesBlock = Api.World.GetBlock(AssetLocation.Create(ownBe.Block.Attributes["foliageBlock"].AsString(), ownBe.Block.Code.Domain)) as BlockFruitTreeFoliage; if (ownBe.Block == leavesBlock) { ownBe.PartType = EnumTreePartType.Leaves; } if (ownBe.Block == branchBlock) { ownBe.PartType = EnumTreePartType.Branch; } if (ownBe.lastGrowthAttemptTotalDays == 0) { ownBe.lastGrowthAttemptTotalDays = api.World.Calendar.TotalDays; } }
public override void Initialize(ICoreAPI api, JsonObject properties) { base.Initialize(api, properties); if (api.Side == EnumAppSide.Server) { Blockentity.RegisterGameTickListener(onRootTick, 5000, api.World.Rand.Next(5000)); } roomreg = api.ModLoader.GetModSystem <RoomRegistry>(); blockBranch = be.Block as BlockFruitTreeBranch; RegisterTreeType(bebr.TreeType); double totalDays = api.World.Calendar.TotalDays; if (TreePlantedTotalDays == 0) { TreePlantedTotalDays = totalDays; LastRootTickTotalDays = totalDays; } else { // In case this block was imported from another older world. In that case lastCheckAtTotalDays would be a future date. TreePlantedTotalDays = Math.Min(TreePlantedTotalDays, totalDays); LastRootTickTotalDays = Math.Min(LastRootTickTotalDays, totalDays); } }
public override void Initialize(ICoreAPI api, JsonObject properties) { base.Initialize(api, properties); this.sound = new AssetLocation("sounds/effect/swoosh"); weatherSystem = Api.ModLoader.GetModSystem <WeatherSystemBase>(); Blockentity.RegisterGameTickListener(CheckWindSpeed, 1000); }
private void ChangeState(bool newEngaged) { if (newEngaged) { CreateJoinAndDiscoverNetwork(orients[0]); CreateJoinAndDiscoverNetwork(orients[1]); this.tryConnect(orients[0]); ////Test for connection on opposite side as well //pos = Position.AddCopy(orients[1]); //block = Api.World.BlockAccessor.GetBlock(pos) as IMechanicalPowerBlock; //if (block != null && this.network != block.GetNetwork(Api.World, pos)) //{ // block.DidConnectAt(Api.World, pos, orients[0]); // this.WasPlaced(orients[1]); //} Blockentity.MarkDirty(true); } else { if (network != null) { manager.OnNodeRemoved(this); } } }
public void KillFire(bool consumeFuel) { IsBurning = false; Blockentity.UnregisterGameTickListener(l1); Blockentity.UnregisterGameTickListener(l2); ambientSound?.FadeOutAndStop(1); OnFireDeath(consumeFuel); }
private void CheckForGrowth(float dt) { double timeFactor = GameMath.Clamp(Api.World.Calendar.SpeedOfTime / 60, 0.1, 5); double now = Api.World.Calendar.TotalDays; bool fastForwarded = now > dateLastChecked + 0.5; dateLastChecked = now; if (Api.World.Rand.NextDouble() > 0.2 * timeFactor && !fastForwarded) return; int count = 0; bool dirty = false; foreach (var val in fruitPoints) { if (val.variant >= 0) { if (val.transitionDate == 0) { val.transitionDate = GetGerminationDate(); // probably this code path is never reached, but just in case something went wrong reading a BlockEntity from a save etc. dirty = true; } if (val.currentStage > 0) count++; } } bool finalStagePlant = false; if (this.Blockentity.Block is BlockCrop crop) { finalStagePlant = (crop.CurrentCropStage == crop.CropProps.GrowthStages); } foreach (var val in fruitPoints) { if (val.variant >= 0) { if (now > val.transitionDate) { if (val.currentStage == 0 && count >= maxFruit) continue; // Suppress growth for now - too many fruits already on this plant - but try again soon if (finalStagePlant && val.currentStage < fruitStages - 3) continue; // No small green fruit growth on final stage crop, except ripe fruit can become overripe if (++val.currentStage > fruitStages) { // reached final stage val.transitionDate = Double.MaxValue; val.currentStage = fruitStages; } else { // set up next transition - take 2.5 times as long for the final stage val.transitionDate = now + transitionDays * (1 + Api.World.Rand.NextDouble()) / 1.5 / PlantHealth() * (val.currentStage == fruitStages - 1 ? 2.5 : 1); } dirty = true; } } } if (dirty) Blockentity.MarkDirty(); }
internal bool OnInteract(IPlayer byPlayer) { if (++this.powerSetting > 10) { this.powerSetting = 1; } Blockentity.MarkDirty(true); return(true); }
public override void Initialize(ICoreAPI api, JsonObject properties) { base.Initialize(api, properties); if (Blockentity.Api.Side == EnumAppSide.Client) { Blockentity.RegisterGameTickListener(OnTick3s, 3000); } }
public virtual void LeaveNetwork() { if (DEBUG) { Api.Logger.Notification("Leaving network " + NetworkId + " at " + this.Position); } network?.Leave(this); network = null; NetworkId = 0; Blockentity.MarkDirty(); }
public override void Initialize(ICoreAPI api, JsonObject properties) { base.Initialize(api, properties); if (api.Side.IsServer()) { face = BlockFacing.FromCode(Block.Variant["side"]); CheckWater(0); Blockentity.RegisterGameTickListener(CheckWater, 1000); } }
public override void Initialize(ICoreAPI api, JsonObject properties) { base.Initialize(api, properties); this.AxisSign = new int[3] { 0, 1, 0 }; if (api.Side == EnumAppSide.Client) { Blockentity.RegisterGameTickListener(onEverySecond, 1000); } }
private void CheckWindSpeed(float dt) { windSpeed = weatherSystem.WeatherDataSlowAccess.GetWindSpeed(Blockentity.Pos.ToVec3d()); if (Api.World.BlockAccessor.GetLightLevel(Blockentity.Pos, EnumLightLevelType.OnlySunLight) < 5 && Api.World.Config.GetString("undergroundWindmills", "false") != "true") { windSpeed = 0; } if (Api.Side == EnumAppSide.Server && sailLength > 0 && Api.World.Rand.NextDouble() < 0.2) { // Todo: Entity Fling and Damage thing /*Cuboidd cuboid = new Cuboidd(-sailLength + 0.1, -sailLength + 0.1, 0.2, sailLength - 0.2, sailLength - 0.2, 0.8); * float rot = (ownFacing.HorizontalAngleIndex+1) * 90; * * cuboid = cuboid.RotatedCopy(0, rot, 0, new Vec3d(0.5, 0.5, 0.5)); * cuboid = cuboid.OffsetCopy(Position.X, Position.Y, Position.Z); * * Api.World.SpawnParticles(100, ColorUtil.WhiteArgb, cuboid.Start, cuboid.End, new Vec3f(), new Vec3f(), 2f, 0); * * Vec3d centerPos = Position.ToVec3d().Add(0.5, 0.5, 0.5); * * partitionUtil.WalkEntityPartitions(centerPos, SailLength + 1, (e) => * { * if (!e.IsInteractable) return; * if (cuboid.IntersectsOrTouches(e.CollisionBox, e.ServerPos.X, e.ServerPos.Y, e.ServerPos.Z)) * { * e.ReceiveDamage(new DamageSource() { SourceBlock = Block, SourcePos = Position.ToVec3d().Add(0.5, 0.5, 0.5), Type = EnumDamageType.BluntAttack, Source = EnumDamageSource.Block }, 0.5f); * * float dx = (float)(centerPos.X - e.ServerPos.X); * float dy = (float)(centerPos.Y - e.ServerPos.Y); * float dz = (float)(centerPos.Y - e.ServerPos.Z); * * e.ServerPos.Motion.Add(dx, dy, dz); * } * });*/ if (obstructed(sailLength + 1)) { Api.World.PlaySoundAt(new AssetLocation("sounds/effect/toolbreak"), Position.X + 0.5, Position.Y + 0.5, Position.Z + 0.5, null, false, 20, 1f); while (sailLength-- > 0) { ItemStack stacks = new ItemStack(Api.World.GetItem(new AssetLocation("sail")), 4); Api.World.SpawnItemEntity(stacks, Blockentity.Pos.ToVec3d().Add(0.5, 0.5, 0.5)); } sailLength = 0; Blockentity.MarkDirty(true); this.network.updateNetwork(manager.getTickNumber()); } } }
internal bool OnInteract(IPlayer byPlayer) { if (++this.powerSetting > 10) { this.powerSetting = 1; } Blockentity.MarkDirty(true); var pos = Blockentity.Pos.ToVec3d().Add(0.5, 0, 0.5); Api.World.PlaySoundAt(new AssetLocation("sounds/toggleswitch"), pos.X, pos.Y, pos.Z, byPlayer, false, 16); return(true); }
public virtual void OnPlayerInteractStop(float secondsUsed, IPlayer player, Vec3d hit) { if (secondsUsed < 0.2f) return; for (int i = 0; i < fruitPoints.Length; i++) { FruitData val = fruitPoints[i]; if (val.variant >= 0 && val.currentStage >= this.ripeStage) { Item item = Api.World.GetItem(new AssetLocation(fruitCodeBases[val.variant] + val.currentStage)); if (item == null) continue; if (item.Attributes != null && item.Attributes["onGround"].AsBool(false)) continue; // ignore fruits already on the ground if (Api.Side == EnumAppSide.Client) manager.RemoveFruit(fruitCodeBases[val.variant] + val.currentStage, positions[i]); val.variant = -1; // Flag this fruit as picked val.transitionDate = Double.MaxValue; if (val.currentStage >= this.ripeStage) // allow both ripe and overripe fruits to be picked { // Play snickety sound double posx = Blockentity.Pos.X + hit.X; double posy = Blockentity.Pos.Y + hit.Y; double posz = Blockentity.Pos.Z + hit.Z; player.Entity.World.PlaySoundAt(new AssetLocation("sounds/effect/squish1"), posx, posy, posz, player, 1.1f + (float)Api.World.Rand.NextDouble() * 0.4f, 16, 0.25f); // Update transition time of any non-started fruit, otherwise they may all start immediately double now = Api.World.Calendar.TotalDays; for (int j = 0; j < fruitPoints.Length; j++) { val = fruitPoints[j]; if (val.variant >= 0 && val.currentStage == 0 && val.transitionDate < now) { val.transitionDate = now + Api.World.Rand.NextDouble() * maxGerminationDays / 2; } } // Give the player one item ItemStack stack = new ItemStack(Api.World.GetItem(dropCode), 1); if (!player.InventoryManager.TryGiveItemstack(stack)) { Api.World.SpawnItemEntity(stack, Blockentity.Pos.ToVec3d().Add(0.5, 0.25, 0.5)); } } Blockentity.MarkDirty(); break; } } }
public override void FromTreeAtributes(ITreeAttribute tree, IWorldAccessor worldForResolving) { base.FromTreeAtributes(tree, worldForResolving); Circuit.FromTreeAttributes(tree.GetTreeAttribute("circuit"), worldForResolving); Blockentity.MarkDirty(true); if (Api == null) { return; } if (Api.Side == EnumAppSide.Client) { renderer.RegenCircuitMesh(this.Circuit); } }
public override void Initialize(ICoreAPI api, JsonObject properties) { base.Initialize(api, properties); if (api.Side == EnumAppSide.Client) { Blockentity.RegisterGameTickListener(onEverySecond, 1000); } if (largeGear != null) { if (largeGear.AngledGearNotAlreadyAdded(this.Position)) // during chunk loading it's random whether the angled gear or the large gear gets initialised first { this.tryConnect(this.orientation.Opposite); } } }
public void OnUseOver(IPlayer byPlayer, Vec3i voxelHitPos, Vec3i voxelBoxPos, BlockFacing facing, bool mouseBreakMode) { // Send a custom network packet for server side, because // serverside blockselection index is inaccurate if (Api.Side == EnumAppSide.Client) { SendUseOverPacket(byPlayer, voxelHitPos, voxelBoxPos, facing, mouseBreakMode); return; } ItemStack itemStack = byPlayer?.InventoryManager?.ActiveHotbarSlot?.Itemstack; Circuit.OnUseOver(byPlayer, voxelHitPos, voxelBoxPos, facing, itemStack, mouseBreakMode); Api.World.PlaySoundAt(new AssetLocation("signals:sounds/buzz_short"), Pos.X, Pos.Y, Pos.Z); Blockentity.MarkDirty(); }
internal bool OnInteract(IPlayer byPlayer) { if (sailLength >= 5) { return(false); } ItemSlot slot = byPlayer.InventoryManager.ActiveHotbarSlot; if (slot.Empty || slot.StackSize < 4) { return(false); } ItemStack sailStack = new ItemStack(Api.World.GetItem(new AssetLocation("sail"))); if (!slot.Itemstack.Equals(Api.World, sailStack, GlobalConstants.IgnoredStackAttributes)) { return(false); } int len = sailLength + 2; if (obstructed(len)) { if (Api.Side == EnumAppSide.Client) { (Api as ICoreClientAPI).TriggerIngameError(this, "notenoughspace", Lang.Get("Cannot add more sails. Make sure there's space for the sails to rotate freely")); } return(false); } if (byPlayer.WorldData.CurrentGameMode != EnumGameMode.Creative) { slot.TakeOut(4); slot.MarkDirty(); } sailLength++; updateShape(); Blockentity.MarkDirty(true); return(true); }
public override void Initialize(ICoreAPI api, JsonObject properties) { base.Initialize(api, properties); Circuit.Initialize(api); listenerId = Blockentity.RegisterGameTickListener(Update, 50); block = Blockentity.Block; Pos = this.Blockentity.Pos; //facing = BlockFacing.FromCode(block?.LastCodePart(0)?.ToString()); //orientation = BlockFacing.FromCode(block?.LastCodePart(1)?.ToString()); facing = BlockFacing.FromCode(properties["side"]?.AsString("down")); orientation = BlockFacing.FromCode(properties["orientation"]?.AsString("north")); if (api.Side == EnumAppSide.Client) { ICoreClientAPI capi = (ICoreClientAPI)api; capi.Event.RegisterRenderer(renderer = new CircuitBoardRenderer(this.Blockentity.Pos, facing, orientation, capi), EnumRenderStage.Opaque, "circuitboard"); renderer.RegenCircuitMesh(Circuit); } }
public override void Initialize(ICoreAPI api, JsonObject properties) { base.Initialize(api, properties); //this.Api = api; //Shape = GetShape(); //manager = Api.ModLoader.GetModSystem<MechanicalPowerMod>(); //if (Api.World.Side == EnumAppSide.Client) //{ // lightRbs = Api.World.BlockAccessor.GetLightRGBs(Blockentity.Pos); // if (NetworkId > 0) // { // network = manager.GetOrCreateNetwork(NetworkId); // JoinNetwork(network); // } //} //manager.AddDeviceForRender(this); //AxisSign = new int[3] { 0, 0, 1 }; //SetOrientations(); //if (api.Side == EnumAppSide.Server && OutFacingForNetworkDiscovery != null) //{ // CreateJoinAndDiscoverNetwork(OutFacingForNetworkDiscovery); //} if (api.Side == EnumAppSide.Client) { Blockentity.RegisterGameTickListener(onEverySecond, 1000); } if (largeGear != null) { if (largeGear.AngledGearNotAlreadyAdded(this.Position)) // during chunk loading it's random whether the angled gear or the large gear gets initialised first { this.tryConnect(this.orientation.Opposite); } } }
public virtual void JoinNetwork(MechanicalNetwork network) { if (this.network != null && this.network != network) { LeaveNetwork(); } if (this.network == null) { this.network = network; network?.Join(this); } if (network == null) { NetworkId = 0; } else { NetworkId = network.networkId; } Blockentity.MarkDirty(); }
private void onRootTick(float dt) { double totalDays = Api.World.Calendar.TotalDays; if (totalDays - LastRootTickTotalDays < stateUpdateIntervalDays) { return; } int prevIntDays = -99; float temp = 0; while (totalDays - LastRootTickTotalDays >= stateUpdateIntervalDays) { foreach (var val in propsByType) { var props = val.Value; if (props.State == EnumFruitTreeState.Dead) { continue; } // Avoid reading the same temp over and over again if (prevIntDays != (int)LastRootTickTotalDays) { // For roughly daily average temps double midday = (int)LastRootTickTotalDays + 0.5; temp = Api.World.BlockAccessor.GetClimateAt(be.Pos, EnumGetClimateMode.ForSuppliedDate_TemperatureOnly, midday).Temperature; temp = applyGreenhouseTempBonus(temp); prevIntDays = (int)LastRootTickTotalDays; Blockentity.MarkDirty(true); } double yearrel = (LastRootTickTotalDays % Api.World.Calendar.DaysPerYear) / Api.World.Calendar.DaysPerYear; if (props.DieBelowTemp > temp) { props.State = EnumFruitTreeState.Dead; props.lastStateChangeTotalDays = Api.World.Calendar.TotalDays; break; } if (props.State == EnumFruitTreeState.Dormant && props.CycleType == EnumTreeCycleType.Deciduous) { updateVernalizedHours(props, temp); if (props.vernalizedHours > props.VernalizationHours) { props.State = EnumFruitTreeState.DormantVernalized; props.lastStateChangeTotalDays = LastRootTickTotalDays; Blockentity.MarkDirty(true); } if (temp >= 20 || (temp > 15 && LastRootTickTotalDays - props.lastCheckAtTotalDays > 3)) { props.State = EnumFruitTreeState.Empty; props.lastStateChangeTotalDays = LastRootTickTotalDays; Blockentity.MarkDirty(true); } } else if (props.State == EnumFruitTreeState.DormantVernalized) { if (temp >= 20 || (temp > 15 && LastRootTickTotalDays - props.lastCheckAtTotalDays > 3)) { props.State = EnumFruitTreeState.Flowering; props.lastStateChangeTotalDays = LastRootTickTotalDays; Blockentity.MarkDirty(true); } } else if (props.CycleType == EnumTreeCycleType.Evergreen && (props.State == EnumFruitTreeState.Empty || props.State == EnumFruitTreeState.Young)) { if (props.State == EnumFruitTreeState.Young && (LastRootTickTotalDays - TreePlantedTotalDays) < nonFloweringYoungDays) { continue; } double yearRel = (LastRootTickTotalDays / Api.World.Calendar.DaysPerYear) % 1.0; if (Math.Abs(yearRel - props.BlossomAtYearRel) < 0.125) { props.State = EnumFruitTreeState.Flowering; props.lastCheckAtTotalDays = LastRootTickTotalDays; Blockentity.MarkDirty(true); } } else if (props.State == EnumFruitTreeState.Flowering && props.lastStateChangeTotalDays + props.FloweringDays < LastRootTickTotalDays) { props.State = EnumFruitTreeState.Fruiting; props.lastStateChangeTotalDays = LastRootTickTotalDays; if (temp < props.EnterDormancyTemp) { props.State = EnumFruitTreeState.Empty; } Blockentity.MarkDirty(true); } else if (props.State == EnumFruitTreeState.Fruiting && props.lastStateChangeTotalDays + props.FruitingDays < LastRootTickTotalDays) { props.State = EnumFruitTreeState.Ripe; props.lastStateChangeTotalDays = LastRootTickTotalDays; Blockentity.MarkDirty(true); } else if (props.State == EnumFruitTreeState.Ripe && props.lastStateChangeTotalDays + props.RipeDays < LastRootTickTotalDays) { props.State = EnumFruitTreeState.Empty; props.lastStateChangeTotalDays = LastRootTickTotalDays; Blockentity.MarkDirty(true); } else if (props.CycleType == EnumTreeCycleType.Deciduous && (props.State == EnumFruitTreeState.Young || props.State == EnumFruitTreeState.Empty) && temp < props.EnterDormancyTemp) { props.State = EnumFruitTreeState.EnterDormancy; props.lastStateChangeTotalDays = LastRootTickTotalDays; Blockentity.MarkDirty(true); } else if (props.CycleType == EnumTreeCycleType.Deciduous && props.State == EnumFruitTreeState.EnterDormancy && props.lastStateChangeTotalDays + 3 < LastRootTickTotalDays) { props.State = EnumFruitTreeState.Dormant; props.lastStateChangeTotalDays = LastRootTickTotalDays; Blockentity.MarkDirty(true); } } LastRootTickTotalDays += stateUpdateIntervalDays; } }
public override void Initialize(ICoreAPI api, JsonObject properties) { base.Initialize(api, properties); dateLastChecked = Api.World.Calendar.TotalDays; // Read the properties fruitCodeBases = properties["fruitCodeBases"].AsArray<string>(new string[0]); if (fruitCodeBases.Length == 0) return; positionsCount = properties["positions"].AsInt(0); if (positionsCount <= 0) return; string maturePlant = properties["maturePlant"].AsString(null); if (maturePlant == null) return; Block mature = api.World.GetBlock(new AssetLocation(maturePlant)); if (!(mature is BlockFruiting matureCrop)) return; if (Api.Side == EnumAppSide.Client) { points = matureCrop.GetFruitingPoints(); } maxFruit = properties["maxFruit"].AsInt(5); fruitStages = properties["fruitStages"].AsInt(6); maxGerminationDays = properties["maxGerminationDays"].AsFloat(6); transitionDays = properties["transitionDays"].AsFloat(1); successfulGrowthChance = properties["successfulGrowthChance"].AsFloat(0.75f); ripeStage = properties["ripeStage"].AsInt(fruitStages - 1); dropCode = new AssetLocation(properties["dropCode"].AsString(null)); // Set up the manager - used for the instanced renderer manager = Api.ModLoader.GetModSystem<FruitingSystem>(); // If initialising client-side after reading from tree attributes, send fruits to the renderer bool addToManager = false; if (Api.Side == EnumAppSide.Client && fruitPoints != null) { LightRgba = Api.World.BlockAccessor.GetLightRGBs(Blockentity.Pos); addToManager = true; } InitializeArrays(); if (addToManager) { for (int i = 0; i < positionsCount; i++) { FruitData val = fruitPoints[i]; if (val.variant >= fruitCodeBases.Length) val.variant %= fruitCodeBases.Length; if (val.variant >= 0 && val.currentStage > 0) { val.SetRandomRotation(Api.World, i, positions[i], this.Blockentity.Pos); manager.AddFruit(new AssetLocation(fruitCodeBases[val.variant] + val.currentStage), positions[i], val); } } } // Tick the blockEntity server-side only if (Api.Side == EnumAppSide.Server) Blockentity.RegisterGameTickListener(CheckForGrowth, 2250); }