mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-22 12:05:51 -04:00
Better drowning physics - custom gas blocks count as 'air' now.
This commit is contained in:
parent
55953c1118
commit
73bb41b64b
@ -346,10 +346,15 @@ namespace MCGalaxy {
|
|||||||
try {
|
try {
|
||||||
Vec3U16 P = (Vec3U16)pos.BlockCoords;
|
Vec3U16 P = (Vec3U16)pos.BlockCoords;
|
||||||
AABB bb = ModelBB.OffsetPosition(Pos);
|
AABB bb = ModelBB.OffsetPosition(Pos);
|
||||||
if (level.Config.SurvivalDeath) CheckSurvival(P.X, P.Y, P.Z, bb);
|
int index = level.PosToInt(P.X, P.Y, P.Z);
|
||||||
|
|
||||||
|
if (level.Config.SurvivalDeath) {
|
||||||
|
if (index != oldIndex) PlayerPhysics.Fall(this, bb);
|
||||||
|
PlayerPhysics.Drown(this, bb);
|
||||||
|
}
|
||||||
|
|
||||||
CheckBlock(bb);
|
PlayerPhysics.Walkthrough(this, bb);
|
||||||
oldIndex = level.PosToInt(P.X, P.Y, P.Z);
|
oldIndex = index;
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Logger.LogError(ex);
|
Logger.LogError(ex);
|
||||||
}
|
}
|
||||||
@ -357,74 +362,6 @@ namespace MCGalaxy {
|
|||||||
|
|
||||||
bool Moved() { return lastRot.RotY != Rot.RotY || lastRot.HeadX != Rot.HeadX; }
|
bool Moved() { return lastRot.RotY != Rot.RotY || lastRot.HeadX != Rot.HeadX; }
|
||||||
|
|
||||||
void CheckSurvival(ushort x, ushort y, ushort z, AABB bb) {
|
|
||||||
byte bHead = GetSurvivalBlock(x, y, z);
|
|
||||||
if (level.PosToInt(x, y, z) != oldIndex) PlayerPhysics.Fall(this, bb);
|
|
||||||
|
|
||||||
switch (Block.Convert(bHead)) {
|
|
||||||
case Block.water:
|
|
||||||
case Block.waterstill:
|
|
||||||
case Block.lava:
|
|
||||||
case Block.lavastill:
|
|
||||||
fallCount = 0;
|
|
||||||
drownCount++;
|
|
||||||
|
|
||||||
// level drown is in 10ths of a second, and there are 100 ticks/second
|
|
||||||
if (drownCount > level.Config.DrownTime * 10) {
|
|
||||||
HandleDeath((ExtBlock)Block.water);
|
|
||||||
drownCount = 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Block.air:
|
|
||||||
drownCount = 0;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
fallCount = 0;
|
|
||||||
drownCount = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
byte GetSurvivalBlock(ushort x, ushort y, ushort z) {
|
|
||||||
if (y >= ushort.MaxValue - 512) return Block.blackrock;
|
|
||||||
if (y >= level.Height) return Block.air;
|
|
||||||
return level.GetTile(x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckBlock(AABB bb) {
|
|
||||||
Vec3S32 min = bb.BlockMin, max = bb.BlockMax;
|
|
||||||
bool hitWalkthrough = false;
|
|
||||||
|
|
||||||
for (int y = min.Y; y <= max.Y; y++)
|
|
||||||
for (int z = min.Z; z <= max.Z; z++)
|
|
||||||
for (int x = min.X; x <= max.X; x++)
|
|
||||||
{
|
|
||||||
ushort xP = (ushort)x, yP = (ushort)y, zP = (ushort)z;
|
|
||||||
ExtBlock block = level.GetBlock(xP, yP, zP);
|
|
||||||
if (block.BlockID == Block.Invalid) continue;
|
|
||||||
|
|
||||||
AABB blockBB = level.blockAABBs[block.Index].Offset(x * 32, y * 32, z * 32);
|
|
||||||
if (!bb.Intersects(blockBB)) continue;
|
|
||||||
|
|
||||||
// We can activate only one walkthrough block per movement
|
|
||||||
if (!hitWalkthrough) {
|
|
||||||
HandleWalkthrough handler = level.walkthroughHandlers[block.Index];
|
|
||||||
if (handler != null && handler(this, block, xP, yP, zP)) {
|
|
||||||
lastWalkthrough = level.PosToInt(xP, yP, zP);
|
|
||||||
hitWalkthrough = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Some blocks will cause death of players
|
|
||||||
if (!level.BlockProps[block.Index].KillerBlock) continue;
|
|
||||||
if (block.BlockID == Block.tntexplosion && PlayingTntWars) continue; // TODO: hardcoded behaviour is icky
|
|
||||||
if (block.BlockID == Block.train && trainInvincible) continue;
|
|
||||||
HandleDeath(block);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hitWalkthrough) lastWalkthrough = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Obsolete("Use HandleDeath with ExtBlock attribute")]
|
[Obsolete("Use HandleDeath with ExtBlock attribute")]
|
||||||
public void HandleDeath(byte b, string customMessage = "", bool explode = false, bool immediate = false) {
|
public void HandleDeath(byte b, string customMessage = "", bool explode = false, bool immediate = false) {
|
||||||
HandleDeath((ExtBlock)b, customMessage, explode, immediate);
|
HandleDeath((ExtBlock)b, customMessage, explode, immediate);
|
||||||
|
@ -21,13 +21,44 @@ using MCGalaxy.Maths;
|
|||||||
namespace MCGalaxy.Blocks.Physics {
|
namespace MCGalaxy.Blocks.Physics {
|
||||||
|
|
||||||
internal static class PlayerPhysics {
|
internal static class PlayerPhysics {
|
||||||
|
|
||||||
|
internal static void Walkthrough(Player p, AABB bb) {
|
||||||
|
Vec3S32 min = bb.BlockMin, max = bb.BlockMax;
|
||||||
|
bool hitWalkthrough = false;
|
||||||
|
|
||||||
|
for (int y = min.Y; y <= max.Y; y++)
|
||||||
|
for (int z = min.Z; z <= max.Z; z++)
|
||||||
|
for (int x = min.X; x <= max.X; x++)
|
||||||
|
{
|
||||||
|
ushort xP = (ushort)x, yP = (ushort)y, zP = (ushort)z;
|
||||||
|
ExtBlock block = p.level.GetBlock(xP, yP, zP);
|
||||||
|
if (block.BlockID == Block.Invalid) continue;
|
||||||
|
|
||||||
|
AABB blockBB = p.level.blockAABBs[block.Index].Offset(x * 32, y * 32, z * 32);
|
||||||
|
if (!bb.Intersects(blockBB)) continue;
|
||||||
|
|
||||||
|
// We can activate only one walkthrough block per movement
|
||||||
|
if (!hitWalkthrough) {
|
||||||
|
HandleWalkthrough handler = p.level.walkthroughHandlers[block.Index];
|
||||||
|
if (handler != null && handler(p, block, xP, yP, zP)) {
|
||||||
|
p.lastWalkthrough = p.level.PosToInt(xP, yP, zP);
|
||||||
|
hitWalkthrough = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some blocks will cause death of players
|
||||||
|
if (!p.level.BlockProps[block.Index].KillerBlock) continue;
|
||||||
|
if (block.BlockID == Block.tntexplosion && p.PlayingTntWars) continue; // TODO: hardcoded behaviour is icky
|
||||||
|
if (block.BlockID == Block.train && p.trainInvincible) continue;
|
||||||
|
p.HandleDeath(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hitWalkthrough) p.lastWalkthrough = -1;
|
||||||
|
}
|
||||||
|
|
||||||
internal static void Fall(Player p, AABB bb) {
|
internal static void Fall(Player p, AABB bb) {
|
||||||
bb.Min.Y -= 2; // test block below player feet
|
bb.Min.Y -= 2; // test block below player feet
|
||||||
Vec3S32 min = bb.BlockMin;
|
Vec3S32 min = bb.BlockMin, max = bb.BlockMax;
|
||||||
if (min.Y == p.oldFallY) return;
|
|
||||||
|
|
||||||
Vec3S32 max = bb.BlockMax;
|
|
||||||
bool allGas = true;
|
bool allGas = true;
|
||||||
|
|
||||||
for (int z = min.Z; z <= max.Z; z++)
|
for (int z = min.Z; z <= max.Z; z++)
|
||||||
@ -54,6 +85,33 @@ namespace MCGalaxy.Blocks.Physics {
|
|||||||
p.drownCount = 0;
|
p.drownCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static void Drown(Player p, AABB bb) {
|
||||||
|
Vec3S32 P = bb.Max;
|
||||||
|
ExtBlock bHead = GetSurvivalBlock(p, (ushort)P.X, (ushort)P.Y, (ushort)P.Z);
|
||||||
|
if (bHead.IsPhysicsType) bHead.BlockID = Block.Convert(bHead.BlockID);
|
||||||
|
|
||||||
|
switch (bHead.BlockID) {
|
||||||
|
case Block.water:
|
||||||
|
case Block.waterstill:
|
||||||
|
case Block.lava:
|
||||||
|
case Block.lavastill:
|
||||||
|
p.fallCount = 0;
|
||||||
|
p.drownCount++;
|
||||||
|
|
||||||
|
// level drown is in 10ths of a second, and there are 100 ticks/second
|
||||||
|
if (p.drownCount > p.level.Config.DrownTime * 10) {
|
||||||
|
p.HandleDeath((ExtBlock)Block.water);
|
||||||
|
p.drownCount = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
bool isGas = p.level.CollideType(bHead) == CollideType.WalkThrough;
|
||||||
|
if (!isGas) p.fallCount = 0;
|
||||||
|
p.drownCount = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static ExtBlock GetSurvivalBlock(Player p, int x, int y, int z) {
|
static ExtBlock GetSurvivalBlock(Player p, int x, int y, int z) {
|
||||||
if (y < 0) return (ExtBlock)Block.blackrock;
|
if (y < 0) return (ExtBlock)Block.blackrock;
|
||||||
if (y >= p.level.Height) return ExtBlock.Air;
|
if (y >= p.level.Height) return ExtBlock.Air;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user