PazerOP / tf2_bot_detector

Automatically detects and votekicks cheaters/bots in TF2 casual.
MIT License
403 stars 54 forks source link

Use custom font mod to display non-printing unicode characters in the Vote UI? #304

Open andy013 opened 3 years ago

andy013 commented 3 years ago

I had the idea that perhaps we could use a custom font to display certain characters that the bots frequently use. This would prevent unicode spoofing as it would be easy to tell 2 players apart from within the vote UI. I'm not even sure if this is possible or not. I tried to do it myself but I could only replace latin letters and wasn't able to get any special characters or zero-width characters to be substituted.

If it is possible it might be a quick way of reducing the effectiveness of unicode spoofing for now. You could add the fonts as a mod just like the app already does for making the vote failed UI not display.

ClusterConsultant commented 3 years ago

Without a custom font I am not sure if this would be possible as most "real" fonts display Unicode as defined by the spec.

I had little success getting any font changes to apply to Unicode.

andy013 commented 3 years ago

I managed to get something working, I'm still testing it for now. If you have a custom font, you must specify the range within the .res files for your language on steam or else it will splice your font together with Tahoma and only use your font for 0x0000 - 0x00FF and Tahoma for the rest. This means most "Unicode characters" won't change.

If you specify the full range of characters (0x000 - 0xFFFF) then this will be overridden and it will try to use your font for everything. E.g.

"font" "resource/fonts/CustomFont.otf"
"name" "CustomFont"
"english" 
{
    "range" "0x0000 0xFFFF"
}

There still seems to be a fall back though. If your font doesn't include the character then windows will use another font installed on your system to try and display it. Just by specifying this range on my system I was able to get some more characters to appear as it started using a different font instead of Tahoma.

I've also noticed that windows seems to replace a bunch of non-printing characters with the space character. For example, U+200F is replaced by U+0020 but with altered spacing between the characters. I think it's the windows APIs that are doing it anyway, it could be something in my font file that I can't figure out how to change. This means I've had to modify the space character in my font to make it obvious when it's used or else these characters won't be perceptible to the user. This makes the font kinda ugly and not really usable for anywhere outside of the voting hud.

andy013 commented 3 years ago

I managed to get this fully working now. I had to end up creating a source mod to get all the characters to print out on the screen so I could test my font. It turns out creating a font is a little more involved than I thought. I had to modify the GSUB table a bit to fool the engine into thinking my font supported certain scripts. It took a bunch of trial and error but I got there in the end.

Here's a quick screenshot of what the font looks like rendering some of the bot names I have encountered:

image

You can easily tell the difference between a player who doesn't have these strange characters and a bot who copied their name and added an invisible character.

At the moment it's just a very basic font substitution, but I think I might try and modify the votehud element more to improve it. If we are going to overwrite it anyway, there doesn't seem to be much reason to keep the default layout, it's quite cluttered and could be improved a lot I think.

I was thinking of having both the usernames print out in 2 different fonts. Once in this custom font and another in a regular font. That way you will be able to tell the difference between players who have a bunch of unicode characters in their name, rather than just seeing a bunch of rectangles.

One limitation of this font is that it doesn't work as well in RichText vgui elements like the chat box. For some reason the source engine seems to handle those differently from the vgui Lables that are used in the rest of the HUD. The font still works but certain characters are rendered as spaces and so can't be differentiated from each other. I don't think this is a big deal. I actually prefer seeing the regular fonts in the chat and scoreboard so I can tell what the usernames appear like to most other players.

Is this something you guys are interested in including with the tool? I could create this as a separate mod on it's own.

The biggest problem I can see right now is that in order to add a custom font you need to modify the clientscheme.res file. This is used by other custom HUDs so it wouldn't be compatible with them. The only way around this I can see would be if the bot detector tool checked the custom folder on start up and added the needed lines into the scheme file if one was found. I think this is possible and it would make the mod compatible with pretty much any custom hud but it would only work if you launched the game via the bot detector.

incontestableness commented 3 years ago

TL;DR but if this can be used to replace the font in the vote dialogs I'd say it's worth implementing as an option, granted that it's not too much trouble. IIRC @crazygunman did some custom stuff to stop the vote dialog showing up and playing the sound when a vote can't be called yet. Bundling both of these with the tool could be beneficial. Maybe even combine them if that makes more sense.

ClusterConsultant commented 3 years ago

Moeb and myself have taken over the custom hud portions of this project since gunman has become busy with other stuff. Currently that vote failed eraser is included in the nightly version of the tool. There are some plans to add automated custom file merging to account for custom huds but it is at a pretty low priority since the vast majority of players use the stock hud.

If the font was uploaded under a reasonable license testing could be done to incorporate it into the plugin system (currently located under Settings > Mods).

andy013 commented 3 years ago

https://github.com/andy013/votehud_custom_font

Here is a very simple mod I set up that uses the font. Just put it in a folder called votehud_custom_font in your tf/custom directory.

The font is just an edited version of NotoMono. I chose that because it was monospaced (easy to compare + count characters) and free to modify and distribute. It does look a little bit grainy in the source engine though. I could probably edit another font if it was required.

This mod will only work if your steam language is set to English.

The most important thing to be aware of when using the font is how to load it into the engine. At the very bottom of clientscheme.res you will see the entry for the font. It must have the range value set to "range" "0x021 0xFFFF" for your language in order for it to work correctly.

This is a bit of a hack to get spaces to render correctly but all other space-like characters to render as a rectangle. The font uses the first 32 characters from Tahoma which includes the space, but then the rest of the range is covered by the font itself. If you don't set the range properly then spaces will look like rectangles and it makes it a bit ugly and hard to read.

There are 2 "unicode characters" in the font. One is an open rectangle and the other is a filled rectangle. I tried to use the open rectangle for most characters and only used the filled rectangle for characters that could appear as zero-width. This is to try and make them more obvious when they are behind another character. Unfortunately there are some glyphs that are used for both spacing and zero-width characters, in those cases I just used the filled rectangle. If you just use the same glyph for everything then it would be impossible to tell when a zero-width character was drawn on top of another unicode character.

Barmem commented 3 years ago

Ok, limiting it to only English is kinda a problem

andy013 commented 3 years ago

@Barmem It's not limited to only English. It's just that simple mod I made only works in English for now. You can go through and add a range entry for every language you like. Although many other languages won't even be displayed in this font.

andy013 commented 3 years ago

I updated the mod a little bit. I managed to get it to draw the names in both my font and the default font. That way you can tell the difference between players who have all unicode characters in their name that just render as boxes in my font.

Here's an example:

I had to leave enough space for even the longest names. Most of the time you just need to glance at the big font quickly to get all the information you need.

andy013 commented 3 years ago

Unfortunately the updates I did break when you change resolution. I think I'm going to have to create a few different versions for common resolutions. I fixed this, see the edit below.

The reason for this is in order to get the name to print out in 2 different fonts I had to use a bit of a hack, The 3 strings that are used for "Kick" "player name" and "reason" are all part of 1 string and 1 label. This means they all must be the same font, same size etc. I got around this by adding a bunch of new lines to the label and then adding duplicate labels that are offset so that only the string I want is drawn. This works at 1080p right now but when you change resolution everything resizes and I think the ratio between the positioning and the new line height changes and the labels are drawn in the wrong place.

I could go back to a simple font substitution but I really like the version I have working now. It's really nice to be able to just glance at the vote panel and immediately get all the info you need. I'm thinking right now I'll make 4-5 different versions for the most common resolutions and that should cover most people.

EDIT: I managed to fix this now without having to resort to multiple different versions. The problem was the default font scaled with resolution, once I set it to a fixed size and played about with the textAlignment I got it to work fine. The mod should now work for all resolutions. 👍

UAVXP commented 3 years ago

Very nice, @andy013 ! I'm using your mod and it's now too easy to detect the right and wrong votekicks) Also the manual vote menu has font changes too, a good feature