Add a GM tag to users who have UserPermissions
From NetGore Wiki
| Difficulty | |
|---|---|
| Topics | Game content,Entities |
| (view all tutorials) | |
This is intended as a guide for people who want to add "[INSERT_CUSTOM_TAG]" tags to users names in-game i.e. for moderators wanting to show the different levels of permissions their game has. The most famous example being "[GM] DarkSummon", where DarkSummon is the game moderators username.
This tutorial could also start the process of a new tutorial, involving adding and changing user permissions in NetGore.
Contents |
Creating the PropertySync Class
Ok, so the first thing we need to do is create a 'PropertySyncUserPermissions' class. This is so we can add the [SyncValue] to the UserPermission property in NetGore, which will handle all the synchronising of data between the client and server. For more information, see Synchronizing Values. The class needs to be saved in the DemoGame project.
Navigate to the 'DemoGame' project and then Right click the 'IO' folder and select 'Add --> Class..' then simply click 'Class' and name it "PropertySyncUserPermissions.cs". Finish by clicking 'Add'.
Remove the generated code with the following:
using System.Linq; using DemoGame; namespace NetGore.IO.PropertySync { /// <summary> /// Implementation of a <see cref="PropertySyncBase{T}"/> that handles synchronizing an <see cref="UserPermissions"/>. /// </summary> [PropertySyncHandler(typeof(UserPermissions))] public sealed class PropertySyncUserPermissions : PropertySyncBase<UserPermissions> { /// <summary> /// Initializes a new instance of the <see cref="PropertySyncUserPermissions"/> class. /// </summary> /// <param name="syncValueAttributeInfo">The <see cref="SyncValueAttributeInfo"/>.</param> public PropertySyncUserPermissions(SyncValueAttributeInfo syncValueAttributeInfo) : base(syncValueAttributeInfo) { } /// <summary> /// When overridden in the derived class, reads a value with the specified name from an IValueReader. /// </summary> /// <param name="name">Name of the value.</param> /// <param name="reader">IValueReader to read from.</param> /// <returns>Value read from the IValueReader.</returns> protected override UserPermissions Read(string name, IValueReader reader) { return reader.ReadEnum<UserPermissions>(name); } /// <summary> /// When overridden in the derived class, writes a value to an IValueWriter with the specified name. /// </summary> /// <param name="name">Name of the value.</param> /// <param name="writer">IValueWriter to write to.</param> /// <param name="value">Value to write.</param> protected override void Write(string name, IValueWriter writer, UserPermissions value) { writer.WriteEnum(name, value); } } }
DemoGame.Server.World.Map.Entities.Characters.Character
Next we need to add a Permissions property to the Character class in the server.
Find:
string _name;
Just After, Add:
<nowiki> /// <summary> /// Gets or sets the user permissions of the character. /// </summary> public override UserPermissions Permissions { get { // Default to None return UserPermissions.None; } set { // Derived classes must override to allow for additional permissions (e.g.: NPCs won't track permisisons, users will) } } </nowiki>
DemoGame.Server.World.Map.Entities.Characters.User
Next we need to change the Permissions property that is in the User class in the server.
Find:
/// <summary> /// Gets the <see cref="UserPermissions"/> level for this user. /// </summary> public UserPermissions Permissions { get { var acc = UserAccount; if (acc == null) return UserPermissions.None; return acc.Permissions; } }
Replace With:
/// <summary> /// Gets the <see cref="UserPermissions"/> level for this user. /// </summary> public override UserPermissions Permissions { get { var acc = UserAccount; if (acc == null) return UserPermissions.None; return acc.Permissions; } set { var acc = UserAccount; if (acc == null) { return; } acc.SetPermissions(value); } }
DemoGame.World.Map.Entities.CharacterEntity
Next we need to add another Permissions property which will act as a getter and setter for the Permissions value. Note that this is where we use the [SyncValue] attribute which will enable NetGore to do all the hard work for us!
Find:
[SyncValue] public virtual string Name { get; set; }
Just After, Add:
/// <summary> /// Gets or sets the permission of the CharacterEntity. /// </summary> [SyncValue] public abstract UserPermissions Permissions { get; set; }
DemoGame.Client.World.Map.Entities.Character
And finally, we add the code to the client which displays the [TAG] on-screen. I'll post an example of the whole property, where it simply displays a "[GM]" tag in front of all users who have special permissions, which are:
Moderator LesserAdmin Admin Owner
A user who doesn't have a special permission is defined as 'None', which is default for all new users.
Find:
/// <summary> /// Draws the Character's name. /// </summary> /// <param name="sb"><see cref="ISpriteBatch"/> to draw to.</param> /// <param name="font">The <see cref="Font"/> to use for the name text. May be null.</param> protected virtual void DrawName(ISpriteBatch sb, Font font) { // Ensure we have a valid font and name first if (font == null || string.IsNullOrEmpty(Name)) return; // Get the size of the name var nameSize = GetNameSize(); // Get the character's center var namePos = DrawPosition; // Center horizontally namePos.X += Size.X / 2f; // Move the left side of the name to the center of the character namePos.X -= (float)Math.Round(nameSize.X / 2f); // Move the center to the center of the character // Move up above the character's head (height of the text, with a little extra offset) namePos.Y -= nameSize.Y + 4f; // Draw sb.DrawStringShaded(font, Name, namePos, Color.Green, Color.Black); }
Replace With:
/// <summary> /// Draws the Character's name. /// </summary> /// <param name="sb"><see cref="ISpriteBatch"/> to draw to.</param> /// <param name="font">The <see cref="Font"/> to use for the name text. May be null.</param> protected virtual void DrawName(ISpriteBatch sb, Font font) { // Ensure we have a valid font and name first if (font == null || string.IsNullOrEmpty(Name)) return; // Get the size of the name var nameSize = GetNameSize(); string GM = "[GM] "; var gmSize = NameFont.MeasureString(GM); // Get the character's center var namePos = DrawPosition; // Center horizontally namePos.X += Size.X / 2f; // Move the left side of the name to the center of the character namePos.X -= (float)Math.Round(nameSize.X / 2f); // Move the center to the center of the character // Move up above the character's head (height of the text, with a little extra offset) namePos.Y -= nameSize.Y + 4f; var gmPos = DrawPosition; gmPos.X = namePos.X - gmSize.X; gmPos.Y = namePos.Y; // Check the users permission level if (Permissions.IsSet(UserPermissions.Moderator)) { // Draw sb.DrawStringShaded(font, GM, gmPos, Color.Red, Color.Black); sb.DrawStringShaded(font, Name, namePos, Color.Yellow, Color.Black); } else { sb.DrawStringShaded(font, Name, namePos, Color.Green, Color.Black); } }
From this, you can add more if statements for each individual permission that you have set. You can also have it display in various colours and even different tag names i.e. [MOD], [Owner], [Event], etc.
Lastly, we need to add one more block of code to act as another getter and setter for the Permission value on the client.
Find:
/// <summary> /// Gets the position for the Camera to focus on this Character. /// </summary> /// <param name="camera">The <see cref="ICamera2D"/> to get the position for.</param> /// <returns> /// Position for the Camera to focus on this Character. /// </returns> public Vector2 GetCameraPos(ICamera2D camera) { var pos = DrawPosition + (Size / 2.0f) - (camera.Size / 2.0f); return pos.Round(); }
Just After, Add:
UserPermissions _permissions; /// <summary> /// Gets or sets the <see cref="UserPermissions"/> for this character. /// Should only be set automatically by PropertySync; never manually. /// </summary> public override UserPermissions Permissions { get { return _permissions; } set { _permissions = value; } }
Database Values
If you want to change an account to have a different permission level, in the database go to the 'account' table and change the values of the 'permissions' column. Here are the values for each permission level:
None: 0 Moderator: 1 LesserAdmin: 3 Admin: 7 Owner: 15