refactor: Change TryParse implementation (#1442)

* Changed how the TryParse function works (and also did some general cleanup along the way)

* Update noexcept attributes (verified these are correct)

* Add fp overload for MacOS functionality

* resolving some feedback

* Split out unrelated changes to CleanupRoundup branch

* Update in response to feedback

* the consequences of emo's member variable renaming request

* Revert "the consequences of emo's member variable renaming request"

This reverts commit bf318caeda.

* Fully revert renaming attempt

* Revert "the consequences of emo's member variable renaming request"

This reverts commit bf318caeda.

Fully revert renaming attempt

* Created ClientVersion.h and moved the client version defaults to it

* Fix partial parsing and MacOS floating point errors

* attempting fix to MacOS compiler error

* syntax pass (should be the last commit unless the CI fails)

* ah, wait, forgot to uncomment the preprocessor statements for MacOS. THIS should be the last commit pending CI

* Okay, one last thing I noticed: We were including C headers here. Now they're C++ headers. Pinky swear this is it!

* typo and I am OCD. please let this be the last

* hash is usally but not always noexcept, so the specifier should go

* Address MOST of the feedback

* address the claim codes issue
This commit is contained in:
jadebenn
2024-02-10 05:05:25 -06:00
committed by GitHub
parent 62b670d283
commit 0c1ee0513d
33 changed files with 463 additions and 453 deletions

View File

@@ -40,10 +40,8 @@ Precondition::Precondition(const uint32_t condition) {
std::string token;
while (std::getline(stream, token, ',')) {
uint32_t value;
if (GeneralUtils::TryParse(token, value)) {
this->values.push_back(value);
}
const auto validToken = GeneralUtils::TryParse<uint32_t>(token);
if (validToken) this->values.push_back(validToken.value());
}
}

View File

@@ -113,13 +113,13 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
if ((chatCommand == "setgmlevel" || chatCommand == "makegm" || chatCommand == "gmlevel") && user->GetMaxGMLevel() > eGameMasterLevel::CIVILIAN) {
if (args.size() != 1) return;
uint32_t level_intermed = 0;
const auto level_intermed = GeneralUtils::TryParse<uint32_t>(args[0]);
if (!GeneralUtils::TryParse(args[0], level_intermed)) {
if (!level_intermed) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid gm level.");
return;
}
eGameMasterLevel level = static_cast<eGameMasterLevel>(level_intermed);
eGameMasterLevel level = static_cast<eGameMasterLevel>(level_intermed.value());
#ifndef DEVELOPER_SERVER
if (user->GetMaxGMLevel() == eGameMasterLevel::JUNIOR_DEVELOPER) {
@@ -378,26 +378,27 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
}
if (chatCommand == "resetmission" && args.size() >= 1 && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
uint32_t missionId;
if (!GeneralUtils::TryParse(args[0], missionId)) {
const auto missionId = GeneralUtils::TryParse<uint32_t>(args[0]);
if (!missionId) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid mission ID.");
return;
}
auto* missionComponent = entity->GetComponent<MissionComponent>();
if (!missionComponent) return;
missionComponent->ResetMission(missionId);
missionComponent->ResetMission(missionId.value());
}
// Log command to database
Database::Get()->InsertSlashCommandUsage(entity->GetObjectID(), chatCommand);
if (chatCommand == "setminifig" && args.size() == 2 && entity->GetGMLevel() >= eGameMasterLevel::FORUM_MODERATOR) { // could break characters so only allow if GM > 0
int32_t minifigItemId;
if (!GeneralUtils::TryParse(args[1], minifigItemId)) {
const auto minifigItemIdExists = GeneralUtils::TryParse<int32_t>(args[1]);
if (!minifigItemIdExists) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid Minifig Item Id ID.");
return;
}
const int32_t minifigItemId = minifigItemIdExists.value();
Game::entityManager->DestructEntity(entity, sysAddr);
auto* charComp = entity->GetComponent<CharacterComponent>();
std::string lowerName = args[0];
@@ -457,14 +458,14 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
}
if (chatCommand == "unlock-emote" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
int32_t emoteID;
const auto emoteID = GeneralUtils::TryParse<int32_t>(args.at(0));
if (!GeneralUtils::TryParse(args[0], emoteID)) {
if (!emoteID) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid emote ID.");
return;
}
entity->GetCharacter()->UnlockEmote(emoteID);
entity->GetCharacter()->UnlockEmote(emoteID.value());
}
if (chatCommand == "force-save" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
@@ -486,19 +487,19 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
}
if (chatCommand == "speedboost" && args.size() == 1 && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
float boost;
if (!GeneralUtils::TryParse(args[0], boost)) {
const auto boostOptional = GeneralUtils::TryParse<float>(args[0]);
if (!boostOptional) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid boost.");
return;
}
const float boost = boostOptional.value();
auto* controllablePhysicsComponent = entity->GetComponent<ControllablePhysicsComponent>();
if (!controllablePhysicsComponent) return;
controllablePhysicsComponent->SetSpeedMultiplier(boost);
// speedboost possesables
// speedboost possessables
auto possessor = entity->GetComponent<PossessorComponent>();
if (possessor) {
auto possessedID = possessor->GetPossessable();
@@ -527,14 +528,14 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
}
if (chatCommand == "setcontrolscheme" && args.size() == 1 && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
uint32_t scheme;
const auto scheme = GeneralUtils::TryParse<uint32_t>(args[0]);
if (!GeneralUtils::TryParse(args[0], scheme)) {
if (!scheme) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid control scheme.");
return;
}
GameMessages::SendSetPlayerControlScheme(entity, static_cast<eControlScheme>(scheme));
GameMessages::SendSetPlayerControlScheme(entity, static_cast<eControlScheme>(scheme.value()));
ChatPackets::SendSystemMessage(sysAddr, u"Switched control scheme.");
return;
@@ -574,29 +575,28 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
}
if ((chatCommand == "setinventorysize" || chatCommand == "setinvsize") && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 1) {
uint32_t size;
if (!GeneralUtils::TryParse(args.at(0), size)) {
const auto sizeOptional = GeneralUtils::TryParse<uint32_t>(args[0]);
if (!sizeOptional) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid size.");
return;
}
const uint32_t size = sizeOptional.value();
eInventoryType selectedInventory = eInventoryType::ITEMS;
// a possible inventory was provided if we got more than 1 argument
if (args.size() >= 2) {
selectedInventory = eInventoryType::INVALID;
if (!GeneralUtils::TryParse(args.at(1), selectedInventory)) {
selectedInventory = GeneralUtils::TryParse<eInventoryType>(args.at(1)).value_or(eInventoryType::INVALID);
if (selectedInventory == eInventoryType::INVALID) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid inventory.");
return;
} else {
// In this case, we treat the input as a string and try to find it in the reflection list
std::transform(args.at(1).begin(), args.at(1).end(), args.at(1).begin(), ::toupper);
for (uint32_t index = 0; index < NUMBER_OF_INVENTORIES; index++) {
if (std::string_view(args.at(1)) == std::string_view(InventoryType::InventoryTypeToString(static_cast<eInventoryType>(index)))) selectedInventory = static_cast<eInventoryType>(index);
}
}
if (selectedInventory == eInventoryType::INVALID) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid inventory.");
return;
}
ChatPackets::SendSystemMessage(sysAddr, u"Setting inventory " +
GeneralUtils::ASCIIToUTF16(args.at(1)) +
@@ -643,48 +643,48 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
if (chatCommand == "addmission" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
if (args.size() == 0) return;
uint32_t missionID;
const auto missionID = GeneralUtils::TryParse<uint32_t>(args.at(0));
if (!GeneralUtils::TryParse(args[0], missionID)) {
if (!missionID) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid mission id.");
return;
}
auto comp = static_cast<MissionComponent*>(entity->GetComponent(eReplicaComponentType::MISSION));
if (comp) comp->AcceptMission(missionID, true);
if (comp) comp->AcceptMission(missionID.value(), true);
return;
}
if (chatCommand == "completemission" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
if (args.size() == 0) return;
uint32_t missionID;
const auto missionID = GeneralUtils::TryParse<uint32_t>(args.at(0));
if (!GeneralUtils::TryParse(args[0], missionID)) {
if (!missionID) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid mission id.");
return;
}
auto comp = static_cast<MissionComponent*>(entity->GetComponent(eReplicaComponentType::MISSION));
if (comp) comp->CompleteMission(missionID, true);
if (comp) comp->CompleteMission(missionID.value(), true);
return;
}
if (chatCommand == "setflag" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() == 1) {
int32_t flagId;
const auto flagId = GeneralUtils::TryParse<int32_t>(args.at(0));
if (!GeneralUtils::TryParse(args[0], flagId)) {
if (!flagId) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid flag id.");
return;
}
entity->GetCharacter()->SetPlayerFlag(flagId, true);
entity->GetCharacter()->SetPlayerFlag(flagId.value(), true);
}
if (chatCommand == "setflag" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() == 2) {
int32_t flagId;
std::string onOffFlag = args[0];
if (!GeneralUtils::TryParse(args[1], flagId)) {
const auto flagId = GeneralUtils::TryParse<int32_t>(args.at(1));
std::string onOffFlag = args.at(0);
if (!flagId) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid flag id.");
return;
}
@@ -692,28 +692,26 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
ChatPackets::SendSystemMessage(sysAddr, u"Invalid flag type.");
return;
}
entity->GetCharacter()->SetPlayerFlag(flagId, onOffFlag == "on");
entity->GetCharacter()->SetPlayerFlag(flagId.value(), onOffFlag == "on");
}
if (chatCommand == "clearflag" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() == 1) {
int32_t flagId;
const auto flagId = GeneralUtils::TryParse<int32_t>(args.at(0));
if (!GeneralUtils::TryParse(args[0], flagId)) {
if (!flagId) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid flag id.");
return;
}
entity->GetCharacter()->SetPlayerFlag(flagId, false);
entity->GetCharacter()->SetPlayerFlag(flagId.value(), false);
}
if (chatCommand == "playeffect" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 3) {
int32_t effectID = 0;
const auto effectID = GeneralUtils::TryParse<int32_t>(args.at(0));
if (!GeneralUtils::TryParse(args[0], effectID)) {
return;
}
if (!effectID) return;
// FIXME: use fallible ASCIIToUTF16 conversion, because non-ascii isn't valid anyway
GameMessages::SendPlayFXEffect(entity->GetObjectID(), effectID, GeneralUtils::ASCIIToUTF16(args[1]), args[2]);
GameMessages::SendPlayFXEffect(entity->GetObjectID(), effectID.value(), GeneralUtils::ASCIIToUTF16(args.at(1)), args.at(2));
}
if (chatCommand == "stopeffect" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 1) {
@@ -775,34 +773,32 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
if (chatCommand == "gmadditem" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
if (args.size() == 1) {
uint32_t itemLOT;
const auto itemLOT = GeneralUtils::TryParse<uint32_t>(args.at(0));
if (!GeneralUtils::TryParse(args[0], itemLOT)) {
if (!itemLOT) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid item LOT.");
return;
}
InventoryComponent* inventory = static_cast<InventoryComponent*>(entity->GetComponent(eReplicaComponentType::INVENTORY));
inventory->AddItem(itemLOT, 1, eLootSourceType::MODERATION);
inventory->AddItem(itemLOT.value(), 1, eLootSourceType::MODERATION);
} else if (args.size() == 2) {
uint32_t itemLOT;
if (!GeneralUtils::TryParse(args[0], itemLOT)) {
const auto itemLOT = GeneralUtils::TryParse<uint32_t>(args.at(0));
if (!itemLOT) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid item LOT.");
return;
}
uint32_t count;
if (!GeneralUtils::TryParse(args[1], count)) {
const auto count = GeneralUtils::TryParse<uint32_t>(args.at(1));
if (!count) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid item count.");
return;
}
InventoryComponent* inventory = static_cast<InventoryComponent*>(entity->GetComponent(eReplicaComponentType::INVENTORY));
inventory->AddItem(itemLOT, count, eLootSourceType::MODERATION);
inventory->AddItem(itemLOT.value(), count.value(), eLootSourceType::MODERATION);
} else {
ChatPackets::SendSystemMessage(sysAddr, u"Correct usage: /gmadditem <lot>");
}
@@ -822,9 +818,9 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
receiverID = playerInfo->id;
LOT lot;
const auto lot = GeneralUtils::TryParse<LOT>(args.at(1));
if (!GeneralUtils::TryParse(args[1], lot)) {
if (!lot) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid item lot.");
return;
}
@@ -837,7 +833,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
mailInsert.subject = "Lost item";
mailInsert.body = "This is a replacement item for one you lost.";
mailInsert.itemID = LWOOBJID_EMPTY;
mailInsert.itemLOT = lot;
mailInsert.itemLOT = lot.value();
mailInsert.itemSubkey = LWOOBJID_EMPTY;
mailInsert.itemCount = 1;
Database::Get()->InsertNewMail(mailInsert);
@@ -871,46 +867,47 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
NiPoint3 pos{};
if (args.size() == 3) {
float x, y, z;
if (!GeneralUtils::TryParse(args[0], x)) {
const auto x = GeneralUtils::TryParse<float>(args.at(0));
if (!x) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid x.");
return;
}
if (!GeneralUtils::TryParse(args[1], y)) {
const auto y = GeneralUtils::TryParse<float>(args.at(1));
if (!y) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid y.");
return;
}
if (!GeneralUtils::TryParse(args[2], z)) {
const auto z = GeneralUtils::TryParse<float>(args.at(2));
if (!z) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid z.");
return;
}
pos.SetX(x);
pos.SetY(y);
pos.SetZ(z);
pos.SetX(x.value());
pos.SetY(y.value());
pos.SetZ(z.value());
LOG("Teleporting objectID: %llu to %f, %f, %f", entity->GetObjectID(), pos.x, pos.y, pos.z);
GameMessages::SendTeleport(entity->GetObjectID(), pos, NiQuaternion(), sysAddr);
} else if (args.size() == 2) {
float x, z;
if (!GeneralUtils::TryParse(args[0], x)) {
const auto x = GeneralUtils::TryParse<float>(args.at(0));
if (!x) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid x.");
return;
}
if (!GeneralUtils::TryParse(args[1], z)) {
const auto z = GeneralUtils::TryParse<float>(args.at(1));
if (!z) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid z.");
return;
}
pos.SetX(x);
pos.SetX(x.value());
pos.SetY(0.0f);
pos.SetZ(z);
pos.SetZ(z.value());
LOG("Teleporting objectID: %llu to X: %f, Z: %f", entity->GetObjectID(), pos.x, pos.z);
GameMessages::SendTeleport(entity->GetObjectID(), pos, NiQuaternion(), sysAddr);
@@ -970,10 +967,10 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
float speedScale = 1.0f;
if (args.size() >= 1) {
float tempScaleStore;
const auto tempScaleStore = GeneralUtils::TryParse<float>(args.at(0));
if (GeneralUtils::TryParse<float>(args[0], tempScaleStore)) {
speedScale = tempScaleStore;
if (tempScaleStore) {
speedScale = tempScaleStore.value();
} else {
ChatPackets::SendSystemMessage(sysAddr, u"Failed to parse speed scale argument.");
}
@@ -1025,16 +1022,17 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
time_t expire = 1; // Default to indefinate mute
if (args.size() >= 2) {
uint32_t days = 0;
uint32_t hours = 0;
if (!GeneralUtils::TryParse(args[1], days)) {
const auto days = GeneralUtils::TryParse<uint32_t>(args[1]);
if (!days) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid days.");
return;
}
std::optional<uint32_t> hours;
if (args.size() >= 3) {
if (!GeneralUtils::TryParse(args[2], hours)) {
hours = GeneralUtils::TryParse<uint32_t>(args[2]);
if (!hours) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid hours.");
return;
@@ -1042,8 +1040,8 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
}
expire = time(NULL);
expire += 24 * 60 * 60 * days;
expire += 60 * 60 * hours;
expire += 24 * 60 * 60 * days.value();
expire += 60 * 60 * hours.value_or(0);
}
if (accountId != 0) Database::Get()->UpdateAccountUnmuteTime(accountId, expire);
@@ -1143,14 +1141,14 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
}
if (chatCommand == "startcelebration" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() == 1) {
int32_t celebration;
const auto celebration = GeneralUtils::TryParse<int32_t>(args.at(0));
if (!GeneralUtils::TryParse(args[0], celebration)) {
if (!celebration) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid celebration.");
return;
}
GameMessages::SendStartCelebrationEffect(entity, entity->GetSystemAddress(), celebration);
GameMessages::SendStartCelebrationEffect(entity, entity->GetSystemAddress(), celebration.value());
}
if (chatCommand == "buffmed" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
@@ -1204,15 +1202,15 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
ControllablePhysicsComponent* comp = static_cast<ControllablePhysicsComponent*>(entity->GetComponent(eReplicaComponentType::CONTROLLABLE_PHYSICS));
if (!comp) return;
uint32_t lot;
const auto lot = GeneralUtils::TryParse<uint32_t>(args[0]);
if (!GeneralUtils::TryParse(args[0], lot)) {
if (!lot) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid lot.");
return;
}
EntityInfo info;
info.lot = lot;
info.lot = lot.value();
info.pos = comp->GetPosition();
info.rot = comp->GetRotation();
info.spawner = nullptr;
@@ -1233,28 +1231,29 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
auto controllablePhysicsComponent = entity->GetComponent<ControllablePhysicsComponent>();
if (!controllablePhysicsComponent) return;
LOT lot{};
uint32_t numberToSpawn{};
float radiusToSpawnWithin{};
if (!GeneralUtils::TryParse(args[0], lot)) {
const auto lot = GeneralUtils::TryParse<LOT>(args[0]);
if (!lot) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid lot.");
return;
}
if (!GeneralUtils::TryParse(args[1], numberToSpawn) && numberToSpawn > 0) {
const auto numberToSpawnOptional = GeneralUtils::TryParse<uint32_t>(args[1]);
if (!numberToSpawnOptional && numberToSpawnOptional.value() > 0) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid number of enemies to spawn.");
return;
}
uint32_t numberToSpawn = numberToSpawnOptional.value();
// Must spawn within a radius of at least 0.0f
if (!GeneralUtils::TryParse(args[2], radiusToSpawnWithin) && radiusToSpawnWithin < 0.0f) {
const auto radiusToSpawnWithinOptional = GeneralUtils::TryParse<float>(args[2]);
if (!radiusToSpawnWithinOptional && radiusToSpawnWithinOptional.value() < 0.0f) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid radius to spawn within.");
return;
}
const float radiusToSpawnWithin = radiusToSpawnWithinOptional.value();
EntityInfo info;
info.lot = lot;
info.lot = lot.value();
info.spawner = nullptr;
info.spawnerID = entity->GetObjectID();
info.spawnerNodeID = 0;
@@ -1281,12 +1280,12 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
}
if ((chatCommand == "giveuscore") && args.size() >= 1 && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
int32_t uscore;
if (!GeneralUtils::TryParse(args[0], uscore)) {
const auto uscoreOptional = GeneralUtils::TryParse<int32_t>(args[0]);
if (!uscoreOptional) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid uscore.");
return;
}
const int32_t uscore = uscoreOptional.value();
CharacterComponent* character = entity->GetComponent<CharacterComponent>();
if (character) character->SetUScore(character->GetUScore() + uscore);
@@ -1294,9 +1293,9 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
eLootSourceType lootType = eLootSourceType::MODERATION;
int32_t type;
if (args.size() >= 2 && GeneralUtils::TryParse(args[1], type)) {
lootType = static_cast<eLootSourceType>(type);
if (args.size() >= 2) {
const auto type = GeneralUtils::TryParse<eLootSourceType>(args[1]);
lootType = type.value_or(lootType);
}
GameMessages::SendModifyLEGOScore(entity, entity->GetSystemAddress(), uscore, lootType);
@@ -1322,14 +1321,15 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
entity = requestedPlayer->GetOwner();
}
uint32_t requestedLevel;
const auto requestedLevelOptional = GeneralUtils::TryParse<uint32_t>(args[0]);
uint32_t oldLevel;
// first check the level is valid
if (!GeneralUtils::TryParse(args[0], requestedLevel)) {
// first check the level is valid
if (!requestedLevelOptional) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid level.");
return;
}
uint32_t requestedLevel = requestedLevelOptional.value();
// query to set our uscore to the correct value for this level
auto characterComponent = entity->GetComponent<CharacterComponent>();
@@ -1402,27 +1402,27 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
}
if ((chatCommand == "freemoney" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) && args.size() == 1) {
int64_t money;
const auto money = GeneralUtils::TryParse<int64_t>(args[0]);
if (!GeneralUtils::TryParse(args[0], money)) {
if (!money) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid money.");
return;
}
auto* ch = entity->GetCharacter();
ch->SetCoins(ch->GetCoins() + money, eLootSourceType::MODERATION);
ch->SetCoins(ch->GetCoins() + money.value(), eLootSourceType::MODERATION);
}
if ((chatCommand == "setcurrency") && args.size() == 1 && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
int32_t money;
const auto money = GeneralUtils::TryParse<int64_t>(args[0]);
if (!GeneralUtils::TryParse(args[0], money)) {
if (!money) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid money.");
return;
}
auto* ch = entity->GetCharacter();
ch->SetCoins(money, eLootSourceType::MODERATION);
ch->SetCoins(money.value(), eLootSourceType::MODERATION);
}
// Allow for this on even while not a GM, as it sometimes toggles incorrrectly.
@@ -1435,17 +1435,14 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
if (chatCommand == "gmimmune" && args.size() >= 1 && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
int32_t state = false;
const auto state = GeneralUtils::TryParse<int32_t>(args[0]);
if (!GeneralUtils::TryParse(args[0], state)) {
if (!state) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid state.");
return;
}
if (destroyableComponent != nullptr) {
destroyableComponent->SetIsGMImmune(state);
}
if (destroyableComponent) destroyableComponent->SetIsGMImmune(state.value());
return;
}
@@ -1453,53 +1450,47 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
if (chatCommand == "attackimmune" && args.size() >= 1 && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
int32_t state = false;
const auto state = GeneralUtils::TryParse<int32_t>(args[0]);
if (!GeneralUtils::TryParse(args[0], state)) {
if (!state) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid state.");
return;
}
if (destroyableComponent != nullptr) {
destroyableComponent->SetIsImmune(state);
}
if (destroyableComponent) destroyableComponent->SetIsImmune(state.value());
return;
}
if (chatCommand == "buff" && args.size() >= 2 && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
auto* buffComponent = entity->GetComponent<BuffComponent>();
int32_t id = 0;
int32_t duration = 0;
if (!GeneralUtils::TryParse(args[0], id)) {
const auto id = GeneralUtils::TryParse<int32_t>(args[0]);
if (!id) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid buff id.");
return;
}
if (!GeneralUtils::TryParse(args[1], duration)) {
const auto duration = GeneralUtils::TryParse<int32_t>(args[1]);
if (!duration) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid buff duration.");
return;
}
if (buffComponent != nullptr) {
buffComponent->ApplyBuff(id, duration, entity->GetObjectID());
}
if (buffComponent) buffComponent->ApplyBuff(id.value(), duration.value(), entity->GetObjectID());
return;
}
if ((chatCommand == "testmap" && args.size() >= 1) && entity->GetGMLevel() >= eGameMasterLevel::FORUM_MODERATOR) {
ChatPackets::SendSystemMessage(sysAddr, u"Requesting map change...");
uint32_t reqZone;
LWOCLONEID cloneId = 0;
bool force = false;
if (!GeneralUtils::TryParse(args[0], reqZone)) {
const auto reqZoneOptional = GeneralUtils::TryParse<LWOMAPID>(args[0]);
if (!reqZoneOptional) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid zone.");
return;
}
const LWOMAPID reqZone = reqZoneOptional.value();
if (args.size() > 1) {
auto index = 1;
@@ -1510,9 +1501,13 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
force = true;
}
if (args.size() > index && !GeneralUtils::TryParse(args[index], cloneId)) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid clone id.");
return;
if (args.size() > index) {
const auto cloneIdOptional = GeneralUtils::TryParse<LWOCLONEID>(args[index]);
if (!cloneIdOptional) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid clone id.");
return;
}
cloneId = cloneIdOptional.value();
}
}
@@ -1550,23 +1545,21 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
}
if (chatCommand == "createprivate" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 3) {
uint32_t zone;
if (!GeneralUtils::TryParse(args[0], zone)) {
const auto zone = GeneralUtils::TryParse<uint32_t>(args[0]);
if (!zone) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid zone.");
return;
}
uint32_t clone;
if (!GeneralUtils::TryParse(args[1], clone)) {
const auto clone = GeneralUtils::TryParse<uint32_t>(args[1]);
if (!clone) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid clone.");
return;
}
const auto& password = args[2];
ZoneInstanceManager::Instance()->CreatePrivateZone(Game::server, zone, clone, password);
ZoneInstanceManager::Instance()->CreatePrivateZone(Game::server, zone.value(), clone.value(), password);
ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16("Sent request for private zone with password: " + password));
@@ -1593,14 +1586,14 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
}
if (args.size() >= 1) {
float time;
const auto time = GeneralUtils::TryParse<float>(args[0]);
if (!GeneralUtils::TryParse(args[0], time)) {
if (!time) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid boost time.");
return;
} else {
GameMessages::SendVehicleAddPassiveBoostAction(vehicle->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS);
entity->AddCallbackTimer(time, [vehicle]() {
entity->AddCallbackTimer(time.value(), [vehicle]() {
if (!vehicle) return;
GameMessages::SendVehicleRemovePassiveBoostAction(vehicle->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS);
});
@@ -1676,20 +1669,19 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
}
if (chatCommand == "reforge" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 2) {
LOT baseItem;
LOT reforgedItem;
const auto baseItem = GeneralUtils::TryParse<LOT>(args[0]);
if (!baseItem) return;
if (!GeneralUtils::TryParse(args[0], baseItem)) return;
if (!GeneralUtils::TryParse(args[1], reforgedItem)) return;
const auto reforgedItem = GeneralUtils::TryParse<LOT>(args[1]);
if (!reforgedItem) return;
auto* inventoryComponent = entity->GetComponent<InventoryComponent>();
if (inventoryComponent == nullptr) return;
if (!inventoryComponent) return;
std::vector<LDFBaseData*> data{};
data.push_back(new LDFData<int32_t>(u"reforgedLOT", reforgedItem));
data.push_back(new LDFData<int32_t>(u"reforgedLOT", reforgedItem.value()));
inventoryComponent->AddItem(baseItem, 1, eLootSourceType::MODERATION, eInventoryType::INVALID, data);
inventoryComponent->AddItem(baseItem.value(), 1, eLootSourceType::MODERATION, eInventoryType::INVALID, data);
}
if (chatCommand == "crash" && entity->GetGMLevel() >= eGameMasterLevel::OPERATOR) {
@@ -1743,8 +1735,8 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
VanityUtilities::SpawnVanity();
dpWorld::Reload();
auto entities = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::SCRIPTED_ACTIVITY);
for (auto entity : entities) {
auto* scriptedActivityComponent = entity->GetComponent<ScriptedActivityComponent>();
for (const auto* const entity : entities) {
auto* const scriptedActivityComponent = entity->GetComponent<ScriptedActivityComponent>();
if (!scriptedActivityComponent) continue;
scriptedActivityComponent->ReloadConfig();
@@ -1755,19 +1747,20 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
}
if (chatCommand == "rollloot" && entity->GetGMLevel() >= eGameMasterLevel::OPERATOR && args.size() >= 3) {
uint32_t lootMatrixIndex = 0;
uint32_t targetLot = 0;
uint32_t loops = 1;
const auto lootMatrixIndex = GeneralUtils::TryParse<uint32_t>(args[0]);
if (!lootMatrixIndex) return;
if (!GeneralUtils::TryParse(args[0], lootMatrixIndex)) return;
if (!GeneralUtils::TryParse(args[1], targetLot)) return;
if (!GeneralUtils::TryParse(args[2], loops)) return;
const auto targetLot = GeneralUtils::TryParse<uint32_t>(args[1]);
if (!targetLot) return;
const auto loops = GeneralUtils::TryParse<uint32_t>(args[2]);
if (!loops) return;
uint64_t totalRuns = 0;
for (uint32_t i = 0; i < loops; i++) {
while (true) {
auto lootRoll = Loot::RollLootMatrix(lootMatrixIndex);
auto lootRoll = Loot::RollLootMatrix(lootMatrixIndex.value());
totalRuns += 1;
bool doBreak = false;
for (const auto& kv : lootRoll) {
@@ -1780,26 +1773,30 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
}
std::u16string message = u"Ran loot drops looking for "
+ GeneralUtils::to_u16string(targetLot)
+ GeneralUtils::to_u16string(targetLot.value())
+ u", "
+ GeneralUtils::to_u16string(loops)
+ GeneralUtils::to_u16string(loops.value())
+ u" times. It ran "
+ GeneralUtils::to_u16string(totalRuns)
+ u" times. Averaging out at "
+ GeneralUtils::to_u16string(static_cast<float>(totalRuns) / loops);
+ GeneralUtils::to_u16string(static_cast<float>(totalRuns) / loops.value());
ChatPackets::SendSystemMessage(sysAddr, message);
}
if (chatCommand == "deleteinven" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 1) {
eInventoryType inventoryType = eInventoryType::INVALID;
if (!GeneralUtils::TryParse(args[0], inventoryType)) {
const auto inventoryTypeOptional = GeneralUtils::TryParse<eInventoryType>(args[0]);
if (!inventoryTypeOptional) {
// In this case, we treat the input as a string and try to find it in the reflection list
std::transform(args[0].begin(), args[0].end(), args[0].begin(), ::toupper);
LOG("looking for inventory %s", args[0].c_str());
for (uint32_t index = 0; index < NUMBER_OF_INVENTORIES; index++) {
if (std::string_view(args[0]) == std::string_view(InventoryType::InventoryTypeToString(static_cast<eInventoryType>(index)))) inventoryType = static_cast<eInventoryType>(index);
}
} else {
inventoryType = inventoryTypeOptional.value();
}
if (inventoryType == eInventoryType::INVALID || inventoryType >= NUMBER_OF_INVENTORIES) {
@@ -1821,32 +1818,32 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
if (chatCommand == "castskill" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 1) {
auto* skillComponent = entity->GetComponent<SkillComponent>();
if (skillComponent) {
uint32_t skillId;
const auto skillId = GeneralUtils::TryParse<uint32_t>(args[0]);
if (!GeneralUtils::TryParse(args[0], skillId)) {
if (!skillId) {
ChatPackets::SendSystemMessage(sysAddr, u"Error getting skill ID.");
return;
} else {
skillComponent->CastSkill(skillId, entity->GetObjectID(), entity->GetObjectID());
skillComponent->CastSkill(skillId.value(), entity->GetObjectID(), entity->GetObjectID());
ChatPackets::SendSystemMessage(sysAddr, u"Cast skill");
}
}
}
if (chatCommand == "setskillslot" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 2) {
uint32_t skillId;
int slot;
auto* inventoryComponent = entity->GetComponent<InventoryComponent>();
auto* const inventoryComponent = entity->GetComponent<InventoryComponent>();
if (inventoryComponent) {
if (!GeneralUtils::TryParse(args[0], slot)) {
const auto slot = GeneralUtils::TryParse<BehaviorSlot>(args[0]);
if (!slot) {
ChatPackets::SendSystemMessage(sysAddr, u"Error getting slot.");
return;
} else {
if (!GeneralUtils::TryParse(args[1], skillId)) {
const auto skillId = GeneralUtils::TryParse<uint32_t>(args[1]);
if (!skillId) {
ChatPackets::SendSystemMessage(sysAddr, u"Error getting skill.");
return;
} else {
if (inventoryComponent->SetSkill(slot, skillId)) ChatPackets::SendSystemMessage(sysAddr, u"Set skill to slot successfully");
if (inventoryComponent->SetSkill(slot.value(), skillId.value())) ChatPackets::SendSystemMessage(sysAddr, u"Set skill to slot successfully");
else ChatPackets::SendSystemMessage(sysAddr, u"Set skill to slot failed");
}
}
@@ -1856,13 +1853,13 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
if (chatCommand == "setfaction" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 1) {
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
if (destroyableComponent) {
int32_t faction;
const auto faction = GeneralUtils::TryParse<int32_t>(args[0]);
if (!GeneralUtils::TryParse(args[0], faction)) {
if (!faction) {
ChatPackets::SendSystemMessage(sysAddr, u"Error getting faction.");
return;
} else {
destroyableComponent->SetFaction(faction);
destroyableComponent->SetFaction(faction.value());
ChatPackets::SendSystemMessage(sysAddr, u"Set faction and updated enemies list");
}
}
@@ -1871,13 +1868,13 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
if (chatCommand == "addfaction" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 1) {
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
if (destroyableComponent) {
int32_t faction;
const auto faction = GeneralUtils::TryParse<int32_t>(args[0]);
if (!GeneralUtils::TryParse(args[0], faction)) {
if (!faction) {
ChatPackets::SendSystemMessage(sysAddr, u"Error getting faction.");
return;
} else {
destroyableComponent->AddFaction(faction);
destroyableComponent->AddFaction(faction.value());
ChatPackets::SendSystemMessage(sysAddr, u"Added faction and updated enemies list");
}
}
@@ -1908,13 +1905,12 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
if (chatCommand == "inspect" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 1) {
Entity* closest = nullptr;
eReplicaComponentType component;
std::u16string ldf;
bool isLDF = false;
if (!GeneralUtils::TryParse(args[0], component)) {
auto component = GeneralUtils::TryParse<eReplicaComponentType>(args[0]);
if (!component) {
component = eReplicaComponentType::INVALID;
ldf = GeneralUtils::UTF8ToUTF16(args[0]);
@@ -1926,7 +1922,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
auto closestDistance = 0.0f;
const auto candidates = Game::entityManager->GetEntitiesByComponent(component);
const auto candidates = Game::entityManager->GetEntitiesByComponent(component.value());
for (auto* candidate : candidates) {
if (candidate->GetLOT() == 1 || candidate->GetLOT() == 8092) {
@@ -1937,7 +1933,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
continue;
}
if (closest == nullptr) {
if (!closest) {
closest = candidate;
closestDistance = NiPoint3::Distance(candidate->GetPosition(), reference);
@@ -1954,9 +1950,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
}
}
if (closest == nullptr) {
return;
}
if (!closest) return;
Game::entityManager->SerializeEntity(closest);
@@ -1982,20 +1976,18 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
if (args.size() >= 2) {
if (args[1] == "-m" && args.size() >= 3) {
auto* movingPlatformComponent = closest->GetComponent<MovingPlatformComponent>();
auto* const movingPlatformComponent = closest->GetComponent<MovingPlatformComponent>();
int32_t value = 0;
const auto mValue = GeneralUtils::TryParse<int32_t>(args[2]);
if (movingPlatformComponent == nullptr || !GeneralUtils::TryParse(args[2], value)) {
return;
}
if (!movingPlatformComponent || !mValue) return;
movingPlatformComponent->SetSerialized(true);
if (value == -1) {
if (mValue == -1) {
movingPlatformComponent->StopPathing();
} else {
movingPlatformComponent->GotoWaypoint(value);
movingPlatformComponent->GotoWaypoint(mValue.value());
}
Game::entityManager->SerializeEntity(closest);
@@ -2036,13 +2028,11 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
}
if (args.size() >= 3) {
int32_t faction;
if (!GeneralUtils::TryParse(args[2], faction)) {
return;
}
const auto faction = GeneralUtils::TryParse<int32_t>(args[2]);
if (!faction) return;
destuctable->SetFaction(-1);
destuctable->AddFaction(faction, true);
destuctable->AddFaction(faction.value(), true);
}
} else if (args[1] == "-cf") {
auto* destuctable = entity->GetComponent<DestroyableComponent>();