Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upstream sync #556

Merged
merged 37 commits into from
Apr 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
5ecff8a
Sanitizes "tbf" into "to be fair" (#26811)
deepdarkdepths Apr 8, 2024
c95bbce
prevent placing dead bodies in cryostorage (#26810)
EmoGarbage404 Apr 8, 2024
356c279
fixed cigarette sprites (#26801)
Bribrooo Apr 8, 2024
a178754
Show missing materials in lathes tooltip (#26795)
Crotalus Apr 8, 2024
9811173
Automatic changelog update
PJBot Apr 8, 2024
f784e9c
Bug fixes for RCD (#26792)
chromiumboy Apr 8, 2024
5e2f1e7
Automatic changelog update
PJBot Apr 8, 2024
e9cbb0e
Add new lobby art (#2024)
lzk228 Apr 8, 2024
8284c0f
New Gelta shuttles (#2025)
Zna1kin Apr 8, 2024
898bc34
Locale tweaks (#2018)
lapatison Apr 8, 2024
6c3448d
Invert status icon side (#2023)
lzk228 Apr 8, 2024
372a252
[Maps] New map Split stations (#2022)
poeMota Apr 8, 2024
11cc48c
New role - Pilot (#1978)
poeMota Apr 8, 2024
3851fcb
Fixes elite operative figurine description (#26814)
deepdarkdepths Apr 8, 2024
d2db6ca
[Maps] Pilot on Split stations (#2026)
poeMota Apr 8, 2024
a9df8cf
Fix lathe materials list bug (#26826)
Crotalus Apr 8, 2024
7188b50
fix bodybag id case (#26823)
lzk228 Apr 8, 2024
4a7aa30
Make bombsuits similar (#26806)
lzk228 Apr 8, 2024
2bbae3e
Automatic changelog update
PJBot Apr 8, 2024
6ce5370
Make clothing cheaper and split clothing restock (#26805)
lzk228 Apr 8, 2024
7f56ba0
Automatic changelog update
PJBot Apr 8, 2024
3d6d782
Fix tray scanner not updating it's range. (#26789)
c4llv07e Apr 8, 2024
2f5c639
predict humanoid identity examine (#26769)
deltanedas Apr 8, 2024
263469d
Spears equippable to suit storage (#26724)
Hanzdegloker Apr 8, 2024
1486617
Automatic changelog update
PJBot Apr 8, 2024
2cc4098
Ion Storm Laws Review (#26703)
FairlySadPanda Apr 8, 2024
e64288a
add ratvar to ion storm laws (#26833)
Dutch-VanDerLinde Apr 8, 2024
a0de0ab
Server-only component YAML cleanup (#26836)
Tayrtahn Apr 9, 2024
a1fcfed
Gauze Markings 3 - Revenge of the Wrap (#25481)
KittenColony Apr 9, 2024
694ae00
Automatic changelog update
PJBot Apr 9, 2024
6d695dd
dirty after calling SetAccesses (#26849)
deltanedas Apr 9, 2024
d879665
Add new "grant_connect_bypass" admin command (#26771)
PJB3005 Apr 9, 2024
862f820
Automatic changelog update
PJBot Apr 9, 2024
57c453f
Merge remote-tracking branch 'upstream/master' into upstream-sync
Rxup Apr 9, 2024
e785748
Merge remote-tracking branch 'wizard/master' into upstream-sync
Rxup Apr 9, 2024
7f72647
fix
Rxup Apr 9, 2024
3d01053
fix
Rxup Apr 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 46 additions & 30 deletions Content.Client/Lathe/UI/LatheMenu.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,41 +104,12 @@ public void PopulateRecipes()
RecipeList.Children.Clear();
foreach (var prototype in sortedRecipesToShow)
{
StringBuilder sb = new();
var first = true;
foreach (var (id, amount) in prototype.RequiredMaterials)
{
if (!_prototypeManager.TryIndex<MaterialPrototype>(id, out var proto))
continue;

if (first)
first = false;
else
sb.Append('\n');

var adjustedAmount = SharedLatheSystem.AdjustMaterial(amount, prototype.ApplyMaterialDiscount, component.MaterialUseMultiplier);
var sheetVolume = _materialStorage.GetSheetVolume(proto);

var unit = Loc.GetString(proto.Unit);
// rounded in locale not here
var sheets = adjustedAmount / (float) sheetVolume;
var amountText = Loc.GetString("lathe-menu-material-amount", ("amount", sheets), ("unit", unit));
var name = Loc.GetString(proto.Name);
sb.Append(Loc.GetString("lathe-menu-tooltip-display", ("material", name), ("amount", amountText)));
}

if (!string.IsNullOrWhiteSpace(prototype.Description))
{
sb.Append('\n');
sb.Append(Loc.GetString("lathe-menu-description-display", ("description", prototype.Description)));
}

var icon = prototype.Icon == null
? _spriteSystem.GetPrototypeIcon(prototype.Result).Default
: _spriteSystem.Frame0(prototype.Icon);
var canProduce = _lathe.CanProduce(_owner, prototype, quantity);

var control = new RecipeControl(prototype, sb.ToString(), canProduce, icon);
var control = new RecipeControl(prototype, () => GenerateTooltipText(prototype), canProduce, icon);
control.OnButtonPressed += s =>
{
if (!int.TryParse(AmountLineEdit.Text, out var amount) || amount <= 0)
Expand All @@ -149,6 +120,51 @@ public void PopulateRecipes()
}
}

private string GenerateTooltipText(LatheRecipePrototype prototype)
{
StringBuilder sb = new();

foreach (var (id, amount) in prototype.RequiredMaterials)
{
if (!_prototypeManager.TryIndex<MaterialPrototype>(id, out var proto))
continue;

var adjustedAmount = SharedLatheSystem.AdjustMaterial(amount, prototype.ApplyMaterialDiscount, _entityManager.GetComponent<LatheComponent>(_owner).MaterialUseMultiplier);
var sheetVolume = _materialStorage.GetSheetVolume(proto);

var unit = Loc.GetString(proto.Unit);
var sheets = adjustedAmount / (float) sheetVolume;

var availableAmount = _materialStorage.GetMaterialAmount(_owner, id);
var missingAmount = Math.Max(0, adjustedAmount - availableAmount);
var missingSheets = missingAmount / (float) sheetVolume;

var name = Loc.GetString(proto.Name);

string tooltipText;
if (missingSheets > 0)
{
tooltipText = Loc.GetString("lathe-menu-material-amount-missing", ("amount", sheets), ("missingAmount", missingSheets), ("unit", unit), ("material", name));
}
else
{
var amountText = Loc.GetString("lathe-menu-material-amount", ("amount", sheets), ("unit", unit));
tooltipText = Loc.GetString("lathe-menu-tooltip-display", ("material", name), ("amount", amountText));
}

sb.AppendLine(tooltipText);
}

if (!string.IsNullOrWhiteSpace(prototype.Description))
sb.AppendLine(Loc.GetString("lathe-menu-description-display", ("description", prototype.Description)));

// Remove last newline
if (sb.Length > 0)
sb.Remove(sb.Length - 1, 1);

return sb.ToString();
}

public void UpdateCategories()
{
var currentCategories = new List<ProtoId<LatheCategoryPrototype>>();
Expand Down
9 changes: 4 additions & 5 deletions Content.Client/Lathe/UI/RecipeControl.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,16 @@ namespace Content.Client.Lathe.UI;
public sealed partial class RecipeControl : Control
{
public Action<string>? OnButtonPressed;
public Func<string> TooltipTextSupplier;

public string TooltipText;

public RecipeControl(LatheRecipePrototype recipe, string tooltip, bool canProduce, Texture? texture = null)
public RecipeControl(LatheRecipePrototype recipe, Func<string> tooltipTextSupplier, bool canProduce, Texture? texture = null)
{
RobustXamlLoader.Load(this);

RecipeName.Text = recipe.Name;
RecipeTexture.Texture = texture;
Button.Disabled = !canProduce;
TooltipText = tooltip;
TooltipTextSupplier = tooltipTextSupplier;
Button.TooltipSupplier = SupplyTooltip;

Button.OnPressed += (_) =>
Expand All @@ -32,6 +31,6 @@ public RecipeControl(LatheRecipePrototype recipe, string tooltip, bool canProduc

private Control? SupplyTooltip(Control sender)
{
return new RecipeTooltip(TooltipText);
return new RecipeTooltip(TooltipTextSupplier());
}
}
43 changes: 40 additions & 3 deletions Content.Client/RCD/RCDMenu.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using Content.Client.UserInterface.Controls;
using Content.Shared.Popups;
using Content.Shared.RCD;
using Content.Shared.RCD.Components;
using Robust.Client.AutoGenerated;
using Robust.Client.GameObjects;
using Robust.Client.Player;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
Expand All @@ -16,17 +18,24 @@ public sealed partial class RCDMenu : RadialMenu
{
[Dependency] private readonly EntityManager _entManager = default!;
[Dependency] private readonly IPrototypeManager _protoManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;

private readonly SpriteSystem _spriteSystem;
private readonly SharedPopupSystem _popup;

public event Action<ProtoId<RCDPrototype>>? SendRCDSystemMessageAction;

private EntityUid _owner;

public RCDMenu(EntityUid owner, RCDMenuBoundUserInterface bui)
{
IoCManager.InjectDependencies(this);
RobustXamlLoader.Load(this);

_spriteSystem = _entManager.System<SpriteSystem>();
_popup = _entManager.System<SharedPopupSystem>();

_owner = owner;

// Find the main radial container
var main = FindControl<RadialContainer>("Main");
Expand All @@ -51,14 +60,21 @@ public RCDMenu(EntityUid owner, RCDMenuBoundUserInterface bui)
if (parent == null)
continue;

var name = Loc.GetString(proto.SetName);
name = char.ToUpper(name[0]) + name.Remove(0, 1);
var tooltip = Loc.GetString(proto.SetName);

if ((proto.Mode == RcdMode.ConstructTile || proto.Mode == RcdMode.ConstructObject) &&
proto.Prototype != null && _protoManager.TryIndex(proto.Prototype, out var entProto))
{
tooltip = Loc.GetString(entProto.Name);
}

tooltip = char.ToUpper(tooltip[0]) + tooltip.Remove(0, 1);

var button = new RCDMenuButton()
{
StyleClasses = { "RadialMenuButton" },
SetSize = new Vector2(64f, 64f),
ToolTip = name,
ToolTip = tooltip,
ProtoId = protoId,
};

Expand Down Expand Up @@ -120,6 +136,27 @@ private void AddRCDMenuButtonOnClickActions(Control control)
castChild.OnButtonUp += _ =>
{
SendRCDSystemMessageAction?.Invoke(castChild.ProtoId);

if (_playerManager.LocalSession?.AttachedEntity != null &&
_protoManager.TryIndex(castChild.ProtoId, out var proto))
{
var msg = Loc.GetString("rcd-component-change-mode", ("mode", Loc.GetString(proto.SetName)));

if (proto.Mode == RcdMode.ConstructTile || proto.Mode == RcdMode.ConstructObject)
{
var name = Loc.GetString(proto.SetName);

if (proto.Prototype != null &&
_protoManager.TryIndex(proto.Prototype, out var entProto))
name = entProto.Name;

msg = Loc.GetString("rcd-component-change-build-mode", ("name", name));
}

// Popup message
_popup.PopupClient(msg, _owner, _playerManager.LocalSession.AttachedEntity);
}

Close();
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public async Task CraftSpear()

// Player's hands should be full of the remaining rods, except those dropped during the failed crafting attempt.
// Spear and left over stacks should be on the floor.
await AssertEntityLookup((Rod, 2), (Cable, 8), (ShardGlass, 2), (Spear, 1));
await AssertEntityLookup((Rod, 2), (Cable, 7), (ShardGlass, 2), (Spear, 1));
}

// The following is wrapped in an if DEBUG. This is because of cursed state handling bugs. Tests don't (de)serialize
Expand Down Expand Up @@ -100,7 +100,7 @@ public async Task CancelCraft()
Assert.That(sys.IsEntityInContainer(rods), Is.False);
Assert.That(sys.IsEntityInContainer(wires), Is.False);
Assert.That(rodStack, Has.Count.EqualTo(8));
Assert.That(wireStack, Has.Count.EqualTo(8));
Assert.That(wireStack, Has.Count.EqualTo(7));

await FindEntity(Spear, shouldSucceed: false);
});
Expand Down
1 change: 1 addition & 0 deletions Content.IntegrationTests/Tests/PostMapInitTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public sealed class PostMapInitTest
"CorvaxMaus",
"CorvaxIshimura",
"CorvaxPaper",
"CorvaxSplit",
// Corvax-End
"Dev",
"TestTeg",
Expand Down
2 changes: 1 addition & 1 deletion Content.Server/Backmen/Research/Oracle/OracleSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public sealed class OracleSystem : EntitySystem
"BluespaceCrystal",
"InsulativeHeadcage",
"CrystalNormality",
"BodyBag_Folded",
"BodyBagFolded",
"BodyBag",
"LockboxDecloner",
"MopBucket",
Expand Down
63 changes: 54 additions & 9 deletions Content.Server/Connection/ConnectionManager.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Immutable;
using System.Runtime.InteropServices;
using System.Text.Json.Nodes;
using System.Threading.Tasks;
using Content.Corvax.Interfaces.Server;
Expand All @@ -12,6 +13,7 @@
using Robust.Server.Player;
using Robust.Shared.Configuration;
using Robust.Shared.Network;
using Robust.Shared.Timing;


namespace Content.Server.Connection
Expand All @@ -20,6 +22,18 @@ public interface IConnectionManager
{
void Initialize();
Task<bool> HavePrivilegedJoin(NetUserId userId); // Corvax-Queue

/// <summary>
/// Temporarily allow a user to bypass regular connection requirements.
/// </summary>
/// <remarks>
/// The specified user will be allowed to bypass regular player cap,
/// whitelist and panic bunker restrictions for <paramref name="duration"/>.
/// Bans are not bypassed.
/// </remarks>
/// <param name="user">The user to give a temporary bypass.</param>
/// <param name="duration">How long the bypass should last for.</param>
void AddTemporaryConnectBypass(NetUserId user, TimeSpan duration);
}

/// <summary>
Expand All @@ -37,15 +51,32 @@ public sealed class ConnectionManager : IConnectionManager
private IServerSponsorsManager? _sponsorsMgr; // Corvax-Sponsors
private IServerVPNGuardManager? _vpnGuardMgr; // Corvax-VPNGuard

[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly ILogManager _logManager = default!;

private readonly Dictionary<NetUserId, TimeSpan> _temporaryBypasses = [];
private ISawmill _sawmill = default!;

public void Initialize()
{
IoCManager.Instance!.TryResolveType(out _sponsorsMgr); // Corvax-Sponsors
_sawmill = _logManager.GetSawmill("connections");

_netMgr.Connecting += NetMgrOnConnecting;
_netMgr.AssignUserIdCallback = AssignUserIdCallback;
// Approval-based IP bans disabled because they don't play well with Happy Eyeballs.
// _netMgr.HandleApprovalCallback = HandleApproval;
}

public void AddTemporaryConnectBypass(NetUserId user, TimeSpan duration)
{
ref var time = ref CollectionsMarshal.GetValueRefOrAddDefault(_temporaryBypasses, user, out _);
var newTime = _gameTiming.RealTime + duration;
// Make sure we only update the time if we wouldn't shrink it.
if (newTime > time)
time = newTime;
}

/*
private async Task<NetApproval> HandleApproval(NetApprovalEventArgs eventArgs)
{
Expand Down Expand Up @@ -115,6 +146,20 @@ private async Task NetMgrOnConnecting(NetConnectingArgs e)
hwId = null;
}

var bans = await _db.GetServerBansAsync(addr, userId, hwId, includeUnbanned: false);
if (bans.Count > 0)
{
var firstBan = bans[0];
var message = firstBan.FormatBanMessage(_cfg, _loc);
return (ConnectionDenyReason.Ban, message, bans);
}

if (HasTemporaryBypass(userId))
{
_sawmill.Verbose("User {UserId} has temporary bypass, skipping further connection checks", userId);
return null;
}

var adminData = await _dbManager.GetAdminDataForAsync(e.UserId);

// Corvax-Start: Allow privileged players bypass bunker
Expand Down Expand Up @@ -192,14 +237,6 @@ private async Task NetMgrOnConnecting(NetConnectingArgs e)
return (ConnectionDenyReason.Full, Loc.GetString("soft-player-cap-full"), null);
}

var bans = await _db.GetServerBansAsync(addr, userId, hwId, includeUnbanned: false);
if (bans.Count > 0)
{
var firstBan = bans[0];
var message = firstBan.FormatBanMessage(_cfg, _loc);
return (ConnectionDenyReason.Ban, message, bans);
}

if (_cfg.GetCVar(CCVars.WhitelistEnabled))
{
var min = _cfg.GetCVar(CCVars.WhitelistMinPlayers);
Expand All @@ -220,6 +257,11 @@ private async Task NetMgrOnConnecting(NetConnectingArgs e)
return null;
}

private bool HasTemporaryBypass(NetUserId user)
{
return _temporaryBypasses.TryGetValue(user, out var time) && time > _gameTiming.RealTime;
}

private async Task<NetUserId?> AssignUserIdCallback(string name)
{
if (!_cfg.GetCVar(CCVars.GamePersistGuests))
Expand All @@ -239,11 +281,14 @@ private async Task NetMgrOnConnecting(NetConnectingArgs e)
}

// Corvax-Queue-Start: Make these conditions in one place, for checks in the connection and in the queue
[Dependency] private readonly IEntityManager _entityManager = default!;
public async Task<bool> HavePrivilegedJoin(NetUserId userId)
{
if (HasTemporaryBypass(userId))
return true;
var adminBypass = _cfg.GetCVar(CCVars.AdminBypassMaxPlayers) && await _dbManager.GetAdminDataForAsync(userId) != null;
var havePriorityJoin = _sponsorsMgr != null && _sponsorsMgr.HavePriorityJoin(userId); // Corvax-Sponsors
var wasInGame = EntitySystem.TryGet<GameTicker>(out var ticker) &&
var wasInGame = _entityManager.TrySystem<GameTicker>(out var ticker) &&
ticker.PlayerGameStatuses.TryGetValue(userId, out var status) &&
status == PlayerGameStatus.JoinedGame;
return adminBypass ||
Expand Down
Loading
Loading