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 {
|
||||
Vec3U16 P = (Vec3U16)pos.BlockCoords;
|
||||
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);
|
||||
|
||||
CheckBlock(bb);
|
||||
oldIndex = level.PosToInt(P.X, P.Y, P.Z);
|
||||
if (level.Config.SurvivalDeath) {
|
||||
if (index != oldIndex) PlayerPhysics.Fall(this, bb);
|
||||
PlayerPhysics.Drown(this, bb);
|
||||
}
|
||||
|
||||
PlayerPhysics.Walkthrough(this, bb);
|
||||
oldIndex = index;
|
||||
} catch (Exception ex) {
|
||||
Logger.LogError(ex);
|
||||
}
|
||||
@ -357,74 +362,6 @@ namespace MCGalaxy {
|
||||
|
||||
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")]
|
||||
public void HandleDeath(byte b, string customMessage = "", bool explode = false, bool immediate = false) {
|
||||
HandleDeath((ExtBlock)b, customMessage, explode, immediate);
|
||||
|
@ -22,12 +22,43 @@ namespace MCGalaxy.Blocks.Physics {
|
||||
|
||||
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) {
|
||||
bb.Min.Y -= 2; // test block below player feet
|
||||
Vec3S32 min = bb.BlockMin;
|
||||
if (min.Y == p.oldFallY) return;
|
||||
|
||||
Vec3S32 max = bb.BlockMax;
|
||||
Vec3S32 min = bb.BlockMin, max = bb.BlockMax;
|
||||
bool allGas = true;
|
||||
|
||||
for (int z = min.Z; z <= max.Z; z++)
|
||||
@ -54,6 +85,33 @@ namespace MCGalaxy.Blocks.Physics {
|
||||
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) {
|
||||
if (y < 0) return (ExtBlock)Block.blackrock;
|
||||
if (y >= p.level.Height) return ExtBlock.Air;
|
||||
|
Loading…
x
Reference in New Issue
Block a user