Redesign BlockQueue/PhysicsArgs for future extensibility

This commit is contained in:
UnknownShadow200 2018-02-28 21:43:52 +11:00
parent 08286625f3
commit ecec7a9843
10 changed files with 62 additions and 56 deletions

View File

@ -89,6 +89,10 @@ namespace MCGalaxy.Blocks {
/// <summary> Retrieves the default physics block handler for the given block. </summary>
internal static HandlePhysics GetPhysicsHandler(BlockID block, BlockProps[] props) {
switch (block) {
case Block.Door_Log_air: return DoorPhysics.Do;
case Block.Door_TNT_air: return DoorPhysics.Do;
case Block.Door_Green_air: return DoorPhysics.Do;
case Block.SnakeTail: return SnakePhysics.DoTail;
case Block.Snake: return SnakePhysics.Do;
case Block.RocketHead: return RocketPhysics.Do;
@ -166,6 +170,10 @@ namespace MCGalaxy.Blocks {
/// <summary> Retrieves the default physics block handler for the given block. </summary>
internal static HandlePhysics GetPhysicsDoorsHandler(BlockID block, BlockProps[] props) {
if (block == Block.Air) return DoorPhysics.Do;
if (block == Block.Door_Log_air) return DoorPhysics.Do;
if (block == Block.Door_TNT_air) return DoorPhysics.Do;
if (block == Block.Door_Green_air) return DoorPhysics.Do;
if (props[block].oDoorBlock != Block.Invalid) return DoorPhysics.oDoor;
return null;
}

View File

@ -84,9 +84,8 @@ namespace MCGalaxy.Blocks.Physics {
internal static PhysicsArgs GetDoorArgs(BlockID block, out BlockID physForm) {
PhysicsArgs args = default(PhysicsArgs);
args.Type1 = PhysicsArgs.Wait; args.Value1 = 16 - 1;
args.Type1 = PhysicsArgs.Custom; args.Value1 = 16 - 1;
args.Type2 = PhysicsArgs.Revert; args.Value2 = (BlockRaw)block;
args.Door = true;
args.ExtBlock = block >= Block.Extended;
physForm = Block.Door_Log_air; // air
@ -102,9 +101,8 @@ namespace MCGalaxy.Blocks.Physics {
internal static PhysicsArgs GetTDoorArgs(BlockID block) {
PhysicsArgs args = default(PhysicsArgs);
args.Type1 = PhysicsArgs.Wait; args.Value1 = 16;
args.Type1 = PhysicsArgs.Custom; args.Value1 = 16;
args.Type2 = PhysicsArgs.Revert; args.Value2 = (BlockRaw)block;
args.Door = true;
args.ExtBlock = block >= Block.Extended;
return args;
}

View File

@ -24,6 +24,10 @@ namespace MCGalaxy.Blocks.Physics {
public static class AirPhysics {
public static void DoAir(Level lvl, ref PhysInfo C) {
if (C.Data.Type1 == PhysicsArgs.Custom) {
DoorPhysics.Do(lvl, ref C); return;
}
ushort x = C.X, y = C.Y, z = C.Z;
ActivateablePhysics.CheckNeighbours(lvl, x, y, z);
ActivateablePhysics.CheckAt(lvl, x, (ushort)(y - 1), z);

View File

@ -21,8 +21,28 @@ using BlockID = System.UInt16;
namespace MCGalaxy.Blocks.Physics {
public static class DoorPhysics {
public static void Do(Level lvl, ref PhysInfo C) {
if (C.Data.Type1 != PhysicsArgs.Custom) return;
if (C.Data.Data == 0) {
BlockID block = (BlockID)(C.Data.Value2 | (C.Data.ExtBlock ? Block.Extended : 0));
bool tdoor = lvl.Props[block].IsTDoor;
if (tdoor) tDoor(lvl, ref C);
else Door(lvl, ref C);
}
if (C.Data.Data <= C.Data.Value1) { // value1 for wait time
C.Data.Data++;
} else {
PhysicsArgs dArgs = default(PhysicsArgs);
dArgs.ExtBlock = C.Data.ExtBlock;
lvl.AddUpdate(C.Index, C.Data.Value2, dArgs);
C.Data.Data = PhysicsArgs.RemoveFromChecks;
}
}
// Change anys door blocks nearby into air forms
public static void Door(Level lvl, ref PhysInfo C) {
static void Door(Level lvl, ref PhysInfo C) {
ushort x = C.X, y = C.Y, z = C.Z;
BlockID block = (BlockID)(C.Data.Value2 | (C.Data.ExtBlock ? Block.Extended : 0));
bool instant = block == Block.Door_Air || block == Block.Door_AirActivatable;
@ -62,8 +82,7 @@ namespace MCGalaxy.Blocks.Physics {
}
}
public static void tDoor(Level lvl, ref PhysInfo C) {
static void tDoor(Level lvl, ref PhysInfo C) {
ushort x = C.X, y = C.Y, z = C.Z;
ActivateTDoor(lvl, (ushort)(x - 1), y, z);
ActivateTDoor(lvl, (ushort)(x + 1), y, z);

View File

@ -25,19 +25,10 @@ namespace MCGalaxy.Blocks.Physics {
public static class ExtraInfoPhysics {
public static bool DoDoorsOnly(Level lvl, ref PhysInfo C) {
if (C.Data.Type1 == PhysicsArgs.Custom) return true;
if (!C.Data.HasWait && C.Block == Block.Air)
C.Data.ResetTypes();
if (!C.Data.HasWait) return false;
if (C.Data.Door && C.Data.Data == 0) {
BlockID block = (BlockID)(C.Data.Value2 | (C.Data.ExtBlock ? Block.Extended : 0));
bool tdoor = lvl.Props[block].IsTDoor;
if (tdoor) DoorPhysics.tDoor(lvl, ref C);
else DoorPhysics.Door(lvl, ref C);
}
int waitTime = 0;
if (C.Data.Type1 == PhysicsArgs.Wait) waitTime = C.Data.Value1;
if (C.Data.Type2 == PhysicsArgs.Wait) waitTime = C.Data.Value2;
@ -46,19 +37,10 @@ namespace MCGalaxy.Blocks.Physics {
if (C.Data.Type1 == PhysicsArgs.Wait) C.Data.Type1 = 0;
if (C.Data.Type2 == PhysicsArgs.Wait) C.Data.Type2 = 0;
if (C.Data.Door) {
PhysicsArgs dArgs = default(PhysicsArgs);
dArgs.ExtBlock = C.Data.ExtBlock;
lvl.AddUpdate(C.Index, C.Data.Value2, dArgs);
C.Data.ResetTypes();
C.Data.Data = PhysicsArgs.RemoveFromChecks;
}
return false;
}
public static bool DoNormal(Level lvl, ref PhysInfo C) {
if (C.Data.Type1 == PhysicsArgs.Custom) return true;
if (!C.Data.HasWait && C.Block == Block.Air)
C.Data.ResetTypes();
@ -68,14 +50,6 @@ namespace MCGalaxy.Blocks.Physics {
args.ExtBlock = C.Data.ExtBlock;
if (args.Wait) {
if (C.Data.Door && C.Data.Data == 0) {
BlockID block = (BlockID)(C.Data.Value2 | (C.Data.ExtBlock ? Block.Extended : 0));
bool tdoor = lvl.Props[block].IsTDoor;
if (tdoor) DoorPhysics.tDoor(lvl, ref C);
else DoorPhysics.Door(lvl, ref C);
}
if (C.Data.Data <= args.WaitTime) { C.Data.Data++; return true; }
if (C.Data.Type1 == PhysicsArgs.Wait) C.Data.Type1 = 0;
if (C.Data.Type2 == PhysicsArgs.Wait) C.Data.Type2 = 0;

View File

@ -27,7 +27,7 @@ namespace MCGalaxy.Blocks.Physics {
public const uint TypeMask = 0x3F;
public const uint TypeBitsMask = 0x07;
public const uint ValueBitsMask = 0xFF;
public const uint ExtBit = 1u << 31;
public const uint ExtBit = 1u << 30;
/// <summary> Indicates that this physics entry should be removed from the list of
/// entries that are checked for physics, at the end of the current tick. </summary>
@ -58,11 +58,6 @@ namespace MCGalaxy.Blocks.Physics {
set { Raw &= ~(ValueBitsMask << 22); Raw |= (uint)value << 22; }
}
public bool Door {
get { return (Raw & (1u << 30)) != 0; }
set { Raw &= ~(1u << 30); Raw |= (value ? 1u : 0u) << 30; }
}
public bool ExtBlock {
get { return (Raw & ExtBit) != 0; }
set { Raw &= ~ExtBit; Raw |= value ? ExtBit : 0u; }

View File

@ -176,7 +176,7 @@ namespace MCGalaxy.Commands.Info {
Player.Message(p, "Water level: &b{0}%S, Bedrock offset: &b{1}%S, Clouds height: &b{2}%S, Max fog distance: &b{3}",
cfg.EdgeLevel,cfg.SidesOffset, cfg.CloudsHeight, cfg.MaxFogDistance);
Player.Message(p, "Edge Block: &b{0}%S, Horizon Block: &b{1}",
cfg.EdgeBlock, cfg.HorizonBlock);
Block.GetName(p, cfg.EdgeBlock), Block.GetName(p, cfg.HorizonBlock));
Player.Message(p, "Clouds speed: &b{0}%%S, Weather speed: &b{1}%",
(cfg.CloudsSpeed / 256f).ToString("F2"),
(cfg.WeatherSpeed / 256f).ToString("F2"));

View File

@ -38,8 +38,7 @@ namespace MCGalaxy.Commands.Building {
p.DefaultBrushArgs = "";
p.Transform = NoTransform.Instance;
lock (p.level.queueLock)
p.level.blockqueue.RemoveAll(b => (int)((b >> 9) & Player.SessionIDMask) == p.SessionID);
BlockQueue.RemoveAll(p);
Player.Message(p, "Every toggle or action was aborted.");
}

View File

@ -27,7 +27,10 @@ namespace MCGalaxy {
public static int Interval = 100;
public static int UpdatesPerTick = 750;
static BufferedBlockSender bulkSender = new BufferedBlockSender();
public const int BlockMask = 0x1FF;
const int posShift = 32;
const int idShift = 12;
const int blockMask = 0x7FF;
public static void Loop(SchedulerTask task) {
Level[] loaded = LevelInfo.Loaded.Items;
@ -44,15 +47,21 @@ namespace MCGalaxy {
if (index == -1) return;
// Bit packing format
// 32-63: index
// 9-31: session ID
// 8: is ext block or not
// 0-7: raw type
ulong flags = (ulong)index << 32;
flags |= (ulong)p.SessionID << 9;
flags |= (ulong)block & BlockMask;
// 12-31: session ID
// 0-11: block type
ulong flags = (ulong)index << posShift;
flags |= (ulong)p.SessionID << idShift;
flags |= (ulong)block & blockMask;
lock (p.level.queueLock)
lock (p.level.queueLock) {
p.level.blockqueue.Add(flags);
}
}
public static void RemoveAll(Player p) {
lock (p.level.queueLock) {
p.level.blockqueue.RemoveAll(b => (int)((b >> idShift) & Player.SessionIDMask) == p.SessionID);
}
}
static void ProcessLevelBlocks(Level lvl) {
@ -67,8 +76,8 @@ namespace MCGalaxy {
for (int i = 0; i < count; i++) {
ulong flags = lvl.blockqueue[i];
int index = (int)(flags >> 32);
BlockID block = (BlockID)(flags & BlockMask);
int index = (int)(flags >> posShift);
BlockID block = (BlockID)(flags & blockMask);
bulkSender.Add(index, block);
}
bulkSender.Send(true);

View File

@ -156,7 +156,7 @@ namespace MCGalaxy {
C.Block = (BlockID)(Block.Extended | GetExtTileNoCheck(C.X, C.Y, C.Z));
}
if ((C.Data.Raw & mask) == 0 || extraHandler(this, ref C)) {
if ((C.Data.Raw & mask) == 0 || C.Data.Type1 == PhysicsArgs.Custom || extraHandler(this, ref C)) {
HandlePhysics handler = handlers[C.Block];
if (handler != null) {
handler(this, ref C);