예제 #1
0
        private void DamageNearbyBlocks(IPlayer player, BlockSelection blockSel, float damage, int leftDurability)
        {
            Block block = player.Entity.World.BlockAccessor.GetBlock(blockSel.Position);

            if (!CanMultiBreak(block))
            {
                return;
            }

            Vec3d hitPos           = blockSel.Position.ToVec3d().Add(blockSel.HitPosition);
            var   orderedPositions = GetNearblyMultibreakables(player.Entity.World, blockSel.Position, hitPos).OrderBy(x => x.Value);

            int q = Math.Min(MultiBreakQuantity, leftDurability);

            foreach (var val in orderedPositions)
            {
                if (q == 0)
                {
                    break;
                }
                BlockFacing facing = BlockFacing.FromVector(player.Entity.ServerPos.GetViewVector()).GetOpposite();

                if (!player.Entity.World.CanPlayerAccessBlock(player, blockSel.Position, EnumBlockAccessFlags.BuildOrBreak))
                {
                    continue;
                }

                player.Entity.World.BlockAccessor.DamageBlock(val.Key, facing, damage);
                q--;
            }
        }
예제 #2
0
파일: Mat4f.cs 프로젝트: Archina/vsapi
        public static BlockFacing MulWithVec3_BlockFacing(float[] matrix, Vec3f vec)
        {
            float x = matrix[0] * vec.X + matrix[4] * vec.Y + matrix[8] * vec.Z;
            float y = matrix[1] * vec.X + matrix[5] * vec.Y + matrix[9] * vec.Z;
            float z = matrix[2] * vec.X + matrix[6] * vec.Y + matrix[10] * vec.Z;

            return(BlockFacing.FromVector(x, y, z));
        }
예제 #3
0
        private Block GetOrientedBlock(IWorldAccessor world, BlockSelection blockSel)
        {
            BlockFacing onBlockFace = blockSel.Face;
            Vec3d       hitPosition = blockSel.HitPosition;

            //hitPosition projected on the onBlockFace to determine block orientation
            Vec3d normal = onBlockFace.Normalf.NormalizedCopy().ToVec3d();

            normal.Mul((float)hitPosition.SubCopy(0.5, 0.5, 0.5).Dot(normal));
            Vec3d projVector = hitPosition.SubCopy(normal).Sub(0.5, 0.5, 0.5);

            BlockFacing orientation  = BlockFacing.FromVector(projVector.X, projVector.Y, projVector.Z);
            BlockFacing oppositeFace = onBlockFace.GetOpposite();

            return(world.BlockAccessor.GetBlock(block.CodeWithParts(orientation.Code, oppositeFace.Code)));
        }
예제 #4
0
        //API
        public virtual bool TryOutputConnection(IElectricity connectto)
        {
            if (outputConnections == null)
            {
                outputConnections = new List <IElectricity>();
            }
            Vec3d       vector = connectto.EBlock.Pos.ToVec3d() - Pos.ToVec3d();
            BlockFacing bf     = BlockFacing.FromVector(vector.X, vector.Y, vector.Z);

            if (distributionFaces == null)
            {
                return(false);
            }
            if (!distributionFaces.Contains(bf))
            {
                return(false);
            }
            if (!outputConnections.Contains(connectto))
            {
                outputConnections.Add(connectto); MarkDirty();
            }
            return(true);
        }
예제 #5
0
        //Allow devices to connection to each other
        //TODO add way to connect valid faces, especially if placed in different directions
        public virtual bool TryInputConnection(BEElectric connectto)
        {
            if (inputConnections == null)
            {
                inputConnections = new List <BEElectric>();
            }
            Vec3d       vector = connectto.Pos.ToVec3d() - Pos.ToVec3d();
            BlockFacing bf     = BlockFacing.FromVector(vector.X, vector.Y, vector.Z);

            if (receptionFaces == null)
            {
                return(false);
            }
            if (!receptionFaces.Contains(bf))
            {
                return(false);
            }
            if (!inputConnections.Contains(connectto))
            {
                inputConnections.Add(connectto); MarkDirty();
            }
            return(true);
        }
예제 #6
0
        public void DisplaceWithBlockCollision(EntityPos pos, EntityControls controls, float dt)
        {
            IBlockAccessor    blockAccess = entity.World.BlockAccessor;
            FrameProfilerUtil profiler    = entity.World.FrameProfiler;
            float             dtFac       = 60 * dt;
            double            prevYMotion = pos.Motion.Y;

            moveDelta.Set(pos.Motion.X * dtFac, prevYMotion * dtFac, pos.Motion.Z * dtFac);

            nextPosition.Set(pos.X + moveDelta.X, pos.Y + moveDelta.Y, pos.Z + moveDelta.Z);
            bool falling            = prevYMotion < 0;
            bool feetInLiquidBefore = entity.FeetInLiquid;
            bool onGroundBefore     = entity.OnGround;
            bool swimmingBefore     = entity.Swimming;

            controls.IsClimbing     = false;
            entity.ClimbingOnFace   = null;
            entity.ClimbingIntoFace = null;


            if (/*!onGroundBefore &&*/ entity.Properties.CanClimb == true)
            {
                int height = (int)Math.Ceiling(entity.CollisionBox.Y2);

                entityBox.SetAndTranslate(entity.CollisionBox, pos.X, pos.Y, pos.Z);

                for (int dy = 0; dy < height; dy++)
                {
                    tmpPos.Set((int)pos.X, (int)pos.Y + dy, (int)pos.Z);
                    Block nblock = blockAccess.GetBlock(tmpPos);
                    if (!nblock.Climbable && !entity.Properties.CanClimbAnywhere)
                    {
                        continue;
                    }

                    Cuboidf[] collBoxes = nblock.GetCollisionBoxes(blockAccess, tmpPos);
                    if (collBoxes == null)
                    {
                        continue;
                    }

                    for (int i = 0; i < collBoxes.Length; i++)
                    {
                        double dist = entityBox.ShortestDistanceFrom(collBoxes[i], tmpPos);
                        controls.IsClimbing |= dist < entity.Properties.ClimbTouchDistance;

                        if (controls.IsClimbing)
                        {
                            entity.ClimbingOnFace = null;
                            break;
                        }
                    }
                }

                if (controls.WalkVector.LengthSq() > 0.00001 && entity.Properties.CanClimbAnywhere && entity.Alive)
                {
                    var walkIntoFace = BlockFacing.FromVector(controls.WalkVector.X, controls.WalkVector.Y, controls.WalkVector.Z);
                    if (walkIntoFace != null)
                    {
                        tmpPos.Set((int)pos.X + walkIntoFace.Normali.X, (int)pos.Y + walkIntoFace.Normali.Y, (int)pos.Z + walkIntoFace.Normali.Z);
                        Block nblock = blockAccess.GetBlock(tmpPos);

                        Cuboidf[] icollBoxes = nblock.GetCollisionBoxes(blockAccess, tmpPos);
                        entity.ClimbingIntoFace = (icollBoxes != null && icollBoxes.Length != 0) ? walkIntoFace : null;
                    }
                }

                for (int i = 0; !controls.IsClimbing && i < BlockFacing.HORIZONTALS.Length; i++)
                {
                    BlockFacing facing = BlockFacing.HORIZONTALS[i];
                    for (int dy = 0; dy < height; dy++)
                    {
                        tmpPos.Set((int)pos.X + facing.Normali.X, (int)pos.Y + dy, (int)pos.Z + facing.Normali.Z);
                        Block nblock = blockAccess.GetBlock(tmpPos);
                        if (!nblock.Climbable && !(entity.Properties.CanClimbAnywhere && entity.Alive))
                        {
                            continue;
                        }

                        Cuboidf[] collBoxes = nblock.GetCollisionBoxes(blockAccess, tmpPos);
                        if (collBoxes == null)
                        {
                            continue;
                        }

                        for (int j = 0; j < collBoxes.Length; j++)
                        {
                            double dist = entityBox.ShortestDistanceFrom(collBoxes[j], tmpPos);
                            controls.IsClimbing |= dist < entity.Properties.ClimbTouchDistance;

                            if (controls.IsClimbing)
                            {
                                entity.ClimbingOnFace    = facing;
                                entity.ClimbingOnCollBox = collBoxes[j];
                                break;
                            }
                        }
                    }
                }
            }


            if (controls.IsClimbing)
            {
                if (controls.WalkVector.Y == 0)
                {
                    pos.Motion.Y = controls.Sneak ? Math.Max(-0.07, pos.Motion.Y - 0.07) : pos.Motion.Y;
                    if (controls.Jump)
                    {
                        pos.Motion.Y = 0.035 * dt * 60f;
                    }
                }


                // what was this for? it causes jitter
                // moveDelta.Y = pos.Motion.Y * dt * 60f;
                // nextPosition.Set(pos.X + moveDelta.X, pos.Y + moveDelta.Y, pos.Z + moveDelta.Z);
            }

            profiler.Mark("prep");

            collisionTester.ApplyTerrainCollision(entity, pos, dtFac, ref outposition, stepHeight);

            profiler.Mark("terraincollision");

            if (!entity.Properties.CanClimbAnywhere)
            {
                if (smoothStepping)
                {
                    controls.IsStepping = HandleSteppingOnBlocksSmooth(pos, moveDelta, dtFac, controls);
                }
                else
                {
                    controls.IsStepping = HandleSteppingOnBlocks(pos, moveDelta, dtFac, controls);
                }
            }

            profiler.Mark("stepping-checks");

            HandleSneaking(pos, controls, dt);

            if (entity.CollidedHorizontally && !controls.IsClimbing && !controls.IsStepping && entity.Properties.Habitat != EnumHabitat.Underwater)
            {
                if (blockAccess.GetBlock((int)pos.X, (int)(pos.Y + 0.5), (int)pos.Z).LiquidLevel >= 7 || blockAccess.GetBlock((int)pos.X, (int)(pos.Y), (int)pos.Z).LiquidLevel >= 7 || (blockAccess.GetBlock((int)pos.X, (int)(pos.Y - 0.05), (int)pos.Z).LiquidLevel >= 7))
                {
                    pos.Motion.Y       += 0.2 * dt;
                    controls.IsStepping = true;
                }
                else   // attempt to prevent endless collisions
                {
                    double absX = Math.Abs(pos.Motion.X);
                    double absZ = Math.Abs(pos.Motion.Z);
                    if (absX > absZ)
                    {
                        if (absZ < 0.001)
                        {
                            pos.Motion.Z += pos.Motion.Z < 0 ? -0.0025 : 0.0025;
                        }
                    }
                    else
                    {
                        if (absX < 0.001)
                        {
                            pos.Motion.X += pos.Motion.X < 0 ? -0.0025 : 0.0025;
                        }
                    }
                }
            }


            if (outposition.X != pos.X && blockAccess.IsNotTraversable((pos.X + pos.Motion.X * dt * 60f), pos.Y, pos.Z))
            {
                outposition.X = pos.X;
            }
            if (outposition.Y != pos.Y && blockAccess.IsNotTraversable(pos.X, (pos.Y + pos.Motion.Y * dt * 60f), pos.Z))
            {
                outposition.Y = pos.Y;
            }
            if (outposition.Z != pos.Z && blockAccess.IsNotTraversable(pos.X, pos.Y, (pos.Z + pos.Motion.Z * dt * 60f)))
            {
                outposition.Z = pos.Z;
            }

            pos.SetPos(outposition);

            profiler.Mark("apply-motion");

            // Set the motion to zero if he collided.

            if ((nextPosition.X < outposition.X && pos.Motion.X < 0) || (nextPosition.X > outposition.X && pos.Motion.X > 0))
            {
                pos.Motion.X = 0;
            }

            if ((nextPosition.Y < outposition.Y && pos.Motion.Y < 0) || (nextPosition.Y > outposition.Y && pos.Motion.Y > 0))
            {
                pos.Motion.Y = 0;
            }

            if ((nextPosition.Z < outposition.Z && pos.Motion.Z < 0) || (nextPosition.Z > outposition.Z && pos.Motion.Z > 0))
            {
                pos.Motion.Z = 0;
            }

            float offX = entity.CollisionBox.X2 - entity.OriginCollisionBox.X2;
            float offZ = entity.CollisionBox.Z2 - entity.OriginCollisionBox.Z2;

            int posX = (int)(pos.X + offX);
            int posZ = (int)(pos.Z + offZ);

            Block block          = blockAccess.GetBlock(posX, (int)(pos.Y), posZ);
            Block waterOrIce     = blockAccess.GetLiquidBlock(posX, (int)(pos.Y), posZ);
            Block middleWOIBlock = blockAccess.GetLiquidBlock(posX, (int)(pos.Y + entity.SwimmingOffsetY), posZ);

            entity.OnGround     = (entity.CollidedVertically && falling && !controls.IsClimbing) || controls.IsStepping;
            entity.FeetInLiquid = false;
            if (waterOrIce.IsLiquid())
            {
                Block aboveblock = blockAccess.GetLiquidBlock(posX, (int)(pos.Y + 1), posZ);
                entity.FeetInLiquid = ((waterOrIce.LiquidLevel + (aboveblock.LiquidLevel > 0 ? 1 : 0)) / 8f >= pos.Y - (int)pos.Y);
            }
            entity.InLava   = block.LiquidCode == "lava";
            entity.Swimming = middleWOIBlock.IsLiquid();

            if (!onGroundBefore && entity.OnGround)
            {
                entity.OnFallToGround(prevYMotion);
            }

            if ((!entity.Swimming && !feetInLiquidBefore && entity.FeetInLiquid) || (!entity.FeetInLiquid && !swimmingBefore && entity.Swimming))
            {
                entity.OnCollideWithLiquid();
            }

            if ((swimmingBefore && !entity.Swimming && !entity.FeetInLiquid) || (feetInLiquidBefore && !entity.FeetInLiquid && !entity.Swimming))
            {
                entity.OnExitedLiquid();
            }

            if (!falling || entity.OnGround || controls.IsClimbing)
            {
                entity.PositionBeforeFalling.Set(outposition);
            }

            profiler.Mark("apply-collisionandflags");

            Cuboidd testedEntityBox = collisionTester.entityBox;

            int xMax = (int)testedEntityBox.X2;
            int yMax = (int)testedEntityBox.Y2;
            int zMax = (int)testedEntityBox.Z2;
            int zMin = (int)testedEntityBox.Z1;

            for (int y = (int)testedEntityBox.Y1; y <= yMax; y++)
            {
                for (int x = (int)testedEntityBox.X1; x <= xMax; x++)
                {
                    for (int z = zMin; z <= zMax; z++)
                    {
                        collisionTester.tmpPos.Set(x, y, z);
                        collisionTester.tempCuboid.Set(x, y, z, x + 1, y + 1, z + 1);

                        if (collisionTester.tempCuboid.IntersectsOrTouches(testedEntityBox))
                        {
                            // Saves us a few cpu cycles
                            if (x == (int)pos.X && z == (int)pos.Z && y == (int)pos.Y)
                            {
                                block.OnEntityInside(entity.World, entity, collisionTester.tmpPos);
                                continue;
                            }

                            blockAccess.GetBlock(x, y, z).OnEntityInside(entity.World, entity, collisionTester.tmpPos);
                        }
                    }
                }
            }
            profiler.Mark("trigger-insideblock");
        }