public static INamedTileCollection CreateReadonlyTileProvider(string Name, int X, int Y, int Width, int Height, ITile[,] CopyFrom, int Layer = 0) { Type newType = Helper.CreateType(); Type tileProviderType = typeof(ReadonlyTileProvider <>).MakeGenericType(newType); INamedTileCollection result = (INamedTileCollection)Activator.CreateInstance(tileProviderType, true); ((dynamic)result).Initialize(Name, X, Y, Width, Height, CopyFrom, Layer); typeof(TileReference <>) .MakeGenericType(newType) .GetField("_Provider", BindingFlags.NonPublic | BindingFlags.Static) .SetValue(null, result); typeof(ReadonlyTileReference <>) .MakeGenericType(newType) .GetField("_Provider", BindingFlags.NonPublic | BindingFlags.Static) .SetValue(null, result); lock (FakeProviderPlugin.ProvidersToAdd) { if (FakeProviderPlugin.ProvidersLoaded) { Tile.Add(result); } else { FakeProviderPlugin.ProvidersToAdd.Add(result); } } return(result); }
public void UpdateRectangleReferences(int X, int Y, int Width, int Height, int RemoveIndex) { if (!FakeProviderPlugin.ProvidersLoaded) { return; } lock (Locker) { (X, Y, Width, Height) = Clamp(X, Y, Width, Height); Queue <INamedTileCollection> providers = new Queue <INamedTileCollection>(); foreach (INamedTileCollection provider in Order) { if (provider.Enabled) { ushort providerIndex = (ushort)provider.Index; // Update tiles Intersect(provider, X, Y, Width, Height, out int x, out int y, out int width, out int height); int dx = x - provider.X; int dy = y - provider.Y; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { ProviderIndexes[x + i, y + j] = providerIndex; } } if (width > 0 && height > 0) { providers.Enqueue(provider); } } } if (RemoveIndex >= 0) { for (int i = X; i < X + Width; i++) { for (int j = Y; j < Y + Height; j++) { if (ProviderIndexes[i, j] == RemoveIndex) { ProviderIndexes[i, j] = 0; } } } } // We are updating all the stuff only after tiles update since signs, // chests and entities apply only in case the tile on top is from this provider. while (providers.Count > 0) { INamedTileCollection provider = providers.Dequeue(); provider.UpdateEntities(); } } }
public void Clear(INamedTileCollection except = null) { lock (Locker) foreach (INamedTileCollection provider in Order.ToArray()) { if (provider != except) { Remove(provider.Name, true, false); } } GC.Collect(); }
public bool SetTop(string Name, bool Draw = true) { lock (Locker) { INamedTileCollection provider = Order.FirstOrDefault(p => (p.Name == Name)); if (provider == null) { return(false); } provider.SetTop(Draw); return(true); } }
public void ScanRectangle(int X, int Y, int Width, int Height, INamedTileCollection IgnoreProvider = null) { lock (Locker) foreach (INamedTileCollection provider in Order) { if (provider != IgnoreProvider) { Intersect(provider, X, Y, Width, Height, out int x, out int y, out int width, out int height); if (width > 0 && height > 0) { provider.ScanEntities(); } } } }
internal static void Intersect(INamedTileCollection Provider, int X, int Y, int Width, int Height, out int RX, out int RY, out int RWidth, out int RHeight) { int ex1 = Provider.X + Provider.Width; int ex2 = X + Width; int ey1 = Provider.Y + Provider.Height; int ey2 = Y + Height; int maxSX = (Provider.X > X) ? Provider.X : X; int maxSY = (Provider.Y > Y) ? Provider.Y : Y; int minEX = (ex1 < ex2) ? ex1 : ex2; int minEY = (ey1 < ey2) ? ey1 : ey2; RX = maxSX; RY = maxSY; RWidth = minEX - maxSX; RHeight = minEY - maxSY; }
internal void PlaceProviderOnTopOfLayer(INamedTileCollection Provider) { lock (Locker) { Order.Remove(Provider); int order = Order.FindIndex(p => (p.Layer > Provider.Layer)); if (order == -1) { order = Order.Count; } Order.Insert(order, Provider); for (int i = order; i < Order.Count; i++) { dynamic provider = Order[i]; provider.Order = i; } } }
public void UpdateProviderReferences(INamedTileCollection Provider) { if (!Provider.Enabled || !FakeProviderPlugin.ProvidersLoaded) { return; } lock (Locker) { ushort providerIndex = (ushort)Provider.Index; // Scanning rectangle where this provider is/will appear. ScanRectangle(Provider.X, Provider.Y, Provider.Width, Provider.Height, Provider); // Update tiles int order = Provider.Order; (int x, int y, int width, int height) = Provider.ClampXYWH(); for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { ushort providerIndexOnTop = ProviderIndexes[x + i, y + j]; IProviderTile tile = _Providers[providerIndexOnTop][x + i, y + j]; if (tile == null || tile.Provider.Order <= order || !tile.Provider.Enabled) { ProviderIndexes[x + i, y + j] = providerIndex; } } } foreach (INamedTileCollection provider in Order) { Intersect(provider, x, y, width, height, out int x2, out int y2, out int width2, out int height2); if (width2 > 0 && height2 > 0) { provider.UpdateEntities(); } } } }
public static bool FindProvider(string name, TSPlayer player, out INamedTileCollection found) { found = null; List <INamedTileCollection> foundProviders = new List <INamedTileCollection>(); string lowerName = name.ToLower(); foreach (INamedTileCollection provider in FakeProviderAPI.Tile.Providers) { if (provider == null) { continue; } if (provider.Name == name) { found = provider; return(true); } else if (provider.Name.ToLower().StartsWith(lowerName)) { foundProviders.Add(provider); } } if (foundProviders.Count == 0) { player?.SendErrorMessage($"Invalid provider '{name}'."); return(false); } else if (foundProviders.Count > 1) { if (player != null) { TShock.Utils.SendMultipleMatchError(player, foundProviders); } return(false); } else { found = foundProviders[0]; return(true); } }
public bool Remove(string Name, bool Draw = true, bool Cleanup = true) { if (Name == VoidProviderName) { throw new InvalidOperationException("You cannot remove void provider."); } lock (Locker) using (INamedTileCollection provider = Order.FirstOrDefault(p => (p.Name == Name))) { if (provider == null) { return(false); } provider.Disable(Draw); Order.Remove(provider); _Providers[provider.Index] = null; } if (Cleanup) { GC.Collect(); } return(true); }