From f5243b56d20c5527217675558a1f5242ae9687a3 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Tue, 23 Feb 2016 22:45:21 +1100 Subject: [PATCH] Slightly optimise level physics and also make them work on Mono. --- Levels/Level.Physics.cs | 117 +++++++++++++++++++--------------------- Levels/Level.cs | 4 +- MCGalaxy_.csproj | 1 + util/FastList.cs | 87 ++++++++++++++++++++++++++++++ 4 files changed, 146 insertions(+), 63 deletions(-) create mode 100644 util/FastList.cs diff --git a/Levels/Level.Physics.cs b/Levels/Level.Physics.cs index acb0dd746..ed4bc1bff 100644 --- a/Levels/Level.Physics.cs +++ b/Levels/Level.Physics.cs @@ -111,13 +111,12 @@ namespace MCGalaxy { } public string foundInfo(ushort x, ushort y, ushort z) { - Check found = null; - try { - found = ListCheck.Find(Check => Check.b == PosToInt(x, y, z)); - } catch { + int index = PosToInt(x, y, z); + for (int i = 0; i < ListCheck.Count; i++) { + Check C = ListCheck.Items[i]; + if (C.b != index) continue; + return (C.data is string) ? (string)C.data : ""; } - if (found != null) - return (found.data is string) ? (string)found.data : ""; return ""; } @@ -127,56 +126,53 @@ namespace MCGalaxy { ushort x, y, z; lastCheck = ListCheck.Count; if (physics == 5) { - ListCheck.ForEach( - delegate(Check C) - { - try { - string info = C.data as string; - if (info == null) info = ""; - IntToPos(C.b, out x, out y, out z); - - if (PhysicsUpdate != null) - PhysicsUpdate(x, y, z, C.time, info, this); - if (info == "" || ExtraInfoPhysics.DoDoorsOnly(this, C, null)) - DoorPhysics.Do(this, C); - } catch { - ListCheck.Remove(C); - } - }); - } else { - var rand = new Random(); - ListCheck.ForEach( - delegate(Check C) - { - try { - IntToPos(C.b, out x, out y, out z); - string info = C.data as string; - if (info == null) info = ""; - - if (PhysicsUpdate != null) - PhysicsUpdate(x, y, z, C.time, info, this); - OnPhysicsUpdateEvent.Call(x, y, z, C.time, info, this); - if (info == "" || ExtraInfoPhysics.DoComplex(this, C, rand)) - DoNormalPhysics(x, y, z, rand, C); - } catch { - ListCheck.Remove(C); - } - }); - } - - ListCheck.RemoveAll(Check => Check.time == 255); //Remove all that are finished with 255 time - lastUpdate = ListUpdate.Count; - ListUpdate.ForEach( - delegate(Update C) - { + for (int i = 0; i < ListCheck.Count; i++) { + Check C = ListCheck.Items[i]; try { string info = C.data as string; if (info == null) info = ""; - Blockchange(C.b, C.type, false, info); + IntToPos(C.b, out x, out y, out z); + + if (PhysicsUpdate != null) + PhysicsUpdate(x, y, z, C.time, info, this); + if (info == "" || ExtraInfoPhysics.DoDoorsOnly(this, C, null)) + DoorPhysics.Do(this, C); } catch { - Server.s.Log("Phys update issue"); + ListCheck.Remove(C); } - }); + } + } else { + Random rand = new Random(); + for (int i = 0; i < ListCheck.Count; i++) { + Check C = ListCheck.Items[i]; + try { + IntToPos(C.b, out x, out y, out z); + string info = C.data as string; + if (info == null) info = ""; + + if (PhysicsUpdate != null) + PhysicsUpdate(x, y, z, C.time, info, this); + OnPhysicsUpdateEvent.Call(x, y, z, C.time, info, this); + if (info == "" || ExtraInfoPhysics.DoComplex(this, C, rand)) + DoNormalPhysics(x, y, z, rand, C); + } catch { + ListCheck.Remove(C); + } + } + } + + ListCheck.RemoveAll(C => C.time == 255); //Remove all that are finished with 255 time + lastUpdate = ListUpdate.Count; + for (int i = 0; i < ListUpdate.Count; i++) { + Update C = ListUpdate.Items[i]; + try { + string info = C.data as string; + if (info == null) info = ""; + Blockchange(C.b, C.type, false, info); + } catch { + Server.s.Log("Phys update issue"); + } + } ListUpdate.Clear(); } catch (Exception e) { Server.s.Log("Level physics error"); @@ -449,14 +445,12 @@ namespace MCGalaxy { public void AddCheck(int b, bool overRide, object data) { try { - if (!ListCheck.Exists(Check => Check.b == b)) { + int index = ListCheck.IndexOf(C => C.b == b); + if (index < 0) { ListCheck.Add(new Check(b, data)); //Adds block to list to be updated } else if (overRide) { - foreach (Check C2 in ListCheck) { - if (C2.b == b) { - C2.data = data; return; //Dont need to check physics here because if the list is active, then physics is active :) - } - } + ListCheck.Items[index].data = data; return; + //Dont need to check physics here because if the list is active, then physics is active :) } if (!physicssate && physics > 0) StartPhysics(); @@ -481,9 +475,9 @@ namespace MCGalaxy { return true; } - if (!ListUpdate.Exists(Update => Update.b == b)) { + if (!ListUpdate.Exists(C => C.b == b)) { } else if (type == Block.sand || type == Block.gravel) { - ListUpdate.RemoveAll(Update => Update.b == b); + ListUpdate.RemoveAll(C => C.b == b); } else { return false; } @@ -500,7 +494,8 @@ namespace MCGalaxy { } public void ClearPhysics() { - ListCheck.ForEach(C => RevertPhysics(C)); + for (int i = 0; i < ListCheck.Count; i++ ) + RevertPhysics(ListCheck.Items[i]); ListCheck.Clear(); ListUpdate.Clear(); } @@ -704,7 +699,7 @@ namespace MCGalaxy { case Block.gravel: case Block.wood_float: AddCheck(b); break; - default: + default: break; } } diff --git a/Levels/Level.cs b/Levels/Level.cs index 33a39aec3..33d15d441 100644 --- a/Levels/Level.cs +++ b/Levels/Level.cs @@ -67,8 +67,8 @@ namespace MCGalaxy public static bool cancelload; public static bool cancelsave; public static bool cancelphysics; - internal readonly List ListCheck = new List(); //A list of blocks that need to be updated - internal readonly List ListUpdate = new List(); //A list of block to change after calculation + internal readonly FastList ListCheck = new FastList(); //A list of blocks that need to be updated + internal readonly FastList ListUpdate = new FastList(); //A list of block to change after calculation internal readonly Dictionary leaves = new Dictionary(); // Holds block state for leaf decay diff --git a/MCGalaxy_.csproj b/MCGalaxy_.csproj index e2159fc19..cb6476564 100644 --- a/MCGalaxy_.csproj +++ b/MCGalaxy_.csproj @@ -569,6 +569,7 @@ + EcoLevelWindow.cs diff --git a/util/FastList.cs b/util/FastList.cs new file mode 100644 index 000000000..4de76aeae --- /dev/null +++ b/util/FastList.cs @@ -0,0 +1,87 @@ +/* + Copyright 2015 MCGalaxy + + Dual-licensed under the Educational Community License, Version 2.0 and + the GNU General Public License, Version 3 (the "Licenses"); you may + not use this file except in compliance with the Licenses. You may + obtain a copy of the Licenses at + + http://www.opensource.org/licenses/ecl2.php + http://www.gnu.org/licenses/gpl-3.0.html + + Unless required by applicable law or agreed to in writing, + software distributed under the Licenses are distributed on an "AS IS" + BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + or implied. See the Licenses for the specific language governing + permissions and limitations under the Licenses. + */ +using System; + +namespace MCGalaxy { + + public class FastList { + + public T[] Items; + public int Count; + + public FastList() { Items = new T[4]; } + + public FastList(int capacity) { Items = new T[capacity]; } + + public void Add(T item) { + if (Count == Items.Length) EnsureCapacity(Count + 1); + Items[Count++] = item; + } + + public void Clear() { + if (Count == 0) return; + Array.Clear(Items, 0, Count); + Count = 0; + } + + public bool Exists(Predicate condition) { + for (int i = 0; i < Count; i++) { + if (condition(Items[i])) return true; + } + return false; + } + + public int IndexOf(Predicate condition) { + for (int i = 0; i < Count; i++) { + if (condition(Items[i])) return i; + } + return -1; + } + + public bool Remove(T item) { + int index = Array.IndexOf(Items, item, 0, Count); + if (index < 0) return false; + + Count--; + if (index < Count) + Array.Copy(Items, index + 1, Items, index, Count - index); + Items[Count] = default(T); + return true; + } + + public void RemoveAll(Predicate condition) { + int j = 0; + for (int i = 0; i < Count; i++) { + if (condition(Items[i])) continue; + Items[j] = Items[i]; j++; + } + Count = j; + } + + void EnsureCapacity(int threshold) { + if (Items.Length >= threshold) return; + int newSize = Items.Length * 2; + if (newSize < threshold) newSize = threshold; + + T[] array = new T[newSize]; + if (Count > 0) + Array.Copy(Items, 0, array, 0, Count); + Items = array; + } + } +}