Skip to content

Commit

Permalink
Permission Levels, Bug Fixes, and Reload Command
Browse files Browse the repository at this point in the history
  • Loading branch information
SkyTech6 committed Sep 19, 2024
1 parent 606bd21 commit dd1a378
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 22 deletions.
34 changes: 31 additions & 3 deletions Commands/Basic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using VampireCommandFramework;
using Unity.Entities;
using ProjectM.Network;
using System.Linq;

namespace CrimsonFAQ.Commands;

Expand All @@ -21,8 +22,9 @@ public void ListFAQs(ChatCommandContext ctx)
{
foreach(KeyResponse kp in Plugin.DB.Responses)
{
if(kp.IsAdmin && !Plugin.DB.IsTrusted(ctx.User)) continue;
reply += kp.Key + "\n";
if(kp.PermissionLevel > 0 && !Plugin.DB.IsTrusted(ctx.User, kp.PermissionLevel)) continue;
string desc = !string.IsNullOrEmpty(kp.Description) ? $"- {kp.Description}" : "";
reply += $"{Settings.Prefix.Value}{kp.Key} {desc}\n";
}
}

Expand All @@ -35,7 +37,6 @@ public void AddTrusted(ChatCommandContext ctx, string playerName = "")
if (string.IsNullOrEmpty(playerName)) ctx.Reply("Must input a player name.");

var entity = PlayerService.GetUserByName(playerName, true);

if (!entity.Equals(Entity.Null) && entity.Has<User>())
{
if (Plugin.DB.AddTrusted(entity.Read<User>()))
Expand Down Expand Up @@ -76,4 +77,31 @@ public void RemoveTrusted(ChatCommandContext ctx, string playerName = "")
ctx.Reply($"Unable to find player named {playerName}");
}
}

[Command("reload", shortHand: "r", description: "reloads the FAQ KeyResponse entries from json", adminOnly: true)]
public void ReloadJSON(ChatCommandContext ctx)
{
var oldResponses = Plugin.DB.Responses.ToArray();

if (Plugin.DB.LoadDatabase())
{
var newResponses = Plugin.DB.Responses;
int updatedResponses = 0;

foreach (var newResponse in newResponses)
{
var oldResponse = oldResponses.FirstOrDefault(r => r.Key == newResponse.Key);
if (oldResponse == null || !oldResponse.Equals(newResponse))
{
updatedResponses++;
}
}

ctx.Reply($"Response collection completed with {updatedResponses} entries updated.");
}
else
{
ctx.Reply($"Failed to retreive a valid collection from the responses.json file, please validate your formatting and values");
}
}
}
10 changes: 9 additions & 1 deletion Plugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using Bloodstone.API;
using CrimsonFAQ.Services;
using CrimsonFAQ.Structs;
using CrimsonFAQ.Systems;
using HarmonyLib;
Expand All @@ -14,14 +15,15 @@ namespace CrimsonFAQ;
[BepInPlugin(MyPluginInfo.PLUGIN_GUID, MyPluginInfo.PLUGIN_NAME, MyPluginInfo.PLUGIN_VERSION)]
[BepInDependency("gg.deca.VampireCommandFramework")]
[BepInDependency("gg.deca.Bloodstone")]
public class Plugin : BasePlugin
public class Plugin : BasePlugin, IRunOnInitialized
{
Harmony _harmony;
internal static Plugin Instance { get; private set; }
public static Settings Settings { get; private set; }
public static Harmony Harmony => Instance._harmony;
public static ManualLogSource LogInstance => Instance.Log;
public static Database DB { get; internal set; }
public static PlayerService PlayerService { get; private set; }

public static string ConfigFiles => Path.Combine(Paths.ConfigPath, "CrimsonFAQ");

Expand Down Expand Up @@ -53,4 +55,10 @@ public override bool Unload()
return true;
}

public void OnGameInitialized()
{
if (VWorld.IsClient) return;

PlayerService = new();
}
}
54 changes: 46 additions & 8 deletions Services/PlayerService.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using Bloodstone.API;
using Il2CppInterop.Runtime;
using ProjectM;
using ProjectM.Network;
using System;
using System.Collections.Generic;
using System.Linq;
using Unity.Collections;
Expand All @@ -11,32 +11,70 @@ namespace CrimsonFAQ.Services;

public class PlayerService
{
static readonly ComponentType[] UserComponent =
{
ComponentType.ReadOnly(Il2CppType.Of<User>())
};
static EntityQuery ActiveUsersQuery;

static EntityQuery AllUsersQuery;

public PlayerService()
{
AllUsersQuery = VWorld.Server.EntityManager.CreateEntityQuery(new EntityQueryDesc {
All = UserComponent,
Options = EntityQueryOptions.IncludeDisabled
});

ActiveUsersQuery = VWorld.Server.EntityManager.CreateEntityQuery(UserComponent);
}

public static IEnumerable<Entity> GetUsers(bool includeDisabled = false)
{
NativeArray<Entity> userEntities = includeDisabled ? AllUsersQuery.ToEntityArray(Allocator.TempJob) : ActiveUsersQuery.ToEntityArray(Allocator.TempJob);
List<Entity> result = new List<Entity>();
try
{
foreach (Entity entity in userEntities)
NativeArray<Entity> userEntities = includeDisabled ? AllUsersQuery.ToEntityArray(Allocator.TempJob) : ActiveUsersQuery.ToEntityArray(Allocator.TempJob);

try
{
if (VWorld.Server.EntityManager.Exists(entity))
foreach (Entity entity in userEntities)
{
yield return entity;
if (VWorld.Server.EntityManager.Exists(entity))
{
result.Add(entity);
}
else
{
Plugin.LogInstance.LogWarning($"Entity {entity.Index} does not exist in EntityManager");
}
}
}
finally
{
userEntities.Dispose();
}
}
finally
catch (Exception ex)
{
userEntities.Dispose();
Plugin.LogInstance.LogError($"Error in GetUsers: {ex.Message}");
Plugin.LogInstance.LogError($"Stack trace: {ex.StackTrace}");
return Enumerable.Empty<Entity>();
}

return result;
}

public static Entity GetUserByName(string playerName, bool includeDisabled = false)
{
Entity userEntity = GetUsers(includeDisabled).FirstOrDefault(entity => entity.Read<User>().CharacterName.Value.ToLower() == playerName.ToLower());
var users = GetUsers(includeDisabled).ToList();

Entity userEntity = users.FirstOrDefault(entity =>
{
var user = entity.Read<User>();
return user.CharacterName.Value.ToLower() == playerName.ToLower();
});

return userEntity != Entity.Null ? userEntity : Entity.Null;
}
}
12 changes: 8 additions & 4 deletions Structs/KeyResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@ public class KeyResponse
[JsonPropertyName("Response")]
public string Response { get; set; }

[JsonPropertyName("Description")]
public string Description { get; set; }

[JsonPropertyName("IsGlobal")]
public bool IsGlobal { get; set; }

[JsonPropertyName("IsAdmin")]
public bool IsAdmin { get; set; }
[JsonPropertyName("PermissionLevel")]
public int PermissionLevel { get; set; } // 0 = User, 1 = Trusted, 2 = Admin

[JsonPropertyName("GlobalCooldownMinutes")]
public int GlobalCooldownMinutes { get; set; }
Expand All @@ -29,12 +32,13 @@ public KeyResponse()
}

[JsonConstructor]
public KeyResponse(string key, string response, bool isGlobal = false, bool isAdmin = false, int globalCooldownMinutes = 0)
public KeyResponse(string key, string response, string description, bool isGlobal = false, int permissionLevel = 0, int globalCooldownMinutes = 0)
{
Key = key;
Response = response;
Description = description;
IsGlobal = isGlobal;
IsAdmin = isAdmin;
PermissionLevel = permissionLevel;
GlobalCooldownMinutes = globalCooldownMinutes;
GlobalLastUsed = DateTime.MinValue;
}
Expand Down
13 changes: 9 additions & 4 deletions Systems/Database.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public static void CreateDatabaseFiles()
{
List<KeyResponse> template = new List<KeyResponse>();

KeyResponse response = new KeyResponse("discord", "Join our discord at discord.gg/RBPesMj", true, false, 30);
KeyResponse response = new KeyResponse("discord", "Join our discord at discord.gg/RBPesMj", "discord link", true, 0, 30);
template.Add(response);

var json = JsonSerializer.Serialize(template, new JsonSerializerOptions { WriteIndented = true});
Expand Down Expand Up @@ -83,11 +83,16 @@ public bool GetResponse(string key, out KeyResponse response)
return false;
}

public bool IsTrusted(User user)
public bool IsTrusted(User user, int keyLevel)
{
if(user.IsAdmin || Trusted.Contains(user.PlatformId.ToString()))
if (keyLevel == 1)
{
return true;
if (user.IsAdmin || Trusted.Contains(user.PlatformId.ToString())) return true;
}

if (keyLevel == 2)
{
if (user.IsAdmin) return true;
}

return false;
Expand Down
4 changes: 2 additions & 2 deletions Systems/Responder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ public static void Respond(VChatEvent message)
var entityManager = VWorld.Server.EntityManager;
var sender = message.SenderUserEntity.Read<User>();

if (response.IsAdmin)
if (response.PermissionLevel > 0)
{
if (!Plugin.DB.IsTrusted(sender)) return;
if (!Plugin.DB.IsTrusted(sender, response.PermissionLevel)) return;
ServerChatUtils.SendSystemMessageToAllClients(entityManager, response.Response);
response.GlobalLastUsed = DateTime.Now;
message.Cancel();
Expand Down

0 comments on commit dd1a378

Please sign in to comment.