Mid-game prototype loading for game admins (#5675)

This commit is contained in:
Moony
2021-12-11 17:28:16 -06:00
committed by GitHub
parent 5abb3cdc36
commit caad34eecb
12 changed files with 186 additions and 4 deletions

View File

@@ -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;
}

View File

@@ -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>

View File

@@ -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)

View File

@@ -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) =>
{ {

View File

@@ -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>();
} }
} }
} }

View 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);
}
}
}

View File

@@ -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();
} }

View File

@@ -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>();
} }
} }
} }

View 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);
}
}

View 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;
}

View File

@@ -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>

View File

@@ -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