Fix not dying from falling when landing on corner of a neighbouring block. Fixes #461 (Thanks goodlyay)

This commit is contained in:
UnknownShadow200 2017-07-01 16:45:09 +10:00
parent 116680cd03
commit 55953c1118
8 changed files with 87 additions and 50 deletions

View File

@ -74,7 +74,7 @@ namespace MCGalaxy.Commands.Fun {
for (; y <= lvl.Height; y++) {
ExtBlock above = lvl.GetBlock(x, (ushort)(y + 1), z);
if (above.IsInvalid) continue;
if (Collide(lvl, above) != CollideType.Solid) continue;
if (lvl.CollideType(above) != CollideType.Solid) continue;
int posY = (y + 1) * 32 - 6;
BlockDefinition def = lvl.GetBlockDef(above);
@ -85,15 +85,6 @@ namespace MCGalaxy.Commands.Fun {
return -1;
}
internal static byte Collide(Level lvl, ExtBlock block) {
BlockDefinition def = lvl.GetBlockDef(block);
byte collide = def != null ? def.CollideType : CollideType.Solid;
if (def == null && !block.IsCustomType)
return DefaultSet.Collide(Block.Convert(block.BlockID));
return collide;
}
public override void Help(Player p) {
Player.Message(p, "%T/slap [name]");
Player.Message(p, "%HSlaps [name], knocking them into the air");

View File

@ -51,12 +51,12 @@ namespace MCGalaxy.Commands.Misc {
static int FindYAbove(Level lvl, ushort x, ushort y, ushort z) {
for (; y < lvl.Height; y++) {
ExtBlock block = lvl.GetBlock(x, y, z);
if (!block.IsInvalid && CmdSlap.Collide(lvl, block) == CollideType.Solid) continue;
if (!block.IsInvalid && lvl.CollideType(block) == CollideType.Solid) continue;
ExtBlock above = lvl.GetBlock(x, (ushort)(y + 1), z);
if (!above.IsInvalid && CmdSlap.Collide(lvl, above) == CollideType.Solid) continue;
if (!above.IsInvalid && lvl.CollideType(above) == CollideType.Solid) continue;
ExtBlock below = lvl.GetBlock(x, (ushort)(y - 1), z);
if (!below.IsInvalid && CmdSlap.Collide(lvl, below) == CollideType.Solid)
if (!below.IsInvalid && lvl.CollideType(below) == CollideType.Solid)
return y;
}
return -1;

View File

@ -54,12 +54,12 @@ namespace MCGalaxy.Commands.Misc {
static int FindYBelow(Level lvl, ushort x, ushort y, ushort z) {
for (; y > 0; y--) {
ExtBlock block = lvl.GetBlock(x, y, z);
if (!block.IsInvalid && CmdSlap.Collide(lvl, block) == CollideType.Solid) continue;
if (!block.IsInvalid && lvl.CollideType(block) == CollideType.Solid) continue;
ExtBlock above = lvl.GetBlock(x, (ushort)(y + 1), z);
if (!above.IsInvalid && CmdSlap.Collide(lvl, above) == CollideType.Solid) continue;
if (!above.IsInvalid && lvl.CollideType(above) == CollideType.Solid) continue;
ExtBlock below = lvl.GetBlock(x, (ushort)(y - 1), z);
if (!below.IsInvalid && CmdSlap.Collide(lvl, below) == CollideType.Solid)
if (!below.IsInvalid && lvl.CollideType(below) == CollideType.Solid)
return y;
}
return -1;

View File

@ -457,6 +457,15 @@ namespace MCGalaxy {
return block.BlockID != Block.custom_block ? Block.Name(block.BlockID).Capitalize() : block.ExtID.ToString();
}
public byte CollideType(ExtBlock block) {
BlockDefinition def = GetBlockDef(block);
byte collide = def != null ? def.CollideType : MCGalaxy.Blocks.CollideType.Solid;
if (def == null && !block.IsCustomType)
return DefaultSet.Collide(Block.Convert(block.BlockID));
return collide;
}
public bool LightPasses(ExtBlock block) {
BlockDefinition def = GetBlockDef(block);
if (def != null) return !def.BlocksLight || def.BlockDraw != DrawType.Opaque;

View File

@ -492,12 +492,7 @@ namespace MCGalaxy {
}
public void UpdateBlockHandler(ExtBlock block) {
bool nonSolid;
if (GetBlockDef(block) == null) {
nonSolid = Block.Walkthrough(Block.Convert(block.BlockID));
} else {
nonSolid = CustomBlockDefs[block.RawID].CollideType != CollideType.Solid;
}
bool nonSolid = CollideType(block) != MCGalaxy.Blocks.CollideType.Solid;
int i = block.Index;
deleteHandlers[i] = BlockBehaviour.GetDeleteHandler(block, BlockProps);

View File

@ -590,6 +590,7 @@
<Compile Include="Player\Player.Login.cs" />
<Compile Include="Player\PlayerActions.cs" />
<Compile Include="Player\PlayerInfo.cs" />
<Compile Include="Player\PlayerPhysics.cs" />
<Compile Include="Player\SpamChecker.cs" />
<Compile Include="Player\TabList.cs" />
<Compile Include="Database\Undo\UndoFormatCBin.cs" />

View File

@ -345,9 +345,10 @@ namespace MCGalaxy {
void CheckBlocks(Position pos) {
try {
Vec3U16 P = (Vec3U16)pos.BlockCoords;
if (level.Config.SurvivalDeath) CheckSurvival(P.X, P.Y, P.Z);
AABB bb = ModelBB.OffsetPosition(Pos);
if (level.Config.SurvivalDeath) CheckSurvival(P.X, P.Y, P.Z, bb);
CheckBlock();
CheckBlock(bb);
oldIndex = level.PosToInt(P.X, P.Y, P.Z);
} catch (Exception ex) {
Logger.LogError(ex);
@ -356,31 +357,9 @@ namespace MCGalaxy {
bool Moved() { return lastRot.RotY != Rot.RotY || lastRot.HeadX != Rot.HeadX; }
internal void CheckSurvival(ushort x, ushort y, ushort z) {
byte bFeet = GetSurvivalBlock(x, (ushort)(y - 2), z);
byte bBody = GetSurvivalBlock(x, (ushort)(y - 1), z);
void CheckSurvival(ushort x, ushort y, ushort z, AABB bb) {
byte bHead = GetSurvivalBlock(x, y, z);
if (level.PosToInt(x, y, z) != oldIndex || y != oldFallY) {
bFeet = Block.Convert(bFeet);
if (bFeet == Block.air) {
if (y < oldFallY)
fallCount++;
else if (y > oldFallY) // flying up, for example
fallCount = 0;
oldFallY = y;
drownCount = 0;
return;
} else if (!(bFeet == Block.water || bFeet == Block.waterstill ||
bFeet == Block.lava || bFeet == Block.lavastill)) {
if (fallCount > level.Config.FallHeight)
HandleDeath(ExtBlock.Air, null, false, true);
fallCount = 0;
drownCount = 0;
return;
}
}
if (level.PosToInt(x, y, z) != oldIndex) PlayerPhysics.Fall(this, bb);
switch (Block.Convert(bHead)) {
case Block.water:
@ -412,8 +391,7 @@ namespace MCGalaxy {
return level.GetTile(x, y, z);
}
internal void CheckBlock() {
AABB bb = ModelBB.OffsetPosition(Pos);
void CheckBlock(AABB bb) {
Vec3S32 min = bb.BlockMin, max = bb.BlockMax;
bool hitWalkthrough = false;

View File

@ -0,0 +1,63 @@
/*
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.Maths;
namespace MCGalaxy.Blocks.Physics {
internal static class PlayerPhysics {
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;
bool allGas = true;
for (int z = min.Z; z <= max.Z; z++)
for (int x = min.X; x <= max.X; x++)
{
ExtBlock block = GetSurvivalBlock(p, x, min.Y, z);
byte collideType = p.level.CollideType(block);
allGas = allGas && collideType == CollideType.WalkThrough;
if (collideType != CollideType.Solid) continue;
if (p.fallCount > p.level.Config.FallHeight)
p.HandleDeath(ExtBlock.Air, null, false, true);
p.fallCount = 0;
p.drownCount = 0;
return;
}
if (!allGas) return;
if (min.Y < p.oldFallY) p.fallCount++;
else if (min.Y > p.oldFallY) p.fallCount = 0; // e.g. flying up
p.oldFallY = min.Y;
p.drownCount = 0;
}
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;
return p.level.GetBlock((ushort)x, (ushort)y, (ushort)z);
}
}
}