mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-10-10 01:18:07 +00:00

* feat: convert character ids to 64 bits remove all usages of the PERSISTENT bit with regards to storing of playerIDs on the server. the bit does not exist and was a phantom in the first place. Tested that a full playthrough of ag, ns and gf was still doable. slash commands work, ugc works, friends works, ignore list works, properties work and have names, teaming works. migrating an old mysql database works . need to test an old sqlite database * fix sqlite migration * remove nd specific column migration
340 lines
10 KiB
C++
340 lines
10 KiB
C++
#include "GMGreaterThanZeroCommands.h"
|
|
|
|
// Classes
|
|
#include "Character.h"
|
|
#include "ChatPackets.h"
|
|
#include "dServer.h"
|
|
#include "PlayerManager.h"
|
|
#include "User.h"
|
|
|
|
// Database
|
|
#include "Database.h"
|
|
|
|
// Components
|
|
#include "DestroyableComponent.h"
|
|
#include "PropertyManagementComponent.h"
|
|
|
|
// Enums
|
|
#include "MessageType/Chat.h"
|
|
#include "eServerDisconnectIdentifiers.h"
|
|
#include "eObjectBits.h"
|
|
|
|
namespace GMGreaterThanZeroCommands {
|
|
|
|
void Kick(Entity* entity, const SystemAddress& sysAddr, const std::string args) {
|
|
const auto splitArgs = GeneralUtils::SplitString(args, ' ');
|
|
if (splitArgs.size() == 1) {
|
|
auto* player = PlayerManager::GetPlayer(splitArgs[0]);
|
|
|
|
std::u16string username = GeneralUtils::UTF8ToUTF16(splitArgs[0]);
|
|
if (player == nullptr) {
|
|
ChatPackets::SendSystemMessage(sysAddr, u"Count not find player of name: " + username);
|
|
return;
|
|
}
|
|
|
|
Game::server->Disconnect(player->GetSystemAddress(), eServerDisconnectIdentifiers::KICK);
|
|
|
|
ChatPackets::SendSystemMessage(sysAddr, u"Kicked: " + username);
|
|
} else {
|
|
ChatPackets::SendSystemMessage(sysAddr, u"Correct usage: /kick <username>");
|
|
}
|
|
}
|
|
|
|
void Ban(Entity* entity, const SystemAddress& sysAddr, const std::string args) {
|
|
const auto splitArgs = GeneralUtils::SplitString(args, ' ');
|
|
|
|
if (splitArgs.size() == 1) {
|
|
auto* player = PlayerManager::GetPlayer(splitArgs[0]);
|
|
|
|
uint32_t accountId = 0;
|
|
|
|
if (player == nullptr) {
|
|
auto characterInfo = Database::Get()->GetCharacterInfo(splitArgs[0]);
|
|
|
|
if (characterInfo) {
|
|
accountId = characterInfo->accountId;
|
|
}
|
|
|
|
if (accountId == 0) {
|
|
ChatPackets::SendSystemMessage(sysAddr, u"Count not find player of name: " + GeneralUtils::UTF8ToUTF16(splitArgs[0]));
|
|
|
|
return;
|
|
}
|
|
} else {
|
|
auto* character = player->GetCharacter();
|
|
auto* user = character != nullptr ? character->GetParentUser() : nullptr;
|
|
if (user) accountId = user->GetAccountID();
|
|
}
|
|
|
|
if (accountId != 0) Database::Get()->UpdateAccountBan(accountId, true);
|
|
|
|
if (player != nullptr) {
|
|
Game::server->Disconnect(player->GetSystemAddress(), eServerDisconnectIdentifiers::FREE_TRIAL_EXPIRED);
|
|
}
|
|
|
|
ChatPackets::SendSystemMessage(sysAddr, u"Banned: " + GeneralUtils::ASCIIToUTF16(splitArgs[0]));
|
|
} else {
|
|
ChatPackets::SendSystemMessage(sysAddr, u"Correct usage: /ban <username>");
|
|
}
|
|
}
|
|
|
|
void MailItem(Entity* entity, const SystemAddress& sysAddr, const std::string args) {
|
|
const auto splitArgs = GeneralUtils::SplitString(args, ' ');
|
|
if (splitArgs.size() < 2) return;
|
|
|
|
const auto& playerName = splitArgs[0];
|
|
|
|
auto playerInfo = Database::Get()->GetCharacterInfo(playerName);
|
|
|
|
uint32_t receiverID = 0;
|
|
if (!playerInfo) {
|
|
ChatPackets::SendSystemMessage(sysAddr, u"Failed to find that player");
|
|
|
|
return;
|
|
}
|
|
|
|
receiverID = playerInfo->id;
|
|
|
|
const auto lot = GeneralUtils::TryParse<LOT>(splitArgs.at(1));
|
|
|
|
if (!lot) {
|
|
ChatPackets::SendSystemMessage(sysAddr, u"Invalid item lot.");
|
|
return;
|
|
}
|
|
|
|
MailInfo mailInsert;
|
|
mailInsert.senderId = entity->GetObjectID();
|
|
mailInsert.senderUsername = "Darkflame Universe";
|
|
mailInsert.receiverId = receiverID;
|
|
mailInsert.recipient = playerName;
|
|
mailInsert.subject = "Lost item";
|
|
mailInsert.body = "This is a replacement item for one you lost.";
|
|
mailInsert.itemID = LWOOBJID_EMPTY;
|
|
mailInsert.itemLOT = lot.value();
|
|
mailInsert.itemSubkey = LWOOBJID_EMPTY;
|
|
mailInsert.itemCount = 1;
|
|
Database::Get()->InsertNewMail(mailInsert);
|
|
|
|
ChatPackets::SendSystemMessage(sysAddr, u"Mail sent");
|
|
}
|
|
|
|
void ApproveProperty(Entity* entity, const SystemAddress& sysAddr, const std::string args) {
|
|
if (PropertyManagementComponent::Instance() != nullptr) {
|
|
PropertyManagementComponent::Instance()->UpdateApprovedStatus(true);
|
|
}
|
|
}
|
|
|
|
void Mute(Entity* entity, const SystemAddress& sysAddr, const std::string args) {
|
|
const auto splitArgs = GeneralUtils::SplitString(args, ' ');
|
|
|
|
if (splitArgs.size() >= 1) {
|
|
auto* player = PlayerManager::GetPlayer(splitArgs[0]);
|
|
|
|
uint32_t accountId = 0;
|
|
LWOOBJID characterId = 0;
|
|
|
|
if (player == nullptr) {
|
|
auto characterInfo = Database::Get()->GetCharacterInfo(splitArgs[0]);
|
|
|
|
if (characterInfo) {
|
|
accountId = characterInfo->accountId;
|
|
characterId = characterInfo->id;
|
|
|
|
GeneralUtils::SetBit(characterId, eObjectBits::CHARACTER);
|
|
}
|
|
|
|
if (accountId == 0) {
|
|
ChatPackets::SendSystemMessage(sysAddr, u"Count not find player of name: " + GeneralUtils::UTF8ToUTF16(splitArgs[0]));
|
|
|
|
return;
|
|
}
|
|
} else {
|
|
auto* character = player->GetCharacter();
|
|
auto* user = character != nullptr ? character->GetParentUser() : nullptr;
|
|
if (user) accountId = user->GetAccountID();
|
|
characterId = player->GetObjectID();
|
|
}
|
|
|
|
time_t expire = 1; // Default to indefinate mute
|
|
|
|
if (splitArgs.size() >= 2) {
|
|
const auto days = GeneralUtils::TryParse<uint32_t>(splitArgs[1]);
|
|
if (!days) {
|
|
ChatPackets::SendSystemMessage(sysAddr, u"Invalid days.");
|
|
|
|
return;
|
|
}
|
|
|
|
std::optional<uint32_t> hours;
|
|
if (splitArgs.size() >= 3) {
|
|
hours = GeneralUtils::TryParse<uint32_t>(splitArgs[2]);
|
|
if (!hours) {
|
|
ChatPackets::SendSystemMessage(sysAddr, u"Invalid hours.");
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
expire = time(NULL);
|
|
expire += 24 * 60 * 60 * days.value();
|
|
expire += 60 * 60 * hours.value_or(0);
|
|
}
|
|
|
|
if (accountId != 0) Database::Get()->UpdateAccountUnmuteTime(accountId, expire);
|
|
|
|
char buffer[32] = "brought up for review.\0";
|
|
|
|
if (expire != 1) {
|
|
std::tm* ptm = std::localtime(&expire);
|
|
// Format: Mo, 15.06.2009 20:20:00
|
|
std::strftime(buffer, 32, "%a, %d.%m.%Y %H:%M:%S", ptm);
|
|
}
|
|
|
|
const auto timeStr = GeneralUtils::ASCIIToUTF16(std::string(buffer));
|
|
|
|
ChatPackets::SendSystemMessage(sysAddr, u"Muted: " + GeneralUtils::UTF8ToUTF16(splitArgs[0]) + u" until " + timeStr);
|
|
|
|
//Notify chat about it
|
|
CBITSTREAM;
|
|
BitStreamUtils::WriteHeader(bitStream, ServiceType::CHAT, MessageType::Chat::GM_MUTE);
|
|
|
|
bitStream.Write(characterId);
|
|
bitStream.Write(expire);
|
|
|
|
Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false);
|
|
} else {
|
|
ChatPackets::SendSystemMessage(sysAddr, u"Correct usage: /mute <username> <days (optional)> <hours (optional)>");
|
|
}
|
|
}
|
|
|
|
void Fly(Entity* entity, const SystemAddress& sysAddr, const std::string args) {
|
|
const auto splitArgs = GeneralUtils::SplitString(args, ' ');
|
|
auto* character = entity->GetCharacter();
|
|
|
|
if (character) {
|
|
bool isFlying = character->GetIsFlying();
|
|
|
|
if (isFlying) {
|
|
GameMessages::SendSetJetPackMode(entity, false);
|
|
|
|
character->SetIsFlying(false);
|
|
} else {
|
|
float speedScale = 1.0f;
|
|
|
|
if (splitArgs.size() >= 1) {
|
|
const auto tempScaleStore = GeneralUtils::TryParse<float>(splitArgs.at(0));
|
|
|
|
if (tempScaleStore) {
|
|
speedScale = tempScaleStore.value();
|
|
} else {
|
|
ChatPackets::SendSystemMessage(sysAddr, u"Failed to parse speed scale argument.");
|
|
}
|
|
}
|
|
|
|
float airSpeed = 20 * speedScale;
|
|
float maxAirSpeed = 30 * speedScale;
|
|
float verticalVelocity = 1.5 * speedScale;
|
|
|
|
GameMessages::SendSetJetPackMode(entity, true, true, false, 167, airSpeed, maxAirSpeed, verticalVelocity);
|
|
|
|
character->SetIsFlying(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
void AttackImmune(Entity* entity, const SystemAddress& sysAddr, const std::string args) {
|
|
const auto splitArgs = GeneralUtils::SplitString(args, ' ');
|
|
if (splitArgs.empty()) return;
|
|
|
|
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
|
|
|
|
const auto state = GeneralUtils::TryParse<int32_t>(splitArgs[0]);
|
|
|
|
if (!state) {
|
|
ChatPackets::SendSystemMessage(sysAddr, u"Invalid state.");
|
|
return;
|
|
}
|
|
|
|
if (destroyableComponent) destroyableComponent->SetIsImmune(state.value());
|
|
}
|
|
|
|
void GmImmune(Entity* entity, const SystemAddress& sysAddr, const std::string args) {
|
|
const auto splitArgs = GeneralUtils::SplitString(args, ' ');
|
|
if (splitArgs.empty()) return;
|
|
|
|
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
|
|
|
|
const auto state = GeneralUtils::TryParse<int32_t>(splitArgs[0]);
|
|
|
|
if (!state) {
|
|
ChatPackets::SendSystemMessage(sysAddr, u"Invalid state.");
|
|
return;
|
|
}
|
|
|
|
if (destroyableComponent) destroyableComponent->SetIsGMImmune(state.value());
|
|
}
|
|
|
|
void GmInvis(Entity* entity, const SystemAddress& sysAddr, const std::string args) {
|
|
GameMessages::SendToggleGMInvis(entity->GetObjectID(), true, UNASSIGNED_SYSTEM_ADDRESS);
|
|
}
|
|
|
|
void SetName(Entity* entity, const SystemAddress& sysAddr, const std::string args) {
|
|
GameMessages::SendSetName(entity->GetObjectID(), GeneralUtils::UTF8ToUTF16(args), UNASSIGNED_SYSTEM_ADDRESS);
|
|
}
|
|
|
|
void Title(Entity* entity, const SystemAddress& sysAddr, const std::string args) {
|
|
std::string name = entity->GetCharacter()->GetName() + " - " + args;
|
|
GameMessages::SendSetName(entity->GetObjectID(), GeneralUtils::UTF8ToUTF16(name), UNASSIGNED_SYSTEM_ADDRESS);
|
|
}
|
|
|
|
void ShowAll(Entity* entity, const SystemAddress& sysAddr, const std::string args) {
|
|
bool displayZoneData = true;
|
|
bool displayIndividualPlayers = true;
|
|
const auto splitArgs = GeneralUtils::SplitString(args, ' ');
|
|
|
|
if (!splitArgs.empty() && !splitArgs.at(0).empty()) displayZoneData = splitArgs.at(0) == "1";
|
|
if (splitArgs.size() > 1) displayIndividualPlayers = splitArgs.at(1) == "1";
|
|
|
|
ShowAllRequest request {
|
|
.requestor = entity->GetObjectID(),
|
|
.displayZoneData = displayZoneData,
|
|
.displayIndividualPlayers = displayIndividualPlayers
|
|
};
|
|
|
|
CBITSTREAM;
|
|
request.Serialize(bitStream);
|
|
Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false);
|
|
}
|
|
|
|
void FindPlayer(Entity* entity, const SystemAddress& sysAddr, const std::string args) {
|
|
if (args.empty()) {
|
|
GameMessages::SendSlashCommandFeedbackText(entity, u"No player Given");
|
|
return;
|
|
}
|
|
|
|
FindPlayerRequest request {
|
|
.requestor = entity->GetObjectID(),
|
|
.playerName = LUWString(args)
|
|
};
|
|
|
|
CBITSTREAM;
|
|
request.Serialize(bitStream);
|
|
Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false);
|
|
}
|
|
|
|
void Spectate(Entity* entity, const SystemAddress& sysAddr, const std::string args) {
|
|
if (args.empty()) {
|
|
GameMessages::SendForceCameraTargetCycle(entity, false, eCameraTargetCyclingMode::DISALLOW_CYCLING, entity->GetObjectID());
|
|
return;
|
|
}
|
|
|
|
auto player = PlayerManager::GetPlayer(args);
|
|
if (!player) {
|
|
GameMessages::SendSlashCommandFeedbackText(entity, u"Player not found");
|
|
return;
|
|
}
|
|
GameMessages::SendSlashCommandFeedbackText(entity, u"Spectating Player");
|
|
GameMessages::SendForceCameraTargetCycle(entity, false, eCameraTargetCyclingMode::DISALLOW_CYCLING, player->GetObjectID());
|
|
}
|
|
}
|