перенос файлов сервера из папки White в _White
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
using Content.Server.Administration;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Console;
|
||||
|
||||
namespace Content.Server._White.Reputation.Commands;
|
||||
|
||||
[AdminCommand(AdminFlags.Admin)]
|
||||
public sealed class GetPlayerReputationCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "getreput";
|
||||
public string Description => "Get player's reputation value.";
|
||||
public string Help => "Usage: getreput {ckey}";
|
||||
public async void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var playerManager = IoCManager.Resolve<IPlayerManager>();
|
||||
var repManager = IoCManager.Resolve<ReputationManager>();
|
||||
|
||||
if (args.Length < 1)
|
||||
{
|
||||
shell.WriteLine($"Not enough arguments.\n{Help}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!playerManager.TryGetPlayerDataByUsername(args[0], out var playerData))
|
||||
{
|
||||
shell.WriteLine($"Couldn't find player: {args[0]}.");
|
||||
return;
|
||||
}
|
||||
|
||||
var uid = playerData.UserId;
|
||||
|
||||
var value = await repManager.GetPlayerReputation(uid);
|
||||
|
||||
if (value == null)
|
||||
{
|
||||
shell.WriteLine("Couldn't get player's reputation.");
|
||||
return;
|
||||
}
|
||||
|
||||
shell.WriteLine($"Reputation of {args[0]}: {value}");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using Content.Server.Administration;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Console;
|
||||
|
||||
namespace Content.Server._White.Reputation.Commands;
|
||||
|
||||
[AdminCommand(AdminFlags.Host)]
|
||||
public sealed class ModifyReputationCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "modifyreput";
|
||||
public string Description => "Add the value to user's reputation.";
|
||||
public string Help => "Usage: modifyreput {ckey} {valueToAdd}";
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var playerManager = IoCManager.Resolve<IPlayerManager>();
|
||||
var repManager = IoCManager.Resolve<ReputationManager>();
|
||||
|
||||
if (args.Length < 2)
|
||||
{
|
||||
shell.WriteLine($"Not enough arguments.\n{Help}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!playerManager.TryGetPlayerDataByUsername(args[0], out var playerData))
|
||||
{
|
||||
shell.WriteLine($"Couldn't find player: {args[0]}.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!float.TryParse(args[1], out var value))
|
||||
{
|
||||
shell.WriteLine($"Invalid value: {args[1]}.");
|
||||
return;
|
||||
}
|
||||
|
||||
var uid = playerData.UserId;
|
||||
var admin = playerData.UserName;
|
||||
|
||||
repManager.ModifyPlayerReputation(uid, value, admin);
|
||||
|
||||
shell.WriteLine($"Added {args[1]} to the reputation of {args[0]}.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using Content.Server.Administration;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Console;
|
||||
|
||||
namespace Content.Server._White.Reputation.Commands;
|
||||
|
||||
[AdminCommand(AdminFlags.Host)]
|
||||
public sealed class SetReputationCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "setreput";
|
||||
public string Description => "Sets the reputation to the certain value.";
|
||||
public string Help => "Usage: setrep {ckey} {value}";
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var playerManager = IoCManager.Resolve<IPlayerManager>();
|
||||
var repManager = IoCManager.Resolve<ReputationManager>();
|
||||
|
||||
if (args.Length < 2)
|
||||
{
|
||||
shell.WriteLine($"Not enough arguments.\n{Help}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!playerManager.TryGetPlayerDataByUsername(args[0], out var playerData))
|
||||
{
|
||||
shell.WriteLine($"Couldn't find player: {args[0]}.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!float.TryParse(args[1], out var value))
|
||||
{
|
||||
shell.WriteLine($"Invalid value: {args[1]}.");
|
||||
return;
|
||||
}
|
||||
|
||||
var uid = playerData.UserId;
|
||||
var admin = playerData.UserName;
|
||||
|
||||
repManager.SetPlayerReputation(uid, value, admin);
|
||||
|
||||
shell.WriteLine($"Set reputation of {args[0]} to {args[1]}.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Shared.Console;
|
||||
|
||||
namespace Content.Server._White.Reputation.Commands;
|
||||
|
||||
[AnyCommand]
|
||||
public sealed class ShowReputationCommand : IConsoleCommand
|
||||
{
|
||||
[Dependency] private readonly ReputationManager _repManager = default!;
|
||||
|
||||
public string Command => "showreput";
|
||||
public string Description => "Узнать свою репутацию.";
|
||||
public string Help => "Использование: showreput";
|
||||
public async void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
if (shell.Player == null)
|
||||
return;
|
||||
|
||||
var value = await _repManager.GetPlayerReputation(shell.Player.UserId);
|
||||
if (value == null)
|
||||
{
|
||||
shell.WriteLine("Не удалось получить данные о репутации. Обратитесь к кодерам или попробуйте ещё раз.");
|
||||
return;
|
||||
}
|
||||
|
||||
shell.WriteLine($"Ваша репутация: {value}");
|
||||
}
|
||||
}
|
||||
259
Content.Server/_White/Reputation/ReputationManager.cs
Normal file
259
Content.Server/_White/Reputation/ReputationManager.cs
Normal file
@@ -0,0 +1,259 @@
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.Database;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Shared.GameTicking;
|
||||
using Content.Shared.White.Reputation;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server._White.Reputation;
|
||||
|
||||
public sealed class ReputationManager : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IServerDbManager _db = default!;
|
||||
[Dependency] private readonly IServerNetManager _netMgr = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly ILogManager _logManager = default!;
|
||||
[Dependency] private readonly IPlayerLocator _locator = default!;
|
||||
|
||||
private readonly Dictionary<NetUserId, ReputationInfo> _cacheReputation = new();
|
||||
private readonly Dictionary<NetUserId, DateTime> _playerConnectionTime = new();
|
||||
|
||||
private ISawmill _sawmill = default!;
|
||||
private const string SawmillId = "reputation.logs";
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_netMgr.RegisterNetMessage<ReputationNetMsg>();
|
||||
|
||||
_netMgr.Connecting += OnConnecting;
|
||||
_netMgr.Connected += OnConnected;
|
||||
|
||||
SubscribeLocalEvent<RoundRestartCleanupEvent>(OnRoundRestartCleanup);
|
||||
SubscribeLocalEvent<UpdateCachedReputationEvent>(UpdateCachedReputation);
|
||||
SubscribeLocalEvent<PlayerBeforeSpawnEvent>(OnPlayerSpawn);
|
||||
}
|
||||
|
||||
#region Cache
|
||||
|
||||
private void OnPlayerSpawn(PlayerBeforeSpawnEvent ev)
|
||||
{
|
||||
_playerConnectionTime[ev.Player.UserId] = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
private void OnConnected(object? sender, NetChannelArgs e)
|
||||
{
|
||||
_cacheReputation.TryGetValue(e.Channel.UserId, out var info);
|
||||
var msg = new ReputationNetMsg() { Info = info };
|
||||
_netMgr.ServerSendMessage(msg, e.Channel);
|
||||
}
|
||||
|
||||
private async Task OnConnecting(NetConnectingArgs e)
|
||||
{
|
||||
var uid = e.UserId;
|
||||
var value = await GetPlayerReputation(uid);
|
||||
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
var info = new ReputationInfo() { Value = value.Value };
|
||||
_cacheReputation[e.UserId] = info;
|
||||
}
|
||||
|
||||
private async void UpdateCachedReputation(UpdateCachedReputationEvent ev)
|
||||
{
|
||||
var player = ev.Player;
|
||||
if (!_cacheReputation.TryGetValue(player, out _))
|
||||
return;
|
||||
|
||||
var value = await GetPlayerReputation(player);
|
||||
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
var info = new ReputationInfo() { Value = value.Value };
|
||||
_cacheReputation[player] = info;
|
||||
}
|
||||
|
||||
private void OnRoundRestartCleanup(RoundRestartCleanupEvent ev)
|
||||
{
|
||||
var connectedPlayers = _netMgr.Channels.Select(channel => channel.UserId).ToList();
|
||||
var newDictionary = _cacheReputation
|
||||
.Where(player => connectedPlayers.Contains(player.Key))
|
||||
.ToDictionary(player => player.Key, player => player.Value);
|
||||
|
||||
_cacheReputation.Clear();
|
||||
_playerConnectionTime.Clear();
|
||||
|
||||
foreach (var kvp in newDictionary)
|
||||
{
|
||||
_cacheReputation.Add(kvp.Key, kvp.Value);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region PublicApi
|
||||
|
||||
public async void SetPlayerReputation(NetUserId player, float value, string? admin = null)
|
||||
{
|
||||
var preValue = await GetPlayerReputation(player);
|
||||
if (preValue == null)
|
||||
return;
|
||||
|
||||
var guid = player.UserId;
|
||||
await SetPlayerReputationTask(guid, value);
|
||||
|
||||
RaiseLocalEvent(new UpdateCachedReputationEvent(player));
|
||||
await LogReputationChange(player, preValue.Value, false, admin);
|
||||
}
|
||||
|
||||
public async void ModifyPlayerReputation(NetUserId player, float value, string? admin = null)
|
||||
{
|
||||
var preValue = await GetPlayerReputation(player);
|
||||
if (preValue == null)
|
||||
return;
|
||||
|
||||
var guid = player.UserId;
|
||||
await ModifyPlayerReputationTask(guid, value);
|
||||
|
||||
RaiseLocalEvent(new UpdateCachedReputationEvent(player));
|
||||
await LogReputationChange(player, preValue.Value, true, admin);
|
||||
}
|
||||
|
||||
public async Task<float?> GetPlayerReputation(NetUserId player)
|
||||
{
|
||||
var guid = player.UserId;
|
||||
return await GetPlayerReputationTask(guid);
|
||||
}
|
||||
|
||||
public bool GetCachedPlayerReputation(NetUserId player, out float? value)
|
||||
{
|
||||
var success = _cacheReputation.TryGetValue(player, out var info);
|
||||
value = info?.Value;
|
||||
return success;
|
||||
}
|
||||
|
||||
public bool GetCachedPlayerConnection(NetUserId player, out DateTime date)
|
||||
{
|
||||
var success = _playerConnectionTime.TryGetValue(player, out var dateTime);
|
||||
date = dateTime;
|
||||
return success;
|
||||
}
|
||||
|
||||
public int GetPlayerWeight(float rep)
|
||||
{
|
||||
// Min-max return values
|
||||
const int minValue = 30;
|
||||
const int maxValue = 50;
|
||||
|
||||
// Min-max reputation values
|
||||
const float minReputation = 0f;
|
||||
const float maxReputation = 1000f;
|
||||
|
||||
if (rep < minReputation)
|
||||
return 20;
|
||||
|
||||
var normalizedReputation = (rep - minReputation) / (maxReputation - minReputation);
|
||||
var result = (int)(minValue + (normalizedReputation * (maxValue - minValue)));
|
||||
|
||||
result = Math.Max(minValue, Math.Min(maxValue, result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public ICommonSession PickPlayerBasedOnReputation(List<ICommonSession> prefList)
|
||||
{
|
||||
var list = new List<ICommonSession>();
|
||||
|
||||
foreach (var session in prefList)
|
||||
{
|
||||
if (!GetCachedPlayerReputation(session.UserId, out var value))
|
||||
continue;
|
||||
|
||||
if (value == null)
|
||||
continue;
|
||||
|
||||
var weight = GetPlayerWeight(value.Value);
|
||||
|
||||
for (var i = 0; i < weight; i++)
|
||||
{
|
||||
list.Add(session);
|
||||
}
|
||||
}
|
||||
|
||||
if (list.Count == 0)
|
||||
return _random.Pick(prefList);
|
||||
|
||||
var number = _random.Next(list.Count - 1);
|
||||
return list[number];
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private
|
||||
|
||||
private async Task SetPlayerReputationTask(Guid player, float value)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _db.SetPlayerReputation(player, value);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Nope
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ModifyPlayerReputationTask(Guid player, float value)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _db.ModifyPlayerReputation(player, value);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Nope
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<float?> GetPlayerReputationTask(Guid player)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await _db.GetPlayerReputation(player);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LogReputationChange(NetUserId user, float preValue, bool modify, string? admin = null)
|
||||
{
|
||||
var located = await _locator.LookupIdAsync(user);
|
||||
if (located == null)
|
||||
return;
|
||||
|
||||
var newValue = await GetPlayerReputation(user);
|
||||
if (newValue == null)
|
||||
return;
|
||||
|
||||
var adminName = admin != null ? $" by {admin}" : "";
|
||||
|
||||
var msg = modify
|
||||
? $"Reputation of {located.Username} was modified from {preValue} to {newValue.Value}{adminName}."
|
||||
: $"Reputation of {located.Username} was set from {preValue} to {newValue.Value}{adminName}.";
|
||||
|
||||
_sawmill = _logManager.GetSawmill(SawmillId);
|
||||
_sawmill.Info(msg);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
184
Content.Server/_White/Reputation/ReputationSystem.cs
Normal file
184
Content.Server/_White/Reputation/ReputationSystem.cs
Normal file
@@ -0,0 +1,184 @@
|
||||
using System.Linq;
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.Objectives;
|
||||
using Content.Server.Roles;
|
||||
using Content.Server._White.AspectsSystem.Base;
|
||||
using Content.Shared.Mind;
|
||||
using Content.Shared.Mind.Components;
|
||||
using Content.Server._White.PandaSocket.Main;
|
||||
using Content.Shared.Mobs;
|
||||
using Content.Shared.Mobs.Components;
|
||||
using Content.Shared.White;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server._White.Reputation;
|
||||
|
||||
public sealed class ReputationSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly ReputationManager _repManager = default!;
|
||||
[Dependency] private readonly GameTicker _gameTicker = default!;
|
||||
[Dependency] private readonly IPlayerLocator _locator = default!;
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
[Dependency] private readonly RoleSystem _roles = default!;
|
||||
[Dependency] private readonly ObjectivesSystem _objectives = default!;
|
||||
|
||||
private const int MinPlayers = 15;
|
||||
private const int MinRoundLength = 25;
|
||||
private const int MinTimePlayerConnected = 20;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<UtkaBannedEvent>(ModifyReputationOnPlayerBanned);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to modify reputation on round end and then returns it's new value and delta value if successful.
|
||||
/// </summary>
|
||||
/// <param name="name">Player to get new values for.</param>
|
||||
/// <param name="newValue">Modified player's reputation value.</param>
|
||||
/// <param name="deltaValue"></param>
|
||||
/// <returns>Success in modifying player's reputation.</returns>
|
||||
public bool TryModifyReputationOnRoundEnd(string name, out float? newValue, out float? deltaValue)
|
||||
{
|
||||
newValue = null;
|
||||
deltaValue = null;
|
||||
|
||||
var repEnabled = _cfg.GetCVar(WhiteCVars.ReputationEnabled);
|
||||
if (!repEnabled)
|
||||
return false;
|
||||
|
||||
if (!_playerManager.TryGetSessionByUsername(name, out var session) || session.AttachedEntity == null)
|
||||
return false;
|
||||
|
||||
if (!TryCalculatePlayerReputation(session.AttachedEntity.Value, out var delta))
|
||||
return false;
|
||||
|
||||
var uid = session.UserId;
|
||||
_repManager.GetCachedPlayerReputation(uid, out var value);
|
||||
|
||||
if (value == null)
|
||||
return false;
|
||||
|
||||
var longConnected = _repManager.GetCachedPlayerConnection(uid, out var date)
|
||||
&& DateTime.UtcNow - date >= TimeSpan.FromMinutes(MinTimePlayerConnected);
|
||||
var longRound = _gameTicker.RoundDuration() >= TimeSpan.FromMinutes(MinRoundLength);
|
||||
var enoughPlayers = _playerManager.PlayerCount >= MinPlayers;
|
||||
|
||||
if (delta != 0 && longRound && longConnected && enoughPlayers)
|
||||
{
|
||||
_repManager.ModifyPlayerReputation(uid, delta);
|
||||
}
|
||||
|
||||
deltaValue = longRound && longConnected && enoughPlayers ? delta : 0f;
|
||||
newValue = value + deltaValue;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool TryCalculatePlayerReputation(EntityUid entity, out float deltaValue)
|
||||
{
|
||||
deltaValue = 0f;
|
||||
var aspect = false;
|
||||
|
||||
if (!TryComp<MobStateComponent>(entity, out var state) || state.CurrentState is MobState.Dead or MobState.Invalid)
|
||||
return true;
|
||||
|
||||
var ruleEnt = _gameTicker.GetActiveGameRules()
|
||||
.Where(HasComp<AspectComponent>)
|
||||
.FirstOrNull();
|
||||
|
||||
if (ruleEnt != null)
|
||||
{
|
||||
if (TryComp<AspectComponent>(ruleEnt, out var comp))
|
||||
{
|
||||
deltaValue += comp.Weight switch
|
||||
{
|
||||
3 => 2f,
|
||||
2 => 3f,
|
||||
1 => 4f,
|
||||
_ => 0f
|
||||
};
|
||||
aspect = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!aspect)
|
||||
deltaValue += 1f;
|
||||
|
||||
if (TryComp<MindContainerComponent>(entity, out var mind)
|
||||
&& mind.Mind != null
|
||||
&& _roles.MindIsAntagonist(mind.Mind)
|
||||
&& TryComp(mind.Mind, out MindComponent? mindComp))
|
||||
{
|
||||
var objCompleted = 0;
|
||||
var totalObj = 0;
|
||||
foreach (var obj in mindComp.Objectives)
|
||||
{
|
||||
totalObj++;
|
||||
|
||||
var info = _objectives.GetInfo(obj, mind.Mind.Value, mindComp);
|
||||
|
||||
if (info is {Progress: > 0.99f})
|
||||
objCompleted++;
|
||||
}
|
||||
|
||||
if (aspect)
|
||||
{
|
||||
if (objCompleted == totalObj)
|
||||
deltaValue += 1f + objCompleted;
|
||||
else
|
||||
deltaValue += 1f + objCompleted * 0.5f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (objCompleted == totalObj)
|
||||
deltaValue += 2f + objCompleted * 0.5f;
|
||||
else
|
||||
deltaValue += objCompleted * 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private async void ModifyReputationOnPlayerBanned(UtkaBannedEvent ev)
|
||||
{
|
||||
NetUserId uid;
|
||||
float value;
|
||||
|
||||
if (ev.Bantype == "server")
|
||||
{
|
||||
value = ev.Duration switch
|
||||
{
|
||||
> 10080 => -10f,
|
||||
> 4320 => -7f,
|
||||
> 1440 => -5f,
|
||||
0 => -25f,
|
||||
_ => -3f
|
||||
};
|
||||
}
|
||||
else
|
||||
value = -2f;
|
||||
|
||||
if (_playerManager.TryGetPlayerDataByUsername(ev.Ckey!, out var data))
|
||||
uid = data.UserId;
|
||||
else
|
||||
{
|
||||
var located = await _locator.LookupIdByNameAsync(ev.Ckey!);
|
||||
|
||||
if (located == null)
|
||||
return;
|
||||
|
||||
uid = located.UserId;
|
||||
}
|
||||
|
||||
_repManager.ModifyPlayerReputation(uid, value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using Robust.Shared.Network;
|
||||
|
||||
namespace Content.Server._White.Reputation;
|
||||
|
||||
[Serializable]
|
||||
public sealed class UpdateCachedReputationEvent : EntityEventArgs
|
||||
{
|
||||
public NetUserId Player;
|
||||
|
||||
public UpdateCachedReputationEvent(NetUserId player)
|
||||
{
|
||||
Player = player;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user