Files
crystall-punk-14/Content.Server/Database/ServerDbBase.cs

1847 lines
68 KiB
C#
Raw Normal View History

2021-03-22 01:30:50 +01:00
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Net;
2023-12-10 16:30:12 +01:00
using System.Runtime.CompilerServices;
using System.Text.Json;
2020-11-10 16:50:28 +01:00
using System.Threading;
using System.Threading.Tasks;
using Content.Server.Administration.Logs;
using Content.Server.Administration.Managers;
using Content.Shared.Administration.Logs;
using Content.Shared.Database;
Humanoid appearance refactor (#10882) * initial commit - species prototype modifications - markings points as its own file - shared humanoid component * adds a tool to convert sprite accessories to markings (in go) * removes a fmt call * converts sprite accessory to markings * adds hair and facial hair to marking categories * multiple changes - humanoid visualizer system - markings modifications for visualizer - modifications to shared humanoid component - lays out a base for humanoid system * hidden layers, ports some properties from appearance component, shrinks DefaultMarkings a little * squishes the initialize event calls into one function adds stuff to set species/skin color externally from a server message - currently laid out as if it a dirty call to a networked component, may be subject to change (server-side has not been implemented yet) * makes the sprite pipeline more obvious * apply all markings, hidden layer set replacement * ensures that markings are cleared when the new set is applied * starts refactoring markingsset (unfinished) * more additions to the markingset api * adds constructor logic to markingset * adds a method to filter out markings in a set based on a given species * fixes enumerators in markingset * adds validator into MarkingSet, fixes ForwardMarkingEnumerator * modifications to the humanoid visual system * ensuredefault in markingset * oop * fixes up data keys, populates OnAppearanceChange in visualizer * changes to humanoid component, markings marking equality is now more strict, humanoidcomponent is now implemented for client as a child of sharedhumanoidcomponent * markings are now applied the visualizer by diffing them * base sprites are now applied to humanoids from humanoidvisualizer * passes along base sprite settings to the marking application so that markings know to follow skin color/alpha or not (see: slimes) * custom base layers on humanoids * merges all data keys into one data class for humanoid visualizers * setappearance in sharedhumanoidsystem, removes custombaselayercolors * humanoidcomponent, system (empty) in server * adds some basic public API functions to HumanoidSystem * add marking, remove marking * changes appearance MarkingsSet to a List<Marking>, adds listener for PlayerSpawnCompleteEvent in HumanoidSystem * ensuredefaultmarkings, oninit for humanoids * markingmanager API changes * removes MarkingsSet * LoadProfile, adjusts randomization in humanoid appearance to account for species * base layer settings in humanoidsystem, eye color from profile * rearranges files to centralize under Humanoid namespace * more reorganization, deletes some stuff gotta break stuff to make other things work, right? goodbye SpriteAccessory... * fixes a good chunk of server-side issues still does not compile, yet * singlemarkingpicker xaml layout * singlemarkingpicker logic * magic mirror window (varying pieces of it, mostly client-oriented) * removes some imports, gives MagicMirror a BUI class (not filled in yet) * populates magic mirror BUI functionality / window callbacks * fixes up some errors in humanoidprofileeditor * changes to SingleMarkingPicker SingleMarkingPicker now accepts a List<Marking>, species, and total possible markings available in that marking category * fixes up hair pickers on humanoid profile editor * fixes the errors in markingpicker * markingsystem is now gone * fixes a bunch of build errors * so that's why i did it like that * namespace issues, adds robustxamlloader to singlemarkingpicker * another robustxamlloader * human, lizard sprites/points * prototype fixes, deletion of old spriteaccessory * component registration, fixes dwarf skin toning no, 'ReptilianToned' does not exist * removes component registration from abstract humanoid component * visualizer data now cloneable * serialize for visualizer key * zero-count edge case * missing semi-colon moment * setspecies in humanoidsystem * ensures that default markings, if empty, will cause ensuredefault to skip over that given category * tryadd instead of add * whoops * diff and apply should properly apply markings now * always ensure default, fixes double load for player spawning * apply skin color now sets the skin color property in humanoidcomponent * removes sprite from a few species prototypes * sprite changes for specific base layers based on humanoid sex * layer ordering fix, and a missing base layer should now disallow markings on that layer * anymarking base layer, adds the right leg/foot for humans * loading a profile will now clear all markings on that humanoid * adds missing layers for humans * separates species.yml into respective species prototype files * ensures that if layer visibility was changed, all markings have to be reapplied * server-side enforcement of hiding hair (and other head-related markings) when equipping things that hide hair * slime fix, clothingsystem now dictates layer visibility server side * sussy * layer settings should now ensure a marking should match the skin tone * whoops * skincolor static class and functions in UI * skin color validation in humanoidcharacterappearance * markingpicker now shows only the markings for the selected category in used * getter for slot in singlemarkingpicker now ensures slot is 0 if markings exists * FilterSpecies no longer attempts to do removal while iterating * expands for SingleMarkingPicker * humanoid base dummy has blank layers now (and snout/tail/headside/headtop) * fixes an issue with visualizer system if the marking count was different but the markings themselves were (somewhat) the same * whoops * adds edge case handlers for count differences in humanoid markings * preview now loads profile instead of directly setting appearance * moves marking set loading to update controls * clones a marking set in markingpicker by using the deep clone constructor * whoops (deep cloning a marking now copies the marking id) * adds replace function for markingset * points should now update after the markings are remove/added * merging base layer sprites into a humanoid should now clear them before merging * sets dirty range start to count only if the dirty range start was never set above 0 * fixes up some issues with singlemarkingpicker * color selector sliders in single marking picker should now expand * hair from hair pickers should now apply in profile loading (client-side) * category in singlemarkingpicker now sets the private category variable * slot selector should now populate * single marking picker buttons now have text, also shows the category name over all user-clickable elements * removes a comment * removing hair slots now sets it to bald, defaults to zero used slots if current hair is bald on hair/facial hair * random skin color, eye color * populate colors now checks if the marking count is greater than zero in singlemarkingpicker * hair/facial hair pickers now just get the first possible hair from the respective species list * different approach to random skin color * oh, that's why it wasn't working * randomize everything now just updates every single control * selecting a new marking in SingleMarkingPicker should attempt to copy over old colors, populate list now uses cache, * markingmanager now uses OnlyWhitelisted to populate by category and species * filterspecies now uses onlyWhitelist to filter markings based on whitelist or not * oops * ui fix for singlemarkingpicker, ensures that cache is not null if it is null when populatelist is called * order of operations for the horizontal expand for add/remove * hair pickers should now update when you add/remove the hair slot * fixes variable naming error in character appearance * loc string fix in singlemarkingpicker * lizards, vox now have onlyWhitelist, vox restriction for hair/facialhairs * having zero possible hairs should no longer cause an exception in randomization * setting species should now update hair pickers * ignore categories for marking picker * and a clear as well for the category button * places that functionality in its own function instead * adds eye base sprite, vox now also have their own custom eye sprites * loading a profile client-side should do FilterSpecies for markings now * client-side load profile does filter species after adding in the hairs now * magic mirror * callbacks now call the callback instead of adding it on construct * whoops * in removemarking too * adds missing synchronize calls * comments out an updateinterface call in magic mirror * magic mirror window title, minimum sizing * fixes minsize, adds warning for players who try to set their hair for species that have no hair * removes spaces in xaml * namespace changes/organization * whoopsie (merge conflicts) * re-enables identity from humanoid component * damagevisuals now uses the enum given to it instead of the layerstate given on that layer tied to the enum * removes commas from json * changes to visuals system so the change is consistent * chest * reptilian * visualizer system now handles body sprite setting/coloration, similar to how characterappearance did it not a big fan of this * adds a check in applybasesprites * adding/removing parts should now make them invisible on a humanoid * body part removal/adding now enumerates over sublayers instead * synchro now runs in bodycomponent startup * parts instead of slots * humanoidcompnent check * switches from rsi to actualrsi * removes all the body stuff (too slow) * cleans up resolves from humanoid visualizer system * merging sprites now checks if the base sprites have been modified or not (through things like species changes, or custom base sprite changes) * not forgetting that one again * merging now returns an actual dirty value * replaces the sequenceequal with a more accurate solution * permanent layers, layer visibility on add/remove part in body * should send all hidden layers over now * isdirty in visualizer system for base layers * isdirty checks count as well * ok, IsDirty should now set the base layers if the merged sprites are different * equals override in HumanoidSpritePrototypes.cs temporary until record prototypes :heck: * makes fields readonly, equates IDs instead * adds forced markings through marking picker * forced in humanoidsystem api, ignorespecies in markingpicker * marking bui * makes that serializable as well * ignore species/forced toggles now work * adds icon to modifier verb, interface and keys to humanoid bases * needs the actual enum value to open, no? * makes the key the actual key * actions now propagate upwards * ignore species when set now repopulates markingpicker * modifiable base layers in the markings window * oops! * layout changes * info box should now appear * adds ignorespecies for marking picker, collapsible for base layer section of appearance modification window * collapsible layout moment * if base layers have changed, all markings are now dirty (and if a base layer is missing, the marking is still 'applied' but it's now just invisible * small change to marking visibility * small changes to modifier UI * markings now match skin on zombification * zombie stuff * makes the line edit in marking modifier window more obvious * disables vox on round start * horizontal expand on the single label in base layer modifiers * humanoid profiles in prototypes * randomhumanoidappearance won't work if the humanoid has a profile already stored * removes unused code * documentation in humanoidsystem server-side * documentation in shared/client * whoops * converts accessory into marking in locale files (also adds marking loc string into single marking picker) * be gone, shared humanoid appearance system from the last upstream merge * species ignore on randomization (defaults to no ignored species) * more upstream merge parts that bypassed any errors before merge * addresses review (also just adds typeserializers in some places) * submodule moment * upstream merge issues
2022-09-22 15:19:00 -07:00
using Content.Shared.Humanoid;
using Content.Shared.Humanoid.Markings;
using Content.Shared.Preferences;
Loadouts redux (#25715) * Loadouts redux * Loadout window mockup * More workout * rent * validation * Developments * bcs * More cleanup * Rebuild working * Fix model and loading * obsession * efcore * We got a stew goin * Cleanup * Optional + SeniorEngineering fix * Fixes * Update science.yml * add add * Automatic naming * Update nukeops * Coming together * Right now * stargate * rejig the UI * weh * Loadouts tweaks * Merge conflicts + ordering fix * yerba mate * chocolat * More updates * Add multi-selection support * test h * fikss * a * add tech assistant and hazard suit * huh * Latest changes * add medical loadouts * and science * finish security loadouts * cargo * service done * added wildcards * add command * Move restrictions * Finalising * Fix existing work * Localise next batch * clothing fix * Fix storage names * review * the scooping room * Test fixes * Xamlify * Xamlify this too * Update Resources/Prototypes/Loadouts/Jobs/Medical/paramedic.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/loadout_groups.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/Jobs/Civilian/clown.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/Jobs/Civilian/clown.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/loadout_groups.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/Jobs/Security/detective.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/loadout_groups.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * ben * Margins --------- Co-authored-by: Firewatch <54725557+musicmanvr@users.noreply.github.com> Co-authored-by: Mr. 27 <koolthunder019@gmail.com> Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com>
2024-04-16 22:57:43 +10:00
using Content.Shared.Preferences.Loadouts;
using Content.Shared.Roles;
using Content.Shared.Traits;
using Microsoft.EntityFrameworkCore;
using Robust.Shared.Enums;
using Robust.Shared.Network;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
namespace Content.Server.Database
{
public abstract class ServerDbBase
{
2023-12-10 16:30:12 +01:00
private readonly ISawmill _opsLog;
Kick on ban for entire server group (#28649) * Start work on PostgresNotificationManager Implement initial version of init and listening code * Finish implementing PostgresNotificationManager Implement ban insert trigger * Implement ignoring notifications if the ban was from the same server * Address reviews * Fixes and refactorings Fix typo in migration SQL Pull new code in BanManager out into its own partial file. Unify logic to kick somebody with that when a new ban is placed directly on the server. New bans are now checked against all parameters (IP, HWID) instead of just user ID. Extracted SQLite ban matching code into a new class so that it can mostly be re-used by the ban notification code. No copy-paste here. Database notifications are now not implicitly sent to the main thread, this means basic checks will happen in the thread pool beforehand. Bans without user ID are now sent to servers. Bans are rate limited to avoid undue work from mass ban imports, beyond the rate limit they are dropped. Improved error handling and logging for the whole system. Matching bans against connected players requires knowing their ban exemption flags. These are now cached when the player connects. ServerBanDef now has exemption flags, again to allow matching full ban details for ban notifications. Made database notifications a proper struct type to reduce copy pasting a tuple. Remove copy pasted connection string building code by just... passing the string into the constructor. Add lock around _notificationHandlers just in case. Fixed postgres connection wait not being called in a loop and therefore spamming LISTEN commands for every received notification. Added more error handling and logging to notification listener. Removed some copy pasting from SQLite database layer too while I was at it because god forbid we expect anybody else to do all the work in this project. Sorry Julian --------- Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com>
2024-08-20 23:31:33 +02:00
public event Action<DatabaseNotification>? OnNotificationReceived;
2023-12-10 16:30:12 +01:00
/// <param name="opsLog">Sawmill to trace log database operations to.</param>
public ServerDbBase(ISawmill opsLog)
{
_opsLog = opsLog;
}
#region Preferences
public async Task<PlayerPreferences?> GetPlayerPreferencesAsync(
NetUserId userId,
CancellationToken cancel = default)
{
await using var db = await GetDb(cancel);
var prefs = await db.DbContext
.Preference
.Include(p => p.Profiles).ThenInclude(h => h.Jobs)
.Include(p => p.Profiles).ThenInclude(h => h.Antags)
2022-09-10 17:40:06 +02:00
.Include(p => p.Profiles).ThenInclude(h => h.Traits)
Loadouts redux (#25715) * Loadouts redux * Loadout window mockup * More workout * rent * validation * Developments * bcs * More cleanup * Rebuild working * Fix model and loading * obsession * efcore * We got a stew goin * Cleanup * Optional + SeniorEngineering fix * Fixes * Update science.yml * add add * Automatic naming * Update nukeops * Coming together * Right now * stargate * rejig the UI * weh * Loadouts tweaks * Merge conflicts + ordering fix * yerba mate * chocolat * More updates * Add multi-selection support * test h * fikss * a * add tech assistant and hazard suit * huh * Latest changes * add medical loadouts * and science * finish security loadouts * cargo * service done * added wildcards * add command * Move restrictions * Finalising * Fix existing work * Localise next batch * clothing fix * Fix storage names * review * the scooping room * Test fixes * Xamlify * Xamlify this too * Update Resources/Prototypes/Loadouts/Jobs/Medical/paramedic.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/loadout_groups.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/Jobs/Civilian/clown.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/Jobs/Civilian/clown.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/loadout_groups.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/Jobs/Security/detective.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/loadout_groups.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * ben * Margins --------- Co-authored-by: Firewatch <54725557+musicmanvr@users.noreply.github.com> Co-authored-by: Mr. 27 <koolthunder019@gmail.com> Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com>
2024-04-16 22:57:43 +10:00
.Include(p => p.Profiles)
.ThenInclude(h => h.Loadouts)
.ThenInclude(l => l.Groups)
.ThenInclude(group => group.Loadouts)
.AsSplitQuery()
.SingleOrDefaultAsync(p => p.UserId == userId.UserId, cancel);
if (prefs is null)
return null;
var maxSlot = prefs.Profiles.Max(p => p.Slot) + 1;
var profiles = new Dictionary<int, ICharacterProfile>(maxSlot);
foreach (var profile in prefs.Profiles)
{
profiles[profile.Slot] = ConvertProfiles(profile);
}
return new PlayerPreferences(profiles, prefs.SelectedCharacterSlot, Color.FromHex(prefs.AdminOOCColor));
}
public async Task SaveSelectedCharacterIndexAsync(NetUserId userId, int index)
{
await using var db = await GetDb();
await SetSelectedCharacterSlotAsync(userId, index, db.DbContext);
await db.DbContext.SaveChangesAsync();
}
public async Task SaveCharacterSlotAsync(NetUserId userId, ICharacterProfile? profile, int slot)
{
await using var db = await GetDb();
if (profile is null)
{
await DeleteCharacterSlot(db.DbContext, userId, slot);
await db.DbContext.SaveChangesAsync();
return;
}
if (profile is not HumanoidCharacterProfile humanoid)
{
// TODO: Handle other ICharacterProfile implementations properly
throw new NotImplementedException();
}
var oldProfile = db.DbContext.Profile
.Include(p => p.Preference)
.Where(p => p.Preference.UserId == userId.UserId)
.Include(p => p.Jobs)
.Include(p => p.Antags)
.Include(p => p.Traits)
Loadouts redux (#25715) * Loadouts redux * Loadout window mockup * More workout * rent * validation * Developments * bcs * More cleanup * Rebuild working * Fix model and loading * obsession * efcore * We got a stew goin * Cleanup * Optional + SeniorEngineering fix * Fixes * Update science.yml * add add * Automatic naming * Update nukeops * Coming together * Right now * stargate * rejig the UI * weh * Loadouts tweaks * Merge conflicts + ordering fix * yerba mate * chocolat * More updates * Add multi-selection support * test h * fikss * a * add tech assistant and hazard suit * huh * Latest changes * add medical loadouts * and science * finish security loadouts * cargo * service done * added wildcards * add command * Move restrictions * Finalising * Fix existing work * Localise next batch * clothing fix * Fix storage names * review * the scooping room * Test fixes * Xamlify * Xamlify this too * Update Resources/Prototypes/Loadouts/Jobs/Medical/paramedic.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/loadout_groups.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/Jobs/Civilian/clown.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/Jobs/Civilian/clown.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/loadout_groups.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/Jobs/Security/detective.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/loadout_groups.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * ben * Margins --------- Co-authored-by: Firewatch <54725557+musicmanvr@users.noreply.github.com> Co-authored-by: Mr. 27 <koolthunder019@gmail.com> Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com>
2024-04-16 22:57:43 +10:00
.Include(p => p.Loadouts)
.ThenInclude(l => l.Groups)
.ThenInclude(group => group.Loadouts)
.AsSplitQuery()
.SingleOrDefault(h => h.Slot == slot);
var newProfile = ConvertProfiles(humanoid, slot, oldProfile);
if (oldProfile == null)
{
var prefs = await db.DbContext
.Preference
.Include(p => p.Profiles)
.SingleAsync(p => p.UserId == userId.UserId);
prefs.Profiles.Add(newProfile);
}
await db.DbContext.SaveChangesAsync();
}
private static async Task DeleteCharacterSlot(ServerDbContext db, NetUserId userId, int slot)
{
var profile = await db.Profile.Include(p => p.Preference)
.Where(p => p.Preference.UserId == userId.UserId && p.Slot == slot)
.SingleOrDefaultAsync();
if (profile == null)
{
return;
}
db.Profile.Remove(profile);
}
public async Task<PlayerPreferences> InitPrefsAsync(NetUserId userId, ICharacterProfile defaultProfile)
{
await using var db = await GetDb();
var profile = ConvertProfiles((HumanoidCharacterProfile) defaultProfile, 0);
var prefs = new Preference
{
UserId = userId.UserId,
SelectedCharacterSlot = 0,
AdminOOCColor = Color.Red.ToHex()
};
prefs.Profiles.Add(profile);
db.DbContext.Preference.Add(prefs);
await db.DbContext.SaveChangesAsync();
return new PlayerPreferences(new[] {new KeyValuePair<int, ICharacterProfile>(0, defaultProfile)}, 0, Color.FromHex(prefs.AdminOOCColor));
}
public async Task DeleteSlotAndSetSelectedIndex(NetUserId userId, int deleteSlot, int newSlot)
{
await using var db = await GetDb();
await DeleteCharacterSlot(db.DbContext, userId, deleteSlot);
await SetSelectedCharacterSlotAsync(userId, newSlot, db.DbContext);
await db.DbContext.SaveChangesAsync();
}
public async Task SaveAdminOOCColorAsync(NetUserId userId, Color color)
{
await using var db = await GetDb();
var prefs = await db.DbContext
.Preference
.Include(p => p.Profiles)
.SingleAsync(p => p.UserId == userId.UserId);
prefs.AdminOOCColor = color.ToHex();
await db.DbContext.SaveChangesAsync();
}
private static async Task SetSelectedCharacterSlotAsync(NetUserId userId, int newSlot, ServerDbContext db)
{
var prefs = await db.Preference.SingleAsync(p => p.UserId == userId.UserId);
prefs.SelectedCharacterSlot = newSlot;
}
private static HumanoidCharacterProfile ConvertProfiles(Profile profile)
{
var jobs = profile.Jobs.ToDictionary(j => new ProtoId<JobPrototype>(j.JobName), j => (JobPriority) j.Priority);
var antags = profile.Antags.Select(a => new ProtoId<AntagPrototype>(a.AntagName));
var traits = profile.Traits.Select(t => new ProtoId<TraitPrototype>(t.TraitName));
var sex = Sex.Male;
if (Enum.TryParse<Sex>(profile.Sex, true, out var sexVal))
sex = sexVal;
var spawnPriority = (SpawnPriorityPreference) profile.SpawnPriority;
var gender = sex == Sex.Male ? Gender.Male : Gender.Female;
if (Enum.TryParse<Gender>(profile.Gender, true, out var genderVal))
gender = genderVal;
// ReSharper disable once ConditionalAccessQualifierIsNonNullableAccordingToAPIContract
var markingsRaw = profile.Markings?.Deserialize<List<string>>();
List<Marking> markings = new();
if (markingsRaw != null)
{
foreach (var marking in markingsRaw)
{
var parsed = Marking.ParseFromDbString(marking);
if (parsed is null) continue;
markings.Add(parsed);
}
}
Loadouts redux (#25715) * Loadouts redux * Loadout window mockup * More workout * rent * validation * Developments * bcs * More cleanup * Rebuild working * Fix model and loading * obsession * efcore * We got a stew goin * Cleanup * Optional + SeniorEngineering fix * Fixes * Update science.yml * add add * Automatic naming * Update nukeops * Coming together * Right now * stargate * rejig the UI * weh * Loadouts tweaks * Merge conflicts + ordering fix * yerba mate * chocolat * More updates * Add multi-selection support * test h * fikss * a * add tech assistant and hazard suit * huh * Latest changes * add medical loadouts * and science * finish security loadouts * cargo * service done * added wildcards * add command * Move restrictions * Finalising * Fix existing work * Localise next batch * clothing fix * Fix storage names * review * the scooping room * Test fixes * Xamlify * Xamlify this too * Update Resources/Prototypes/Loadouts/Jobs/Medical/paramedic.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/loadout_groups.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/Jobs/Civilian/clown.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/Jobs/Civilian/clown.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/loadout_groups.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/Jobs/Security/detective.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/loadout_groups.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * ben * Margins --------- Co-authored-by: Firewatch <54725557+musicmanvr@users.noreply.github.com> Co-authored-by: Mr. 27 <koolthunder019@gmail.com> Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com>
2024-04-16 22:57:43 +10:00
var loadouts = new Dictionary<string, RoleLoadout>();
foreach (var role in profile.Loadouts)
{
var loadout = new RoleLoadout(role.RoleName)
{
};
Loadouts redux (#25715) * Loadouts redux * Loadout window mockup * More workout * rent * validation * Developments * bcs * More cleanup * Rebuild working * Fix model and loading * obsession * efcore * We got a stew goin * Cleanup * Optional + SeniorEngineering fix * Fixes * Update science.yml * add add * Automatic naming * Update nukeops * Coming together * Right now * stargate * rejig the UI * weh * Loadouts tweaks * Merge conflicts + ordering fix * yerba mate * chocolat * More updates * Add multi-selection support * test h * fikss * a * add tech assistant and hazard suit * huh * Latest changes * add medical loadouts * and science * finish security loadouts * cargo * service done * added wildcards * add command * Move restrictions * Finalising * Fix existing work * Localise next batch * clothing fix * Fix storage names * review * the scooping room * Test fixes * Xamlify * Xamlify this too * Update Resources/Prototypes/Loadouts/Jobs/Medical/paramedic.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/loadout_groups.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/Jobs/Civilian/clown.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/Jobs/Civilian/clown.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/loadout_groups.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/Jobs/Security/detective.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/loadout_groups.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * ben * Margins --------- Co-authored-by: Firewatch <54725557+musicmanvr@users.noreply.github.com> Co-authored-by: Mr. 27 <koolthunder019@gmail.com> Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com>
2024-04-16 22:57:43 +10:00
foreach (var group in role.Groups)
{
var groupLoadouts = loadout.SelectedLoadouts.GetOrNew(group.GroupName);
foreach (var profLoadout in group.Loadouts)
{
groupLoadouts.Add(new Loadout()
{
Prototype = profLoadout.LoadoutName,
});
}
}
loadouts[role.RoleName] = loadout;
}
return new HumanoidCharacterProfile(
profile.CharacterName,
2022-05-14 08:58:45 +10:00
profile.FlavorText,
profile.Species,
profile.Age,
sex,
gender,
new HumanoidCharacterAppearance
(
profile.HairName,
Color.FromHex(profile.HairColor),
profile.FacialHairName,
Color.FromHex(profile.FacialHairColor),
Color.FromHex(profile.EyeColor),
Color.FromHex(profile.SkinColor),
Humanoid appearance refactor (#10882) * initial commit - species prototype modifications - markings points as its own file - shared humanoid component * adds a tool to convert sprite accessories to markings (in go) * removes a fmt call * converts sprite accessory to markings * adds hair and facial hair to marking categories * multiple changes - humanoid visualizer system - markings modifications for visualizer - modifications to shared humanoid component - lays out a base for humanoid system * hidden layers, ports some properties from appearance component, shrinks DefaultMarkings a little * squishes the initialize event calls into one function adds stuff to set species/skin color externally from a server message - currently laid out as if it a dirty call to a networked component, may be subject to change (server-side has not been implemented yet) * makes the sprite pipeline more obvious * apply all markings, hidden layer set replacement * ensures that markings are cleared when the new set is applied * starts refactoring markingsset (unfinished) * more additions to the markingset api * adds constructor logic to markingset * adds a method to filter out markings in a set based on a given species * fixes enumerators in markingset * adds validator into MarkingSet, fixes ForwardMarkingEnumerator * modifications to the humanoid visual system * ensuredefault in markingset * oop * fixes up data keys, populates OnAppearanceChange in visualizer * changes to humanoid component, markings marking equality is now more strict, humanoidcomponent is now implemented for client as a child of sharedhumanoidcomponent * markings are now applied the visualizer by diffing them * base sprites are now applied to humanoids from humanoidvisualizer * passes along base sprite settings to the marking application so that markings know to follow skin color/alpha or not (see: slimes) * custom base layers on humanoids * merges all data keys into one data class for humanoid visualizers * setappearance in sharedhumanoidsystem, removes custombaselayercolors * humanoidcomponent, system (empty) in server * adds some basic public API functions to HumanoidSystem * add marking, remove marking * changes appearance MarkingsSet to a List<Marking>, adds listener for PlayerSpawnCompleteEvent in HumanoidSystem * ensuredefaultmarkings, oninit for humanoids * markingmanager API changes * removes MarkingsSet * LoadProfile, adjusts randomization in humanoid appearance to account for species * base layer settings in humanoidsystem, eye color from profile * rearranges files to centralize under Humanoid namespace * more reorganization, deletes some stuff gotta break stuff to make other things work, right? goodbye SpriteAccessory... * fixes a good chunk of server-side issues still does not compile, yet * singlemarkingpicker xaml layout * singlemarkingpicker logic * magic mirror window (varying pieces of it, mostly client-oriented) * removes some imports, gives MagicMirror a BUI class (not filled in yet) * populates magic mirror BUI functionality / window callbacks * fixes up some errors in humanoidprofileeditor * changes to SingleMarkingPicker SingleMarkingPicker now accepts a List<Marking>, species, and total possible markings available in that marking category * fixes up hair pickers on humanoid profile editor * fixes the errors in markingpicker * markingsystem is now gone * fixes a bunch of build errors * so that's why i did it like that * namespace issues, adds robustxamlloader to singlemarkingpicker * another robustxamlloader * human, lizard sprites/points * prototype fixes, deletion of old spriteaccessory * component registration, fixes dwarf skin toning no, 'ReptilianToned' does not exist * removes component registration from abstract humanoid component * visualizer data now cloneable * serialize for visualizer key * zero-count edge case * missing semi-colon moment * setspecies in humanoidsystem * ensures that default markings, if empty, will cause ensuredefault to skip over that given category * tryadd instead of add * whoops * diff and apply should properly apply markings now * always ensure default, fixes double load for player spawning * apply skin color now sets the skin color property in humanoidcomponent * removes sprite from a few species prototypes * sprite changes for specific base layers based on humanoid sex * layer ordering fix, and a missing base layer should now disallow markings on that layer * anymarking base layer, adds the right leg/foot for humans * loading a profile will now clear all markings on that humanoid * adds missing layers for humans * separates species.yml into respective species prototype files * ensures that if layer visibility was changed, all markings have to be reapplied * server-side enforcement of hiding hair (and other head-related markings) when equipping things that hide hair * slime fix, clothingsystem now dictates layer visibility server side * sussy * layer settings should now ensure a marking should match the skin tone * whoops * skincolor static class and functions in UI * skin color validation in humanoidcharacterappearance * markingpicker now shows only the markings for the selected category in used * getter for slot in singlemarkingpicker now ensures slot is 0 if markings exists * FilterSpecies no longer attempts to do removal while iterating * expands for SingleMarkingPicker * humanoid base dummy has blank layers now (and snout/tail/headside/headtop) * fixes an issue with visualizer system if the marking count was different but the markings themselves were (somewhat) the same * whoops * adds edge case handlers for count differences in humanoid markings * preview now loads profile instead of directly setting appearance * moves marking set loading to update controls * clones a marking set in markingpicker by using the deep clone constructor * whoops (deep cloning a marking now copies the marking id) * adds replace function for markingset * points should now update after the markings are remove/added * merging base layer sprites into a humanoid should now clear them before merging * sets dirty range start to count only if the dirty range start was never set above 0 * fixes up some issues with singlemarkingpicker * color selector sliders in single marking picker should now expand * hair from hair pickers should now apply in profile loading (client-side) * category in singlemarkingpicker now sets the private category variable * slot selector should now populate * single marking picker buttons now have text, also shows the category name over all user-clickable elements * removes a comment * removing hair slots now sets it to bald, defaults to zero used slots if current hair is bald on hair/facial hair * random skin color, eye color * populate colors now checks if the marking count is greater than zero in singlemarkingpicker * hair/facial hair pickers now just get the first possible hair from the respective species list * different approach to random skin color * oh, that's why it wasn't working * randomize everything now just updates every single control * selecting a new marking in SingleMarkingPicker should attempt to copy over old colors, populate list now uses cache, * markingmanager now uses OnlyWhitelisted to populate by category and species * filterspecies now uses onlyWhitelist to filter markings based on whitelist or not * oops * ui fix for singlemarkingpicker, ensures that cache is not null if it is null when populatelist is called * order of operations for the horizontal expand for add/remove * hair pickers should now update when you add/remove the hair slot * fixes variable naming error in character appearance * loc string fix in singlemarkingpicker * lizards, vox now have onlyWhitelist, vox restriction for hair/facialhairs * having zero possible hairs should no longer cause an exception in randomization * setting species should now update hair pickers * ignore categories for marking picker * and a clear as well for the category button * places that functionality in its own function instead * adds eye base sprite, vox now also have their own custom eye sprites * loading a profile client-side should do FilterSpecies for markings now * client-side load profile does filter species after adding in the hairs now * magic mirror * callbacks now call the callback instead of adding it on construct * whoops * in removemarking too * adds missing synchronize calls * comments out an updateinterface call in magic mirror * magic mirror window title, minimum sizing * fixes minsize, adds warning for players who try to set their hair for species that have no hair * removes spaces in xaml * namespace changes/organization * whoopsie (merge conflicts) * re-enables identity from humanoid component * damagevisuals now uses the enum given to it instead of the layerstate given on that layer tied to the enum * removes commas from json * changes to visuals system so the change is consistent * chest * reptilian * visualizer system now handles body sprite setting/coloration, similar to how characterappearance did it not a big fan of this * adds a check in applybasesprites * adding/removing parts should now make them invisible on a humanoid * body part removal/adding now enumerates over sublayers instead * synchro now runs in bodycomponent startup * parts instead of slots * humanoidcompnent check * switches from rsi to actualrsi * removes all the body stuff (too slow) * cleans up resolves from humanoid visualizer system * merging sprites now checks if the base sprites have been modified or not (through things like species changes, or custom base sprite changes) * not forgetting that one again * merging now returns an actual dirty value * replaces the sequenceequal with a more accurate solution * permanent layers, layer visibility on add/remove part in body * should send all hidden layers over now * isdirty in visualizer system for base layers * isdirty checks count as well * ok, IsDirty should now set the base layers if the merged sprites are different * equals override in HumanoidSpritePrototypes.cs temporary until record prototypes :heck: * makes fields readonly, equates IDs instead * adds forced markings through marking picker * forced in humanoidsystem api, ignorespecies in markingpicker * marking bui * makes that serializable as well * ignore species/forced toggles now work * adds icon to modifier verb, interface and keys to humanoid bases * needs the actual enum value to open, no? * makes the key the actual key * actions now propagate upwards * ignore species when set now repopulates markingpicker * modifiable base layers in the markings window * oops! * layout changes * info box should now appear * adds ignorespecies for marking picker, collapsible for base layer section of appearance modification window * collapsible layout moment * if base layers have changed, all markings are now dirty (and if a base layer is missing, the marking is still 'applied' but it's now just invisible * small change to marking visibility * small changes to modifier UI * markings now match skin on zombification * zombie stuff * makes the line edit in marking modifier window more obvious * disables vox on round start * horizontal expand on the single label in base layer modifiers * humanoid profiles in prototypes * randomhumanoidappearance won't work if the humanoid has a profile already stored * removes unused code * documentation in humanoidsystem server-side * documentation in shared/client * whoops * converts accessory into marking in locale files (also adds marking loc string into single marking picker) * be gone, shared humanoid appearance system from the last upstream merge * species ignore on randomization (defaults to no ignored species) * more upstream merge parts that bypassed any errors before merge * addresses review (also just adds typeserializers in some places) * submodule moment * upstream merge issues
2022-09-22 15:19:00 -07:00
markings
),
spawnPriority,
jobs,
(PreferenceUnavailableMode) profile.PreferenceUnavailable,
antags.ToHashSet(),
traits.ToHashSet(),
Loadouts redux (#25715) * Loadouts redux * Loadout window mockup * More workout * rent * validation * Developments * bcs * More cleanup * Rebuild working * Fix model and loading * obsession * efcore * We got a stew goin * Cleanup * Optional + SeniorEngineering fix * Fixes * Update science.yml * add add * Automatic naming * Update nukeops * Coming together * Right now * stargate * rejig the UI * weh * Loadouts tweaks * Merge conflicts + ordering fix * yerba mate * chocolat * More updates * Add multi-selection support * test h * fikss * a * add tech assistant and hazard suit * huh * Latest changes * add medical loadouts * and science * finish security loadouts * cargo * service done * added wildcards * add command * Move restrictions * Finalising * Fix existing work * Localise next batch * clothing fix * Fix storage names * review * the scooping room * Test fixes * Xamlify * Xamlify this too * Update Resources/Prototypes/Loadouts/Jobs/Medical/paramedic.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/loadout_groups.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/Jobs/Civilian/clown.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/Jobs/Civilian/clown.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/loadout_groups.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/Jobs/Security/detective.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/loadout_groups.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * ben * Margins --------- Co-authored-by: Firewatch <54725557+musicmanvr@users.noreply.github.com> Co-authored-by: Mr. 27 <koolthunder019@gmail.com> Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com>
2024-04-16 22:57:43 +10:00
loadouts
);
}
private static Profile ConvertProfiles(HumanoidCharacterProfile humanoid, int slot, Profile? profile = null)
{
profile ??= new Profile();
var appearance = (HumanoidCharacterAppearance) humanoid.CharacterAppearance;
List<string> markingStrings = new();
foreach (var marking in appearance.Markings)
{
markingStrings.Add(marking.ToString());
}
var markings = JsonSerializer.SerializeToDocument(markingStrings);
profile.CharacterName = humanoid.Name;
profile.FlavorText = humanoid.FlavorText;
profile.Species = humanoid.Species;
profile.Age = humanoid.Age;
profile.Sex = humanoid.Sex.ToString();
profile.Gender = humanoid.Gender.ToString();
profile.HairName = appearance.HairStyleId;
profile.HairColor = appearance.HairColor.ToHex();
profile.FacialHairName = appearance.FacialHairStyleId;
profile.FacialHairColor = appearance.FacialHairColor.ToHex();
profile.EyeColor = appearance.EyeColor.ToHex();
profile.SkinColor = appearance.SkinColor.ToHex();
profile.SpawnPriority = (int) humanoid.SpawnPriority;
profile.Markings = markings;
profile.Slot = slot;
profile.PreferenceUnavailable = (DbPreferenceUnavailableMode) humanoid.PreferenceUnavailable;
profile.Jobs.Clear();
profile.Jobs.AddRange(
humanoid.JobPriorities
.Where(j => j.Value != JobPriority.Never)
.Select(j => new Job {JobName = j.Key, Priority = (DbJobPriority) j.Value})
);
profile.Antags.Clear();
profile.Antags.AddRange(
humanoid.AntagPreferences
.Select(a => new Antag {AntagName = a})
);
profile.Traits.Clear();
profile.Traits.AddRange(
2022-09-10 17:40:06 +02:00
humanoid.TraitPreferences
.Select(t => new Trait {TraitName = t})
);
Loadouts redux (#25715) * Loadouts redux * Loadout window mockup * More workout * rent * validation * Developments * bcs * More cleanup * Rebuild working * Fix model and loading * obsession * efcore * We got a stew goin * Cleanup * Optional + SeniorEngineering fix * Fixes * Update science.yml * add add * Automatic naming * Update nukeops * Coming together * Right now * stargate * rejig the UI * weh * Loadouts tweaks * Merge conflicts + ordering fix * yerba mate * chocolat * More updates * Add multi-selection support * test h * fikss * a * add tech assistant and hazard suit * huh * Latest changes * add medical loadouts * and science * finish security loadouts * cargo * service done * added wildcards * add command * Move restrictions * Finalising * Fix existing work * Localise next batch * clothing fix * Fix storage names * review * the scooping room * Test fixes * Xamlify * Xamlify this too * Update Resources/Prototypes/Loadouts/Jobs/Medical/paramedic.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/loadout_groups.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/Jobs/Civilian/clown.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/Jobs/Civilian/clown.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/loadout_groups.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/Jobs/Security/detective.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/loadout_groups.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * ben * Margins --------- Co-authored-by: Firewatch <54725557+musicmanvr@users.noreply.github.com> Co-authored-by: Mr. 27 <koolthunder019@gmail.com> Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com>
2024-04-16 22:57:43 +10:00
profile.Loadouts.Clear();
foreach (var (role, loadouts) in humanoid.Loadouts)
{
var dz = new ProfileRoleLoadout()
{
RoleName = role,
};
foreach (var (group, groupLoadouts) in loadouts.SelectedLoadouts)
{
var profileGroup = new ProfileLoadoutGroup()
{
GroupName = group,
};
foreach (var loadout in groupLoadouts)
{
profileGroup.Loadouts.Add(new ProfileLoadout()
{
LoadoutName = loadout.Prototype,
});
}
dz.Groups.Add(profileGroup);
}
profile.Loadouts.Add(dz);
}
return profile;
}
#endregion
2021-11-11 17:54:02 +01:00
#region User Ids
public async Task<NetUserId?> GetAssignedUserIdAsync(string name)
{
await using var db = await GetDb();
var assigned = await db.DbContext.AssignedUserId.SingleOrDefaultAsync(p => p.UserName == name);
return assigned?.UserId is { } g ? new NetUserId(g) : default(NetUserId?);
}
public async Task AssignUserIdAsync(string name, NetUserId netUserId)
{
await using var db = await GetDb();
db.DbContext.AssignedUserId.Add(new AssignedUserId
{
UserId = netUserId.UserId,
UserName = name
});
await db.DbContext.SaveChangesAsync();
}
2021-11-11 17:54:02 +01:00
#endregion
2021-11-11 17:54:02 +01:00
#region Bans
/*
* BAN STUFF
*/
/// <summary>
/// Looks up a ban by id.
/// This will return a pardoned ban as well.
/// </summary>
/// <param name="id">The ban id to look for.</param>
/// <returns>The ban with the given id or null if none exist.</returns>
public abstract Task<ServerBanDef?> GetServerBanAsync(int id);
/// <summary>
/// Looks up an user's most recent received un-pardoned ban.
/// This will NOT return a pardoned ban.
/// One of <see cref="address"/> or <see cref="userId"/> need to not be null.
/// </summary>
/// <param name="address">The ip address of the user.</param>
/// <param name="userId">The id of the user.</param>
/// <param name="hwId">The legacy HWId of the user.</param>
/// <param name="modernHWIds">The modern HWIDs of the user.</param>
/// <returns>The user's latest received un-pardoned ban, or null if none exist.</returns>
2021-03-22 01:30:50 +01:00
public abstract Task<ServerBanDef?> GetServerBanAsync(
IPAddress? address,
NetUserId? userId,
ImmutableArray<byte>? hwId,
ImmutableArray<ImmutableArray<byte>>? modernHWIds);
/// <summary>
/// Looks up an user's ban history.
/// This will return pardoned bans as well.
/// One of <see cref="address"/> or <see cref="userId"/> need to not be null.
/// </summary>
/// <param name="address">The ip address of the user.</param>
/// <param name="userId">The id of the user.</param>
/// <param name="hwId">The legacy HWId of the user.</param>
/// <param name="modernHWIds">The modern HWIDs of the user.</param>
/// <param name="includeUnbanned">Include pardoned and expired bans.</param>
/// <returns>The user's ban history.</returns>
2021-03-22 01:30:50 +01:00
public abstract Task<List<ServerBanDef>> GetServerBansAsync(
IPAddress? address,
NetUserId? userId,
ImmutableArray<byte>? hwId,
ImmutableArray<ImmutableArray<byte>>? modernHWIds,
bool includeUnbanned);
public abstract Task AddServerBanAsync(ServerBanDef serverBan);
public abstract Task AddServerUnbanAsync(ServerUnbanDef serverUnban);
2023-04-03 02:24:55 +02:00
public async Task EditServerBan(int id, string reason, NoteSeverity severity, DateTimeOffset? expiration, Guid editedBy, DateTimeOffset editedAt)
{
await using var db = await GetDb();
var ban = await db.DbContext.Ban.SingleOrDefaultAsync(b => b.Id == id);
if (ban is null)
return;
ban.Severity = severity;
ban.Reason = reason;
ban.ExpirationTime = expiration?.UtcDateTime;
ban.LastEditedById = editedBy;
ban.LastEditedAt = editedAt.UtcDateTime;
await db.DbContext.SaveChangesAsync();
}
Kick on ban for entire server group (#28649) * Start work on PostgresNotificationManager Implement initial version of init and listening code * Finish implementing PostgresNotificationManager Implement ban insert trigger * Implement ignoring notifications if the ban was from the same server * Address reviews * Fixes and refactorings Fix typo in migration SQL Pull new code in BanManager out into its own partial file. Unify logic to kick somebody with that when a new ban is placed directly on the server. New bans are now checked against all parameters (IP, HWID) instead of just user ID. Extracted SQLite ban matching code into a new class so that it can mostly be re-used by the ban notification code. No copy-paste here. Database notifications are now not implicitly sent to the main thread, this means basic checks will happen in the thread pool beforehand. Bans without user ID are now sent to servers. Bans are rate limited to avoid undue work from mass ban imports, beyond the rate limit they are dropped. Improved error handling and logging for the whole system. Matching bans against connected players requires knowing their ban exemption flags. These are now cached when the player connects. ServerBanDef now has exemption flags, again to allow matching full ban details for ban notifications. Made database notifications a proper struct type to reduce copy pasting a tuple. Remove copy pasted connection string building code by just... passing the string into the constructor. Add lock around _notificationHandlers just in case. Fixed postgres connection wait not being called in a loop and therefore spamming LISTEN commands for every received notification. Added more error handling and logging to notification listener. Removed some copy pasting from SQLite database layer too while I was at it because god forbid we expect anybody else to do all the work in this project. Sorry Julian --------- Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com>
2024-08-20 23:31:33 +02:00
protected static async Task<ServerBanExemptFlags?> GetBanExemptionCore(
DbGuard db,
NetUserId? userId,
CancellationToken cancel = default)
2023-04-03 02:24:55 +02:00
{
if (userId == null)
return null;
var exemption = await db.DbContext.BanExemption
Kick on ban for entire server group (#28649) * Start work on PostgresNotificationManager Implement initial version of init and listening code * Finish implementing PostgresNotificationManager Implement ban insert trigger * Implement ignoring notifications if the ban was from the same server * Address reviews * Fixes and refactorings Fix typo in migration SQL Pull new code in BanManager out into its own partial file. Unify logic to kick somebody with that when a new ban is placed directly on the server. New bans are now checked against all parameters (IP, HWID) instead of just user ID. Extracted SQLite ban matching code into a new class so that it can mostly be re-used by the ban notification code. No copy-paste here. Database notifications are now not implicitly sent to the main thread, this means basic checks will happen in the thread pool beforehand. Bans without user ID are now sent to servers. Bans are rate limited to avoid undue work from mass ban imports, beyond the rate limit they are dropped. Improved error handling and logging for the whole system. Matching bans against connected players requires knowing their ban exemption flags. These are now cached when the player connects. ServerBanDef now has exemption flags, again to allow matching full ban details for ban notifications. Made database notifications a proper struct type to reduce copy pasting a tuple. Remove copy pasted connection string building code by just... passing the string into the constructor. Add lock around _notificationHandlers just in case. Fixed postgres connection wait not being called in a loop and therefore spamming LISTEN commands for every received notification. Added more error handling and logging to notification listener. Removed some copy pasting from SQLite database layer too while I was at it because god forbid we expect anybody else to do all the work in this project. Sorry Julian --------- Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com>
2024-08-20 23:31:33 +02:00
.SingleOrDefaultAsync(e => e.UserId == userId.Value.UserId, cancellationToken: cancel);
2023-04-03 02:24:55 +02:00
return exemption?.Flags;
}
public async Task UpdateBanExemption(NetUserId userId, ServerBanExemptFlags flags)
{
await using var db = await GetDb();
if (flags == 0)
{
// Delete whatever is there.
await db.DbContext.BanExemption.Where(u => u.UserId == userId.UserId).ExecuteDeleteAsync();
return;
}
var exemption = await db.DbContext.BanExemption.SingleOrDefaultAsync(u => u.UserId == userId.UserId);
if (exemption == null)
{
exemption = new ServerBanExemption
{
UserId = userId
};
db.DbContext.BanExemption.Add(exemption);
}
exemption.Flags = flags;
await db.DbContext.SaveChangesAsync();
}
Kick on ban for entire server group (#28649) * Start work on PostgresNotificationManager Implement initial version of init and listening code * Finish implementing PostgresNotificationManager Implement ban insert trigger * Implement ignoring notifications if the ban was from the same server * Address reviews * Fixes and refactorings Fix typo in migration SQL Pull new code in BanManager out into its own partial file. Unify logic to kick somebody with that when a new ban is placed directly on the server. New bans are now checked against all parameters (IP, HWID) instead of just user ID. Extracted SQLite ban matching code into a new class so that it can mostly be re-used by the ban notification code. No copy-paste here. Database notifications are now not implicitly sent to the main thread, this means basic checks will happen in the thread pool beforehand. Bans without user ID are now sent to servers. Bans are rate limited to avoid undue work from mass ban imports, beyond the rate limit they are dropped. Improved error handling and logging for the whole system. Matching bans against connected players requires knowing their ban exemption flags. These are now cached when the player connects. ServerBanDef now has exemption flags, again to allow matching full ban details for ban notifications. Made database notifications a proper struct type to reduce copy pasting a tuple. Remove copy pasted connection string building code by just... passing the string into the constructor. Add lock around _notificationHandlers just in case. Fixed postgres connection wait not being called in a loop and therefore spamming LISTEN commands for every received notification. Added more error handling and logging to notification listener. Removed some copy pasting from SQLite database layer too while I was at it because god forbid we expect anybody else to do all the work in this project. Sorry Julian --------- Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com>
2024-08-20 23:31:33 +02:00
public async Task<ServerBanExemptFlags> GetBanExemption(NetUserId userId, CancellationToken cancel)
2023-04-03 02:24:55 +02:00
{
Kick on ban for entire server group (#28649) * Start work on PostgresNotificationManager Implement initial version of init and listening code * Finish implementing PostgresNotificationManager Implement ban insert trigger * Implement ignoring notifications if the ban was from the same server * Address reviews * Fixes and refactorings Fix typo in migration SQL Pull new code in BanManager out into its own partial file. Unify logic to kick somebody with that when a new ban is placed directly on the server. New bans are now checked against all parameters (IP, HWID) instead of just user ID. Extracted SQLite ban matching code into a new class so that it can mostly be re-used by the ban notification code. No copy-paste here. Database notifications are now not implicitly sent to the main thread, this means basic checks will happen in the thread pool beforehand. Bans without user ID are now sent to servers. Bans are rate limited to avoid undue work from mass ban imports, beyond the rate limit they are dropped. Improved error handling and logging for the whole system. Matching bans against connected players requires knowing their ban exemption flags. These are now cached when the player connects. ServerBanDef now has exemption flags, again to allow matching full ban details for ban notifications. Made database notifications a proper struct type to reduce copy pasting a tuple. Remove copy pasted connection string building code by just... passing the string into the constructor. Add lock around _notificationHandlers just in case. Fixed postgres connection wait not being called in a loop and therefore spamming LISTEN commands for every received notification. Added more error handling and logging to notification listener. Removed some copy pasting from SQLite database layer too while I was at it because god forbid we expect anybody else to do all the work in this project. Sorry Julian --------- Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com>
2024-08-20 23:31:33 +02:00
await using var db = await GetDb(cancel);
2023-04-03 02:24:55 +02:00
Kick on ban for entire server group (#28649) * Start work on PostgresNotificationManager Implement initial version of init and listening code * Finish implementing PostgresNotificationManager Implement ban insert trigger * Implement ignoring notifications if the ban was from the same server * Address reviews * Fixes and refactorings Fix typo in migration SQL Pull new code in BanManager out into its own partial file. Unify logic to kick somebody with that when a new ban is placed directly on the server. New bans are now checked against all parameters (IP, HWID) instead of just user ID. Extracted SQLite ban matching code into a new class so that it can mostly be re-used by the ban notification code. No copy-paste here. Database notifications are now not implicitly sent to the main thread, this means basic checks will happen in the thread pool beforehand. Bans without user ID are now sent to servers. Bans are rate limited to avoid undue work from mass ban imports, beyond the rate limit they are dropped. Improved error handling and logging for the whole system. Matching bans against connected players requires knowing their ban exemption flags. These are now cached when the player connects. ServerBanDef now has exemption flags, again to allow matching full ban details for ban notifications. Made database notifications a proper struct type to reduce copy pasting a tuple. Remove copy pasted connection string building code by just... passing the string into the constructor. Add lock around _notificationHandlers just in case. Fixed postgres connection wait not being called in a loop and therefore spamming LISTEN commands for every received notification. Added more error handling and logging to notification listener. Removed some copy pasting from SQLite database layer too while I was at it because god forbid we expect anybody else to do all the work in this project. Sorry Julian --------- Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com>
2024-08-20 23:31:33 +02:00
var flags = await GetBanExemptionCore(db, userId, cancel);
2023-04-03 02:24:55 +02:00
return flags ?? ServerBanExemptFlags.None;
}
2021-11-11 17:54:02 +01:00
#endregion
2022-02-21 14:11:39 -08:00
#region Role Bans
/*
* ROLE BANS
*/
/// <summary>
/// Looks up a role ban by id.
/// This will return a pardoned role ban as well.
/// </summary>
/// <param name="id">The role ban id to look for.</param>
/// <returns>The role ban with the given id or null if none exist.</returns>
public abstract Task<ServerRoleBanDef?> GetServerRoleBanAsync(int id);
/// <summary>
/// Looks up an user's role ban history.
/// This will return pardoned role bans based on the <see cref="includeUnbanned"/> bool.
/// Requires one of <see cref="address"/>, <see cref="userId"/>, or <see cref="hwId"/> to not be null.
/// </summary>
/// <param name="address">The IP address of the user.</param>
/// <param name="userId">The NetUserId of the user.</param>
/// <param name="hwId">The Hardware Id of the user.</param>
/// <param name="modernHWIds">The modern HWIDs of the user.</param>
2022-02-21 14:11:39 -08:00
/// <param name="includeUnbanned">Whether expired and pardoned bans are included.</param>
/// <returns>The user's role ban history.</returns>
public abstract Task<List<ServerRoleBanDef>> GetServerRoleBansAsync(IPAddress? address,
NetUserId? userId,
ImmutableArray<byte>? hwId,
ImmutableArray<ImmutableArray<byte>>? modernHWIds,
2022-02-21 14:11:39 -08:00
bool includeUnbanned);
public abstract Task<ServerRoleBanDef> AddServerRoleBanAsync(ServerRoleBanDef serverRoleBan);
2022-02-21 14:11:39 -08:00
public abstract Task AddServerRoleUnbanAsync(ServerRoleUnbanDef serverRoleUnban);
public async Task EditServerRoleBan(int id, string reason, NoteSeverity severity, DateTimeOffset? expiration, Guid editedBy, DateTimeOffset editedAt)
{
await using var db = await GetDb();
var roleBanDetails = await db.DbContext.RoleBan
.Where(b => b.Id == id)
.Select(b => new { b.BanTime, b.PlayerUserId })
.SingleOrDefaultAsync();
if (roleBanDetails == default)
return;
await db.DbContext.RoleBan
.Where(b => b.BanTime == roleBanDetails.BanTime && b.PlayerUserId == roleBanDetails.PlayerUserId)
.ExecuteUpdateAsync(setters => setters
.SetProperty(b => b.Severity, severity)
.SetProperty(b => b.Reason, reason)
.SetProperty(b => b.ExpirationTime, expiration.HasValue ? expiration.Value.UtcDateTime : (DateTime?)null)
.SetProperty(b => b.LastEditedById, editedBy)
.SetProperty(b => b.LastEditedAt, editedAt.UtcDateTime)
);
}
2022-02-21 14:11:39 -08:00
#endregion
#region Playtime
public async Task<List<PlayTime>> GetPlayTimes(Guid player, CancellationToken cancel)
{
await using var db = await GetDb(cancel);
return await db.DbContext.PlayTime
.Where(p => p.PlayerId == player)
.ToListAsync(cancel);
}
public async Task UpdatePlayTimes(IReadOnlyCollection<PlayTimeUpdate> updates)
{
await using var db = await GetDb();
// Ideally I would just be able to send a bunch of UPSERT commands, but EFCore is a pile of garbage.
// So... In the interest of not making this take forever at high update counts...
// Bulk-load play time objects for all players involved.
// This allows us to semi-efficiently load all entities we need in a single DB query.
// Then we can update & insert without further round-trips to the DB.
var players = updates.Select(u => u.User.UserId).Distinct().ToArray();
var dbTimes = (await db.DbContext.PlayTime
.Where(p => players.Contains(p.PlayerId))
.ToArrayAsync())
.GroupBy(p => p.PlayerId)
.ToDictionary(g => g.Key, g => g.ToDictionary(p => p.Tracker, p => p));
foreach (var (user, tracker, time) in updates)
{
if (dbTimes.TryGetValue(user.UserId, out var userTimes)
&& userTimes.TryGetValue(tracker, out var ent))
{
// Already have a tracker in the database, update it.
ent.TimeSpent = time;
continue;
}
// No tracker, make a new one.
var playTime = new PlayTime
{
Tracker = tracker,
PlayerId = user.UserId,
TimeSpent = time
};
db.DbContext.PlayTime.Add(playTime);
}
await db.DbContext.SaveChangesAsync();
}
#endregion
2021-11-11 17:54:02 +01:00
#region Player Records
/*
* PLAYER RECORDS
*/
2021-11-11 17:54:02 +01:00
public async Task UpdatePlayerRecord(
2021-03-22 01:30:50 +01:00
NetUserId userId,
string userName,
IPAddress address,
ImmutableTypedHwid? hwId)
2021-11-11 17:54:02 +01:00
{
await using var db = await GetDb();
var record = await db.DbContext.Player.SingleOrDefaultAsync(p => p.UserId == userId.UserId);
if (record == null)
{
db.DbContext.Player.Add(record = new Player
{
FirstSeenTime = DateTime.UtcNow,
UserId = userId.UserId,
});
}
record.LastSeenTime = DateTime.UtcNow;
record.LastSeenAddress = address;
record.LastSeenUserName = userName;
record.LastSeenHWId = hwId;
2021-11-11 17:54:02 +01:00
await db.DbContext.SaveChangesAsync();
}
2021-11-11 17:54:02 +01:00
public async Task<PlayerRecord?> GetPlayerRecordByUserName(string userName, CancellationToken cancel)
{
await using var db = await GetDb();
// Sort by descending last seen time.
// So if, due to account renames, we have two people with the same username in the DB,
// the most recent one is picked.
var record = await db.DbContext.Player
.OrderByDescending(p => p.LastSeenTime)
.FirstOrDefaultAsync(p => p.LastSeenUserName == userName, cancel);
return record == null ? null : MakePlayerRecord(record);
}
public async Task<PlayerRecord?> GetPlayerRecordByUserId(NetUserId userId, CancellationToken cancel)
{
await using var db = await GetDb();
var record = await db.DbContext.Player
.SingleOrDefaultAsync(p => p.UserId == userId.UserId, cancel);
return record == null ? null : MakePlayerRecord(record);
}
protected async Task<bool> PlayerRecordExists(DbGuard db, NetUserId userId)
{
return await db.DbContext.Player.AnyAsync(p => p.UserId == userId);
}
[return: NotNullIfNotNull(nameof(player))]
protected PlayerRecord? MakePlayerRecord(Player? player)
{
if (player == null)
return null;
return new PlayerRecord(
new NetUserId(player.UserId),
new DateTimeOffset(NormalizeDatabaseTime(player.FirstSeenTime)),
player.LastSeenUserName,
new DateTimeOffset(NormalizeDatabaseTime(player.LastSeenTime)),
player.LastSeenAddress,
player.LastSeenHWId);
}
2021-11-11 17:54:02 +01:00
#endregion
#region Connection Logs
/*
* CONNECTION LOG
*/
public abstract Task<int> AddConnectionLogAsync(NetUserId userId,
2021-03-22 01:30:50 +01:00
string userName,
IPAddress address,
ImmutableTypedHwid? hwId,
float trust,
ConnectionDenyReason? denied,
int serverId);
public async Task AddServerBanHitsAsync(int connection, IEnumerable<ServerBanDef> bans)
{
await using var db = await GetDb();
foreach (var ban in bans)
{
db.DbContext.ServerBanHit.Add(new ServerBanHit
{
ConnectionId = connection, BanId = ban.Id!.Value
});
}
await db.DbContext.SaveChangesAsync();
}
2021-11-11 17:54:02 +01:00
#endregion
2021-11-11 17:54:02 +01:00
#region Admin Ranks
/*
2021-11-11 17:54:02 +01:00
* ADMIN RANKS
*/
2020-11-10 16:50:28 +01:00
public async Task<Admin?> GetAdminDataForAsync(NetUserId userId, CancellationToken cancel)
{
await using var db = await GetDb(cancel);
return await db.DbContext.Admin
.Include(p => p.Flags)
.Include(p => p.AdminRank)
.ThenInclude(p => p!.Flags)
2022-01-04 06:37:06 -07:00
.AsSplitQuery() // tests fail because of a random warning if you dont have this!
2020-11-10 16:50:28 +01:00
.SingleOrDefaultAsync(p => p.UserId == userId.UserId, cancel);
}
public abstract Task<((Admin, string? lastUserName)[] admins, AdminRank[])>
GetAllAdminAndRanksAsync(CancellationToken cancel);
public async Task<AdminRank?> GetAdminRankDataForAsync(int id, CancellationToken cancel = default)
{
await using var db = await GetDb(cancel);
2020-11-10 16:50:28 +01:00
return await db.DbContext.AdminRank
.Include(r => r.Flags)
.SingleOrDefaultAsync(r => r.Id == id, cancel);
}
public async Task RemoveAdminAsync(NetUserId userId, CancellationToken cancel)
{
await using var db = await GetDb(cancel);
2020-11-10 16:50:28 +01:00
var admin = await db.DbContext.Admin.SingleAsync(a => a.UserId == userId.UserId, cancel);
db.DbContext.Admin.Remove(admin);
await db.DbContext.SaveChangesAsync(cancel);
}
public async Task AddAdminAsync(Admin admin, CancellationToken cancel)
{
await using var db = await GetDb(cancel);
2020-11-10 16:50:28 +01:00
db.DbContext.Admin.Add(admin);
await db.DbContext.SaveChangesAsync(cancel);
}
public async Task UpdateAdminAsync(Admin admin, CancellationToken cancel)
{
await using var db = await GetDb(cancel);
2020-11-10 16:50:28 +01:00
2020-11-13 03:23:13 +01:00
var existing = await db.DbContext.Admin.Include(a => a.Flags).SingleAsync(a => a.UserId == admin.UserId, cancel);
existing.Flags = admin.Flags;
existing.Title = admin.Title;
existing.AdminRankId = admin.AdminRankId;
Upstream sync (#786) * Box Station - Dechristmassified (#34135) * dechrismassified * removed camera from shower * Marathon Station - Dechristmassified (#34136) * dechristmassified * further dechristmassified * Loop Station Decal and maints additions (#34103) * many changes * contentingregrationtests * serialized invalid removed * blank * "Changes and fixes as suggested" * blank * blank * added desk bells * engi rework rework rework * added gate to content integration * tweaks * aaa * bbb * added holopads * ccc * Update default.yml * hotfix * aaa * bbb * many many tweaks and fixes * aaa * decals and maints * aaa * bbb * ccc --------- Co-authored-by: Emisse <99158783+Emisse@users.noreply.github.com> * Rename cryobed yml file (#34134) renamed cryopod.yml to cryogenic_sleep_unit.yml * Cog update (not very merry) (#34144) removed christmas merry * bagel update (#34145) * Add hair pulato (#34117) * add sprite pulato * update * add pulato hair * add pulato hair * add pulato hair * update meta "pulato" * Automatic changelog update * Holopad UI tweak for incoming calls (#34137) * Initial commit * Update * Comment correction * Minor margin increase * Holopads no longer log broadcasted speech and emotes in the chat (#34114) Initial commit * Automatic changelog update * Fixes borgs not being able to check their laws in crit (#34133) * fix * fix2 * Add contraband parent to laser gun safe (#34132) * Automatic changelog update * Add Holopad Circuit Board to A/V Communication Technology (#34150) Added the holopad circuit board to the AV Communication technology and circuit imprinter lathe. * Automatic changelog update * Fix disposal signal routers sprites (#34139) * Fix disposal signal routers sprites * Remove old shitcode * Automatic changelog update * Meta station overhaul (#33506) * added mail, moved some things around, and fixed a lot of APCs * fixed my mistakes * Fixed a few mistakes and AI camera names * Redid south medbay and more wiring * Finished sci overhaul, and fixed all issues that I could find. * rebuilt botany, removed vox box, fixed all known issues. * Overhauled security * Minor commit as I prepare to update my copy * Rebalanced role counts * Final changes, ready for review! * Emisse and other people fixed issues with the station * Finalized changes (for real this time)! * Standardize shotgun ammo in storagefills (#34156) shotgun ammo changes * Automatic changelog update * meta update (#34158) * Amber Station Adjustments (#34126) * Made a couple fixes to various decals, cleaned up some entities, gave the clown their bag and the bartender a handlabeler * Several changes, more cameras, lighting fixes, adjusted hydro a bit, gave sec a bunch of shutters * Added new random spawners for science and added them to Amber * fixed the science spawners and modified amber slightly * Fixed the random instrument entry * Fix friendly vent spiders (#34153) Swapped order of parents for MobGiantSpiderAngry * Removed UseDelay component from RCD (#34149) * Automatic changelog update * Decrease hp for rusted walls (#34043) * Automatic changelog update * FIX: Thief beacon doubled steal targets (#33750) * Automatic changelog update * remove nukemass song (#34066) * Automatic changelog update * Corrected all ghost role names to title case. (#34155) * Corrected all ghost role names to title case. * Removes full stop from Hamlet's title. * Updated ghost role names not in the main ghost roles .ftl * Two capitals corrections * Packed Update (Remove Christmas & New Evac) (#34168) * Packed update (remove christmas, new shuttle) * Fix invalid * the voices * Omega Update (Remove Christmas) (#34174) omega soap * Renamed "Irish Car Bomb" drink to "Irish Slammer" (#34107) * Renamed "Irish Car Bomb" drink to "Irish Slammer", due to concerns over insensitivity. * Fixing some missed references * Added prototype id changes to migration.yml. Removed any reference to the troubles (and corrected ale to stout for flavour text). * Corrected description back to "Irish Cream" * Removed non-entities from migration.yml * Automatic changelog update * Bugfix for the AI player's eye getting stuck when their broadcast is interrupted (#34093) Initial commit * Speech is relayed by holopad holograms (#33978) * Initial commit * Corrected a field attribute * Make JPEG a PNG (#34176) Make 3.png a PNG * Removed Undesirable Ion Storm Verbs (#34175) * Remove Undesirable Laws * empty * added basic admin logs for PDA notekeeper notes (#34118) * added basic admin logs for PDA notekeeper notes * formatting * added new LogType 'PdaInteract' and changed PDA notekeeper logs to it --------- Co-authored-by: dylanhunter <dylan2.whittingham@live.uwe.ac.uk> * Automatic changelog update * Sprites defined for all non-generic computer boards. Added new syndicate computer board sprite. (#34104) * Defined sprites for non-generic computer boards. Added new syndicate computer board sprite. * Added new sprite to meta.json and updated attribution. * Reformatted module.rsi meta.json to match other meta file styles. * Syndicate board sprite made less yellow/gold, changed outer chips to black. Using grey/silver for CPU centre, akin to syndie agent PDA theme, and to keep distinctive from security board. * Corrected indentation spacing for currently edited entities. * Update Resources/Prototypes/Entities/Objects/Devices/Circuitboards/computer.yml * add pr link to attribution --------- Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> Co-authored-by: Errant <35878406+Errant-4@users.noreply.github.com> * Added pricegun sound (#34119) added pricegun sound Co-authored-by: dylanhunter <dylan2.whittingham@live.uwe.ac.uk> * Automatic changelog update * Separate Tables n' Counters (#32673) * Update tables.yml * Remove Extra base: state_ * Update tables.yml * Automatic changelog update * Add Chameleon PDA (#30514) * V1 commit * Remove PDA name and unnecessary pda state * Adds PDA to Chameleon backpack & thief toolbox * Change to use AppearanceDataInit * Add basic PDA state to ensure there's always a sprite before AppearanceData can be applied * Revert PDA name (this will be changed to another way later) * Update PDA name updating to new system * Fix yaml, and fix Agent ID chameleon * Updated based on review * Automatic changelog update * Add some ion storm actions to replace removed ones (#34180) * Add some ion storm actions to replace removed ones * Remove other country references, replace * Some more tuning of the storm values, removing real-world countries * boldy basics * Automatic changelog update * Amber Station and Science Spawner Tweaks (#34187) * Modified science spawners a bit since I realized including maints loot was undesireable * Linked Medical doors to buttons, redesigned the floor of the dining area a bit, placed more science spawners * Somehow I overlooked that I was importing the maints loot table instead of the sci loot table * Gave sci an EOD closet * named the evac shuttle * Core update (#34201) add * Elkridge Depot (The station formerly known as Cell) (#34085) * named apcs, doors, air alarms, cameras, fire alarms, substations, SMESs * updated PostMapInitTest.cs to include Cell * added psychologist spawn * fixed scanner console link, fixed disposals conveyors, and more * added janitor service lights, maints firelocks, and more * added more fun maint rooms * improved head offices, kitchen, psych. added maints between science and arrivals * fixed spawners placed over solid objects * added unique evac shuttle, the Cilium * evac shuttle is now orientated correctly * added unique cargo shuttle * updated kitchen area * renamed Cell Station to Elkridge Depot, removed most main hall airlocks for smoother travel * general last-minute touch-ups around the bridge and sec * changed station name in PostMapInitTest.cs * Add Elkridge Depot into Map Rotation (#34206) * named apcs, doors, air alarms, cameras, fire alarms, substations, SMESs * updated PostMapInitTest.cs to include Cell * added psychologist spawn * fixed scanner console link, fixed disposals conveyors, and more * added janitor service lights, maints firelocks, and more * added more fun maint rooms * improved head offices, kitchen, psych. added maints between science and arrivals * fixed spawners placed over solid objects * added unique evac shuttle, the Cilium * evac shuttle is now orientated correctly * added unique cargo shuttle * updated kitchen area * renamed Cell Station to Elkridge Depot, removed most main hall airlocks for smoother travel * general last-minute touch-ups around the bridge and sec * changed station name in PostMapInitTest.cs * added Elkridge to default map pool * added myself to map_attribution.yml credits * Automatic changelog update * Packed Update (#34208) Packed Update (decals mostly) * Apply forensics when loading with an ammo box (#32280) * Automatic changelog update * Update Credits (#34220) Co-authored-by: PJBot <pieterjan.briers+bot@gmail.com> * Fix rainbow lizard plushie inhands (#34128) * fix rainbow plushie inhands * address requested changes * attribute sprites * wielding refactor/fixes (#32188) * refactor wieldable events * fix inconsitency with wielding and use updated events * wieldable cosmetic refactoring * Update Content.Shared/Wieldable/Events.cs Co-authored-by: Centronias <charlie.t.santos@gmail.com> * real Co-authored-by: ScarKy0 <106310278+ScarKy0@users.noreply.github.com> --------- Co-authored-by: deltanedas <@deltanedas:kde.org> Co-authored-by: Centronias <charlie.t.santos@gmail.com> Co-authored-by: ScarKy0 <106310278+ScarKy0@users.noreply.github.com> * Automatic changelog update * Lobby chat width and custom lobby titles (#33783) * lobby name cvar * panel width * skrek * server name localization fix * comment format fix Co-authored-by: Thomas <87614336+Aeshus@users.noreply.github.com> * remove redundant newline Co-authored-by: Thomas <87614336+Aeshus@users.noreply.github.com> * string.empty Co-authored-by: Thomas <87614336+Aeshus@users.noreply.github.com> * use SetWidth * Update Resources/Locale/en-US/lobby/lobby-gui.ftl --------- Co-authored-by: Thomas <87614336+Aeshus@users.noreply.github.com> Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Automatic changelog update * Adds bullet collision to station lights (#34070) Adds collision with bullets to lights * Automatic changelog update * Oasis Update (#34245) santa is keel. * Amber Station - Minor Fixes (#34246) * Moved the stand clear decal in front of the janitor's shutters up two pixels * added tech maints under most maints doors, fixed power issues in cargo, and fixed a couple minor issues * Make station anchor hitbox less insufferable (#34217) * Automatic changelog update * Remove kessler and zombeteors gamemodes from the secret pool (#34051) * Remove kessler, zombeteors gameodes * Probably should keep the protos in case an admin wants to torture players secretly * address slart review * Automatic changelog update * Added distinct ad and bye chatter to Dr. Gibb vending (#34182) * Added distinct ad and bye chatter to Dr. Gibb vending * Correcting revert mistake * Changed ad pack names to better match naming convention * Implement approved rule changes (#34233) * Special reagents now appear in the guidebook (#34265) * Special reagents now appear in the guidebook * Improved guidebook wording for reagent category * Automatic changelog update * Implement approved rule changes (#34233) * Fix compilation errors in tests from update (#34272) Required for https://github.com/space-wizards/RobustToolbox/pull/5590 to not cause compile fails, but can be merged on its own * Fix portable scrubber appearing powered on spawn (#34274) * [HOTFIX] Fix chameleon PDAs renaming IDs (#34249) Fix chameleon PDA * [HOTFIX] Fix Meta station power (#34256) * hotfix meta power * fixed AME * add missing cargo shuttle pilot console to cargo * Update vessel_warning.ogg (#34263) * Update vessel_warning.ogg Remove DC offset and apply short fade out. * Update attributions.yml * Update attributions.yml * Add bleating accent to goats (#34273) * Automatic changelog update * Happy New Year (#34288) happy new year * Amber Station - Balance Improvements (#34294) changed the center area in med bay to a garden, weakened meteor shielding in some areas, also general touch ups around the station * Fixed Loop Station's southern solar array unlinked airlocks (#34296) Fixed Southern solar external airlock door bolts * Fix empty lines in adminwho with stealthmins. (#34122) Don't print newline if admin is hidden. * Automatic changelog update * Added missing cameras to Loop Station (#34308) * Added missing cameras * Added missing cameras * Amber Station - Fixes and Warm Lights (#34324) * Added warm lights, placed them around the map, also fixed an issue with the MV wire in the cafeteria * Fixed lv wiring in caf, and adjusted a couple things * Empty commit to force checks to rerun * Automatic changelog update * change locking to use ComplexInteraction (#34326) Co-authored-by: deltanedas <@deltanedas:kde.org> * Automatic changelog update * Drink titles and soda vendor consistency (#34178) * Made capitalisation of proper names consistent. * Roy Rogers is presumably a proper name. * Second pass at distinguishing proper names only. * Two nitpicking/minor changes * Fixed some overlooked can brand names. Matched case with descriptions. * Switched generic sodas with brands for SodaInventory * Removed commonly available branded cans * Matched case consistency used elsewhere. Minor SPAG corrections. * Added "nothing" and some missing alcohol bottles to RandomSpawner * Added distinct ad and bye chatter to Dr. Gibb machines. * Revert "Added distinct ad and bye chatter to Dr. Gibb machines." This reverts commit f90b8a470556de05aca81255db8b6b03596ae944. * Revert "Removed commonly available branded cans" This reverts commit 43b82168dac1f73b187b7677f34ecdd33b6bb81a. * Revert "Switched generic sodas with brands for SodaInventory" This reverts commit f1790f0ce61ef135c79068de6a741e8bb50d85d3. * Lowercased DrinkGlass suffix. Moved alcoholic drinks from drinks to alcohol. * Renamed energy drink to Red Bool. Corrected and added some jug descriptions. * Added reagent names for all bottles except poison-wine * Revision of title case for cocktails * SPAG and fixed the only brand reagen with unbranded name. * Possibly controversial, shortened some bran names to better fit the UI. * Fixed some inconsistencies in naming * Matched brand localisation change * Two name style edits * Fixed Smite bottle name * Minor, punctuation * Blank line to end of file * Upgraded descriptive names to title case * Banana Mama * reverts change, moved to another PR to avoid conflict. * Removed caffeine reference. * Minor, corrected some more inconsistencies * Removed Bottle of Nothing from random spawner. * Automatic changelog update * Fix access configurator debug assert (#34330) * fix * greytide fix * fix admin log * Dirty * Renamed water melon juice to watermelon juice (#34341) * Fix battery charging stopping just short of being full (#34028) * Add copy threshold button to air alarms (#34346) * Automatic changelog update * Oasis updoot the dimmining (#34347) updooty * Fland Station - Dirt Fix (#34352) Fland * Omega Station - Dirt Fix (#34353) omega * Marathon Station - Dirt Fix (#34354) * Marathon * Rerunning tests * Cog Station - Dirt Fix (#34355) Cog * Box Station - Dirt Fix (#34356) Box * Bagel Station - Dirt Fix (#34357) Bagel * Packed Station - Dirt Fix (#34351) * packed * Rerunning tests * Replace some sound PlayEntity with PlayPvs (#34317) * Fixed Forensic Gloves to be Security Contraband (#34193) * added BaseRestrictedContraband to forensic gloves * moved from id to parent * Automatic changelog update * add large instruments to the cargo request computer (#34240) * added the church organ to the cargo console (will add more in this PR, assuming i did this right (HOW DO YOU BUY CARGO ORDERS IN DEV ENVIROMENT???? *sobs)) * added other structure instruments to cargo Catalog * fixed an epic copy/paste fail * changed prices * fixed epic copy/paste fail #2 --------- Co-authored-by: TeenSarlacc <baddiepro123@gmail.com> * Automatic changelog update * Fix crayon losing durability on stamped paper (#34202) * Automatic changelog update * Adds a border to Oppenhopper poster (#34219) * border * Update meta.json * Update Resources/Textures/Structures/Wallmounts/posters.rsi/meta.json --------- Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Trim trailing newlines from examine messages (#33381) * Trim trailing newlines from examine messages * TrimTrailingNewlines -> TrimEnd * Add a popup message when ghost Boo action does nothing (#34369) * fix ghost_component.ftl locale grammar (#34372) fix ghost component locale grammar * Let ghosts sometimes make certain devices say creepy things (#34368) * Add SpookySpeaker component/system * Shuffle Boo action targets before trying to activate them * Add SpookySpeaker to vending machines * Fix chatcode eating messages starting with "..." * Add SpookySpeaker to recycler * Oops * Decrease speak probability for vending machines * Add spooky speaker to arcade machines * Automatic changelog update * Add directional escape pod sign (#34367) * Make indestructible tiles not breakable by explosions (#34339) * No more Ai Spacing * Move guard into earlier guard statement * Automatic changelog update * Arachnid stomach organ yaml fix (#34298) Arachnid stomach yaml fix Arachnids had their stomach `updateInterval` set to 1.5, 50% slower than normal. But this doesn't actually slow down the speed that the stomach digests things, only the rate at which it updates to check if enough time has passed. (See https://github.com/space-wizards/space-station-14/blob/23f0b304f284d2600cb2c6b4c9d36fdca7f99ec4/Content.Server/Body/Systems/StomachSystem.cs#L57 ) This PR changes arachnid stomachs to have a `digestionDelay` of 30 (20 is default) to achive the desired effect. Stasis beds are also bugged in a similar manner. They are intended to slow down the digestion speed, but similarly all they do is change the update rate. But fixing that requires actual code changes and is out of scope for this commit. * Automatic changelog update * Bended radiator (#34251) * Automatic changelog update * Remove Entity<T> data-fields (#34083) * Update submodule, .NET 9 (#34320) * Role Types (#33420) * mindcomponent namespace * wip MindRole stuff * admin player tab * mindroletype comment * mindRolePrototype redesign * broken param * wip RoleType implementation * basic role type switching for antags * traitor fix * fix AdminPanel update * the renameningTM * cleanup * feature uncreeping * roletypes on mind roles * update MindComponent.RoleType when MindRoles change * ghostrole configuration * ghostrole config improvements * live update of roleType on the character window * logging stuff and notes * remove thing no one asked for * weh * Mind Role Entities wip * headrev count fix * silicon stuff, cleanup * exclusive antag config, cleanup * jobroleadd overwerite * logging stuff * MindHasRole cleanup, admin log stuff * last second cleanup * ocd * move roletypeprototype to its own file, minor note stuff * remove Roletype.Created * log stuff * roletype setup for ghostroles and autotraitor reinforcements * ghostrole type configs * adjustable admin overlay * cleanup * fix this in its own PR * silicon antagonist * borg stuff * mmi roletype handling * spawnable borg roletype handling * weh * ghost role cleanup * weh * RoleEvent update * polish * log stuff * admin overlay config * ghostrolecomponent cleanup * weh * admin overlay code cleanup * minor cleanup * Obsolete MindRoleAddedEvent * comment * minor code cleanup * MindOnDoGreeting fix * Role update message * fix duplicate job greeting for cyborgs * fix emag job message dupe * nicer-looking role type update * crew aligned * syndicate assault borg role fix * fix test fail * fix a merge mistake * fix LoneOp role type * Update Content.Client/Administration/AdminNameOverlay.cs Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Update Content.Shared/Roles/SharedRoleSystem.cs Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * comment formatting Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * change logging category Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * fix a space Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * use MindAddRoles Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * get MindComponent from TryGetMind Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * move var declaration outside loop * remove TryComp * take RoleEnum behind the barn * don't use ensurecomp unnecessarily * cvar comments * toggleableghostrolecomponent documentation * skrek * use EntProtoId * mindrole config * merge baserolecomponent into basemindrolecomponent * ai and borg silicon role tweaks * formatting Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * I will end you (the color) Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * use LocId type for a locale id * update RoleEvent documentation * update RoleEvent documentation * remove obsolete MindRoleAddedEvent * refine MindRolesUpdate() * use dependency Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * inject dependency Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * roleType.Name no longer required * reformatted draw code logic * GhostRoleMarkerRoleComponent comment * minor SharedRoleSystem cleanup * StartingMindRoleComponent, unhardcode roundstart silicon * Update Content.Shared/Roles/SharedRoleSystem.cs * remove a whitespace --------- Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Automatic changelog update * Update Credits (#34389) Co-authored-by: PJBot <pieterjan.briers+bot@gmail.com> * Elkridge Depot Improvements (#34377) * updates decals * more decal work, more dinginess in certain areas * added decals under doors * Fix force-feeding Loc strings not using target's gender (#34276) * HOTFIX Tweaked air alarm default settings for nitrogen breathing crew (#34198) air alarm default settings modified for anaerobic crew * #33571 Bomb defusal lockers always should have tools (#34394) * Automatic changelog update * [HOTFIX] fix holopads with multiple ai cores dying (#34289) change return to continue Co-authored-by: deltanedas <@deltanedas:kde.org> * Reduce Panic Bunker Minimum Playtime to 2 hours (#34401) * Add IPIntel API support. (#33339) Co-authored-by: PJB3005 <pieterjan.briers+git@gmail.com> * Automatic changelog update * Fland Reporters Room (#34408) changed the command checkpoint to a reporters room. * Automatic changelog update * Add a high-capacity water tank to the janitor's closet of Oasis (#34366) added high capacity water tank * Darkened Service job interface icons for better contrast (#34270) * Darkened Service job interface icons for better contrast * Fixed Botanist job interface icon dark handle hole * Change to new, darker, service color in all resource yml files * Revert Map file service color changes * Use new darker service color on id cards * Revert Service color change in mapping_actions.yml * Revert salvage difficulties service color * Redo service ID and job colors to match advanced palette * Revert all service color yml file changes * Switch icons to use existing service pallete colors from advanced pallete * Update meta.json for darkened service icons --------- Co-authored-by: Erskin Cherry <frobnic8@gmail.com> * Amber Station - Moved Vents Around (#34410) * Moved all vents around, made some small changes * Finished work * Removed insuls spawner since they're not merged yet * Insuls Spawner (#34407) * Added insuls spawner, time to test * adjusted whitespace since that was causing issues * Update Resources/Prototypes/Entities/Markers/Spawners/Random/maintenance.yml Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> --------- Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Manual Valves Resprite (#34378) * resprited manual valves to be colourblind friendly * Update Resources/Textures/Structures/Piping/Atmospherics/pump.rsi/meta.json Co-authored-by: Errant <35878406+Errant-4@users.noreply.github.com> --------- Co-authored-by: Errant <35878406+Errant-4@users.noreply.github.com> * Automatic changelog update * loop station door access fixes and air sink (#34414) small fixes * Raise syndicate kobold reinforcement HP crit threshold from 75 to 100 to match monkey. (#34409) kobold ops have 100 health * Anomaly dragging exploit fix and QOL changes (#34280) * Wood wall is now built from barricade congraph and on top of a barricade instead of using rods * APE dragging exploit fix * Fixed doors being blocked with mousetraps, and other Collidable items (#34045) * Changed SharedDoorSystem.GetColliding() to allow non-LowImpassible mask entities to stay in the door while it closes * Update Content.Shared/Doors/Systems/SharedDoorSystem.cs Clarifies comment of how the mask is used Co-authored-by: Centronias <charlie.t.santos@gmail.com> --------- Co-authored-by: Centronias <charlie.t.santos@gmail.com> * Fixed Jazz Instrument for Electric Guitars (#33363) * fixed jazz midi program byte * swapped around jazz and clean in instrumentList * Automatic changelog update * Porting Pride-O-Mat to Upstream (#34412) * Pride-O-Mat (#1322) * Added Pride-O-Mat * Yep * Updated license to the correct one * Added more lines, reconfigured settings a bit, also added cloaks to inventory, set coder socks to emag inventory * Removed bunny ears, fixed typo * Made requested changes Webedit lmao --------- Co-authored-by: Dorragon <101672978+Dorragon@users.noreply.github.com> * Automatic changelog update * Oasis Power Rebalance + Misc fixes (#34425) * balance oasis power as a stopgap * change waste color to proper waste color * Fix IPIntel causing frequent errors with the cleanup job. (#34428) Co-authored-by: Pieter-Jan Briers <pieterjan.briers@gmail.com> * craftable pet carrier (#34431) * craftable pet carrier * epic integration test fail * Update Resources/Prototypes/Recipes/Crafting/improvised.yml Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Update Resources/Prototypes/Recipes/Crafting/Graphs/storage/pet_carrier.yml Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Update Resources/Prototypes/Recipes/Crafting/Graphs/storage/pet_carrier.yml Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Update Resources/Prototypes/Entities/Objects/Misc/pet_carrier.yml Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * extra tab begone * epic linter fail * how did linter not see this??? --------- Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Automatic changelog update * Adds omnisexual pin (#34439) * Make important change (#7) This is to help julian test his bot * Omnibus * Remove random test file from testing a gh bot * Add pin to vendor, spawners and loadout --------- Co-authored-by: nikthechampiongr <32041239+nikthechampiongr@users.noreply.github.com> * Fix bad Rider analysis error in AccessOverriderWindow.xaml.cs (#34213) * Disable meta-atlas for big rare RSIs (#33643) * Persist deadmin to database, add admin suspension system (#34048) * Automatic changelog update * STAThread client content start (#34212) * Minor client packaging changes (#33787) * Fix muzzle accent (#34419) * Automatic changelog update * Add Discord webhook on watchlist connection (#33483) * Automatic changelog update * Fixed Thief starting gear failing on specific bag inventories. (#34430) Fixed it yayyy * Added missing details from worn capes to head of department beadsheets (#34396) * Added key and missing details from worn cape to HOP bedsheet * Corrected canvas size for sprite * Subtle tweak to shading to reduce color blurring at pillow edge * Matched Hue and tone to cape * Tweak chekered pattern marks for gold trim * Removed accidental palette inclusion * Clearer wording and corrected attribution name. * Tweaked shading on key image to fit in better with bed aesthetics * Added CE cape icon to bedsheet * Added cape image to HOP bedsheet. Made gold trim better match cape visuals * RD cape icon added. Colour tweaked to better match cape. * Updates json * Tweaks to gold trim shading to match bed aesthetics * Added better shading for HOP sheet side. Halved file size. * Optimised HOS RD and CE sheet sprites * Corrected sprite title in attribution * Replace ERT Medic's Advanced Medkits with 2 Combat Medkits (#34380) Replaced Adv kits with 2 combat kits * Fix nonsensical RegEx for name restriction (#34375) * Fixed nonsense RegEx "-" character is a range, caused an error. No need for "," to repeat so much, it's not a separator. "\\" - just why? * Further optimized RegEx structure Added: "@" delimiter for consistency "/" to escape "-" for good and to avoid further problems * Remove the ability to print the station anchor circuit board (#34358) remove the ability to print the station anchor circuit board * Automatic changelog update * Meta hotfix (#34306) * Fixed major issues with power, cargo shuttle docking, etc. * remove serialized invalids * Finished fixing the critical issues, ready for merge? * Empty commit * Added new break room to sci (they deserve it) * Fixed up other minor issues * if this map isnt PERFECT Emisse has permission to gib me and turn me into a cyborg * added Roomba's changes --------- Co-authored-by: ArtisticRoomba <145879011+ArtisticRoomba@users.noreply.github.com> * Make Mime PDA interactions silent (#34426) * make insert and eject datafields in ItemSlotsComponent.cs nullable, make mime PDA silent * make it so that you can't fit wirecutters into the slots, among other various things * Automatic changelog update * Smite vending machine (#34420) * Added smite machine to YAML * Added smite ads and inventory * Added smite vendor sprites * Changed the description of the machine to not repeat and ad line. * Added newline to end of inventory .yml * Corrected erroneous edit. * Tweaked all sprites * Added tesla toy to contraband. Reduced number of drinks available * Reduced soda varieties but increased can numbers. * Removed tesla toy from contraband inventory * Removed speech component from vending machines that already inherit it * Moved Sprite component to top of list * Added Smite vendors to random spanwers * Alphabetised spawn prototypes, commented where name is unclear * Automatic changelog update * Printable bedsheets (#34034) * Bedsheets * that one fixes yellow bedsheet and delete american bedsheet * Automatic changelog update * Update RT to v239.0.1 (#34454) * Remove christmas anomaly spawn (#34053) Update anomaly.yml * Automatic changelog update * Remove baby jail (#34443) * Remove baby jail Closes #33893 * Test fail fix. * Add a CCVar to allow from hiding admins in the reported player count. (#34406) Good for: - Keeping admins hidden - Not confuse players seeing 84/80 players Nicely pairs up with the ``admin.admins_count_for_max_players`` ccvar * Automatic changelog update * Fix Mixed puddles not updating slips when evap (#34303) * Fix Mixed puddles not updating slips when evap * Remove Comment that isn't needed Co-authored-by: Centronias <charlie.t.santos@gmail.com> * CR - use SolutionContainerSystem.UpdateChemicals * CR - cleanup unused imports --------- Co-authored-by: Centronias <charlie.t.santos@gmail.com> * Automatic changelog update * WizDen config update for IPIntel (#34457) * Fix DNA scrambler updating station record (#34091) * Fix DNA scrambler updating station record * Update Content.Server/Implants/SubdermalImplantSystem.cs --------- Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Automatic changelog update * New and Modified Map Spawners (#34424) * Added spanwers and modified others * adjusted values to be more in line with what I want * this comment may have caused that test fail * oh my god another typo * Modified door crate to be engineering flavored * reduced the pride vendor odds Webedit lmao * Elkridge Depot Fixes Again (#34461) fixes evac shuttle, fix north solars, fix vents and scrubbers * Space Ruins Variant (#34445) * Space Ruins Variant * Updated File * Added Goliaths/Removed some mobs * Plasma Station (#33991) * Plasma Station initial commit * Map fixes 1 Expanded science's SMES array Added advanced SMES Redone stamped documents with custom stamps Expanded atmospherics with more storage tanks Added status displays Add missing beacons to solars Replaced the passive gates in science with valves Removed protolathe in engineering Added guitar to CE office Replaced throngler plushie with weh cloak Add a lattice tile outside the atmos burn chamber and storange tanks Added atmos network monitor in bridge * Add cargo and emergency shuttle * Updated maps * Add plasma to map testing list * Map fixes 2 Reworked pipenets to not go under walls Redid salvage and disposals Reworked the bar to include a new bar extension facing the pool Replaced arrivals cryo with an arcade Replaced the toilets in the service plaza with cryo Removed the cryo in dorms Added more details to hallways Redid tools room to include a front desk for the janitor closet Reconnected sci to power roundstart Removed some unideal spawns Expanded the TEG airlock to be 2x3 instead of 1x3 Reduced the size of the SMES bank from 10 to 6 Disabled the plasma miners (downstreams or admins can re-enable them) Replaced illegal maint items * Fixes a 6 pack destroying the universe Ok maybe cracking a cold one with the boys wasn't a great idea. * Map fixes 3 * Quick research assistant fix * Map fixes 4 * Map fixes 5 * webedit go brrrt * Map fixes 6 * Map fixes 7 * Map fixes 8 * Fixes non-existent object It's amazing this game runs at all * Map fixes 9 * update pools * Map fixes 10 * forgot to clear my multitool I love mapping I love mapping I love mapping I love mapping I love mapping --------- Co-authored-by: Emisse <99158783+Emisse@users.noreply.github.com> * Automatic changelog update * Plasma station population tweak (#34462) * Plasma Station initial commit * Map fixes 1 Expanded science's SMES array Added advanced SMES Redone stamped documents with custom stamps Expanded atmospherics with more storage tanks Added status displays Add missing beacons to solars Replaced the passive gates in science with valves Removed protolathe in engineering Added guitar to CE office Replaced throngler plushie with weh cloak Add a lattice tile outside the atmos burn chamber and storange tanks Added atmos network monitor in bridge * Add cargo and emergency shuttle * Updated maps * Add plasma to map testing list * Map fixes 2 Reworked pipenets to not go under walls Redid salvage and disposals Reworked the bar to include a new bar extension facing the pool Replaced arrivals cryo with an arcade Replaced the toilets in the service plaza with cryo Removed the cryo in dorms Added more details to hallways Redid tools room to include a front desk for the janitor closet Reconnected sci to power roundstart Removed some unideal spawns Expanded the TEG airlock to be 2x3 instead of 1x3 Reduced the size of the SMES bank from 10 to 6 Disabled the plasma miners (downstreams or admins can re-enable them) Replaced illegal maint items * Fixes a 6 pack destroying the universe Ok maybe cracking a cold one with the boys wasn't a great idea. * Map fixes 3 * Quick research assistant fix * Map fixes 4 * Map fixes 5 * webedit go brrrt * Map fixes 6 * Map fixes 7 * Map fixes 8 * Fixes non-existent object It's amazing this game runs at all * Map fixes 9 * update pools * Map fixes 10 * forgot to clear my multitool I love mapping I love mapping I love mapping I love mapping I love mapping * Tweaked player counts --------- Co-authored-by: Emisse <99158783+Emisse@users.noreply.github.com> * Automatic changelog update * Fix inconsistent borg flashlight state (#33027) * Fix borg light being stuck on if no cell is inserted * Fix HandheldLightComponent.Activted becoming out of sync with SharedPointLightComponent.Enabled * Fix for entities which don't have a handheld light component * FIX: Uranium, Cak, and BreadDog are not garbage! (#34192) * FIX: Uranium, Cak, and BreadDog are not garbage! * Fixed bread typo for spacegarbage change. * Style: moved ediblebase * Update Resources/Prototypes/Entities/Objects/Consumable/Food/Baked/bread.yml * Update Resources/Prototypes/Entities/Objects/Consumable/Food/Baked/cake.yml --------- Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Automatic changelog update * Fix the HoS mantle metashield break (#33831) Changes 'nukies' to 'syndicate agents' in the HoS mantle's description. * fix for climbable pianos (#33690) fix for climable pianos Co-authored-by: aa5g21 <aa5g21@soton.ac.uk> * Automatic changelog update * BorgChassis transfer their mind to a dropped BorgBrain fix (#34464) Fix * Staging: Add taped logo back for 10th anniversary (#34486) * Update engine to v240.0.1 (#34497) * mind roles * partial ritual serialization fix * Update CP14RoundEndSystem.cs * delete worldEdge system * Delete StencilOverlay.WorldEdge.cs * Update CP14MagicEffectComponent.cs * delete rituals system * fix demiplane serialization * mapdamage fix serialization * common objectives fix * remove failed personal goals endscreen * fix special selling, fix serialization * more fixes * more fixes x2 * final bruh * fix --------- Co-authored-by: Southbridge <7013162+southbridge-fur@users.noreply.github.com> Co-authored-by: TytosB <54259736+TytosB@users.noreply.github.com> Co-authored-by: Emisse <99158783+Emisse@users.noreply.github.com> Co-authored-by: Booblesnoot42 <108703193+Booblesnoot42@users.noreply.github.com> Co-authored-by: Spessmann <156740760+Spessmann@users.noreply.github.com> Co-authored-by: ~DreamlyJack~ <148849095+DreamlyJack@users.noreply.github.com> Co-authored-by: PJBot <pieterjan.briers+bot@gmail.com> Co-authored-by: chromiumboy <50505512+chromiumboy@users.noreply.github.com> Co-authored-by: PopGamer46 <yt1popgamer@gmail.com> Co-authored-by: crazybrain23 <44417085+crazybrain23@users.noreply.github.com> Co-authored-by: amatwiedle <amatwiedle@gmail.com> Co-authored-by: justdie12 <125140938+justdie12@users.noreply.github.com> Co-authored-by: Nox <nebulousnox38@gmail.com> Co-authored-by: ArtisticRoomba <145879011+ArtisticRoomba@users.noreply.github.com> Co-authored-by: lzk <124214523+lzk228@users.noreply.github.com> Co-authored-by: ReeZer2 <63300653+ReeZer2@users.noreply.github.com> Co-authored-by: Errant <35878406+Errant-4@users.noreply.github.com> Co-authored-by: Alpaccalypse <21291379+Alpaccalypse@users.noreply.github.com> Co-authored-by: Spanky <scott@wearejacob.com> Co-authored-by: Thomas <87614336+Aeshus@users.noreply.github.com> Co-authored-by: Dylan Hunter Whittingham <45404433+DylanWhittingham@users.noreply.github.com> Co-authored-by: dylanhunter <dylan2.whittingham@live.uwe.ac.uk> Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> Co-authored-by: Ps3Moira <113228053+ps3moira@users.noreply.github.com> Co-authored-by: SlamBamActionman <83650252+SlamBamActionman@users.noreply.github.com> Co-authored-by: Hannah Giovanna Dawson <karakkaraz@gmail.com> Co-authored-by: Ubaser <134914314+UbaserB@users.noreply.github.com> Co-authored-by: Deerstop <edainturner@gmail.com> Co-authored-by: themias <89101928+themias@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com> Co-authored-by: Centronias <charlie.t.santos@gmail.com> Co-authored-by: ScarKy0 <106310278+ScarKy0@users.noreply.github.com> Co-authored-by: SpaceRox1244 <138547931+SpaceRox1244@users.noreply.github.com> Co-authored-by: IProduceWidgets <107586145+IProduceWidgets@users.noreply.github.com> Co-authored-by: nikthechampiongr <32041239+nikthechampiongr@users.noreply.github.com> Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com> Co-authored-by: Tayrtahn <tayrtahn@gmail.com> Co-authored-by: Pancake <Pangogie@users.noreply.github.com> Co-authored-by: Piras314 <p1r4s@proton.me> Co-authored-by: flymo5678 <86871317+flymo5678@users.noreply.github.com> Co-authored-by: c4llv07e <igor@c4llv07e.xyz> Co-authored-by: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com> Co-authored-by: Coolsurf6 <coolsurf24@yahoo.com.au> Co-authored-by: TeenSarlacc <46608342+TeenSarlacc@users.noreply.github.com> Co-authored-by: TeenSarlacc <baddiepro123@gmail.com> Co-authored-by: SpaceManiac <tad@platymuus.com> Co-authored-by: War Pigeon <54217755+minus1over12@users.noreply.github.com> Co-authored-by: Zachary Higgs <compgeek223@gmail.com> Co-authored-by: 0x6273 <0x40@keemail.me> Co-authored-by: Floxington <florian.decker@mailbox.org> Co-authored-by: Myra <vasilis@pikachu.systems> Co-authored-by: SlimSlam <73899110+Stewie523@users.noreply.github.com> Co-authored-by: frobnic8 <erskin@eldritch.org> Co-authored-by: Erskin Cherry <frobnic8@gmail.com> Co-authored-by: hyperDelegate <zachary1064@gmail.com> Co-authored-by: JustinWinningham <justinmwinningham@gmail.com> Co-authored-by: zHonys <69396539+zHonys@users.noreply.github.com> Co-authored-by: Dorragon <101672978+Dorragon@users.noreply.github.com> Co-authored-by: Pieter-Jan Briers <pieterjan.briers@gmail.com> Co-authored-by: Killerqu00 <47712032+Killerqu00@users.noreply.github.com> Co-authored-by: Julian Giebel <juliangiebel@live.de> Co-authored-by: Palladinium <patrick.chieppe@hotmail.com> Co-authored-by: Alpha-Two <92269094+Alpha-Two@users.noreply.github.com> Co-authored-by: Hyper B <137433177+HyperB1@users.noreply.github.com> Co-authored-by: kosticia <kosticia46@gmail.com> Co-authored-by: compilatron <40789662+jbox144@users.noreply.github.com> Co-authored-by: eoineoineoin <github@eoinrul.es> Co-authored-by: Patrik Caes-Sayrs <heartofgoldfish@gmail.com> Co-authored-by: ApolloVector <149586366+ApolloVector@users.noreply.github.com> Co-authored-by: Gansu <68031780+GansuLalan@users.noreply.github.com> Co-authored-by: aa5g21 <aa5g21@soton.ac.uk>
2025-01-21 23:57:12 +03:00
existing.Deadminned = admin.Deadminned;
existing.Suspended = admin.Suspended;
await db.DbContext.SaveChangesAsync(cancel);
}
public async Task UpdateAdminDeadminnedAsync(NetUserId userId, bool deadminned, CancellationToken cancel)
{
await using var db = await GetDb(cancel);
var adminRecord = db.DbContext.Admin.Where(a => a.UserId == userId);
await adminRecord.ExecuteUpdateAsync(
set => set.SetProperty(p => p.Deadminned, deadminned),
cancellationToken: cancel);
2020-11-10 16:50:28 +01:00
await db.DbContext.SaveChangesAsync(cancel);
}
public async Task RemoveAdminRankAsync(int rankId, CancellationToken cancel)
{
await using var db = await GetDb(cancel);
2020-11-10 16:50:28 +01:00
var admin = await db.DbContext.AdminRank.SingleAsync(a => a.Id == rankId, cancel);
db.DbContext.AdminRank.Remove(admin);
await db.DbContext.SaveChangesAsync(cancel);
}
public async Task AddAdminRankAsync(AdminRank rank, CancellationToken cancel)
{
await using var db = await GetDb(cancel);
2020-11-10 16:50:28 +01:00
db.DbContext.AdminRank.Add(rank);
await db.DbContext.SaveChangesAsync(cancel);
}
Fix database round start date issues (#26838) How can ONE DATABASE COLUMN have so many cursed issues I don't know, but it certainly pissed off the devil in its previous life. The start_date column on round entities in the database was added by https://github.com/space-wizards/space-station-14/pull/21153. For some reason, this PR gave the column a nonsensical default value instead of making it nullable. This default value causes the code from #25280 to break. It actually trips an assert though that's not what the original issue report ran into. This didn't get noticed on wizden servers because we at some point backfilled the start_date column based on the stored admin logs. So I change the database model to make this column nullable, updated the C# code to match, and made the existing migration set the invalid values to be NULL instead. Cool. Wait how's SQLite handle in this scenario anyways? Well actually turns out the column was *completely broken* in the first place! The code for inserting into the round table was copy pasted between SQLite and PostgreSQL, with the only difference being that the SQLite key manually assigned the primary key instead of letting SQLite AUTOINCREMENT it. And then the code to give a start_date value was only added to the PostgreSQL version (which is actually in the base class already). So for SQLite that column's been filled up with the same invalid default the whole time. Why was the code manually assigning a PK? I checked the SQLite docs for AUTOINCREMENT[1], and the behavior seems appropriate. I removed the SQLite-specific code path and it just seems to work regardless. The migration just sets the old values to NULL too. BUT WAIT, THERE'S MORE! Turns out just doing the migration on SQLite is a pain in the ass! EF Core has to create a new table to apply the nullability change, because SQLite doesn't support proper ALTER COLUMN. This causes the generated SQL commands to be weird and the UPDATE for the migration goes BEFORE the nullability change... I ended up having to make TWO migrations for SQLite. Yay. Fixes #26800 [1]: https://www.sqlite.org/autoinc.html
2024-04-14 07:39:43 +02:00
public async Task<int> AddNewRound(Server server, params Guid[] playerIds)
{
await using var db = await GetDb();
var players = await db.DbContext.Player
.Where(player => playerIds.Contains(player.UserId))
.ToListAsync();
var round = new Round
{
StartDate = DateTime.UtcNow,
Players = players,
ServerId = server.Id
};
db.DbContext.Round.Add(round);
await db.DbContext.SaveChangesAsync();
return round.Id;
}
public async Task<Round> GetRound(int id)
{
await using var db = await GetDb();
var round = await db.DbContext.Round
.Include(round => round.Players)
.SingleAsync(round => round.Id == id);
return round;
}
public async Task AddRoundPlayers(int id, Guid[] playerIds)
{
await using var db = await GetDb();
// ReSharper disable once SuggestVarOrType_Elsewhere
Dictionary<Guid, int> players = await db.DbContext.Player
.Where(player => playerIds.Contains(player.UserId))
.ToDictionaryAsync(player => player.UserId, player => player.Id);
foreach (var player in playerIds)
{
await db.DbContext.Database.ExecuteSqlAsync($"""
INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}) ON CONFLICT DO NOTHING
""");
}
await db.DbContext.SaveChangesAsync();
}
[return: NotNullIfNotNull(nameof(round))]
protected RoundRecord? MakeRoundRecord(Round? round)
{
if (round == null)
return null;
return new RoundRecord(
round.Id,
NormalizeDatabaseTime(round.StartDate),
MakeServerRecord(round.Server));
}
2020-11-10 16:50:28 +01:00
public async Task UpdateAdminRankAsync(AdminRank rank, CancellationToken cancel)
{
await using var db = await GetDb(cancel);
2020-11-10 16:50:28 +01:00
2020-11-13 03:23:13 +01:00
var existing = await db.DbContext.AdminRank
.Include(r => r.Flags)
.SingleAsync(a => a.Id == rank.Id, cancel);
existing.Flags = rank.Flags;
existing.Name = rank.Name;
2020-11-10 16:50:28 +01:00
await db.DbContext.SaveChangesAsync(cancel);
}
2021-11-11 17:54:02 +01:00
#endregion
#region Admin Logs
public async Task<(Server, bool existed)> AddOrGetServer(string serverName)
{
await using var db = await GetDb();
var server = await db.DbContext.Server
.Where(server => server.Name.Equals(serverName))
.SingleOrDefaultAsync();
if (server != default)
return (server, true);
server = new Server
{
Name = serverName
};
db.DbContext.Server.Add(server);
await db.DbContext.SaveChangesAsync();
return (server, false);
}
[return: NotNullIfNotNull(nameof(server))]
protected ServerRecord? MakeServerRecord(Server? server)
{
if (server == null)
return null;
return new ServerRecord(server.Id, server.Name);
}
public async Task AddAdminLogs(List<AdminLog> logs)
{
const int maxRetryAttempts = 5;
var initialRetryDelay = TimeSpan.FromSeconds(5);
DebugTools.Assert(logs.All(x => x.RoundId > 0), "Adding logs with invalid round ids.");
var attempt = 0;
var retryDelay = initialRetryDelay;
while (attempt < maxRetryAttempts)
{
try
{
await using var db = await GetDb();
db.DbContext.AdminLog.AddRange(logs);
await db.DbContext.SaveChangesAsync();
_opsLog.Debug($"Successfully saved {logs.Count} admin logs.");
break;
}
catch (Exception ex)
{
attempt += 1;
_opsLog.Error($"Attempt {attempt} failed to save logs: {ex}");
if (attempt >= maxRetryAttempts)
{
_opsLog.Error($"Max retry attempts reached. Failed to save {logs.Count} admin logs.");
return;
}
_opsLog.Warning($"Retrying in {retryDelay.TotalSeconds} seconds...");
await Task.Delay(retryDelay);
retryDelay *= 2;
}
}
}
protected abstract IQueryable<AdminLog> StartAdminLogsQuery(ServerDbContext db, LogFilter? filter = null);
private IQueryable<AdminLog> GetAdminLogsQuery(ServerDbContext db, LogFilter? filter = null)
{
// Save me from SQLite
var query = StartAdminLogsQuery(db, filter);
if (filter == null)
{
return query.OrderBy(log => log.Date);
}
if (filter.Round != null)
{
query = query.Where(log => log.RoundId == filter.Round);
}
if (filter.Types != null)
{
query = query.Where(log => filter.Types.Contains(log.Type));
}
if (filter.Impacts != null)
{
query = query.Where(log => filter.Impacts.Contains(log.Impact));
}
if (filter.Before != null)
{
query = query.Where(log => log.Date < filter.Before);
}
if (filter.After != null)
{
query = query.Where(log => log.Date > filter.After);
}
if (filter.IncludePlayers)
{
if (filter.AnyPlayers != null)
{
query = query.Where(log =>
log.Players.Any(p => filter.AnyPlayers.Contains(p.PlayerUserId)) ||
log.Players.Count == 0 && filter.IncludeNonPlayers);
}
if (filter.AllPlayers != null)
{
query = query.Where(log =>
log.Players.All(p => filter.AllPlayers.Contains(p.PlayerUserId)) ||
log.Players.Count == 0 && filter.IncludeNonPlayers);
}
}
else
{
query = query.Where(log => log.Players.Count == 0);
}
if (filter.LastLogId != null)
{
query = filter.DateOrder switch
{
DateOrder.Ascending => query.Where(log => log.Id > filter.LastLogId),
DateOrder.Descending => query.Where(log => log.Id < filter.LastLogId),
_ => throw new ArgumentOutOfRangeException(nameof(filter),
$"Unknown {nameof(DateOrder)} value {filter.DateOrder}")
};
}
query = filter.DateOrder switch
{
DateOrder.Ascending => query.OrderBy(log => log.Date),
DateOrder.Descending => query.OrderByDescending(log => log.Date),
_ => throw new ArgumentOutOfRangeException(nameof(filter),
$"Unknown {nameof(DateOrder)} value {filter.DateOrder}")
};
2022-09-27 21:16:04 -07:00
const int hardLogLimit = 500_000;
if (filter.Limit != null)
{
2022-09-27 21:16:04 -07:00
query = query.Take(Math.Min(filter.Limit.Value, hardLogLimit));
}
else
{
query = query.Take(hardLogLimit);
}
return query;
}
public async IAsyncEnumerable<string> GetAdminLogMessages(LogFilter? filter = null)
{
await using var db = await GetDb();
var query = GetAdminLogsQuery(db.DbContext, filter);
await foreach (var log in query.Select(log => log.Message).AsAsyncEnumerable())
{
yield return log;
}
}
public async IAsyncEnumerable<SharedAdminLog> GetAdminLogs(LogFilter? filter = null)
{
await using var db = await GetDb();
var query = GetAdminLogsQuery(db.DbContext, filter);
query = query.Include(log => log.Players);
await foreach (var log in query.AsAsyncEnumerable())
{
var players = new Guid[log.Players.Count];
for (var i = 0; i < log.Players.Count; i++)
{
players[i] = log.Players[i].PlayerUserId;
}
yield return new SharedAdminLog(log.Id, log.Type, log.Impact, log.Date, log.Message, players);
}
}
public async IAsyncEnumerable<JsonDocument> GetAdminLogsJson(LogFilter? filter = null)
{
await using var db = await GetDb();
var query = GetAdminLogsQuery(db.DbContext, filter);
await foreach (var json in query.Select(log => log.Json).AsAsyncEnumerable())
{
yield return json;
}
}
public async Task<int> CountAdminLogs(int round)
{
await using var db = await GetDb();
return await db.DbContext.AdminLog.CountAsync(log => log.RoundId == round);
}
#endregion
2022-01-04 06:37:06 -07:00
#region Whitelist
public async Task<bool> GetWhitelistStatusAsync(NetUserId player)
{
await using var db = await GetDb();
return await db.DbContext.Whitelist.AnyAsync(w => w.UserId == player);
}
public async Task AddToWhitelistAsync(NetUserId player)
{
await using var db = await GetDb();
db.DbContext.Whitelist.Add(new Whitelist { UserId = player });
await db.DbContext.SaveChangesAsync();
}
public async Task RemoveFromWhitelistAsync(NetUserId player)
{
await using var db = await GetDb();
var entry = await db.DbContext.Whitelist.SingleAsync(w => w.UserId == player);
db.DbContext.Whitelist.Remove(entry);
await db.DbContext.SaveChangesAsync();
}
public async Task<DateTimeOffset?> GetLastReadRules(NetUserId player)
{
await using var db = await GetDb();
return NormalizeDatabaseTime(await db.DbContext.Player
.Where(dbPlayer => dbPlayer.UserId == player)
.Select(dbPlayer => dbPlayer.LastReadRules)
.SingleOrDefaultAsync());
}
public async Task SetLastReadRules(NetUserId player, DateTimeOffset date)
{
await using var db = await GetDb();
var dbPlayer = await db.DbContext.Player.Where(dbPlayer => dbPlayer.UserId == player).SingleOrDefaultAsync();
if (dbPlayer == null)
{
return;
}
dbPlayer.LastReadRules = date.UtcDateTime;
await db.DbContext.SaveChangesAsync();
}
public async Task<bool> GetBlacklistStatusAsync(NetUserId player)
{
await using var db = await GetDb();
return await db.DbContext.Blacklist.AnyAsync(w => w.UserId == player);
}
public async Task AddToBlacklistAsync(NetUserId player)
{
await using var db = await GetDb();
db.DbContext.Blacklist.Add(new Blacklist() { UserId = player });
await db.DbContext.SaveChangesAsync();
}
public async Task RemoveFromBlacklistAsync(NetUserId player)
{
await using var db = await GetDb();
var entry = await db.DbContext.Blacklist.SingleAsync(w => w.UserId == player);
db.DbContext.Blacklist.Remove(entry);
await db.DbContext.SaveChangesAsync();
}
2022-01-04 06:37:06 -07:00
#endregion
#region Uploaded Resources Logs
public async Task AddUploadedResourceLogAsync(NetUserId user, DateTimeOffset date, string path, byte[] data)
{
await using var db = await GetDb();
db.DbContext.UploadedResourceLog.Add(new UploadedResourceLog() { UserId = user, Date = date.UtcDateTime, Path = path, Data = data });
await db.DbContext.SaveChangesAsync();
}
public async Task PurgeUploadedResourceLogAsync(int days)
{
await using var db = await GetDb();
var date = DateTime.UtcNow.Subtract(TimeSpan.FromDays(days));
await foreach (var log in db.DbContext.UploadedResourceLog
.Where(l => date > l.Date)
.AsAsyncEnumerable())
{
db.DbContext.UploadedResourceLog.Remove(log);
}
await db.DbContext.SaveChangesAsync();
}
#endregion
#region Admin Notes
public virtual async Task<int> AddAdminNote(AdminNote note)
{
await using var db = await GetDb();
db.DbContext.AdminNotes.Add(note);
await db.DbContext.SaveChangesAsync();
return note.Id;
}
public virtual async Task<int> AddAdminWatchlist(AdminWatchlist watchlist)
{
await using var db = await GetDb();
db.DbContext.AdminWatchlists.Add(watchlist);
await db.DbContext.SaveChangesAsync();
return watchlist.Id;
}
public virtual async Task<int> AddAdminMessage(AdminMessage message)
{
await using var db = await GetDb();
db.DbContext.AdminMessages.Add(message);
await db.DbContext.SaveChangesAsync();
return message.Id;
}
public async Task<AdminNoteRecord?> GetAdminNote(int id)
{
await using var db = await GetDb();
var entity = await db.DbContext.AdminNotes
.Where(note => note.Id == id)
.Include(note => note.Round)
.ThenInclude(r => r!.Server)
.Include(note => note.CreatedBy)
.Include(note => note.LastEditedBy)
.Include(note => note.DeletedBy)
.Include(note => note.Player)
.SingleOrDefaultAsync();
return entity == null ? null : MakeAdminNoteRecord(entity);
}
private AdminNoteRecord MakeAdminNoteRecord(AdminNote entity)
{
return new AdminNoteRecord(
entity.Id,
MakeRoundRecord(entity.Round),
MakePlayerRecord(entity.Player),
entity.PlaytimeAtNote,
entity.Message,
entity.Severity,
MakePlayerRecord(entity.CreatedBy),
NormalizeDatabaseTime(entity.CreatedAt),
MakePlayerRecord(entity.LastEditedBy),
NormalizeDatabaseTime(entity.LastEditedAt),
NormalizeDatabaseTime(entity.ExpirationTime),
entity.Deleted,
MakePlayerRecord(entity.DeletedBy),
NormalizeDatabaseTime(entity.DeletedAt),
entity.Secret);
}
public async Task<AdminWatchlistRecord?> GetAdminWatchlist(int id)
{
await using var db = await GetDb();
var entity = await db.DbContext.AdminWatchlists
.Where(note => note.Id == id)
.Include(note => note.Round)
.ThenInclude(r => r!.Server)
.Include(note => note.CreatedBy)
.Include(note => note.LastEditedBy)
.Include(note => note.DeletedBy)
.Include(note => note.Player)
.SingleOrDefaultAsync();
return entity == null ? null : MakeAdminWatchlistRecord(entity);
}
public async Task<AdminMessageRecord?> GetAdminMessage(int id)
{
await using var db = await GetDb();
var entity = await db.DbContext.AdminMessages
.Where(note => note.Id == id)
.Include(note => note.Round)
.ThenInclude(r => r!.Server)
.Include(note => note.CreatedBy)
.Include(note => note.LastEditedBy)
.Include(note => note.DeletedBy)
.Include(note => note.Player)
.SingleOrDefaultAsync();
return entity == null ? null : MakeAdminMessageRecord(entity);
}
private AdminMessageRecord MakeAdminMessageRecord(AdminMessage entity)
{
return new AdminMessageRecord(
entity.Id,
MakeRoundRecord(entity.Round),
MakePlayerRecord(entity.Player),
entity.PlaytimeAtNote,
entity.Message,
MakePlayerRecord(entity.CreatedBy),
NormalizeDatabaseTime(entity.CreatedAt),
MakePlayerRecord(entity.LastEditedBy),
NormalizeDatabaseTime(entity.LastEditedAt),
NormalizeDatabaseTime(entity.ExpirationTime),
entity.Deleted,
MakePlayerRecord(entity.DeletedBy),
NormalizeDatabaseTime(entity.DeletedAt),
entity.Seen,
entity.Dismissed);
}
public async Task<ServerBanNoteRecord?> GetServerBanAsNoteAsync(int id)
{
await using var db = await GetDb();
var ban = await db.DbContext.Ban
.Include(ban => ban.Unban)
.Include(ban => ban.Round)
.ThenInclude(r => r!.Server)
.Include(ban => ban.CreatedBy)
.Include(ban => ban.LastEditedBy)
.Include(ban => ban.Unban)
.SingleOrDefaultAsync(b => b.Id == id);
if (ban is null)
return null;
var player = await db.DbContext.Player.SingleOrDefaultAsync(p => p.UserId == ban.PlayerUserId);
return new ServerBanNoteRecord(
ban.Id,
MakeRoundRecord(ban.Round),
MakePlayerRecord(player),
ban.PlaytimeAtNote,
ban.Reason,
ban.Severity,
MakePlayerRecord(ban.CreatedBy),
ban.BanTime,
MakePlayerRecord(ban.LastEditedBy),
ban.LastEditedAt,
ban.ExpirationTime,
ban.Hidden,
MakePlayerRecord(ban.Unban?.UnbanningAdmin == null
? null
: await db.DbContext.Player.SingleOrDefaultAsync(p =>
p.UserId == ban.Unban.UnbanningAdmin.Value)),
ban.Unban?.UnbanTime);
}
public async Task<ServerRoleBanNoteRecord?> GetServerRoleBanAsNoteAsync(int id)
{
await using var db = await GetDb();
var ban = await db.DbContext.RoleBan
.Include(ban => ban.Unban)
.Include(ban => ban.Round)
.ThenInclude(r => r!.Server)
.Include(ban => ban.CreatedBy)
.Include(ban => ban.LastEditedBy)
.Include(ban => ban.Unban)
.SingleOrDefaultAsync(b => b.Id == id);
if (ban is null)
return null;
var player = await db.DbContext.Player.SingleOrDefaultAsync(p => p.UserId == ban.PlayerUserId);
var unbanningAdmin =
ban.Unban is null
? null
: await db.DbContext.Player.SingleOrDefaultAsync(b => b.UserId == ban.Unban.UnbanningAdmin);
return new ServerRoleBanNoteRecord(
ban.Id,
MakeRoundRecord(ban.Round),
MakePlayerRecord(player),
ban.PlaytimeAtNote,
ban.Reason,
ban.Severity,
MakePlayerRecord(ban.CreatedBy),
ban.BanTime,
MakePlayerRecord(ban.LastEditedBy),
ban.LastEditedAt,
ban.ExpirationTime,
ban.Hidden,
new [] { ban.RoleId.Replace(BanManager.JobPrefix, null) },
MakePlayerRecord(unbanningAdmin),
ban.Unban?.UnbanTime);
}
public async Task<List<IAdminRemarksRecord>> GetAllAdminRemarks(Guid player)
{
await using var db = await GetDb();
List<IAdminRemarksRecord> notes = new();
notes.AddRange(
(await (from note in db.DbContext.AdminNotes
where note.PlayerUserId == player &&
!note.Deleted &&
(note.ExpirationTime == null || DateTime.UtcNow < note.ExpirationTime)
select note)
.Include(note => note.Round)
.ThenInclude(r => r!.Server)
.Include(note => note.CreatedBy)
.Include(note => note.LastEditedBy)
.Include(note => note.Player)
.ToListAsync()).Select(MakeAdminNoteRecord));
notes.AddRange(await GetActiveWatchlistsImpl(db, player));
notes.AddRange(await GetMessagesImpl(db, player));
notes.AddRange(await GetServerBansAsNotesForUser(db, player));
notes.AddRange(await GetGroupedServerRoleBansAsNotesForUser(db, player));
return notes;
}
public async Task EditAdminNote(int id, string message, NoteSeverity severity, bool secret, Guid editedBy, DateTimeOffset editedAt, DateTimeOffset? expiryTime)
{
await using var db = await GetDb();
var note = await db.DbContext.AdminNotes.Where(note => note.Id == id).SingleAsync();
note.Message = message;
note.Severity = severity;
note.Secret = secret;
note.LastEditedById = editedBy;
note.LastEditedAt = editedAt.UtcDateTime;
note.ExpirationTime = expiryTime?.UtcDateTime;
await db.DbContext.SaveChangesAsync();
}
public async Task EditAdminWatchlist(int id, string message, Guid editedBy, DateTimeOffset editedAt, DateTimeOffset? expiryTime)
{
await using var db = await GetDb();
var note = await db.DbContext.AdminWatchlists.Where(note => note.Id == id).SingleAsync();
note.Message = message;
note.LastEditedById = editedBy;
note.LastEditedAt = editedAt.UtcDateTime;
note.ExpirationTime = expiryTime?.UtcDateTime;
await db.DbContext.SaveChangesAsync();
}
public async Task EditAdminMessage(int id, string message, Guid editedBy, DateTimeOffset editedAt, DateTimeOffset? expiryTime)
{
await using var db = await GetDb();
var note = await db.DbContext.AdminMessages.Where(note => note.Id == id).SingleAsync();
note.Message = message;
note.LastEditedById = editedBy;
note.LastEditedAt = editedAt.UtcDateTime;
note.ExpirationTime = expiryTime?.UtcDateTime;
await db.DbContext.SaveChangesAsync();
}
public async Task DeleteAdminNote(int id, Guid deletedBy, DateTimeOffset deletedAt)
{
await using var db = await GetDb();
var note = await db.DbContext.AdminNotes.Where(note => note.Id == id).SingleAsync();
note.Deleted = true;
note.DeletedById = deletedBy;
note.DeletedAt = deletedAt.UtcDateTime;
await db.DbContext.SaveChangesAsync();
}
public async Task DeleteAdminWatchlist(int id, Guid deletedBy, DateTimeOffset deletedAt)
{
await using var db = await GetDb();
var watchlist = await db.DbContext.AdminWatchlists.Where(note => note.Id == id).SingleAsync();
watchlist.Deleted = true;
watchlist.DeletedById = deletedBy;
watchlist.DeletedAt = deletedAt.UtcDateTime;
await db.DbContext.SaveChangesAsync();
}
public async Task DeleteAdminMessage(int id, Guid deletedBy, DateTimeOffset deletedAt)
{
await using var db = await GetDb();
var message = await db.DbContext.AdminMessages.Where(note => note.Id == id).SingleAsync();
message.Deleted = true;
message.DeletedById = deletedBy;
message.DeletedAt = deletedAt.UtcDateTime;
await db.DbContext.SaveChangesAsync();
}
public async Task HideServerBanFromNotes(int id, Guid deletedBy, DateTimeOffset deletedAt)
{
await using var db = await GetDb();
var ban = await db.DbContext.Ban.Where(ban => ban.Id == id).SingleAsync();
ban.Hidden = true;
ban.LastEditedById = deletedBy;
ban.LastEditedAt = deletedAt.UtcDateTime;
await db.DbContext.SaveChangesAsync();
}
public async Task HideServerRoleBanFromNotes(int id, Guid deletedBy, DateTimeOffset deletedAt)
{
await using var db = await GetDb();
var roleBan = await db.DbContext.RoleBan.Where(roleBan => roleBan.Id == id).SingleAsync();
roleBan.Hidden = true;
roleBan.LastEditedById = deletedBy;
roleBan.LastEditedAt = deletedAt.UtcDateTime;
await db.DbContext.SaveChangesAsync();
}
public async Task<List<IAdminRemarksRecord>> GetVisibleAdminRemarks(Guid player)
{
await using var db = await GetDb();
List<IAdminRemarksRecord> notesCol = new();
notesCol.AddRange(
(await (from note in db.DbContext.AdminNotes
where note.PlayerUserId == player &&
!note.Secret &&
!note.Deleted &&
(note.ExpirationTime == null || DateTime.UtcNow < note.ExpirationTime)
select note)
.Include(note => note.Round)
.ThenInclude(r => r!.Server)
.Include(note => note.CreatedBy)
.Include(note => note.Player)
.ToListAsync()).Select(MakeAdminNoteRecord));
notesCol.AddRange(await GetMessagesImpl(db, player));
notesCol.AddRange(await GetServerBansAsNotesForUser(db, player));
notesCol.AddRange(await GetGroupedServerRoleBansAsNotesForUser(db, player));
return notesCol;
}
public async Task<List<AdminWatchlistRecord>> GetActiveWatchlists(Guid player)
{
await using var db = await GetDb();
return await GetActiveWatchlistsImpl(db, player);
}
protected async Task<List<AdminWatchlistRecord>> GetActiveWatchlistsImpl(DbGuard db, Guid player)
{
var entities = await (from watchlist in db.DbContext.AdminWatchlists
where watchlist.PlayerUserId == player &&
!watchlist.Deleted &&
(watchlist.ExpirationTime == null || DateTime.UtcNow < watchlist.ExpirationTime)
select watchlist)
.Include(note => note.Round)
.ThenInclude(r => r!.Server)
.Include(note => note.CreatedBy)
.Include(note => note.LastEditedBy)
.Include(note => note.Player)
.ToListAsync();
return entities.Select(MakeAdminWatchlistRecord).ToList();
}
private AdminWatchlistRecord MakeAdminWatchlistRecord(AdminWatchlist entity)
{
return new AdminWatchlistRecord(entity.Id, MakeRoundRecord(entity.Round), MakePlayerRecord(entity.Player), entity.PlaytimeAtNote, entity.Message, MakePlayerRecord(entity.CreatedBy), NormalizeDatabaseTime(entity.CreatedAt), MakePlayerRecord(entity.LastEditedBy), NormalizeDatabaseTime(entity.LastEditedAt), NormalizeDatabaseTime(entity.ExpirationTime), entity.Deleted, MakePlayerRecord(entity.DeletedBy), NormalizeDatabaseTime(entity.DeletedAt));
}
public async Task<List<AdminMessageRecord>> GetMessages(Guid player)
{
await using var db = await GetDb();
return await GetMessagesImpl(db, player);
}
protected async Task<List<AdminMessageRecord>> GetMessagesImpl(DbGuard db, Guid player)
{
var entities = await (from message in db.DbContext.AdminMessages
where message.PlayerUserId == player && !message.Deleted &&
(message.ExpirationTime == null || DateTime.UtcNow < message.ExpirationTime)
select message).Include(note => note.Round)
.ThenInclude(r => r!.Server)
.Include(note => note.CreatedBy)
.Include(note => note.LastEditedBy)
.Include(note => note.Player)
.ToListAsync();
return entities.Select(MakeAdminMessageRecord).ToList();
}
public async Task MarkMessageAsSeen(int id, bool dismissedToo)
{
await using var db = await GetDb();
var message = await db.DbContext.AdminMessages.SingleAsync(m => m.Id == id);
message.Seen = true;
if (dismissedToo)
message.Dismissed = true;
await db.DbContext.SaveChangesAsync();
}
// These two are here because they get converted into notes later
protected async Task<List<ServerBanNoteRecord>> GetServerBansAsNotesForUser(DbGuard db, Guid user)
{
// You can't group queries, as player will not always exist. When it doesn't, the
// whole query returns nothing
var player = await db.DbContext.Player.SingleOrDefaultAsync(p => p.UserId == user);
2023-07-21 15:43:47 +02:00
var bans = await db.DbContext.Ban
.Where(ban => ban.PlayerUserId == user && !ban.Hidden)
.Include(ban => ban.Unban)
.Include(ban => ban.Round)
.ThenInclude(r => r!.Server)
.Include(ban => ban.CreatedBy)
.Include(ban => ban.LastEditedBy)
.Include(ban => ban.Unban)
2023-07-21 15:43:47 +02:00
.ToArrayAsync();
var banNotes = new List<ServerBanNoteRecord>();
2023-07-21 15:43:47 +02:00
foreach (var ban in bans)
{
var banNote = new ServerBanNoteRecord(
ban.Id,
MakeRoundRecord(ban.Round),
MakePlayerRecord(player),
ban.PlaytimeAtNote,
ban.Reason,
ban.Severity,
MakePlayerRecord(ban.CreatedBy),
NormalizeDatabaseTime(ban.BanTime),
MakePlayerRecord(ban.LastEditedBy),
NormalizeDatabaseTime(ban.LastEditedAt),
NormalizeDatabaseTime(ban.ExpirationTime),
ban.Hidden,
MakePlayerRecord(ban.Unban?.UnbanningAdmin == null
2023-07-21 15:43:47 +02:00
? null
: await db.DbContext.Player.SingleOrDefaultAsync(
p => p.UserId == ban.Unban.UnbanningAdmin.Value)),
NormalizeDatabaseTime(ban.Unban?.UnbanTime));
2023-07-21 15:43:47 +02:00
banNotes.Add(banNote);
}
return banNotes;
}
protected async Task<List<ServerRoleBanNoteRecord>> GetGroupedServerRoleBansAsNotesForUser(DbGuard db, Guid user)
{
// Server side query
2023-07-21 15:43:47 +02:00
var bansQuery = await db.DbContext.RoleBan
.Where(ban => ban.PlayerUserId == user && !ban.Hidden)
.Include(ban => ban.Unban)
.Include(ban => ban.Round)
.ThenInclude(r => r!.Server)
.Include(ban => ban.CreatedBy)
.Include(ban => ban.LastEditedBy)
.Include(ban => ban.Unban)
2023-07-21 15:43:47 +02:00
.ToArrayAsync();
// Client side query, as EF can't do groups yet
2023-07-21 15:43:47 +02:00
var bansEnumerable = bansQuery
2023-07-22 20:27:29 +03:00
.GroupBy(ban => new { ban.BanTime, CreatedBy = (Player?)ban.CreatedBy, ban.Reason, Unbanned = ban.Unban == null })
2023-07-21 15:43:47 +02:00
.Select(banGroup => banGroup)
.ToArray();
List<ServerRoleBanNoteRecord> bans = new();
var player = await db.DbContext.Player.SingleOrDefaultAsync(p => p.UserId == user);
2023-07-21 15:43:47 +02:00
foreach (var banGroup in bansEnumerable)
{
2023-07-21 15:43:47 +02:00
var firstBan = banGroup.First();
Player? unbanningAdmin = null;
2023-07-21 15:43:47 +02:00
if (firstBan.Unban?.UnbanningAdmin is not null)
unbanningAdmin = await db.DbContext.Player.SingleOrDefaultAsync(p => p.UserId == firstBan.Unban.UnbanningAdmin.Value);
2023-07-21 15:43:47 +02:00
bans.Add(new ServerRoleBanNoteRecord(
firstBan.Id,
MakeRoundRecord(firstBan.Round),
MakePlayerRecord(player),
firstBan.PlaytimeAtNote,
firstBan.Reason,
firstBan.Severity,
MakePlayerRecord(firstBan.CreatedBy),
NormalizeDatabaseTime(firstBan.BanTime),
MakePlayerRecord(firstBan.LastEditedBy),
NormalizeDatabaseTime(firstBan.LastEditedAt),
NormalizeDatabaseTime(firstBan.ExpirationTime),
firstBan.Hidden,
banGroup.Select(ban => ban.RoleId.Replace(BanManager.JobPrefix, null)).ToArray(),
MakePlayerRecord(unbanningAdmin),
NormalizeDatabaseTime(firstBan.Unban?.UnbanTime)));
}
return bans;
}
#endregion
#region Job Whitelists
public async Task<bool> AddJobWhitelist(Guid player, ProtoId<JobPrototype> job)
{
await using var db = await GetDb();
var exists = await db.DbContext.RoleWhitelists
.Where(w => w.PlayerUserId == player)
.Where(w => w.RoleId == job.Id)
.AnyAsync();
if (exists)
return false;
var whitelist = new RoleWhitelist
{
PlayerUserId = player,
RoleId = job
};
db.DbContext.RoleWhitelists.Add(whitelist);
await db.DbContext.SaveChangesAsync();
return true;
}
public async Task<List<string>> GetJobWhitelists(Guid player, CancellationToken cancel)
{
await using var db = await GetDb(cancel);
return await db.DbContext.RoleWhitelists
.Where(w => w.PlayerUserId == player)
.Select(w => w.RoleId)
.ToListAsync(cancellationToken: cancel);
}
public async Task<bool> IsJobWhitelisted(Guid player, ProtoId<JobPrototype> job)
{
await using var db = await GetDb();
return await db.DbContext.RoleWhitelists
.Where(w => w.PlayerUserId == player)
.Where(w => w.RoleId == job.Id)
.AnyAsync();
}
public async Task<bool> RemoveJobWhitelist(Guid player, ProtoId<JobPrototype> job)
{
await using var db = await GetDb();
var entry = await db.DbContext.RoleWhitelists
.Where(w => w.PlayerUserId == player)
.Where(w => w.RoleId == job.Id)
.SingleOrDefaultAsync();
if (entry == null)
return false;
db.DbContext.RoleWhitelists.Remove(entry);
await db.DbContext.SaveChangesAsync();
return true;
}
#endregion
Upstream sync (#786) * Box Station - Dechristmassified (#34135) * dechrismassified * removed camera from shower * Marathon Station - Dechristmassified (#34136) * dechristmassified * further dechristmassified * Loop Station Decal and maints additions (#34103) * many changes * contentingregrationtests * serialized invalid removed * blank * "Changes and fixes as suggested" * blank * blank * added desk bells * engi rework rework rework * added gate to content integration * tweaks * aaa * bbb * added holopads * ccc * Update default.yml * hotfix * aaa * bbb * many many tweaks and fixes * aaa * decals and maints * aaa * bbb * ccc --------- Co-authored-by: Emisse <99158783+Emisse@users.noreply.github.com> * Rename cryobed yml file (#34134) renamed cryopod.yml to cryogenic_sleep_unit.yml * Cog update (not very merry) (#34144) removed christmas merry * bagel update (#34145) * Add hair pulato (#34117) * add sprite pulato * update * add pulato hair * add pulato hair * add pulato hair * update meta "pulato" * Automatic changelog update * Holopad UI tweak for incoming calls (#34137) * Initial commit * Update * Comment correction * Minor margin increase * Holopads no longer log broadcasted speech and emotes in the chat (#34114) Initial commit * Automatic changelog update * Fixes borgs not being able to check their laws in crit (#34133) * fix * fix2 * Add contraband parent to laser gun safe (#34132) * Automatic changelog update * Add Holopad Circuit Board to A/V Communication Technology (#34150) Added the holopad circuit board to the AV Communication technology and circuit imprinter lathe. * Automatic changelog update * Fix disposal signal routers sprites (#34139) * Fix disposal signal routers sprites * Remove old shitcode * Automatic changelog update * Meta station overhaul (#33506) * added mail, moved some things around, and fixed a lot of APCs * fixed my mistakes * Fixed a few mistakes and AI camera names * Redid south medbay and more wiring * Finished sci overhaul, and fixed all issues that I could find. * rebuilt botany, removed vox box, fixed all known issues. * Overhauled security * Minor commit as I prepare to update my copy * Rebalanced role counts * Final changes, ready for review! * Emisse and other people fixed issues with the station * Finalized changes (for real this time)! * Standardize shotgun ammo in storagefills (#34156) shotgun ammo changes * Automatic changelog update * meta update (#34158) * Amber Station Adjustments (#34126) * Made a couple fixes to various decals, cleaned up some entities, gave the clown their bag and the bartender a handlabeler * Several changes, more cameras, lighting fixes, adjusted hydro a bit, gave sec a bunch of shutters * Added new random spawners for science and added them to Amber * fixed the science spawners and modified amber slightly * Fixed the random instrument entry * Fix friendly vent spiders (#34153) Swapped order of parents for MobGiantSpiderAngry * Removed UseDelay component from RCD (#34149) * Automatic changelog update * Decrease hp for rusted walls (#34043) * Automatic changelog update * FIX: Thief beacon doubled steal targets (#33750) * Automatic changelog update * remove nukemass song (#34066) * Automatic changelog update * Corrected all ghost role names to title case. (#34155) * Corrected all ghost role names to title case. * Removes full stop from Hamlet's title. * Updated ghost role names not in the main ghost roles .ftl * Two capitals corrections * Packed Update (Remove Christmas & New Evac) (#34168) * Packed update (remove christmas, new shuttle) * Fix invalid * the voices * Omega Update (Remove Christmas) (#34174) omega soap * Renamed "Irish Car Bomb" drink to "Irish Slammer" (#34107) * Renamed "Irish Car Bomb" drink to "Irish Slammer", due to concerns over insensitivity. * Fixing some missed references * Added prototype id changes to migration.yml. Removed any reference to the troubles (and corrected ale to stout for flavour text). * Corrected description back to "Irish Cream" * Removed non-entities from migration.yml * Automatic changelog update * Bugfix for the AI player's eye getting stuck when their broadcast is interrupted (#34093) Initial commit * Speech is relayed by holopad holograms (#33978) * Initial commit * Corrected a field attribute * Make JPEG a PNG (#34176) Make 3.png a PNG * Removed Undesirable Ion Storm Verbs (#34175) * Remove Undesirable Laws * empty * added basic admin logs for PDA notekeeper notes (#34118) * added basic admin logs for PDA notekeeper notes * formatting * added new LogType 'PdaInteract' and changed PDA notekeeper logs to it --------- Co-authored-by: dylanhunter <dylan2.whittingham@live.uwe.ac.uk> * Automatic changelog update * Sprites defined for all non-generic computer boards. Added new syndicate computer board sprite. (#34104) * Defined sprites for non-generic computer boards. Added new syndicate computer board sprite. * Added new sprite to meta.json and updated attribution. * Reformatted module.rsi meta.json to match other meta file styles. * Syndicate board sprite made less yellow/gold, changed outer chips to black. Using grey/silver for CPU centre, akin to syndie agent PDA theme, and to keep distinctive from security board. * Corrected indentation spacing for currently edited entities. * Update Resources/Prototypes/Entities/Objects/Devices/Circuitboards/computer.yml * add pr link to attribution --------- Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> Co-authored-by: Errant <35878406+Errant-4@users.noreply.github.com> * Added pricegun sound (#34119) added pricegun sound Co-authored-by: dylanhunter <dylan2.whittingham@live.uwe.ac.uk> * Automatic changelog update * Separate Tables n' Counters (#32673) * Update tables.yml * Remove Extra base: state_ * Update tables.yml * Automatic changelog update * Add Chameleon PDA (#30514) * V1 commit * Remove PDA name and unnecessary pda state * Adds PDA to Chameleon backpack & thief toolbox * Change to use AppearanceDataInit * Add basic PDA state to ensure there's always a sprite before AppearanceData can be applied * Revert PDA name (this will be changed to another way later) * Update PDA name updating to new system * Fix yaml, and fix Agent ID chameleon * Updated based on review * Automatic changelog update * Add some ion storm actions to replace removed ones (#34180) * Add some ion storm actions to replace removed ones * Remove other country references, replace * Some more tuning of the storm values, removing real-world countries * boldy basics * Automatic changelog update * Amber Station and Science Spawner Tweaks (#34187) * Modified science spawners a bit since I realized including maints loot was undesireable * Linked Medical doors to buttons, redesigned the floor of the dining area a bit, placed more science spawners * Somehow I overlooked that I was importing the maints loot table instead of the sci loot table * Gave sci an EOD closet * named the evac shuttle * Core update (#34201) add * Elkridge Depot (The station formerly known as Cell) (#34085) * named apcs, doors, air alarms, cameras, fire alarms, substations, SMESs * updated PostMapInitTest.cs to include Cell * added psychologist spawn * fixed scanner console link, fixed disposals conveyors, and more * added janitor service lights, maints firelocks, and more * added more fun maint rooms * improved head offices, kitchen, psych. added maints between science and arrivals * fixed spawners placed over solid objects * added unique evac shuttle, the Cilium * evac shuttle is now orientated correctly * added unique cargo shuttle * updated kitchen area * renamed Cell Station to Elkridge Depot, removed most main hall airlocks for smoother travel * general last-minute touch-ups around the bridge and sec * changed station name in PostMapInitTest.cs * Add Elkridge Depot into Map Rotation (#34206) * named apcs, doors, air alarms, cameras, fire alarms, substations, SMESs * updated PostMapInitTest.cs to include Cell * added psychologist spawn * fixed scanner console link, fixed disposals conveyors, and more * added janitor service lights, maints firelocks, and more * added more fun maint rooms * improved head offices, kitchen, psych. added maints between science and arrivals * fixed spawners placed over solid objects * added unique evac shuttle, the Cilium * evac shuttle is now orientated correctly * added unique cargo shuttle * updated kitchen area * renamed Cell Station to Elkridge Depot, removed most main hall airlocks for smoother travel * general last-minute touch-ups around the bridge and sec * changed station name in PostMapInitTest.cs * added Elkridge to default map pool * added myself to map_attribution.yml credits * Automatic changelog update * Packed Update (#34208) Packed Update (decals mostly) * Apply forensics when loading with an ammo box (#32280) * Automatic changelog update * Update Credits (#34220) Co-authored-by: PJBot <pieterjan.briers+bot@gmail.com> * Fix rainbow lizard plushie inhands (#34128) * fix rainbow plushie inhands * address requested changes * attribute sprites * wielding refactor/fixes (#32188) * refactor wieldable events * fix inconsitency with wielding and use updated events * wieldable cosmetic refactoring * Update Content.Shared/Wieldable/Events.cs Co-authored-by: Centronias <charlie.t.santos@gmail.com> * real Co-authored-by: ScarKy0 <106310278+ScarKy0@users.noreply.github.com> --------- Co-authored-by: deltanedas <@deltanedas:kde.org> Co-authored-by: Centronias <charlie.t.santos@gmail.com> Co-authored-by: ScarKy0 <106310278+ScarKy0@users.noreply.github.com> * Automatic changelog update * Lobby chat width and custom lobby titles (#33783) * lobby name cvar * panel width * skrek * server name localization fix * comment format fix Co-authored-by: Thomas <87614336+Aeshus@users.noreply.github.com> * remove redundant newline Co-authored-by: Thomas <87614336+Aeshus@users.noreply.github.com> * string.empty Co-authored-by: Thomas <87614336+Aeshus@users.noreply.github.com> * use SetWidth * Update Resources/Locale/en-US/lobby/lobby-gui.ftl --------- Co-authored-by: Thomas <87614336+Aeshus@users.noreply.github.com> Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Automatic changelog update * Adds bullet collision to station lights (#34070) Adds collision with bullets to lights * Automatic changelog update * Oasis Update (#34245) santa is keel. * Amber Station - Minor Fixes (#34246) * Moved the stand clear decal in front of the janitor's shutters up two pixels * added tech maints under most maints doors, fixed power issues in cargo, and fixed a couple minor issues * Make station anchor hitbox less insufferable (#34217) * Automatic changelog update * Remove kessler and zombeteors gamemodes from the secret pool (#34051) * Remove kessler, zombeteors gameodes * Probably should keep the protos in case an admin wants to torture players secretly * address slart review * Automatic changelog update * Added distinct ad and bye chatter to Dr. Gibb vending (#34182) * Added distinct ad and bye chatter to Dr. Gibb vending * Correcting revert mistake * Changed ad pack names to better match naming convention * Implement approved rule changes (#34233) * Special reagents now appear in the guidebook (#34265) * Special reagents now appear in the guidebook * Improved guidebook wording for reagent category * Automatic changelog update * Implement approved rule changes (#34233) * Fix compilation errors in tests from update (#34272) Required for https://github.com/space-wizards/RobustToolbox/pull/5590 to not cause compile fails, but can be merged on its own * Fix portable scrubber appearing powered on spawn (#34274) * [HOTFIX] Fix chameleon PDAs renaming IDs (#34249) Fix chameleon PDA * [HOTFIX] Fix Meta station power (#34256) * hotfix meta power * fixed AME * add missing cargo shuttle pilot console to cargo * Update vessel_warning.ogg (#34263) * Update vessel_warning.ogg Remove DC offset and apply short fade out. * Update attributions.yml * Update attributions.yml * Add bleating accent to goats (#34273) * Automatic changelog update * Happy New Year (#34288) happy new year * Amber Station - Balance Improvements (#34294) changed the center area in med bay to a garden, weakened meteor shielding in some areas, also general touch ups around the station * Fixed Loop Station's southern solar array unlinked airlocks (#34296) Fixed Southern solar external airlock door bolts * Fix empty lines in adminwho with stealthmins. (#34122) Don't print newline if admin is hidden. * Automatic changelog update * Added missing cameras to Loop Station (#34308) * Added missing cameras * Added missing cameras * Amber Station - Fixes and Warm Lights (#34324) * Added warm lights, placed them around the map, also fixed an issue with the MV wire in the cafeteria * Fixed lv wiring in caf, and adjusted a couple things * Empty commit to force checks to rerun * Automatic changelog update * change locking to use ComplexInteraction (#34326) Co-authored-by: deltanedas <@deltanedas:kde.org> * Automatic changelog update * Drink titles and soda vendor consistency (#34178) * Made capitalisation of proper names consistent. * Roy Rogers is presumably a proper name. * Second pass at distinguishing proper names only. * Two nitpicking/minor changes * Fixed some overlooked can brand names. Matched case with descriptions. * Switched generic sodas with brands for SodaInventory * Removed commonly available branded cans * Matched case consistency used elsewhere. Minor SPAG corrections. * Added "nothing" and some missing alcohol bottles to RandomSpawner * Added distinct ad and bye chatter to Dr. Gibb machines. * Revert "Added distinct ad and bye chatter to Dr. Gibb machines." This reverts commit f90b8a470556de05aca81255db8b6b03596ae944. * Revert "Removed commonly available branded cans" This reverts commit 43b82168dac1f73b187b7677f34ecdd33b6bb81a. * Revert "Switched generic sodas with brands for SodaInventory" This reverts commit f1790f0ce61ef135c79068de6a741e8bb50d85d3. * Lowercased DrinkGlass suffix. Moved alcoholic drinks from drinks to alcohol. * Renamed energy drink to Red Bool. Corrected and added some jug descriptions. * Added reagent names for all bottles except poison-wine * Revision of title case for cocktails * SPAG and fixed the only brand reagen with unbranded name. * Possibly controversial, shortened some bran names to better fit the UI. * Fixed some inconsistencies in naming * Matched brand localisation change * Two name style edits * Fixed Smite bottle name * Minor, punctuation * Blank line to end of file * Upgraded descriptive names to title case * Banana Mama * reverts change, moved to another PR to avoid conflict. * Removed caffeine reference. * Minor, corrected some more inconsistencies * Removed Bottle of Nothing from random spawner. * Automatic changelog update * Fix access configurator debug assert (#34330) * fix * greytide fix * fix admin log * Dirty * Renamed water melon juice to watermelon juice (#34341) * Fix battery charging stopping just short of being full (#34028) * Add copy threshold button to air alarms (#34346) * Automatic changelog update * Oasis updoot the dimmining (#34347) updooty * Fland Station - Dirt Fix (#34352) Fland * Omega Station - Dirt Fix (#34353) omega * Marathon Station - Dirt Fix (#34354) * Marathon * Rerunning tests * Cog Station - Dirt Fix (#34355) Cog * Box Station - Dirt Fix (#34356) Box * Bagel Station - Dirt Fix (#34357) Bagel * Packed Station - Dirt Fix (#34351) * packed * Rerunning tests * Replace some sound PlayEntity with PlayPvs (#34317) * Fixed Forensic Gloves to be Security Contraband (#34193) * added BaseRestrictedContraband to forensic gloves * moved from id to parent * Automatic changelog update * add large instruments to the cargo request computer (#34240) * added the church organ to the cargo console (will add more in this PR, assuming i did this right (HOW DO YOU BUY CARGO ORDERS IN DEV ENVIROMENT???? *sobs)) * added other structure instruments to cargo Catalog * fixed an epic copy/paste fail * changed prices * fixed epic copy/paste fail #2 --------- Co-authored-by: TeenSarlacc <baddiepro123@gmail.com> * Automatic changelog update * Fix crayon losing durability on stamped paper (#34202) * Automatic changelog update * Adds a border to Oppenhopper poster (#34219) * border * Update meta.json * Update Resources/Textures/Structures/Wallmounts/posters.rsi/meta.json --------- Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Trim trailing newlines from examine messages (#33381) * Trim trailing newlines from examine messages * TrimTrailingNewlines -> TrimEnd * Add a popup message when ghost Boo action does nothing (#34369) * fix ghost_component.ftl locale grammar (#34372) fix ghost component locale grammar * Let ghosts sometimes make certain devices say creepy things (#34368) * Add SpookySpeaker component/system * Shuffle Boo action targets before trying to activate them * Add SpookySpeaker to vending machines * Fix chatcode eating messages starting with "..." * Add SpookySpeaker to recycler * Oops * Decrease speak probability for vending machines * Add spooky speaker to arcade machines * Automatic changelog update * Add directional escape pod sign (#34367) * Make indestructible tiles not breakable by explosions (#34339) * No more Ai Spacing * Move guard into earlier guard statement * Automatic changelog update * Arachnid stomach organ yaml fix (#34298) Arachnid stomach yaml fix Arachnids had their stomach `updateInterval` set to 1.5, 50% slower than normal. But this doesn't actually slow down the speed that the stomach digests things, only the rate at which it updates to check if enough time has passed. (See https://github.com/space-wizards/space-station-14/blob/23f0b304f284d2600cb2c6b4c9d36fdca7f99ec4/Content.Server/Body/Systems/StomachSystem.cs#L57 ) This PR changes arachnid stomachs to have a `digestionDelay` of 30 (20 is default) to achive the desired effect. Stasis beds are also bugged in a similar manner. They are intended to slow down the digestion speed, but similarly all they do is change the update rate. But fixing that requires actual code changes and is out of scope for this commit. * Automatic changelog update * Bended radiator (#34251) * Automatic changelog update * Remove Entity<T> data-fields (#34083) * Update submodule, .NET 9 (#34320) * Role Types (#33420) * mindcomponent namespace * wip MindRole stuff * admin player tab * mindroletype comment * mindRolePrototype redesign * broken param * wip RoleType implementation * basic role type switching for antags * traitor fix * fix AdminPanel update * the renameningTM * cleanup * feature uncreeping * roletypes on mind roles * update MindComponent.RoleType when MindRoles change * ghostrole configuration * ghostrole config improvements * live update of roleType on the character window * logging stuff and notes * remove thing no one asked for * weh * Mind Role Entities wip * headrev count fix * silicon stuff, cleanup * exclusive antag config, cleanup * jobroleadd overwerite * logging stuff * MindHasRole cleanup, admin log stuff * last second cleanup * ocd * move roletypeprototype to its own file, minor note stuff * remove Roletype.Created * log stuff * roletype setup for ghostroles and autotraitor reinforcements * ghostrole type configs * adjustable admin overlay * cleanup * fix this in its own PR * silicon antagonist * borg stuff * mmi roletype handling * spawnable borg roletype handling * weh * ghost role cleanup * weh * RoleEvent update * polish * log stuff * admin overlay config * ghostrolecomponent cleanup * weh * admin overlay code cleanup * minor cleanup * Obsolete MindRoleAddedEvent * comment * minor code cleanup * MindOnDoGreeting fix * Role update message * fix duplicate job greeting for cyborgs * fix emag job message dupe * nicer-looking role type update * crew aligned * syndicate assault borg role fix * fix test fail * fix a merge mistake * fix LoneOp role type * Update Content.Client/Administration/AdminNameOverlay.cs Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Update Content.Shared/Roles/SharedRoleSystem.cs Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * comment formatting Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * change logging category Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * fix a space Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * use MindAddRoles Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * get MindComponent from TryGetMind Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * move var declaration outside loop * remove TryComp * take RoleEnum behind the barn * don't use ensurecomp unnecessarily * cvar comments * toggleableghostrolecomponent documentation * skrek * use EntProtoId * mindrole config * merge baserolecomponent into basemindrolecomponent * ai and borg silicon role tweaks * formatting Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * I will end you (the color) Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * use LocId type for a locale id * update RoleEvent documentation * update RoleEvent documentation * remove obsolete MindRoleAddedEvent * refine MindRolesUpdate() * use dependency Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * inject dependency Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * roleType.Name no longer required * reformatted draw code logic * GhostRoleMarkerRoleComponent comment * minor SharedRoleSystem cleanup * StartingMindRoleComponent, unhardcode roundstart silicon * Update Content.Shared/Roles/SharedRoleSystem.cs * remove a whitespace --------- Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Automatic changelog update * Update Credits (#34389) Co-authored-by: PJBot <pieterjan.briers+bot@gmail.com> * Elkridge Depot Improvements (#34377) * updates decals * more decal work, more dinginess in certain areas * added decals under doors * Fix force-feeding Loc strings not using target's gender (#34276) * HOTFIX Tweaked air alarm default settings for nitrogen breathing crew (#34198) air alarm default settings modified for anaerobic crew * #33571 Bomb defusal lockers always should have tools (#34394) * Automatic changelog update * [HOTFIX] fix holopads with multiple ai cores dying (#34289) change return to continue Co-authored-by: deltanedas <@deltanedas:kde.org> * Reduce Panic Bunker Minimum Playtime to 2 hours (#34401) * Add IPIntel API support. (#33339) Co-authored-by: PJB3005 <pieterjan.briers+git@gmail.com> * Automatic changelog update * Fland Reporters Room (#34408) changed the command checkpoint to a reporters room. * Automatic changelog update * Add a high-capacity water tank to the janitor's closet of Oasis (#34366) added high capacity water tank * Darkened Service job interface icons for better contrast (#34270) * Darkened Service job interface icons for better contrast * Fixed Botanist job interface icon dark handle hole * Change to new, darker, service color in all resource yml files * Revert Map file service color changes * Use new darker service color on id cards * Revert Service color change in mapping_actions.yml * Revert salvage difficulties service color * Redo service ID and job colors to match advanced palette * Revert all service color yml file changes * Switch icons to use existing service pallete colors from advanced pallete * Update meta.json for darkened service icons --------- Co-authored-by: Erskin Cherry <frobnic8@gmail.com> * Amber Station - Moved Vents Around (#34410) * Moved all vents around, made some small changes * Finished work * Removed insuls spawner since they're not merged yet * Insuls Spawner (#34407) * Added insuls spawner, time to test * adjusted whitespace since that was causing issues * Update Resources/Prototypes/Entities/Markers/Spawners/Random/maintenance.yml Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> --------- Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Manual Valves Resprite (#34378) * resprited manual valves to be colourblind friendly * Update Resources/Textures/Structures/Piping/Atmospherics/pump.rsi/meta.json Co-authored-by: Errant <35878406+Errant-4@users.noreply.github.com> --------- Co-authored-by: Errant <35878406+Errant-4@users.noreply.github.com> * Automatic changelog update * loop station door access fixes and air sink (#34414) small fixes * Raise syndicate kobold reinforcement HP crit threshold from 75 to 100 to match monkey. (#34409) kobold ops have 100 health * Anomaly dragging exploit fix and QOL changes (#34280) * Wood wall is now built from barricade congraph and on top of a barricade instead of using rods * APE dragging exploit fix * Fixed doors being blocked with mousetraps, and other Collidable items (#34045) * Changed SharedDoorSystem.GetColliding() to allow non-LowImpassible mask entities to stay in the door while it closes * Update Content.Shared/Doors/Systems/SharedDoorSystem.cs Clarifies comment of how the mask is used Co-authored-by: Centronias <charlie.t.santos@gmail.com> --------- Co-authored-by: Centronias <charlie.t.santos@gmail.com> * Fixed Jazz Instrument for Electric Guitars (#33363) * fixed jazz midi program byte * swapped around jazz and clean in instrumentList * Automatic changelog update * Porting Pride-O-Mat to Upstream (#34412) * Pride-O-Mat (#1322) * Added Pride-O-Mat * Yep * Updated license to the correct one * Added more lines, reconfigured settings a bit, also added cloaks to inventory, set coder socks to emag inventory * Removed bunny ears, fixed typo * Made requested changes Webedit lmao --------- Co-authored-by: Dorragon <101672978+Dorragon@users.noreply.github.com> * Automatic changelog update * Oasis Power Rebalance + Misc fixes (#34425) * balance oasis power as a stopgap * change waste color to proper waste color * Fix IPIntel causing frequent errors with the cleanup job. (#34428) Co-authored-by: Pieter-Jan Briers <pieterjan.briers@gmail.com> * craftable pet carrier (#34431) * craftable pet carrier * epic integration test fail * Update Resources/Prototypes/Recipes/Crafting/improvised.yml Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Update Resources/Prototypes/Recipes/Crafting/Graphs/storage/pet_carrier.yml Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Update Resources/Prototypes/Recipes/Crafting/Graphs/storage/pet_carrier.yml Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Update Resources/Prototypes/Entities/Objects/Misc/pet_carrier.yml Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * extra tab begone * epic linter fail * how did linter not see this??? --------- Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Automatic changelog update * Adds omnisexual pin (#34439) * Make important change (#7) This is to help julian test his bot * Omnibus * Remove random test file from testing a gh bot * Add pin to vendor, spawners and loadout --------- Co-authored-by: nikthechampiongr <32041239+nikthechampiongr@users.noreply.github.com> * Fix bad Rider analysis error in AccessOverriderWindow.xaml.cs (#34213) * Disable meta-atlas for big rare RSIs (#33643) * Persist deadmin to database, add admin suspension system (#34048) * Automatic changelog update * STAThread client content start (#34212) * Minor client packaging changes (#33787) * Fix muzzle accent (#34419) * Automatic changelog update * Add Discord webhook on watchlist connection (#33483) * Automatic changelog update * Fixed Thief starting gear failing on specific bag inventories. (#34430) Fixed it yayyy * Added missing details from worn capes to head of department beadsheets (#34396) * Added key and missing details from worn cape to HOP bedsheet * Corrected canvas size for sprite * Subtle tweak to shading to reduce color blurring at pillow edge * Matched Hue and tone to cape * Tweak chekered pattern marks for gold trim * Removed accidental palette inclusion * Clearer wording and corrected attribution name. * Tweaked shading on key image to fit in better with bed aesthetics * Added CE cape icon to bedsheet * Added cape image to HOP bedsheet. Made gold trim better match cape visuals * RD cape icon added. Colour tweaked to better match cape. * Updates json * Tweaks to gold trim shading to match bed aesthetics * Added better shading for HOP sheet side. Halved file size. * Optimised HOS RD and CE sheet sprites * Corrected sprite title in attribution * Replace ERT Medic's Advanced Medkits with 2 Combat Medkits (#34380) Replaced Adv kits with 2 combat kits * Fix nonsensical RegEx for name restriction (#34375) * Fixed nonsense RegEx "-" character is a range, caused an error. No need for "," to repeat so much, it's not a separator. "\\" - just why? * Further optimized RegEx structure Added: "@" delimiter for consistency "/" to escape "-" for good and to avoid further problems * Remove the ability to print the station anchor circuit board (#34358) remove the ability to print the station anchor circuit board * Automatic changelog update * Meta hotfix (#34306) * Fixed major issues with power, cargo shuttle docking, etc. * remove serialized invalids * Finished fixing the critical issues, ready for merge? * Empty commit * Added new break room to sci (they deserve it) * Fixed up other minor issues * if this map isnt PERFECT Emisse has permission to gib me and turn me into a cyborg * added Roomba's changes --------- Co-authored-by: ArtisticRoomba <145879011+ArtisticRoomba@users.noreply.github.com> * Make Mime PDA interactions silent (#34426) * make insert and eject datafields in ItemSlotsComponent.cs nullable, make mime PDA silent * make it so that you can't fit wirecutters into the slots, among other various things * Automatic changelog update * Smite vending machine (#34420) * Added smite machine to YAML * Added smite ads and inventory * Added smite vendor sprites * Changed the description of the machine to not repeat and ad line. * Added newline to end of inventory .yml * Corrected erroneous edit. * Tweaked all sprites * Added tesla toy to contraband. Reduced number of drinks available * Reduced soda varieties but increased can numbers. * Removed tesla toy from contraband inventory * Removed speech component from vending machines that already inherit it * Moved Sprite component to top of list * Added Smite vendors to random spanwers * Alphabetised spawn prototypes, commented where name is unclear * Automatic changelog update * Printable bedsheets (#34034) * Bedsheets * that one fixes yellow bedsheet and delete american bedsheet * Automatic changelog update * Update RT to v239.0.1 (#34454) * Remove christmas anomaly spawn (#34053) Update anomaly.yml * Automatic changelog update * Remove baby jail (#34443) * Remove baby jail Closes #33893 * Test fail fix. * Add a CCVar to allow from hiding admins in the reported player count. (#34406) Good for: - Keeping admins hidden - Not confuse players seeing 84/80 players Nicely pairs up with the ``admin.admins_count_for_max_players`` ccvar * Automatic changelog update * Fix Mixed puddles not updating slips when evap (#34303) * Fix Mixed puddles not updating slips when evap * Remove Comment that isn't needed Co-authored-by: Centronias <charlie.t.santos@gmail.com> * CR - use SolutionContainerSystem.UpdateChemicals * CR - cleanup unused imports --------- Co-authored-by: Centronias <charlie.t.santos@gmail.com> * Automatic changelog update * WizDen config update for IPIntel (#34457) * Fix DNA scrambler updating station record (#34091) * Fix DNA scrambler updating station record * Update Content.Server/Implants/SubdermalImplantSystem.cs --------- Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Automatic changelog update * New and Modified Map Spawners (#34424) * Added spanwers and modified others * adjusted values to be more in line with what I want * this comment may have caused that test fail * oh my god another typo * Modified door crate to be engineering flavored * reduced the pride vendor odds Webedit lmao * Elkridge Depot Fixes Again (#34461) fixes evac shuttle, fix north solars, fix vents and scrubbers * Space Ruins Variant (#34445) * Space Ruins Variant * Updated File * Added Goliaths/Removed some mobs * Plasma Station (#33991) * Plasma Station initial commit * Map fixes 1 Expanded science's SMES array Added advanced SMES Redone stamped documents with custom stamps Expanded atmospherics with more storage tanks Added status displays Add missing beacons to solars Replaced the passive gates in science with valves Removed protolathe in engineering Added guitar to CE office Replaced throngler plushie with weh cloak Add a lattice tile outside the atmos burn chamber and storange tanks Added atmos network monitor in bridge * Add cargo and emergency shuttle * Updated maps * Add plasma to map testing list * Map fixes 2 Reworked pipenets to not go under walls Redid salvage and disposals Reworked the bar to include a new bar extension facing the pool Replaced arrivals cryo with an arcade Replaced the toilets in the service plaza with cryo Removed the cryo in dorms Added more details to hallways Redid tools room to include a front desk for the janitor closet Reconnected sci to power roundstart Removed some unideal spawns Expanded the TEG airlock to be 2x3 instead of 1x3 Reduced the size of the SMES bank from 10 to 6 Disabled the plasma miners (downstreams or admins can re-enable them) Replaced illegal maint items * Fixes a 6 pack destroying the universe Ok maybe cracking a cold one with the boys wasn't a great idea. * Map fixes 3 * Quick research assistant fix * Map fixes 4 * Map fixes 5 * webedit go brrrt * Map fixes 6 * Map fixes 7 * Map fixes 8 * Fixes non-existent object It's amazing this game runs at all * Map fixes 9 * update pools * Map fixes 10 * forgot to clear my multitool I love mapping I love mapping I love mapping I love mapping I love mapping --------- Co-authored-by: Emisse <99158783+Emisse@users.noreply.github.com> * Automatic changelog update * Plasma station population tweak (#34462) * Plasma Station initial commit * Map fixes 1 Expanded science's SMES array Added advanced SMES Redone stamped documents with custom stamps Expanded atmospherics with more storage tanks Added status displays Add missing beacons to solars Replaced the passive gates in science with valves Removed protolathe in engineering Added guitar to CE office Replaced throngler plushie with weh cloak Add a lattice tile outside the atmos burn chamber and storange tanks Added atmos network monitor in bridge * Add cargo and emergency shuttle * Updated maps * Add plasma to map testing list * Map fixes 2 Reworked pipenets to not go under walls Redid salvage and disposals Reworked the bar to include a new bar extension facing the pool Replaced arrivals cryo with an arcade Replaced the toilets in the service plaza with cryo Removed the cryo in dorms Added more details to hallways Redid tools room to include a front desk for the janitor closet Reconnected sci to power roundstart Removed some unideal spawns Expanded the TEG airlock to be 2x3 instead of 1x3 Reduced the size of the SMES bank from 10 to 6 Disabled the plasma miners (downstreams or admins can re-enable them) Replaced illegal maint items * Fixes a 6 pack destroying the universe Ok maybe cracking a cold one with the boys wasn't a great idea. * Map fixes 3 * Quick research assistant fix * Map fixes 4 * Map fixes 5 * webedit go brrrt * Map fixes 6 * Map fixes 7 * Map fixes 8 * Fixes non-existent object It's amazing this game runs at all * Map fixes 9 * update pools * Map fixes 10 * forgot to clear my multitool I love mapping I love mapping I love mapping I love mapping I love mapping * Tweaked player counts --------- Co-authored-by: Emisse <99158783+Emisse@users.noreply.github.com> * Automatic changelog update * Fix inconsistent borg flashlight state (#33027) * Fix borg light being stuck on if no cell is inserted * Fix HandheldLightComponent.Activted becoming out of sync with SharedPointLightComponent.Enabled * Fix for entities which don't have a handheld light component * FIX: Uranium, Cak, and BreadDog are not garbage! (#34192) * FIX: Uranium, Cak, and BreadDog are not garbage! * Fixed bread typo for spacegarbage change. * Style: moved ediblebase * Update Resources/Prototypes/Entities/Objects/Consumable/Food/Baked/bread.yml * Update Resources/Prototypes/Entities/Objects/Consumable/Food/Baked/cake.yml --------- Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Automatic changelog update * Fix the HoS mantle metashield break (#33831) Changes 'nukies' to 'syndicate agents' in the HoS mantle's description. * fix for climbable pianos (#33690) fix for climable pianos Co-authored-by: aa5g21 <aa5g21@soton.ac.uk> * Automatic changelog update * BorgChassis transfer their mind to a dropped BorgBrain fix (#34464) Fix * Staging: Add taped logo back for 10th anniversary (#34486) * Update engine to v240.0.1 (#34497) * mind roles * partial ritual serialization fix * Update CP14RoundEndSystem.cs * delete worldEdge system * Delete StencilOverlay.WorldEdge.cs * Update CP14MagicEffectComponent.cs * delete rituals system * fix demiplane serialization * mapdamage fix serialization * common objectives fix * remove failed personal goals endscreen * fix special selling, fix serialization * more fixes * more fixes x2 * final bruh * fix --------- Co-authored-by: Southbridge <7013162+southbridge-fur@users.noreply.github.com> Co-authored-by: TytosB <54259736+TytosB@users.noreply.github.com> Co-authored-by: Emisse <99158783+Emisse@users.noreply.github.com> Co-authored-by: Booblesnoot42 <108703193+Booblesnoot42@users.noreply.github.com> Co-authored-by: Spessmann <156740760+Spessmann@users.noreply.github.com> Co-authored-by: ~DreamlyJack~ <148849095+DreamlyJack@users.noreply.github.com> Co-authored-by: PJBot <pieterjan.briers+bot@gmail.com> Co-authored-by: chromiumboy <50505512+chromiumboy@users.noreply.github.com> Co-authored-by: PopGamer46 <yt1popgamer@gmail.com> Co-authored-by: crazybrain23 <44417085+crazybrain23@users.noreply.github.com> Co-authored-by: amatwiedle <amatwiedle@gmail.com> Co-authored-by: justdie12 <125140938+justdie12@users.noreply.github.com> Co-authored-by: Nox <nebulousnox38@gmail.com> Co-authored-by: ArtisticRoomba <145879011+ArtisticRoomba@users.noreply.github.com> Co-authored-by: lzk <124214523+lzk228@users.noreply.github.com> Co-authored-by: ReeZer2 <63300653+ReeZer2@users.noreply.github.com> Co-authored-by: Errant <35878406+Errant-4@users.noreply.github.com> Co-authored-by: Alpaccalypse <21291379+Alpaccalypse@users.noreply.github.com> Co-authored-by: Spanky <scott@wearejacob.com> Co-authored-by: Thomas <87614336+Aeshus@users.noreply.github.com> Co-authored-by: Dylan Hunter Whittingham <45404433+DylanWhittingham@users.noreply.github.com> Co-authored-by: dylanhunter <dylan2.whittingham@live.uwe.ac.uk> Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> Co-authored-by: Ps3Moira <113228053+ps3moira@users.noreply.github.com> Co-authored-by: SlamBamActionman <83650252+SlamBamActionman@users.noreply.github.com> Co-authored-by: Hannah Giovanna Dawson <karakkaraz@gmail.com> Co-authored-by: Ubaser <134914314+UbaserB@users.noreply.github.com> Co-authored-by: Deerstop <edainturner@gmail.com> Co-authored-by: themias <89101928+themias@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com> Co-authored-by: Centronias <charlie.t.santos@gmail.com> Co-authored-by: ScarKy0 <106310278+ScarKy0@users.noreply.github.com> Co-authored-by: SpaceRox1244 <138547931+SpaceRox1244@users.noreply.github.com> Co-authored-by: IProduceWidgets <107586145+IProduceWidgets@users.noreply.github.com> Co-authored-by: nikthechampiongr <32041239+nikthechampiongr@users.noreply.github.com> Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com> Co-authored-by: Tayrtahn <tayrtahn@gmail.com> Co-authored-by: Pancake <Pangogie@users.noreply.github.com> Co-authored-by: Piras314 <p1r4s@proton.me> Co-authored-by: flymo5678 <86871317+flymo5678@users.noreply.github.com> Co-authored-by: c4llv07e <igor@c4llv07e.xyz> Co-authored-by: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com> Co-authored-by: Coolsurf6 <coolsurf24@yahoo.com.au> Co-authored-by: TeenSarlacc <46608342+TeenSarlacc@users.noreply.github.com> Co-authored-by: TeenSarlacc <baddiepro123@gmail.com> Co-authored-by: SpaceManiac <tad@platymuus.com> Co-authored-by: War Pigeon <54217755+minus1over12@users.noreply.github.com> Co-authored-by: Zachary Higgs <compgeek223@gmail.com> Co-authored-by: 0x6273 <0x40@keemail.me> Co-authored-by: Floxington <florian.decker@mailbox.org> Co-authored-by: Myra <vasilis@pikachu.systems> Co-authored-by: SlimSlam <73899110+Stewie523@users.noreply.github.com> Co-authored-by: frobnic8 <erskin@eldritch.org> Co-authored-by: Erskin Cherry <frobnic8@gmail.com> Co-authored-by: hyperDelegate <zachary1064@gmail.com> Co-authored-by: JustinWinningham <justinmwinningham@gmail.com> Co-authored-by: zHonys <69396539+zHonys@users.noreply.github.com> Co-authored-by: Dorragon <101672978+Dorragon@users.noreply.github.com> Co-authored-by: Pieter-Jan Briers <pieterjan.briers@gmail.com> Co-authored-by: Killerqu00 <47712032+Killerqu00@users.noreply.github.com> Co-authored-by: Julian Giebel <juliangiebel@live.de> Co-authored-by: Palladinium <patrick.chieppe@hotmail.com> Co-authored-by: Alpha-Two <92269094+Alpha-Two@users.noreply.github.com> Co-authored-by: Hyper B <137433177+HyperB1@users.noreply.github.com> Co-authored-by: kosticia <kosticia46@gmail.com> Co-authored-by: compilatron <40789662+jbox144@users.noreply.github.com> Co-authored-by: eoineoineoin <github@eoinrul.es> Co-authored-by: Patrik Caes-Sayrs <heartofgoldfish@gmail.com> Co-authored-by: ApolloVector <149586366+ApolloVector@users.noreply.github.com> Co-authored-by: Gansu <68031780+GansuLalan@users.noreply.github.com> Co-authored-by: aa5g21 <aa5g21@soton.ac.uk>
2025-01-21 23:57:12 +03:00
# region IPIntel
public async Task<bool> UpsertIPIntelCache(DateTime time, IPAddress ip, float score)
{
while (true)
{
try
{
await using var db = await GetDb();
var existing = await db.DbContext.IPIntelCache
.Where(w => ip.Equals(w.Address))
.SingleOrDefaultAsync();
if (existing == null)
{
var newCache = new IPIntelCache
{
Time = time,
Address = ip,
Score = score,
};
db.DbContext.IPIntelCache.Add(newCache);
}
else
{
existing.Time = time;
existing.Score = score;
}
await Task.Delay(5000);
await db.DbContext.SaveChangesAsync();
return true;
}
catch (DbUpdateException)
{
_opsLog.Warning("IPIntel UPSERT failed with a db exception... retrying.");
}
}
}
public async Task<IPIntelCache?> GetIPIntelCache(IPAddress ip)
{
await using var db = await GetDb();
return await db.DbContext.IPIntelCache
.SingleOrDefaultAsync(w => ip.Equals(w.Address));
}
public async Task<bool> CleanIPIntelCache(TimeSpan range)
{
await using var db = await GetDb();
// Calculating this here cause otherwise sqlite whines.
var cutoffTime = DateTime.UtcNow.Subtract(range);
await db.DbContext.IPIntelCache
.Where(w => w.Time <= cutoffTime)
.ExecuteDeleteAsync();
await db.DbContext.SaveChangesAsync();
return true;
}
#endregion
// SQLite returns DateTime as Kind=Unspecified, Npgsql actually knows for sure it's Kind=Utc.
// Normalize DateTimes here so they're always Utc. Thanks.
protected abstract DateTime NormalizeDatabaseTime(DateTime time);
[return: NotNullIfNotNull(nameof(time))]
protected DateTime? NormalizeDatabaseTime(DateTime? time)
{
return time != null ? NormalizeDatabaseTime(time.Value) : time;
}
public async Task<bool> HasPendingModelChanges()
{
await using var db = await GetDb();
return db.DbContext.Database.HasPendingModelChanges();
}
protected abstract Task<DbGuard> GetDb(
CancellationToken cancel = default,
[CallerMemberName] string? name = null);
2023-12-10 16:30:12 +01:00
protected void LogDbOp(string? name)
{
_opsLog.Verbose($"Running DB operation: {name ?? "unknown"}");
}
protected abstract class DbGuard : IAsyncDisposable
{
public abstract ServerDbContext DbContext { get; }
public abstract ValueTask DisposeAsync();
}
Kick on ban for entire server group (#28649) * Start work on PostgresNotificationManager Implement initial version of init and listening code * Finish implementing PostgresNotificationManager Implement ban insert trigger * Implement ignoring notifications if the ban was from the same server * Address reviews * Fixes and refactorings Fix typo in migration SQL Pull new code in BanManager out into its own partial file. Unify logic to kick somebody with that when a new ban is placed directly on the server. New bans are now checked against all parameters (IP, HWID) instead of just user ID. Extracted SQLite ban matching code into a new class so that it can mostly be re-used by the ban notification code. No copy-paste here. Database notifications are now not implicitly sent to the main thread, this means basic checks will happen in the thread pool beforehand. Bans without user ID are now sent to servers. Bans are rate limited to avoid undue work from mass ban imports, beyond the rate limit they are dropped. Improved error handling and logging for the whole system. Matching bans against connected players requires knowing their ban exemption flags. These are now cached when the player connects. ServerBanDef now has exemption flags, again to allow matching full ban details for ban notifications. Made database notifications a proper struct type to reduce copy pasting a tuple. Remove copy pasted connection string building code by just... passing the string into the constructor. Add lock around _notificationHandlers just in case. Fixed postgres connection wait not being called in a loop and therefore spamming LISTEN commands for every received notification. Added more error handling and logging to notification listener. Removed some copy pasting from SQLite database layer too while I was at it because god forbid we expect anybody else to do all the work in this project. Sorry Julian --------- Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com>
2024-08-20 23:31:33 +02:00
protected void NotificationReceived(DatabaseNotification notification)
{
OnNotificationReceived?.Invoke(notification);
}
public virtual void Shutdown()
{
}
}
}