diff --git a/ClassicalSharp/2D/Screens/Menu/OptionsScreen.cs b/ClassicalSharp/2D/Screens/Menu/OptionsScreen.cs index 06d7cb234..f7d8833f9 100644 --- a/ClassicalSharp/2D/Screens/Menu/OptionsScreen.cs +++ b/ClassicalSharp/2D/Screens/Menu/OptionsScreen.cs @@ -63,7 +63,7 @@ namespace ClassicalSharp { // Extra stuff !network.IsSinglePlayer ? null : - Make( -140, -150, "Singleplayer physics", Anchor.Centre, OnWidgetClick, + Make( -140, -200, "Singleplayer physics", Anchor.Centre, OnWidgetClick, g => ((SinglePlayerServer)network).physics.Enabled ? "yes" : "no", (g, v) => { ((SinglePlayerServer)network).physics.Enabled = v == "yes"; @@ -72,8 +72,17 @@ namespace ClassicalSharp { Make( 140, -150, "Pushback block placing", Anchor.Centre, OnWidgetClick, g => g.LocalPlayer.PushbackBlockPlacing && g.LocalPlayer.CanPushbackBlocks ? "yes" : "no", - (g, v) => { if( g.LocalPlayer.CanPushbackBlocks) - g.LocalPlayer.PushbackBlockPlacing = v == "yes"; }), + (g, v) => { + if( g.LocalPlayer.CanPushbackBlocks) + g.LocalPlayer.PushbackBlockPlacing = v == "yes"; + }), + + Make( -140, -150, "Show hover names", Anchor.Centre, OnWidgetClick, + g => g.Players.ShowHoveredNames ? "yes" : "no", + (g, v) => { + g.Players.ShowHoveredNames = v == "yes"; + Options.Set( OptionsKey.ShowHoveredNames, v == "yes" ); + }), Make( 0, 5, "Back to menu", Anchor.BottomOrRight, (g, w) => g.SetNewScreen( new PauseScreen( g ) ), null, null ), @@ -91,7 +100,8 @@ namespace ClassicalSharp { new BooleanValidator(), network.IsSinglePlayer ? new BooleanValidator() : null, - new BooleanValidator() + new BooleanValidator(), + new BooleanValidator(), }; okayIndex = buttons.Length - 1; } diff --git a/ClassicalSharp/Entities/EntityList.cs b/ClassicalSharp/Entities/EntityList.cs index 16a18b5de..06b76a34f 100644 --- a/ClassicalSharp/Entities/EntityList.cs +++ b/ClassicalSharp/Entities/EntityList.cs @@ -9,18 +9,23 @@ namespace ClassicalSharp { public const int MaxCount = 256; public Player[] Players = new Player[MaxCount]; public Game game; + uint[] doIntersect; + + /// Whether the names of entities that the player is looking at + /// should be rendered through everything else without depth testing. + public bool ShowHoveredNames; public EntityList( Game game ) { this.game = game; game.Events.ChatFontChanged += ChatFontChanged; + doIntersect = new uint[MaxCount / 32]; } /// Performs a tick call for all player entities contained in this list. public void Tick( double delta ) { for( int i = 0; i < Players.Length; i++ ) { - if( Players[i] != null ) { - Players[i].Tick( delta ); - } + if( Players[i] == null ) continue; + Players[i].Tick( delta ); } } @@ -29,23 +34,57 @@ namespace ClassicalSharp { api.Texturing = true; api.AlphaTest = true; for( int i = 0; i < Players.Length; i++ ) { - if( Players[i] != null ) - Players[i].RenderModel( delta, t ); + if( Players[i] == null ) continue; + Players[i].RenderModel( delta, t ); } api.Texturing = false; api.AlphaTest = false; } - /// Renders the names of all player entities contained in this list. + /// Renders the names of all player entities contained in this list.
+ /// If ShowHoveredNames is false, this method only renders names of entities that are + /// not currently being looked at by the user.
public void RenderNames( IGraphicsApi api, double delta, float t ) { api.Texturing = true; api.AlphaTest = true; + LocalPlayer localP = game.LocalPlayer; + Vector3 eyePos = localP.EyePosition; + Vector3 dir = Utils.GetDirVector( localP.YawRadians, localP.PitchRadians ); + for( int i = 0; i < doIntersect.Length; i++ ) + doIntersect[i] = 0; + for( int i = 0; i < Players.Length; i++ ) { - if( Players[i] != null ) + if( Players[i] == null ) continue; + float t0, t1; + Player p = Players[i]; + + if( !ShowHoveredNames || + !Intersection.RayIntersectsRotatedBox( eyePos, dir, p, out t0, out t1 ) ) { + Players[i].RenderName(); + } else { + doIntersect[i >> 5] |= (uint)(1 << (i & 0x1F)); + } + } + api.Texturing = false; + api.AlphaTest = false; + } + + public void RenderHoveredNames( IGraphicsApi api, double delta, float t ) { + if( !ShowHoveredNames ) return; + api.Texturing = true; + api.AlphaTest = true; + api.DepthTest = false; + + for( int i = 0; i < Players.Length; i++ ) { + if( Players[i] == null ) continue; + + bool draw = (doIntersect[i >> 5] & (uint)(1 << (i & 0x1F))) != 0; + if( draw ) Players[i].RenderName(); } api.Texturing = false; api.AlphaTest = false; + api.DepthTest = true; } void ChatFontChanged( object sender, EventArgs e ) { @@ -74,6 +113,7 @@ namespace ClassicalSharp { for( int i = 0; i < Players.Length - 1; i++ ) { // -1 because we don't want to pick against local player Player p = Players[i]; if( p == null ) continue; + float t0, t1; if( Intersection.RayIntersectsRotatedBox( eyePos, dir, p, out t0, out t1 ) ) { if( t0 < closestDist && closestDist < localP.ReachDistance ) { @@ -88,7 +128,7 @@ namespace ClassicalSharp { /// Gets or sets the player entity for the specified id. public Player this[int id] { get { return Players[id]; } - set { + set { Players[id] = value; if( value != null ) value.ID = (byte)id; diff --git a/ClassicalSharp/Game/Game.cs b/ClassicalSharp/Game/Game.cs index 2ce669871..824aaff5e 100644 --- a/ClassicalSharp/Game/Game.cs +++ b/ClassicalSharp/Game/Game.cs @@ -113,6 +113,7 @@ namespace ClassicalSharp { Options.Load(); AcceptedUrls.Load(); + Players.ShowHoveredNames = Options.GetBool( OptionsKey.ShowHoveredNames, true ); ViewDistance = Options.GetInt( OptionsKey.ViewDist, 16, 4096, 512 ); InputHandler = new InputHandler( this ); Chat = new ChatLog( this ); @@ -244,6 +245,7 @@ namespace ClassicalSharp { MapRenderer.Render( e.Time ); SelectionManager.Render( e.Time ); WeatherRenderer.Render( e.Time ); + Players.RenderHoveredNames( Graphics, e.Time, t ); bool left = IsMousePressed( MouseButton.Left ); bool middle = IsMousePressed( MouseButton.Middle ); diff --git a/ClassicalSharp/Utils/Options.cs b/ClassicalSharp/Utils/Options.cs index 4f741b815..2d99bd199 100644 --- a/ClassicalSharp/Utils/Options.cs +++ b/ClassicalSharp/Utils/Options.cs @@ -15,6 +15,7 @@ namespace ClassicalSharp { public const string ArialChatFont = "arialchatfont"; public const string DefaultTexturePack = "defaulttexpack"; public const string SingleplayerPhysics = "singleplayerphysics"; + public const string ShowHoveredNames = "showhoverednames"; public const string MouseLeft = "mouseleft"; public const string MouseMiddle = "mousemiddle";