Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
8794ae2
Added two new songs for the Jukebox
KarmaKitsuna Aug 22, 2025
fbda750
Update attributions.yml
KarmaKitsuna Aug 22, 2025
6c012ac
Merge remote-tracking branch 'Starlight/starlight-dev' into Starlight…
KarmaKitsuna Aug 22, 2025
0df7fcd
revert unintended changes
KarmaKitsuna Aug 22, 2025
c2e4c95
vulps need to speak fox
DoubleHypercube Aug 23, 2025
56f3385
Woof.
DoubleHypercube Aug 23, 2025
ab37a50
Merge pull request #1435 from KarmaKitsuna/Starlight-added-songs
StarlightHost Aug 23, 2025
06f2251
Update changelog for PR #1435 [skip ci]
github-actions[bot] Aug 23, 2025
d70da11
fix
StarlightHost Aug 23, 2025
1a4256c
fix
StarlightHost Aug 23, 2025
99d4f35
reintroduce event for knocbkack to work properly
Happyrobot33 Aug 23, 2025
b4c7556
zombified prevents language cloning
walksanatora Aug 23, 2025
e1ee23b
Happy's requests
DoubleHypercube Aug 23, 2025
8ae40ee
mothroach
DoubleHypercube Aug 23, 2025
637f6f0
Merge pull request #1453 from walksanatora/zombie-lose-lang
ShadesMars Aug 23, 2025
6442ca5
Update changelog for PR #1453 [skip ci]
github-actions[bot] Aug 23, 2025
a00c974
Update Resources/Prototypes/_StarLight/Language/Animals/mothroach.yml
DoubleHypercube Aug 23, 2025
0d4286b
yaml fix
DoubleHypercube Aug 23, 2025
4966efa
Merge branch 'starlight-dev' into vulpkanin_lang_fix
DoubleHypercube Aug 23, 2025
75173e5
Merge pull request #1451 from ss14Starlight/nullLink/trycath
StarlightHost Aug 24, 2025
e62d026
antag
StarlightHost Aug 17, 2025
a67c754
enable rr
StarlightHost Aug 24, 2025
15c1d4a
fix 20 min
StarlightHost Aug 24, 2025
80f19d2
fix filename
StarlightHost Aug 24, 2025
dac94a8
Merge pull request #1446 from AutumnalModding/vulpkanin_lang_fix
ShadesMars Aug 24, 2025
d26a328
Update changelog for PR #1446 [skip ci]
github-actions[bot] Aug 24, 2025
776700f
Merge pull request #1461 from ss14Starlight/railroading/criminal
StarlightHost Aug 24, 2025
73db1ae
Merge pull request #1452 from Happyrobot33/fix-knockback
StarlightHost Aug 24, 2025
73db4b5
Update changelog for PR #1452 [skip ci]
github-actions[bot] Aug 24, 2025
5241718
Update changelog for PR #1461 [skip ci]
StarlightHost Aug 24, 2025
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
79 changes: 46 additions & 33 deletions Content.Server/Administration/Managers/BanManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public sealed partial class BanManager : IBanManager, IPostInjectInit

public const string SawmillId = "admin.bans";
public const string JobPrefix = "Job:";

private readonly HttpClient _httpClient = new();
private string _serverName = string.Empty;
private string _webhookUrl = string.Empty;
Expand All @@ -79,7 +79,7 @@ public void Initialize()
BanNotificationChannel,
ProcessBanNotification,
OnDatabaseNotificationEarlyFilter);

_cfg.OnValueChanged(StarlightCCVars.DiscordBanWebhook, OnWebhookChanged, true);
_cfg.OnValueChanged(CVars.GameHostName, OnServerNameChanged, true);

Expand Down Expand Up @@ -309,7 +309,7 @@ public async void CreateRoleBan(NetUserId? target, string? targetUsername, NetUs
SendRoleBans(session);
}
}

public async void WebhookUpdateRoleBans(NetUserId? target, string? targetUsername, NetUserId? banningAdmin, (IPAddress, int)? addressRange, ImmutableTypedHwid? hwid, IReadOnlyCollection<string> roles, uint? minutes, NoteSeverity severity, string reason, DateTimeOffset timeOfBan)
{
_systems.TryGetEntitySystem(out GameTicker? ticker);
Expand Down Expand Up @@ -406,7 +406,7 @@ public void PostInject()
{
_sawmill = _logManager.GetSawmill(SawmillId);
}

#region Webhook
private async void SendWebhook(WebhookPayload payload)
{
Expand All @@ -429,7 +429,7 @@ private async void SendWebhook(WebhookPayload payload)
return;
}
}

private async Task<WebhookPayload> GenerateJobBanPayload(ServerRoleBanDef banDef, IReadOnlyCollection<string> roles, uint? minutes = null)
{
var hwid = banDef.HWId?.ToString() ?? "null";
Expand All @@ -450,38 +450,44 @@ private async Task<WebhookPayload> GenerateJobBanPayload(ServerRoleBanDef banDef
string? adminDiscordId = null;
string? targetDiscordId = null;

if (_actor.TryGetServerGrain(out var serverGrain))
try
{
if (banDef.BanningAdmin != null)
adminDiscordId = await serverGrain.GetPlayerDiscordId(banDef.BanningAdmin.Value)
.Then(x => x.ToString());
if (_actor.TryGetServerGrain(out var serverGrain))
{
if (banDef.BanningAdmin != null)
adminDiscordId = await serverGrain.GetPlayerDiscordId(banDef.BanningAdmin.Value)
.Then(x => x != 0 ? x.ToString() : null);

if (banDef.UserId != null)
targetDiscordId = await serverGrain.GetPlayerDiscordId(banDef.UserId.Value)
.Then(x => x.ToString());
if (banDef.UserId != null)
targetDiscordId = await serverGrain.GetPlayerDiscordId(banDef.UserId.Value)
.Then(x => x != 0 ? x.ToString() : null);
}
}
catch (Exception)
{
}
// nulllink end

var adminLink = "";
var targetLink = "";
var mentions = new List<User>{};
var mentions = new List<User> { };
if (adminDiscordId != null)
{
adminLink = $"<@{adminDiscordId}>";
mentions.Add(new User(){Id = adminDiscordId});
mentions.Add(new User() { Id = adminDiscordId });
}

if (targetDiscordId != null)
{
targetLink = $"<@{targetDiscordId}>";
mentions.Add(new User(){Id = targetDiscordId});
mentions.Add(new User() { Id = targetDiscordId });
}

var allowedMentions = new Dictionary<string, string[]>
{
{ "parse", new List<string> {"users"}.ToArray() }
};

if (banDef.ExpirationTime != null && minutes != null) // Time ban
return new WebhookPayload
{
Expand Down Expand Up @@ -543,7 +549,7 @@ private async Task<WebhookPayload> GenerateJobBanPayload(ServerRoleBanDef banDef
},
};
}

private async Task<WebhookPayload> GenerateBanPayload(ServerBanDef banDef, uint? minutes = null)
{
var hwid = banDef.HWId?.ToString() ?? "null";
Expand All @@ -561,31 +567,38 @@ private async Task<WebhookPayload> GenerateBanPayload(ServerBanDef banDef, uint?
string? adminDiscordId = null;
string? targetDiscordId = null;

if (_actor.TryGetServerGrain(out var serverGrain))
try
{
if(banDef.BanningAdmin != null)
adminDiscordId = await serverGrain.GetPlayerDiscordId(banDef.BanningAdmin.Value)
.Then(x=>x.ToString());
if (_actor.TryGetServerGrain(out var serverGrain))
{
if (banDef.BanningAdmin != null)
adminDiscordId = await serverGrain.GetPlayerDiscordId(banDef.BanningAdmin.Value)
.Then(x => x != 0 ? x.ToString() : null);

if (banDef.UserId != null)
targetDiscordId = await serverGrain.GetPlayerDiscordId(banDef.UserId.Value)
.Then(x => x.ToString());
if (banDef.UserId != null)
targetDiscordId = await serverGrain.GetPlayerDiscordId(banDef.UserId.Value)
.Then(x => x != 0 ? x.ToString() : null);
}
}
catch (Exception)
{
}

// nulllink end

var adminLink = "";
var targetLink = "";
var mentions = new List<User>{};
var mentions = new List<User> { };
if (adminDiscordId != null)
{
adminLink = $"<@{adminDiscordId}>";
mentions.Add(new User(){Id = adminDiscordId});
mentions.Add(new User() { Id = adminDiscordId });
}

if (targetDiscordId != null)
{
targetLink = $"<@{targetDiscordId}>";
mentions.Add(new User(){Id = targetDiscordId});
mentions.Add(new User() { Id = targetDiscordId });
}

var allowedMentions = new Dictionary<string, string[]>
Expand Down Expand Up @@ -654,7 +667,7 @@ private async Task<WebhookPayload> GenerateBanPayload(ServerBanDef banDef, uint?
},
};
}

private void OnWebhookChanged(string url)
{
_webhookUrl = url;
Expand Down Expand Up @@ -684,12 +697,12 @@ private void OnWebhookChanged(string url)
// Fire and forget
_ = SetWebhookData(webhookId, webhookToken);
}

private void OnServerNameChanged(string obj)
{
_serverName = obj;
}

private async Task SetWebhookData(string id, string token)
{
var response = await _httpClient.GetAsync($"https://discord.com/api/v10/webhooks/{id}/{token}");
Expand Down Expand Up @@ -725,7 +738,7 @@ public Embed()
{
}
}

// https://discord.com/developers/docs/resources/channel#embed-object-embed-author-structure
private struct EmbedAuthor
{
Expand All @@ -739,7 +752,7 @@ public EmbedAuthor()
{
}
}

// https://discord.com/developers/docs/resources/webhook#webhook-object-webhook-structure
private struct WebhookData
{
Expand All @@ -753,7 +766,7 @@ public WebhookData()
{
}
}

// https://discord.com/developers/docs/resources/channel#message-object-message-structure
private struct WebhookPayload
{
Expand Down
16 changes: 13 additions & 3 deletions Content.Server/Connection/ConnectionManager.Whitelist.cs
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,19 @@ private bool CheckConditionPlaytime(ConditionPlaytime conditionPlaytime, List<Pl
}

// NullLink Whitelist start
private async Task<bool> CheckNullLinkRolesCondition(NullLinkRolesCondition condition, NetUserId userId)
=> _actors.TryGetServerGrain(out var server)
&& await server.HasPlayerAnyRole(userId, [.. condition.Roles]);
private async Task<bool> CheckNullLinkRolesCondition(NullLinkRolesCondition condition, NetUserId userId)
{
try
{
return _actors.TryGetServerGrain(out var server)
&& await server.HasPlayerAnyRole(userId, [.. condition.Roles]);
}
catch (Exception)
{
}
return false;
}

// NullLink Whitelist end

private bool CheckConditionNotesPlaytimeRange(
Expand Down
14 changes: 10 additions & 4 deletions Content.Server/Connection/ConnectionManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -271,10 +271,16 @@ session.Status is SessionStatus.Connected or SessionStatus.InGame
var bypassAllowed = _cfg.GetCVar(CCVars.BypassBunkerWhitelist) && await _db.GetWhitelistStatusAsync(userId);

// NullLink Bypass start
if (!validAccountAge
&& _roleReqPeacefulBypass is not null
&& _actors.TryGetServerGrain(out var serverGrain))
validAccountAge = await serverGrain.HasPlayerAnyRole(userId, _roleReqPeacefulBypass.Roles);
try
{
if (!validAccountAge
&& _roleReqPeacefulBypass is not null
&& _actors.TryGetServerGrain(out var serverGrain))
validAccountAge = await serverGrain.HasPlayerAnyRole(userId, _roleReqPeacefulBypass.Roles);
}
catch (Exception)
{
}
// NullLink Bypass end

// Use the custom reason if it exists & they don't have the minimum account age
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using Content.Server.Chat.Systems;
using Content.Server.GameTicking;
using Content.Shared._Starlight.Railroading;
using Content.Shared._Starlight.Railroading.Events;
using Content.Shared.Starlight.Economy;
using Robust.Server.Player;
using Robust.Shared.Player;
using Robust.Shared.Random;

namespace Content.Server._Starlight.Railroading;

public sealed partial class RailroadingAnnounceHandlerSystem : EntitySystem
{
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly ChatSystem _chatSystem = default!;
[Dependency] private readonly GameTicker _gameTicker = default!;

public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<RailroadAnnounceOnChosenComponent, RailroadingCardChosenEvent>(OnChosen);
}

private void OnChosen(Entity<RailroadAnnounceOnChosenComponent> ent, ref RailroadingCardChosenEvent args)
=> _chatSystem.DispatchFilteredAnnouncement
(
Filter.Empty().AddWhere(_gameTicker.UserHasJoinedGame),
Loc.GetString(_random.Pick(ent.Comp.Text)),
playSound: ent.Comp.PlaySound,
announcementSound: ent.Comp.Sound,
colorOverride: ent.Comp.Color
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Content.Server.Mind;
using Content.Server.Roles;
using Content.Shared._Starlight.Railroading;
using Content.Shared._Starlight.Railroading.Events;
using Content.Shared.Mind.Components;
using Content.Shared.Roles.Components;

namespace Content.Server._Starlight.Railroading;

public sealed partial class RailroadingAssignRoleHandlerSystem : EntitySystem
{
[Dependency] private readonly RoleSystem _roles = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<RailroadAssignRoleComponent, RailroadingCardChosenEvent>(OnChosen);
}

private void OnChosen(Entity<RailroadAssignRoleComponent> ent, ref RailroadingCardChosenEvent args)
{
if(TryComp<MindContainerComponent>(args.Subject, out var mindContainer)
&& mindContainer.Mind.HasValue)
{
_roles.MindAddRole(mindContainer.Mind.Value, ent.Comp.Role);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using Content.Server.Fax;
using Content.Shared._Starlight.Railroading;
using Content.Shared._Starlight.Railroading.Events;
using Content.Shared.DeviceNetwork;
using Content.Shared.DeviceNetwork.Events;
using Content.Shared.Fax.Components;
using Robust.Shared.Random;

namespace Content.Server._Starlight.Railroading;

public sealed partial class RailroadingFaxHandlerSystem : EntitySystem
{
[Dependency] private readonly IRobustRandom _random = default!;

public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<RailroadFaxOnChosenComponent, RailroadingCardChosenEvent>(OnChosen);
}

private void OnChosen(Entity<RailroadFaxOnChosenComponent> ent, ref RailroadingCardChosenEvent args)
{
var letter = _random.Pick(ent.Comp.Letters);

var payload = new NetworkPayload
{
[DeviceNetworkConstants.Command] = FaxConstants.FaxPrintCommand,
[FaxConstants.FaxPaperNameData] = Loc.GetString(letter.PaperName, ("subject", args.Subject)),
[FaxConstants.FaxPaperContentData] = Loc.GetString(letter.PaperContent, ("subject",args.Subject)),
[FaxConstants.FaxPaperLabelData] = letter.PaperLabel,
[FaxConstants.FaxPaperStampStateData] = letter.StampState,
[FaxConstants.FaxPaperStampedByData] = letter.StampedBy,
[FaxConstants.FaxPaperPrototypeData] = letter.PaperPrototype,
[FaxConstants.FaxPaperLockedData] = letter.Locked
};

var query = EntityQueryEnumerator<FaxMachineComponent>();
while (query.MoveNext(out var faxEnt, out var faxComp))
{
if (!ent.Comp.Addresses.Contains(faxComp.FaxName))
continue;
var @event = new DeviceNetworkPacketEvent
(
0,
null,
0,
"NT",
EntityUid.Invalid,
payload
);
RaiseLocalEvent(faxEnt, @event);
}
}
}
4 changes: 4 additions & 0 deletions Content.Server/_Starlight/Railroading/RailroadingSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ public void OnCardSelected(Entity<RailroadableComponent> subject, NetEntity card
{
subject.Comp.ActiveCard = card;
_adminLogger.Add(LogType.Railroading, LogImpact.Medium, $"{ToPrettyString(subject)} selected card {ToPrettyString(cardUid)}.");

var cardPerformer = EnsureComp<RailroadCardPerformerComponent>(card);
cardPerformer.Performer = subject;

var @event = new RailroadingCardChosenEvent(subject);
RaiseLocalEvent(card, ref @event);
}
Expand Down
Loading
Loading