示例#1
0
        private void InitDebugInfo()
        {
            _debugInfo.AddDebugLeft(() =>
            {
                //FpsCounter.Update();
                //World.ChunkManager.GetPendingLightingUpdates(out int lowLight, out int midLight, out int highLight);

                double avg = 0;
                if (World.ChunkManager.TotalChunkUpdates > 0)
                {
                    avg = (World.ChunkManager.ChunkUpdateTime / World.ChunkManager.TotalChunkUpdates).TotalMilliseconds;
                }

                return
                ($"Alex {Alex.Version} ({Alex.FpsMonitor.Value:##} FPS, Chunk Updates: {World.EnqueuedChunkUpdates} queued, {World.ConcurrentChunkUpdates} active, Avg: {avg:F2}ms, Max: {World.ChunkManager.MaxUpdateTime.TotalMilliseconds:F2}ms, Min: {World.ChunkManager.MinUpdateTIme.TotalMilliseconds:F2})"                        /*, H: {highLight} M: {midLight} L: {lowLight} lighting updates)"*/
                );
            });
            _debugInfo.AddDebugLeft(() =>
            {
                var pos      = World.Player.KnownPosition;
                var blockPos = pos.GetCoordinates3D();
                return($"RenderPosition: (X={pos.X:F2}, Y={pos.Y:F2}, Z={pos.Z:F2}) / Block: ({blockPos.X:D}, {blockPos.Y:D}, {blockPos.Z:D})");
            });
            _debugInfo.AddDebugLeft(() =>
            {
                var pos = World.Player.KnownPosition;
                return($"Facing: {GetCardinalDirection(pos)} (HeadYaw={pos.HeadYaw:F2}, Yaw={pos.Yaw:F2}, Pitch={pos.Pitch:F2})");
            });
            _debugInfo.AddDebugLeft(() =>
            {
                var pos = World.Player.Velocity;
                return($"Velocity: (X={pos.X:F2}, Y={pos.Y:F2}, Z={pos.Z:F2}) / Target Speed: {(World.Player.Controller.LastSpeedFactor * 20f):F3} M/s");
            });
            _debugInfo.AddDebugLeft(() => $"Vertices: {World.Vertices:N0} ({GetBytesReadable((long)(World.Vertices * BlockShaderVertex.VertexDeclaration.VertexStride))})");
            //	_debugInfo.AddDebugLeft(() => $"IndexBuffer Elements: {World.IndexBufferSize:N0} ({GetBytesReadable(World.IndexBufferSize * 4)})");
            _debugInfo.AddDebugLeft(() => $"Chunks: {World.ChunkCount}, {World.ChunkManager.RenderedChunks}");
            _debugInfo.AddDebugLeft(() => $"Entities: {World.EntityManager.EntityCount}, {World.EntityManager.EntitiesRendered}");
            _debugInfo.AddDebugLeft(() =>
            {
                return($"Biome: {_currentBiome.Name} ({_currentBiomeId})");
            });
            _debugInfo.AddDebugLeft(() => { return($"Do DaylightCycle: {World.DoDaylightcycle}"); });

            _debugInfo.AddDebugRight(() => Alex.OperatingSystem);
            _debugInfo.AddDebugRight(() => Alex.Gpu);
            _debugInfo.AddDebugRight(() => $"{Alex.DotnetRuntime}\n");
            //_debugInfo.AddDebugRight(() => MemoryUsageDisplay);
            _debugInfo.AddDebugRight(() => $"RAM: {GetBytesReadable(_ramUsage, 2)}");
            _debugInfo.AddDebugRight(() => $"GPU: {GetBytesReadable(GpuResourceManager.GetMemoryUsage, 2)}");
            _debugInfo.AddDebugRight(() =>
            {
                return
                ($"Threads: {(_threadsUsed):00}/{_maxThreads}");
            });
            _debugInfo.AddDebugRight(() =>
            {
                if (_raytracedBlock.Y > 0 && _raytracedBlock.Y < 256)
                {
                    var adj = Vector3.Floor(_adjacentBlock) - Vector3.Floor(_raytracedBlock);
                    adj.Normalize();

                    var face = adj.GetBlockFace();

                    StringBuilder sb = new StringBuilder();
                    sb.AppendLine($"Target: {_raytracedBlock} Face: {face}");
                    sb.AppendLine(
                        $"Skylight: {World.GetSkyLight(_raytracedBlock)} Face Skylight: {World.GetSkyLight(_adjacentBlock)}");
                    sb.AppendLine(
                        $"Blocklight: {World.GetBlockLight(_raytracedBlock)} Face Blocklight: {World.GetBlockLight(_adjacentBlock)}");

                    //sb.AppendLine($"Skylight scheduled: {World.IsScheduled((int) _raytracedBlock.X, (int) _raytracedBlock.Y, (int) _raytracedBlock.Z)}");

                    foreach (var bs in World
                             .GetBlockStates((int)_raytracedBlock.X, (int)_raytracedBlock.Y, (int)_raytracedBlock.Z))
                    {
                        var blockstate = bs.State;
                        if (blockstate != null && blockstate.Block.Renderable)
                        {
                            sb.AppendLine($"{blockstate.Name} (S: {bs.Storage})");
                            if (blockstate.IsMultiPart)
                            {
                                sb.AppendLine($"MultiPart=true");
                                sb.AppendLine();

                                sb.AppendLine("Models:");

                                foreach (var model in blockstate.AppliedModels)
                                {
                                    sb.AppendLine(model);
                                }
                            }

                            var dict = blockstate.ToDictionary();

                            if (dict.Count > 0)
                            {
                                sb.AppendLine();
                                sb.AppendLine("Blockstate:");

                                foreach (var kv in dict)
                                {
                                    sb.AppendLine($"{kv.Key}={kv.Value}");
                                }
                            }
                        }
                    }

                    return(sb.ToString());
                }
                else
                {
                    return(string.Empty);
                }
            });

            _debugInfo.AddDebugRight(() =>
            {
                var player = World.Player;
                if (player == null || player.HitEntity == null)
                {
                    return(string.Empty);
                }

                var entity = player.HitEntity;
                return($"Hit entity: {entity.EntityId} / {entity.ToString()}");
            });
        }
示例#2
0
        public ModelDebugState()
        {
            _debugInfo = new GuiDebugInfo();

            Background = Color.DeepSkyBlue;

            BlockModelExplorer  = new BlockModelExplorer(Alex.Instance, null);
            EntityModelExplorer = new EntityModelExplorer(Alex.Instance, null);

            ModelExplorer = BlockModelExplorer;

            //AddChild(_wrap = new GuiStackContainer()
            //{
            //	Orientation = Orientation.Horizontal,
            //	Anchor = Alignment.Fill,
            //	ChildAnchor = Alignment.FillY
            //});

            AddChild(_modelExplorerView = new GuiModelExplorerView(ModelExplorer, new Vector3(0f, 1.85f, 6f), new Vector3(0.5f, 0.5f, 0.5f))
            {
                Anchor            = Alignment.Fill,
                Background        = Color.TransparentBlack,
                BackgroundOverlay = new Color(Color.Black, 0.15f),

                Margin = new Thickness(0),

                Width  = 92,
                Height = 128,

                AutoSizeMode = AutoSizeMode.None,

                //Anchor = Alignment.BottomRight,

                // Width = 100,
                // Height = 100
            });

            AddChild(_mainMenu = new GuiStackMenu()
            {
                Margin  = new Thickness(0, 0, 15, 0),
                Padding = new Thickness(0, 50, 0, 0),
                Width   = 125,
                Anchor  = Alignment.FillY | Alignment.MinX,

                ChildAnchor       = Alignment.CenterY | Alignment.FillX,
                BackgroundOverlay = new Color(Color.Black, 0.35f)
            });

            //_wrap.AddChild(_modelRenderer = new DebugModelRenderer(Alex)
            //{
            //	Anchor = Alignment.Fill,
            //	// Width = 100,
            //	// Height = 100
            //});



            _mainMenu.AddMenuItem("Skip", () => { Task.Run(() => { ModelExplorer.Skip(); }); });
            _mainMenu.AddMenuItem("Next", NextModel);
            _mainMenu.AddMenuItem("Previous", PrevModel);
            _mainMenu.AddMenuItem("Switch Models", () =>
            {
                SwitchModelExplorers();
                _modelExplorerView.ModelExplorer = ModelExplorer;
            });

            //AddChild(_mainMenu);

            _debugInfo.AddDebugRight(() => Alex.DotnetRuntime);
            //_debugInfo.AddDebugRight(() => MemoryUsageDisplay);
            _debugInfo.AddDebugRight(() => $"RAM: {PlayingState.GetBytesReadable(_ramUsage, 2)}");
            _debugInfo.AddDebugRight(() =>
                                     $"GPU: {PlayingState.GetBytesReadable(GpuResourceManager.GetMemoryUsage, 2)}");
            _debugInfo.AddDebugRight(() =>
            {
                return
                ($"Threads: {(_threadsUsed):00}/{_maxThreads}\nCompl.ports: {_complPortUsed:00}/{_maxComplPorts}");
            });

            _debugInfo.AddDebugRight(() =>
            {
                if (ModelExplorer == null)
                {
                    return(string.Empty);
                }

                return(ModelExplorer.GetDebugInfo());
            });

            _keyState = Keyboard.GetState();
        }
示例#3
0
        public TitleState()
        {
            FpsMonitor        = new FpsMonitor();
            _backgroundSkyBox = new GuiPanoramaSkyBox(Alex);

            Background.Texture    = _backgroundSkyBox;
            Background.RepeatMode = TextureRepeatMode.Stretch;

            #region Create MainMenu

            _mainMenu = new GuiStackMenu()
            {
                Margin  = new Thickness(15, 0, 15, 0),
                Padding = new Thickness(0, 50, 0, 0),
                Width   = 125,
                Anchor  = Alignment.FillY | Alignment.MinX,

                ChildAnchor       = Alignment.CenterY | Alignment.FillX,
                BackgroundOverlay = new Color(Color.Black, 0.35f)
            };

            _mainMenu.AddMenuItem("Multiplayer", JavaEditionButtonPressed, EnableMultiplayer);
            _mainMenu.AddMenuItem("SinglePlayer", OnSinglePlayerPressed);

            _mainMenu.AddMenuItem("Options", () => { Alex.GameStateManager.SetActiveState("options"); });
            _mainMenu.AddMenuItem("Exit", () => { Alex.Exit(); });
            #endregion

            #region Create DebugMenu

            _debugMenu = new GuiStackMenu()
            {
                Margin  = new Thickness(15, 0, 15, 0),
                Padding = new Thickness(0, 50, 0, 0),
                Width   = 125,
                Anchor  = Alignment.FillY | Alignment.MinX,

                ChildAnchor       = Alignment.CenterY | Alignment.FillX,
                BackgroundOverlay = new Color(Color.Black, 0.35f),
            };

            _debugMenu.AddMenuItem("Debug Blockstates", DebugWorldButtonActivated);
            _debugMenu.AddMenuItem("Debug Flatland", DebugFlatland);
            //_debugMenu.AddMenuItem("Debug Anvil", DebugAnvil);
            _debugMenu.AddMenuItem("Debug Chunk", DebugChunkButtonActivated);
            //	_debugMenu.AddMenuItem("Debug XBL Login", BedrockEditionButtonPressed);
            _debugMenu.AddMenuItem("Go Back", DebugGoBackPressed);

            #endregion

            #region Create SPMenu

            _spMenu = new GuiStackMenu()
            {
                Margin  = new Thickness(15, 0, 15, 0),
                Padding = new Thickness(0, 50, 0, 0),
                Width   = 125,
                Anchor  = Alignment.FillY | Alignment.MinX,

                ChildAnchor       = Alignment.CenterY | Alignment.FillX,
                BackgroundOverlay = new Color(Color.Black, 0.35f),
            };

            _spMenu.AddMenuItem("SinglePlayer", () => {}, false);
            _spMenu.AddMenuItem("Debug Worlds", OnDebugPressed);

            _spMenu.AddMenuItem("Return to main menu", SpBackPressed);

            #endregion

            CreateProtocolMenu();

            AddChild(_mainMenu);

            AddChild(_logo = new GuiImage(GuiTextures.AlexLogo)
            {
                Margin = new Thickness(95, 25, 0, 0),
                Anchor = Alignment.TopCenter
            });

            AddChild(_splashText = new GuiTextElement()
            {
                TextColor = TextColor.Yellow,
                Rotation  = 17.5f,

                Margin = new Thickness(240, 15, 0, 0),
                Anchor = Alignment.TopCenter,

                Text = "Who liek minecwaf?!",
            });

            _debugInfo = new GuiDebugInfo();
            _debugInfo.AddDebugRight(() => $"GPU Memory: {API.Extensions.GetBytesReadable(GpuResourceManager.GetMemoryUsage)}");
            _debugInfo.AddDebugLeft(() => $"FPS: {FpsMonitor.Value:F0}");

            _playerProfileService = Alex.Services.GetService <IPlayerProfileService>();
            _playerProfileService.ProfileChanged += PlayerProfileServiceOnProfileChanged;

            Alex.GameStateManager.AddState("options", new OptionsState(_backgroundSkyBox));
        }
示例#4
0
        private void InitDebugInfo()
        {
            string gameVersion = VersionUtils.GetVersion();

            _debugInfo.AddDebugLeft(
                () =>
            {
                double avg = 0;

                /*	if (World.ChunkManager.TotalChunkUpdates > 0)
                 *      {
                 *              avg = (World.ChunkManager.ChunkUpdateTime / World.ChunkManager.TotalChunkUpdates)
                 *                 .TotalMilliseconds;
                 *      }*/

                return
                ($"Alex {gameVersion} ({Alex.FpsMonitor.Value:##} FPS, {World.Ticker.TicksPerSecond:##} TPS, Chunk Updates: {World.EnqueuedChunkUpdates} queued, {World.ConcurrentChunkUpdates} active)");
            }, TimeSpan.FromMilliseconds(50));

            _debugInfo.AddDebugLeft(() =>
            {
                var pos      = World.Player.KnownPosition;
                var blockPos = pos.GetCoordinates3D();
                return($"Position: (X={pos.X:F2}, Y={pos.Y:F2}, Z={pos.Z:F2}, OnGround={pos.OnGround}) / Block: ({blockPos.X:D}, {blockPos.Y:D}, {blockPos.Z:D})");
            });

            _debugInfo.AddDebugLeft(() =>
            {
                var pos = World.Player.KnownPosition;
                return($"Facing: {GetCardinalDirection(pos)} (HeadYaw={pos.HeadYaw:F2}, Yaw={pos.Yaw:F2}, Pitch={pos.Pitch:F2})");
            });

            _debugInfo.AddDebugLeft(() =>
            {
                var pos = World.Player.Velocity;
                return($"Velocity: (X={pos.X:F2}, Y={pos.Y:F2}, Z={pos.Z:F2}) ({World.Player.CurrentSpeed:F3} m/s)");               // / Target Speed: {(World.Player.CalculateMovementSpeed() * 20f):F3} m/s";
            });

            _debugInfo.AddDebugLeft(() => $"Primitives: {Alex.Metrics.PrimitiveCount:N0} Draw count: {Alex.Metrics.DrawCount}", TimeSpan.FromMilliseconds(500));
            //	_debugInfo.AddDebugLeft(() => $"IndexBuffer Elements: {World.IndexBufferSize:N0} ({GetBytesReadable(World.IndexBufferSize * 4)})");
            _debugInfo.AddDebugLeft(() => $"Chunks: {World.ChunkCount}, {World.ChunkManager.RenderedChunks}", TimeSpan.FromMilliseconds(500));
            _debugInfo.AddDebugLeft(() => $"Entities: {World.EntityManager.EntityCount}, {World.EntityManager.EntitiesRendered}", TimeSpan.FromMilliseconds(500));
            _debugInfo.AddDebugLeft(() =>
            {
                return($"Biome: {_currentBiome.Name} ({_currentBiomeId})");
            }, TimeSpan.FromMilliseconds(500));
            //_debugInfo.AddDebugLeft(() => { return $"Do DaylightCycle: {World.DoDaylightcycle}"; });

            _debugInfo.AddDebugLeft(
                () =>
            {
                return($"Exhaustion: {World.Player.HealthManager.Exhaustion:F1}/{World.Player.HealthManager.MaxExhaustion}");
            }, TimeSpan.FromMilliseconds(250));

            _debugInfo.AddDebugLeft(
                () =>
            {
                return($"Saturation: {World.Player.HealthManager.Saturation:F1}/{World.Player.HealthManager.MaxSaturation}");
            }, TimeSpan.FromMilliseconds(250));

            _debugInfo.AddDebugLeft(
                () =>
            {
                return($"Health: {World.Player.HealthManager.Health:F1}/{World.Player.HealthManager.MaxHealth}");
            }, TimeSpan.FromMilliseconds(250));

            _debugInfo.AddDebugLeft(
                () =>
            {
                return($"Gamemode: {World.Player.Gamemode}");
            }, TimeSpan.FromSeconds(5));

            _debugInfo.AddDebugRight(Alex.OperatingSystem);
            _debugInfo.AddDebugRight(Alex.Gpu);
            _debugInfo.AddDebugRight($"{Alex.DotnetRuntime}\n");
            _debugInfo.AddDebugRight(Alex.RenderingEngine);
            //_debugInfo.AddDebugRight(() => MemoryUsageDisplay);
            _debugInfo.AddDebugRight(() => $"RAM: {GetBytesReadable(_ramUsage, 2)}", TimeSpan.FromMilliseconds(1000));
            _debugInfo.AddDebugRight(() => $"GPU: {GetBytesReadable(GpuResourceManager.GetMemoryUsage, 2)}", TimeSpan.FromMilliseconds(1000));
            _debugInfo.AddDebugRight(() =>
            {
                return
                ($"Threads: {(_threadsUsed):00}/{_maxThreads}");
            }, TimeSpan.FromMilliseconds(50));
            _debugInfo.AddDebugRight(() =>
            {
                var player = World?.Player;

                if (player == null)
                {
                    return("");
                }

                if (player.HasRaytraceResult)
                {
                    var raytracedBlock = player.RaytracedBlock;
                    var adjacentBlock  = player.AdjacentRaytraceBlock;
                    var adj            = Vector3.Floor(adjacentBlock) - Vector3.Floor(raytracedBlock);
                    adj.Normalize();

                    var face = adj.GetBlockFace();

                    StringBuilder sb = new StringBuilder();
                    sb.AppendLine($"Target: {raytracedBlock} Face: {face}");
                    sb.AppendLine(
                        $"Skylight: {World.GetSkyLight(raytracedBlock)} Face Skylight: {World.GetSkyLight(adjacentBlock)}");
                    sb.AppendLine(
                        $"Blocklight: {World.GetBlockLight(raytracedBlock)} Face Blocklight: {World.GetBlockLight(adjacentBlock)}");

                    //sb.AppendLine($"Skylight scheduled: {World.IsScheduled((int) _raytracedBlock.X, (int) _raytracedBlock.Y, (int) _raytracedBlock.Z)}");

                    foreach (var bs in World
                             .GetBlockStates((int)raytracedBlock.X, (int)raytracedBlock.Y, (int)raytracedBlock.Z))
                    {
                        var blockstate = bs.State;
                        if (blockstate != null && blockstate.Block.HasHitbox)
                        {
                            sb.AppendLine($"{blockstate.Name} (S: {bs.Storage})");

                            /*if (blockstate.IsMultiPart)
                             * {
                             *      sb.AppendLine($"MultiPart=true");
                             *      sb.AppendLine();
                             *
                             *      sb.AppendLine("Models:");
                             *
                             *      foreach (var model in blockstate.AppliedModels)
                             *      {
                             *              sb.AppendLine(model);
                             *      }
                             * }*/

                            var dict = blockstate.ToDictionary();

                            if (dict.Count > 0)
                            {
                                sb.AppendLine();
                                sb.AppendLine("Blockstate:");

                                foreach (var kv in dict)
                                {
                                    sb.AppendLine($"{kv.Key}={kv.Value}");
                                }
                            }
                        }
                    }

                    return(sb.ToString());
                }
                else
                {
                    return(string.Empty);
                }
            }, TimeSpan.FromMilliseconds(500));

            _debugInfo.AddDebugRight(() =>
            {
                var player = World.Player;
                if (player == null || player.HitEntity == null)
                {
                    return(string.Empty);
                }

                var entity = player.HitEntity;
                return($"Hit entity: {entity.EntityId} / {entity.ToString()}");
            }, TimeSpan.FromMilliseconds(500));
        }
示例#5
0
        private void InitDebugInfo()
        {
            _debugInfo.AddDebugLeft(() =>
            {
                //FpsCounter.Update();
                //World.ChunkManager.GetPendingLightingUpdates(out int lowLight, out int midLight, out int highLight);

                return($"Alex {Alex.Version} ({Alex.FpsMonitor.Value:##} FPS, Chunk Updates: {World.EnqueuedChunkUpdates} queued, {World.ConcurrentChunkUpdates} active" /*, H: {highLight} M: {midLight} L: {lowLight} lighting updates)"*/);
            });
            _debugInfo.AddDebugLeft(() =>
            {
                var pos      = World.Player.KnownPosition;
                var blockPos = pos.GetCoordinates3D();
                return($"RenderPosition: (X={pos.X:F2}, Y={pos.Y:F2}, Z={pos.Z:F2}) / Block: ({blockPos.X:D}, {blockPos.Y:D}, {blockPos.Z:D})");
            });
            _debugInfo.AddDebugLeft(() =>
            {
                var pos = World.Player.KnownPosition;
                return($"Facing: {GetCardinalDirection(pos)} (HeadYaw={pos.HeadYaw:F2}, Yaw={pos.Yaw:F2}, Pitch={pos.Pitch:F2})");
            });
            _debugInfo.AddDebugLeft(() =>
            {
                var pos = World.Player.Velocity;
                return($"Velocity: (X={pos.X:F2}, Y={pos.Y:F2}, Z={pos.Z:F2}) / SpeedFactor: {World.Player.Controller.LastSpeedFactor:F2}");
            });
            _debugInfo.AddDebugLeft(() => $"Vertices: {World.Vertices:N0} ({GetBytesReadable((long)(World.Vertices * VertexPositionNormalTextureColor.VertexDeclaration.VertexStride))})");
            _debugInfo.AddDebugLeft(() => $"IndexBuffer Elements: {World.IndexBufferSize:N0} ({GetBytesReadable(World.IndexBufferSize * 4)})");
            _debugInfo.AddDebugLeft(() => $"Chunks: {World.ChunkCount}, {World.ChunkManager.RenderedChunks}");
            _debugInfo.AddDebugLeft(() => $"Entities: {World.EntityManager.EntityCount}, {World.EntityManager.EntitiesRendered}");
            _debugInfo.AddDebugLeft(() =>
            {
                return($"Biome: {_currentBiome.Name} ({_currentBiomeId})");
            });

            _debugInfo.AddDebugRight(() => Alex.DotnetRuntime);
            //_debugInfo.AddDebugRight(() => MemoryUsageDisplay);
            _debugInfo.AddDebugRight(() => $"RAM: {GetBytesReadable(_ramUsage, 2)}");
            _debugInfo.AddDebugRight(() => $"GPU: {GetBytesReadable(GpuResourceManager.GetMemoryUsage, 2)}");
            _debugInfo.AddDebugRight(() =>
            {
                return
                ($"Threads: {(_threadsUsed):00}/{_maxThreads}\nCompl.ports: {_complPortUsed:00}/{_maxComplPorts}");
            });
            _debugInfo.AddDebugRight(() =>
            {
                if (_raytracedBlock.Y > 0 && _raytracedBlock.Y < 256)
                {
                    var adj = _adjacentBlock.Floor() - _raytracedBlock.Floor();
                    adj.Normalize();

                    var face = adj.GetBlockFace();

                    StringBuilder sb = new StringBuilder();
                    sb.AppendLine($"Target: {_raytracedBlock} Face: {face}");
                    sb.AppendLine(
                        $"Skylight: {World.GetSkyLight(_raytracedBlock)} Face Skylight: {World.GetSkyLight(_adjacentBlock)}");
                    sb.AppendLine(
                        $"Blocklight: {World.GetBlockLight(_raytracedBlock)} Face Blocklight: {World.GetBlockLight(_adjacentBlock)}");
                    sb.AppendLine($"{SelBlock}");

                    if (SelBlock.BlockState != null)
                    {
                        if (SelBlock.BlockState is BlockState s && s.IsMultiPart)
                        {
                            sb.AppendLine($"MultiPart=true");
                        }

                        var dict = SelBlock.BlockState.ToDictionary();
                        foreach (var kv in dict)
                        {
                            sb.AppendLine($"{kv.Key}={kv.Value}");
                        }
                    }

                    return(sb.ToString());
                }
                else
                {
                    return(string.Empty);
                }
            });

            _debugInfo.AddDebugRight(() =>
            {
                var player = World.Player;
                if (player == null || player.HitEntity == null)
                {
                    return(string.Empty);
                }

                var entity = player.HitEntity;
                return($"Hit entity: {entity.EntityId} / {entity.ToString()}");
            });
        }