/Commands/CmdSpheroid.cs

https://github.com/cazzar/MCaznowl-Build · C# · 241 lines · 186 code · 27 blank · 28 comment · 50 complexity · 7366d336a097738eb9db58cb00ab9c36 MD5 · raw file

  1. /*
  2. Copyright 2011 MCForge
  3. Dual-licensed under the Educational Community License, Version 2.0 and
  4. the GNU General Public License, Version 3 (the "Licenses"); you may
  5. not use this file except in compliance with the Licenses. You may
  6. obtain a copy of the Licenses at
  7. http://www.opensource.org/licenses/ecl2.php
  8. http://www.gnu.org/licenses/gpl-3.0.html
  9. Unless required by applicable law or agreed to in writing,
  10. software distributed under the Licenses are distributed on an "AS IS"
  11. BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
  12. or implied. See the Licenses for the specific language governing
  13. permissions and limitations under the Licenses.
  14. */
  15. using System;
  16. using System.Collections.Generic;
  17. using MCForge;
  18. namespace MCForge.Commands
  19. {
  20. public class CmdSpheroid : Command
  21. {
  22. public override string name { get { return "spheroid"; } }
  23. public override string shortcut { get { return "e"; } }
  24. public override string type { get { return "build"; } }
  25. public override bool museumUsable { get { return false; } }
  26. public override LevelPermission defaultRank { get { return LevelPermission.Builder; } }
  27. public CmdSpheroid() { }
  28. public static byte wait = 0;
  29. public override void Use(Player p, string message)
  30. {
  31. wait = 0;
  32. CatchPos cpos;
  33. cpos.x = 0; cpos.y = 0; cpos.z = 0;
  34. if (message == "")
  35. {
  36. cpos.type = Block.Zero;
  37. cpos.vertical = false;
  38. }
  39. else if (message.IndexOf(' ') == -1)
  40. {
  41. cpos.type = Block.Byte(message);
  42. cpos.vertical = false;
  43. if (message.ToLower() != "vertical" && !Block.canPlace(p, cpos.type)) { Player.SendMessage(p, "Cannot place that."); wait = 1; return; }
  44. if (cpos.type == Block.Zero)
  45. {
  46. if (message.ToLower() == "vertical")
  47. {
  48. cpos.vertical = true;
  49. }
  50. else
  51. {
  52. Help(p); wait = 1; return;
  53. }
  54. }
  55. }
  56. else
  57. {
  58. cpos.type = Block.Byte(message.Split(' ')[0]);
  59. if (!Block.canPlace(p, cpos.type)) { Player.SendMessage(p, "Cannot place that."); wait = 1; return; }
  60. if (cpos.type == Block.Zero || message.Split(' ')[1].ToLower() != "vertical")
  61. {
  62. Help(p); wait = 1; return;
  63. }
  64. cpos.vertical = true;
  65. }
  66. if (!Block.canPlace(p, cpos.type) && cpos.type != Block.Zero) { Player.SendMessage(p, "Cannot place this block type!"); wait = 1; return; }
  67. p.blockchangeObject = cpos;
  68. Player.SendMessage(p, "Place two blocks to determine the edges.");
  69. p.ClearBlockchange();
  70. p.Blockchange += new Player.BlockchangeEventHandler(Blockchange1);
  71. }
  72. public override void Help(Player p)
  73. {
  74. Player.SendMessage(p, "/spheroid [type] <vertical> - Create a spheroid of blocks.");
  75. Player.SendMessage(p, "If <vertical> is added, it will be a vertical tube");
  76. }
  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. public void Blockchange2(Player p, ushort x, ushort y, ushort z, byte type)
  87. {
  88. p.ClearBlockchange();
  89. byte b = p.level.GetTile(x, y, z);
  90. p.SendBlockchange(x, y, z, b);
  91. CatchPos cpos = (CatchPos)p.blockchangeObject;
  92. if (cpos.type != Block.Zero) { type = cpos.type; }
  93. List<Pos> buffer = new List<Pos>();
  94. if (!cpos.vertical)
  95. {
  96. /* Courtesy of fCraft's awesome Open-Source'ness :D */
  97. // find start/end coordinates
  98. int sx = Math.Min(cpos.x, x);
  99. int ex = Math.Max(cpos.x, x);
  100. int sy = Math.Min(cpos.y, y);
  101. int ey = Math.Max(cpos.y, y);
  102. int sz = Math.Min(cpos.z, z);
  103. int ez = Math.Max(cpos.z, z);
  104. // find center points
  105. double cx = (ex + sx) / 2 + (((ex + sx) % 2 == 1) ? 0.5 : 0);
  106. double cy = (ey + sy) / 2 + (((ey + sy) % 2 == 1) ? 0.5 : 0);
  107. double cz = (ez + sz) / 2 + (((ez + sz) % 2 == 1) ? 0.5 : 0);
  108. // find axis lengths
  109. double rx = Convert.ToDouble(ex) - cx + 0.25;
  110. double ry = Convert.ToDouble(ey) - cy + 0.25;
  111. double rz = Convert.ToDouble(ez) - cz + 0.25;
  112. double rx2 = 1 / (rx * rx);
  113. double ry2 = 1 / (ry * ry);
  114. double rz2 = 1 / (rz * rz);
  115. int totalBlocks = (int)(Math.PI * 0.75 * rx * ry * rz);
  116. if (totalBlocks > p.group.maxBlocks)
  117. {
  118. Player.SendMessage(p, "You tried to spheroid " + totalBlocks + " blocks.");
  119. Player.SendMessage(p, "You cannot spheroid more than " + p.group.maxBlocks + ".");
  120. wait = 1;
  121. return;
  122. }
  123. Player.SendMessage(p, totalBlocks + " blocks.");
  124. for (int xx = sx; xx <= ex; xx += 8)
  125. for (int yy = sy; yy <= ey; yy += 8)
  126. for (int zz = sz; zz <= ez; zz += 8)
  127. for (int z3 = 0; z3 < 8 && zz + z3 <= ez; z3++)
  128. for (int y3 = 0; y3 < 8 && yy + y3 <= ey; y3++)
  129. for (int x3 = 0; x3 < 8 && xx + x3 <= ex; x3++)
  130. {
  131. // get relative coordinates
  132. double dx = (xx + x3 - cx);
  133. double dy = (yy + y3 - cy);
  134. double dz = (zz + z3 - cz);
  135. // test if it's inside ellipse
  136. if ((dx * dx) * rx2 + (dy * dy) * ry2 + (dz * dz) * rz2 <= 1)
  137. {
  138. p.level.Blockchange(p, (ushort)(x3 + xx), (ushort)(yy + y3), (ushort)(zz + z3), type);
  139. }
  140. }
  141. }
  142. else
  143. {
  144. // find start/end coordinates
  145. int sx = Math.Min(cpos.x, x);
  146. int ex = Math.Max(cpos.x, x);
  147. int sy = Math.Min(cpos.y, y);
  148. int ey = Math.Max(cpos.y, y);
  149. int sz = Math.Min(cpos.z, z);
  150. int ez = Math.Max(cpos.z, z);
  151. // find center points
  152. double cx = (ex + sx) / 2 + (((ex + sx) % 2 == 1) ? 0.5 : 0);
  153. double cz = (ez + sz) / 2 + (((ez + sz) % 2 == 1) ? 0.5 : 0);
  154. // find axis lengths
  155. double rx = Convert.ToDouble(ex) - cx + 0.25;
  156. double rz = Convert.ToDouble(ez) - cz + 0.25;
  157. double rx2 = 1 / (rx * rx);
  158. double rz2 = 1 / (rz * rz);
  159. double smallrx2 = 1 / ((rx - 1) * (rx - 1));
  160. double smallrz2 = 1 / ((rz - 1) * (rz - 1));
  161. Pos pos = new Pos();
  162. for (int xx = sx; xx <= ex; xx += 8)
  163. for (int zz = sz; zz <= ez; zz += 8)
  164. for (int z3 = 0; z3 < 8 && zz + z3 <= ez; z3++)
  165. for (int x3 = 0; x3 < 8 && xx + x3 <= ex; x3++)
  166. {
  167. // get relative coordinates
  168. double dx = (xx + x3 - cx);
  169. double dz = (zz + z3 - cz);
  170. // test if it's inside ellipse
  171. if ((dx * dx) * rx2 + (dz * dz) * rz2 <= 1 && (dx * dx) * smallrx2 + (dz * dz) * smallrz2 > 1)
  172. {
  173. pos.x = (ushort)(x3 + xx);
  174. pos.y = (ushort)(sy);
  175. pos.z = (ushort)(zz + z3);
  176. buffer.Add(pos);
  177. }
  178. }
  179. int ydiff = Math.Abs(y - cpos.y) + 1;
  180. if (buffer.Count * ydiff > p.group.maxBlocks)
  181. {
  182. Player.SendMessage(p, "You tried to spheroid " + buffer.Count * ydiff + " blocks.");
  183. Player.SendMessage(p, "You cannot spheroid more than " + p.group.maxBlocks + ".");
  184. wait = 1;
  185. return;
  186. }
  187. Player.SendMessage(p, buffer.Count * ydiff + " blocks.");
  188. foreach (Pos Pos in buffer)
  189. {
  190. for (ushort yy = (ushort)sy; yy <= (ushort)ey; yy++)
  191. {
  192. p.level.Blockchange(p, Pos.x, yy, Pos.z, type);
  193. }
  194. }
  195. }
  196. wait = 2;
  197. if (p.staticCommands) p.Blockchange += new Player.BlockchangeEventHandler(Blockchange1);
  198. }
  199. void BufferAdd(List<Pos> list, ushort x, ushort y, ushort z)
  200. {
  201. Pos pos; pos.x = x; pos.y = y; pos.z = z; list.Add(pos);
  202. }
  203. struct Pos { public ushort x, y, z; }
  204. struct CatchPos
  205. {
  206. public byte type;
  207. public ushort x, y, z;
  208. public bool vertical;
  209. }
  210. }
  211. }