[Feat] Респект и уважуха (#476)
* db * wd comment * manager & commands * system & round end results * raise ban event * client manager & cached values * role pick tweak * tweak last commit * more fixes * weights fix * Fix for short rounds * tweak in cached dictionary * reva pick system * fix last commit * cult role pick * nukeops role picking * fix cache in async & show command * ooc msg show value * move pick method to manager & traitor pick fix
This commit is contained in:
@@ -23,6 +23,7 @@ using Content.Client.Viewport;
|
||||
using Content.Client.Voting;
|
||||
using Content.Client.White.JoinQueue;
|
||||
using Content.Client.White.Jukebox;
|
||||
using Content.Client.White.Reputation;
|
||||
using Content.Client.White.Sponsors;
|
||||
using Content.Shared.Ame;
|
||||
using Content.Client.White.Stalin;
|
||||
@@ -82,6 +83,7 @@ namespace Content.Client.Entry
|
||||
[Dependency] private readonly StalinManager _stalinManager = default!;
|
||||
[Dependency] private readonly ClientJukeboxSongsSyncManager _jukeboxSyncManager = default!;
|
||||
[Dependency] private readonly TTSManager _ttsManager = default!;
|
||||
[Dependency] private readonly ReputationManager _reputationManager = default!;
|
||||
//WD-EDIT
|
||||
|
||||
public override void Init()
|
||||
@@ -189,6 +191,7 @@ namespace Content.Client.Entry
|
||||
_queueManager.Initialize();
|
||||
_jukeboxSyncManager.Initialize();
|
||||
_ttsManager.Initialize();
|
||||
_reputationManager.Initialize();
|
||||
//WD-EDIT
|
||||
|
||||
_baseClient.RunLevelChanged += (_, args) =>
|
||||
|
||||
@@ -19,6 +19,7 @@ using Content.Client.Guidebook;
|
||||
using Content.Client.Replay;
|
||||
using Content.Client.White.JoinQueue;
|
||||
using Content.Client.White.Jukebox;
|
||||
using Content.Client.White.Reputation;
|
||||
using Content.Client.White.Sponsors;
|
||||
using Content.Client.White.Stalin;
|
||||
using Content.Client.White.Trail.Line.Manager;
|
||||
@@ -59,6 +60,7 @@ namespace Content.Client.IoC
|
||||
IoCManager.Register<ClientJukeboxSongsSyncManager>();
|
||||
IoCManager.Register<TTSManager>();
|
||||
IoCManager.Register<ITrailLineManager, TrailSplineManager>();
|
||||
IoCManager.Register<ReputationManager>();
|
||||
//WD-EDIT
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Content.Client.RoundEnd
|
||||
{
|
||||
_entityManager = entityManager;
|
||||
|
||||
MinSize = SetSize = new Vector2(520, 580);
|
||||
MinSize = SetSize = new Vector2(800, 580);
|
||||
|
||||
Title = Loc.GetString("round-end-summary-window-title");
|
||||
|
||||
@@ -155,7 +155,8 @@ namespace Content.Client.RoundEnd
|
||||
("playerOOCName", playerInfo.PlayerOOCName),
|
||||
("icNameColor", icNameColor),
|
||||
("playerICName", playerInfo.PlayerICName),
|
||||
("playerRole", Loc.GetString(playerInfo.Role))));
|
||||
("playerRole", Loc.GetString(playerInfo.Role)),
|
||||
("reputation", playerInfo.Reputation)));
|
||||
}
|
||||
}
|
||||
hBox.AddChild(playerInfoText);
|
||||
|
||||
23
Content.Client/White/Reputation/ReputationManager.cs
Normal file
23
Content.Client/White/Reputation/ReputationManager.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Shared.White.Reputation;
|
||||
using Robust.Shared.Network;
|
||||
|
||||
namespace Content.Client.White.Reputation;
|
||||
|
||||
public sealed class ReputationManager
|
||||
{
|
||||
[Dependency] private readonly IClientNetManager _netMgr = default!;
|
||||
|
||||
private ReputationInfo? _info;
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
_netMgr.RegisterNetMessage<ReputationNetMsg>(msg => _info = msg.Info);
|
||||
}
|
||||
|
||||
public bool TryGetInfo([NotNullWhen(true)] out float? value)
|
||||
{
|
||||
value = _info?.Value;
|
||||
return _info != null;
|
||||
}
|
||||
}
|
||||
1424
Content.Server.Database/Migrations/Postgres/20231006121631_PlayerReputation.Designer.cs
generated
Normal file
1424
Content.Server.Database/Migrations/Postgres/20231006121631_PlayerReputation.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Postgres
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class PlayerReputation : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "player_reputations",
|
||||
columns: table => new
|
||||
{
|
||||
player_reputations_id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
user_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
reputation = table.Column<float>(type: "real", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_player_reputations", x => x.player_reputations_id);
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "player_reputations");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -689,6 +689,29 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.PlayerReputation", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("player_reputations_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<float>("Reputation")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("reputation");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_player_reputations");
|
||||
|
||||
b.ToTable("player_reputations", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Preference", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
|
||||
1354
Content.Server.Database/Migrations/Sqlite/20231006121608_PlayerReputation.Designer.cs
generated
Normal file
1354
Content.Server.Database/Migrations/Sqlite/20231006121608_PlayerReputation.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Sqlite
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class PlayerReputation : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "player_reputations",
|
||||
columns: table => new
|
||||
{
|
||||
player_reputations_id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
user_id = table.Column<Guid>(type: "TEXT", nullable: false),
|
||||
reputation = table.Column<float>(type: "REAL", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_player_reputations", x => x.player_reputations_id);
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "player_reputations");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -647,6 +647,27 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
b.ToTable("player", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.PlayerReputation", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("player_reputations_id");
|
||||
|
||||
b.Property<float>("Reputation")
|
||||
.HasColumnType("REAL")
|
||||
.HasColumnName("reputation");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_player_reputations");
|
||||
|
||||
b.ToTable("player_reputations", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Preference", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
|
||||
@@ -39,6 +39,7 @@ namespace Content.Server.Database
|
||||
public DbSet<AdminNote> AdminNotes { get; set; } = null!;
|
||||
public DbSet<AdminWatchlist> AdminWatchlists { get; set; } = null!;
|
||||
public DbSet<AdminMessage> AdminMessages { get; set; } = null!;
|
||||
public DbSet<PlayerReputation> PlayerReputations { get; set; } = default!; // WD edit
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
@@ -301,6 +302,15 @@ namespace Content.Server.Database
|
||||
public abstract int CountAdminLogs();
|
||||
}
|
||||
|
||||
// WD start
|
||||
public class PlayerReputation
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public Guid UserId { get; set; }
|
||||
public float Reputation { get; set; }
|
||||
}
|
||||
// WD end
|
||||
|
||||
public class Preference
|
||||
{
|
||||
// NOTE: on postgres there SHOULD be an FK ensuring that the selected character slot always exists.
|
||||
|
||||
@@ -20,6 +20,7 @@ public sealed class BanCommand : LocalizedCommands
|
||||
[Dependency] private readonly IBanManager _bans = default!;
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
[Dependency] private readonly UtkaTCPWrapper _utkaSockets = default!; // WD
|
||||
[Dependency] private readonly IEntityManager _entMan = default!; // WD
|
||||
|
||||
public override string Command => "ban";
|
||||
|
||||
@@ -128,6 +129,7 @@ public sealed class BanCommand : LocalizedCommands
|
||||
BanId = banId
|
||||
};
|
||||
_utkaSockets.SendMessageToAll(utkaBanned);
|
||||
_entMan.EventBus.RaiseEvent(EventSource.Local, utkaBanned);
|
||||
//WD end
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ public sealed class RoleBanManager
|
||||
[Dependency] private readonly UtkaTCPWrapper _utkaSockets = default!; // WD
|
||||
[Dependency] private readonly IEntitySystemManager _systems = default!; // WD
|
||||
[Dependency] private readonly IBanManager _banManager = default!; // WD
|
||||
[Dependency] private readonly IEntityManager _entMan = default!; // WD
|
||||
|
||||
private const string JobPrefix = "Job:";
|
||||
|
||||
@@ -425,6 +426,7 @@ public sealed class RoleBanManager
|
||||
};
|
||||
|
||||
_utkaSockets.SendMessageToAll(utkaBanned);
|
||||
_entMan.EventBus.RaiseEvent(EventSource.Local, utkaBanned);
|
||||
}
|
||||
|
||||
private async Task<int> UtkaGetBanId(string reason, string role, NetUserId targetUid)
|
||||
|
||||
@@ -27,6 +27,7 @@ using Robust.Server.Containers;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Content.Server.Shuttles.Components;
|
||||
using Content.Server.White.Reputation;
|
||||
using Content.Shared.Players;
|
||||
|
||||
namespace Content.Server.Antag;
|
||||
@@ -47,6 +48,7 @@ public sealed class AntagSelectionSystem : GameRuleSystem<GameRuleComponent>
|
||||
[Dependency] private readonly EmergencyShuttleSystem _emergencyShuttle = default!;
|
||||
[Dependency] private readonly RoleSystem _roles = default!; // WD
|
||||
[Dependency] private readonly SharedPlayerSystem _sharedPlayerSystem = default!; // WD
|
||||
[Dependency] private readonly ReputationManager _reputationManager = default!; // WD
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to start the game rule by checking if there are enough players in lobby and readied.
|
||||
@@ -217,7 +219,12 @@ public sealed class AntagSelectionSystem : GameRuleSystem<GameRuleComponent>
|
||||
|
||||
for (var i = 0; i < antagCount; i++)
|
||||
{
|
||||
results.Add(_random.PickAndTake(prefList));
|
||||
//results.Add(_random.PickAndTake(prefList));
|
||||
// WD EDIT START
|
||||
var pref = _reputationManager.PickPlayerBasedOnReputation(prefList);
|
||||
prefList.Remove(pref);
|
||||
results.Add(pref);
|
||||
// WD EDIT END
|
||||
Log.Info("Selected a preferred antag.");
|
||||
}
|
||||
return results;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.Administration.Managers;
|
||||
using Content.Server.Administration.Systems;
|
||||
@@ -8,6 +9,7 @@ using Content.Server.MoMMI;
|
||||
using Content.Server.Players;
|
||||
using Content.Server.Preferences.Managers;
|
||||
using Content.Server.UtkaIntegration;
|
||||
using Content.Server.White.Reputation;
|
||||
using Content.Server.White.Sponsors;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.CCVar;
|
||||
@@ -16,6 +18,7 @@ using Content.Shared.Database;
|
||||
using Content.Shared.Mind;
|
||||
using Content.Shared.White;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Asynchronous;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Player;
|
||||
@@ -54,6 +57,8 @@ namespace Content.Server.Chat.Managers
|
||||
[Dependency] private readonly SponsorsManager _sponsorsManager = default!;
|
||||
[Dependency] private readonly UtkaTCPWrapper _utkaSocketWrapper = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly ReputationManager _repManager = default!;
|
||||
[Dependency] private readonly ITaskManager _taskManager = default!;
|
||||
/// WD-EDIT
|
||||
|
||||
/// <summary>
|
||||
@@ -296,8 +301,22 @@ namespace Content.Server.Chat.Managers
|
||||
if (!TrySendNewMessage(player, message)) // WD
|
||||
return;
|
||||
|
||||
// WD start
|
||||
//_repManager.GetCachedPlayerReputation(player.UserId, out var value);
|
||||
var task = Task.Run(async () => await _repManager.GetPlayerReputation(player.UserId));
|
||||
_taskManager.BlockWaitOnTask(task);
|
||||
var value = task.GetAwaiter().GetResult();
|
||||
|
||||
var reputation = "";
|
||||
if (value != null)
|
||||
{
|
||||
var color = value >= 0 ? "green" : "red";
|
||||
reputation = $"[color={color}]({value})[/color]";
|
||||
}
|
||||
// WD end
|
||||
|
||||
Color? colorOverride = null;
|
||||
var wrappedMessage = Loc.GetString("chat-manager-send-ooc-wrap-message", ("playerName",player.Name), ("message", FormattedMessage.EscapeText(message)));
|
||||
var wrappedMessage = Loc.GetString("chat-manager-send-ooc-wrap-message", ("playerName",player.Name), ("message", FormattedMessage.EscapeText(message)), ("rep", reputation));
|
||||
if (_adminManager.HasAdminFlag(player, AdminFlags.Admin))
|
||||
{
|
||||
var prefs = _preferencesManager.GetPreferences(player.UserId);
|
||||
@@ -306,13 +325,13 @@ namespace Content.Server.Chat.Managers
|
||||
if (player.Channel.UserData.PatronTier is { } patron &&
|
||||
PatronOocColors.TryGetValue(patron, out var patronColor))
|
||||
{
|
||||
wrappedMessage = Loc.GetString("chat-manager-send-ooc-patron-wrap-message", ("patronColor", patronColor),("playerName", player.Name), ("message", FormattedMessage.EscapeText(message)));
|
||||
wrappedMessage = Loc.GetString("chat-manager-send-ooc-patron-wrap-message", ("patronColor", patronColor),("playerName", player.Name), ("message", FormattedMessage.EscapeText(message)), ("rep", reputation));
|
||||
}
|
||||
|
||||
//WD-EDIT
|
||||
if (_sponsorsManager.TryGetInfo(player.UserId, out var sponsorData) && sponsorData.OOCColor != null)
|
||||
{
|
||||
wrappedMessage = Loc.GetString("chat-manager-send-ooc-patron-wrap-message", ("patronColor", sponsorData.OOCColor),("playerName", player.Name), ("message", FormattedMessage.EscapeText(message)));
|
||||
wrappedMessage = Loc.GetString("chat-manager-send-ooc-patron-wrap-message", ("patronColor", sponsorData.OOCColor),("playerName", player.Name), ("message", FormattedMessage.EscapeText(message)), ("rep", reputation));
|
||||
}
|
||||
//WD-EDIT
|
||||
|
||||
|
||||
@@ -1401,6 +1401,69 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Player Reputation (WD edit)
|
||||
|
||||
public async Task SetPlayerReputation(Guid player, float value)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
var reputation = await db.DbContext.PlayerReputations
|
||||
.SingleOrDefaultAsync(p => p.UserId == player);
|
||||
|
||||
if (reputation == null)
|
||||
{
|
||||
reputation = new PlayerReputation()
|
||||
{
|
||||
UserId = player,
|
||||
Reputation = value
|
||||
};
|
||||
db.DbContext.PlayerReputations.Add(reputation);
|
||||
}
|
||||
else
|
||||
{
|
||||
reputation.Reputation = value;
|
||||
}
|
||||
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task ModifyPlayerReputation(Guid player, float value)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
var reputation = await db.DbContext.PlayerReputations
|
||||
.SingleOrDefaultAsync(p => p.UserId == player);
|
||||
|
||||
if (reputation == null)
|
||||
{
|
||||
reputation = new PlayerReputation()
|
||||
{
|
||||
UserId = player,
|
||||
Reputation = 0f + value
|
||||
};
|
||||
db.DbContext.PlayerReputations.Add(reputation);
|
||||
}
|
||||
else
|
||||
{
|
||||
reputation.Reputation += value;
|
||||
}
|
||||
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task<float> GetPlayerReputation(Guid player)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
var reputation = await db.DbContext.PlayerReputations
|
||||
.SingleOrDefaultAsync(p => p.UserId == player);
|
||||
|
||||
return reputation?.Reputation ?? 0f;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
protected abstract Task<DbGuard> GetDb([CallerMemberName] string? name = null);
|
||||
|
||||
protected void LogDbOp(string? name)
|
||||
|
||||
@@ -281,6 +281,31 @@ namespace Content.Server.Database
|
||||
Task MarkMessageAsSeen(int id);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Player Reputation (WD edit)
|
||||
|
||||
/// <summary>
|
||||
/// Set player's reputation to the certain value.
|
||||
/// </summary>
|
||||
/// <param name="player">Guid of the player to set the value.</param>
|
||||
/// <param name="value">Value to set.</param>
|
||||
Task SetPlayerReputation(Guid player, float value);
|
||||
|
||||
/// <summary>
|
||||
/// Modify player's reputation by adding value (currentValue + value).
|
||||
/// </summary>
|
||||
/// <param name="player">Guid of the player to modify the value.</param>
|
||||
/// <param name="value">Value to add.</param>
|
||||
Task ModifyPlayerReputation(Guid player, float value);
|
||||
|
||||
/// <summary>
|
||||
/// Gets value of player reputation.
|
||||
/// </summary>
|
||||
/// <param name="player">Guid of the player to get the value.</param>
|
||||
/// <returns>Value of player's reputation.</returns>
|
||||
Task<float> GetPlayerReputation(Guid player);
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public sealed class ServerDbManager : IServerDbManager
|
||||
@@ -502,6 +527,28 @@ namespace Content.Server.Database
|
||||
|
||||
#endregion
|
||||
|
||||
#region Player Reputation (WD edit)
|
||||
|
||||
public Task SetPlayerReputation(Guid player, float value)
|
||||
{
|
||||
DbWriteOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.SetPlayerReputation(player, value));
|
||||
}
|
||||
|
||||
public Task ModifyPlayerReputation(Guid player, float value)
|
||||
{
|
||||
DbWriteOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.ModifyPlayerReputation(player, value));
|
||||
}
|
||||
|
||||
public Task<float> GetPlayerReputation(Guid player)
|
||||
{
|
||||
DbWriteOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.GetPlayerReputation(player));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public Task UpdatePlayerRecordAsync(
|
||||
NetUserId userId,
|
||||
string userName,
|
||||
|
||||
@@ -33,6 +33,7 @@ using Content.Server.UtkaIntegration;
|
||||
using Content.Server.White;
|
||||
using Content.Server.White.JoinQueue;
|
||||
using Content.Server.White.Jukebox;
|
||||
using Content.Server.White.Reputation;
|
||||
using Content.Server.White.Sponsors;
|
||||
using Content.Server.White.Stalin;
|
||||
using Content.Server.White.TTS;
|
||||
|
||||
@@ -22,6 +22,7 @@ using Robust.Shared.Random;
|
||||
using Robust.Shared.Utility;
|
||||
using Content.Server.UtkaIntegration;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.White.Reputation;
|
||||
using Content.Server.White.Stalin;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.White;
|
||||
@@ -37,6 +38,7 @@ namespace Content.Server.GameTicking
|
||||
//WD-EDIT
|
||||
[Dependency] private readonly UtkaTCPWrapper _utkaSocketWrapper = default!;
|
||||
[Dependency] private readonly StalinManager _stalinManager = default!;
|
||||
[Dependency] private readonly ReputationSystem _repSys = default!;
|
||||
//WD-EDIT
|
||||
|
||||
private static readonly Counter RoundNumberMetric = Metrics.CreateCounter(
|
||||
@@ -394,6 +396,17 @@ namespace Content.Server.GameTicking
|
||||
|
||||
var roles = _roles.MindGetAllRoles(mindId);
|
||||
|
||||
// WD start
|
||||
var reputation = "";
|
||||
if (mind.Session != null &&
|
||||
_repSys.TryModifyReputationOnRoundEnd(mind.Session.Name, out var value, out var delta))
|
||||
{
|
||||
var color = value >= 0 ? "green" : "red";
|
||||
var change = delta >= 0 ? $"+{delta}" : $"{delta}";
|
||||
reputation = $"[color={color}]{value} ({change})";
|
||||
}
|
||||
// WD end
|
||||
|
||||
var playerEndRoundInfo = new RoundEndMessageEvent.RoundEndPlayerInfo()
|
||||
{
|
||||
// Note that contentPlayerData?.Name sticks around after the player is disconnected.
|
||||
@@ -407,7 +420,8 @@ namespace Content.Server.GameTicking
|
||||
: roles.FirstOrDefault().Name ?? Loc.GetString("game-ticker-unknown-role"),
|
||||
Antag = antag,
|
||||
Observer = observer,
|
||||
Connected = connected
|
||||
Connected = connected,
|
||||
Reputation = reputation
|
||||
};
|
||||
listOfPlayerInfo.Add(playerEndRoundInfo);
|
||||
}
|
||||
|
||||
@@ -29,6 +29,9 @@ using Content.Server.Station.Systems;
|
||||
using Content.Server.Store.Components;
|
||||
using Content.Server.Store.Systems;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Server.Traitor;
|
||||
using Content.Server.White.Administration;
|
||||
using Content.Server.White.Reputation;
|
||||
using Content.Shared.Dataset;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Humanoid.Prototypes;
|
||||
@@ -86,6 +89,9 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
|
||||
[Dependency] private readonly IAdminManager _adminManager = default!;
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
[Dependency] private readonly WarDeclaratorSystem _warDeclarator = default!;
|
||||
//WD EDIT
|
||||
[Dependency] private readonly ReputationManager _reputationManager = default!;
|
||||
//WD EDIT
|
||||
|
||||
|
||||
[ValidatePrototypeId<CurrencyPrototype>]
|
||||
@@ -686,7 +692,9 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
|
||||
}
|
||||
else
|
||||
{
|
||||
nukeOp = _random.PickAndTake(cmdrPrefList);
|
||||
//nukeOp = _random.PickAndTake(cmdrPrefList);
|
||||
nukeOp = _reputationManager.PickPlayerBasedOnReputation(cmdrPrefList); // WD edit
|
||||
cmdrPrefList.Remove(nukeOp); // WD edit
|
||||
everyone.Remove(nukeOp);
|
||||
prefList.Remove(nukeOp);
|
||||
medPrefList.Remove(nukeOp);
|
||||
@@ -716,7 +724,9 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
|
||||
}
|
||||
else
|
||||
{
|
||||
nukeOp = _random.PickAndTake(medPrefList);
|
||||
//nukeOp = _random.PickAndTake(medPrefList);
|
||||
nukeOp = _reputationManager.PickPlayerBasedOnReputation(medPrefList); // WD edit
|
||||
medPrefList.Remove(nukeOp); // WD edit
|
||||
everyone.Remove(nukeOp);
|
||||
prefList.Remove(nukeOp);
|
||||
Logger.InfoS("preset", "Insufficient preferred nukeop commanders, picking an agent");
|
||||
@@ -725,7 +735,9 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
|
||||
}
|
||||
else
|
||||
{
|
||||
nukeOp = _random.PickAndTake(prefList);
|
||||
//nukeOp = _random.PickAndTake(prefList);
|
||||
nukeOp = _reputationManager.PickPlayerBasedOnReputation(prefList); // WD edit
|
||||
prefList.Remove(nukeOp); // WD edit
|
||||
everyone.Remove(nukeOp);
|
||||
Logger.InfoS("preset", "Selected a preferred nukeop commander.");
|
||||
}
|
||||
|
||||
@@ -15,18 +15,15 @@ using Content.Shared.Mind;
|
||||
using Content.Shared.Mobs.Systems;
|
||||
using Content.Shared.Objectives.Components;
|
||||
using Content.Shared.PDA;
|
||||
using Content.Shared.Preferences;
|
||||
using Content.Shared.Roles;
|
||||
using Content.Shared.Roles.Jobs;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Timing;
|
||||
using Content.Server.Objectives;
|
||||
using Content.Server.White.Reputation;
|
||||
using Content.Shared.White.Mood;
|
||||
|
||||
namespace Content.Server.GameTicking.Rules;
|
||||
@@ -49,6 +46,8 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
|
||||
[Dependency] private readonly ObjectivesSystem _objectives = default!;
|
||||
[Dependency] private readonly RoleSystem _roles = default!; // WD
|
||||
|
||||
private ISawmill _sawmill = default!;
|
||||
|
||||
private int PlayersPerTraitor => _cfg.GetCVar(CCVars.TraitorPlayersPerTraitor);
|
||||
private int MaxTraitors => _cfg.GetCVar(CCVars.TraitorMaxTraitors);
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ using Content.Server.UtkaIntegration;
|
||||
using Content.Server.White;
|
||||
using Content.Server.White.JoinQueue;
|
||||
using Content.Server.White.Jukebox;
|
||||
using Content.Server.White.Reputation;
|
||||
using Content.Server.White.Sponsors;
|
||||
using Content.Server.White.Stalin;
|
||||
using Content.Server.White.TTS;
|
||||
@@ -75,6 +76,7 @@ namespace Content.Server.IoC
|
||||
IoCManager.Register<StalinManager>();
|
||||
IoCManager.Register<ServerJukeboxSongsSyncManager>();
|
||||
IoCManager.Register<SalusManager>();
|
||||
IoCManager.Register<ReputationManager>();
|
||||
// WD-EDIT
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.Linq;
|
||||
using Content.Server.Administration.Managers;
|
||||
using Content.Server.Players.PlayTimeTracking;
|
||||
using Content.Server.Station.Components;
|
||||
using Content.Server.White.Reputation;
|
||||
using Content.Shared.Preferences;
|
||||
using Content.Shared.Roles;
|
||||
using Robust.Shared.Network;
|
||||
@@ -17,6 +18,7 @@ public sealed partial class StationJobsSystem
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IBanManager _banManager = default!;
|
||||
[Dependency] private readonly PlayTimeTrackingSystem _playTime = default!;
|
||||
[Dependency] private readonly ReputationManager _reputationManager = default!; // WD edit
|
||||
|
||||
private Dictionary<int, HashSet<string>> _jobsByWeight = default!;
|
||||
private List<int> _orderedWeights = default!;
|
||||
@@ -245,7 +247,8 @@ public sealed partial class StationJobsSystem
|
||||
continue;
|
||||
|
||||
// Picking players it finds that have the job set.
|
||||
var player = _random.Pick(jobPlayerOptions[job]);
|
||||
//var player = _random.Pick(jobPlayerOptions[job]);
|
||||
var player = GetPlayerToAssign(jobPlayerOptions[job]); // WD edit
|
||||
AssignPlayer(player, job, station);
|
||||
stationShares[station]--;
|
||||
|
||||
@@ -374,4 +377,33 @@ public sealed partial class StationJobsSystem
|
||||
|
||||
return outputDict;
|
||||
}
|
||||
|
||||
// WD start
|
||||
private NetUserId GetPlayerToAssign(HashSet<NetUserId> players)
|
||||
{
|
||||
var list = new List<NetUserId>();
|
||||
|
||||
foreach (var player in players)
|
||||
{
|
||||
if (!_reputationManager.GetCachedPlayerReputation(player, out var value))
|
||||
continue;
|
||||
|
||||
if (value == null)
|
||||
continue;
|
||||
|
||||
var weight = _reputationManager.GetPlayerWeight(value.Value);
|
||||
|
||||
for (var i = 0; i < weight; i++)
|
||||
{
|
||||
list.Add(player);
|
||||
}
|
||||
}
|
||||
|
||||
if (list.Count == 0)
|
||||
return _random.Pick(players);
|
||||
|
||||
var number = _random.Next(list.Count - 1);
|
||||
return list[number];
|
||||
}
|
||||
// WD end
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@ public sealed class UtkaBanCommand : IUtkaCommand
|
||||
{
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
[Dependency] private UtkaTCPWrapper _utkaSocketWrapper = default!;
|
||||
[Dependency] private readonly IServerDbManager _db = default!;
|
||||
[Dependency] private readonly IEntityManager _entMan = default!;
|
||||
|
||||
private const ILocalizationManager LocalizationManager = default!;
|
||||
|
||||
@@ -27,7 +29,6 @@ public sealed class UtkaBanCommand : IUtkaCommand
|
||||
|
||||
var plyMgr = IoCManager.Resolve<IPlayerManager>();
|
||||
var locator = IoCManager.Resolve<IPlayerLocator>();
|
||||
var dbMan = IoCManager.Resolve<IServerDbManager>();
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
var locatedPlayer = await locator.LookupIdByNameOrIdAsync(message.ACkey!);
|
||||
@@ -87,7 +88,7 @@ public sealed class UtkaBanCommand : IUtkaCommand
|
||||
|
||||
IoCManager.Resolve<IEntitySystemManager>().TryGetEntitySystem<GameTicker>(out var ticker);
|
||||
int? roundId = ticker == null || ticker.RoundId == 0 ? null : ticker.RoundId;
|
||||
var playtime = (await dbMan.GetPlayTimes(targetUid)).Find(p => p.Tracker == PlayTimeTrackingShared.TrackerOverall)?.TimeSpent ?? TimeSpan.Zero;
|
||||
var playtime = (await _db.GetPlayTimes(targetUid)).Find(p => p.Tracker == PlayTimeTrackingShared.TrackerOverall)?.TimeSpent ?? TimeSpan.Zero;
|
||||
|
||||
var banDef = new ServerBanDef(
|
||||
null,
|
||||
@@ -106,7 +107,7 @@ public sealed class UtkaBanCommand : IUtkaCommand
|
||||
|
||||
UtkaSendResponse(true);
|
||||
|
||||
await dbMan.AddServerBanAsync(banDef);
|
||||
await _db.AddServerBanAsync(banDef);
|
||||
|
||||
if (plyMgr.TryGetSessionById(targetUid, out var targetPlayer))
|
||||
{
|
||||
@@ -114,7 +115,7 @@ public sealed class UtkaBanCommand : IUtkaCommand
|
||||
targetPlayer.ConnectedClient.Disconnect(msg);
|
||||
}
|
||||
|
||||
var banlist = await dbMan.GetServerBansAsync(null, targetUid, null);
|
||||
var banlist = await _db.GetServerBansAsync(null, targetUid, null);
|
||||
var banId = banlist[^1].Id;
|
||||
|
||||
var utkaBanned = new UtkaBannedEvent()
|
||||
@@ -129,6 +130,7 @@ public sealed class UtkaBanCommand : IUtkaCommand
|
||||
BanId = banId
|
||||
};
|
||||
_utkaSocketWrapper.SendMessageToAll(utkaBanned);
|
||||
_entMan.EventBus.RaiseEvent(EventSource.Local, utkaBanned);
|
||||
}
|
||||
|
||||
private void UtkaSendResponse(bool banned)
|
||||
|
||||
@@ -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,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.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;
|
||||
|
||||
repManager.ModifyPlayerReputation(uid, value);
|
||||
|
||||
shell.WriteLine($"Added {args[1]} to the reputation of {args[0]}.");
|
||||
}
|
||||
}
|
||||
@@ -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.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;
|
||||
|
||||
repManager.SetPlayerReputation(uid, value);
|
||||
|
||||
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}");
|
||||
}
|
||||
}
|
||||
201
Content.Server/White/Reputation/ReputationManager.cs
Normal file
201
Content.Server/White/Reputation/ReputationManager.cs
Normal file
@@ -0,0 +1,201 @@
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Database;
|
||||
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!;
|
||||
|
||||
private readonly Dictionary<NetUserId, ReputationInfo> _cacheReputation = new();
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_netMgr.RegisterNetMessage<ReputationNetMsg>();
|
||||
|
||||
_netMgr.Connecting += OnConnecting;
|
||||
_netMgr.Connected += OnConnected;
|
||||
|
||||
SubscribeLocalEvent<RoundRestartCleanupEvent>(OnRoundRestartCleanup);
|
||||
SubscribeLocalEvent<UpdateCachedReputationEvent>(UpdateCachedReputation);
|
||||
}
|
||||
|
||||
#region Cache
|
||||
|
||||
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();
|
||||
|
||||
foreach (var kvp in newDictionary)
|
||||
{
|
||||
_cacheReputation.Add(kvp.Key, kvp.Value);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region PublicApi
|
||||
|
||||
public async void SetPlayerReputation(NetUserId player, float value)
|
||||
{
|
||||
var guid = player.UserId;
|
||||
await SetPlayerReputationTask(guid, value);
|
||||
RaiseLocalEvent(new UpdateCachedReputationEvent(player));
|
||||
}
|
||||
|
||||
public async void ModifyPlayerReputation(NetUserId player, float value)
|
||||
{
|
||||
var guid = player.UserId;
|
||||
await ModifyPlayerReputationTask(guid, value);
|
||||
RaiseLocalEvent(new UpdateCachedReputationEvent(player));
|
||||
}
|
||||
|
||||
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 int GetPlayerWeight(float reputation)
|
||||
{
|
||||
return reputation switch
|
||||
{
|
||||
> 1000 => 9,
|
||||
> 700 => 8,
|
||||
> 500 => 7,
|
||||
> 300 => 6,
|
||||
> 100 => 5,
|
||||
> 50 => 4,
|
||||
> 15 => 3,
|
||||
< 0 => 1,
|
||||
_ => 2
|
||||
};
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
167
Content.Server/White/Reputation/ReputationSystem.cs
Normal file
167
Content.Server/White/Reputation/ReputationSystem.cs
Normal file
@@ -0,0 +1,167 @@
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.Mind.Components;
|
||||
using Content.Server.UtkaIntegration;
|
||||
using Content.Server.White.AspectsSystem.Base;
|
||||
using Content.Shared.Mobs;
|
||||
using Content.Shared.Mobs.Components;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Asynchronous;
|
||||
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 ITaskManager _taskManager = default!;
|
||||
[Dependency] private readonly IPlayerLocator _locator = default!;
|
||||
|
||||
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;
|
||||
|
||||
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 longRound = _gameTicker.RoundDuration().Minutes >= 25;
|
||||
if (delta != 0 && longRound)
|
||||
{
|
||||
_repManager.ModifyPlayerReputation(uid, delta);
|
||||
}
|
||||
|
||||
deltaValue = longRound ? 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
|
||||
&& mind.Mind.AllRoles.Any(role => role.Antagonist))
|
||||
{
|
||||
var condCompleted = 0;
|
||||
var totalCond = 0;
|
||||
foreach (var obj in mind.Mind.AllObjectives)
|
||||
{
|
||||
foreach (var condition in obj.Conditions)
|
||||
{
|
||||
totalCond++;
|
||||
|
||||
if (condition.Progress > 0.99f)
|
||||
condCompleted++;
|
||||
}
|
||||
}
|
||||
|
||||
if (aspect)
|
||||
{
|
||||
if (condCompleted == totalCond)
|
||||
deltaValue += 1f + condCompleted;
|
||||
else
|
||||
deltaValue += 1f + condCompleted * 0.5f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (condCompleted == totalCond)
|
||||
deltaValue += 2f + condCompleted * 0.5f;
|
||||
else
|
||||
deltaValue += condCompleted * 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;
|
||||
}
|
||||
}
|
||||
@@ -148,6 +148,7 @@ namespace Content.Shared.GameTicking
|
||||
public bool Antag;
|
||||
public bool Observer;
|
||||
public bool Connected;
|
||||
public string Reputation; // WD edit
|
||||
}
|
||||
|
||||
public string GamemodeTitle { get; }
|
||||
|
||||
49
Content.Shared/White/Reputation/ReputationNetMsg.cs
Normal file
49
Content.Shared/White/Reputation/ReputationNetMsg.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System.IO;
|
||||
using System.Text.Json.Serialization;
|
||||
using Lidgren.Network;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared.White.Reputation;
|
||||
|
||||
public sealed class ReputationNetMsg : NetMessage
|
||||
{
|
||||
public override MsgGroups MsgGroup => MsgGroups.Command;
|
||||
|
||||
public ReputationInfo? Info;
|
||||
|
||||
public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer serializer)
|
||||
{
|
||||
var success = buffer.ReadBoolean();
|
||||
buffer.ReadPadBits();
|
||||
|
||||
if (!success)
|
||||
return;
|
||||
|
||||
var length = buffer.ReadVariableInt32();
|
||||
using var stream = buffer.ReadAlignedMemory(length);
|
||||
serializer.DeserializeDirect(stream, out Info);
|
||||
}
|
||||
|
||||
public override void WriteToBuffer(NetOutgoingMessage buffer, IRobustSerializer serializer)
|
||||
{
|
||||
buffer.Write(Info != null);
|
||||
buffer.WritePadBits();
|
||||
|
||||
if (Info == null)
|
||||
return;
|
||||
|
||||
var stream = new MemoryStream();
|
||||
serializer.SerializeDirect(stream, Info);
|
||||
buffer.WriteVariableInt32((int) stream.Length);
|
||||
buffer.Write(stream.AsSpan());
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class ReputationInfo
|
||||
{
|
||||
[JsonPropertyName("value")]
|
||||
public float Value { get; set; }
|
||||
}
|
||||
@@ -34,8 +34,8 @@ chat-manager-entity-me-wrap-message = [italic]{ PROPER($entity) ->
|
||||
}
|
||||
|
||||
chat-manager-entity-looc-wrap-message = LOOC: [bold]{$entityName}:[/bold] {$message}
|
||||
chat-manager-send-ooc-wrap-message = OOC: [bold]{$playerName}:[/bold] {$message}
|
||||
chat-manager-send-ooc-patron-wrap-message = OOC: [bold][color={$patronColor}]{$playerName}[/color]:[/bold] {$message}
|
||||
chat-manager-send-ooc-wrap-message = OOC: [bold]{$playerName}{$rep}:[/bold] {$message}
|
||||
chat-manager-send-ooc-patron-wrap-message = OOC: [bold][color={$patronColor}]{$playerName}[/color]{$rep}:[/bold] {$message}
|
||||
|
||||
chat-manager-send-dead-chat-wrap-message = {$deadChannelName}: [bold][BubbleHeader]{$playerName}[/BubbleHeader]:[/bold] [BubbleContent]{$message}[/BubbleContent]
|
||||
chat-manager-send-admin-dead-chat-wrap-message = {$adminChannelName}: [bold]([BubbleHeader]{$userName}[/BubbleHeader]):[/bold] [BubbleContent]{$message}[/BubbleContent]
|
||||
|
||||
@@ -5,4 +5,4 @@ round-end-summary-window-round-id-label = Round [color=white]#{$roundId}[/color]
|
||||
round-end-summary-window-gamemode-name-label = The game mode was [color=white]{$gamemode}[/color].
|
||||
round-end-summary-window-duration-label = It lasted for [color=yellow]{$hours} hours, {$minutes} minutes, and {$seconds} seconds.
|
||||
round-end-summary-window-player-info-if-observer-text = [color=gray]{$playerOOCName}[/color] was [color=lightblue]{$playerICName}[/color], an observer.
|
||||
round-end-summary-window-player-info-if-not-observer-text = [color=gray]{$playerOOCName}[/color] was [color={$icNameColor}]{$playerICName}[/color] playing role of [color=orange]{$playerRole}[/color].
|
||||
round-end-summary-window-player-info-if-not-observer-text = [color=gray]{$playerOOCName}[/color] was [color={$icNameColor}]{$playerICName}[/color] playing role of [color=orange]{$playerRole}[/color]. { $reputation }
|
||||
|
||||
@@ -31,8 +31,8 @@ chat-manager-entity-whisper-unknown-wrap-message = [font size=11][italic][Bubble
|
||||
chat-manager-entity-me-wrap-message = { $entityName } { $message }
|
||||
|
||||
chat-manager-entity-looc-wrap-message = LOOC: [bold]{$entityName}:[/bold] {$message}
|
||||
chat-manager-send-ooc-wrap-message = OOC: [bold]{$playerName}:[/bold] {$message}
|
||||
chat-manager-send-ooc-patron-wrap-message = OOC: [bold][color={$patronColor}]{$playerName}[/color]:[/bold] {$message}
|
||||
chat-manager-send-ooc-wrap-message = OOC: [bold]{$playerName}{$rep}:[/bold] {$message}
|
||||
chat-manager-send-ooc-patron-wrap-message = OOC: [bold][color={$patronColor}]{$playerName}[/color]{$rep}:[/bold] {$message}
|
||||
|
||||
chat-manager-send-dead-chat-wrap-message = {$deadChannelName}: [bold][BubbleHeader]{$playerName}[/BubbleHeader]:[/bold] [BubbleContent]{$message}[/BubbleContent]
|
||||
chat-manager-send-admin-dead-chat-wrap-message = {$adminChannelName}: [bold]([BubbleHeader]{$userName}[/BubbleHeader]):[/bold] [BubbleContent]{$message}[/BubbleContent]
|
||||
|
||||
@@ -5,4 +5,4 @@ round-end-summary-window-round-id-label = Раунд [color=white]#{ $roundId }[
|
||||
round-end-summary-window-gamemode-name-label = Игровой режим был [color=white]{ $gamemode }[/color].
|
||||
round-end-summary-window-duration-label = Он длился [color=yellow]{ $hours } ч., { $minutes } мин., и { $seconds } сек.
|
||||
round-end-summary-window-player-info-if-observer-text = [color=gray]{ $playerOOCName }[/color] был [color=lightblue]{ $playerICName }[/color], наблюдатель.
|
||||
round-end-summary-window-player-info-if-not-observer-text = [color=gray]{ $playerOOCName }[/color] был [color={ $icNameColor }]{ $playerICName }[/color], в роли [color=orange]{ $playerRole }[/color].
|
||||
round-end-summary-window-player-info-if-not-observer-text = [color=gray]{ $playerOOCName }[/color] был [color={ $icNameColor }]{ $playerICName }[/color], в роли [color=orange]{ $playerRole }[/color]. { $reputation }
|
||||
|
||||
Reference in New Issue
Block a user