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 Init() { FluidInfo Water = new FluidInfo(); FluidInfo Lava = new FluidInfo(); Water.source = ItemTypes.IndexLookup.GetIndex("GreatWater"); Water.fake = ItemTypes.IndexLookup.GetIndex("GreatWaterFake"); Water.bucket = ItemTypes.IndexLookup.GetIndex("bucketwater"); //Lava.source = ItemTypes.IndexLookup.GetIndex("Khanx.SimpleFluids.Lava"); //Lava.fake = ItemTypes.IndexLookup.GetIndex("Khanx.SimpleFluids.Fake.Lava"); //Lava.bucket = ItemTypes.IndexLookup.GetIndex("Khanx.SimpleFluids.LavaBucket"); int w_spreadDistance = ConfigManager.GetConfigIntOrDefault(NewColonyAPIEntry.ModName, "fluids.water.spreaddistance", 8); if (w_spreadDistance > W_MAX_DISTANCE || w_spreadDistance < W_MIN_DISTANCE) { Helpers.Logging.WriteLog(NewColonyAPIEntry.ModName, string.Format("Water spreaddistance must be between {0} and {1}", W_MIN_DISTANCE, W_MAX_DISTANCE), Helpers.Logging.LogType.Loading); w_spreadDistance = W_DEFAULT_DISTANCE; } Water.distance = w_spreadDistance; long w_spreadSpeed = ConfigManager.GetConfigIntOrDefault(NewColonyAPIEntry.ModName, "fluids.water.spreadspeed", 350); if (w_spreadSpeed > W_MAX_SPEED || w_spreadSpeed < W_MIN_SPEED) { Helpers.Logging.WriteLog(NewColonyAPIEntry.ModName, string.Format("Water spreadspeed must be between {0} and {1}", W_MIN_SPEED, W_MAX_SPEED), Helpers.Logging.LogType.Loading); w_spreadSpeed = W_DEFAULT_SPEED; } Water.time = w_spreadSpeed; int l_spreadDistance = ConfigManager.GetConfigIntOrDefault(NewColonyAPIEntry.ModName, "fluids.lava.spreaddistance", 8); if (l_spreadDistance > L_MAX_DISTANCE || l_spreadDistance < L_MIN_DISTANCE) { Helpers.Logging.WriteLog(NewColonyAPIEntry.ModName, string.Format("Lava spreaddistance must be between {0} and {1}", L_MIN_DISTANCE, L_MAX_DISTANCE), Helpers.Logging.LogType.Loading); l_spreadDistance = L_DEFAULT_DISTANCE; } Lava.distance = l_spreadDistance; long l_spreadSpeed = ConfigManager.GetConfigIntOrDefault(NewColonyAPIEntry.ModName, "fluids.lava.spreadspeed", 350); if (l_spreadSpeed > L_MAX_SPEED || l_spreadSpeed < L_MIN_SPEED) { Helpers.Logging.WriteLog(NewColonyAPIEntry.ModName, string.Format("Lava spreadspeed must be between {0} and {1}", L_MIN_SPEED, L_MAX_SPEED), Helpers.Logging.LogType.Loading); w_spreadSpeed = L_DEFAULT_SPEED; } Lava.time = l_spreadSpeed; _fluids[(int)EFluids.Water] = Water; _fluids[(int)EFluids.Lava] = Lava; _FluidsThread.IsBackground = true; _FluidsThread.Start(); }
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) { ThreadManager.InvokeOnMainThread(() => { if (World.TryGetTypeAt(position, out ushort posToRemove) && (posToRemove == info.fake)) { ServerManager.TryChangeBlock(position, BlockTypes.BuiltinBlocks.Types.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.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(); } } } }
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) { ThreadManager.InvokeOnMainThread(() => { if (World.TryGetTypeAt(position, out ushort posType) && (posType == BlockTypes.BuiltinBlocks.Types.air.ItemIndex || posType == info.fake)) { ServerManager.TryChangeBlock(position, info.source); } }); } else { ThreadManager.InvokeOnMainThread(() => { if (World.TryGetTypeAt(position, out ushort posType) && (posType == BlockTypes.BuiltinBlocks.Types.air.ItemIndex)) { 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 || typeDown == BlockTypes.BuiltinBlocks.Types.water.ItemIndex) { return; } //If down is air or fake.fluid -> SPREAD DOWN if (typeDown == BlockTypes.BuiltinBlocks.Types.air.ItemIndex || 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.BuiltinBlocks.Types.air.ItemIndex || typeAdj == info.fake) { var adjDown = adj + Vector3Int.down; if (!World.TryGetTypeAt(adjDown, out ushort typeAdjD)) { continue; } if (typeAdjD == info.source || typeAdjD == BlockTypes.BuiltinBlocks.Types.water.ItemIndex) // Source { continue; } //Continue spreading down if (typeAdjD == BlockTypes.BuiltinBlocks.Types.air.ItemIndex) { _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(); } } } }