static ExtBlock GetFreeBlock(bool global, Level lvl) { // Start from opposite ends to avoid overlap. if (global) { BlockDefinition[] defs = BlockDefinition.GlobalDefs; for (int i = Block.CpeCount; i < Block.Invalid; i++) { if (defs[i] == null) { return(ExtBlock.FromRaw((byte)i)); } } } else { BlockDefinition[] defs = lvl.CustomBlockDefs; for (int i = Block.Invalid - 1; i >= Block.CpeCount; i--) { if (defs[i] == null) { return(ExtBlock.FromRaw((byte)i)); } } } return(ExtBlock.Invalid); }
bool DoUndoArea(Player p, Vec3S32[] marks, object state, ExtBlock block) { UndoAreaArgs args = (UndoAreaArgs)state; UndoPlayer(p, args.delta, args.names, args.ids, marks); return(false); }
internal static void C4(Player p, ExtBlock block, ushort x, ushort y, ushort z) { if (p.level.physics == 0 || p.level.physics == 5) { p.RevertBlock(x, y, z); return; } // Use red wool to detonate c4 ExtBlock held = p.BlockBindings[p.RawHeldBlock.RawID]; if (held.BlockID == Block.Red) { Player.Message(p, "Placed detonator block, delete it to detonate."); C4Det(p, (ExtBlock)Block.C4Detonator, x, y, z); return; } if (p.c4circuitNumber == -1) { sbyte num = C4Physics.NextCircuit(p.level); p.level.C4list.Add(new C4Data(num)); p.c4circuitNumber = num; string detonatorName = p.level.BlockName((ExtBlock)Block.Red); Player.Message(p, "Place more blocks for more c4, then place a &c{0} %Sblock for the detonator.", detonatorName); } C4Data c4 = C4Physics.Find(p.level, p.c4circuitNumber); if (c4 != null) { c4.list.Add(p.level.PosToInt(x, y, z)); } p.ChangeBlock(x, y, z, (ExtBlock)Block.C4); }
static void CheckBlockBindings(Player who) { ExtBlock block = who.ModeBlock; if (block != ExtBlock.Air && !CommandParser.IsBlockAllowed(who, "place", block)) { who.ModeBlock = ExtBlock.Air; Player.Message(who, " Hence, &b{0} %Smode was turned &cOFF", who.level.BlockName(block)); } for (int i = 0; i < who.BlockBindings.Length; i++) { block = who.BlockBindings[i]; ExtBlock defaultBinding = ExtBlock.FromRaw((byte)i); if (block == defaultBinding) { continue; } if (!CommandParser.IsBlockAllowed(who, "place", block)) { who.BlockBindings[i] = defaultBinding; Player.Message(who, " Hence, binding for &b{0} %Swas unbound", who.level.BlockName(defaultBinding)); } } }
static int FindYAbove(Level lvl, ushort x, ushort y, ushort z) { for (; y <= lvl.Height; y++) { ExtBlock above = lvl.GetBlock(x, (ushort)(y + 1), z); if (above.IsInvalid) { continue; } if (!CollideType.IsSolid(lvl.CollideType(above))) { continue; } int posY = (y + 1) * 32 - 6; BlockDefinition def = lvl.GetBlockDef(above); if (def != null) { posY += def.MinZ * 2; } return(posY); } return(-1); }
public static void OutputMessageBlock(Player p, ExtBlock block, ushort x, ushort y, ushort z) { if (!p.level.Props[block.Index].IsMessageBlock) { return; } try { if (!Database.Backend.TableExists("Messages" + p.level.name)) { return; } DataTable messages = Database.Backend.GetRows("Messages" + p.level.name, "*", "WHERE X=@0 AND Y=@1 AND Z=@2", x, y, z); int last = messages.Rows.Count - 1; if (last == -1) { messages.Dispose(); return; } string message = messages.Rows[last]["Message"].ToString().Trim(); message = message.Replace("\\'", "\'"); Player.Message(p, "Message Block contents: {0}", message); } catch { } }
protected override bool DoDraw(Player p, Vec3S32[] marks, object state, ExtBlock block) { DrawArgs dArgs = (DrawArgs)state; ushort x = (ushort)marks[0].X, y = (ushort)marks[0].Y, z = (ushort)marks[0].Z; ExtBlock old = p.level.GetBlock(x, y, z); if (!CommandParser.IsBlockAllowed(p, "fill over", old)) { return(false); } if (dArgs.Mode == DrawMode.volcano) { dArgs.Mode = Calc2DFill(p, marks); } FillDrawOp op = (FillDrawOp)dArgs.Op; op.Positions = FillDrawOp.FloodFill(p, p.level.PosToInt(x, y, z), old, dArgs.Mode); int count = op.Positions.Count; bool confirmed = IsConfirmed(dArgs.Message), success = true; if (count < p.group.DrawLimit && count > p.level.ReloadThreshold && !confirmed) { Player.Message(p, "This fill would affect {0} blocks.", count); Player.Message(p, "If you still want to fill, type %T/Fill {0} confirm", dArgs.Message); } else { success = base.DoDraw(p, marks, state, block); } op.Positions = null; return(success); }
/// <summary> Loads this copy state from the given stream, using the very old format. </summary> public void LoadFromOld(Stream stream, Stream underlying) { byte[] raw = new byte[underlying.Length]; underlying.Read(raw, 0, (int)underlying.Length); raw = raw.Decompress(); if (raw.Length == 0) { return; } ExtBlock block = default(ExtBlock); CalculateBounds(raw); for (int i = 0; i < raw.Length; i += 7) { ushort x = BitConverter.ToUInt16(raw, i + 0); ushort y = BitConverter.ToUInt16(raw, i + 2); ushort z = BitConverter.ToUInt16(raw, i + 4); block.BlockID = raw[i + 6]; Set(block, x - X, y - Y, z - Z); } UsedBlocks = Volume; OriginX = X; OriginY = Y; OriginZ = Z; }
public ExtBlock Get(int x, int y, int z) { int index = (y * Length + z) * Width + x; return(ExtBlock.FromRaw(raw[index], (isExt[index >> 3] & (1 << (index & 0x07))) != 0)); }
bool DoHighlightArea(Player p, Vec3S32[] marks, object state, ExtBlock block) { HighlightAreaArgs args = (HighlightAreaArgs)state; HighlightPlayer(p, args.delta, args.who, args.ids, marks); return(false); }
protected override void PlacedMark(Player p, ushort x, ushort y, ushort z, ExtBlock block) { p.RevertBlock(x, y, z); if (!p.level.Config.Guns) { p.ClearBlockchange(); return; } if (!CommandParser.IsBlockAllowed(p, "use", block)) { return; } WeaponArgs args = new WeaponArgs(); args.player = p; args.block = block; args.weaponType = (WeaponType)p.blockchangeObject; args.start = MakePos(p); args.dir = DirUtils.GetFlatDirVector(p.Rot.RotY, p.Rot.HeadX); args.pos = args.PosAt(3); args.iterations = 4; SchedulerTask task = new SchedulerTask(GunCallback, args, TimeSpan.Zero, true); p.CriticalTasks.Add(task); }
protected static bool HandlesHitBlock(Player p, ExtBlock block, WeaponType ending, Vec3U16 pos, bool doExplode) { if (p.level.physics < 2 || ending == WeaponType.Teleport || ending == WeaponType.Normal) { return(true); } if (ending == WeaponType.Destroy) { bool fireKills = block.BlockID != Block.Air && p.level.Props[block.Index].LavaKills; if ((!fireKills && !Block.NeedRestart(block.BlockID)) && block.BlockID != Block.Glass) { return(true); } } else if (p.level.physics >= 3) { if (block.BlockID != Block.Glass && doExplode) { p.level.MakeExplosion(pos.X, pos.Y, pos.Z, 1); return(true); } } else { return(true); } return(false); }
static void RemoveBlockProps(bool global, ExtBlock block, Player p) { // Level block reverts to using global block if (!global) { p.level.Props[block.Index] = BlockDefinition.DefaultProps(block); p.level.UpdateBlockHandler(block); return; } BlockProps props = BlockProps.MakeDefault(); if (!block.IsCustomType) { props = Block.Props[block.RawID]; } BlockDefinition.GlobalProps[block.RawID] = props; Level[] loaded = LevelInfo.Loaded.Items; byte raw = block.RawID; foreach (Level lvl in loaded) { if (lvl.CustomBlockDefs[raw] != BlockDefinition.GlobalDefs[raw]) { continue; } lvl.Props[block.Index] = BlockDefinition.GlobalProps[block.RawID]; lvl.UpdateBlockHandler(block); } }
static void MessageAlreadyBlock(Player p, ExtBlock block, bool global, string cmd) { string scope = global ? "global" : "level"; Player.Message(p, "&cThere is already a {1} custom block with the id \"{0}\".", block.RawID, scope); Player.Message(p, "Type \"%T{0} list\" %Sto see a list of {1} custom blocks.", cmd, scope); }
public override void Use(Player p, string message) { if (message.Length == 0) { Help(p); return; } if (!MessageCmd.CanSpeak(p, name)) { return; // do not allow using kill to spam every 2 secs } string[] args = message.SplitSpaces(2); Player target = PlayerInfo.FindMatches(p, args[0]); ExtBlock rock = (ExtBlock)Block.Stone; if (target == null) { if (p != null) { p.HandleDeath(rock, "@p %Skilled themselves in their confusion"); } return; } if (p != null && (target != p && target.Rank >= p.Rank)) { MessageTooHighRank(p, "kill", false); return; } bool explode = false; string killer = p == null ? "(console)" : p.ColoredName; string deathMsg = GetDeathMessage(args, killer, ref explode); target.HandleDeath(rock, deathMsg, explode); }
static CopyState Rotate(CopyState state, CopyState flipped, int[] m, ExtBlock[] transform) { int volume = state.Volume; for (int i = 0; i < volume; i++) { ushort x, y, z; state.GetCoords(i, out x, out y, out z); ExtBlock block = transform[state.Get(i).Index]; flipped.Set(block, Rotate(m[0], x, y, z, state), Rotate(m[1], x, y, z, state), Rotate(m[2], x, y, z, state)); } int oX = state.OriginX - state.X, oY = state.OriginY - state.Y, oZ = state.OriginZ - state.Z; flipped.OriginX = state.X + Rotate(m[0], oX, oY, oZ, state); flipped.OriginY = state.Y + Rotate(m[1], oX, oY, oZ, state); flipped.OriginZ = state.Z + Rotate(m[2], oX, oY, oZ, state); // Offset is relative to Origin oX += state.Offset.X; oY += state.Offset.Y; oZ += state.Offset.Z; flipped.Offset.X = state.X + Rotate(m[0], oX, oY, oZ, state) - flipped.OriginX; flipped.Offset.Y = state.Y + Rotate(m[1], oX, oY, oZ, state) - flipped.OriginY; flipped.Offset.Z = state.Z + Rotate(m[2], oX, oY, oZ, state) - flipped.OriginZ; return(flipped); }
public static void Output(Player p, string name, BlockDBEntry e) { ExtBlock oldBlock = ExtBlock.FromRaw(e.OldRaw, (e.Flags & BlockDBFlags.OldCustom) != 0); ExtBlock newBlock = ExtBlock.FromRaw(e.NewRaw, (e.Flags & BlockDBFlags.NewCustom) != 0); DateTime time = BlockDB.Epoch.AddSeconds(e.TimeDelta); TimeSpan delta = DateTime.UtcNow.Subtract(time); name = PlayerInfo.GetColoredName(p, name); if (newBlock.BlockID == Block.Air) { Player.Message(p, "{0} ago {1} &4deleted %S{2}{3}", delta.Shorten(true, false), name, p.level.BlockName(oldBlock), FormatReason(e.Flags)); } else { Player.Message(p, "{0} ago {1} &3placed %S{2}{3}", delta.Shorten(true, false), name, p.level.BlockName(newBlock), FormatReason(e.Flags)); } }
public static void MirrorX(CopyState state, BlockDefinition[] defs) { // ceiling division by 2, because for odd length, we still want to // mirror the middle row to rotate directional blocks int midZ = (state.Length + 1) / 2, maxZ = state.Length - 1; state.OriginZ = state.OppositeOriginZ; state.Offset.Z = -state.Offset.Z; ExtBlock[] transform = Transform(defs, mirrorX, null); for (int y = 0; y < state.Height; y++) { for (int z = 0; z < midZ; z++) { int endZ = maxZ - z; int start = state.GetIndex(0, y, z); int end = state.GetIndex(0, y, endZ); for (int x = 0; x < state.Width; x++) { ExtBlock blockA = transform[state.Get(start).Index]; ExtBlock blockB = transform[state.Get(end).Index]; state.Set(blockB, start); state.Set(blockA, end); start++; end++; } } } }
public static void OutputPortal(Player p, ExtBlock block, ushort x, ushort y, ushort z) { if (!p.level.Props[block.Index].IsPortal) { return; } try { if (!Database.Backend.TableExists("Portals" + p.level.name)) { return; } DataTable portals = Database.Backend.GetRows("Portals" + p.level.name, "*", "WHERE EntryX=@0 AND EntryY=@1 AND EntryZ=@2", x, y, z); int last = portals.Rows.Count - 1; if (last == -1) { portals.Dispose(); return; } string exitMap = portals.Rows[last]["ExitMap"].ToString().Trim(); ushort exitX = U16(portals.Rows[last]["ExitX"]); ushort exitY = U16(portals.Rows[last]["ExitY"]); ushort exitZ = U16(portals.Rows[last]["ExitZ"]); Player.Message(p, "Portal destination: ({0}, {1}, {2}) in {3}", exitX, exitY, exitZ, exitMap); } catch { } }
public static void MirrorY(CopyState state, BlockDefinition[] defs) { int midY = (state.Height + 1) / 2, maxY = state.Height - 1; state.OriginY = state.OppositeOriginY; state.Offset.Y = -state.Offset.Y; ExtBlock[] transform = Transform(defs, mirrorY, null); for (int y = 0; y < midY; y++) { int endY = maxY - y; int start = state.GetIndex(0, y, 0); int end = state.GetIndex(0, endY, 0); for (int z = 0; z < state.Length; z++) { for (int x = 0; x < state.Width; x++) { ExtBlock blockA = transform[state.Get(start).Index]; ExtBlock blockB = transform[state.Get(end).Index]; state.Set(blockB, start); state.Set(blockA, end); start++; end++; } } } }
static void GetRaw(string[] parts, Predicate <string> filter, BrushArgs args, out ExtBlock[] blocks, out int[] count) { int bCount = 0; for (int i = 0; i < parts.Length; i++) { if (parts[i] == "" || !filter(parts[i])) { continue; } bCount++; } // For 0 or 1 blocks given, treat second block as 'unchanged'. blocks = new ExtBlock[Math.Max(2, bCount)]; count = new int[blocks.Length]; for (int i = 0; i < count.Length; i++) { count[i] = 1; blocks[i] = new ExtBlock(Block.Invalid, 0); } // No blocks given, assume first is held block if (bCount == 0) { blocks[0] = new ExtBlock(args.Block, args.ExtBlock); } }
public static void MirrorZ(CopyState state, BlockDefinition[] defs) { int midX = (state.Width + 1) / 2, maxX = state.Width - 1; state.OriginX = state.OppositeOriginX; state.Offset.X = -state.Offset.X; ExtBlock[] transform = Transform(defs, mirrorZ, null); for (int y = 0; y < state.Height; y++) { for (int z = 0; z < state.Length; z++) { for (int x = 0; x < midX; x++) { int endX = maxX - x; int start = state.GetIndex(x, y, z); int end = state.GetIndex(endX, y, z); ExtBlock blockA = transform[state.Get(start).Index]; ExtBlock blockB = transform[state.Get(end).Index]; state.Set(blockB, start); state.Set(blockA, end); } } } }
static void ExpandDiagonal(Level lvl, ushort x, ushort y, ushort z, int dx, int dy, int dz) { ExtBlock block = lvl.GetBlock((ushort)(x + dx), (ushort)(y + dy), (ushort)(z + dz)); if (block.BlockID == Block.Air) { return; } if (!lvl.Props[block.Index].LavaKills) { return; } if (dx != 0) { lvl.AddUpdate(lvl.PosToInt((ushort)(x + dx), y, z), Block.Fire); } if (dy != 0) { lvl.AddUpdate(lvl.PosToInt(x, (ushort)(y + dy), z), Block.Fire); } if (dz != 0) { lvl.AddUpdate(lvl.PosToInt(x, y, (ushort)(z + dz)), Block.Fire); } }
internal static void HandlePlayerClick(Player p, MouseButton button, MouseAction action, ushort yaw, ushort pitch, byte entity, ushort x, ushort y, ushort z, TargetBlockFace face) { if (action != MouseAction.Pressed) { return; } if (entity != Entities.SelfID && ClickOnBot(p, entity)) { return; } if (p.level.Config.Deletable || !p.level.IsValidPos(x, y, z)) { return; } ExtBlock block = p.level.GetBlock(x, y, z); bool isMB = p.level.Props[block.Index].IsMessageBlock; bool isPortal = p.level.Props[block.Index].IsPortal; if (isMB) { MessageBlock.Handle(p, x, y, z, true); } if (isPortal) { Portal.Handle(p, x, y, z); } }
static string Format(ExtBlock block, Level lvl, BlockProps[] props) { if (!props[block.Index].IsPortal) { return(null); } // We want to use the simple aliases if possible if (block.BlockID == Block.Portal_Orange) { return("orange"); } if (block.BlockID == Block.Portal_Blue) { return("blue"); } if (block.BlockID == Block.Portal_Air) { return("air"); } if (block.BlockID == Block.Portal_Lava) { return("lava"); } if (block.BlockID == Block.Portal_Water) { return("water"); } return(lvl == null?Block.Name(block.BlockID) : lvl.BlockName(block)); }
public static void DoAir(Level lvl, ref Check C) { ushort x, y, z; lvl.IntToPos(C.b, out x, out y, out z); ActivateablePhysics.CheckNeighbours(lvl, x, y, z); ActivateablePhysics.CheckAt(lvl, lvl.PosToInt(x, (ushort)(y - 1), z)); //Edge of map water if (lvl.Config.EdgeWater && (y < lvl.Config.EdgeLevel && y >= (lvl.Config.EdgeLevel + lvl.Config.SidesOffset))) { if (x == 0 || x == lvl.Width - 1 || z == 0 || z == lvl.Length - 1) { ExtBlock block = ExtBlock.FromRaw((byte)lvl.Config.HorizonBlock); PhysicsArgs args = default(PhysicsArgs); args.ExtBlock = block.BlockID == Block.custom_block; lvl.AddUpdate(C.b, block.RawID, false, args); } } if (!C.data.HasWait) { C.data.Data = PhysicsArgs.RemoveFromChecks; } }
/// <summary> Retrieves the default walkthrough block handler for the given block. </summary> internal static HandleWalkthrough GetWalkthroughHandler(ExtBlock block, BlockProps[] props, bool nonSolid) { switch (block.BlockID) { case Block.Checkpoint: return(WalkthroughBehaviour.Checkpoint); case Block.Door_AirActivatable: return(WalkthroughBehaviour.Door); case Block.Door_Water: return(WalkthroughBehaviour.Door); case Block.Door_Lava: return(WalkthroughBehaviour.Door); case Block.Train: return(WalkthroughBehaviour.Train); } int i = block.Index; if (props[i].IsMessageBlock && nonSolid) { return(WalkthroughBehaviour.DoMessageBlock); } if (props[i].IsPortal && nonSolid) { return(WalkthroughBehaviour.DoPortal); } return(null); }
internal static bool Handles(Player p, ushort x, ushort y, ushort z, bool placing, ExtBlock block, ExtBlock old, ZSGame game) { if (placing && !game.Map.Config.Pillaring && !p.Game.Referee) { if (NotPillaring(game.Map, block, old)) { p.Game.BlocksStacked = 0; } else if (CheckCoords(p, x, y, z)) { p.Game.BlocksStacked++; } else { p.Game.BlocksStacked = 0; } if (MessagePillaring(p, x, y, z)) { return(true); } } p.Game.LastX = x; p.Game.LastY = y; p.Game.LastZ = z; return(false); }
static ExtBlock[] MostFrequentBlocks(int[] countsRaw) { ExtBlock[] blocks = new ExtBlock[512]; int[] counts = new int[512]; // copy array as Sort works in place int total = 0; for (int i = 0; i < blocks.Length; i++) { blocks[i] = ExtBlock.FromIndex(i); counts[i] = countsRaw[i]; if (counts[i] > 0) { total++; } } Array.Sort(counts, blocks); if (total > 5) { total = 5; } ExtBlock[] mostFrequent = new ExtBlock[total]; for (int i = 0; i < total; i++) { mostFrequent[i] = blocks[blocks.Length - 1 - i]; } return(mostFrequent); }
internal static void C4Det(Player p, ExtBlock block, ushort x, ushort y, ushort z) { int index = p.level.PosToInt(x, y, z); C4Physics.BlowUp(index, p.level); p.ChangeBlock(x, y, z, ExtBlock.Air); }