Majorly optimise block physics performance, also reduce memory usage of level physics undo buffer.

This commit is contained in:
UnknownShadow200 2016-02-28 14:46:15 +11:00
parent 0543cb1dd3
commit db2b4646ff
11 changed files with 185 additions and 122 deletions

View File

@ -192,8 +192,8 @@ namespace MCGalaxy.Commands
bool CheckBlockPhysics(Player p, long seconds, int i, Level.UndoPos undo) {
byte b = p.level.GetTile(undo.location);
if (undo.timePerformed.AddSeconds(seconds) < DateTime.Now)
return false;
DateTime time = Server.StartTime.AddSeconds(undo.timeDelta);
if (time.AddSeconds(seconds) < DateTime.UtcNow) return false;
if (b == undo.newType || Block.Convert(b) == Block.water || Block.Convert(b) == Block.lava) {
ushort x, y, z;

View File

@ -392,7 +392,7 @@ namespace MCGalaxy {
uP.location = b;
uP.newType = type; uP.newExtType = extType;
uP.oldType = oldBlock; uP.oldExtType = oldExtType;
uP.timePerformed = DateTime.Now;
uP.timeDelta = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds;
if (currentUndo > Server.physUndo) {
currentUndo = 0;

View File

@ -128,16 +128,17 @@ namespace MCGalaxy {
if (physics == 5) {
for (int i = 0; i < ListCheck.Count; i++) {
Check C = ListCheck.Items[i];
try {
IntToPos(C.b, out x, out y, out z);
try {
string info = C.data as string;
if (info == null) info = "";
IntToPos(C.b, out x, out y, out z);
if (info == null) info = "";
if (PhysicsUpdate != null)
PhysicsUpdate(x, y, z, C.time, info, this);
if (info == "" || ExtraInfoPhysics.DoDoorsOnly(this, C, null))
DoorPhysics.Do(this, C);
} catch {
listCheckExists.Set(x, y, z, false);
ListCheck.Remove(C);
}
}
@ -145,23 +146,25 @@ namespace MCGalaxy {
Random rand = new Random();
for (int i = 0; i < ListCheck.Count; i++) {
Check C = ListCheck.Items[i];
try {
IntToPos(C.b, out x, out y, out z);
IntToPos(C.b, out x, out y, out z);
try {
string info = C.data as string;
if (info == null) info = "";
if (PhysicsUpdate != null)
PhysicsUpdate(x, y, z, C.time, info, this);
OnPhysicsUpdateEvent.Call(x, y, z, C.time, info, this);
if (OnPhysicsUpdateEvent.events.Count > 0)
OnPhysicsUpdateEvent.Call(x, y, z, C.time, info, this);
if (info == "" || ExtraInfoPhysics.DoComplex(this, C, rand))
DoNormalPhysics(x, y, z, rand, C);
} catch {
listCheckExists.Set(x, y, z, false);
ListCheck.Remove(C);
}
}
}
}
RemoveExpiredChecks();
ListCheck.RemoveAll(C => C.time == 255); //Remove all that are finished with 255 time
lastUpdate = ListUpdate.Count;
for (int i = 0; i < ListUpdate.Count; i++) {
Update C = ListUpdate.Items[i];
@ -173,7 +176,7 @@ namespace MCGalaxy {
Server.s.Log("Phys update issue");
}
}
ListUpdate.Clear();
ListUpdate.Clear(); listUpdateExists.Clear();
} catch (Exception e) {
Server.s.Log("Level physics error");
Server.ErrorLog(e);
@ -415,7 +418,6 @@ namespace MCGalaxy {
ZombiePhysics.Do(this, C, rand); break;
case Block.c4:
Server.s.Log("Processing C4");
C4.C4s c4 = C4.Find(this, ((Player)C.data).c4circuitNumber);
if (c4 != null) {
FillPos pos; pos.X = x; pos.Y = y; pos.Z = z;
@ -425,7 +427,6 @@ namespace MCGalaxy {
break;
case Block.c4det:
Server.s.Log("Processing C4 det");
C4.C4s c = C4.Find(this, ((Player)C.data).c4circuitNumber);
if (c != null) {
c.detenator[0] = x;
@ -440,16 +441,25 @@ namespace MCGalaxy {
DoorPhysics.Do(this, C); break;
}
}
public void AddCheck(int b, bool overRide = false) { AddCheck(b, overRide, ""); }
public void AddCheck(int b, bool overRide, object data) {
try {
int index = ListCheck.IndexOf(C => C.b == b);
if (index < 0) {
try {
ushort x, y, z;
IntToPos(b, out x, out y, out z);
if (x >= Width || y >= Height || z >= Length) return;
if (!listCheckExists.Get(x, y, z)) {
ListCheck.Add(new Check(b, data)); //Adds block to list to be updated
listCheckExists.Set(x, y, z, true);
} else if (overRide) {
ListCheck.Items[index].data = data; return;
Check[] items = ListCheck.Items;
int count = ListCheck.Count;
for (int i = 0; i < count; i++) {
if (items[i].b != b) continue;
items[i].data = data; return;
}
//Dont need to check physics here because if the list is active, then physics is active :)
}
if (!physicssate && physics > 0)
@ -464,23 +474,25 @@ namespace MCGalaxy {
internal bool AddUpdate(int b, int type, bool overRide, object data) {
try {
if (overRide) {
ushort x, y, z;
IntToPos(b, out x, out y, out z);
AddCheck(b, true, data); //Dont need to check physics here....AddCheck will do that
ushort x, y, z;
IntToPos(b, out x, out y, out z);
if (x >= Width || y >= Height || z >= Length) return false;
if (overRide) {
AddCheck(b, true, data); //Dont need to check physics here....AddCheck will do that
string info = data as string;
if (info == null) info = "";
Blockchange(x, y, z, (byte)type, true, info);
return true;
}
if (!ListUpdate.Exists(C => C.b == b)) {
if (!listUpdateExists.Get(x, y, z)) {
listUpdateExists.Set(x, y, z, true);
} else if (type == Block.sand || type == Block.gravel) {
ListUpdate.RemoveAll(C => C.b == b);
RemoveUpdatesAtPos(b);
} else {
return false;
}
}
ListUpdate.Add(new Update(b, (byte)type, data));
if (!physicssate && physics > 0)
@ -492,12 +504,41 @@ namespace MCGalaxy {
return false;
}
}
void RemoveExpiredChecks() {
Check[] items = ListCheck.Items;
int j = 0, count = ListCheck.Count;
ushort x, y, z;
for (int i = 0; i < count; i++) {
if (items[i].time == 255) {
IntToPos(items[i].b, out x, out y, out z);
listCheckExists.Set(x, y, z, false);
continue;
}
items[j] = items[i]; j++;
}
ListCheck.Items = items;
ListCheck.Count = j;
}
void RemoveUpdatesAtPos(int b) {
Update[] items = ListUpdate.Items;
int j = 0, count = ListUpdate.Count;
for (int i = 0; i < count; i++) {
if (items[j].b == b) continue;
items[j] = items[i]; j++;
}
ListUpdate.Items = items;
ListUpdate.Count = j;
}
public void ClearPhysics() {
for (int i = 0; i < ListCheck.Count; i++ )
RevertPhysics(ListCheck.Items[i]);
ListCheck.Clear();
ListUpdate.Clear();
ListCheck.Clear(); listCheckExists.Clear();
ListUpdate.Clear(); listUpdateExists.Clear();
}
void RevertPhysics(Check C) {
@ -541,22 +582,21 @@ namespace MCGalaxy {
internal void PhysAir(int b) { AirPhysics.PhysAir(this, b); }
internal void PhysWater(int b, byte type) {
if (b == -1) return;
ushort x, y, z;
IntToPos(b, out x, out y, out z);
internal void PhysWater(ushort x, ushort y, ushort z, byte type) {
if (x >= Width || y >= Height || z >= Length) return;
if (Server.lava.active && Server.lava.map == this && Server.lava.InSafeZone(x, y, z))
return;
int b = x + (z * Width) + (y * Width * Length);
switch (blocks[b]) {
case Block.air:
if (!PhysSpongeCheck(b)) AddUpdate(b, type);
if (!CheckSpongeWater(x, y, z)) AddUpdate(b, type);
break;
case Block.lava:
case Block.lava_fast:
case Block.activedeathlava:
if (!PhysSpongeCheck(b)) AddUpdate(b, Block.rock);
if (!CheckSpongeWater(x, y, z)) AddUpdate(b, Block.rock);
break;
case Block.shrub:
@ -564,7 +604,7 @@ namespace MCGalaxy {
case Block.redflower:
case Block.mushroom:
case Block.redmushroom:
if (physics > 1 && physics != 5 && !PhysSpongeCheck(b))
if (physics > 1 && physics != 5 && !CheckSpongeWater(x, y, z))
AddUpdate(b, 0); //Adv physics kills flowers and mushrooms in water
break;
@ -577,25 +617,24 @@ namespace MCGalaxy {
}
}
internal void PhysLava(int b, byte type) {
if (b == -1) return;
ushort x, y, z;
IntToPos(b, out x, out y, out z);
internal void PhysLava(ushort x, ushort y, ushort z, byte type) {
if (x >= Width || y >= Height || z >= Length) return;
if (Server.lava.active && Server.lava.map == this && Server.lava.InSafeZone(x, y, z))
return;
if (physics > 1 && physics != 5 && !PhysSpongeCheck(b, true) && blocks[b] >= 21 && blocks[b] <= 36) {
int b = x + Width * (z + y * Length);
if (physics > 1 && physics != 5 && !CheckSpongeLava(x, y, z) && blocks[b] >= 21 && blocks[b] <= 36) {
AddUpdate(b, Block.air); return;
} // Adv physics destroys cloth
} // Adv physics destroys cloth
switch (blocks[b]) {
case Block.air:
if (!PhysSpongeCheck(b, true)) AddUpdate(b, type);
if (!CheckSpongeLava(x, y, z)) AddUpdate(b, type);
break;
case Block.water:
case Block.activedeathwater:
if (!PhysSpongeCheck(b, true)) AddUpdate(b, Block.rock); break;
if (!CheckSpongeLava(x, y, z)) AddUpdate(b, Block.rock); break;
case Block.sand:
if (physics > 1) { //Adv physics changes sand to glass next to lava
@ -616,7 +655,7 @@ namespace MCGalaxy {
case Block.mushroom:
case Block.redmushroom:
if (physics > 1 && physics != 5) //Adv physics kills flowers and mushrooms plus wood in lava
if (!PhysSpongeCheck(b, true)) AddUpdate(b, Block.air);
if (!CheckSpongeLava(x, y, z)) AddUpdate(b, Block.air);
break;
default:
break;
@ -716,16 +755,33 @@ namespace MCGalaxy {
AddUpdate(bBelow, Block.stone);
}
}
internal bool PhysSpongeCheck(int b, bool lava = false) {
for (int y = -2; y <= +2; ++y)
for (int z = -2; z <= +2; ++z)
for (int x = -2; x <= +2; ++x)
{
byte block = GetTile(IntOffset(b, x, y, z));
if (block == Block.Zero) continue;
if ((!lava && block == Block.sponge) || (lava && block == Block.lava_sponge))
return true;
internal bool CheckSpongeWater(ushort x, ushort y, ushort z) {
for (int yy = y - 2; yy <= y + 2; ++yy) {
if (yy < 0 || yy >= Height) continue;
for (int zz = z - 2; zz <= z + 2; ++zz) {
if (zz < 0 || zz >= Length) continue;
for (int xx = x - 2; xx <= x + 2; ++xx) {
if (xx < 0 || xx >= Width) continue;
if (blocks[xx + Width * (zz + yy * Length)] == Block.sponge)
return true;
}
}
}
return false;
}
internal bool CheckSpongeLava(ushort x, ushort y, ushort z) {
for (int yy = y - 2; yy <= y + 2; ++yy) {
if (yy < 0 || yy >= Height) continue;
for (int zz = z - 2; zz <= z + 2; ++zz) {
if (zz < 0 || zz >= Length) continue;
for (int xx = x - 2; xx <= x + 2; ++xx) {
if (xx < 0 || xx >= Width) continue;
if (blocks[xx + Width * (zz + yy * Length)] == Block.lava_sponge)
return true;
}
}
}
return false;
}

View File

@ -69,6 +69,7 @@ namespace MCGalaxy
public static bool cancelphysics;
internal readonly FastList<Check> ListCheck = new FastList<Check>(); //A list of blocks that need to be updated
internal readonly FastList<Update> ListUpdate = new FastList<Update>(); //A list of block to change after calculation
internal readonly SparseBitSet listCheckExists, listUpdateExists;
internal readonly Dictionary<int, sbyte> leaves = new Dictionary<int, sbyte>();
// Holds block state for leaf decay
@ -236,6 +237,8 @@ namespace MCGalaxy
spawnz = (ushort)(Length / 2);
rotx = 0;
roty = 0;
listCheckExists = new SparseBitSet(Width, Height, Length);
listUpdateExists = new SparseBitSet(Width, Height, Length);
//season = new SeasonsCore(this);
}
@ -251,8 +254,8 @@ namespace MCGalaxy
Extras.Clear();
liquids.Clear();
leaves.Clear();
ListCheck.Clear();
ListUpdate.Clear();
ListCheck.Clear(); listCheckExists.Clear();
ListUpdate.Clear(); listUpdateExists.Clear();
UndoBuffer.Clear();
blockCache.Clear();
ZoneList.Clear();
@ -429,10 +432,8 @@ namespace MCGalaxy
// Returns true if ListCheck does not already have an check in the position.
// Useful for fireworks, which depend on two physics blocks being checked, one with extraInfo.
public bool CheckClear(ushort x, ushort y, ushort z)
{
int b = PosToInt(x, y, z);
return !ListCheck.Exists(C => C.b == b);
public bool CheckClear(ushort x, ushort y, ushort z) {
return x >= Width || y >= Height || z >= Length || !listCheckExists.Get(x, y, z);
}
public void Save(bool Override = false, bool clearPhysics = false)
@ -744,7 +745,7 @@ namespace MCGalaxy
public int location;
public byte newType, newExtType;
public byte oldType, oldExtType;
public DateTime timePerformed;
public int timeDelta;
}
public struct Zone {

View File

@ -151,8 +151,8 @@ namespace MCGalaxy.BlockPhysics {
int b1 = lvl.IntOffset(C.b, xx * 3, yy * 3, zz * 3);
int b2 = lvl.IntOffset(C.b, xx * 2, yy * 2, zz * 2);
bool unblocked = lvl.GetTile(b1) == Block.air && lvl.GetTile(b2) == Block.air &&
!lvl.ListUpdate.Exists(u => u.b == b1) &&
!lvl.ListUpdate.Exists(u => u.b == b2);
!lvl.listUpdateExists.Get(x + xx * 3, y + yy * 3, z + zz * 3) &&
!lvl.listUpdateExists.Get(x + xx * 2, y + yy * 2, z + zz * 2);
if (unblocked) {
lvl.AddUpdate(b1, Block.rockethead);
@ -166,8 +166,8 @@ namespace MCGalaxy.BlockPhysics {
int b1 = lvl.IntOffset(C.b, xx, yy + 1, zz);
int b2 = lvl.IntOffset(C.b, xx, yy + 2, zz);
bool unblocked = lvl.GetTile(b1) == Block.air && lvl.GetTile(b2) == Block.air &&
!lvl.ListUpdate.Exists(u => u.b == b1) &&
!lvl.ListUpdate.Exists(u => u.b == b2);
!lvl.listUpdateExists.Get(x + xx, y + yy + 1, z + zz) &&
!lvl.listUpdateExists.Get(x + xx, y + yy + 2, z + zz);
if (unblocked) {
lvl.AddUpdate(b2, Block.firework);

View File

@ -33,10 +33,10 @@ namespace MCGalaxy.BlockPhysics {
lvl.AddUpdate(lvl.PosToInt(x, (ushort)(y - 1), z), Block.magma);
} else if (below != Block.magma) {
byte block = lvl.blocks[C.b];
lvl.PhysLava(lvl.PosToInt((ushort)(x + 1), y, z), block);
lvl.PhysLava(lvl.PosToInt((ushort)(x - 1), y, z), block);
lvl.PhysLava(lvl.PosToInt(x, y, (ushort)(z + 1)), block);
lvl.PhysLava(lvl.PosToInt(x, y, (ushort)(z - 1)), block);
lvl.PhysLava((ushort)(x + 1), y, z, block);
lvl.PhysLava((ushort)(x - 1), y, z, block);
lvl.PhysLava(x, y, (ushort)(z + 1), block);
lvl.PhysLava(x, y, (ushort)(z - 1), block);
}
if (lvl.physics <= 1 || C.time <= 10) return;
@ -70,10 +70,10 @@ namespace MCGalaxy.BlockPhysics {
lvl.AddUpdate(lvl.PosToInt(x, (ushort)(y - 1), z), Block.geyser);
} else if (below != Block.geyser) {
byte block = lvl.blocks[C.b];
lvl.PhysWater(lvl.PosToInt((ushort)(x + 1), y, z), block);
lvl.PhysWater(lvl.PosToInt((ushort)(x - 1), y, z), block);
lvl.PhysWater(lvl.PosToInt(x, y, (ushort)(z + 1)), block);
lvl.PhysWater(lvl.PosToInt(x, y, (ushort)(z - 1)), block);
lvl.PhysWater((ushort)(x + 1), y, z, block);
lvl.PhysWater((ushort)(x - 1), y, z, block);
lvl.PhysWater(x, y, (ushort)(z + 1), block);
lvl.PhysWater(x, y, (ushort)(z - 1), block);
}
if (lvl.physics <= 1 || C.time <= 10) return;
@ -116,10 +116,10 @@ namespace MCGalaxy.BlockPhysics {
break;
default:
byte block = lvl.blocks[C.b];
lvl.PhysWater(lvl.PosToInt((ushort)(x + 1), y, z), block);
lvl.PhysWater(lvl.PosToInt((ushort)(x - 1), y, z), block);
lvl.PhysWater(lvl.PosToInt(x, y, (ushort)(z + 1)),block);
lvl.PhysWater(lvl.PosToInt(x, y, (ushort)(z - 1)), block);
lvl.PhysWater((ushort)(x + 1), y, z, block);
lvl.PhysWater((ushort)(x - 1), y, z, block);
lvl.PhysWater(x, y, (ushort)(z + 1),block);
lvl.PhysWater(x, y, (ushort)(z - 1), block);
if (!(C.data is string) || !((string)C.data).Contains("wait"))
C.time = 255;
break;
@ -145,10 +145,10 @@ namespace MCGalaxy.BlockPhysics {
break;
default:
byte block = lvl.blocks[C.b];
lvl.PhysLava(lvl.PosToInt((ushort)(x + 1), y, z), block);
lvl.PhysLava(lvl.PosToInt((ushort)(x - 1), y, z), block);
lvl.PhysLava(lvl.PosToInt(x, y, (ushort)(z + 1)),block);
lvl.PhysLava(lvl.PosToInt(x, y, (ushort)(z - 1)), block);
lvl.PhysLava((ushort)(x + 1), y, z, block);
lvl.PhysLava((ushort)(x - 1), y, z, block);
lvl.PhysLava(x, y, (ushort)(z + 1),block);
lvl.PhysLava(x, y, (ushort)(z - 1), block);
if (!(C.data is string) || !((string)C.data).Contains("wait"))
C.time = 255;
break;

View File

@ -152,7 +152,7 @@ namespace MCGalaxy.BlockPhysics {
// Not setting drop = false can cause occasional leftover blocks, since C.extraInfo is emptied, so
// drop can generate another block with no dissipate/explode information.
if (args.Dissipate && rand.Next(1, 100) <= args.DissipateNum) {
if (!lvl.ListUpdate.Exists(Update => Update.b == C.b)) {
if (!lvl.listUpdateExists.Get(x, y, z)) {
lvl.AddUpdate(C.b, Block.air);
C.data = "";
args.Drop = false;

View File

@ -36,7 +36,7 @@ namespace MCGalaxy.BlockPhysics {
if (keepGoing) {
int bAbove = lvl.PosToInt(x, (ushort)(y + 1), z);
bool unblocked = !lvl.ListUpdate.Exists(u => u.b == bAbove);
bool unblocked = bAbove < 0 || !lvl.listUpdateExists.Get(x, y + 1, z);
if (unblocked) {
lvl.AddUpdate(bAbove, Block.firework, false);
lvl.AddUpdate(C.b, Block.lavastill, false, "wait 1 dissipate 100");

View File

@ -22,6 +22,7 @@ namespace MCGalaxy.BlockPhysics {
public static class LiquidPhysics {
const StringComparison comp = StringComparison.Ordinal;
public static void DoWater(Level lvl, Check C, Random rand) {
if (lvl.finite) {
lvl.liquids.Remove(C.b);
@ -65,7 +66,7 @@ namespace MCGalaxy.BlockPhysics {
ushort x, y, z;
lvl.IntToPos(C.b, out x, out y, out z);
if (!lvl.PhysSpongeCheck(C.b)) {
if (!lvl.CheckSpongeWater(x, y, z)) {
if (!lvl.liquids.TryGetValue(C.b, out blocked)) {
blocked = new bool[5];
lvl.liquids.Add(C.b, blocked);
@ -77,23 +78,23 @@ namespace MCGalaxy.BlockPhysics {
}
if (!blocked[0] && rand.Next(4) == 0) {
lvl.PhysWater(lvl.PosToInt((ushort)(x + 1), y, z), block);
lvl.PhysWater((ushort)(x + 1), y, z, block);
blocked[0] = true;
}
if (!blocked[1] && rand.Next(4) == 0) {
lvl.PhysWater(lvl.PosToInt((ushort)(x - 1), y, z), block);
lvl.PhysWater((ushort)(x - 1), y, z, block);
blocked[1] = true;
}
if (!blocked[2] && rand.Next(4) == 0) {
lvl.PhysWater(lvl.PosToInt(x, y, (ushort)(z + 1)), block);
lvl.PhysWater(x, y, (ushort)(z + 1), block);
blocked[2] = true;
}
if (!blocked[3] && rand.Next(4) == 0) {
lvl.PhysWater(lvl.PosToInt(x, y, (ushort)(z - 1)), block);
lvl.PhysWater(x, y, (ushort)(z - 1), block);
blocked[3] = true;
}
if (!blocked[4] && rand.Next(4) == 0) {
lvl.PhysWater(lvl.PosToInt(x, (ushort)(y - 1), z), block);
lvl.PhysWater(x, (ushort)(y - 1), z, block);
blocked[4] = true;
}
@ -111,11 +112,11 @@ namespace MCGalaxy.BlockPhysics {
lvl.liquids.TryGetValue(C.b, out blocked);
lvl.AddUpdate(C.b, Block.air);
if (((string)C.data).IndexOf("wait") == -1)
if (((string)C.data).IndexOf("wait", comp) == -1)
C.time = 255;
}
if (((string)C.data).IndexOf("wait") == -1 && blocked != null)
if (((string)C.data).IndexOf("wait", comp) == -1 && blocked != null)
if (blocked[0] && blocked[1] && blocked[2] && blocked[3] && blocked[4])
{
lvl.liquids.Remove(C.b);
@ -128,21 +129,21 @@ namespace MCGalaxy.BlockPhysics {
ushort x, y, z;
lvl.IntToPos(C.b, out x, out y, out z);
if (!lvl.PhysSpongeCheck(C.b)) {
if (!lvl.CheckSpongeWater(x, y, z)) {
byte block = lvl.blocks[C.b];
if (lvl.GetTile(x, (ushort)(y + 1), z) != Block.Zero) {
lvl.PhysSandCheck(lvl.PosToInt(x, (ushort)(y + 1), z));
}
lvl.PhysWater(lvl.PosToInt((ushort)(x + 1), y, z), block);
lvl.PhysWater(lvl.PosToInt((ushort)(x - 1), y, z), block);
lvl.PhysWater(lvl.PosToInt(x, y, (ushort)(z + 1)), block);
lvl.PhysWater(lvl.PosToInt(x, y, (ushort)(z - 1)), block);
lvl.PhysWater(lvl.PosToInt(x, (ushort)(y - 1), z), block);
lvl.PhysWater((ushort)(x + 1), y, z, block);
lvl.PhysWater((ushort)(x - 1), y, z, block);
lvl.PhysWater(x, y, (ushort)(z + 1), block);
lvl.PhysWater(x, y, (ushort)(z - 1), block);
lvl.PhysWater(x, (ushort)(y - 1), z, block);
} else { //was placed near sponge
lvl.AddUpdate(C.b, Block.air);
}
if (((string)C.data).IndexOf("wait") == -1)
if (((string)C.data).IndexOf("wait", comp) == -1)
C.time = 255;
}
@ -158,7 +159,7 @@ namespace MCGalaxy.BlockPhysics {
case Block.lava:
case Block.lava_fast:
case Block.activedeathlava:
if (!lvl.PhysSpongeCheck(b)) return false;
if (!lvl.CheckSpongeWater(x, y, z)) return false;
break;
case Block.shrub:
@ -166,7 +167,7 @@ namespace MCGalaxy.BlockPhysics {
case Block.redflower:
case Block.mushroom:
case Block.redmushroom:
if (lvl.physics > 1 && !lvl.PhysSpongeCheck(b)) return false;
if (lvl.physics > 1 && !lvl.CheckSpongeWater(x, y, z)) return false;
break;
case Block.sand:
@ -182,7 +183,7 @@ namespace MCGalaxy.BlockPhysics {
ushort x, y, z;
lvl.IntToPos(C.b, out x, out y, out z);
if (!lvl.PhysSpongeCheck(C.b, true)) {
if (!lvl.CheckSpongeLava(x, y, z)) {
C.time = (byte)rand.Next(3);
if (!lvl.liquids.TryGetValue(C.b, out blocked)) {
blocked = new bool[5];
@ -191,23 +192,23 @@ namespace MCGalaxy.BlockPhysics {
byte block = lvl.blocks[C.b];
if (!blocked[0] && rand.Next(4) == 0) {
lvl.PhysLava(lvl.PosToInt((ushort)(x + 1), y, z), block);
lvl.PhysLava((ushort)(x + 1), y, z, block);
blocked[0] = true;
}
if (!blocked[1] && rand.Next(4) == 0) {
lvl.PhysLava(lvl.PosToInt((ushort)(x - 1), y, z), block);
lvl.PhysLava((ushort)(x - 1), y, z, block);
blocked[1] = true;
}
if (!blocked[2] && rand.Next(4) == 0) {
lvl.PhysLava(lvl.PosToInt(x, y, (ushort)(z + 1)), block);
lvl.PhysLava(x, y, (ushort)(z + 1), block);
blocked[2] = true;
}
if (!blocked[3] && rand.Next(4) == 0) {
lvl.PhysLava(lvl.PosToInt(x, y, (ushort)(z - 1)), block);
lvl.PhysLava(x, y, (ushort)(z - 1), block);
blocked[3] = true;
}
if (!blocked[4] && rand.Next(4) == 0) {
lvl.PhysLava(lvl.PosToInt(x, (ushort)(y - 1), z), block);
lvl.PhysLava(x, (ushort)(y - 1), z, block);
blocked[4] = true;
}
@ -224,11 +225,11 @@ namespace MCGalaxy.BlockPhysics {
} else { //was placed near sponge
lvl.liquids.TryGetValue(C.b, out blocked);
lvl.AddUpdate(C.b, Block.air);
if (!checkWait || ((string)C.data).IndexOf("wait") == -1)
if (!checkWait || ((string)C.data).IndexOf("wait", comp) == -1)
C.time = 255;
}
if (blocked != null && (!checkWait || ((string)C.data).IndexOf("wait") == -1))
if (blocked != null && (!checkWait || ((string)C.data).IndexOf("wait", comp) == -1))
if (blocked[0] && blocked[1] && blocked[2] && blocked[3] && blocked[4])
{
lvl.liquids.Remove(C.b);
@ -241,18 +242,18 @@ namespace MCGalaxy.BlockPhysics {
ushort x, y, z;
lvl.IntToPos(C.b, out x, out y, out z);
if (!lvl.PhysSpongeCheck(C.b, true)) {
if (!lvl.CheckSpongeLava(x, y, z)) {
byte block = lvl.blocks[C.b];
lvl.PhysLava(lvl.PosToInt((ushort)(x + 1), y, z), block);
lvl.PhysLava(lvl.PosToInt((ushort)(x - 1), y, z), block);
lvl.PhysLava(lvl.PosToInt(x, y, (ushort)(z + 1)), block);
lvl.PhysLava(lvl.PosToInt(x, y, (ushort)(z - 1)), block);
lvl.PhysLava(lvl.PosToInt(x, (ushort)(y - 1), z), block);
lvl.PhysLava((ushort)(x + 1), y, z, block);
lvl.PhysLava((ushort)(x - 1), y, z, block);
lvl.PhysLava(x, y, (ushort)(z + 1), block);
lvl.PhysLava(x, y, (ushort)(z - 1), block);
lvl.PhysLava(x, (ushort)(y - 1), z, block);
} else { //was placed near sponge
lvl.AddUpdate(C.b, Block.air);
}
if (!checkWait || ((string)C.data).IndexOf("wait") == -1)
if (!checkWait || ((string)C.data).IndexOf("wait", comp) == -1)
C.time = 255;
}
@ -264,7 +265,7 @@ namespace MCGalaxy.BlockPhysics {
return true;
if (lvl.physics > 1 && lvl.blocks[b] >= Block.red && lvl.blocks[b] <= Block.white
&& !lvl.PhysSpongeCheck(b, true))
&& !lvl.CheckSpongeLava(x, y, z))
return false; // Adv physics destroys cloth
switch (lvl.blocks[b]) {
@ -273,7 +274,7 @@ namespace MCGalaxy.BlockPhysics {
case Block.water:
case Block.activedeathwater:
if (!lvl.PhysSpongeCheck(b, true)) return false;
if (!lvl.CheckSpongeLava(x, y, z)) return false;
break;
case Block.sand:
@ -288,7 +289,7 @@ namespace MCGalaxy.BlockPhysics {
case Block.redflower:
case Block.mushroom:
case Block.redmushroom:
if (lvl.physics > 1 && !lvl.PhysSpongeCheck(b, true)) return false;
if (lvl.physics > 1 && !lvl.CheckSpongeLava(x, y, z)) return false;
break;
}
return true;

View File

@ -38,7 +38,8 @@ namespace MCGalaxy.BlockPhysics {
int headIndex = lvl.PosToInt((ushort)(x - cx), (ushort)(y - cy), (ushort)(z - cz));
byte rocketHead = headIndex < 0 ? Block.Zero : lvl.blocks[headIndex];
bool unblocked = !lvl.ListUpdate.Exists(u => u.b == headIndex || u.b == C.b);
bool unblocked = !lvl.listUpdateExists.Get(x, y, z) &&
(headIndex < 0 || !lvl.listUpdateExists.Get(x - cx, y - cy, z - cz));
if (unblocked && (rocketHead == Block.air || rocketHead == Block.rocketstart)) {
lvl.AddUpdate(headIndex, Block.rockethead);

View File

@ -62,6 +62,10 @@
</ItemGroup>
<ItemGroup>
<Content Include="Galaxy.ico" />
<Content Include="ProfilingSessions\Session20160228_124429.sdps" />
<Content Include="ProfilingSessions\Session20160228_131348.sdps" />
<Content Include="ProfilingSessions\Session20160228_135632.sdps" />
<Content Include="ProfilingSessions\Session20160228_135946.sdps" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.