mirror of
https://gitlab.acidiclight.dev/sociallydistant/sociallydistant.git
synced 2025-01-22 17:41:49 -05:00
Add support for automatic news article posting
This commit is contained in:
parent
bd2d61b315
commit
6deabb0c3d
13 changed files with 148 additions and 17 deletions
|
@ -1,10 +1,11 @@
|
|||
# NOTE: This was generated by ChatGPT as dummy text to test the asset importer.
|
||||
|
||||
id test
|
||||
title Breaking News\: Tragedy Strikes as Fictional City of Rivertown Explodes
|
||||
headline Breaking News\: Tragedy Strikes as Fictional City of Rivertown Explodes
|
||||
excerpt In a devastating turn of events, the tranquil city of Rivertown has been rocked by a catastrophic explosion, leaving residents and authorities reeling in shock and disbelief. The incident, which occurred in the early hours of this morning, has resulted in widespread damage and loss of life, marking a dark day in the history of this once-thriving community.
|
||||
host newciphertoday.com
|
||||
author testuser
|
||||
flags old
|
||||
|
||||
Eyewitnesses reported a deafening blast that shattered windows and sent plumes of smoke billowing into the sky. The explosion, centered in the heart of Rivertown\'s downtown district, reportedly originated from a gas leak in a commercial building, triggering a chain reaction of destruction that engulfed neighboring structures within moments.
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#nullable enable
|
||||
using System;
|
||||
using Core.Scripting;
|
||||
using DevTools;
|
||||
using GameplaySystems.Social;
|
||||
|
||||
namespace Editor.CustomImporters
|
||||
|
@ -13,7 +15,7 @@ namespace Editor.CustomImporters
|
|||
this.asset = asset;
|
||||
}
|
||||
|
||||
[Function("title")]
|
||||
[Function("headline")]
|
||||
private void SetTitle(string[] args)
|
||||
{
|
||||
asset.Title = string.Join(" ", args);
|
||||
|
@ -42,5 +44,21 @@ namespace Editor.CustomImporters
|
|||
{
|
||||
asset.Excerpt = string.Join(" ", text);
|
||||
}
|
||||
|
||||
[Function("flags")]
|
||||
public void SetFlags(string[] flags)
|
||||
{
|
||||
ArticleFlags newFlags = default;
|
||||
|
||||
foreach (string flag in flags)
|
||||
{
|
||||
if (!Enum.TryParse(flag, true, out ArticleFlags flagValue))
|
||||
throw new InvalidOperationException($"'{flag}' is not a valid news article flag.");
|
||||
|
||||
newFlags |= flagValue;
|
||||
}
|
||||
|
||||
asset.Flags = newFlags;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -68,6 +68,12 @@ namespace Core.DataManagement
|
|||
return this[narrativeIdLookup[narrativeId]];
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool ContainsNarrativeId(string narrativeId)
|
||||
{
|
||||
return this.narrativeIdLookup.ContainsKey(narrativeId);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerator<TDataElement> GetEnumerator()
|
||||
{
|
||||
|
|
14
Assets/Scripts/DevTools/ArticleFlags.cs
Normal file
14
Assets/Scripts/DevTools/ArticleFlags.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
#nullable enable
|
||||
using System;
|
||||
|
||||
namespace DevTools
|
||||
{
|
||||
[Flags]
|
||||
public enum ArticleFlags : byte
|
||||
{
|
||||
None = 0,
|
||||
Scripted = 1,
|
||||
Old = Scripted << 1,
|
||||
Hidden = Old << 1,
|
||||
}
|
||||
}
|
3
Assets/Scripts/DevTools/ArticleFlags.cs.meta
Normal file
3
Assets/Scripts/DevTools/ArticleFlags.cs.meta
Normal file
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6bc13aff85c842889285de8e643bfcbc
|
||||
timeCreated: 1718984474
|
21
Assets/Scripts/DevTools/IArticleAsset.cs
Normal file
21
Assets/Scripts/DevTools/IArticleAsset.cs
Normal file
|
@ -0,0 +1,21 @@
|
|||
#nullable enable
|
||||
using System.Threading.Tasks;
|
||||
using Core.WorldData.Data;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DevTools
|
||||
{
|
||||
public interface IArticleAsset
|
||||
{
|
||||
string NarrativeId { get; }
|
||||
string HostName { get; }
|
||||
string Title { get; }
|
||||
string NarrativeAuthorId { get; }
|
||||
string Excerpt { get; }
|
||||
|
||||
DocumentElement[] Body { get; }
|
||||
ArticleFlags Flags { get; }
|
||||
|
||||
Task<Texture2D?> GetFeaturedImage();
|
||||
}
|
||||
}
|
3
Assets/Scripts/DevTools/IArticleAsset.cs.meta
Normal file
3
Assets/Scripts/DevTools/IArticleAsset.cs.meta
Normal file
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b0edd7966f274e86b364cd36d1d22505
|
||||
timeCreated: 1718984375
|
|
@ -2,25 +2,10 @@
|
|||
using System.Threading.Tasks;
|
||||
using ContentManagement;
|
||||
using Core;
|
||||
using Core.WorldData.Data;
|
||||
using Modules;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DevTools
|
||||
{
|
||||
public interface IArticleAsset
|
||||
{
|
||||
string NarrativeId { get; }
|
||||
string HostName { get; }
|
||||
string Title { get; }
|
||||
string NarrativeAuthorId { get; }
|
||||
string Excerpt { get; }
|
||||
|
||||
DocumentElement[] Body { get; }
|
||||
|
||||
Task<Texture2D?> GetFeaturedImage();
|
||||
}
|
||||
|
||||
public interface ICharacterGenerator : IGameContent
|
||||
{
|
||||
Task GenerateNpcs(IWorldManager world);
|
||||
|
|
|
@ -18,5 +18,7 @@ namespace Core
|
|||
where TDataElement : struct, IWorldData, IDataWithId, INarrativeObject
|
||||
{
|
||||
TDataElement GetNarrativeObject(string narrativeId);
|
||||
|
||||
bool ContainsNarrativeId(string narrativeId);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
#nullable enable
|
||||
using System;
|
||||
using System.Linq;
|
||||
using ContentManagement;
|
||||
using Core.WorldData.Data;
|
||||
using DevTools;
|
||||
|
@ -42,6 +43,8 @@ namespace GameplaySystems.Social
|
|||
internal void Update(WorldNewsData data, IContentManager contentManager)
|
||||
{
|
||||
Date = data.Date;
|
||||
|
||||
articleAsset = contentManager.GetContentOfType<IArticleAsset>().FirstOrDefault(x => x.NarrativeId == data.NarrativeId);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -29,6 +29,9 @@ namespace GameplaySystems.Social
|
|||
[SerializeField]
|
||||
private DocumentElement[] body = Array.Empty<DocumentElement>();
|
||||
|
||||
[SerializeField]
|
||||
private ArticleFlags articleFlags;
|
||||
|
||||
/// <inheritdoc />
|
||||
public string NarrativeId
|
||||
{
|
||||
|
@ -83,6 +86,16 @@ namespace GameplaySystems.Social
|
|||
#endif
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ArticleFlags Flags
|
||||
{
|
||||
get => articleFlags;
|
||||
#if UNITY_EDITOR
|
||||
set => articleFlags = value;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<Texture2D?> GetFeaturedImage()
|
||||
{
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ContentManagement;
|
||||
using Core;
|
||||
using Core.WorldData.Data;
|
||||
using DevTools;
|
||||
using Social;
|
||||
using Time = UnityEngine.Time;
|
||||
|
||||
namespace GameplaySystems.Social
|
||||
{
|
||||
|
@ -16,6 +19,10 @@ namespace GameplaySystems.Social
|
|||
private readonly List<NewsArticle> articles = new();
|
||||
private readonly Dictionary<ObjectId, int> articlesById = new();
|
||||
|
||||
private const float UpdateIntervalSeconds = 2;
|
||||
|
||||
private float updateTime = 0;
|
||||
|
||||
public NewsManager(ISocialService socialService, IWorldManager worldManager, IContentManager contentManager)
|
||||
{
|
||||
this.socialService = socialService;
|
||||
|
@ -96,5 +103,55 @@ namespace GameplaySystems.Social
|
|||
return articles.Where(x => x.HostName == hostname)
|
||||
.OrderByDescending(x => x.Date);
|
||||
}
|
||||
|
||||
internal void Update()
|
||||
{
|
||||
updateTime += Time.deltaTime;
|
||||
|
||||
if (updateTime < UpdateIntervalSeconds)
|
||||
return;
|
||||
|
||||
updateTime = 0;
|
||||
PostNewArticles();
|
||||
}
|
||||
|
||||
private void PostNewArticles()
|
||||
{
|
||||
foreach (IArticleAsset asset in contentManager.GetContentOfType<IArticleAsset>())
|
||||
{
|
||||
if (asset.Flags.HasFlag(ArticleFlags.Scripted))
|
||||
continue;
|
||||
|
||||
bool shouldPost = asset.Flags.HasFlag(ArticleFlags.Old);
|
||||
|
||||
if (shouldPost)
|
||||
{
|
||||
if (worldManager.World.NewsArticles.ContainsNarrativeId(asset.NarrativeId))
|
||||
continue;
|
||||
|
||||
ObjectId id = worldManager.GetNextObjectId();
|
||||
|
||||
var data = new WorldNewsData()
|
||||
{
|
||||
InstanceId = id,
|
||||
NarrativeId = asset.NarrativeId,
|
||||
Date = asset.Flags.HasFlag(ArticleFlags.Old)
|
||||
? DateTime.MinValue.AddMonths(id.Id)
|
||||
: worldManager.World.GlobalWorldState.Value.Now
|
||||
};
|
||||
|
||||
worldManager.World.NewsArticles.Add(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!worldManager.World.NewsArticles.ContainsNarrativeId(asset.NarrativeId))
|
||||
continue;
|
||||
|
||||
WorldNewsData data = worldManager.World.NewsArticles.GetNarrativeObject(asset.NarrativeId);
|
||||
worldManager.World.NewsArticles.Remove(data);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -78,6 +78,11 @@ namespace GameplaySystems.Social
|
|||
newsManager = new NewsManager(this, worldManager, game.ContentManager);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
newsManager.Update();
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
game.ScriptSystem.UnregisterHookListener(CommonScriptHooks.AfterWorldStateUpdate, characterUpdateHook);
|
||||
|
|
Loading…
Reference in a new issue