From 9621275334d69292d271d9ca4d6c1a88c7ddd836 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sat, 2 Apr 2016 16:38:14 +1100 Subject: [PATCH] Modularise more block behaviour. --- Blocks/Behaviour/Block.Behaviour.cs | 57 +++++++++ .../DeleteBehaviour.cs} | 31 ++--- Blocks/Behaviour/WalkthroughBehaviour.cs | 92 ++++++++++++++ Blocks/Block.Convert.cs | 8 +- Blocks/Block.ID.cs | 2 +- Blocks/Block.Permissions.cs | 2 +- Blocks/Block.cs | 2 +- Levels/Level.Physics.cs | 2 +- Levels/Physics/DoorPhysics.cs | 2 +- MCGalaxy_.csproj | 5 +- Player/Player.Handlers.cs | 120 +++--------------- 11 files changed, 188 insertions(+), 135 deletions(-) create mode 100644 Blocks/Behaviour/Block.Behaviour.cs rename Blocks/{Block.Behaviour.cs => Behaviour/DeleteBehaviour.cs} (71%) create mode 100644 Blocks/Behaviour/WalkthroughBehaviour.cs diff --git a/Blocks/Behaviour/Block.Behaviour.cs b/Blocks/Behaviour/Block.Behaviour.cs new file mode 100644 index 000000000..54e9ad206 --- /dev/null +++ b/Blocks/Behaviour/Block.Behaviour.cs @@ -0,0 +1,57 @@ +/* + Copyright 2010 MCSharp team (Modified for use with MCZall/MCLawl/MCGalaxy) + + Dual-licensed under the Educational Community License, Version 2.0 and + the GNU General Public License, Version 3 (the "Licenses"); you may + not use this file except in compliance with the Licenses. You may + obtain a copy of the Licenses at + + http://www.opensource.org/licenses/ecl2.php + http://www.gnu.org/licenses/gpl-3.0.html + + Unless required by applicable law or agreed to in writing, + software distributed under the Licenses are distributed on an "AS IS" + BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + or implied. See the Licenses for the specific language governing + permissions and limitations under the Licenses. + */ +using System; +using MCGalaxy.BlockBehaviour; + +namespace MCGalaxy { + + public sealed partial class Block { + + /// Returns whether this block handles the player placing a block at the given coordinates. + /// If this returns true, the usual 'dirt/grass below' behaviour and 'adding to the BlockDB' is skipped. + public delegate bool HandleDelete(Player p, byte block, ushort x, ushort y, ushort z); + internal static HandleDelete[] deleteHandlers = new HandleDelete[256]; + + /// Returns whether this block handles the player deleting a block at the given coordinates. + /// If this returns true, the usual 'checking dirt/grass below' and 'adding to the BlockDB' is skipped. + public delegate bool HandlePlace(Player p, byte block, ushort x, ushort y, ushort z); + internal static HandlePlace[] placeHandlers = new Block.HandlePlace[256]; + + /// Returns whether this block handles the player walking through this block at the given coordinates. + /// If this returns true, the usual 'checking dirt/grass below' behaviour is skipped. + public delegate bool HandleWalkthrough(Player p, byte block, ushort x, ushort y, ushort z); + internal static HandleWalkthrough[] walkthroughHandlers = new Block.HandleWalkthrough[256]; + + static void SetupCoreHandlers() { + deleteHandlers[Block.rocketstart] = DeleteBehaviour.RocketStart; + deleteHandlers[Block.firework] = DeleteBehaviour.Firework; + walkthroughHandlers[Block.checkpoint] = WalkthroughBehaviour.Checkpoint; + deleteHandlers[Block.c4det] = DeleteBehaviour.C4Det; + + for (int i = 0; i < 256; i++) { + if (Block.mb((byte)i)) { + walkthroughHandlers[i] = WalkthroughBehaviour.MessageBlock; + deleteHandlers[i] = WalkthroughBehaviour.MessageBlock; + } else if (Block.portal((byte)i)) { + walkthroughHandlers[i] = WalkthroughBehaviour.Portal; + deleteHandlers[i] = WalkthroughBehaviour.Portal; + } + } + } + } +} diff --git a/Blocks/Block.Behaviour.cs b/Blocks/Behaviour/DeleteBehaviour.cs similarity index 71% rename from Blocks/Block.Behaviour.cs rename to Blocks/Behaviour/DeleteBehaviour.cs index 2df1b94f6..1c17f1b49 100644 --- a/Blocks/Block.Behaviour.cs +++ b/Blocks/Behaviour/DeleteBehaviour.cs @@ -17,30 +17,15 @@ */ using System; -namespace MCGalaxy { +namespace MCGalaxy.BlockBehaviour { - public sealed partial class Block { - - /// Returns whether this block handles the player placing a block at the given coordinates. - /// If this returns true, the usual 'checking dirt/grass below' behaviour is skipped. - public delegate bool HandleDelete(Player p, byte block, ushort x, ushort y, ushort z); - internal static HandleDelete[] deleteHandlers = new HandleDelete[256]; - - /// Returns whether this block handles the player deleting a block at the given coordinates. - /// If this returns true, the usual 'checking dirt/grass below' behaviour is skipped. - public delegate bool HandlePlace(Player p, byte block, ushort x, ushort y, ushort z); - internal static HandlePlace[] placeHandlers = new Block.HandlePlace[256]; - - static void SetupCoreHandlers() { - deleteHandlers[Block.rocketstart] = RocketStartDelete; - deleteHandlers[Block.firework] = FireworkDelete; - } + internal static class DeleteBehaviour { - static bool RocketStartDelete(Player p, byte block, ushort x, ushort y, ushort z) { + internal static bool RocketStart(Player p, byte block, ushort x, ushort y, ushort z) { if (p.level.physics < 2 || p.level.physics == 5) { p.RevertBlock(x, y, z); return true; } int newZ = 0, newX = 0, newY = 0; - p.SendBlockchange(x, y, z, Block.rocketstart); + p.RevertBlock(x, y, z); if ( p.rot[0] < 48 || p.rot[0] > ( 256 - 48 ) ) newZ = -1; else if ( p.rot[0] > ( 128 - 48 ) && p.rot[0] < ( 128 + 48 ) ) @@ -68,7 +53,7 @@ namespace MCGalaxy { return false; } - static bool FireworkDelete(Player p, byte block, ushort x, ushort y, ushort z) { + internal static bool Firework(Player p, byte block, ushort x, ushort y, ushort z) { if (p.level.physics == 0 || p.level.physics == 5) { p.RevertBlock(x, y, z); return true; } Random rand = new Random(); @@ -84,5 +69,11 @@ namespace MCGalaxy { } p.RevertBlock(x, y, z); return false; } + + internal static bool C4Det(Player p, byte block, ushort x, ushort y, ushort z) { + Level.C4.BlowUp(new ushort[] { x, y, z }, p.level); + p.level.UpdateBlock(p, x, y, z, Block.air, 0); + return false; + } } } diff --git a/Blocks/Behaviour/WalkthroughBehaviour.cs b/Blocks/Behaviour/WalkthroughBehaviour.cs new file mode 100644 index 000000000..8942c57dd --- /dev/null +++ b/Blocks/Behaviour/WalkthroughBehaviour.cs @@ -0,0 +1,92 @@ +/* + Copyright 2010 MCSharp team (Modified for use with MCZall/MCLawl/MCGalaxy) + + Dual-licensed under the Educational Community License, Version 2.0 and + the GNU General Public License, Version 3 (the "Licenses"); you may + not use this file except in compliance with the Licenses. You may + obtain a copy of the Licenses at + + http://www.opensource.org/licenses/ecl2.php + http://www.gnu.org/licenses/gpl-3.0.html + + Unless required by applicable law or agreed to in writing, + software distributed under the Licenses are distributed on an "AS IS" + BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + or implied. See the Licenses for the specific language governing + permissions and limitations under the Licenses. + */ +using System; +using System.Data; +using MCGalaxy.SQL; + +namespace MCGalaxy.BlockBehaviour { + + internal static class WalkthroughBehaviour { + + internal static bool Portal(Player p, byte block, ushort x, ushort y, ushort z) { + p.RevertBlock(x, y, z); + try { + //safe against SQL injections because no user input is given here + DataTable Portals = Database.fillData("SELECT * FROM `Portals" + p.level.name + "` WHERE EntryX=" + (int)x + " AND EntryY=" + (int)y + " AND EntryZ=" + (int)z); + int last = Portals.Rows.Count - 1; + if (last == -1) { Portals.Dispose(); return true; } + + DataRow row = Portals.Rows[last]; + if (p.level.name != row["ExitMap"].ToString()) { + if (p.level.permissionvisit > p.group.Permission) { + Player.SendMessage(p, "You do not have the adequate rank to visit this map!"); return true; + } + + p.ignorePermission = true; + Level curLevel = p.level; + Command.all.Find("goto").Use(p, row["ExitMap"].ToString()); + if (curLevel == p.level) { Player.SendMessage(p, "The map the portal goes to isn't loaded."); return true; } + p.ignorePermission = false; + } + p.BlockUntilLoad(10); + Command.all.Find("move").Use(p, p.name + " " + row["ExitX"].ToString() + " " + row["ExitY"].ToString() + " " + row["ExitZ"].ToString()); + Portals.Dispose(); + } catch { + Player.SendMessage(p, "Portal had no exit."); + } + return true; + } + + static char[] trimChars = { ' ' }; + internal static bool MessageBlock(Player p, byte block, ushort x, ushort y, ushort z) { + p.RevertBlock(x, y, z); + try { + //safe against SQL injections because no user input is given here + DataTable Messages = Database.fillData("SELECT * FROM `Messages" + p.level.name + "` WHERE X=" + (int)x + " AND Y=" + (int)y + " AND Z=" + (int)z); + int last = Messages.Rows.Count - 1; + if (last == -1) { Messages.Dispose(); return true; } + + string message = Messages.Rows[last]["Message"].ToString().Trim(); + message = message.Replace("\\'", "\'"); + if ( message != p.prevMsg || Server.repeatMessage ) { + if ( message.StartsWith("/") ) { + string[] parts = message.Remove(0, 1).Split(trimChars, 2); + p.HandleCommand(parts[0], parts.Length > 1 ? parts[1] : ""); + } else { + Player.SendMessage(p, message); + } + p.prevMsg = message; + } + } catch { + Player.SendMessage(p, "No message was stored."); + } + return true; + } + + internal static bool Checkpoint(Player p, byte block, ushort x, ushort y, ushort z) { + p.useCheckpointSpawn = true; + p.checkpointX = x; p.checkpointY = y; p.checkpointZ = z; + int index = p.level.PosToInt(x, y, z); + if (index != p.lastCheckpointIndex) { + p.SendSpawn(0xFF, p.color + p.truename, p.pos[0], (ushort)((y - 1) * 32 + 51), p.pos[2], p.rot[0], p.rot[1]); + p.lastCheckpointIndex = index; + } + return true; + } + } +} diff --git a/Blocks/Block.Convert.cs b/Blocks/Block.Convert.cs index 0ec83e5ad..743211117 100644 --- a/Blocks/Block.Convert.cs +++ b/Blocks/Block.Convert.cs @@ -232,7 +232,7 @@ namespace MCGalaxy //Blocks after this are converted before saving case air_flood: return "air_flood"; - case door_tree__air: return "door_air"; + case door_tree_air: return "door_air"; case air_flood_layer: return "air_flood_layer"; case air_flood_down: return "air_flood_down"; case air_flood_up: return "air_flood_up"; @@ -550,7 +550,7 @@ namespace MCGalaxy case "air_flood_layer": return air_flood_layer; case "air_flood_down": return air_flood_down; case "air_flood_up": return air_flood_up; - case "door_air": return door_tree__air; + case "door_air": return door_tree_air; case "door2_air": return door_obsidian_air; case "door3_air": return door_glass_air; case "door4_air": return door_stone_air; @@ -762,7 +762,7 @@ namespace MCGalaxy case Block.checkpoint: return Block.air; case air_flood: - case door_tree__air: + case door_tree_air: case air_flood_layer: case air_flood_down: case air_flood_up: @@ -845,7 +845,7 @@ namespace MCGalaxy case air_flood_down: case air_flood_up: return air; //air_flood must be converted to air on save to prevent issues - case door_tree__air: return door_tree; + case door_tree_air: return door_tree; case door_obsidian_air: return door_obsidian; case door_glass_air: return door_glass; case door_stone_air: return door_stone; diff --git a/Blocks/Block.ID.cs b/Blocks/Block.ID.cs index 291e42753..dd5612611 100644 --- a/Blocks/Block.ID.cs +++ b/Blocks/Block.ID.cs @@ -255,7 +255,7 @@ namespace MCGalaxy public const byte checkpoint = (byte)197; public const byte air_flood = (byte)200; - public const byte door_tree__air = (byte)201; + public const byte door_tree_air = (byte)201; public const byte air_flood_layer = (byte)202; public const byte air_flood_down = (byte)203; public const byte air_flood_up = (byte)204; diff --git a/Blocks/Block.Permissions.cs b/Blocks/Block.Permissions.cs index d0aa274bc..f77bada8d 100644 --- a/Blocks/Block.Permissions.cs +++ b/Blocks/Block.Permissions.cs @@ -117,7 +117,7 @@ namespace MCGalaxy case wood_float: case lava_sponge: - case door_tree__air: + case door_tree_air: case door_obsidian_air: case door_glass_air: case door_stone_air: diff --git a/Blocks/Block.cs b/Blocks/Block.cs index 16071d2ee..b36b7841d 100644 --- a/Blocks/Block.cs +++ b/Blocks/Block.cs @@ -472,7 +472,7 @@ namespace MCGalaxy { switch (b) { - case door_tree: return door_tree__air; + case door_tree: return door_tree_air; case door_obsidian: return door_obsidian_air; case door_glass: return door_glass_air; case door_stone: return door_stone_air; diff --git a/Levels/Level.Physics.cs b/Levels/Level.Physics.cs index b448435c4..7efa1858f 100644 --- a/Levels/Level.Physics.cs +++ b/Levels/Level.Physics.cs @@ -567,7 +567,7 @@ namespace MCGalaxy { case Block.air_flood_down: case Block.air_flood_up: blocks[C.b] = 0; break; - case Block.door_tree__air: + case Block.door_tree_air: //blocks[C.b] = 111; Blockchange(x, y, z, Block.door_tree); break; case Block.door_obsidian_air: diff --git a/Levels/Physics/DoorPhysics.cs b/Levels/Physics/DoorPhysics.cs index 6f24d0b68..6aa6abb8f 100644 --- a/Levels/Physics/DoorPhysics.cs +++ b/Levels/Physics/DoorPhysics.cs @@ -29,7 +29,7 @@ namespace MCGalaxy.BlockPhysics { switch (lvl.blocks[C.b]) { //Change any door blocks nearby into door_air - case Block.door_tree__air: + case Block.door_tree_air: case Block.door_obsidian_air: case Block.door_glass_air: case Block.door_stone_air: diff --git a/MCGalaxy_.csproj b/MCGalaxy_.csproj index be9d5458d..f3ba948c5 100644 --- a/MCGalaxy_.csproj +++ b/MCGalaxy_.csproj @@ -101,7 +101,9 @@ - + + + @@ -719,6 +721,7 @@ + diff --git a/Player/Player.Handlers.cs b/Player/Player.Handlers.cs index 62e76cb15..70fe0b088 100644 --- a/Player/Player.Handlers.cs +++ b/Player/Player.Handlers.cs @@ -126,13 +126,9 @@ namespace MCGalaxy { } //else if ( !painting && action == 0 ) { - if ( !deleteMode ) { - if ( Block.portal(b) ) { HandlePortal(this, x, y, z, b); return; } - if ( Block.mb(b) ) { HandleMsgBlock(this, x, y, z, b); return; } - } - bP.flags |= 1; - level.blockCache.Add(bP); - DeleteBlock(b, x, y, z, type, extType); + bP.flags |= 1; + if (DeleteBlock(b, x, y, z, type, extType)) + level.blockCache.Add(bP); } else { level.blockCache.Add(bP); PlaceBlock(b, x, y, z, type, extType); @@ -672,77 +668,18 @@ namespace MCGalaxy { } } - void HandlePortal(Player p, ushort x, ushort y, ushort z, byte b) { - try { - //safe against SQL injections because no user input is given here - DataTable Portals = Database.fillData("SELECT * FROM `Portals" + level.name + "` WHERE EntryX=" + (int)x + " AND EntryY=" + (int)y + " AND EntryZ=" + (int)z); - - int LastPortal = Portals.Rows.Count - 1; - if ( LastPortal > -1 ) { - if ( level.name != Portals.Rows[LastPortal]["ExitMap"].ToString() ) { - if ( level.permissionvisit > this.group.Permission ) { - Player.SendMessage(this, "You do not have the adequate rank to visit this map!"); - return; - } - ignorePermission = true; - Level thisLevel = level; - Command.all.Find("goto").Use(this, Portals.Rows[LastPortal]["ExitMap"].ToString()); - if ( thisLevel == level ) { Player.SendMessage(p, "The map the portal goes to isn't loaded."); return; } - ignorePermission = false; - } - else SendBlockchange(x, y, z, b); - - p.BlockUntilLoad(10); - Command.all.Find("move").Use(this, this.name + " " + Portals.Rows[LastPortal]["ExitX"].ToString() + " " + Portals.Rows[LastPortal]["ExitY"].ToString() + " " + Portals.Rows[LastPortal]["ExitZ"].ToString()); - } - else { - Blockchange(this, x, y, z, Block.air, 0); - } - Portals.Dispose(); - } - catch { Player.SendMessage(p, "Portal had no exit."); return; } - } - static char[] trimChars = { ' ' }; - void HandleMsgBlock(Player p, ushort x, ushort y, ushort z, byte b) { - try { - //safe against SQL injections because no user input is given here - DataTable Messages = Database.fillData("SELECT * FROM `Messages" + level.name + "` WHERE X=" + (int)x + " AND Y=" + (int)y + " AND Z=" + (int)z); - - int LastMsg = Messages.Rows.Count - 1; - if ( LastMsg > -1 ) { - string message = Messages.Rows[LastMsg]["Message"].ToString().Trim(); - message = message.Replace("\\'", "\'"); - if ( message != prevMsg || Server.repeatMessage ) { - if ( message.StartsWith("/") ) { - string[] parts = message.Remove(0, 1).Split(trimChars, 2); - HandleCommand(parts[0], parts.Length > 1 ? parts[1] : ""); - } else { - Player.SendMessage(p, message); - } - prevMsg = message; - } - SendBlockchange(x, y, z, b); - } else { - Blockchange(this, x, y, z, Block.air, 0); - } - Messages.Dispose(); - } catch { - Player.SendMessage(p, "No message was stored."); - RevertBlock(x, y, z); return; - } - } - void DeleteBlock(byte b, ushort x, ushort y, ushort z, byte type, byte extType) { - if ( deleteMode && b != Block.c4det ) { ChangeBlock(x, y, z, Block.air, 0); return; } + bool DeleteBlock(byte b, ushort x, ushort y, ushort z, byte type, byte extType) { + if (deleteMode) { ChangeBlock(x, y, z, Block.air, 0); return true; } - if ( Block.tDoor(b) ) { RevertBlock(x, y, z); return; } + if ( Block.tDoor(b) ) { RevertBlock(x, y, z); return true; } if ( Block.DoorAirs(b) != 0 ) { if ( level.physics != 0 ) level.Blockchange(x, y, z, Block.DoorAirs(b)); else RevertBlock(x, y, z); - return; + return true; } if ( Block.odoor(b) != Block.Zero ) { if ( b == Block.odoor8 || b == Block.odoor8_air ) { @@ -750,11 +687,11 @@ namespace MCGalaxy { } else { RevertBlock(x, y, z); } - return; + return true; } switch ( b ) { - case Block.door_tree__air: //Door_air + case Block.door_tree_air: //Door_air case Block.door_obsidian_air: case Block.door_glass_air: case Block.door_stone_air: @@ -779,15 +716,10 @@ namespace MCGalaxy { case Block.door_book_air: break; - case Block.c4det: - Level.C4.BlowUp(new ushort[] { x, y, z }, level); - level.Blockchange(x, y, z, Block.air); - break; - default: Block.HandleDelete handler = Block.deleteHandlers[b]; if (handler != null) { - if (handler(this, b, x, y, z)) return; + if (handler(this, b, x, y, z)) return false; } else { ChangeBlock(x, y, z, Block.air, 0); } @@ -795,6 +727,7 @@ namespace MCGalaxy { } if ((level.physics == 0 || level.physics == 5) && level.GetTile(x, (ushort)(y - 1), z) == Block.dirt) ChangeBlock(x, (ushort)(y - 1), z, Block.grass, 0); + return true; } void PlaceBlock(byte b, ushort x, ushort y, ushort z, byte type, byte extType) { @@ -941,33 +874,10 @@ return; level.Blockchange(x, (ushort)(y - 1), z, Block.DoorAirs(b1)); if ( level.PosToInt( x, y, z ) != oldIndex ) { - if ( b == Block.air_portal || b == Block.water_portal || b == Block.lava_portal ) { - HandlePortal(this, x, y, z, b); - } else if ( b1 == Block.air_portal || b1 == Block.water_portal || b1 == Block.lava_portal ) { - HandlePortal(this, x, (ushort)(y - 1), z, b1); - } - - if ( b == Block.MsgAir || b == Block.MsgWater || b == Block.MsgLava ) { - HandleMsgBlock(this, x, y, z, b); - } else if ( b1 == Block.MsgAir || b1 == Block.MsgWater || b1 == Block.MsgLava ) { - HandleMsgBlock(this, x, (ushort)(y - 1), z, b1); - } else if ( b == Block.checkpoint ) { - useCheckpointSpawn = true; - checkpointX = x; checkpointY = y; checkpointZ = z; - int index = level.PosToInt(x, y, z); - if (index != lastCheckpointIndex) { - SendSpawn(0xFF, color + truename, pos[0], (ushort)((y - 1) * 32 + 51), pos[2], rot[0], rot[1]); - lastCheckpointIndex = index; - } - } else if ( b1 == Block.checkpoint ) { - useCheckpointSpawn = true; - checkpointX = x; checkpointY = (ushort)(y + 1); checkpointZ = z; - int index = level.PosToInt(x, (ushort)(y - 1), z); - if (index != lastCheckpointIndex) { - SendSpawn(0xFF, color + truename, pos[0], (ushort)((y - 1) * 32 + 51), pos[2], rot[0], rot[1]); - lastCheckpointIndex = index; - } - } + Block.HandleWalkthrough handler = Block.walkthroughHandlers[b]; + if (handler != null && handler(this, b, x, y, z)) return; + handler = Block.walkthroughHandlers[b1]; + if (handler != null && handler(this, b, x, y, z)) return; } } if ( ( b == Block.tntexplosion || b1 == Block.tntexplosion ) && PlayingTntWars ) { }