Skip to content

Commit

Permalink
Holiday System (#3122)
Browse files Browse the repository at this point in the history
  • Loading branch information
gradientvera authored Feb 12, 2021
1 parent 857c65d commit 9ee0ec4
Show file tree
Hide file tree
Showing 36 changed files with 1,086 additions and 24 deletions.
12 changes: 12 additions & 0 deletions Content.Client/Jobs/JanitorSpecial.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Content.Shared.Roles;
using JetBrains.Annotations;

namespace Content.Client.Jobs
{
[UsedImplicitly]
public class JanitorSpecial : JobSpecial
{
// Dummy class that exists solely to avoid an exception on the client,
// but allow the server-side counterpart to exist.
}
}
2 changes: 0 additions & 2 deletions Content.Client/UserInterface/GhostRoleWindow.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using Content.Client.GameObjects.EntitySystems;
using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.GameObjects.Systems;

namespace Content.Client.UserInterface
{
Expand Down
3 changes: 3 additions & 0 deletions Content.IntegrationTests/ContentIntegrationTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ protected override ServerIntegrationInstance StartServer(ServerIntegrationOption
// Avoid funny race conditions with the database.
options.CVarOverrides[CCVars.DatabaseSynchronous.Name] = "true";

// Disable holidays as some of them might mess with the map at round start.
options.CVarOverrides[CCVars.HolidaysEnabled.Name] = "false";

// Avoid loading a large map by default for integration tests.
options.CVarOverrides[CCVars.GameMap.Name] = "Maps/Test/empty.yml";

Expand Down
1 change: 1 addition & 0 deletions Content.IntegrationTests/Tests/ContainerOcclusionTest.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Content.Server.GameObjects.Components.Items.Storage;
Expand Down
2 changes: 2 additions & 0 deletions Content.Server/Chat/ChatManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Log;
using Robust.Shared.Network;
using static Content.Server.Interfaces.Chat.IChatManager;

Expand Down Expand Up @@ -67,6 +68,7 @@ public void DispatchServerAnnouncement(string message)
msg.Message = message;
msg.MessageWrap = "SERVER: {0}";
_netManager.ServerSendToAll(msg);
Logger.InfoS("SERVER", message);
}

public void DispatchStationAnnouncement(string message, string sender = "CentComm")
Expand Down
2 changes: 2 additions & 0 deletions Content.Server/EntryPoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Content.Server.Eui;
using Content.Server.GameObjects.Components.Mobs.Speech;
using Content.Server.GameObjects.Components.NodeContainer.NodeGroups;
using Content.Server.Holiday.Interfaces;
using Content.Server.Interfaces;
using Content.Server.Interfaces.Chat;
using Content.Server.Interfaces.GameTicking;
Expand Down Expand Up @@ -78,6 +79,7 @@ public override void PostInit()
{
base.PostInit();

IoCManager.Resolve<IHolidayManager>().Initialize();
_gameTicker.Initialize();
IoCManager.Resolve<RecipeManager>().Initialize();
IoCManager.Resolve<AlertManager>().Initialize();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using Content.Server.GameObjects.EntitySystems;
using Robust.Server.Interfaces.Player;
using Robust.Server.Player;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,8 @@
using Content.Server.GameObjects.Components.Mobs;
using Content.Server.Players;
using JetBrains.Annotations;
using Robust.Server.Interfaces.GameObjects;
using Robust.Server.Interfaces.Player;
using Robust.Server.Player;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using Content.Server.GameObjects.EntitySystems;
using Content.Shared.Eui;
using Content.Shared.GameObjects.Components.Observer;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.GameObjects;

namespace Content.Server.GameObjects.Components.Observer
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@
using Content.Server.GameObjects.Components.Mobs;
using Content.Server.GameObjects.EntitySystems;
using Content.Server.Players;
using Robust.Server.Interfaces.Player;
using Robust.Server.Player;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Systems;

namespace Content.Server.GameObjects.Components.Observer
{
Expand Down
7 changes: 2 additions & 5 deletions Content.Server/GameObjects/EntitySystems/GhostRoleSystem.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
using System.Collections.Generic;
using System.Drawing;
using Content.Server.Administration;
using Content.Server.Eui;
using Content.Server.GameObjects.Components.Observer;
using Content.Shared.GameObjects.Components.Observer;
using Content.Shared.GameObjects.EntitySystemMessages;
using Content.Shared.GameTicking;
using JetBrains.Annotations;
using Robust.Server.GameObjects;
using Robust.Server.Interfaces.Player;
using Robust.Server.Player;
using Robust.Shared.Console;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;

namespace Content.Server.GameObjects.EntitySystems
Expand Down
2 changes: 2 additions & 0 deletions Content.Server/GameTicking/GameTicker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
using Content.Server.GameObjects.Components.Observer;
using Content.Server.GameObjects.Components.PDA;
using Content.Server.GameTicking.GamePresets;
using Content.Server.Holiday;
using Content.Server.Holiday.Interfaces;
using Content.Server.Interfaces;
using Content.Server.Interfaces.Chat;
using Content.Server.Interfaces.GameTicking;
Expand Down
12 changes: 12 additions & 0 deletions Content.Server/Holiday/Celebrate/DefaultHolidayCelebrate.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Content.Server.Holiday.Interfaces;

namespace Content.Server.Holiday.Celebrate
{
public class DefaultHolidayCelebrate : IHolidayCelebrate
{
public void Celebrate(HolidayPrototype holiday)
{
// Nada.
}
}
}
22 changes: 22 additions & 0 deletions Content.Server/Holiday/Greet/Custom.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using Content.Server.Holiday.Interfaces;
using JetBrains.Annotations;
using Robust.Shared.Serialization;

namespace Content.Server.Holiday.Greet
{
[UsedImplicitly]
public class Custom : IHolidayGreet
{
private string _greet;

void IExposeData.ExposeData(ObjectSerializer serializer)
{
serializer.DataField(ref _greet, "text", string.Empty);
}

public string Greet(HolidayPrototype holiday)
{
return _greet;
}
}
}
13 changes: 13 additions & 0 deletions Content.Server/Holiday/Greet/DefaultHolidayGreet.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Content.Server.Holiday.Interfaces;
using Robust.Shared.Localization;

namespace Content.Server.Holiday.Greet
{
public class DefaultHolidayGreet : IHolidayGreet
{
public string Greet(HolidayPrototype holiday)
{
return Loc.GetString("Have a happy {0}!", holiday.Name);
}
}
}
105 changes: 105 additions & 0 deletions Content.Server/Holiday/HolidayManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
using System;
using System.Collections.Generic;
using Content.Server.GameTicking;
using Content.Server.Holiday.Interfaces;
using Content.Server.Interfaces.Chat;
using Content.Server.Interfaces.GameTicking;
using Content.Shared;
using Robust.Shared.Configuration;
using Robust.Shared.IoC;
using Robust.Shared.Prototypes;
using Robust.Shared.ViewVariables;

namespace Content.Server.Holiday
{
// ReSharper disable once ClassNeverInstantiated.Global
public class HolidayManager : IHolidayManager
{
[Dependency] private readonly IConfigurationManager _configManager = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IGameTicker _gameTicker = default!;
[Dependency] private readonly IChatManager _chatManager = default!;

[ViewVariables]
private readonly List<HolidayPrototype> _currentHolidays = new();

[ViewVariables]
private bool _enabled = true;

public void RefreshCurrentHolidays()
{
_currentHolidays.Clear();

if (!_enabled) return;

var now = DateTime.Now;

foreach (var holiday in _prototypeManager.EnumeratePrototypes<HolidayPrototype>())
{
if(holiday.ShouldCelebrate(now))
_currentHolidays.Add(holiday);
}
}

public void DoGreet()
{
foreach (var holiday in _currentHolidays)
{
_chatManager.DispatchServerAnnouncement(holiday.Greet());
}
}

public void DoCelebrate()
{
foreach (var holiday in _currentHolidays)
{
holiday.Celebrate();
}
}

public IEnumerable<HolidayPrototype> GetCurrentHolidays()
{
return _currentHolidays;
}

public bool IsCurrentlyHoliday(string holiday)
{
if (!_prototypeManager.TryIndex(holiday, out HolidayPrototype prototype))
return false;

return _currentHolidays.Contains(prototype);
}

public void Initialize()
{
_configManager.OnValueChanged(CCVars.HolidaysEnabled, OnHolidaysEnableChange, true);

_gameTicker.OnRunLevelChanged += OnRunLevelChanged;
}

private void OnHolidaysEnableChange(bool enabled)
{
_enabled = enabled;

RefreshCurrentHolidays();
}

private void OnRunLevelChanged(GameRunLevelChangedEventArgs eventArgs)
{
if (!_enabled) return;

switch (eventArgs.NewRunLevel)
{
case GameRunLevel.PreRoundLobby:
RefreshCurrentHolidays();
break;
case GameRunLevel.InRound:
DoGreet();
DoCelebrate();
break;
case GameRunLevel.PostRound:
break;
}
}
}
}
78 changes: 78 additions & 0 deletions Content.Server/Holiday/HolidayPrototype.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#nullable enable
using System;
using Content.Server.Holiday.Celebrate;
using Content.Server.Holiday.Greet;
using Content.Server.Holiday.Interfaces;
using Content.Server.Holiday.ShouldCelebrate;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
using YamlDotNet.RepresentationModel;

namespace Content.Server.Holiday
{
[Prototype("holiday")]
public class HolidayPrototype : IPrototype, IIndexedPrototype, IExposeData
{
[ViewVariables] public string Name { get; private set; } = string.Empty;
[ViewVariables] public string ID { get; private set; } = string.Empty;
[ViewVariables] public byte BeginDay { get; set; } = 1;
[ViewVariables] public Month BeginMonth { get; set; } = Month.Invalid;

/// <summary>
/// Day this holiday will end. Zero means it lasts a single day.
/// </summary>
[ViewVariables] public byte EndDay { get; set; } = 0;

/// <summary>
/// Month this holiday will end in. Invalid means it lasts a single month.
/// </summary>
[ViewVariables] public Month EndMonth { get; set; } = Month.Invalid;

[ViewVariables]
private IHolidayShouldCelebrate _shouldCelebrate = new DefaultHolidayShouldCelebrate();

[ViewVariables]
private IHolidayGreet _greet = new DefaultHolidayGreet();

[ViewVariables]
private IHolidayCelebrate _celebrate = new DefaultHolidayCelebrate();

public void LoadFrom(YamlMappingNode mapping)
{
var serializer = YamlObjectSerializer.NewReader(mapping);
ExposeData(serializer);
}

public void ExposeData(ObjectSerializer serializer)
{
serializer.DataField(this, x => x.ID, "id", string.Empty);
serializer.DataField(this, x => x.Name, "name", string.Empty);
serializer.DataField(this, x => x.BeginDay, "beginDay", (byte)1);
serializer.DataField(this, x => x.BeginMonth, "beginMonth", Month.Invalid);
serializer.DataField(this, x => x.EndDay, "endDay", (byte)0);
serializer.DataField(this, x => x.EndMonth, "endMonth", Month.Invalid);
serializer.DataField(ref _shouldCelebrate, "shouldCelebrate", new DefaultHolidayShouldCelebrate());
serializer.DataField(ref _greet, "greet", new DefaultHolidayGreet());
serializer.DataField(ref _celebrate, "celebrate", new DefaultHolidayCelebrate());
}

public bool ShouldCelebrate(DateTime date)
{
return _shouldCelebrate.ShouldCelebrate(date, this);
}

public string Greet()
{
return _greet.Greet(this);
}

/// <summary>
/// Called before the round starts to set up any festive shenanigans.
/// </summary>
public void Celebrate()
{
_celebrate.Celebrate(this);
}
}
}
15 changes: 15 additions & 0 deletions Content.Server/Holiday/Interfaces/IHolidayCelebrate.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Robust.Shared.Serialization;

namespace Content.Server.Holiday.Interfaces
{
public interface IHolidayCelebrate : IExposeData
{
void IExposeData.ExposeData(ObjectSerializer serializer) {}

/// <summary>
/// This method is called before a round starts.
/// Use it to do any fun festive modifications.
/// </summary>
void Celebrate(HolidayPrototype holiday);
}
}
Loading

0 comments on commit 9ee0ec4

Please sign in to comment.