public override void OnGameTick(float deltaTime)
        {
            if (entity.State == EnumEntityState.Inactive)
            {
                return;
            }

            Vec3d pos = entity.LocalPos.XYZ;

            pushVector.Set(0, 0, 0);
            Vec3d p = new Vec3d();

            entity.World.GetEntitiesAround(pos, 10, 5, (e) => {
                EntityPos epos    = e.LocalPos;
                double distanceSq = epos.SquareDistanceTo(pos);

                if (e != entity && distanceSq < touchDistance * touchDistance && e.HasBehavior("repulseagents") && e.IsInteractable)
                {
                    p.Set(pos.X - epos.X, pos.Y - epos.Y, pos.Z - epos.Z);
                    p.Normalize().Mul(1 - GameMath.Sqrt(distanceSq) / touchDistance);
                    pushVector.Add(p.X, p.Y, p.Z);
                }

                return(false);
            });


            pushVector.X = GameMath.Clamp(pushVector.X, -3, 3);
            pushVector.Y = GameMath.Clamp(pushVector.Y, -3, 3);
            pushVector.Z = GameMath.Clamp(pushVector.Z, -3, 3);
            entity.LocalPos.Motion.Add(pushVector.X / 15, pushVector.Y / 30, pushVector.Z / 15);

            entity.World.FrameProfiler.Mark("entity-repulse");
        }
Beispiel #2
0
        public override void OnEntitySpawn()
        {
            base.OnEntitySpawn();
            id = entity.World.RegisterGameTickListener(dt =>
            {
                runAwayFrom = null;
                try
                {
                    runAwayFrom = poiRegistry.GetNearestPoi(entity.ServerPos.XYZ, 100, (poi) =>
                    {
                        if (poi == null)
                        {
                            return(false);
                        }
                        float?fear = (poi as IPointOfFear)?.FearRadius;
                        if (fear == null)
                        {
                            return(false);
                        }
                        return(poi.Position.DistanceTo(entity.Pos.XYZ) < fear && poi.Type == "scary");
                    }) as IPointOfFear;
                    if (runAwayFrom == null)
                    {
                        return;
                    }

                    goTo = goTo ?? runAwayFrom.Position.AheadCopy(runAwayFrom.FearRadius + 5, 0, rand.NextDouble() * 360);
                    while (goTo.AsBlockPos.GetBlock(entity.Api).Id != 0 && goTo.AsBlockPos.Y < world.BlockAccessor.MapSizeY)
                    {
                        goTo.Add(0, 1, 0);
                    }
                }
                catch (Exception) { }
            }, 4000 + rand.Next(0, 1000));
        }
Beispiel #3
0
        private bool WalkEntity(Entity e)
        {
            if (!e.hasRepulseBehavior || !e.IsInteractable || e == entity)
            {
                return(true);
            }

            double dx = ownPosRepulseX - e.ownPosRepulse.X;
            double dy = ownPosRepulseY - e.ownPosRepulse.Y;
            double dz = ownPosRepulseZ - e.ownPosRepulse.Z;

            double distSq    = dx * dx + dy * dy + dz * dz;
            double minDistSq = entity.touchDistanceSq + e.touchDistanceSq;

            if (distSq >= minDistSq)
            {
                return(true);
            }

            double pushForce = (1 - distSq / minDistSq) / Math.Max(0.001f, GameMath.Sqrt(distSq));
            double px        = dx * pushForce;
            double py        = dy * pushForce;
            double pz        = dz * pushForce;

            float hisSize  = e.SelectionBox.Length * e.SelectionBox.Height;
            float pushDiff = GameMath.Clamp(hisSize / mySize, 0, 1);

            pushVector.Add(px * pushDiff, py * pushDiff, pz * pushDiff);

            return(true);
        }
        public Vec3d RandomParticlePos(BlockFacing facing = null)
        {
            Random         rand        = Api.World.Rand;
            IBlockAccessor blockAccess = Api.World.BlockAccessor;
            Cuboidf        box         = Block.GetParticleBreakBox(blockAccess, Pos, facing);

            if (facing == null)
            {
                return(new Vec3d(
                           Pos.X + box.X1 + 1 / 32f + rand.NextDouble() * (box.XSize - 1 / 16f),
                           Pos.Y + box.Y1 + 1 / 32f + rand.NextDouble() * (box.YSize - 1 / 16f),
                           Pos.Z + box.Z1 + 1 / 32f + rand.NextDouble() * (box.ZSize - 1 / 16f)
                           ));
            }
            else
            {
                bool  haveBox = box != null;
                Vec3i facev   = facing.Normali;

                Vec3d outpos = new Vec3d(
                    Pos.X + 0.5f + facev.X / 1.9f + (haveBox && facing.Axis == EnumAxis.X ? (facev.X > 0 ? box.X2 - 1 : box.X1) : 0),
                    Pos.Y + 0.5f + facev.Y / 1.9f + (haveBox && facing.Axis == EnumAxis.Y ? (facev.Y > 0 ? box.Y2 - 1 : box.Y1) : 0),
                    Pos.Z + 0.5f + facev.Z / 1.9f + (haveBox && facing.Axis == EnumAxis.Z ? (facev.Z > 0 ? box.Z2 - 1 : box.Z1) : 0)
                    );

                outpos.Add(
                    (rand.NextDouble() - 0.5) * (1 - Math.Abs(facev.X)),
                    (rand.NextDouble() - 0.5) * (1 - Math.Abs(facev.Y)) - (facing == BlockFacing.DOWN ? 0.1f : 0f),
                    (rand.NextDouble() - 0.5) * (1 - Math.Abs(facev.Z))
                    );

                return(outpos);
            }
        }
Beispiel #5
0
        private void WalkEntity(Entity e)
        {
            double    hisTouchDistance = (e.CollisionBox.X2 - e.CollisionBox.X1) / 2;
            EntityPos epos             = e.LocalPos;

            hisPos.Set(
                epos.X + (e.CollisionBox.X2 - e.OriginCollisionBox.X2),
                epos.Y + (e.CollisionBox.Y2 - e.OriginCollisionBox.Y2),
                epos.Z + (e.CollisionBox.Z2 - e.OriginCollisionBox.Z2)
                );

            double centerToCenterDistance = GameMath.Sqrt(hisPos.SquareDistanceTo(ownPos));

            if (e != entity && centerToCenterDistance < ownTouchDistance + hisTouchDistance && e.HasBehavior("repulseagents") && e.IsInteractable)
            {
                tmppos.Set(ownPos.X - hisPos.X, ownPos.Y - hisPos.Y, ownPos.Z - hisPos.Z);
                tmppos.Normalize().Mul(1 - centerToCenterDistance / (ownTouchDistance + hisTouchDistance));

                float hisSize  = e.CollisionBox.Length * e.CollisionBox.Height;
                float mySize   = entity.CollisionBox.Length * entity.CollisionBox.Height;
                float pushDiff = GameMath.Clamp(hisSize / mySize, 0, 1);

                pushVector.Add(tmppos.X * pushDiff, tmppos.Y * pushDiff, tmppos.Z * pushDiff);
            }
        }
Beispiel #6
0
 public override bool ContinueExecute(float dt)
 {
     goTo = goTo ?? runAwayFrom.Position.AheadCopy(runAwayFrom.FearRadius + 5, 0, rand.NextDouble() * 360);
     while (goTo.AsBlockPos.GetBlock(entity.Api).Id != 0 && goTo.AsBlockPos.Y < world.BlockAccessor.MapSizeY)
     {
         goTo.Add(0, 1, 0);
     }
     pathTraverser.NavigateTo(goTo, moveSpeed, OnGoalReached, OnStuck);
     return(ShouldExecute());
 }
Beispiel #7
0
 private void OnGoalReached()
 {
     fleeState = !fleeState;
     if (fleeState)
     {
         pathTraverser.WalkTowards(targetPos.Add(0, 1, 0), moveSpeed, 1f, OnGoalReached, OnStuck);
     }
     else
     {
         pathTraverser.WalkTowards(targetPos, moveSpeed, 1f, OnGoalReached, OnStuck);
     }
 }
Beispiel #8
0
        public override void OnFinalizeFrame(float dt)
        {
            base.OnFinalizeFrame(dt);

            entityPos.Set(owningEntity.Pos.X, owningEntity.Pos.Y, owningEntity.Pos.Z);
            entityPos.Add(owningEntity.SelectionBox.X2 - owningEntity.OriginSelectionBox.X2, 0, owningEntity.SelectionBox.Z2 - owningEntity.OriginSelectionBox.Z2);

            if (!IsInRangeOfBlock())
            {
                // Because we cant do it in here
                capi.Event.EnqueueMainThreadTask(() => TryClose(), "closedlg");
            }
        }
        public override void OnFinalizeFrame(float dt)
        {
            base.OnFinalizeFrame(dt);

            entityPos.Set(owningEntity.Pos.X, owningEntity.Pos.Y, owningEntity.Pos.Z);
            entityPos.Add(owningEntity.CollisionBox.X2 - owningEntity.OriginCollisionBox.X2, 0, owningEntity.CollisionBox.Z2 - owningEntity.OriginCollisionBox.Z2);

            if (!IsInRangeOfBlock())
            {
                // Because we cant do it in here
                capi.Event.RegisterCallback((deltatime) => TryClose(), 0);
            }
        }
Beispiel #10
0
        public override void OnBlockPlaced(IWorldAccessor world, BlockPos blockPos, ref EnumHandling handled)
        {
            testBlockPos.Clear();
            lworld = world;
            if (world.Side != EnumAppSide.Server)
            {
                return;
            }
            BlockPos pos = blockPos;

            targetPos = world.GetNearestEntity(pos.ToVec3d(), 64, 64).Pos.AsBlockPos;
            Vec3d    posv = pos.ToVec3d();
            Vec3d    tgtv = targetPos.ToVec3d();
            BlockPos mP   = ((posv.Add(tgtv)) / 2).AsBlockPos;
            int      sR   = (int)mP.DistanceTo(pos) + 4;
            var      grid = new CubeGrid(sR * 2, sR * 2, sR * 2);

            if (!grid.isInBounds(world, targetPos) || !grid.isPassable(world, targetPos) || !grid.isWalkable(world, targetPos))
            {
                return;
            }
            for (int x = mP.X - sR; x <= mP.X + sR; x++)
            {
                for (int y = mP.Y - sR; y <= mP.Y + sR; y++)
                {
                    for (int z = mP.Z - sR; z <= mP.Z + sR; z++)
                    {
                        BlockPos currentPos = new BlockPos(x, y, z);
                        if (grid.isInBounds(world, currentPos) && grid.isPassable(world, currentPos) && grid.isWalkable(world, currentPos))
                        {
                            grid.air.Add(currentPos);
                        }
                        else
                        {
                            grid.walls.Add(currentPos);
                        }
                    }
                }
            }
            var astar = new AStarSearch(world, grid, pos, targetPos);

            DrawGrid(world, astar, mP, sR);
            world.BlockAccessor.SetBlock(2278, pos);
            //world.BlockAccessor.SetBlock(2279, mP);
            world.BlockAccessor.SetBlock(2278, targetPos);
            testBlockPos.Add(targetPos);
            testBlockPos.Add(pos);
            //testBlockPos.Add(mP);
            return;
        }
Beispiel #11
0
        private void onTick25msClient(float dt)
        {
            double squeezeRel = mashStack?.Attributes.GetDouble("squeezeRel", 1) ?? 1;

            if (MashSlot.Empty || renderer.juiceTexPos == null || squeezeRel >= 1)
            {
                return;
            }

            int[] cols = renderer.juiceTexPos.RndColors;
            var   rand = Api.World.Rand;

            liquidParticles.MinQuantity = (float)juiceableLitresLeft / 10f;

            for (int i = 0; i < 4; i++)
            {
                BlockFacing face = BlockFacing.HORIZONTALS[i];

                liquidParticles.Color = cols[rand.Next(cols.Length)];

                Vec3d minPos = face.Plane.Startd.Add(-0.5, 0, -0.5);
                Vec3d maxPos = face.Plane.Endd.Add(-0.5, 0, -0.5);

                minPos.Mul(8 / 16f);
                maxPos.Mul(8 / 16f);
                maxPos.Y = 5 / 16f - (1 - squeezeRel) * 0.25f;

                minPos.Add(face.Normalf.X * 1.2f / 16f, 0, face.Normalf.Z * 1.2f / 16f);
                maxPos.Add(face.Normalf.X * 1.2f / 16f, 0, face.Normalf.Z * 1.2f / 16f);

                liquidParticles.MinPos = minPos;
                liquidParticles.AddPos = maxPos.Sub(minPos);
                liquidParticles.MinPos.Add(Pos).Add(0.5, 1, 0.5);

                Api.World.SpawnParticles(liquidParticles);
            }

            if (squeezeRel < 0.9f)
            {
                liquidParticles.MinPos = Pos.ToVec3d().Add(6 / 16f, 0.7f, 6 / 16f);
                liquidParticles.AddPos.Set(4 / 16f, 0f, 4 / 16f);
                for (int i = 0; i < 3; i++)
                {
                    liquidParticles.Color = cols[rand.Next(cols.Length)];
                    Api.World.SpawnParticles(liquidParticles);
                }
            }
        }
Beispiel #12
0
        public List <BlockPos> MakeGrid(IWorldAccessor world, BlockPos targetPos, BlockPos startPos)
        {
            BlockPos pos  = startPos;
            Vec3d    posv = pos.ToVec3d();
            Vec3d    tgtv = targetPos.ToVec3d();
            BlockPos mP   = ((posv.Add(tgtv)) / 2).AsBlockPos;
            int      sR   = (int)mP.DistanceTo(pos) + 4;
            var      grid = new CubeGrid(sR * 2, sR * 2, sR * 2);

            if (!grid.isInBounds(world, targetPos) || !grid.isPassable(world, targetPos) || !grid.isWalkable(world, targetPos))
            {
                return(new List <BlockPos> {
                    startPos
                });
            }
            for (int x = mP.X - sR; x <= mP.X + sR; x++)
            {
                for (int y = mP.Y - sR; y <= mP.Y + sR; y++)
                {
                    for (int z = mP.Z - sR; z <= mP.Z + sR; z++)
                    {
                        BlockPos currentPos = new BlockPos(x, y, z);
                        if (grid.isInBounds(world, currentPos) && grid.isPassable(world, currentPos) && grid.isWalkable(world, currentPos))
                        {
                            grid.air.Add(currentPos);
                        }
                        else
                        {
                            grid.walls.Add(currentPos);
                        }
                    }
                }
            }
            var astar = new AStarSearch(world, grid, pos, targetPos);

            return(CurrentPath(world, astar, mP, sR));
        }
        /// <summary>
        ///     Gets the point in between.
        /// </summary>
        /// <param name="point1">The point1.</param>
        /// <param name="point2">The point2.</param>
        /// <param name="percent">The percent.</param>
        /// <param name="wholeProgress">The whole progress.</param>
        /// <param name="isFirstLoop">if set to <c>true</c> [is first loop].</param>
        /// <param name="isLastLoop">if set to <c>true</c> [is last loop].</param>
        /// <returns>CamNode.</returns>
        internal new CamNode GetPointInBetween(CamNode point1, CamNode point2, double percent, double wholeProgress, bool isFirstLoop,
                                               bool isLastLoop)
        {
            var newCamPoint = base.GetPointInBetween(point1, point2, percent, wholeProgress, isFirstLoop, isLastLoop);

            var angle = wholeProgress * 360;

            var center = _target.GetPosition();

            if (center == null)
            {
                return(newCamPoint);
            }

            var centerPoint = new Vec3d(center.X, center.Y, center.Z);

            var newPoint = new Vec3d(_sphereOrigin.X, _sphereOrigin.Y, _sphereOrigin.Z)
            {
                Y = 0
            };

            var matrix = new Matrix3d();

            Matrix3d.RotY(angle * GameMath.DEG2RAD);
            matrix.Transform(newPoint);

            newPoint.Y = _yAxis.ValueAt(wholeProgress) - center.Y;
            newPoint.Normalize();
            newPoint.Scale(_radius);

            newPoint.Add(centerPoint);
            newCamPoint.X = newPoint.X;
            newCamPoint.Y = newPoint.Y;
            newCamPoint.Z = newPoint.Z;
            return(newCamPoint);
        }
Beispiel #14
0
        private bool TryCircleTarget()
        {
            // Console.WriteLine("try circle target");

            bool giveUpWhenNoPath = targetPos.SquareDistanceTo(entity.Pos) < 12 * 12;
            int  searchDepth      = 3500;

            attackPattern  = EnumAttackPattern.CircleTarget;
            lastPathfindOk = false;

            // If we cannot find a path to the target, let's circle it!
            float angle = (float)Math.Atan2(entity.ServerPos.X - targetPos.X, entity.ServerPos.Z - targetPos.Z);

            for (int i = 0; i < 3; i++)
            {
                // We need to avoid crossing the path of the target, so we do only small angle variation between us and the target
                double randAngle = angle + 0.5 + world.Rand.NextDouble() / 2;

                double distance = 4 + world.Rand.NextDouble() * 6;

                double dx = GameMath.Sin(randAngle) * distance;
                double dz = GameMath.Cos(randAngle) * distance;
                targetPos.Add(dx, 0, dz);

                int      tries = 0;
                bool     ok    = false;
                BlockPos tmp   = new BlockPos((int)targetPos.X, (int)targetPos.Y, (int)targetPos.Z);

                int dy = 0;
                while (tries < 5)
                {
                    // Down ok?
                    if (world.BlockAccessor.GetBlock(tmp.X, tmp.Y - dy, tmp.Z).SideSolid[BlockFacing.UP.Index] && !world.CollisionTester.IsColliding(world.BlockAccessor, entity.SelectionBox, new Vec3d(tmp.X + 0.5, tmp.Y - dy + 1, tmp.Z + 0.5), false))
                    {
                        ok           = true;
                        targetPos.Y -= dy;
                        targetPos.Y++;
                        break;
                    }

                    // Up ok?
                    if (world.BlockAccessor.GetBlock(tmp.X, tmp.Y + dy, tmp.Z).SideSolid[BlockFacing.UP.Index] && !world.CollisionTester.IsColliding(world.BlockAccessor, entity.SelectionBox, new Vec3d(tmp.X + 0.5, tmp.Y + dy + 1, tmp.Z + 0.5), false))
                    {
                        ok           = true;
                        targetPos.Y += dy;
                        targetPos.Y++;
                        break;
                    }

                    tries++;
                    dy++;
                }

                if (ok)
                {
                    pathTraverser.NavigateTo_Async(targetPos.Clone(), moveSpeed, MinDistanceToTarget(), OnGoalReached, OnStuck, OnCircleTargetUnable, searchDepth, 1);
                    return(true);
                }
            }

            return(false);
        }
Beispiel #15
0
        public override bool OnHeldInteractStep(float secondsUsed, ItemSlot slot, EntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel)
        {
            if (blockSel == null)
            {
                return(false);
            }

            ILiquidMetalSink be = byEntity.World.BlockAccessor.GetBlockEntity(blockSel.Position) as ILiquidMetalSink;

            if (be == null)
            {
                return(false);
            }

            if (!be.CanReceiveAny)
            {
                return(false);
            }
            KeyValuePair <ItemStack, int> contents = GetContents(byEntity.World, slot.Itemstack);

            if (!be.CanReceive(contents.Key))
            {
                return(false);
            }

            float speed = 1.5f;
            float temp  = GetTemperature(byEntity.World, slot.Itemstack);

            if (byEntity.World is IClientWorldAccessor)
            {
                ModelTransform tf = new ModelTransform();
                tf.EnsureDefaultValues();

                tf.Origin.Set(0.5f, 0.2f, 0.5f);
                tf.Translation.Set(0, 0, -Math.Min(0.25f, speed * secondsUsed / 4));
                tf.Scale      = 1f + Math.Min(0.25f, speed * secondsUsed / 4);
                tf.Rotation.X = Math.Max(-110, -secondsUsed * 90 * speed);
                byEntity.Controls.UsingHeldItemTransformBefore = tf;
            }

            IPlayer byPlayer = null;

            if (byEntity is EntityPlayer)
            {
                byPlayer = byEntity.World.PlayerByUid(((EntityPlayer)byEntity).PlayerUID);
            }


            if (secondsUsed > 1 / speed)
            {
                if ((int)(30 * secondsUsed) % 3 == 1)
                {
                    Vec3d pos =
                        byEntity.Pos.XYZ
                        .Ahead(0.1f, byEntity.Pos.Pitch, byEntity.Pos.Yaw)
                        .Ahead(1.0f, byEntity.Pos.Pitch, byEntity.Pos.Yaw - GameMath.PIHALF)
                    ;
                    pos.Y += byEntity.LocalEyePos.Y - 0.4f;

                    smokePouring.MinPos = pos.AddCopy(-0.15, -0.15, -0.15);

                    Vec3d blockpos = blockSel.Position.ToVec3d().Add(0.5, 0.2, 0.5);

                    bigMetalSparks.MinQuantity = Math.Max(0.2f, 1 - (secondsUsed - 1) / 4);

                    if ((int)(30 * secondsUsed) % 7 == 1)
                    {
                        bigMetalSparks.MinPos = pos;
                        bigMetalSparks.MinVelocity.Set(-2, -1, -2);
                        bigMetalSparks.AddVelocity.Set(4, 1, 4);
                        byEntity.World.SpawnParticles(bigMetalSparks, byPlayer);

                        byEntity.World.SpawnParticles(smokePouring, byPlayer);
                    }

                    float     y2       = 0;
                    Block     block    = byEntity.World.BlockAccessor.GetBlock(blockSel.Position);
                    Cuboidf[] collboxs = block.GetCollisionBoxes(byEntity.World.BlockAccessor, blockSel.Position);
                    for (int i = 0; collboxs != null && i < collboxs.Length; i++)
                    {
                        y2 = Math.Max(y2, collboxs[i].Y2);
                    }

                    // Metal Spark on the mold
                    bigMetalSparks.MinVelocity.Set(-2, 1, -2);
                    bigMetalSparks.AddVelocity.Set(4, 5, 4);
                    bigMetalSparks.MinPos = blockpos.AddCopy(-0.25, y2 - 2 / 16f, -0.25);
                    bigMetalSparks.AddPos.Set(0.5, 0, 0.5);
                    bigMetalSparks.VertexFlags = (byte)GameMath.Clamp((int)temp - 770, 48, 128);
                    byEntity.World.SpawnParticles(bigMetalSparks, byPlayer);

                    // Smoke on the mold
                    byEntity.World.SpawnParticles(
                        Math.Max(1, 12 - (secondsUsed - 1) * 6),
                        ColorUtil.ToRgba(50, 220, 220, 220),
                        blockpos.AddCopy(-0.5, y2 - 2 / 16f, -0.5),
                        blockpos.Add(0.5, y2 - 2 / 16f + 0.15, 0.5),
                        new Vec3f(-0.5f, 0f, -0.5f),
                        new Vec3f(0.5f, 0f, 0.5f),
                        1.5f,
                        -0.05f,
                        0.75f,
                        EnumParticleModel.Quad,
                        byPlayer
                        );
                }

                int transferedAmount = Math.Min(2, contents.Value);


                be.ReceiveLiquidMetal(contents.Key, ref transferedAmount, temp);

                int newAmount = Math.Max(0, contents.Value - (2 - transferedAmount));
                slot.Itemstack.Attributes.SetInt("units", newAmount);


                if (newAmount <= 0 && byEntity.World is IServerWorldAccessor)
                {
                    string emptiedCode = Attributes["emptiedBlockCode"].AsString();
                    slot.Itemstack = new ItemStack(byEntity.World.GetBlock(AssetLocation.Create(emptiedCode, Code.Domain)));
                    slot.MarkDirty();
                    // Since we change the item stack we have to call this ourselves
                    OnHeldInteractStop(secondsUsed, slot, byEntity, blockSel, entitySel);
                    return(false);
                }

                return(true);
            }

            return(true);
        }
        public override bool OnHeldInteractStep(float secondsUsed, ItemSlot slot, EntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel)
        {
            if (blockSel == null)
            {
                return(false);
            }
            if (slot.Itemstack.TempAttributes.GetInt("refilled") > 0)
            {
                return(false);
            }

            float prevsecondsused = slot.Itemstack.TempAttributes.GetFloat("secondsUsed");

            slot.Itemstack.TempAttributes.SetFloat("secondsUsed", secondsUsed);

            float remainingwater = GetRemainingWateringSeconds(slot.Itemstack);

            SetRemainingWateringSeconds(slot.Itemstack, remainingwater -= secondsUsed - prevsecondsused);


            if (remainingwater <= 0)
            {
                return(false);
            }

            IWorldAccessor world = byEntity.World;

            BlockPos targetPos = blockSel.Position;

            if (api.World.Side == EnumAppSide.Server)
            {
                var beburningBh = world.BlockAccessor.GetBlockEntity(blockSel.Position.AddCopy(blockSel.Face))?.GetBehavior <BEBehaviorBurning>();
                if (beburningBh != null)
                {
                    beburningBh.KillFire(false);
                }

                beburningBh = world.BlockAccessor.GetBlockEntity(blockSel.Position)?.GetBehavior <BEBehaviorBurning>();
                if (beburningBh != null)
                {
                    beburningBh.KillFire(false);
                }

                Vec3i voxelPos = new Vec3i();
                for (int dx = -2; dx < 2; dx++)
                {
                    for (int dy = -2; dy < 2; dy++)
                    {
                        for (int dz = -2; dz < 2; dz++)
                        {
                            int x = (int)(blockSel.HitPosition.X * 16);
                            int y = (int)(blockSel.HitPosition.Y * 16);
                            int z = (int)(blockSel.HitPosition.Z * 16);
                            if (x + dx < 0 || x + dx > 15 || y + dy < 0 || y + dy > 15 || z + dz < 0 || z + dz > 15)
                            {
                                continue;
                            }

                            voxelPos.Set(x + dx, y + dy, z + dz);

                            int   faceAndSubPosition = CollectibleBehaviorArtPigment.BlockSelectionToSubPosition(blockSel.Face, voxelPos);
                            Block decorblock         = world.BlockAccessor.GetDecor(blockSel.Position, faceAndSubPosition);

                            if (decorblock?.FirstCodePart() == "caveart")
                            {
                                world.BlockAccessor.BreakDecor(blockSel.Position, blockSel.Face, faceAndSubPosition);
                            }
                        }
                    }
                }
            }

            Block block           = world.BlockAccessor.GetBlock(blockSel.Position);
            bool  notOnSolidblock = false;

            if ((block.CollisionBoxes == null || block.CollisionBoxes.Length == 0) && !block.IsLiquid())
            {
                notOnSolidblock = true;
                targetPos       = targetPos.DownCopy();
            }

            BlockEntityFarmland be = world.BlockAccessor.GetBlockEntity(targetPos) as BlockEntityFarmland;

            if (be != null)
            {
                be.WaterFarmland(secondsUsed - prevsecondsused);
            }

            float speed = 3f;

            if (world.Side == EnumAppSide.Client)
            {
                ModelTransform tf = new ModelTransform();
                tf.EnsureDefaultValues();

                tf.Origin.Set(0.5f, 0.2f, 0.5f);
                tf.Translation.Set(-Math.Min(0.25f, speed * secondsUsed / 2), 0, 0);
                tf.Rotation.Z = GameMath.Min(60, secondsUsed * 90 * speed, 120 - remainingwater * 4);
                byEntity.Controls.UsingHeldItemTransformBefore = tf;
            }

            IPlayer byPlayer = null;

            if (byEntity is EntityPlayer)
            {
                byPlayer = byEntity.World.PlayerByUid(((EntityPlayer)byEntity).PlayerUID);
            }


            if (secondsUsed > 1 / speed)
            {
                Vec3d pos = blockSel.Position.ToVec3d().Add(blockSel.HitPosition);
                if (notOnSolidblock)
                {
                    pos.Y = (int)pos.Y + 0.05;
                }
                WaterParticles.MinPos = pos.Add(-0.125 / 2, 1 / 16f, -0.125 / 2);
                byEntity.World.SpawnParticles(WaterParticles, byPlayer);
            }

            return(true);
        }
        public override bool OnHeldInteractStep(float secondsUsed, ItemSlot slot, EntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel)
        {
            if (blockSel == null)
            {
                return(false);
            }
            if (slot.Itemstack.TempAttributes.GetInt("refilled") > 0)
            {
                return(false);
            }

            float prevsecondsused = slot.Itemstack.TempAttributes.GetFloat("secondsUsed");

            slot.Itemstack.TempAttributes.SetFloat("secondsUsed", secondsUsed);

            float remainingwater = GetRemainingWateringSeconds(slot.Itemstack);

            SetRemainingWateringSeconds(slot.Itemstack, remainingwater -= secondsUsed - prevsecondsused);


            if (remainingwater <= 0)
            {
                return(false);
            }

            IWorldAccessor world = byEntity.World;

            BlockPos targetPos = blockSel.Position;

            Block facingBlock = world.BlockAccessor.GetBlock(blockSel.Position.AddCopy(blockSel.Face));

            if (facingBlock.Code.Path == "fire")
            {
                world.BlockAccessor.SetBlock(0, blockSel.Position.AddCopy(blockSel.Face));
            }

            Block block           = world.BlockAccessor.GetBlock(blockSel.Position);
            bool  notOnSolidblock = false;

            if ((block.CollisionBoxes == null || block.CollisionBoxes.Length == 0) && !block.IsLiquid())
            {
                notOnSolidblock = true;
                targetPos       = targetPos.DownCopy();
            }

            BlockEntityFarmland be = world.BlockAccessor.GetBlockEntity(targetPos) as BlockEntityFarmland;

            if (be != null)
            {
                be.WaterFarmland(secondsUsed - prevsecondsused);
            }

            float speed = 4f;

            if (world.Side == EnumAppSide.Client)
            {
                ModelTransform tf = new ModelTransform();
                tf.EnsureDefaultValues();

                tf.Origin.Set(0.5f, 0.2f, 0.5f);
                tf.Translation.Set(-Math.Min(0.25f, speed * secondsUsed / 4), 0, 0);

                tf.Rotation.Z = GameMath.Min(60, secondsUsed * 90 * speed, 80 - remainingwater * 5);
                byEntity.Controls.UsingHeldItemTransformBefore = tf;
            }

            IPlayer byPlayer = null;

            if (byEntity is EntityPlayer)
            {
                byPlayer = byEntity.World.PlayerByUid(((EntityPlayer)byEntity).PlayerUID);
            }


            if (secondsUsed > 1 / speed)
            {
                Vec3d pos = blockSel.Position.ToVec3d().Add(blockSel.HitPosition);
                if (notOnSolidblock)
                {
                    pos.Y = (int)pos.Y + 0.05;
                }
                WaterParticles.MinPos = pos.Add(-0.125 / 2, 1 / 16f, -0.125 / 2);
                byEntity.World.SpawnParticles(WaterParticles, byPlayer);
            }

            return(true);
        }
Beispiel #18
0
        public override void DoRender2D(float dt)
        {
            if (isSpectator || (nameTagTexture == null && debugTagTexture == null))
            {
                return;
            }
            if ((entity as EntityPlayer)?.ServerControls.Sneak == true && debugTagTexture == null)
            {
                return;
            }

            IRenderAPI   rapi         = capi.Render;
            EntityPlayer entityPlayer = capi.World.Player.Entity;
            Vec3d        aboveHeadPos;

            if (capi.World.Player.Entity.EntityId == entity.EntityId)
            {
                if (rapi.CameraType == EnumCameraMode.FirstPerson)
                {
                    return;
                }
                aboveHeadPos = new Vec3d(entityPlayer.CameraPos.X + entityPlayer.LocalEyePos.X, entityPlayer.CameraPos.Y + 0.4 + entityPlayer.LocalEyePos.Y, entityPlayer.CameraPos.Z + entityPlayer.LocalEyePos.Z);
            }
            else
            {
                var thisMount = (entity as EntityAgent)?.MountedOn;
                var selfMount = entityPlayer.MountedOn;

                if (thisMount?.MountSupplier != null && thisMount.MountSupplier == selfMount?.MountSupplier)
                {
                    var mpos = thisMount.MountSupplier.GetMountOffset(entity);

                    aboveHeadPos = new Vec3d(entityPlayer.CameraPos.X + entityPlayer.LocalEyePos.X, entityPlayer.CameraPos.Y + 0.4 + entityPlayer.LocalEyePos.Y, entityPlayer.CameraPos.Z + entityPlayer.LocalEyePos.Z);
                    aboveHeadPos.Add(mpos);
                }
                else
                {
                    float f = 1;

                    /*if (entity.Code.Path.Contains("bot") && entity.AnimManager.ActiveAnimationsByAnimCode.ContainsKey("sitflooridle"))
                     * {
                     *  f = 0.55f;
                     * }*/

                    aboveHeadPos = new Vec3d(entity.Pos.X, entity.Pos.Y + entity.SelectionBox.Y2 * f + 0.2, entity.Pos.Z);
                }
            }

            double offX = entity.SelectionBox.X2 - entity.OriginSelectionBox.X2;
            double offZ = entity.SelectionBox.Z2 - entity.OriginSelectionBox.Z2;

            aboveHeadPos.Add(offX, 0, offZ);


            Vec3d pos = MatrixToolsd.Project(aboveHeadPos, rapi.PerspectiveProjectionMat, rapi.PerspectiveViewMat, rapi.FrameWidth, rapi.FrameHeight);

            // Z negative seems to indicate that the name tag is behind us \o/
            if (pos.Z < 0)
            {
                return;
            }

            float scale = 4f / Math.Max(1, (float)pos.Z);

            float cappedScale = Math.Min(1f, scale);

            if (cappedScale > 0.75f)
            {
                cappedScale = 0.75f + (cappedScale - 0.75f) / 2;
            }

            float offY = 0;

            double dist = entityPlayer.Pos.SquareDistanceTo(entity.Pos);

            if (nameTagTexture != null && (!showNameTagOnlyWhenTargeted || capi.World.Player.CurrentEntitySelection?.Entity == entity) && renderRange * renderRange > dist)
            {
                float posx = (float)pos.X - cappedScale * nameTagTexture.Width / 2;
                float posy = rapi.FrameHeight - (float)pos.Y - (nameTagTexture.Height * Math.Max(0, cappedScale));

                rapi.Render2DTexture(
                    nameTagTexture.TextureId, posx, posy, cappedScale * nameTagTexture.Width, cappedScale * nameTagTexture.Height, 20
                    );

                offY += nameTagTexture.Height;
            }

            if (debugTagTexture != null)
            {
                float posx = (float)pos.X - cappedScale * debugTagTexture.Width / 2;
                float posy = rapi.FrameHeight - (float)pos.Y - (offY + debugTagTexture.Height) * Math.Max(0, cappedScale);

                rapi.Render2DTexture(
                    debugTagTexture.TextureId, posx, posy - offY, cappedScale * debugTagTexture.Width, cappedScale * debugTagTexture.Height, 20
                    );
            }

            if (messageTextures != null)
            {
                offY += 0;

                foreach (MessageTexture mt in messageTextures)
                {
                    offY += (mt.tex.Height * cappedScale) + 4;

                    float posx = (float)pos.X - cappedScale * mt.tex.Width / 2;
                    float posy = (float)pos.Y + offY;


                    rapi.Render2DTexture(
                        mt.tex.TextureId, posx, rapi.FrameHeight - posy, cappedScale * mt.tex.Width, cappedScale * mt.tex.Height, 20
                        );
                }
            }
        }
        public void update(float dt)
        {
            if (pinned)
            {
                if (pinnedTo != null)
                {
                    if (pinnedTo.ShouldDespawn && pinnedTo.DespawnReason?.reason != EnumDespawnReason.Unload)
                    {
                        UnPin();
                        return;
                    }

                    // New ideas:
                    // don't apply force onto the player/entity on compression
                    // apply huge forces onto the player on strong extension (to prevent massive stretching) (just set player motion to 0 or so. or we add a new countermotion field thats used in EntityControlledPhysics?)

                    float weight = pinnedTo.Properties.Weight;
                    float counterTensionStrength = GameMath.Clamp(50f / weight, 0.1f, 2f);

                    bool  extraResist           = (pinnedTo as EntityAgent)?.Controls.Sneak == true || pinnedTo.AnimManager?.IsAnimationActive("sit") == true || pinnedTo.AnimManager?.IsAnimationActive("sleep") == true;
                    float tensionResistStrength = weight / 10f * (extraResist ? 200 : 0);

                    pinOffsetTransform.Identity();
                    pinOffsetTransform.RotateY(pinnedTo.SidedPos.Yaw - pinnedToOffsetStartYaw);
                    tmpvec.Set(pinnedToOffset.X, pinnedToOffset.Y, pinnedToOffset.Z, 1);
                    Vec4f outvec = pinOffsetTransform.TransformVector(tmpvec);

                    EntityPos pos = pinnedTo.SidedPos;
                    Pos.Set(pos.X + outvec.X, pos.Y + outvec.Y, pos.Z + outvec.Z);

                    bool pushable = !(pinnedTo is EntityPlayer eplr && eplr.Player.WorldData.CurrentGameMode == EnumGameMode.Creative);

                    if (pushable && extension > 0) // Do not act on compressive force
                    {
                        float f = counterTensionStrength * dt * 0.003f;
                        pos.Motion.Add(
                            GameMath.Clamp(Math.Abs(TensionDirection.X) - tensionResistStrength, 0, 400) * f * Math.Sign(TensionDirection.X),
                            GameMath.Clamp(Math.Abs(TensionDirection.Y) - tensionResistStrength, 0, 400) * f * Math.Sign(TensionDirection.Y),
                            GameMath.Clamp(Math.Abs(TensionDirection.Z) - tensionResistStrength, 0, 400) * f * Math.Sign(TensionDirection.Z)
                            );
                    }

                    Velocity.Set(0, 0, 0);
                }
                else
                {
                    Velocity.Set(0, 0, 0);

                    accum1s += dt;

                    if (accum1s >= 1)
                    {
                        accum1s = 0;
                        Block block = cs.api.World.BlockAccessor.GetBlock(PinnedToBlockPos);
                        if (!block.HasBehavior <BlockBehaviorRopeTieable>())
                        {
                            UnPin();
                        }
                    }
                }

                return;
            }

            // Calculate the force on this ball
            Vec3f force = Tension.Clone();

            force.Y -= GravityStrength * 10;

            // Calculate the acceleration
            Vec3f acceleration = force * (float)InvMass;

            if (CollideFlags == 0)
            {
                acceleration.X += (float)cs.windSpeed.X * InvMass;
            }


            // Update velocity
            Vec3f nextVelocity = Velocity + (acceleration * dt);

            // Damp the velocity
            nextVelocity *= dampFactor;

            // Collision detection
            float size = 0.1f;

            cs.pp.HandleBoyancy(Pos, nextVelocity, cs.boyant, GravityStrength, dt, size);
            CollideFlags = cs.pp.UpdateMotion(Pos, nextVelocity, size);

            dt *= 0.99f;
            Pos.Add(nextVelocity.X * dt, nextVelocity.Y * dt, nextVelocity.Z * dt);


            Velocity.Set(nextVelocity);
            Tension.Set(0, 0, 0);
        }