Mid-game prototype loading for game admins (#5675)
This commit is contained in:
@@ -0,0 +1,39 @@
|
|||||||
|
using System;
|
||||||
|
using Content.Shared.Administration;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Localization;
|
||||||
|
using Robust.Shared.Log;
|
||||||
|
using Robust.Shared.Network;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Client.Administration.Managers;
|
||||||
|
|
||||||
|
public class GamePrototypeLoadManager : IGamePrototypeLoadManager
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IClientNetManager _netManager = default!;
|
||||||
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
|
[Dependency] private readonly ILocalizationManager _localizationManager = default!;
|
||||||
|
|
||||||
|
public void Initialize()
|
||||||
|
{
|
||||||
|
_netManager.RegisterNetMessage<GamePrototypeLoadMessage>(LoadGamePrototype);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadGamePrototype(GamePrototypeLoadMessage message)
|
||||||
|
{
|
||||||
|
_prototypeManager.LoadString(message.PrototypeData);
|
||||||
|
_prototypeManager.Resync();
|
||||||
|
_localizationManager.ReloadLocalizations();
|
||||||
|
GamePrototypeLoaded?.Invoke();
|
||||||
|
Logger.InfoS("adminbus", "Loaded adminbus prototype data.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendGamePrototype(string prototype)
|
||||||
|
{
|
||||||
|
var msg = _netManager.CreateNetMessage<GamePrototypeLoadMessage>();
|
||||||
|
msg.PrototypeData = prototype;
|
||||||
|
_netManager.ClientSendMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public event Action? GamePrototypeLoaded;
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
<GridContainer Columns="3">
|
<GridContainer Columns="3">
|
||||||
<Button Name="SpawnEntitiesButton" Text="{Loc 'sandbox-window-spawn-entities-button'}" />
|
<Button Name="SpawnEntitiesButton" Text="{Loc 'sandbox-window-spawn-entities-button'}" />
|
||||||
<Button Name="SpawnTilesButton" Text="{Loc 'sandbox-window-spawn-tiles-button'} " />
|
<Button Name="SpawnTilesButton" Text="{Loc 'sandbox-window-spawn-tiles-button'} " />
|
||||||
|
<Button Name="LoadGamePrototypeButton" Text="{Loc 'load-game-prototype'}"/>
|
||||||
<cc:CommandButton Command="deleteewc Singularity" Name="DeleteSingulos" Text="{Loc 'delete-singularities'}"/>
|
<cc:CommandButton Command="deleteewc Singularity" Name="DeleteSingulos" Text="{Loc 'delete-singularities'}"/>
|
||||||
<cc:UICommandButton Command="events" Text="{Loc 'open-station-events'}" WindowType="{x:Type abt:StationEventsWindow}" />
|
<cc:UICommandButton Command="events" Text="{Loc 'open-station-events'}" WindowType="{x:Type abt:StationEventsWindow}" />
|
||||||
</GridContainer>
|
</GridContainer>
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
using Content.Client.Administration.Managers;
|
using System.IO;
|
||||||
|
using Content.Client.Administration.Managers;
|
||||||
|
using Content.Shared.Administration;
|
||||||
using Robust.Client.AutoGenerated;
|
using Robust.Client.AutoGenerated;
|
||||||
using Robust.Client.Placement;
|
using Robust.Client.Placement;
|
||||||
using Robust.Client.ResourceManagement;
|
using Robust.Client.ResourceManagement;
|
||||||
@@ -24,6 +26,23 @@ namespace Content.Client.Administration.UI.Tabs.AdminbusTab
|
|||||||
// TODO: This will probably need some command check at some point
|
// TODO: This will probably need some command check at some point
|
||||||
SpawnEntitiesButton.OnPressed += SpawnEntitiesButtonOnOnPressed;
|
SpawnEntitiesButton.OnPressed += SpawnEntitiesButtonOnOnPressed;
|
||||||
SpawnTilesButton.OnPressed += SpawnTilesButtonOnOnPressed;
|
SpawnTilesButton.OnPressed += SpawnTilesButtonOnOnPressed;
|
||||||
|
LoadGamePrototypeButton.OnPressed += LoadGamePrototypeButtonOnOnPressed;
|
||||||
|
LoadGamePrototypeButton.Visible = IoCManager.Resolve<IClientAdminManager>().HasFlag(AdminFlags.Query);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void LoadGamePrototypeButtonOnOnPressed(BaseButton.ButtonEventArgs obj)
|
||||||
|
{
|
||||||
|
var dialogManager = IoCManager.Resolve<IFileDialogManager>();
|
||||||
|
var loadManager = IoCManager.Resolve<IGamePrototypeLoadManager>();
|
||||||
|
|
||||||
|
var stream = await dialogManager.OpenFile();
|
||||||
|
if (stream is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// ew oop
|
||||||
|
var reader = new StreamReader(stream);
|
||||||
|
var proto = await reader.ReadToEndAsync();
|
||||||
|
loadManager.SendGamePrototype(proto);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SpawnEntitiesButtonOnOnPressed(BaseButton.ButtonEventArgs obj)
|
private void SpawnEntitiesButtonOnOnPressed(BaseButton.ButtonEventArgs obj)
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ using Content.Client.Stylesheets;
|
|||||||
using Content.Client.Viewport;
|
using Content.Client.Viewport;
|
||||||
using Content.Client.Voting;
|
using Content.Client.Voting;
|
||||||
using Content.Shared.Actions;
|
using Content.Shared.Actions;
|
||||||
|
using Content.Shared.Administration;
|
||||||
using Content.Shared.Alert;
|
using Content.Shared.Alert;
|
||||||
using Content.Shared.AME;
|
using Content.Shared.AME;
|
||||||
using Content.Shared.Cargo.Components;
|
using Content.Shared.Cargo.Components;
|
||||||
@@ -188,6 +189,7 @@ namespace Content.Client.Entry
|
|||||||
IoCManager.Resolve<AlertManager>().Initialize();
|
IoCManager.Resolve<AlertManager>().Initialize();
|
||||||
IoCManager.Resolve<ActionManager>().Initialize();
|
IoCManager.Resolve<ActionManager>().Initialize();
|
||||||
IoCManager.Resolve<IVoteManager>().Initialize();
|
IoCManager.Resolve<IVoteManager>().Initialize();
|
||||||
|
IoCManager.Resolve<IGamePrototypeLoadManager>().Initialize();
|
||||||
|
|
||||||
_baseClient.RunLevelChanged += (_, args) =>
|
_baseClient.RunLevelChanged += (_, args) =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Client.Administration.Managers;
|
using Content.Client.Administration;
|
||||||
|
using Content.Client.Administration.Managers;
|
||||||
using Content.Client.Changelog;
|
using Content.Client.Changelog;
|
||||||
using Content.Client.Chat.Managers;
|
using Content.Client.Chat.Managers;
|
||||||
using Content.Client.Clickable;
|
using Content.Client.Clickable;
|
||||||
@@ -17,6 +18,7 @@ using Content.Client.Stylesheets;
|
|||||||
using Content.Client.Viewport;
|
using Content.Client.Viewport;
|
||||||
using Content.Client.Voting;
|
using Content.Client.Voting;
|
||||||
using Content.Shared.Actions;
|
using Content.Shared.Actions;
|
||||||
|
using Content.Shared.Administration;
|
||||||
using Content.Shared.Alert;
|
using Content.Shared.Alert;
|
||||||
using Content.Shared.Module;
|
using Content.Shared.Module;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
@@ -47,6 +49,7 @@ namespace Content.Client.IoC
|
|||||||
IoCManager.Register<ChangelogManager, ChangelogManager>();
|
IoCManager.Register<ChangelogManager, ChangelogManager>();
|
||||||
IoCManager.Register<RulesManager, RulesManager>();
|
IoCManager.Register<RulesManager, RulesManager>();
|
||||||
IoCManager.Register<ViewportManager, ViewportManager>();
|
IoCManager.Register<ViewportManager, ViewportManager>();
|
||||||
|
IoCManager.Register<IGamePrototypeLoadManager, GamePrototypeLoadManager>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
76
Content.Server/Administration/GamePrototypeLoadManager.cs
Normal file
76
Content.Server/Administration/GamePrototypeLoadManager.cs
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Content.Server.Administration.Managers;
|
||||||
|
using Content.Shared.Administration;
|
||||||
|
using Robust.Server.Player;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Localization;
|
||||||
|
using Robust.Shared.Log;
|
||||||
|
using Robust.Shared.Network;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Server.Administration;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Manages sending runtime-loaded prototypes from game staff to clients.
|
||||||
|
/// </summary>
|
||||||
|
public class GamePrototypeLoadManager : IGamePrototypeLoadManager
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IServerNetManager _netManager = default!;
|
||||||
|
[Dependency] private readonly IAdminManager _adminManager = default!;
|
||||||
|
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||||
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
|
[Dependency] private readonly ILocalizationManager _localizationManager = default!;
|
||||||
|
|
||||||
|
private readonly List<string> LoadedPrototypes = new();
|
||||||
|
|
||||||
|
public void Initialize()
|
||||||
|
{
|
||||||
|
_netManager.RegisterNetMessage<GamePrototypeLoadMessage>(ClientLoadsPrototype);
|
||||||
|
_netManager.Connected += NetManagerOnConnected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendGamePrototype(string prototype)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public event Action? GamePrototypeLoaded;
|
||||||
|
|
||||||
|
private void ClientLoadsPrototype(GamePrototypeLoadMessage message)
|
||||||
|
{
|
||||||
|
var player = _playerManager.GetSessionByChannel(message.MsgChannel);
|
||||||
|
if (_adminManager.IsAdmin(player) && _adminManager.HasAdminFlag(player, AdminFlags.Query))
|
||||||
|
{
|
||||||
|
LoadPrototypeData(message.PrototypeData);
|
||||||
|
Logger.InfoS("adminbus", $"Loaded adminbus prototype data from {player.Name}.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
message.MsgChannel.Disconnect("Sent prototype message without permission!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadPrototypeData(string prototypeData)
|
||||||
|
{
|
||||||
|
LoadedPrototypes.Add(prototypeData);
|
||||||
|
var msg = _netManager.CreateNetMessage<GamePrototypeLoadMessage>();
|
||||||
|
msg.PrototypeData = prototypeData;
|
||||||
|
_netManager.ServerSendToAll(msg); // everyone load it up!
|
||||||
|
_prototypeManager.LoadString(prototypeData); // server needs it too.
|
||||||
|
_prototypeManager.Resync();
|
||||||
|
_localizationManager.ReloadLocalizations();
|
||||||
|
GamePrototypeLoaded?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void NetManagerOnConnected(object? sender, NetChannelArgs e)
|
||||||
|
{
|
||||||
|
// Just dump all the prototypes on connect, before them missing could be an issue.
|
||||||
|
foreach (var prototype in LoadedPrototypes)
|
||||||
|
{
|
||||||
|
var msg = _netManager.CreateNetMessage<GamePrototypeLoadMessage>();
|
||||||
|
msg.PrototypeData = prototype;
|
||||||
|
e.Channel.SendMessage(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,15 +8,14 @@ using Content.Server.Connection;
|
|||||||
using Content.Server.Database;
|
using Content.Server.Database;
|
||||||
using Content.Server.EUI;
|
using Content.Server.EUI;
|
||||||
using Content.Server.GameTicking;
|
using Content.Server.GameTicking;
|
||||||
using Content.Server.Holiday.Interfaces;
|
|
||||||
using Content.Server.IoC;
|
using Content.Server.IoC;
|
||||||
using Content.Server.Maps;
|
using Content.Server.Maps;
|
||||||
using Content.Server.NodeContainer.NodeGroups;
|
using Content.Server.NodeContainer.NodeGroups;
|
||||||
using Content.Server.Preferences.Managers;
|
using Content.Server.Preferences.Managers;
|
||||||
using Content.Server.Sandbox;
|
using Content.Server.Sandbox;
|
||||||
using Content.Server.Speech;
|
|
||||||
using Content.Server.Voting.Managers;
|
using Content.Server.Voting.Managers;
|
||||||
using Content.Shared.Actions;
|
using Content.Shared.Actions;
|
||||||
|
using Content.Shared.Administration;
|
||||||
using Content.Shared.Alert;
|
using Content.Shared.Alert;
|
||||||
using Content.Shared.Kitchen;
|
using Content.Shared.Kitchen;
|
||||||
using Robust.Server.Bql;
|
using Robust.Server.Bql;
|
||||||
@@ -75,6 +74,7 @@ namespace Content.Server.Entry
|
|||||||
IoCManager.Resolve<IServerDbManager>().Init();
|
IoCManager.Resolve<IServerDbManager>().Init();
|
||||||
IoCManager.Resolve<IServerPreferencesManager>().Init();
|
IoCManager.Resolve<IServerPreferencesManager>().Init();
|
||||||
IoCManager.Resolve<INodeGroupFactory>().Initialize();
|
IoCManager.Resolve<INodeGroupFactory>().Initialize();
|
||||||
|
IoCManager.Resolve<IGamePrototypeLoadManager>().Initialize();
|
||||||
_voteManager.Initialize();
|
_voteManager.Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ using Content.Server.Sandbox;
|
|||||||
using Content.Server.Speech;
|
using Content.Server.Speech;
|
||||||
using Content.Server.Voting.Managers;
|
using Content.Server.Voting.Managers;
|
||||||
using Content.Shared.Actions;
|
using Content.Shared.Actions;
|
||||||
|
using Content.Shared.Administration;
|
||||||
using Content.Shared.Alert;
|
using Content.Shared.Alert;
|
||||||
using Content.Shared.Kitchen;
|
using Content.Shared.Kitchen;
|
||||||
using Content.Shared.Module;
|
using Content.Shared.Module;
|
||||||
@@ -55,6 +56,7 @@ namespace Content.Server.IoC
|
|||||||
IoCManager.Register<IPlayerLocator, PlayerLocator>();
|
IoCManager.Register<IPlayerLocator, PlayerLocator>();
|
||||||
IoCManager.Register<IAfkManager, AfkManager>();
|
IoCManager.Register<IAfkManager, AfkManager>();
|
||||||
IoCManager.Register<IGameMapManager, GameMapManager>();
|
IoCManager.Register<IGameMapManager, GameMapManager>();
|
||||||
|
IoCManager.Register<IGamePrototypeLoadManager, GamePrototypeLoadManager>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
25
Content.Shared/Administration/GamePrototypeLoadMessage.cs
Normal file
25
Content.Shared/Administration/GamePrototypeLoadMessage.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
using System;
|
||||||
|
using Lidgren.Network;
|
||||||
|
using Robust.Shared.Network;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
|
namespace Content.Shared.Administration;
|
||||||
|
|
||||||
|
[NetSerializable]
|
||||||
|
[Serializable]
|
||||||
|
public class GamePrototypeLoadMessage : NetMessage
|
||||||
|
{
|
||||||
|
public override MsgGroups MsgGroup => MsgGroups.String;
|
||||||
|
|
||||||
|
public string PrototypeData { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
public override void ReadFromBuffer(NetIncomingMessage buffer)
|
||||||
|
{
|
||||||
|
PrototypeData = buffer.ReadString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteToBuffer(NetOutgoingMessage buffer)
|
||||||
|
{
|
||||||
|
buffer.Write(PrototypeData);
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Content.Shared/Administration/IGamePrototypeLoadManager.cs
Normal file
11
Content.Shared/Administration/IGamePrototypeLoadManager.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Content.Shared.Administration;
|
||||||
|
|
||||||
|
public interface IGamePrototypeLoadManager
|
||||||
|
{
|
||||||
|
public void Initialize();
|
||||||
|
public void SendGamePrototype(string prototype);
|
||||||
|
|
||||||
|
event Action GamePrototypeLoaded;
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using Content.Shared.Administration;
|
||||||
using Content.Shared.Administration.Logs;
|
using Content.Shared.Administration.Logs;
|
||||||
using Content.Shared.Chemistry.Components;
|
using Content.Shared.Chemistry.Components;
|
||||||
using Content.Shared.Chemistry.Reagent;
|
using Content.Shared.Chemistry.Reagent;
|
||||||
@@ -24,6 +25,7 @@ namespace Content.Shared.Chemistry.Reaction
|
|||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
[Dependency] protected readonly SharedAdminLogSystem _logSystem = default!;
|
[Dependency] protected readonly SharedAdminLogSystem _logSystem = default!;
|
||||||
|
[Dependency] private readonly IGamePrototypeLoadManager _gamePrototypeLoadManager = default!;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A cache of all existant chemical reactions indexed by one of their
|
/// A cache of all existant chemical reactions indexed by one of their
|
||||||
@@ -37,6 +39,7 @@ namespace Content.Shared.Chemistry.Reaction
|
|||||||
|
|
||||||
InitializeReactionCache();
|
InitializeReactionCache();
|
||||||
_prototypeManager.PrototypesReloaded += OnPrototypesReloaded;
|
_prototypeManager.PrototypesReloaded += OnPrototypesReloaded;
|
||||||
|
_gamePrototypeLoadManager.GamePrototypeLoaded += InitializeReactionCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
delete-singularities = Delete Singularities
|
delete-singularities = Delete Singularities
|
||||||
open-station-events = Station Events
|
open-station-events = Station Events
|
||||||
|
load-game-prototype = Load Prototype
|
||||||
|
|||||||
Reference in New Issue
Block a user