Gulag v2 (#21)
* Components или чет типо того * Gulag System * Shared shit * Cvars * Ban manager update * Ghost roles shit * No ooc for gulaged * Connection manager update * Gulag proto shit * Merge conflict issue * Fixing shit * Фикс говняхи плюс QOL * Pendos loc * better loc * More qol * ctrl+s issue * No bwoink for banned * Ore shit * MAP!!!!!! --------- Co-authored-by: Mona Hmiza <you@example.com>
This commit is contained in:
@@ -4,6 +4,7 @@ using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server._Miracle.GulagSystem;
|
||||
using Content.Server.Chat.Managers;
|
||||
using Content.Server.Database;
|
||||
using Content.Server.GameTicking;
|
||||
@@ -47,6 +48,7 @@ public sealed class BanManager : IBanManager, IPostInjectInit
|
||||
public const string UnknownServer = "unknown";
|
||||
|
||||
private readonly Dictionary<NetUserId, HashSet<ServerRoleBanDef>> _cachedRoleBans = new();
|
||||
private readonly Dictionary<NetUserId, HashSet<ServerBanDef>> _cachedServerBans = new(); // Miracle edit
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
@@ -63,6 +65,7 @@ public sealed class BanManager : IBanManager, IPostInjectInit
|
||||
var netChannel = e.Session.Channel;
|
||||
ImmutableArray<byte>? hwId = netChannel.UserData.HWId.Length == 0 ? null : netChannel.UserData.HWId;
|
||||
await CacheDbRoleBans(e.Session.UserId, netChannel.RemoteEndPoint.Address, hwId);
|
||||
await CacheDbServerBans(e.Session.UserId, netChannel.RemoteEndPoint.Address, hwId); //Miracle edit
|
||||
|
||||
SendRoleBans(e.Session);
|
||||
}
|
||||
@@ -97,6 +100,17 @@ public sealed class BanManager : IBanManager, IPostInjectInit
|
||||
_cachedRoleBans[userId] = userRoleBans;
|
||||
}
|
||||
|
||||
//Miracle edit start
|
||||
private async Task CacheDbServerBans(NetUserId userId, IPAddress? address = null, ImmutableArray<byte>? hwId = null)
|
||||
{
|
||||
var serverBans = await _db.GetServerBansAsync(address, userId, hwId, false);
|
||||
|
||||
var userServerBans = new HashSet<ServerBanDef>(serverBans);
|
||||
|
||||
_cachedServerBans[userId] = userServerBans;
|
||||
}
|
||||
//Miracle edit end
|
||||
|
||||
public void Restart()
|
||||
{
|
||||
// Clear out players that have disconnected.
|
||||
@@ -110,6 +124,7 @@ public sealed class BanManager : IBanManager, IPostInjectInit
|
||||
foreach (var player in toRemove)
|
||||
{
|
||||
_cachedRoleBans.Remove(player);
|
||||
_cachedServerBans.Remove(player); //Miracle edit
|
||||
}
|
||||
|
||||
// Check for expired bans
|
||||
@@ -117,6 +132,13 @@ public sealed class BanManager : IBanManager, IPostInjectInit
|
||||
{
|
||||
roleBans.RemoveWhere(ban => DateTimeOffset.Now > ban.ExpirationTime);
|
||||
}
|
||||
|
||||
//Miracle edit start
|
||||
foreach (var serverBan in _cachedServerBans.Values)
|
||||
{
|
||||
serverBan.RemoveWhere(ban => DateTimeOffset.Now > ban.ExpirationTime);
|
||||
}
|
||||
//Miracle edit end
|
||||
}
|
||||
|
||||
#region Server Bans
|
||||
@@ -182,6 +204,12 @@ public sealed class BanManager : IBanManager, IPostInjectInit
|
||||
_sawmill.Info(logMessage);
|
||||
_chat.SendAdminAlert(logMessage);
|
||||
|
||||
|
||||
if (banDef.UserId.HasValue)
|
||||
{
|
||||
_cachedServerBans.GetOrNew(banDef.UserId.Value).Add(banDef);
|
||||
}
|
||||
|
||||
// If we're not banning a player we don't care about disconnecting people
|
||||
if (target == null)
|
||||
return;
|
||||
@@ -189,12 +217,32 @@ public sealed class BanManager : IBanManager, IPostInjectInit
|
||||
// Is the player connected?
|
||||
if (!_playerManager.TryGetSessionById(target.Value, out var targetPlayer))
|
||||
return;
|
||||
// If they are, kick them
|
||||
var message = banDef.FormatBanMessage(_cfg, _localizationManager);
|
||||
targetPlayer.Channel.Disconnect(message);
|
||||
// Kick when perma
|
||||
if (banDef.ExpirationTime == null)
|
||||
{
|
||||
var message = banDef.FormatBanMessage(_cfg, _localizationManager);
|
||||
targetPlayer.Channel.Disconnect(message);
|
||||
}
|
||||
else // Teleport to gulag
|
||||
{
|
||||
var gulag = _systems.GetEntitySystem<GulagSystem>();
|
||||
gulag.SendToGulag(targetPlayer);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
//Miracle edit start
|
||||
public HashSet<ServerBanDef> GetServerBans(NetUserId userId)
|
||||
{
|
||||
if (_cachedServerBans.TryGetValue(userId, out var bans))
|
||||
{
|
||||
return bans;
|
||||
}
|
||||
|
||||
return new HashSet<ServerBanDef>();
|
||||
}
|
||||
//Miracle edit end
|
||||
|
||||
#region Job Bans
|
||||
// If you are trying to remove timeOfBan, please don't. It's there because the note system groups role bans by time, reason and banning admin.
|
||||
// Removing it will clutter the note list. Please also make sure that department bans are applied to roles with the same DateTimeOffset.
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.Collections.Immutable;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server._White.PandaSocket.Interfaces;
|
||||
using Content.Server.Database;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Roles;
|
||||
using Robust.Shared.Network;
|
||||
@@ -28,6 +29,8 @@ public interface IBanManager
|
||||
public HashSet<string>? GetRoleBans(NetUserId playerUserId);
|
||||
public HashSet<string>? GetJobBans(NetUserId playerUserId);
|
||||
|
||||
public HashSet<ServerBanDef> GetServerBans(NetUserId userId); // Miracle edit
|
||||
|
||||
/// <summary>
|
||||
/// Creates a job ban for the specified target, username or GUID
|
||||
/// </summary>
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Text.Json.Nodes;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server._Miracle.GulagSystem;
|
||||
using Content.Server.Administration.Managers;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server._White.PandaSocket.Main;
|
||||
@@ -35,6 +36,8 @@ namespace Content.Server.Administration.Systems
|
||||
[Dependency] private readonly GameTicker _gameTicker = default!;
|
||||
[Dependency] private readonly SharedMindSystem _minds = default!;
|
||||
[Dependency] private readonly PandaWebManager _pandaWeb = default!; // WD
|
||||
[Dependency] private readonly GulagSystem _gulagSystem = default!; // Miracle
|
||||
|
||||
|
||||
private ISawmill _sawmill = default!;
|
||||
private readonly HttpClient _httpClient = new();
|
||||
@@ -389,6 +392,12 @@ namespace Content.Server.Administration.Systems
|
||||
base.OnBwoinkTextMessage(message, eventArgs);
|
||||
var senderSession = eventArgs.SenderSession;
|
||||
|
||||
//No bwoink for banned
|
||||
if (_gulagSystem.IsUserGulaged(senderSession.UserId, out _))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Sanitize text?
|
||||
// Confirm that this person is actually allowed to send a message here.
|
||||
var personalChannel = senderSession.UserId == message.UserId;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Server._Miracle.GulagSystem;
|
||||
using Content.Server.Chat.Managers;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Shared.Console;
|
||||
@@ -19,6 +20,12 @@ namespace Content.Server.Chat.Commands
|
||||
return;
|
||||
}
|
||||
|
||||
var gulag = EntitySystem.Get<GulagSystem>();
|
||||
if (gulag.IsUserGulaged(shell.Player.UserId, out var _))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.Length < 1)
|
||||
return;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Database;
|
||||
using Content.Server.GameTicking;
|
||||
@@ -170,7 +171,7 @@ namespace Content.Server.Connection
|
||||
//WD-EDIT
|
||||
|
||||
var bans = await _db.GetServerBansAsync(addr, userId, hwId, includeUnbanned: false);
|
||||
if (bans.Count > 0)
|
||||
if (bans.Count > 0 && bans.Any(x=> x.ExpirationTime == null)) //Miracle edit
|
||||
{
|
||||
var firstBan = bans[0];
|
||||
var message = firstBan.FormatBanMessage(_cfg, _loc);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Server._Miracle.GulagSystem;
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.EUI;
|
||||
using Content.Server.Ghost.Roles.Components;
|
||||
@@ -37,6 +38,8 @@ namespace Content.Server.Ghost.Roles
|
||||
[Dependency] private readonly TransformSystem _transform = default!;
|
||||
[Dependency] private readonly SharedMindSystem _mindSystem = default!;
|
||||
[Dependency] private readonly SharedRoleSystem _roleSystem = default!;
|
||||
[Dependency] private readonly GulagSystem _gulagSystem = default!;
|
||||
|
||||
|
||||
private uint _nextRoleIdentifier;
|
||||
private bool _needsUpdateGhostRoleCount = true;
|
||||
@@ -201,6 +204,11 @@ namespace Content.Server.Ghost.Roles
|
||||
if (!_ghostRoles.TryGetValue(identifier, out var role))
|
||||
return;
|
||||
|
||||
if (_gulagSystem.IsUserGulaged(player.UserId, out _))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var ev = new TakeGhostRoleEvent(player);
|
||||
RaiseLocalEvent(role, ref ev);
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
using Content.Shared._Miracle.GulagSystem;
|
||||
|
||||
namespace Content.Server._Miracle.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
[Access(typeof(SharedGulagSystem))]
|
||||
public sealed partial class GulagBoundComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using Content.Shared._Miracle.GulagSystem;
|
||||
|
||||
namespace Content.Server._Miracle.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
[Access(typeof(SharedGulagSystem))]
|
||||
public sealed partial class GulagFillContainerComponent : Component
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using Content.Shared._Miracle.GulagSystem;
|
||||
using Robust.Shared.Network;
|
||||
|
||||
namespace Content.Server._Miracle.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
[Access(typeof(SharedGulagSystem))]
|
||||
|
||||
public sealed partial class GulagOreProcessorComponent : Component
|
||||
{
|
||||
//I hate my life
|
||||
public NetUserId? LastInteractedUser;
|
||||
}
|
||||
|
||||
462
Content.Server/_Miracle/GulagSystem/GulagSystem.cs
Normal file
462
Content.Server/_Miracle/GulagSystem/GulagSystem.cs
Normal file
@@ -0,0 +1,462 @@
|
||||
using System.Linq;
|
||||
using Content.Server._Miracle.Components;
|
||||
using Content.Server.Administration.Managers;
|
||||
using Content.Server.Administration.Systems;
|
||||
using Content.Server.Cargo.Components;
|
||||
using Content.Server.Cargo.Systems;
|
||||
using Content.Server.Chat.Managers;
|
||||
using Content.Server.Database;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.GameTicking.Events;
|
||||
using Content.Server.KillTracking;
|
||||
using Content.Server.Materials;
|
||||
using Content.Server.Mind;
|
||||
using Content.Server.Parallax;
|
||||
using Content.Server.Preferences.Managers;
|
||||
using Content.Server.Spawners.Components;
|
||||
using Content.Server.Station.Components;
|
||||
using Content.Server.Station.Systems;
|
||||
using Content.Server.Storage.EntitySystems;
|
||||
using Content.Shared._Miracle.Cvars;
|
||||
using Content.Shared._Miracle.GulagSystem;
|
||||
using Content.Shared.GameTicking;
|
||||
using Content.Shared.Hands.Components;
|
||||
using Content.Shared.Hands.EntitySystems;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Inventory;
|
||||
using Content.Shared.Materials;
|
||||
using Content.Shared.Parallax.Biomes;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Preferences;
|
||||
using Content.Shared.Throwing;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Physics.Systems;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server._Miracle.GulagSystem;
|
||||
|
||||
public sealed partial class GulagSystem : SharedGulagSystem
|
||||
{
|
||||
//1 second = 10 points
|
||||
[Dependency] private readonly AdminSystem _adminSystem = default!;
|
||||
[Dependency] private readonly IBanManager _banManager = default!;
|
||||
[Dependency] private readonly BiomeSystem _biome = default!;
|
||||
[Dependency] private readonly IServerDbManager _db = default!;
|
||||
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
|
||||
[Dependency] private readonly InventorySystem _inventorySystem = default!;
|
||||
[Dependency] private readonly MapLoaderSystem _mapLoader = default!;
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[Dependency] private readonly MetaDataSystem _metaData = default!;
|
||||
[Dependency] private readonly MindSystem _mind = default!;
|
||||
[Dependency] private readonly SharedPhysicsSystem _physicsSystem = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly StationSpawningSystem _spawningSystem = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
|
||||
[Dependency] private readonly CargoSystem _cargoSystem = default!;
|
||||
[Dependency] private readonly MaterialStorageSystem _materialStorageSystem = default!;
|
||||
[Dependency] private readonly EntityStorageSystem _entityStorageSystem = default!;
|
||||
[Dependency] private readonly GameTicker _gameTicker = default!;
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
[Dependency] private readonly IServerPreferencesManager _preferencesManager = default!;
|
||||
[Dependency] private readonly IChatManager _chatManager = default!;
|
||||
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
||||
[Dependency] private readonly StationSystem _stationSystem = default!;
|
||||
|
||||
|
||||
private readonly List<ProtoId<BiomeTemplatePrototype>> _gulagBiomes = new()
|
||||
{
|
||||
"GulagBiome"
|
||||
};
|
||||
|
||||
private readonly List<string> _gulagMaps = new()
|
||||
{
|
||||
"/Maps/Gulags/gulag.yml"
|
||||
};
|
||||
|
||||
private double _timeToPointsRatio;
|
||||
|
||||
private MapId? _activeMap;
|
||||
private EntityUid? _mapEntity;
|
||||
|
||||
private readonly TimeSpan _safeguardUpdateRate = TimeSpan.FromSeconds(10);
|
||||
private DateTime _nextSafeguardUpdate = DateTime.MinValue;
|
||||
|
||||
private readonly TimeSpan _shuttleFillUpdateRate = TimeSpan.FromMinutes(10);
|
||||
private DateTime _nextShuttleFillUpdate = DateTime.MinValue;
|
||||
|
||||
private List<EntityCoordinates> _spawnCoords = new();
|
||||
|
||||
private readonly Dictionary<NetUserId, double> _pointsPerPlayer = new();
|
||||
private readonly Dictionary<ProtoId<MaterialPrototype>, int> _gulagMaterialStorage = new();
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_cfg.OnValueChanged(MiracleCvars.GulagPointsToTimeRatio, newValue => _timeToPointsRatio = newValue, true);
|
||||
|
||||
SubscribeLocalEvent<RoundStartingEvent>(OnRoundStarting);
|
||||
SubscribeLocalEvent<RoundRestartCleanupEvent>(OnRoundRestart);
|
||||
|
||||
SubscribeLocalEvent<PlayerBeforeSpawnEvent>(BeforeSpawn);
|
||||
|
||||
SubscribeLocalEvent<GulagOreProcessorComponent, MaterialEntityInsertedEvent>(OnOreInserted);
|
||||
SubscribeLocalEvent<GulagOreProcessorComponent, InteractUsingEvent>(OnInteract, before: new[] {typeof(MaterialStorageSystem)});
|
||||
|
||||
SubscribeLocalEvent<GulagFillContainerComponent, MapInitEvent>(OnGulagContainerSpawned);
|
||||
SubscribeLocalEvent<KillReportedEvent>(OnKillReported);
|
||||
|
||||
SubscribeLocalEvent<PlayerJoinedLobbyEvent>(OnJoinedLobby);
|
||||
//safeguard
|
||||
SubscribeLocalEvent<PlayerAttachedEvent>(OnPlayerAttached);
|
||||
}
|
||||
|
||||
private void OnJoinedLobby(PlayerJoinedLobbyEvent ev)
|
||||
{
|
||||
if(IsUserGulaged(ev.PlayerSession.UserId, out _))
|
||||
{
|
||||
_chatManager.DispatchServerMessage(ev.PlayerSession, Loc.GetString("gulag-chat-join-message"));
|
||||
}
|
||||
}
|
||||
|
||||
private void OnKillReported(ref KillReportedEvent ev)
|
||||
{
|
||||
if (!HasComp<GulagBoundComponent>(ev.Entity))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (ev.Primary is not KillPlayerSource source)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var player = source.PlayerId;
|
||||
|
||||
if (!IsUserGulaged(player, out var ban))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var banDef = ban.First();
|
||||
var newExpirationTime = banDef.ExpirationTime!.Value.DateTime + TimeSpan.FromDays(1);
|
||||
_db.EditServerBan(banDef.Id!.Value, banDef.Reason, banDef.Severity, newExpirationTime, banDef.UserId!.Value, DateTime.Now);
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
Safeguard();
|
||||
TryFillCargoShuttle();
|
||||
}
|
||||
|
||||
private void OnGulagContainerSpawned(EntityUid uid, GulagFillContainerComponent component, MapInitEvent args)
|
||||
{
|
||||
var coords = Transform(uid).Coordinates;
|
||||
|
||||
foreach (var (materialId, value) in _gulagMaterialStorage)
|
||||
{
|
||||
var materialEntities = _materialStorageSystem.SpawnMultipleFromMaterial(value, materialId, coords);
|
||||
|
||||
foreach (var material in materialEntities)
|
||||
{
|
||||
_entityStorageSystem.Insert(material, uid);
|
||||
}
|
||||
}
|
||||
|
||||
_gulagMaterialStorage.Clear();
|
||||
}
|
||||
|
||||
private void TryFillCargoShuttle()
|
||||
{
|
||||
if (_nextShuttleFillUpdate > DateTime.Now)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_gulagMaterialStorage.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var station = GetMainStation();
|
||||
|
||||
if (!station.HasValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TryComp<StationCargoOrderDatabaseComponent>(station.Value, out var comp))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_cargoSystem.AddAndApproveOrder(station.Value, "CrateGulag", 0, 1, Loc.GetString("gulag-sender"),
|
||||
Loc.GetString("gulag-order-description"), Loc.GetString("gulag-order-destination"), comp);
|
||||
|
||||
_nextShuttleFillUpdate = DateTime.Now + _shuttleFillUpdateRate;
|
||||
}
|
||||
|
||||
// Just check if we need to bring back somehow escaped players
|
||||
private void Safeguard()
|
||||
{
|
||||
if (_nextSafeguardUpdate > DateTime.Now)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var querry = EntityQueryEnumerator<GulagBoundComponent, TransformComponent>();
|
||||
|
||||
while (querry.MoveNext(out var uid, out var gulagbound, out var xform))
|
||||
{
|
||||
if (xform.MapID != _activeMap)
|
||||
{
|
||||
SendToGulag(uid);
|
||||
}
|
||||
}
|
||||
|
||||
_nextSafeguardUpdate = DateTime.Now + _safeguardUpdateRate;
|
||||
}
|
||||
|
||||
public void SendToGulag(ICommonSession session)
|
||||
{
|
||||
var playerEntity = session.AttachedEntity;
|
||||
|
||||
if (_mapEntity == null)
|
||||
{
|
||||
_adminSystem.Erase(session);
|
||||
return;
|
||||
}
|
||||
|
||||
if (playerEntity.HasValue)
|
||||
{
|
||||
SendToGulag(playerEntity.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
SpawnPlayer(session, (HumanoidCharacterProfile)_preferencesManager.GetPreferences(session.UserId).SelectedCharacter);
|
||||
}
|
||||
|
||||
var banDef = _banManager.GetServerBans(session.UserId).First();
|
||||
var message = Loc.GetString("gulag-greetings-message", ("BanTime", $"{(banDef.ExpirationTime! - DateTime.Now).Value.TotalHours}"));
|
||||
|
||||
_chatManager.DispatchServerMessage(session, message);
|
||||
}
|
||||
|
||||
private void OnInteract(EntityUid uid, GulagOreProcessorComponent component, InteractUsingEvent args)
|
||||
{
|
||||
//It wasn't player who interacted with the entity
|
||||
if (!_playerManager.TryGetSessionByEntity(args.User, out var session))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
component.LastInteractedUser = session.UserId;
|
||||
Log.Info("OnInteract raised");
|
||||
}
|
||||
|
||||
private void OnOreInserted(EntityUid uid, GulagOreProcessorComponent component, MaterialEntityInsertedEvent args)
|
||||
{
|
||||
var storageComponent = Comp<MaterialStorageComponent>(uid);
|
||||
var userId = component.LastInteractedUser!.Value;
|
||||
|
||||
foreach (var (materialId, currentVolume ) in storageComponent.Storage)
|
||||
{
|
||||
var materialPrototype = _prototypeManager.Index<MaterialPrototype>(materialId.Id);
|
||||
var stackVolume = _materialStorageSystem.GetSheetVolume(materialPrototype);
|
||||
var actualOreCount = currentVolume / stackVolume;
|
||||
|
||||
var points = materialPrototype.Price * actualOreCount;
|
||||
|
||||
_pointsPerPlayer[userId] = points + _pointsPerPlayer.GetValueOrDefault(userId);
|
||||
|
||||
_gulagMaterialStorage[materialId] = currentVolume + _gulagMaterialStorage.GetValueOrDefault(materialId);
|
||||
_materialStorageSystem.TrySetMaterialAmount(uid, materialId, 0);
|
||||
|
||||
}
|
||||
|
||||
var time = ConvertPointsToTime(_pointsPerPlayer[userId]);
|
||||
_popupSystem.PopupEntity(Loc.GetString("gulag-ban-time-changed", ("Time", $"{time.TotalSeconds}")), uid, PopupType.Medium);
|
||||
}
|
||||
|
||||
public bool IsUserGulaged(NetUserId playerId, out HashSet<ServerBanDef> bans)
|
||||
{
|
||||
bans = _banManager.GetServerBans(playerId);
|
||||
|
||||
return bans.Count != 0;
|
||||
}
|
||||
|
||||
private void SendToGulag(EntityUid playerEntity)
|
||||
{
|
||||
if (_inventorySystem.TryGetContainerSlotEnumerator(playerEntity, out var enumerator))
|
||||
{
|
||||
while (enumerator.NextItem(out var item, out var slot))
|
||||
{
|
||||
if (_inventorySystem.TryUnequip(playerEntity, playerEntity, slot.Name, true, true))
|
||||
_physicsSystem.ApplyAngularImpulse(item, ThrowingSystem.ThrowAngularImpulse);
|
||||
}
|
||||
}
|
||||
|
||||
if (TryComp(playerEntity, out HandsComponent? hands))
|
||||
{
|
||||
foreach (var hand in _handsSystem.EnumerateHands(playerEntity, hands))
|
||||
{
|
||||
_handsSystem.TryDrop(playerEntity, hand, checkActionBlocker: false, doDropInteraction: false,
|
||||
handsComp: hands);
|
||||
}
|
||||
}
|
||||
|
||||
var newPosition = GetSpawnPosition();
|
||||
|
||||
_transformSystem.SetCoordinates(playerEntity, newPosition);
|
||||
_transformSystem.AttachToGridOrMap(playerEntity);
|
||||
|
||||
EnsureComp<GulagBoundComponent>(playerEntity);
|
||||
EnsureComp<KillTrackerComponent>(playerEntity);
|
||||
}
|
||||
|
||||
private void SpawnPlayer(ICommonSession session, HumanoidCharacterProfile profile)
|
||||
{
|
||||
var newMind = _mind.CreateMind(session.UserId, profile.Name);
|
||||
_mind.SetUserId(newMind, session.UserId);
|
||||
|
||||
var coords = GetSpawnPosition();
|
||||
var mob = _spawningSystem.SpawnPlayerMob(coords, null, profile, null);
|
||||
|
||||
_mind.TransferTo(newMind, mob);
|
||||
|
||||
EnsureComp<GulagBoundComponent>(mob);
|
||||
EnsureComp<KillTrackerComponent>(mob);
|
||||
}
|
||||
|
||||
private void OnPlayerAttached(PlayerAttachedEvent ev)
|
||||
{
|
||||
var bans = _banManager.GetServerBans(ev.Player.UserId);
|
||||
|
||||
if (bans.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var xform = Transform(ev.Entity);
|
||||
|
||||
if (xform.MapID != _activeMap)
|
||||
{
|
||||
SendToGulag(ev.Player);
|
||||
}
|
||||
}
|
||||
|
||||
private void BeforeSpawn(PlayerBeforeSpawnEvent ev)
|
||||
{
|
||||
var bans = _banManager.GetServerBans(ev.Player.UserId);
|
||||
|
||||
if (bans.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ev.Handled = true;
|
||||
SendToGulag(ev.Player);
|
||||
}
|
||||
|
||||
private void OnRoundRestart(RoundRestartCleanupEvent ev)
|
||||
{
|
||||
foreach (var (player, points) in _pointsPerPlayer)
|
||||
{
|
||||
var banDef = _banManager.GetServerBans(player).FirstOrDefault();
|
||||
if (banDef == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var newExpirationTime = banDef.ExpirationTime!.Value.DateTime - ConvertPointsToTime(points);
|
||||
|
||||
_db.EditServerBan(banDef.Id!.Value, banDef.Reason, banDef.Severity, newExpirationTime, banDef.UserId!.Value, DateTime.Now);
|
||||
}
|
||||
|
||||
_activeMap = null!;
|
||||
_mapEntity = null!;
|
||||
}
|
||||
|
||||
private void OnRoundStarting(RoundStartingEvent ev)
|
||||
{
|
||||
//Spawn Gulag
|
||||
var mapId = _mapManager.CreateMap();
|
||||
var mapUid = _mapManager.GetMapEntityId(mapId);
|
||||
|
||||
_metaData.SetEntityName(mapUid, "Gulag Map");
|
||||
|
||||
_mapManager.AddUninitializedMap(mapId);
|
||||
|
||||
var pickedMap = _random.Pick(_gulagMaps);
|
||||
if (!_mapLoader.TryLoad(mapId, pickedMap, out var uids))
|
||||
{
|
||||
_mapManager.DeleteMap(mapId);
|
||||
Log.Error("Can't spawn map with path {0}", pickedMap);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var uid in uids)
|
||||
{
|
||||
_metaData.SetEntityName(uid, $"Gulag grid {uid}");
|
||||
}
|
||||
|
||||
var pickerBiome = _random.Pick(_gulagBiomes);
|
||||
_biome.EnsurePlanet(mapUid, _prototypeManager.Index<BiomeTemplatePrototype>(pickerBiome));
|
||||
|
||||
_mapManager.DoMapInitialize(mapId);
|
||||
_activeMap = mapId;
|
||||
_mapEntity = mapUid;
|
||||
|
||||
|
||||
//Item2 = TransformComponent
|
||||
_spawnCoords = EntityQuery<SpawnPointComponent, TransformComponent>()
|
||||
.Where(x => x.Item2.MapID == mapId)
|
||||
.Select(x => x.Item2.Coordinates)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private TimeSpan ConvertPointsToTime(double points)
|
||||
{
|
||||
return TimeSpan.FromSeconds(points / _timeToPointsRatio);
|
||||
}
|
||||
|
||||
private EntityCoordinates GetSpawnPosition()
|
||||
{
|
||||
return _spawnCoords.Count != 0 ? _random.Pick(_spawnCoords) : Transform(_mapEntity!.Value).Coordinates;
|
||||
}
|
||||
|
||||
private EntityUid? GetMainStation()
|
||||
{
|
||||
var stations = _stationSystem.GetStations();
|
||||
|
||||
foreach (var station in stations)
|
||||
{
|
||||
var stationData = Comp<StationDataComponent>(station);
|
||||
|
||||
if (!HasComp<StationCargoOrderDatabaseComponent>(station))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var grid in stationData.Grids)
|
||||
{
|
||||
if (Transform(grid).MapID == _gameTicker.DefaultMap)
|
||||
{
|
||||
return station;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null!;
|
||||
}
|
||||
}
|
||||
12
Content.Shared/_Miracle/Cvars/MiracleCvars.cs
Normal file
12
Content.Shared/_Miracle/Cvars/MiracleCvars.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using Robust.Shared.Configuration;
|
||||
|
||||
namespace Content.Shared._Miracle.Cvars;
|
||||
|
||||
[CVarDefs]
|
||||
public sealed class MiracleCvars
|
||||
{
|
||||
// <points> / <ratio> = <time_in_seconds>
|
||||
// 100 / 10 = 10
|
||||
public static readonly CVarDef<double> GulagPointsToTimeRatio = CVarDef.Create("miracle.gulag.points_to_time",
|
||||
10.0d, CVar.SERVERONLY, "<points> / <ratio> = <time_in_seconds>");
|
||||
}
|
||||
6
Content.Shared/_Miracle/GulagSystem/SharedGulagSystem.cs
Normal file
6
Content.Shared/_Miracle/GulagSystem/SharedGulagSystem.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace Content.Shared._Miracle.GulagSystem;
|
||||
|
||||
public abstract class SharedGulagSystem : EntitySystem
|
||||
{
|
||||
|
||||
}
|
||||
15
Resources/Locale/en-US/_miracle/gulag/gulag.ftl
Normal file
15
Resources/Locale/en-US/_miracle/gulag/gulag.ftl
Normal file
@@ -0,0 +1,15 @@
|
||||
ent-GulagOreProcessor = Ore Receiver.
|
||||
.desc = Load ore, reduce your sentence.
|
||||
|
||||
ent-CrateGulag = Ore Container.
|
||||
.desc = Ore straight from NanoTrasen's mining facility.
|
||||
|
||||
gulag-sender = NanoTrasen Mining Facility.
|
||||
gulag-order-description = With love from our miners.
|
||||
gulag-order-destination = Supply Department.
|
||||
|
||||
gulag-greetings-message = You have been sent to the correctional labor camp for violating local laws. You can shorten your sentence by mining ore and shipping it to the ore receiver. Remaining punishment time: { $BanTime } hours.
|
||||
gulag-ban-time-changed = Your sentence has been reduced by { $Time } seconds.
|
||||
|
||||
gulag-chat-join-message = Welcome to the server. Due to violations committed by you, it has been decided to give you the opportunity to redeem your guilt through hard labor. After the start of the game round, you will be sent to the correctional labor camp, where you will be tasked with mining ore to reduce the duration of your punishment. It is important to note that killing your fellow unfortunate will increase your sentence by 1 day. We wish you luck in serving your sentence!
|
||||
|
||||
14
Resources/Locale/ru-RU/_miracle/gulag/gulag.ftl
Normal file
14
Resources/Locale/ru-RU/_miracle/gulag/gulag.ftl
Normal file
@@ -0,0 +1,14 @@
|
||||
ent-GulagOreProcessor = Приемник руды с трудового лагеря.
|
||||
.desc = Загружаешь руду, сокращаешь срок.
|
||||
|
||||
ent-CrateGulag = Контейнер руды.
|
||||
.desc = Руда прямиком с горнодобывающего предприятия НаноТразена.
|
||||
|
||||
gulag-sender = Горнодобывающее предприятие НаноТразен.
|
||||
gulag-order-description = С любовью от наших горняков.
|
||||
gulag-order-destination = Отдел снабжения.
|
||||
|
||||
gulag-greetings-message = Вы были отправлены в исправительный лагерь за нарушение местных законов. Вы можете сократить свой срок добывая руду и отгружая её в приёмник руды. Оставшийся срок наказания { $BanTime } часов.
|
||||
gulag-ban-time-changed = Ваш срок был сокращен на { $Time } секунд.
|
||||
|
||||
gulag-chat-join-message = Добро пожаловать на сервер. В связи с нарушениями, совершенными вами, было принято решение предоставить вам возможность искупить свою вину через тяжелый труд. После начала игрового раунда вы будете отправлены в исправительный лагерь, где вам предстоит добывать руду, чтобы сократить срок своего наказания. Важно отметить, что за убийство своего собрата по несчастью ваш срок будет увеличен на 1 день. Желаем вам удачи в исполнении наказания!
|
||||
5079
Resources/Maps/Gulags/gulag.yml
Normal file
5079
Resources/Maps/Gulags/gulag.yml
Normal file
File diff suppressed because it is too large
Load Diff
83
Resources/Prototypes/_Miracle/Biomes/gulag_biomes.yml
Normal file
83
Resources/Prototypes/_Miracle/Biomes/gulag_biomes.yml
Normal file
@@ -0,0 +1,83 @@
|
||||
# Caves
|
||||
- type: biomeTemplate
|
||||
id: GulagBiome
|
||||
layers:
|
||||
- !type:BiomeEntityLayer
|
||||
threshold: 0.85
|
||||
noise:
|
||||
seed: 2
|
||||
noiseType: OpenSimplex2
|
||||
fractalType: PingPong
|
||||
allowedTiles:
|
||||
- FloorAsteroidSand
|
||||
entities:
|
||||
- CrystalGreen
|
||||
- CrystalPink
|
||||
- CrystalOrange
|
||||
- CrystalBlue
|
||||
- CrystalCyan
|
||||
- !type:BiomeEntityLayer
|
||||
threshold: 0.95
|
||||
noise:
|
||||
seed: 1
|
||||
noiseType: OpenSimplex2
|
||||
frequency: 1
|
||||
allowedTiles:
|
||||
- FloorAsteroidSand
|
||||
entities:
|
||||
- FloraStalagmite1
|
||||
- FloraStalagmite2
|
||||
- FloraStalagmite3
|
||||
- FloraStalagmite4
|
||||
- FloraStalagmite5
|
||||
- FloraStalagmite6
|
||||
- !type:BiomeEntityLayer
|
||||
threshold: -0.5
|
||||
invert: true
|
||||
noise:
|
||||
seed: 0
|
||||
noiseType: Perlin
|
||||
fractalType: Ridged
|
||||
octaves: 1
|
||||
frequency: 0.1
|
||||
gain: 0.5
|
||||
allowedTiles:
|
||||
- FloorAsteroidSand
|
||||
entities:
|
||||
- GulagWallRock
|
||||
- !type:BiomeDummyLayer
|
||||
id: Loot
|
||||
- !type:BiomeTileLayer
|
||||
threshold: -1.0
|
||||
tile: FloorAsteroidSand
|
||||
variants:
|
||||
- 0
|
||||
- !type:BiomeTileLayer
|
||||
threshold: 0.5
|
||||
noise:
|
||||
seed: 1
|
||||
noiseType: OpenSimplex2
|
||||
frequency: 2
|
||||
tile: FloorAsteroidSand
|
||||
|
||||
- type: entity
|
||||
id: GulagWallRock
|
||||
parent: WallRock
|
||||
name: rock
|
||||
suffix: planetmap
|
||||
components:
|
||||
- type: OreVein
|
||||
oreChance: 0.25
|
||||
oreRarityPrototypeId: RandomGulagOreDistributionStandard
|
||||
|
||||
- type: weightedRandomOre
|
||||
id: RandomGulagOreDistributionStandard
|
||||
weights:
|
||||
OreSteel: 10
|
||||
OreCoal: 10
|
||||
OreSpaceQuartz: 8
|
||||
OreGold: 2
|
||||
OrePlasma: 4
|
||||
OreSilver: 1
|
||||
OreUranium: 1
|
||||
OreBananium: 0.5
|
||||
@@ -0,0 +1,6 @@
|
||||
- type: entity
|
||||
id: CrateGulag
|
||||
parent: CrateGenericSteel
|
||||
noSpawn: true
|
||||
components:
|
||||
- type: GulagFillContainer
|
||||
@@ -0,0 +1,38 @@
|
||||
- type: entity
|
||||
id: GulagOreProcessor
|
||||
name: gulagMachine
|
||||
description: Shit
|
||||
parent: BaseMachinePowered
|
||||
suffix: NoSpawn
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: Structures/Machines/ore_processor.rsi
|
||||
layers:
|
||||
- state: icon
|
||||
map: [ "enum.LatheVisualLayers.IsRunning" ]
|
||||
- state: unlit
|
||||
shader: unshaded
|
||||
map: [ "enum.PowerDeviceVisualLayers.Powered" ]
|
||||
- state: inserting
|
||||
map: [ "enum.MaterialStorageVisualLayers.Inserting" ]
|
||||
- state: panel
|
||||
map: [ "enum.WiresVisualLayers.MaintenancePanel" ]
|
||||
- type: MaterialStorage
|
||||
ignoreColor: true
|
||||
whitelist:
|
||||
tags:
|
||||
- Ore
|
||||
- type: GulagOreProcessor
|
||||
- type: Fixtures
|
||||
fixtures:
|
||||
fix1:
|
||||
shape:
|
||||
!type:PhysShapeAabb
|
||||
bounds: "-0.4,-0.4,0.4,0.4"
|
||||
density: 190
|
||||
mask:
|
||||
- MachineMask
|
||||
layer:
|
||||
- MachineLayer
|
||||
- type: Transform
|
||||
anchored: true
|
||||
Reference in New Issue
Block a user