public override void ReceiveUpdate(BSONObject bsonObj) { bool changed = false; if (!bsonObj.ContainsKey("trunks")) { return; } BSONArray trunks = bsonObj["trunks"].ArrayValue; foreach (BSONObject obj in trunks) { Guid id = obj["id"]; TrunkPiece piece = this.trunkPieces.FirstOrDefault(p => p.ID == id); if (piece != null && (piece.Position != obj["pos"] || piece.Rotation != obj["rot"])) { piece.Position = obj["pos"]; piece.Rotation = obj["rot"]; piece.Velocity = obj["v"]; piece.LastUpdateTime = TimeUtil.Seconds; changed = true; } } if (changed) { if (this.UpRooted) { this.Position = this.trunkPieces.First().Position; } this.lastKeyframeTime = bsonObj["time"]; this.LastUpdateTime = TimeUtil.Seconds; } }
void FellTree(INetObject killer) { // create the initial trunk piece var trunkPiece = new TrunkPiece() { ID = Guid.NewGuid(), SliceStart = 0f, SliceEnd = 1f, }; // clear tree occupancy if (this.Species.BlockType != null) { var treeBlockCheck = this.Position.Round + Vector3i.Up; while (World.GetBlock(treeBlockCheck).GetType() == this.Species.BlockType) { World.DeleteBlock(treeBlockCheck); treeBlockCheck += Vector3i.Up; } } this.trunkPieces.Add(trunkPiece); if (killer is Player) { this.SetPhysicsController((INetObjectViewer)killer); killer.RPC("YellTimber"); Animal.AlertNearbyAnimals(this.Position, 30); } this.RPC("FellTree", trunkPiece.ID, this.resourceMultiplier); // break off any branches that are young for (int branchID = 0; branchID < this.branches.Count(); branchID++) { var branch = this.branches[branchID]; if (branch == null) { continue; } var branchAge = Mathf.Clamp01((float)((this.GrowthPercent - branch.SpawnAge) / (branch.MatureAge - branch.SpawnAge))); if (branchAge <= .5f) { this.DestroyBranch(branchID); } } if (killer is Player) { PlantSimEvents.OnTreeFelled.Invoke((killer as Player).DisplayName); } //Add air pollution (minor) WorldLayerManager.ClimateSim.AddAirPollution(new WorldPosition3i(this.Position.XYZi), -this.Species.ReleasesCO2ppmPerDay); this.Save(); }
private bool TrySliceTrunk(Player player, float slicePoint) { lock (this) // prevent threading issues due to multiple choppers { // find the trunk piece this is coming from TrunkPiece target = this.trunkPieces.Where(p => p.SliceStart <slicePoint && p.SliceEnd> slicePoint).FirstOrDefault(); if (target == null) { return(false); } else { // if this is a tiny slice, clamp to the nearest valid size const float minPieceResources = 5f; float minPieceSize = minPieceResources / this.resourceMultiplier; float targetSize = target.SliceEnd - target.SliceStart; float targetResources = targetSize * this.resourceMultiplier; float newPieceSize = target.SliceEnd - slicePoint; float newPieceResources = newPieceSize * this.resourceMultiplier; if (targetResources <= minPieceResources) { return(false); // can't slice, too small } if (targetResources < (2 * minPieceResources)) // if smaller than 2x the min size, slice directly in half { slicePoint = target.SliceStart + (.5f * targetSize); } else if (newPieceSize < minPieceSize) // round down to nearest slice point where the resulting block will be the size of the log { slicePoint = target.SliceEnd - minPieceSize; } else if (slicePoint - target.SliceStart <= minPieceSize) // round up { slicePoint = target.SliceStart + minPieceSize; } // slice and assign new IDs (New piece is always the back end of the source piece) var newPiece = new TrunkPiece() { ID = Guid.NewGuid(), SliceStart = slicePoint, SliceEnd = target.SliceEnd, Position = target.Position, Rotation = target.Rotation, }; this.trunkPieces.Add(newPiece); target.SliceEnd = slicePoint; // ensure the pieces are listed in order this.trunkPieces.Sort((a, b) => a.SliceStart.CompareTo(b.SliceStart)); // reciprocate to clients this.RPC("SliceTrunk", slicePoint, target.ID, newPiece.ID); PlantSimEvents.OnLogChopped.Invoke(player.DisplayName); this.Save(); return(true); } } }
private int GetBasePickupSize(TrunkPiece trunk) { return(Math.Max((int)Math.Round((trunk.SliceEnd - trunk.SliceStart) * resourceMultiplier), 1)); }
private bool CanPickup(TrunkPiece trunk) { return(this.GetBasePickupSize(trunk) <= maxTrunkPickupSize); }