/MCSharp/Commands/Block/CmdCuboid.cs

http://github.com/Voziv/MCSharp · C# · 212 lines · 172 code · 17 blank · 23 comment · 95 complexity · 532d50de5c3c631d0600cd92ba7cdaa1 MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using MCSharp.World;
  4. namespace MCSharp
  5. {
  6. public class CmdCuboid : Command
  7. {
  8. // Constructor
  9. public CmdCuboid (CommandGroup g, GroupEnum group, string name) : base(g, group, name) { blnConsoleSupported = false; /* By default no console support*/ }
  10. // Command usage help
  11. public override void Help (Player p)
  12. {
  13. p.SendMessage("/cuboid [type] <solid/hollow/walls> - create a cuboid of blocks.");
  14. }
  15. // Code to run when used by a player
  16. public override void Use (Player p, string message)
  17. {
  18. int number = message.Split(' ').Length;
  19. if (number > 2) { Help(p); return; }
  20. // example, /cuboid op_white walls
  21. if (number == 2)
  22. {
  23. int pos = message.IndexOf(' ');
  24. string t = message.Substring(0, pos).ToLower();
  25. string s = message.Substring(pos + 1).ToLower();
  26. byte type = Block.Byte(t);
  27. if (type == 255) { p.SendMessage("There is no block \"" + t + "\"."); return; }
  28. if (Server.advbuilders.Contains(p.name))
  29. {
  30. if (!Block.Placable(type) && !Block.AdvPlacable(type)) { p.SendMessage("Your not allowed to place that."); return; }
  31. }
  32. SolidType solid;
  33. if (s == "solid") { solid = SolidType.solid; }
  34. else if (s == "hollow") { solid = SolidType.hollow; }
  35. else if (s == "walls") { solid = SolidType.walls; }
  36. else { Help(p); return; }
  37. CatchPos cpos = new CatchPos(); cpos.solid = solid; cpos.type = type;
  38. cpos.x = 0; cpos.y = 0; cpos.z = 0; p.blockchangeObject = cpos;
  39. }
  40. // Example, /cuboid op_white
  41. // Example, /cuboid walls
  42. else if (message != "")
  43. {
  44. SolidType solid = SolidType.solid;
  45. message = message.ToLower();
  46. byte type; unchecked { type = (byte) -1; }
  47. if (message == "solid") { solid = SolidType.solid; }
  48. else if (message == "hollow") { solid = SolidType.hollow; }
  49. else if (message == "walls") { solid = SolidType.walls; }
  50. else
  51. {
  52. byte t = Block.Byte(message);
  53. if (t == 255) { p.SendMessage("There is no block \"" + message + "\"."); return; }
  54. if (p.Rank == GroupEnum.AdvBuilder)
  55. {
  56. if (!Block.Placable(t) && !Block.AdvPlacable(t)) { p.SendMessage("Your not allowed to place that."); return; }
  57. }
  58. type = t;
  59. } CatchPos cpos = new CatchPos(); cpos.solid = solid; cpos.type = type;
  60. cpos.x = 0; cpos.y = 0; cpos.z = 0; p.blockchangeObject = cpos;
  61. }
  62. // Example, /cuboid
  63. // Take currently held block
  64. else
  65. {
  66. CatchPos cpos = new CatchPos(); cpos.solid = SolidType.solid; unchecked { cpos.type = (byte) -1; }
  67. cpos.x = 0; cpos.y = 0; cpos.z = 0; p.blockchangeObject = cpos;
  68. }
  69. p.SendMessage("Place two blocks to determine the edges.");
  70. p.ClearBlockchange();
  71. p.Blockchange += new Player.BlockchangeEventHandler(Blockchange1);
  72. }
  73. // Grab First Pos
  74. // First block change (defining first corner)
  75. // Figure out what kind of cuboid
  76. // Process Changes to the world
  77. public void Blockchange1 (Player p, ushort x, ushort y, ushort z, byte type)
  78. {
  79. p.ClearBlockchange();
  80. byte b = p.level.GetTile(x, y, z);
  81. p.SendBlockchange(x, y, z, b);
  82. CatchPos bp = (CatchPos) p.blockchangeObject;
  83. bp.x = x; bp.y = y; bp.z = z; p.blockchangeObject = bp;
  84. p.Blockchange += new Player.BlockchangeEventHandler(Blockchange2);
  85. }
  86. // Second block change (defining second corner)
  87. public void Blockchange2 (Player p, ushort x, ushort y, ushort z, byte type)
  88. {
  89. p.ClearBlockchange();
  90. byte b = p.level.GetTile(x, y, z);
  91. p.SendBlockchange(x, y, z, b);
  92. CatchPos cpos = (CatchPos) p.blockchangeObject;
  93. unchecked { if (cpos.type != (byte) -1) { type = cpos.type; } }
  94. List<Pos> buffer = new List<Pos>();
  95. // Solid is default
  96. switch (cpos.solid)
  97. {
  98. case SolidType.solid:
  99. // redundant?
  100. if (Math.Abs(cpos.x - x) * Math.Abs(cpos.y - y) * Math.Abs(cpos.z - z) > p.group.CuboidLimit && p.group.CuboidLimit != 0)
  101. {
  102. p.SendMessage("You're trying to place " + buffer.Count.ToString() + " blocks.");
  103. p.SendMessage("Your block limit is " + p.group.CuboidLimit.ToString() + " blocks. Build in stages.");
  104. return;
  105. }
  106. // end redundant?
  107. buffer.Capacity = Math.Abs(cpos.x - x) * Math.Abs(cpos.y - y) * Math.Abs(cpos.z - z);
  108. // Nested for loops to cover a solid cube
  109. for (ushort xx = Math.Min(cpos.x, x); xx <= Math.Max(cpos.x, x); ++xx)
  110. for (ushort yy = Math.Min(cpos.y, y); yy <= Math.Max(cpos.y, y); ++yy)
  111. for (ushort zz = Math.Min(cpos.z, z); zz <= Math.Max(cpos.z, z); ++zz)
  112. if (p.level.GetTile(xx, yy, zz) != type) { BufferAdd(buffer, xx, yy, zz); }
  113. break;
  114. case SolidType.hollow:
  115. // TODO: Work out if theres 800 blocks used before making the buffer
  116. // Hollow will build only the outer shell of a cube leaving the center alone
  117. for (ushort yy = Math.Min(cpos.y, y); yy <= Math.Max(cpos.y, y); ++yy)
  118. for (ushort zz = Math.Min(cpos.z, z); zz <= Math.Max(cpos.z, z); ++zz)
  119. {
  120. if (p.level.GetTile(cpos.x, yy, zz) != type) { BufferAdd(buffer, cpos.x, yy, zz); }
  121. if (cpos.x != x) { if (p.level.GetTile(x, yy, zz) != type) { BufferAdd(buffer, x, yy, zz); } }
  122. }
  123. if (Math.Abs(cpos.x - x) >= 2)
  124. {
  125. for (ushort xx = (ushort) (Math.Min(cpos.x, x) + 1); xx <= Math.Max(cpos.x, x) - 1; ++xx)
  126. for (ushort zz = Math.Min(cpos.z, z); zz <= Math.Max(cpos.z, z); ++zz)
  127. {
  128. if (p.level.GetTile(xx, cpos.y, zz) != type) { BufferAdd(buffer, xx, cpos.y, zz); }
  129. if (cpos.y != y) { if (p.level.GetTile(xx, y, zz) != type) { BufferAdd(buffer, xx, y, zz); } }
  130. }
  131. if (Math.Abs(cpos.y - y) >= 2)
  132. {
  133. for (ushort xx = (ushort) (Math.Min(cpos.x, x) + 1); xx <= Math.Max(cpos.x, x) - 1; ++xx)
  134. for (ushort yy = (ushort) (Math.Min(cpos.y, y) + 1); yy <= Math.Max(cpos.y, y) - 1; ++yy)
  135. {
  136. if (p.level.GetTile(xx, yy, cpos.z) != type) { BufferAdd(buffer, xx, yy, cpos.z); }
  137. if (cpos.z != z) { if (p.level.GetTile(xx, yy, z) != type) { BufferAdd(buffer, xx, yy, z); } }
  138. }
  139. }
  140. }
  141. break;
  142. // Walls builds only the surrounding vertical borders of a cube
  143. case SolidType.walls:
  144. for (ushort yy = Math.Min(cpos.y, y); yy <= Math.Max(cpos.y, y); ++yy)
  145. for (ushort zz = Math.Min(cpos.z, z); zz <= Math.Max(cpos.z, z); ++zz)
  146. {
  147. if (p.level.GetTile(cpos.x, yy, zz) != type) { BufferAdd(buffer, cpos.x, yy, zz); }
  148. if (cpos.x != x) { if (p.level.GetTile(x, yy, zz) != type) { BufferAdd(buffer, x, yy, zz); } }
  149. }
  150. if (Math.Abs(cpos.x - x) >= 2)
  151. {
  152. if (Math.Abs(cpos.z - z) >= 2)
  153. {
  154. for (ushort xx = (ushort) (Math.Min(cpos.x, x) + 1); xx <= Math.Max(cpos.x, x) - 1; ++xx)
  155. for (ushort yy = (ushort) (Math.Min(cpos.y, y)); yy <= Math.Max(cpos.y, y); ++yy)
  156. {
  157. if (p.level.GetTile(xx, yy, cpos.z) != type) { BufferAdd(buffer, xx, yy, cpos.z); }
  158. if (cpos.z != z) { if (p.level.GetTile(xx, yy, z) != type) { BufferAdd(buffer, xx, yy, z); } }
  159. }
  160. }
  161. }
  162. break;
  163. }
  164. // Why are we running this in the solid case statement as well?
  165. if (buffer.Count > p.group.CuboidLimit && p.group.CuboidLimit != 0)
  166. {
  167. p.SendMessage("You're trying to place " + buffer.Count.ToString() + " blocks.");
  168. p.SendMessage("Your block limit is " + p.group.CuboidLimit.ToString() + " blocks. Build in stages.");
  169. return;
  170. }
  171. p.SendMessage(buffer.Count.ToString() + " blocks.");
  172. // This code may not be needed. We already check whether the player can place the block near the top of this class
  173. if (!Server.advbuilders.Contains(p.name))
  174. {
  175. buffer.ForEach(delegate(Pos pos)
  176. {
  177. p.level.Blockchange(p, pos.x, pos.y, pos.z, type); //update block for everyone
  178. });
  179. }
  180. else
  181. {
  182. buffer.ForEach(delegate(Pos pos)
  183. {
  184. byte bl = p.level.GetTile(pos.x, pos.y, pos.z);
  185. if (Block.Placable(bl) || Block.AdvPlacable(bl)) { p.level.Blockchange(p, pos.x, pos.y, pos.z, type); } //update block for everyone
  186. });
  187. }
  188. // end possibly not needed code
  189. }
  190. void BufferAdd (List<Pos> list, ushort x, ushort y, ushort z)
  191. {
  192. Pos pos; pos.x = x; pos.y = y; pos.z = z; list.Add(pos);
  193. }
  194. }
  195. }