public bool SphereInFrustumAndRange(Sphere sphere, bool nowVisible, int lodLevel = 0) { double d; d = frustum00 * sphere.x + frustum01 * sphere.y + frustum02 * sphere.z + frustum03; if (d <= -sphere.radius) { return(false); } d = frustum10 * sphere.x + frustum11 * sphere.y + frustum12 * sphere.z + frustum13; if (d <= -sphere.radius) { return(false); } d = frustum20 * sphere.x + frustum21 * sphere.y + frustum22 * sphere.z + frustum23; if (d <= -sphere.radius) { return(false); } d = frustum30 * sphere.x + frustum31 * sphere.y + frustum32 * sphere.z + frustum33; if (d <= -sphere.radius) { return(false); } d = frustum40 * sphere.x + frustum41 * sphere.y + frustum42 * sphere.z + frustum43; if (d <= -sphere.radius) { return(false); } d = frustum50 * sphere.x + frustum51 * sphere.y + frustum52 * sphere.z + frustum53; if (d <= -sphere.radius) { return(false); } // Lod level 1: all stuff // Lod level 0: only high detail stuff double distance = playerPos.HorDistanceSqTo(sphere.x, sphere.z); return((distance < ViewDistanceSq && lodLevel == 1) || (lodBiasSq > 0 && distance < ViewDistanceSq * lodBiasSq + 32 * 32)); }
public bool SphereInFrustumAndRange(Sphere sphere, bool nowVisible, int lodLevel = 0) { double d; float x = sphere.x; float y = sphere.y; float z = sphere.z; float radius = sphere.radius; d = frustum00 * x + frustum01 * y + frustum02 * z + frustum03; if (d <= -radius) { return(false); } d = frustum10 * x + frustum11 * y + frustum12 * z + frustum13; if (d <= -radius) { return(false); } d = frustum20 * x + frustum21 * y + frustum22 * z + frustum23; if (d <= -radius) { return(false); } d = frustum30 * x + frustum31 * y + frustum32 * z + frustum33; if (d <= -radius) { return(false); } d = frustum40 * x + frustum41 * y + frustum42 * z + frustum43; if (d <= -radius) { return(false); } d = frustum50 * x + frustum51 * y + frustum52 * z + frustum53; if (d <= -radius) { return(false); } // Lod level 3: implements Lod2: this is the mesh drawn at long distance (may be empty) // Lod level 2: implements Lod2: this is the mesh drawn at short and medium view distance // Lod level 1: drawn at all view distance // Lod level 0: only high detail stuff double distance = playerPos.HorDistanceSqTo(x, z); switch (lodLevel) { case 0: return(lod0BiasSq > 0 && distance < ViewDistanceSq * lod0BiasSq + 32 * 32); case 1: return(distance < ViewDistanceSq); case 2: return(distance <= ViewDistanceSq * lod2BiasSq); case 3: return(distance > ViewDistanceSq * lod2BiasSq && distance < ViewDistanceSq); default: return(false); } }
public Stack <BlockPos> FindTree(IWorldAccessor world, BlockPos startPos, out string treeType) { Queue <Vec4i> queue = new Queue <Vec4i>(); HashSet <BlockPos> checkedPositions = new HashSet <BlockPos>(); Stack <BlockPos> foundPositions = new Stack <BlockPos>(); treeType = ""; Block block = world.BlockAccessor.GetBlock(startPos); if (block.Code == null) { return(foundPositions); } if (block.Code.Path.StartsWith("log-grown") || block.Code.Path.StartsWith("beehive-inlog-") || block.Code.Path.StartsWith("log-resin") || block.Code.Path.StartsWith("bamboo-grown-")) { treeType = block.FirstCodePart(2); queue.Enqueue(new Vec4i(startPos.X, startPos.Y, startPos.Z, 2)); foundPositions.Push(startPos); checkedPositions.Add(startPos); } string logcode = block.Code.Path.StartsWith("bamboo") ? "bamboo-grown-" + treeType : "log-grown-" + treeType; if (block is BlockFernTree) { treeType = "fern"; logcode = "ferntree-normal"; queue.Enqueue(new Vec4i(startPos.X, startPos.Y, startPos.Z, 2)); foundPositions.Push(startPos); checkedPositions.Add(startPos); } string logcode2 = "log-resin-" + treeType; string logcode3 = "log-resinharvested-" + treeType; string leavescode = block.Code.Path.StartsWith("bamboo") ? "bambooleaves-" + treeType + "-grown" : "leaves-grown-" + treeType; string leavesbranchycode = "leavesbranchy-grown-" + treeType; while (queue.Count > 0) { if (foundPositions.Count > 2000) { break; } Vec4i pos = queue.Dequeue(); for (int i = 0; i < Vec3i.DirectAndIndirectNeighbours.Length; i++) { Vec3i facing = Vec3i.DirectAndIndirectNeighbours[i]; BlockPos neibPos = new BlockPos(pos.X + facing.X, pos.Y + facing.Y, pos.Z + facing.Z); float hordist = GameMath.Sqrt(neibPos.HorDistanceSqTo(startPos.X, startPos.Z)); float vertdist = (neibPos.Y - startPos.Y); // "only breaks blocks inside an upside down square base pyramid" if (hordist - 1 >= 2 * vertdist) { continue; } if (checkedPositions.Contains(neibPos)) { continue; } block = world.BlockAccessor.GetBlock(neibPos); if (block.Code == null) { continue; } if (block.Code.Path.StartsWith(logcode) || block.Code.Path.StartsWith(logcode2) || block.Code.Path.StartsWith(logcode3)) { if (pos.W < 2) { continue; } foundPositions.Push(neibPos.Copy()); queue.Enqueue(new Vec4i(neibPos.X, neibPos.Y, neibPos.Z, 2)); } else if (block.Code.Path.StartsWith(leavesbranchycode)) { if (pos.W < 1) { continue; } foundPositions.Push(neibPos.Copy()); queue.Enqueue(new Vec4i(neibPos.X, neibPos.Y, neibPos.Z, 1)); } else if (block.Code.Path.StartsWith(leavescode)) { foundPositions.Push(neibPos.Copy()); queue.Enqueue(new Vec4i(neibPos.X, neibPos.Y, neibPos.Z, 0)); } checkedPositions.Add(neibPos); } } return(foundPositions); }
public void CmdMeasuringTape(int groupId, CmdArgs args) { WaypointUtilSystem wUtil = capi.ModLoader.GetModSystem <WaypointUtilSystem>(); string arg = args.PopWord(); switch (arg) { case "start": if (capi.World.Player.CurrentBlockSelection != null) { start = capi.World.Player.CurrentBlockSelection.Position; //capi.ShowChatMessage("Okay, start set to: " + start); MakeHighlights(); } else { capi.ShowChatMessage("Please look at a block."); } break; case "end": if (capi.World.Player.CurrentBlockSelection != null) { end = capi.World.Player.CurrentBlockSelection.Position; //capi.ShowChatMessage("Okay, end set to: " + end); MakeHighlights(); } else { capi.ShowChatMessage("Please look at a block."); } break; case "startwp": int?swpID = args.PopInt(); if (swpID != null) { start = wUtil.Waypoints[(int)swpID].Position.AsBlockPos; MakeHighlights(); } else { capi.ShowChatMessage("Please enter a waypoint id."); } break; case "endwp": int?ewpID = args.PopInt(); if (ewpID != null) { end = wUtil.Waypoints[(int)ewpID].Position.AsBlockPos; MakeHighlights(); } else { capi.ShowChatMessage("Please enter a waypoint id."); } break; case "calc": string type = args.PopWord(); switch (type) { case "block": capi.ShowChatMessage("Block Distance: " + Math.Round(start.DistanceTo(end) + 1)); break; case "euclidian": capi.ShowChatMessage("Euclidian Distance: " + start.DistanceTo(end)); break; case "manhattan": capi.ShowChatMessage("Manhattan Distance: " + start.ManhattenDistance(end)); break; case "horizontal": capi.ShowChatMessage("Horizontal Distance: " + Math.Sqrt(start.HorDistanceSqTo(end.X, end.Z))); break; case "horizontalmanhattan": capi.ShowChatMessage("Horizontal Manhattan Distance: " + start.HorizontalManhattenDistance(end)); break; default: capi.ShowChatMessage("Syntax: .measure calc [block|euclidian|manhattan|horizontal|horizontalmanhattan]"); break; } break; default: capi.ShowChatMessage("Syntax: .measure [start|end|calc]"); break; } }
public Stack <BlockPos> FindTree(IWorldAccessor world, BlockPos startPos) { Queue <Vec4i> queue = new Queue <Vec4i>(); HashSet <BlockPos> checkedPositions = new HashSet <BlockPos>(); Stack <BlockPos> foundPositions = new Stack <BlockPos>(); Block block = world.BlockAccessor.GetBlock(startPos); if (block.Code == null) { return(foundPositions); } string treeFellingGroupCode = block.Attributes?["treeFellingGroupCode"].AsString(); int spreadIndex = block.Attributes?["treeFellingGroupSpreadIndex"].AsInt(0) ?? 0; if (block.Attributes?["treeFellingCanChop"].AsBool(true) == false) { return(foundPositions); } EnumTreeFellingBehavior bh = EnumTreeFellingBehavior.Chop; if (block is ICustomTreeFellingBehavior ctfbh) { bh = ctfbh.GetTreeFellingBehavior(startPos, null, spreadIndex); if (bh == EnumTreeFellingBehavior.NoChop) { return(foundPositions); } } // Must start with a log if (spreadIndex < 2) { return(foundPositions); } if (treeFellingGroupCode == null) { return(foundPositions); } queue.Enqueue(new Vec4i(startPos.X, startPos.Y, startPos.Z, spreadIndex)); foundPositions.Push(startPos); checkedPositions.Add(startPos); while (queue.Count > 0) { if (foundPositions.Count > 2500) { break; } Vec4i pos = queue.Dequeue(); block = world.BlockAccessor.GetBlock(pos.X, pos.Y, pos.Z); if (block is ICustomTreeFellingBehavior ctfbhh) { bh = ctfbhh.GetTreeFellingBehavior(startPos, null, spreadIndex); } if (bh == EnumTreeFellingBehavior.NoChop) { continue; } for (int i = 0; i < Vec3i.DirectAndIndirectNeighbours.Length; i++) { Vec3i facing = Vec3i.DirectAndIndirectNeighbours[i]; BlockPos neibPos = new BlockPos(pos.X + facing.X, pos.Y + facing.Y, pos.Z + facing.Z); float hordist = GameMath.Sqrt(neibPos.HorDistanceSqTo(startPos.X, startPos.Z)); float vertdist = (neibPos.Y - startPos.Y); // "only breaks blocks inside an upside down square base pyramid" float f = bh == EnumTreeFellingBehavior.ChopSpreadVertical ? 0.5f : 2; if (hordist - 1 >= f * vertdist) { continue; } if (checkedPositions.Contains(neibPos)) { continue; } block = world.BlockAccessor.GetBlock(neibPos); if (block.Code == null || block.Id == 0) { continue; } string ngcode = block.Attributes?["treeFellingGroupCode"].AsString(); // Only break the same type tree blocks if (ngcode != treeFellingGroupCode) { continue; } // Only spread from "high to low". i.e. spread from log to leaves, but not from leaves to logs int nspreadIndex = block.Attributes?["treeFellingGroupSpreadIndex"].AsInt(0) ?? 0; if (pos.W < nspreadIndex) { continue; } checkedPositions.Add(neibPos); if (bh == EnumTreeFellingBehavior.ChopSpreadVertical && !facing.Equals(0, 1, 0) && nspreadIndex > 0) { continue; } foundPositions.Push(neibPos.Copy()); queue.Enqueue(new Vec4i(neibPos.X, neibPos.Y, neibPos.Z, nspreadIndex)); } } return(foundPositions); }