Modularise more block behaviour.

This commit is contained in:
UnknownShadow200 2016-04-02 16:38:14 +11:00
parent eac5ea6794
commit 9621275334
11 changed files with 188 additions and 135 deletions

View File

@ -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 {
/// <summary> Returns whether this block handles the player placing a block at the given coordinates. </summary>
/// <remarks>If this returns true, the usual 'dirt/grass below' behaviour and 'adding to the BlockDB' is skipped. </remarks>
public delegate bool HandleDelete(Player p, byte block, ushort x, ushort y, ushort z);
internal static HandleDelete[] deleteHandlers = new HandleDelete[256];
/// <summary> Returns whether this block handles the player deleting a block at the given coordinates. </summary>
/// <remarks>If this returns true, the usual 'checking dirt/grass below' and 'adding to the BlockDB' is skipped. </remarks>
public delegate bool HandlePlace(Player p, byte block, ushort x, ushort y, ushort z);
internal static HandlePlace[] placeHandlers = new Block.HandlePlace[256];
/// <summary> Returns whether this block handles the player walking through this block at the given coordinates. </summary>
/// <remarks>If this returns true, the usual 'checking dirt/grass below' behaviour is skipped. </remarks>
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;
}
}
}
}
}

View File

@ -17,30 +17,15 @@
*/
using System;
namespace MCGalaxy {
namespace MCGalaxy.BlockBehaviour {
public sealed partial class Block {
/// <summary> Returns whether this block handles the player placing a block at the given coordinates. </summary>
/// <remarks>If this returns true, the usual 'checking dirt/grass below' behaviour is skipped. </remarks>
public delegate bool HandleDelete(Player p, byte block, ushort x, ushort y, ushort z);
internal static HandleDelete[] deleteHandlers = new HandleDelete[256];
/// <summary> Returns whether this block handles the player deleting a block at the given coordinates. </summary>
/// <remarks>If this returns true, the usual 'checking dirt/grass below' behaviour is skipped. </remarks>
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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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:

View File

@ -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;

View File

@ -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:

View File

@ -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:

View File

@ -101,7 +101,9 @@
</ItemGroup>
<ItemGroup>
<Compile Include="API\WhoWas.cs" />
<Compile Include="Blocks\Block.Behaviour.cs" />
<Compile Include="Blocks\Behaviour\Block.Behaviour.cs" />
<Compile Include="Blocks\Behaviour\DeleteBehaviour.cs" />
<Compile Include="Blocks\Behaviour\WalkthroughBehaviour.cs" />
<Compile Include="Blocks\Block.Convert.cs" />
<Compile Include="Blocks\Block.cs" />
<Compile Include="Blocks\Block.ID.cs" />
@ -719,6 +721,7 @@
</Content>
</ItemGroup>
<ItemGroup>
<Folder Include="Blocks\Behaviour" />
<Folder Include="Commands" />
<Folder Include="Commands\Building" />
<Folder Include="Commands\Fun" />

View File

@ -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 ) { }