public static Vector3Int ClosestSource(Vector3Int position, EFluids fluid) { FluidInfo info = _fluids[(int)fluid]; LinkedList <Tuple <Vector3Int, int> > toVisit = new LinkedList <Tuple <Vector3Int, int> >(); toVisit.AddLast(new Tuple <Vector3Int, int>(position, 0)); List <Vector3Int> alreadyVisited = new List <Vector3Int>(); while (toVisit.Count > 0) { var node = toVisit.First.Value; toVisit.RemoveFirst(); if (alreadyVisited.Contains(node.Item1)) { continue; } alreadyVisited.Add(node.Item1); if (node.Item2 == info.distance) { continue; } foreach (var adjacent in adjacents) { var adj = node.Item1 + adjacent; if (!World.TryGetTypeAt(adj, out ushort typeadj)) { continue; } if (typeadj == info.source) { return(adj); } if (typeadj == info.fake) { if (!alreadyVisited.Contains(adj)) { toVisit.AddLast(new Tuple <Vector3Int, int>(adj, node.Item2 + 1)); } } } } return(Vector3Int.maximum); }
public static void TryRemove(Vector3Int position, EFluids fluid, int distance = int.MinValue) { //Log.Write(string.Format("<color=blue>TryRemove {0}</color>", position)); FluidInfo info = _fluids[(int)fluid]; if(!World.TryGetTypeAt(position, out ushort typeToRemove) && ( typeToRemove != info.source && typeToRemove != info.fake )) return; if(distance == int.MinValue) distance = info.distance; if(distance < 0) return; if(!World.TryGetTypeAt(position, out ushort type)) return; if(type != info.fake) return; if(ClosestSource(position, fluid) == Vector3Int.maximum) { Pipliz.Threading.ThreadManager.InvokeOnMainThread(() => { if(World.TryGetTypeAt(position, out ushort posToRemove) && ( posToRemove == info.fake )) ServerManager.TryChangeBlock(position, BlockTypes.Builtin.BuiltinBlocks.Air); }); } var down = position + Vector3Int.down; if(!World.TryGetTypeAt(down, out ushort typeDown)) return; if(typeDown == info.source) { _actions.Add(Time.MillisecondsSinceStart + info.time, delegate () { Remove(down, fluid); }); _SomeAction.Set(); return; } foreach(var adjacent in adjacents) { var adj = position + adjacent; if(!World.TryGetTypeAt(adj, out ushort typeAdj)) continue; if(typeAdj == info.fake) { _actions.Add(Time.MillisecondsSinceStart + info.time, delegate () { TryRemove(adj, fluid, distance - 1); }); _SomeAction.Set(); } else if(typeAdj == BlockTypes.Builtin.BuiltinBlocks.Air) { var adjD = adj + Vector3Int.down; if(!World.TryGetTypeAt(adjD, out ushort typeAdjD)) continue; if(typeAdjD == info.source) { _actions.Add(Time.MillisecondsSinceStart + info.time, delegate () { Remove(adjD, fluid); }); _SomeAction.Set(); } } } }
public static void Spread(Vector3Int position, EFluids fluid, int distance = int.MinValue, bool start = true) { //Log.Write(string.Format("<color=blue>Spread {0}</color>", position)); FluidInfo info = _fluids[(int)fluid]; if(distance == int.MinValue) distance = info.distance; if(distance <= 0) return; if(start) { Pipliz.Threading.ThreadManager.InvokeOnMainThread(() => { if(World.TryGetTypeAt(position, out ushort posType) && ( posType == BlockTypes.Builtin.BuiltinBlocks.Air || posType == info.fake )) ServerManager.TryChangeBlock(position, info.source); }); } else { Pipliz.Threading.ThreadManager.InvokeOnMainThread(() => { if(World.TryGetTypeAt(position, out ushort posType) && ( posType == BlockTypes.Builtin.BuiltinBlocks.Air )) ServerManager.TryChangeBlock(position, info.fake); }); } var down = position + Vector3Int.down; if(!World.TryGetTypeAt(down, out ushort typeDown)) return; //If DOWN is source -> IGNORE if(typeDown == info.source) return; //If down is air or fake.fluid -> SPREAD DOWN if(typeDown == BlockTypes.Builtin.BuiltinBlocks.Air || typeDown == info.fake) { _actions.Add(Time.MillisecondsSinceStart + info.time, delegate () { Spread(down, fluid); }); _SomeAction.Set(); return; } foreach(var adjacent in adjacents) { var adj = position + adjacent; if(!World.TryGetTypeAt(adj, out ushort typeAdj)) continue; if(typeAdj == BlockTypes.Builtin.BuiltinBlocks.Air || typeAdj == info.fake) { var adjDown = adj + Vector3Int.down; if(!World.TryGetTypeAt(adjDown, out ushort typeAdjD)) continue; if(typeAdjD == info.source) // Source continue; //Continue spreading down if(typeAdjD == BlockTypes.Builtin.BuiltinBlocks.Air) { _actions.Add(Time.MillisecondsSinceStart + info.time, delegate () { Spread(adjDown, fluid); }); _SomeAction.Set(); } else //Spread Side { _actions.Add(Time.MillisecondsSinceStart + info.time, delegate () { Spread(adj, fluid, distance - 1, false); }); _SomeAction.Set(); } } } }
public static void Remove(Vector3Int position, EFluids fluid, ushort newType = ushort.MaxValue) { //Log.Write(string.Format("<color=blue>Remove {0}</color>", position)); FluidInfo info = _fluids[(int)fluid]; if (!World.TryGetTypeAt(position, out ushort posToRemove) && (posToRemove != info.source && posToRemove != info.fake)) { return; } ThreadManager.InvokeOnMainThread(() => { if (newType == ushort.MaxValue) { ServerManager.TryChangeBlock(position, BlockTypes.BuiltinBlocks.Types.air); } else { ServerManager.TryChangeBlock(position, newType); } }); var down = position + Vector3Int.down; if (!World.TryGetTypeAt(down, out ushort typeDown)) { return; } //If DOWN is source if (typeDown == info.source) { _actions.Add(Time.MillisecondsSinceStart + info.time, delegate() { Remove(down, fluid); }); _SomeAction.Set(); return; } foreach (var adjacent in adjacents) { var adj = position + adjacent; if (!World.TryGetTypeAt(adj, out ushort typeAdj)) { continue; } if (typeAdj == info.fake) { _actions.Add(Time.MillisecondsSinceStart + info.time, delegate() { TryRemove(adj, fluid, info.distance - 1); }); _SomeAction.Set(); } else if (typeAdj == BlockTypes.BuiltinBlocks.Types.air.ItemIndex) { var adjD = adj + Vector3Int.down; if (!World.TryGetTypeAt(adjD, out ushort typeAdjD)) { continue; } if (typeAdjD == info.source) { _actions.Add(Time.MillisecondsSinceStart + info.time, delegate() { Remove(adjD, fluid); }); _SomeAction.Set(); } } } }