static int LargestDelta(Level lvl, Vec3S32 point) { Vec3S32 clamped; clamped.X = Math.Max(0, Math.Min(point.X, lvl.Width - 1)); clamped.Y = Math.Max(0, Math.Min(point.Y, lvl.Height - 1)); clamped.Z = Math.Max(0, Math.Min(point.Z, lvl.Length - 1)); int dx = Math.Abs(point.X - clamped.X); int dy = Math.Abs(point.Y - clamped.Y); int dz = Math.Abs(point.Z - clamped.Z); return(Math.Max(dx, Math.Max(dy, dz))); }
internal static bool GetTeleportCoords(Player p, Entity ori, string[] args, bool precise, out Position pos, out byte yaw, out byte pitch) { Vec3S32 P; pos = p.Pos; yaw = ori.Rot.RotY; pitch = ori.Rot.HeadX; if (!precise) { // relative to feet block coordinates P = p.Pos.FeetBlockCoords; if (!CommandParser.GetCoords(p, args, 0, ref P)) { return(false); } pos = Position.FromFeetBlockCoords(P.X, P.Y, P.Z); } else { // relative to feet position exactly P = new Vec3S32(p.Pos.X, p.Pos.Y + Entities.CharacterHeight, p.Pos.Z); if (!CommandParser.GetCoords(p, args, 0, ref P)) { return(false); } pos = new Position(P.X, P.Y - Entities.CharacterHeight, P.Z); } int angle = 0; if (args.Length > 3) { if (!CommandParser.GetInt(p, args[3], "Yaw angle", ref angle, -360, 360)) { return(false); } yaw = Orientation.DegreesToPacked(angle); } if (args.Length > 4) { if (!CommandParser.GetInt(p, args[4], "Pitch angle", ref angle, -360, 360)) { return(false); } pitch = Orientation.DegreesToPacked(angle); } return(true); }
static void TeleportCoordsPrecise(Player p, string[] args) { Vec3S32 P = new Vec3S32(p.Pos.X, p.Pos.Y + Entities.CharacterHeight, p.Pos.Z); if (!CommandParser.GetCoords(p, args, 1, ref P)) { return; } SavePreTeleportState(p); Position pos = new Position(P.X, P.Y - Entities.CharacterHeight, P.Z); p.SendPos(Entities.SelfID, pos, p.Rot); }
void MakeBranch(int x, int y, int z, TreeOutput output) { int branchX = rnd.Next(-maxExtent, maxExtent); int branchZ = rnd.Next(-maxExtent, maxExtent); int branchStartY = rnd.Next((trunkHeight / 4) + 1, trunkHeight + (trunkHeight / 4)); int branchEndY = branchStartY + rnd.Next(1, maxBranchHeight + 3); Vec3S32 p1 = new Vec3S32(x, y + branchStartY, z); Vec3S32 p2 = new Vec3S32(x + branchX, y + branchEndY, z + branchZ); Line(p1, p2, output); GenCluster(x + branchX, y + branchEndY, z + branchZ, output); }
public override void Generate(ushort x, ushort y, ushort z, TreeOutput output) { // Generate base tree Vec3S32 p1 = new Vec3S32(x, y, z); Vec3S32 p2 = new Vec3S32(x, y + trunkHeight, z); Line(p1, p2, output); GenCluster(x, y + trunkHeight, z, output); // Generate branches for (int i = 0; i < numBranches; i++) { MakeBranch(x, y, z, output); } }
internal static void Fall(Player p, AABB bb, bool movingDown) { // Client position is slightly more precise than server's // If don't adjust, it's possible for player to land on edge of a block and not die // Only do when not moving down, so hitting a pillar while falling doesn't trigger if (!movingDown) { bb.Min.X -= 1; bb.Max.X += 1; bb.Min.Z -= 1; bb.Max.Z += 1; } bb.Min.Y -= 2; // test block below player feet Vec3S32 min = bb.BlockMin, max = bb.BlockMax; bool allGas = true; for (int z = min.Z; z <= max.Z; z++) { for (int x = min.X; x <= max.X; x++) { BlockID block = GetSurvivalBlock(p, x, min.Y, z); byte collide = p.level.CollideType(block); allGas = allGas && collide == CollideType.WalkThrough; if (!CollideType.IsSolid(collide)) { continue; } int fallHeight = p.startFallY - bb.Min.Y; if (fallHeight > p.level.Config.FallHeight * 32) { p.HandleDeath(Block.Air, null, false, true); } p.startFallY = -1; return; } } if (!allGas) { return; } if (bb.Min.Y > p.lastFallY) { p.startFallY = -1; // flying up resets fall height } p.startFallY = Math.Max(bb.Min.Y, p.startFallY); }
public override void Use(Player p, string message) { if (CheckSuper(p, message, "player name")) { return; } int ignored = 0; if (message == "") { UndoSelf(p); return; } else if (p != null && int.TryParse(message, out ignored)) { message = p.name.ToLower() + " " + message; } string[] parts = message.Split(' '); bool undoPhysics = parts[0].CaselessEq("physics"); Player who = undoPhysics ? null : PlayerInfo.Find(parts[0]); TimeSpan delta = GetDelta(p, who, parts.Length > 1 ? parts[1] : "30m"); if (delta == TimeSpan.MinValue) { return; } if (parts.Length > 1 && parts[1].CaselessEq("update")) { UndoFormat.UpgradePlayerUndoFiles(parts[0]); Player.Message(p, "Updated undo files for " + parts[0] + " to the new binary format."); return; } Vec3S32[] marks = new Vec3S32[] { Vec3U16.MaxVal, Vec3U16.MaxVal }; if (who != null) { UndoOnlinePlayer(p, delta, who, marks); } else if (undoPhysics) { UndoLevelPhysics(p, delta); } else { UndoOfflinePlayer(p, delta, parts[0], marks); } }
public override void Use(Player p, string message, CommandData data) { TimeSpan delta = TimeSpan.Zero; bool area = message.CaselessStarts("area "); if (area) { message = message.Substring("area ".Length); } if (message.Length == 0) { message = p.name; } string[] parts = message.SplitSpaces(); if (parts.Length >= 2) { if (!CommandParser.GetTimespan(p, parts[1], ref delta, "highlight the past", "s")) { return; } } else { delta = TimeSpan.FromMinutes(30); } parts[0] = PlayerDB.MatchNames(p, parts[0]); if (parts[0] == null) { return; } int[] ids = NameConverter.FindIds(parts[0]); if (!area) { Vec3S32[] marks = new Vec3S32[] { Vec3U16.MinVal, Vec3U16.MaxVal }; HighlightPlayer(p, delta, parts[0], ids, marks); } else { p.Message("Place or break two blocks to determine the edges."); HighlightAreaArgs args = new HighlightAreaArgs(); args.ids = ids; args.who = parts[0]; args.delta = delta; p.MakeSelection(2, "Selecting region for &SHighlight", args, DoHighlightArea); } }
public override void Use(Player p, string message, CommandData data) { bool area = message.CaselessStarts("-area"); if (area) { message = message.Substring("-area".Length).TrimStart(); } if (CheckSuper(p, message, "player name")) { return; } if (message.Length == 0) { p.Message("You need to provide a player name."); return; } string[] parts = message.SplitSpaces(), names = null; int[] ids = GetIds(p, parts, data, out names); if (ids == null) { return; } TimeSpan delta = CmdUndo.GetDelta(p, parts[0], parts, 1); if (delta == TimeSpan.MinValue) { return; } if (!area) { Vec3S32[] marks = new Vec3S32[] { Vec3U16.MinVal, Vec3U16.MaxVal }; UndoPlayer(p, delta, names, ids, marks); } else { if (!p.Ignores.DrawOutput || !p.Supports(CpeExt.MessageTypes)) { p.Message("Place or break two blocks to determine the edges."); } UndoAreaArgs args = new UndoAreaArgs(); args.ids = ids; args.names = names; args.delta = delta; p.MakeSelection(2, "Selecting region for &SUndo player", args, DoUndoArea); } }
void DrawPlayerFlag(Player p, CtfData data) { Vec3S32 coords = p.Pos.BlockCoords; coords.Y += 3; if (coords == data.LastHeadPos) { return; } ResetPlayerFlag(p, data); data.LastHeadPos = coords; ushort x = (ushort)coords.X, y = (ushort)coords.Y, z = (ushort)coords.Z; CtfTeam opposing = Opposing(TeamOf(p)); Map.BroadcastChange(x, y, z, opposing.FlagBlock); }
public override long BlocksAffected(Level lvl, Vec3S32[] marks) { Vec3S32 p1 = Min, p2 = Max; long total = 0; while (p1.Y >= 0 && p1.Y < lvl.Height && p1.X <= p2.X && p1.Z <= p2.Z) { baseOp.Min = p1; baseOp.Max = p2; total += baseOp.BlocksAffected(lvl, marks); p1.X++; p2.X--; p1.Z++; p2.Z--; p1.Y += yDir; p2.Y = p1.Y; } return(total); }
public override void Perform(Vec3S32[] marks, Brush brush, DrawOpOutput output) { Vec3S32 p1 = Min, p2 = Max; baseOp.Setup(Player, Level, marks); while (p1.Y >= 0 && p1.Y < Level.Height && p1.X <= p2.X && p1.Z <= p2.Z) { baseOp.Min = p1; baseOp.Max = p2; baseOp.Perform(marks, brush, output); p1.X++; p2.X--; p1.Z++; p2.Z--; p1.Y += yDir; p2.Y = p1.Y; } }
public override long BlocksAffected(Level lvl, Vec3S32[] marks) { Vec3S32 p1 = marks[0], p2 = marks[1]; double dx = Math.Abs(p2.X - p1.X) + 0.25, dy = Math.Abs(p2.Y - p1.Y) + 0.25, dz = Math.Abs(p2.Z - p1.Z) + 0.25; if (WallsMode) { int baseLen = (int)Math.Ceiling(Math.Sqrt(dx * dx + dz * dz)); return(Math.Min(baseLen, MaxLength) * (Math.Abs(p2.Y - p1.Y) + 1)); } else { int baseLen = (int)Math.Ceiling(Math.Sqrt(dx * dx + dy * dy + dz * dz)); return(Math.Min(baseLen, MaxLength)); } }
internal static void Drown(Player p, AABB bb) { // Want to check block at centre of bounding box bb.Max.X -= (bb.Max.X - bb.Min.X) / 2; bb.Max.Z -= (bb.Max.Z - bb.Min.Z) / 2; Vec3S32 P = bb.BlockMax; BlockID bHead = GetSurvivalBlock(p, P.X, P.Y, P.Z); if (Block.IsPhysicsType(bHead)) { bHead = Block.Convert(bHead); } if (p.level.Props[bHead].Drownable) { p.startFallY = -1; DateTime now = DateTime.UtcNow; // level drown is in 10ths of a second if (p.drownTime == DateTime.MaxValue) { p.drownTime = now.AddSeconds(p.level.Config.DrownTime / 10.0); } if (now > p.drownTime) { p.HandleDeath(bHead); p.drownTime = DateTime.MaxValue; } } else { bool isGas = p.level.CollideType(bHead) == CollideType.WalkThrough; // NOTE: Rope is a special case, it should always reset fall height if (bHead == Block.Rope) { isGas = false; } if (!isGas) { p.startFallY = -1; } p.drownTime = DateTime.MaxValue; } }
public override void Use(Player p, string message, CommandData data) { if (message.Length == 0) { Help(p); return; } if (message.CaselessEq("me")) { message = p.name; } string[] args = message.SplitSpaces(); Vec3S32 P = p.Pos.BlockCoords; if (args.Length == 1) { Player target = PlayerInfo.FindMatches(p, args[0]); if (target == null) { return; } P = target.Pos.BlockCoords; if (DoExplode(p, target.level, ref P)) { p.Message("{0} %Shas been exploded!", p.FormatNick(target)); } } else if (args.Length == 3) { if (!CommandParser.GetCoords(p, args, 0, ref P)) { return; } if (DoExplode(p, p.level, ref P)) { p.Message("An explosion was made at ({0}, {1}, {2}).", P.X, P.Y, P.Z); } } else { Help(p); } }
public override void Perform(Vec3S32[] marks, Player p, Level lvl, DrawOp op, Brush brush, Action <DrawOpBlock> output) { P = (op.Min + op.Max) / 2; dirX = 1; dirY = 1; dirZ = 1; width = lvl.Width; height = lvl.Height; length = lvl.Length; if (!CentreOrigin) { // Guess the direction in which we should be scaling - // for simplicity we assume we are scaling in positive direction P = op.Origin; dirX = op.Min.X == op.Max.X ? 1 : (P.X == op.Max.X ? -1 : 1); dirY = op.Min.Y == op.Max.Y ? 1 : (P.Y == op.Max.Y ? -1 : 1); dirZ = op.Min.Z == op.Max.Z ? 1 : (P.Z == op.Max.Z ? -1 : 1); } op.Perform(marks, brush, b => OutputBlock(b, output)); }
bool ParseCoords(string message, Player p, ref Vec3S32 P) { string[] args = message.SplitSpaces(); // Expand /mark ~4 into /mark ~4 ~4 ~4 if (args.Length == 1) { args = new string[] { message, message, message }; } if (args.Length != 3) { Help(p); return(false); } AdjustArg(ref args[0], ref P.X, "X", p.lastClick.X); AdjustArg(ref args[1], ref P.Y, "Y", p.lastClick.Y); AdjustArg(ref args[2], ref P.Z, "Z", p.lastClick.Z); return(CommandParser.GetCoords(p, args, 0, ref P)); }
bool DeleteZone(Player p, Vec3S32[] marks, object state, byte type, byte extType) { Level lvl = p.level; bool foundDel = false; Vec3S32 P = marks[0]; for (int i = 0; i < lvl.ZoneList.Count; i++) { Level.Zone zn = lvl.ZoneList[i]; if (P.X < zn.smallX || P.X > zn.bigX || P.Y < zn.smallY || P.Y > zn.bigY || P.Z < zn.smallZ || P.Z > zn.bigZ) { continue; } if (zn.Owner.Length >= 3 && zn.Owner.StartsWith("grp")) { string grpName = zn.Owner.Substring(3); if (p.Rank < Group.Find(grpName).Permission) { continue; } } else if (zn.Owner != "" && !zn.Owner.CaselessEq(p.name)) { Group group = Group.findPlayerGroup(zn.Owner); if (p.Rank < group.Permission) { continue; } } LevelDB.DeleteZone(lvl.name, zn); lvl.ZoneList.RemoveAt(i); i--; Player.Message(p, "Zone deleted for &b" + zn.Owner); foundDel = true; } if (!foundDel) { Player.Message(p, "No zones found to delete."); } return(false); }
public override void Perform(Vec3S32[] marks, Brush brush, DrawOpOutput output) { Vec3S32 p1 = marks[0], p2 = marks[1]; if (Math.Abs(p2.X - p1.X) > Math.Abs(p2.Z - p1.Z)) { dir.X = p2.X > p1.X ? 1 : -1; } else { dir.Z = p2.Z > p1.Z ? 1 : -1; } pos = p1; foreach (char c in Text) { DrawLetter(Player, c, brush, output); } }
static bool RedFlagCallback(Player p, Vec3S32[] marks, object state, ExtBlock block) { CTFConfig cfg = RetrieveConfig(p); Vec3S32 P = marks[0]; cfg.RedFlagX = P.X; cfg.RedFlagY = P.Y; cfg.RedFlagZ = P.Z; Player.Message(p, "Set flag position of red team to ({0}, {1}, {2})", P.X, P.Y, P.Z); block = p.level.GetBlock((ushort)P.X, (ushort)P.Y, (ushort)P.Z); if (block.IsAir) { block = (ExtBlock)Block.Red; } cfg.RedFlagBlock = block.RawID; Player.Message(p, "Set flag block of red team to {0}", p.level.BlockName(block)); UpdateConfig(p, cfg); return(false); }
static bool DoExplode(Player p, Level lvl, ref Vec3S32 pos) { if (lvl.physics < 3 || lvl.physics == 5) { p.Message("%WThe physics on {0} %Ware not sufficient for exploding!", lvl.ColoredName); return(false); } pos = lvl.ClampPos(pos); ushort x = (ushort)pos.X, y = (ushort)pos.Y, z = (ushort)pos.Z; BlockID old = lvl.GetBlock(x, y, z); if (!lvl.CheckAffect(p, x, y, z, old, Block.TNT)) { return(false); } lvl.MakeExplosion(x, y, z, 1); return(true); }
static void ComposeParts(Level lvl, List <Model> parts, int minX, int minY, int minZ) { foreach (Model part in parts) { for (int i = 0; i < part.Voxels.Length; i++) { Voxel v = part.Voxels[i]; Vec3S32 p = part.Transform(v.X, v.Y, v.Z); // need to make the global coordinates fit inside the level int x = p.X - minX, y = p.Y - minY, z = p.Z - minZ; // mirror over Y to match magicavoxel y = (lvl.Length - 1 - y); // magicavox uses Z for vertical lvl.SetBlock((ushort)x, (ushort)z, (ushort)y, Block.FromRaw(v.B)); } } }
/// <summary> Initialize the internal values for the Tree object. </summary> /// <remarks> Primarily, sets up the foliage cluster locations. </remarks> public override void Prepare() { Vec3S32 treeposition = pos; trunkradius = (float)(Math.Sqrt(height * TRUNKTHICKNESS)); if (trunkradius < 1) { trunkradius = 1; } trunkheight = 0.618f * height; int ystart = treeposition.Y, yend = treeposition.Y + height; branchdensity = BRANCHDENSITY / FOLIAGEDENSITY; int topy = treeposition.Y + (int)(trunkheight + 0.5); int num_of_clusters_per_y = (int)(1.5 + Math.Pow(FOLIAGEDENSITY * height / 19.0, 2)); if (num_of_clusters_per_y < 1) { num_of_clusters_per_y = 1; } // TODO: fCraft is yEnd - 1, ???? // Outdated, since maps can be twice as tall now. foliage_coords.Clear(); for (int y = yend; y != ystart; y--) { for (int i = 0; i < num_of_clusters_per_y; i++) { double shapefac = ShapeFunc(y - ystart); if (shapefac == none) { continue; } double r = (Math.Sqrt(random()) + 0.328) * shapefac; double theta = random() * 2 * Math.PI; int x = (int)(r * Math.Sin(theta)) + treeposition.X; int z = (int)(r * Math.Cos(theta)) + treeposition.Z; foliage_coords.Add(new Vec3S32(x, y, z)); } } }
protected override void GetMarks(DrawArgs dArgs, ref Vec3S32[] m) { AdvDrawMeta meta = (AdvDrawMeta)dArgs.Meta; int radius = meta.radius; Vec3S32 P = m[0]; m = new Vec3S32[] { new Vec3S32(P.X - radius, P.Y, P.Z - radius), new Vec3S32(P.X + radius, P.Y, P.Z + radius), }; if (UsesHeight(dArgs)) { m[1].Y += meta.height - 1; } else { m[0].Y -= radius; m[1].Y += radius; } }
public override void Perform(Vec3S32[] marks, Brush brush, Action <DrawOpBlock> output) { Vec3S32 p1 = Min, p2 = Max; baseOp.Level = Level; baseOp.Player = Player; while (true) { baseOp.Perform(marks, brush, output); if (p1.Y >= Level.Height || Math.Abs(p2.X - p1.X) <= 1 || Math.Abs(p2.Z - p1.Z) <= 1) { return; } p1.X++; p2.X--; p1.Z++; p2.Z--; p1.Y = (ushort)(p1.Y + yDir); p2.Y = p1.Y; baseOp.Min = p1; baseOp.Max = p2; } }
public override void Perform(Vec3S32[] marks, Brush brush, DrawOpOutput output) { int upper = (Radius + 1) * (Radius + 1); Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); Vec3S32 C = (Min + Max) / 2; for (ushort y = p1.Y; y <= p2.Y; y++) { for (ushort z = p1.Z; z <= p2.Z; z++) { for (ushort x = p1.X; x <= p2.X; x++) { int dist = (C.X - x) * (C.X - x) + (C.Y - y) * (C.Y - y) + (C.Z - z) * (C.Z - z); if (dist < upper) { output(Place(x, y, z, brush)); } } } } }
public override void Perform(Vec3S32[] marks, Brush brush, Action <DrawOpBlock> output) { Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); Vec3S32 C = (Min + Max) / 2; int height = Max.Y - Min.Y; for (ushort y = p1.Y; y <= p2.Y; y++) { for (ushort z = p1.Z; z <= p2.Z; z++) { for (ushort x = p1.X; x <= p2.X; x++) { int xx = C.X - x, yy = y - Min.Y, zz = C.Z - z; int curHeight = Invert ? yy : height - yy; if (curHeight == 0) { continue; } double curRadius = Radius * ((double)curHeight / (double)height); int absx = Math.Abs(xx), absz = Math.Abs(zz); if (absx > curRadius || absz > curRadius) { continue; } if (absx < (curRadius - 1) && absz < (curRadius - 1)) { continue; } byte ctile = Level.GetTile(x, y, z); if (ctile != 0) { continue; } output(Place(x, y, z, brush)); } } } }
public override void Perform(Vec3S32[] marks, Brush brush, DrawOpOutput output) { Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); Vec3S32 C = (Min + Max) / 2; int height = Max.Y - Min.Y; for (ushort y = p1.Y; y <= p2.Y; y++) { int yy = y - Min.Y; int curHeight = height - yy; if (curHeight == 0) { continue; } int curRadius = Radius * curHeight / height; int curRadius2 = Radius * (curHeight - 1) / height; for (ushort z = p1.Z; z <= p2.Z; z++) { for (ushort x = p1.X; x <= p2.X; x++) { int dx = C.X - x, dz = C.Z - z; int dist = dx * dx + dz * dz; if (dist > curRadius * curRadius) { continue; } bool layer = curRadius == 0 || !(dist <= (curRadius - 1) * (curRadius - 1) && dist <= (curRadius2) * (curRadius2)); BlockID block = layer ? Block.Grass : Block.StillLava; output(Place(x, y, z, block)); } } } }
bool DoMeasure(Player p, Vec3S32[] m, object state, ExtBlock block) { ExtBlock[] toCount = (ExtBlock[])state; Vec3S32 min = Vec3S32.Min(m[0], m[1]), max = Vec3S32.Max(m[0], m[1]); int[] counts = new int[512]; for (ushort y = (ushort)min.Y; y <= (ushort)max.Y; y++) { for (ushort z = (ushort)min.Z; z <= (ushort)max.Z; z++) { for (ushort x = (ushort)min.X; x <= (ushort)max.X; x++) { counts[p.level.GetBlock(x, y, z).Index]++; } } } int width = max.X - min.X + 1, height = max.Y - min.Y + 1, length = max.Z - min.Z + 1; int volume = width * height * length; Player.Message(p, "Measuring from &a({0}, {1}, {2}) %Sto &a({3}, {4}, {5})", min.X, min.Y, min.Z, max.X, max.Y, max.Z); Player.Message(p, " &b{0} %Swide, &b{1} %Shigh, &b{2} %Slong, {3} blocks", width, height, length, volume); string title = "Block types: "; if (toCount == null) { toCount = MostFrequentBlocks(counts); title = "Top " + toCount.Length + " block types: "; } string blocks = toCount.Join(bl => p.level.BlockName(bl) + FormatCount(counts[bl.Index], volume)); Player.Message(p, title + blocks); return(true); }
public override void Perform(Vec3S32[] marks, Brush brush, DrawOpOutput output) { Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); Vec3S32 C = (Min + Max) / 2; int height = Max.Y - Min.Y; for (ushort y = p1.Y; y <= p2.Y; y++) { int dy = y - Min.Y; int curHeight = Invert ? dy : height - dy; if (curHeight == 0) { continue; } int curRadius = Radius * curHeight / height; int curRadius2 = Radius * (curHeight - 1) / height; for (ushort z = p1.Z; z <= p2.Z; z++) { for (ushort x = p1.X; x <= p2.X; x++) { int dx = C.X - x, dz = C.Z - z; int dist = dx * dx + dz * dz; if (dist > curRadius * curRadius) { continue; } if (dist <= (curRadius - 1) * (curRadius - 1) && dist <= (curRadius2) * (curRadius2)) { continue; } output(Place(x, y, z, brush)); } } } }