Terraria ModLoader  0.11.7.5
A mod to make and play Terraria mods
WallLoader.cs
Go to the documentation of this file.
1 using Microsoft.Xna.Framework.Graphics;
2 using System;
3 using System.Collections.Generic;
4 using System.IO;
5 using Terraria.ID;
6 
7 namespace Terraria.ModLoader
8 {
9  //todo: further documentation
13  public static class WallLoader
14  {
15  private static int nextWall = WallID.Count;
16  internal static readonly IList<ModWall> walls = new List<ModWall>();
17  internal static readonly IList<GlobalWall> globalWalls = new List<GlobalWall>();
18  private static bool loaded = false;
19 
20  private static Func<int, int, int, bool>[] HookKillSound;
21  private delegate void DelegateNumDust(int i, int j, int type, bool fail, ref int num);
22  private static DelegateNumDust[] HookNumDust;
23  private delegate bool DelegateCreateDust(int i, int j, int type, ref int dustType);
24  private static DelegateCreateDust[] HookCreateDust;
25  private delegate bool DelegateDrop(int i, int j, int type, ref int dropType);
26  private static DelegateDrop[] HookDrop;
27  private delegate void DelegateKillWall(int i, int j, int type, ref bool fail);
28  private static DelegateKillWall[] HookKillWall;
29  private static Func<int, int, int, bool>[] HookCanExplode;
30  private delegate void DelegateModifyLight(int i, int j, int type, ref float r, ref float g, ref float b);
31  private static DelegateModifyLight[] HookModifyLight;
32  private static Action<int, int, int>[] HookRandomUpdate;
33  private static Func<int, int, int, SpriteBatch, bool>[] HookPreDraw;
34  private static Action<int, int, int, SpriteBatch>[] HookPostDraw;
35  private static Action<int, int, int, Item>[] HookPlaceInWorld;
36 
37  internal static int ReserveWallID() {
38  if (ModNet.AllowVanillaClients) throw new Exception("Adding walls breaks vanilla client compatibility");
39 
40  int reserveID = nextWall;
41  nextWall++;
42  return reserveID;
43  }
44 
45  public static int WallCount => nextWall;
46 
50  public static ModWall GetWall(int type) {
51  return type >= WallID.Count && type < WallCount ? walls[type - WallID.Count] : null;
52  }
53 
54  private static void Resize2DArray<T>(ref T[,] array, int newSize) {
55  int dim1 = array.GetLength(0);
56  int dim2 = array.GetLength(1);
57  T[,] newArray = new T[newSize, dim2];
58  for (int j = 0; j < newSize && j < dim1; j++) {
59  for (int k = 0; k < dim2; k++) {
60  newArray[j, k] = array[j, k];
61  }
62  }
63  array = newArray;
64  }
65 
66  internal static void ResizeArrays(bool unloading = false) {
67  Array.Resize(ref Main.wallLoaded, nextWall);
68  for (int k = WallID.Count; k < nextWall; k++) {
69  Main.wallLoaded[k] = true;
70  }
71  Resize2DArray(ref Main.wallAltTexture, nextWall);
72  Resize2DArray(ref Main.wallAltTextureInit, nextWall);
73  Resize2DArray(ref Main.wallAltTextureDrawn, nextWall);
74  Array.Resize(ref Main.wallTexture, nextWall);
75  Array.Resize(ref Main.wallHouse, nextWall);
76  Array.Resize(ref Main.wallDungeon, nextWall);
77  Array.Resize(ref Main.wallLight, nextWall);
78  Array.Resize(ref Main.wallBlend, nextWall);
79  Array.Resize(ref Main.wallLargeFrames, nextWall);
80  Array.Resize(ref Main.wallFrame, nextWall);
81  Array.Resize(ref Main.wallFrameCounter, nextWall);
82  Array.Resize(ref WallID.Sets.Conversion.Grass, nextWall);
83  Array.Resize(ref WallID.Sets.Conversion.Stone, nextWall);
84  Array.Resize(ref WallID.Sets.Conversion.Sandstone, nextWall);
85  Array.Resize(ref WallID.Sets.Conversion.HardenedSand, nextWall);
86  Array.Resize(ref WallID.Sets.Transparent, nextWall);
87  Array.Resize(ref WallID.Sets.Corrupt, nextWall);
88  Array.Resize(ref WallID.Sets.Crimson, nextWall);
89  Array.Resize(ref WallID.Sets.Hallow, nextWall);
90 
91  ModLoader.BuildGlobalHook(ref HookKillSound, globalWalls, g => g.KillSound);
92  ModLoader.BuildGlobalHook(ref HookNumDust, globalWalls, g => g.NumDust);
93  ModLoader.BuildGlobalHook(ref HookCreateDust, globalWalls, g => g.CreateDust);
94  ModLoader.BuildGlobalHook(ref HookDrop, globalWalls, g => g.Drop);
95  ModLoader.BuildGlobalHook(ref HookKillWall, globalWalls, g => g.KillWall);
96  ModLoader.BuildGlobalHook(ref HookCanExplode, globalWalls, g => g.CanExplode);
97  ModLoader.BuildGlobalHook(ref HookModifyLight, globalWalls, g => g.ModifyLight);
98  ModLoader.BuildGlobalHook(ref HookRandomUpdate, globalWalls, g => g.RandomUpdate);
99  ModLoader.BuildGlobalHook(ref HookPreDraw, globalWalls, g => g.PreDraw);
100  ModLoader.BuildGlobalHook(ref HookPostDraw, globalWalls, g => g.PostDraw);
101  ModLoader.BuildGlobalHook(ref HookPlaceInWorld, globalWalls, g => g.PlaceInWorld);
102 
103  if (!unloading) {
104  loaded = true;
105  }
106  }
107 
108  internal static void Unload() {
109  loaded = false;
110  walls.Clear();
111  nextWall = WallID.Count;
112  globalWalls.Clear();
113  }
114 
115  //change type of Terraria.Tile.wall to ushort and fix associated compile errors
116  //in Terraria.IO.WorldFile.SaveWorldTiles increase length of array by 1 from 13 to 14
117  //in Terraria.IO.WorldFile.SaveWorldTiles inside block if (tile.wall != 0) after incrementing num2
118  // call WallLoader.WriteType(tile.wall, array, ref num2, ref b3);
119  internal static void WriteType(ushort wall, byte[] data, ref int index, ref byte flags) {
120  if (wall > 255) {
121  data[index] = (byte)(wall >> 8);
122  index++;
123  flags |= 32;
124  }
125  }
126  //in Terraria.IO.WorldFile.LoadWorldTiles after setting tile.wall call
127  // WallLoader.ReadType(ref tile.wall, reader, b, modWalls);
128  //in Terraria.IO.WorldFile.ValidateWorld before if ((b2 & 16) == 16)
129  // replace fileIO.ReadByte(); with ushort wall = fileIO.ReadByte();
130  // ushort _ = 0; WallLoader.ReadType(ref wall, fileIO, b2, new Dictionary<int, int>());
131  internal static void ReadType(ref ushort wall, BinaryReader reader, byte flags, IDictionary<int, int> wallTable) {
132  if ((flags & 32) == 32) {
133  wall |= (ushort)(reader.ReadByte() << 8);
134  }
135  if (wallTable.ContainsKey(wall)) {
136  wall = (ushort)wallTable[wall];
137  }
138  }
139  //in Terraria.WorldGen.KillWall add if(!WallLoader.KillSound(i, j, tile.wall)) { } to beginning of
140  // if/else chain for playing sounds, and turn first if into else if
141  public static bool KillSound(int i, int j, int type) {
142  foreach (var hook in HookKillSound) {
143  if (!hook(i, j, type)) {
144  return false;
145  }
146  }
147  ModWall modWall = GetWall(type);
148  if (modWall != null) {
149  if (!modWall.KillSound(i, j)) {
150  return false;
151  }
152  Main.PlaySound(modWall.soundType, i * 16, j * 16, modWall.soundStyle);
153  return false;
154  }
155  return true;
156  }
157  //in Terraria.WorldGen.KillWall after if statement setting num to 3 add
158  // WallLoader.NumDust(i, j, tile.wall, fail, ref num);
159  public static void NumDust(int i, int j, int type, bool fail, ref int numDust) {
160  GetWall(type)?.NumDust(i, j, fail, ref numDust);
161 
162  foreach (var hook in HookNumDust) {
163  hook(i, j, type, fail, ref numDust);
164  }
165  }
166  //in Terraria.WorldGen.KillWall before if statements creating dust add
167  // if(!WallLoader.CreateDust(i, j, tile.wall, ref int num2)) { continue; }
168  public static bool CreateDust(int i, int j, int type, ref int dustType) {
169  foreach (var hook in HookCreateDust) {
170  if (!hook(i, j, type, ref dustType)) {
171  return false;
172  }
173  }
174  return GetWall(type)?.CreateDust(i, j, ref dustType) ?? true;
175  }
176  //in Terraria.WorldGen.KillWall replace if (num4 > 0) with
177  // if (WallLoader.Drop(i, j, tile.wall, ref num4) && num4 > 0)
178  public static bool Drop(int i, int j, int type, ref int dropType) {
179  foreach (var hook in HookDrop) {
180  if (!hook(i, j, type, ref dropType)) {
181  return false;
182  }
183  }
184  return GetWall(type)?.Drop(i, j, ref dropType) ?? true;
185  }
186  //in Terraria.WorldGen.KillWall after if statements setting fail to true call
187  // WallLoader.KillWall(i, j, tile.wall, ref fail);
188  public static void KillWall(int i, int j, int type, ref bool fail) {
189  GetWall(type)?.KillWall(i, j, ref fail);
190 
191  foreach (var hook in HookKillWall) {
192  hook(i, j, type, ref fail);
193  }
194  }
195 
196  public static bool CanExplode(int i, int j, int type) {
197  foreach (var hook in HookCanExplode) {
198  if (!hook(i, j, type)) {
199  return false;
200  }
201  }
202  return GetWall(type)?.CanExplode(i, j) ?? true;
203  }
204  //in Terraria.Lighting.PreRenderPhase after wall modifies light call
205  // WallLoader.ModifyLight(n, num17, wall, ref num18, ref num19, ref num20);
206  public static void ModifyLight(int i, int j, int type, ref float r, ref float g, ref float b) {
207  GetWall(type)?.ModifyLight(i, j, ref r, ref g, ref b);
208 
209  foreach (var hook in HookModifyLight) {
210  hook(i, j, type, ref r, ref g, ref b);
211  }
212  }
213  //in Terraria.WorldGen.UpdateWorld after each call to TileLoader.RandomUpdate call
214  // WallLoader.RandomUpdate(num7, num8, Main.tile[num7, num8].wall);
215  // WallLoader.RandomUpdate(num64, num65, Main.tile[num64, num65].wall);
216  public static void RandomUpdate(int i, int j, int type) {
217  GetWall(type)?.RandomUpdate(i, j);
218 
219  foreach (var hook in HookRandomUpdate) {
220  hook(i, j, type);
221  }
222  }
223  //in Terraria.Main.Update after vanilla wall animations call WallLoader.AnimateWalls();
224  public static void AnimateWalls() {
225  if (loaded) {
226  for (int i = 0; i < walls.Count; i++) {
227  ModWall modWall = walls[i];
228  modWall.AnimateWall(ref Main.wallFrame[modWall.Type], ref Main.wallFrameCounter[modWall.Type]);
229  }
230  }
231  }
232  //in Terraria.Main.DrawWalls before if statements that do the drawing add
233  // if(!WallLoader.PreDraw(j, i, wall, Main.spriteBatch))
234  // { WallLoader.PostDraw(j, i, wall, Main.spriteBatch); continue; }
235  public static bool PreDraw(int i, int j, int type, SpriteBatch spriteBatch) {
236  foreach (var hook in HookPreDraw) {
237  if (!hook(i, j, type, spriteBatch)) {
238  return false;
239  }
240  }
241  return GetWall(type)?.PreDraw(i, j, spriteBatch) ?? true;
242  }
243  //in Terraria.Main.DrawWalls after wall outlines are drawn call
244  // WallLoader.PostDraw(j, i, wall, Main.spriteBatch);
245  public static void PostDraw(int i, int j, int type, SpriteBatch spriteBatch) {
246  GetWall(type)?.PostDraw(i, j, spriteBatch);
247 
248  foreach (var hook in HookPostDraw) {
249  hook(i, j, type, spriteBatch);
250  }
251  }
252 
253  public static void PlaceInWorld(int i, int j, Item item) {
254  int type = item.createWall;
255  if (type < 0)
256  return;
257 
258  foreach (var hook in HookPlaceInWorld) {
259  hook(i, j, type, item);
260  }
261 
262  GetWall(type)?.PlaceInWorld(i, j, item);
263  }
264  }
265 }
static void KillWall(int i, int j, int type, ref bool fail)
Definition: WallLoader.cs:188
static bool Drop(int i, int j, int type, ref int dropType)
Definition: WallLoader.cs:178
static bool AllowVanillaClients
Definition: ModNet.cs:53
static ModWall GetWall(int type)
Gets the ModWall instance with the given type. If no ModWall with the given type exists, returns null.
Definition: WallLoader.cs:50
static DelegateNumDust[] HookNumDust
Definition: WallLoader.cs:22
int soundStyle
The default style of sound made when this wall is hit. Defaults to 1.
Definition: ModWall.cs:46
static void PlaceInWorld(int i, int j, Item item)
Definition: WallLoader.cs:253
static bool KillSound(int i, int j, int type)
Definition: WallLoader.cs:141
virtual bool KillSound(int i, int j)
Allows you to customize which sound you want to play when the wall at the given coordinates is hit...
Definition: ModWall.cs:136
static Action< int, int, int, SpriteBatch >[] HookPostDraw
Definition: WallLoader.cs:34
This serves as the central class which loads mods. It contains many static fields and methods related...
Definition: ModLoader.cs:28
int soundType
The default type of sound made when this wall is hit. Defaults to 0.
Definition: ModWall.cs:42
static void RandomUpdate(int i, int j, int type)
Definition: WallLoader.cs:216
static void PostDraw(int i, int j, int type, SpriteBatch spriteBatch)
Definition: WallLoader.cs:245
ushort Type
The internal ID of this type of wall.
Definition: ModWall.cs:33
static bool PreDraw(int i, int j, int type, SpriteBatch spriteBatch)
Definition: WallLoader.cs:235
static Action< int, int, int, Item >[] HookPlaceInWorld
Definition: WallLoader.cs:35
static DelegateKillWall[] HookKillWall
Definition: WallLoader.cs:28
static Action< int, int, int >[] HookRandomUpdate
Definition: WallLoader.cs:32
This class represents a type of wall that can be added by a mod. Only one instance of this class will...
Definition: ModWall.cs:12
static bool CreateDust(int i, int j, int type, ref int dustType)
Definition: WallLoader.cs:168
This serves as the central class from which wall-related functions are supported and carried out...
Definition: WallLoader.cs:13
static DelegateDrop[] HookDrop
Definition: WallLoader.cs:26
static Func< int, int, int, bool >[] HookCanExplode
Definition: WallLoader.cs:29
static DelegateCreateDust[] HookCreateDust
Definition: WallLoader.cs:24
static DelegateModifyLight[] HookModifyLight
Definition: WallLoader.cs:31
static void NumDust(int i, int j, int type, bool fail, ref int numDust)
Definition: WallLoader.cs:159
static void ModifyLight(int i, int j, int type, ref float r, ref float g, ref float b)
Definition: WallLoader.cs:206
virtual void AnimateWall(ref byte frame, ref byte frameCounter)
Allows you to animate your wall. Use frameCounter to keep track of how long the current frame has bee...
Definition: ModWall.cs:197
static Func< int, int, int, bool >[] HookKillSound
Definition: WallLoader.cs:20
static bool CanExplode(int i, int j, int type)
Definition: WallLoader.cs:196
static Func< int, int, int, SpriteBatch, bool >[] HookPreDraw
Definition: WallLoader.cs:33