Skip to content

Commit

Permalink
add command to set who can damage what for #361
Browse files Browse the repository at this point in the history
  • Loading branch information
Lazrius committed Nov 19, 2023
1 parent bb8ef1d commit 0973299
Show file tree
Hide file tree
Showing 11 changed files with 191 additions and 28 deletions.
2 changes: 1 addition & 1 deletion include/API/FLHook/ClientList.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ struct ClientData
// Your randomly assigned formation tag, e.g. Navy Lambda 1-6
uint formationNumber1 = 0;
uint formationNumber2 = 0;
uint formationTag = 0;
AllowedFormation formationTag = AllowedFormation::Alpha;

ClientData()
{
Expand Down
7 changes: 5 additions & 2 deletions include/Core/Commands/AdminCommandProcessor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,10 @@ class AdminCommandProcessor final : public Singleton<AdminCommandProcessor>, pub
std::wstring Chase(std::wstring_view characterName);
std::wstring Beam(std::wstring_view characterName, std::wstring_view baseName);
std::wstring Pull(std::wstring_view characterName);
std::wstring SetDamageType(std::wstring_view newDamageType);
// std::wstring Move(const std::wstring& characterName, Vector position);

constexpr inline static std::array<CommandInfo, 29> commands = {
constexpr inline static std::array<CommandInfo, 30> commands = {
{AddAdminCommand(L"getcash", GetCash, GameAndConsole, Cash, L".getcash <charname> <cash>", L"Gets the cash of the target cash"),
AddAdminCommand(L"setcash", SetCash, GameAndConsole, Cash, L".setcash <charname> <cash>", L"Sets the cash of the target cash"),
AddAdminCommand(L"kick", KickPlayer, GameAndConsole, Expel, L".kick <charname>", L"Kick the specified character from the server."),
Expand Down Expand Up @@ -126,7 +127,9 @@ class AdminCommandProcessor final : public Singleton<AdminCommandProcessor>, pub
L"Teleport the admin to the location of the specified character. Does not traverse systems."),
AddAdminCommand(L"beam", Beam, GameAndConsole, Movement, L".beam <charname> <base>", L"Teleport the specified character to the specified base."),
AddAdminCommand(L"pull", Pull, GameOnly, Movement, L".pull <charname>",
L"Pulls the specified character to your location. Does not traverse systems.")}
L"Pulls the specified character to your location. Does not traverse systems."),
AddAdminCommand(L"damagemode", SetDamageType, GameAndConsole, SuperAdmin, L".damagemode <all/none/pvp/pve>",
L"Sets the source of allowed damage on the server.")}
// AddAdminCommand(L"move", Move, GameOnly, Movement)
};

Expand Down
1 change: 0 additions & 1 deletion include/Core/FLHook.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@ class FLHook final
bool LoadBaseMarket();

uint damageToClientId;
uint damageToSpaceId;

bool messagePrivate;
bool messageSystem;
Expand Down
81 changes: 81 additions & 0 deletions include/Defs/Enums.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,84 @@ enum class IdType
Arch,
Reputation
};

enum class DamageMode
{
None,
PvE = 1 << 0,
PvP = 1 << 1,
All = PvE | PvP
};

NLOHMANN_JSON_SERIALIZE_ENUM(DamageMode, {
{DamageMode::None, 0},
{ DamageMode::PvE, "pve"},
{ DamageMode::PvP, "pvp"},
{ DamageMode::All, "all"},
});

enum class AllowedFormation
{
Alpha = 1,
Beta,
Gamma,
Delta,
Epsilon,
Zeta,
Theta,
Iota,
Kappa,
Lambda,
Omicron,
Sigma,
Omega,
Red,
Blue,
Gold,
Green,
Silver,
Black,
White,
Yellow,
Matsu,
Sakura,
Fuji,
Botan,
Hagi,
Susuki,
Kiku,
Yanagi
};

NLOHMANN_JSON_SERIALIZE_ENUM(AllowedFormation,
{
{ AllowedFormation::Alpha, "alpha"},
{ AllowedFormation::Beta, "beta"},
{ AllowedFormation::Gamma, "gamma"},
{ AllowedFormation::Delta, "delta"},
{AllowedFormation::Omicron, "omicron"},
{ AllowedFormation::Omega, "omega"},
{ AllowedFormation::Sigma, "sigma"},
{AllowedFormation::Epsilon, "epsilon"},
{ AllowedFormation::Zeta, "zeta"},
{ AllowedFormation::Theta, "theta"},
{ AllowedFormation::Kappa, "kappa"},
{ AllowedFormation::Lambda, "lambda"},
{ AllowedFormation::Iota, "iota"},
{ AllowedFormation::Red, "red"},
{ AllowedFormation::Blue, "blue"},
{ AllowedFormation::Gold, "gold"},
{ AllowedFormation::Green, "green"},
{ AllowedFormation::Silver, "silver"},
{ AllowedFormation::Black, "black"},
{ AllowedFormation::White, "white"},
{ AllowedFormation::Yellow, "yellow"},
{ AllowedFormation::Matsu, "matsu"},
{ AllowedFormation::Sakura, "sakura"},
{ AllowedFormation::Fuji, "fuji"},
{ AllowedFormation::Botan, "botan"},
{ AllowedFormation::Hagi, "hagi"},
{ AllowedFormation::Susuki, "susuki"},
{ AllowedFormation::Kiku, "kiku"},
{ AllowedFormation::Yanagi, "yanagi"},
})
31 changes: 23 additions & 8 deletions include/Defs/FLHookConfig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ struct DLL FLHookConfig final : Singleton<FLHookConfig>
//! Time of invulnerability upon undock in milliseconds.
//! Protected player can also not inflict any damage.
uint antiDockKill = 4000;
//! Number of milliseconds the player character remains in space after disconnecting.
uint antiF1 = 0;

//! The type of damage allowed on this server. Allowed values: 'All', 'None', 'PvP' and 'PvE'
DamageMode damageMode = DamageMode::All;

//! Disable the cruise disrupting effects.
bool changeCruiseDisruptorBehaviour = false;

Expand Down Expand Up @@ -52,14 +54,21 @@ struct DLL FLHookConfig final : Singleton<FLHookConfig>

std::vector<uint> noPVPSystemsHashed;

Serialize(General, antiDockKill, changeCruiseDisruptorBehaviour, damageMode, disableCharfileEncryption, disconnectDelay, disableNPCSpawns,
maxGroupSize, persistGroup, torpMissileBaseDamageMultiplier, tempBansEnabled, chatSuppressList, noPVPSystems);
};

struct AutoKicks final
{
//! Amount of time spent idly on a base resulting in a server kick, in seconds.
uint antiBaseIdle = 600;
//! Amount of time spent idly on character select screen resulting in a server kick, in seconds.
uint antiCharMenuIdle = 600;

Serialize(General, antiDockKill, antiF1, changeCruiseDisruptorBehaviour, disableCharfileEncryption, disconnectDelay, disableNPCSpawns,
maxGroupSize, persistGroup, torpMissileBaseDamageMultiplier, tempBansEnabled, chatSuppressList, noPVPSystems, antiBaseIdle,
antiCharMenuIdle);
//! Number of milliseconds the player character remains in space after disconnecting.
uint antiF1 = 0;

Serialize(AutoKicks, antiBaseIdle, antiCharMenuIdle, antiF1)
};

struct Plugins final
Expand Down Expand Up @@ -179,8 +188,13 @@ struct DLL FLHookConfig final : Singleton<FLHookConfig>
struct Callsign final
{
//! The mapping of numbers to formations. 1, min = Alpha. 29, max = Yanagi
std::vector<int> allowedFormations = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29
std::vector<AllowedFormation> allowedFormations = {
AllowedFormation::Alpha, AllowedFormation::Beta, AllowedFormation::Gamma, AllowedFormation::Delta, AllowedFormation::Epsilon,
AllowedFormation::Zeta, AllowedFormation::Theta, AllowedFormation::Iota, AllowedFormation::Kappa, AllowedFormation::Lambda,
AllowedFormation::Omicron, AllowedFormation::Sigma, AllowedFormation::Omega, AllowedFormation::Red, AllowedFormation::Blue,
AllowedFormation::Gold, AllowedFormation::Green, AllowedFormation::Silver, AllowedFormation::Black, AllowedFormation::White,
AllowedFormation::Yellow, AllowedFormation::Matsu, AllowedFormation::Sakura, AllowedFormation::Fuji, AllowedFormation::Botan,
AllowedFormation::Hagi, AllowedFormation::Susuki, AllowedFormation::Kiku, AllowedFormation::Yanagi
};

//! If true, formations and numbers will not be assigned to ships. All ships will be alpha 1-1.
Expand All @@ -194,12 +208,13 @@ struct DLL FLHookConfig final : Singleton<FLHookConfig>

Debug debug;
General general;
AutoKicks autoKicks;
Plugins plugins;
MessageQueue messageQueue;
UserCommands userCommands;
Bans bans;
ChatConfig chatConfig;
Callsign callsign;

Serialize(FLHookConfig, debug, general, plugins, messageQueue, userCommands, bans, chatConfig, callsign);
Serialize(FLHookConfig, debug, general, autoKicks, plugins, messageQueue, userCommands, bans, chatConfig, callsign);
};
1 change: 1 addition & 0 deletions include/PCH.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#define MAGIC_ENUM_USING_ALIAS_STRING_VIEW using string_view = std::wstring_view;
#define MAGIC_ENUM_USING_ALIAS_STRING using string = std::wstring;
#include <magic_enum.hpp>
#include <magic_enum_flags.hpp>

#include <nlohmann/json.hpp>

Expand Down
43 changes: 41 additions & 2 deletions source/Core/Commands/AdminCommandProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

#include "Core/Commands/AdminCommandProcessor.hpp"

#include "API/FLHook/ClientList.hpp"

// TODO: General, a lot of these functions are agnostic about whether or not the player is online and thus has a clientId, so along with the player database
// rework a lot of these functions need to be reworked to account for that.

Expand Down Expand Up @@ -378,6 +376,47 @@ std::wstring AdminCommandProcessor::Pull(std::wstring_view characterName)
return std::format(L"player {} pulled to {} at x={:.0f} y={:.0f} z={:.0f}", characterName, currentUser, pos.x, pos.y, pos.z);
}

std::wstring AdminCommandProcessor::SetDamageType(std::wstring_view newDamageType)
{
static std::wstring usage = L"Sets what can be damaged on the server. Valid values are 'None', 'All', PvP, 'PvE'.";
if (newDamageType.empty())
{
return usage;
}

auto* config = FLHookConfig::i();
const auto lower = StringUtils::ToLower(newDamageType);
if (lower == L"none")
{
config->general.damageMode = DamageMode::None;
Serializer::SaveToJson(*config, L"flhook.json");
return L"Set damage mode to None. No player ship can take damage, but NPCs can still hurt each other.";
}

if (lower == L"all")
{
config->general.damageMode = DamageMode::All;
Serializer::SaveToJson(*config, L"flhook.json");
return L"Set damage mode to All. All ships can take damage.";
}

if (lower == L"pvp")
{
config->general.damageMode = DamageMode::PvP;
Serializer::SaveToJson(*config, L"flhook.json");
return L"Set damage mode to PvP. Players can hurt players, and NPCs can hurt NPCs, but they cannot hurt each other.";
}

if (lower == L"pve")
{
config->general.damageMode = DamageMode::PvE;
Serializer::SaveToJson(*config, L"flhook.json");
return L"Set damage mode to PvE. Players cannot hurt each other, but can hurt and be hurt by NPCs.";
}

return usage;
}

// std::wstring AdminCommandProcessor::Move(std::wstring_view characterName, Vector position)
//{
// std::wstring targetPlayer;
Expand Down
8 changes: 4 additions & 4 deletions source/Core/Timers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,17 +96,17 @@ void FLHook::TimerCheckKick()
}

const auto* config = FLHookConfig::c();
if (config->general.antiBaseIdle)
if (config->autoKicks.antiBaseIdle)
{
// anti base-idle check
if (client.baseEnterTime && time - client.baseEnterTime >= config->general.antiBaseIdle)
if (client.baseEnterTime && time - client.baseEnterTime >= config->autoKicks.antiBaseIdle)
{
client.id.Kick(L"Base idling", 10);
client.baseEnterTime = 0;
}
}

if (config->general.antiCharMenuIdle)
if (config->autoKicks.antiCharMenuIdle)
{
// anti charmenu-idle check
if (!client.characterName.empty())
Expand All @@ -115,7 +115,7 @@ void FLHook::TimerCheckKick()
{
client.charMenuEnterTime = static_cast<uint>(time);
}
else if (time - client.charMenuEnterTime >= config->general.antiCharMenuIdle)
else if (time - client.charMenuEnterTime >= config->autoKicks.antiCharMenuIdle)
{
client.id.Kick();
client.charMenuEnterTime = 0;
Expand Down
7 changes: 5 additions & 2 deletions source/FLHook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ BOOL WINAPI DllMain([[maybe_unused]] const HINSTANCE& hinstDLL, [[maybe_unused]]
}

FLHook::FLHook()
: damageToClientId(0), damageToSpaceId(0), messagePrivate(false), messageSystem(false), messageUniverse(false), serverLoadInMs(0), playerCount(0),
disableNpcs(false), flhookReady(false)
: damageToClientId(0), messagePrivate(false), messageSystem(false), messageUniverse(false), serverLoadInMs(0), playerCount(0), disableNpcs(false),
flhookReady(false)
{
Logger::Init();
// Set module references
Expand Down Expand Up @@ -292,6 +292,9 @@ void FLHook::LoadSettings()
config->general.noPVPSystemsHashed.emplace_back(systemId);
}

// Resave to add any missing properties that have been added
Serializer::SaveToJson(*config, L"flhook.json");

// Explicitly replace the config
FLHookConfig::i(&config);
}
Expand Down
22 changes: 14 additions & 8 deletions source/Hooks/ClientServerInterface/Character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,23 @@ void IServerImplHook::CharacterSelectInnerAfter([[maybe_unused]] const CHARACTER
// Assign their random formation id.
// Numbers are between 0-20 (inclusive)
// Formations are between 1-29 (inclusive)
std::random_device dev;
std::mt19937 rng(dev());
static std::random_device dev;
static std::mt19937 rng(dev());
std::uniform_int_distribution<std::mt19937::result_type> distNum(1, 20);
const auto* conf = FLHookConfig::c();
std::uniform_int_distribution<std::mt19937::result_type> distForm(0, conf->callsign.allowedFormations.size() - 1);

if (conf->callsign.allowedFormations.empty())
{
info.formationTag = AllowedFormation::Alpha;
}
else
{
info.formationTag = conf->callsign.allowedFormations[distForm(rng)];
}

info.formationNumber1 = distNum(rng);
info.formationNumber2 = distNum(rng);
info.formationTag = conf->callsign.allowedFormations[distForm(rng)];
}
}
CatchHook({})
Expand Down Expand Up @@ -142,8 +150,7 @@ void __stdcall IServerImplHook::DestroyCharacter(const CHARACTER_ID& cid, Client

void __stdcall IServerImplHook::RequestRankLevel(ClientId client, uint unk1, int unk2)
{
Logger::Log(LogLevel::Trace,
std::format(L"RequestRankLevel(\n\tClientId client = {}\n\tuint unk1 = 0x{:08X}\n\tint unk2 = {}\n)", client, unk1, unk2));
Logger::Log(LogLevel::Trace, std::format(L"RequestRankLevel(\n\tClientId client = {}\n\tuint unk1 = 0x{:08X}\n\tint unk2 = {}\n)", client, unk1, unk2));

if (const auto skip = CallPlugins(&Plugin::OnRequestRankLevel, client, unk1, unk2); !skip)
{
Expand All @@ -156,8 +163,7 @@ void __stdcall IServerImplHook::RequestRankLevel(ClientId client, uint unk1, int

void __stdcall IServerImplHook::RequestPlayerStats(ClientId client, uint unk1, int unk2)
{
Logger::Log(LogLevel::Trace,
std::format(L"RequestPlayerStats(\n\tClientId client = {}\n\tuint unk1 = 0x{:08X}\n\tint unk2 = {}\n)", client, unk1, unk2));
Logger::Log(LogLevel::Trace, std::format(L"RequestPlayerStats(\n\tClientId client = {}\n\tuint unk1 = 0x{:08X}\n\tint unk2 = {}\n)", client, unk1, unk2));

if (const auto skip = CallPlugins(&Plugin::OnRequestPlayerStats, client, unk1, unk2); !skip)
{
Expand Down Expand Up @@ -185,7 +191,7 @@ bool IServerImplHook::CharacterInfoReqInner(ClientId client, bool)
if (shipId)
{
// in space
info.f1Time = TimeUtils::UnixTime<std::chrono::milliseconds>() + FLHookConfig::i()->general.antiF1;
info.f1Time = TimeUtils::UnixTime<std::chrono::milliseconds>() + FLHookConfig::i()->autoKicks.antiF1;
return false;
}
}
Expand Down
16 changes: 16 additions & 0 deletions source/Hooks/HkIEngineDamage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,13 @@ void __stdcall IEngineHook::AddDamageEntry(DamageList* dmgList, unsigned short s
return;
}

if (const auto damageMode = FLHookConfig::i()->general.damageMode;
!magic_enum::enum_flags_test(damageMode, DamageMode::PvE) && (dmgList->is_inflictor_a_player() && !FLHook::dmgToClient) ||
(!dmgList->is_inflictor_a_player() && FLHook::dmgToClient))
{
return;
}

// check if we got damaged by a cd with changed behaviour
if (dmgList->get_cause() == DamageCause::DummyDisrupter)
{
Expand Down Expand Up @@ -231,9 +238,18 @@ bool IEngineHook::AllowPlayerDamage(ClientId client, ClientId clientTarget)
}

const auto* config = FLHookConfig::c();
if (config->general.damageMode == DamageMode::None)
{
return false;
}

if (clientTarget)
{
if (!magic_enum::enum_flags_test(config->general.damageMode, DamageMode::PvP))
{
return false;
}

auto time = TimeUtils::UnixTime<std::chrono::milliseconds>();

// anti-dockkill check
Expand Down

0 comments on commit 0973299

Please sign in to comment.