Skip to content

Commit

Permalink
Allow user configuration of workshop effects & more refactoring
Browse files Browse the repository at this point in the history
Store the custom user settings inside the submission json file used for disabled_files

Another mega commit, wheee
  • Loading branch information
pongo1231 committed Aug 21, 2023
1 parent 8c79a90 commit 7340ab0
Show file tree
Hide file tree
Showing 26 changed files with 664 additions and 318 deletions.
7 changes: 3 additions & 4 deletions ChaosMod/Components/EffectDispatcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ static void _DispatchEffect(EffectDispatcher *effectDispatcher, const EffectDisp

if (activeEffect.Identifier == entry.Identifier)
{
if (effectData.TimedType != EffectTimedType::Default && effectData.TimedType != EffectTimedType::NotTimed)
if (effectData.TimedType != EffectTimedType::NotTimed)
{
alreadyExists = true;
activeEffect.Timer = activeEffect.MaxTime;
Expand Down Expand Up @@ -444,9 +444,8 @@ void EffectDispatcher::UpdateEffects(int deltaTime)
if (g_EnabledEffects.contains(effect.Identifier))
{
auto &effectData = g_EnabledEffects.at(effect.Identifier);
isTimed =
effectData.TimedType != EffectTimedType::NotTimed && effectData.TimedType != EffectTimedType::Default;
isMeta = effectData.IsMeta();
isTimed = effectData.TimedType != EffectTimedType::NotTimed;
isMeta = effectData.IsMeta();
}

if (effect.MaxTime > 0)
Expand Down
20 changes: 9 additions & 11 deletions ChaosMod/Components/EffectDispatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,15 @@ class EffectDispatcher : public Component
ActiveEffect(const EffectIdentifier &effectIdentifier, RegisteredEffect *registeredEffect,
const std::string &name, const EffectData &effectData, float effectDuration)
{
Identifier = effectIdentifier;
Name = name;
FakeName = effectData.FakeName;
Timer = effectDuration;
MaxTime = effectDuration;
HideEffectName = effectData.ShouldHideRealNameOnStart();

auto eTimedType = g_EnabledEffects.at(effectIdentifier).TimedType;

ThreadId = EffectThreads::CreateThread(registeredEffect, eTimedType != EffectTimedType::Default
&& eTimedType != EffectTimedType::NotTimed);
Identifier = effectIdentifier;
Name = name;
FakeName = effectData.FakeName;
Timer = effectDuration;
MaxTime = effectDuration;
HideEffectName = effectData.ShouldHideRealNameOnStart();

auto timedType = g_EnabledEffects.at(effectIdentifier).TimedType;
ThreadId = EffectThreads::CreateThread(registeredEffect, timedType != EffectTimedType::NotTimed);
}
};
struct
Expand Down
86 changes: 77 additions & 9 deletions ChaosMod/Components/LuaScripts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "Components/EffectDispatcher.h"
#include "Components/KeyStates.h"
#include "Components/MetaModifiers.h"
#include "Components/Workshop.h"

#include "Effects/Effect.h"
#include "Effects/EffectData.h"
Expand Down Expand Up @@ -34,7 +35,6 @@
#include "Util/Types.h"
#include "Util/Vehicle.h"
#include "Util/Weapon.h"
#include "Util/Workshop.h"

#define LUA_NATIVESDEF "chaosmod\\natives_def.lua"

Expand Down Expand Up @@ -333,9 +333,25 @@ LuaScripts::LuaScripts()
LUA_LOG("Running script " << scriptName);
}

auto currentThread = std::this_thread::get_id();
if (ParseScriptRaw(fileName, buffer.str(),
currentThread == mainThread ? ParseScriptFlag_None : ParseScriptFlag_IsAlienThread)
auto currentThread = std::this_thread::get_id();
int parseScriptFlags = ParseScriptFlag_None;
if (currentThread != mainThread)
{
parseScriptFlags |= ParseScriptFlag_IsAlienThread;
}

std::unordered_map<std::string, nlohmann::json> userEffectSettings;
if (pathStr.starts_with("chaosmod\\workshop") && ComponentExists<Workshop>())
{
// Read user script settings
auto tmp = pathStr.substr(strlen("chaosmod\\workshop\\"));
userEffectSettings = GetComponent<Workshop>()->GetSubmissionScriptSettings(
pathStr.substr(0, pathStr.find('\\', pathStr.find_first_not_of("chaosmod\\workshop\\"))),
tmp.substr(tmp.find("\\") + 1));
}

if (ParseScriptRaw(fileName, buffer.str(), static_cast<LuaScripts::ParseScriptFlags>(parseScriptFlags),
userEffectSettings)
== ParseScriptReturnReason::Error_ThreadUnsafe)
{
std::lock_guard lock(threadUnsafeEntryQueueMutex);
Expand Down Expand Up @@ -408,10 +424,10 @@ LuaScripts::LuaScripts()
{
for (const auto &entry : std::filesystem::directory_iterator(dir))
{
if (entry.is_directory())
if (entry.is_directory() && ComponentExists<Workshop>())
{
for (const auto &entry :
GetWorkshopSubmissionFiles(entry.path().string(), WorkshopFileType::Script))
for (const auto &entry : GetComponent<Workshop>()->GetSubmissionFiles(entry.path().string(),
Workshop::FileType::Script))
{
parseScriptThreaded(entry);
}
Expand Down Expand Up @@ -475,8 +491,9 @@ LuaScripts::~LuaScripts()
}
}

LuaScripts::ParseScriptReturnReason LuaScripts::ParseScriptRaw(std::string scriptName, std::string_view script,
ParseScriptFlags flags)
LuaScripts::ParseScriptReturnReason
LuaScripts::ParseScriptRaw(std::string scriptName, std::string_view script, ParseScriptFlags flags,
std::unordered_map<std::string, nlohmann::json> settingOverrides)
{
sol::state lua;
lua.open_libraries(sol::lib::base);
Expand Down Expand Up @@ -903,13 +920,38 @@ LuaScripts::ParseScriptReturnReason LuaScripts::ParseScriptRaw(std::string scrip
<< effectName << "\"!");
}
}
try
{
effectData.TimedType = static_cast<EffectTimedType>(settingOverrides["TimedType"]);
}
catch (nlohmann::json::exception)
{
}
try
{
effectData.CustomTime = settingOverrides["CustomTime"];
if (effectData.CustomTime > 0)
{
effectData.TimedType = EffectTimedType::Custom;
}
}
catch (nlohmann::json::exception)
{
}

const sol::optional<int> &weightMultOpt = effectInfo["WeightMultiplier"];
if (weightMultOpt)
{
effectData.WeightMult = (std::max)(1, *weightMultOpt);
effectData.Weight = effectData.WeightMult;
}
try
{
effectData.WeightMult = settingOverrides["WeightMult"];
}
catch (nlohmann::json::exception)
{
}

const sol::optional<bool> &isMetaOpt = effectInfo["IsMeta"];
if (isMetaOpt)
Expand All @@ -922,6 +964,13 @@ LuaScripts::ParseScriptReturnReason LuaScripts::ParseScriptRaw(std::string scrip
{
effectData.SetAttribute(EffectAttributes::ExcludedFromVoting, *excludeFromVotingOpt);
}
try
{
effectData.SetAttribute(EffectAttributes::ExcludedFromVoting, settingOverrides["ExcludedFromVoting"]);
}
catch (nlohmann::json::exception)
{
}

const sol::optional<bool> &isUtilityOpt = effectInfo["IsUtility"];
if (isUtilityOpt)
Expand Down Expand Up @@ -988,6 +1037,25 @@ LuaScripts::ParseScriptReturnReason LuaScripts::ParseScriptRaw(std::string scrip
effectData.ShortcutKeycode = shortcutKeycode;
}
}
try
{
effectData.ShortcutKeycode = settingOverrides["ShortcutKeycode"];
}
catch (nlohmann::json::exception)
{
}

try
{
std::string name = StringTrim(settingOverrides["CustomName"]);
if (!name.empty())
{
effectData.CustomName = name;
}
}
catch (nlohmann::json::exception)
{
}

// Exclude temporary effects from choices pool
effectData.SetAttribute(EffectAttributes::IsTemporary, flags & ParseScriptFlag_IsTemporary);
Expand Down
5 changes: 4 additions & 1 deletion ChaosMod/Components/LuaScripts.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#define SOL_SAFE_NUMERICS 1
#include <sol3/sol.hpp>

#include <json.hpp>

#include <string>

class LuaScripts : public Component
Expand Down Expand Up @@ -98,7 +100,8 @@ class LuaScripts : public Component
Error_ThreadUnsafe
};
ParseScriptReturnReason ParseScriptRaw(std::string scriptName, std::string_view script,
ParseScriptFlags flags = ParseScriptFlag_None);
ParseScriptFlags flags = ParseScriptFlag_None,
std::unordered_map<std::string, nlohmann::json> settingOverrides = {});
void RemoveScriptEntry(const std::string &effectId);

public:
Expand Down
10 changes: 5 additions & 5 deletions ChaosMod/Components/Mp3Manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#include "Mp3Manager.h"

#include "Util/Workshop.h"
#include "Components/Workshop.h"

#define CHAOS_SOUNDFILES_USER_DIR "chaosmod"
#define CHAOS_SOUNDFILES_WORKSHOP_DIR "chaosmod\\workshop"
Expand Down Expand Up @@ -30,13 +30,13 @@ void Mp3Manager::HandleDirectory(const std::string &dir, const std::string &soun
return;
}

auto soundDirPath = soundRootDirName + soundName;
auto soundFilePath = soundDirPath + ".mp3";
auto soundDirPath = soundRootDirName + soundName;
auto soundFilePath = soundDirPath + ".mp3";

std::vector<std::string> blacklistedFiles;
if (dir.starts_with(CHAOS_SOUNDFILES_WORKSHOP_DIR))
if (dir.starts_with(CHAOS_SOUNDFILES_WORKSHOP_DIR) && ComponentExists<Workshop>())
{
blacklistedFiles = GetWorkshopSubmissionBlacklistedFiles(dir);
blacklistedFiles = GetComponent<Workshop>()->GetSubmissionBlacklistedFiles(dir);
}

auto &soundFiles = m_EffectSoundFilesCache[soundName];
Expand Down
98 changes: 98 additions & 0 deletions ChaosMod/Components/Workshop.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#include <stdafx.h>

#include "Workshop.h"

void Workshop::OnModPauseCleanup()
{
m_CachedSubmissionSettings.clear();
}

nlohmann::json Workshop::GetSubmissionSettingJson(const std::string &submissionPath)
{
if (m_CachedSubmissionSettings.contains(submissionPath))
{
return m_CachedSubmissionSettings.at(submissionPath);
}

auto submissionSettingsFile = submissionPath + ".json";
if (!DoesFileExist(submissionSettingsFile))
{
return {};
}

std::ifstream file(submissionSettingsFile);
std::stringstream buffer;
buffer << file.rdbuf();

try
{
m_CachedSubmissionSettings[submissionPath] = nlohmann::json::parse(buffer.str());
}
catch (nlohmann::json::exception)
{
m_CachedSubmissionSettings[submissionPath] = {};
}

return m_CachedSubmissionSettings.at(submissionPath);
}

std::vector<std::string> Workshop::GetSubmissionBlacklistedFiles(const std::string &submissionPath)
{
std::vector<std::string> blacklistedFiles;

auto json = GetSubmissionSettingJson(submissionPath);
try
{
for (const std::string &file : json["disabled_files"])
{
blacklistedFiles.push_back(file);
}
}
catch (nlohmann::json::exception)
{
}

return blacklistedFiles;
}

std::vector<std::filesystem::directory_entry> Workshop::GetSubmissionFiles(const std::string &submissionPath,
FileType fileType, std::string subPath)
{
const auto &blacklistedFiles = GetSubmissionBlacklistedFiles(submissionPath);

std::vector<std::filesystem::directory_entry> entries;
switch (fileType)
{
case FileType::Script:
entries = GetFiles(submissionPath + "\\" + subPath, ".lua", true, blacklistedFiles);
break;
case FileType::Audio:
entries = GetFiles(submissionPath + "\\" + subPath, ".mp3", true, blacklistedFiles);
break;
default:
return {};
}

return entries;
}

std::unordered_map<std::string, nlohmann::json> Workshop::GetSubmissionScriptSettings(const std::string &submissionPath,
const std::string &scriptPath)
{
std::unordered_map<std::string, nlohmann::json> scriptSettings;

auto json = GetSubmissionSettingJson(submissionPath);
try
{
for (const auto &[key, value] : json["effect_settings"][scriptPath].items())
{
LOG(key << " " << value);
scriptSettings[key] = value;
}
}
catch (nlohmann::json::exception)
{
}

return scriptSettings;
}
38 changes: 38 additions & 0 deletions ChaosMod/Components/Workshop.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#pragma once

#include "Util/File.h"

#include <filesystem>
#include <string>
#include <unordered_map>
#include <vector>

#include <json.hpp>

class Workshop : public Component
{
private:
std::unordered_map<std::string, nlohmann::json> m_CachedSubmissionSettings;

private:
nlohmann::json GetSubmissionSettingJson(const std::string &submissionPath);

public:
void OnModPauseCleanup() override;

std::vector<std::string> GetSubmissionBlacklistedFiles(const std::string &submissionPath);
enum class FileType
{
Script,
Audio
};
std::vector<std::filesystem::directory_entry> GetSubmissionFiles(const std::string &submissionPath,
FileType fileType, std::string subPath = "");

std::unordered_map<std::string, nlohmann::json> GetSubmissionScriptSettings(const std::string &submissionPath,
const std::string &scriptPath);

template <class T>
requires std::is_base_of_v<Component, T>
friend struct ComponentHolder;
};
Loading

0 comments on commit 7340ab0

Please sign in to comment.