mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-02 10:53:44 +00:00
feat: contraband list with flagging and optional removal
Staff list contraband items on a new dashboard page (item search, reason, flag or flag and remove; contraband_manage to edit, reports_view to see). World servers check every inventory when a character loads and every item a player receives: each find is an economy flag of the new kind Contraband, shown with the other flags and in the character's related data. Items marked for removal are taken away, with a character snapshot kept first so they can be given back, an audit entry and a mail or chat message telling the player why. Staff are skipped unless contraband_ignore_staff is off. Worlds reload the list when it changes (RELOAD_CONTRABAND, added at the end of ePlayerAction). Fixes #1563 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -99,6 +99,7 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(ILiveOps::Challenge, id, title, description,
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(ILiveOps::ChallengeTotal, total, contributors);
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(ILiveOps::Reward, challengeId, characterId, amount, coins, rewardedAt, claimedAt);
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(IFeaturedProperties::FeaturedSlot, templateId, mode, propertyId, updatedAt, updatedBy, zoneId);
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(IContraband::ContrabandItem, lot, reason, action, addedBy, addedAt);
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(IFeaturedProperties::FeaturedSettings, fullAuto, updatedAt, updatedBy);
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(IMessageCaptures::MessageCaptureSession, id, characterId, characterName, accountId, accountName, startedById, startedBy, startedAt, endsAt, endedAt, endReason, toServer, toClient, onlyMessages, skipMessages, zoneId, instanceId, cloneId, zones, messageCount, byteCount, dropped);
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(IMessageCaptures::MessageCaptureRecord, sessionId, seq, timeMs, direction, messageId, objectId, bits, droppedBefore, zoneId, instanceId, cloneId, payload, decoded);
|
||||
@@ -1395,6 +1396,22 @@ TEST_F(ParitySeeded, FeaturedProperties) {
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(ParitySeeded, Contraband) {
|
||||
Both("GetContrabandItems empty", [](GameDatabase& db) { return db.GetContrabandItems(); });
|
||||
Both("SetContrabandItem", [](GameDatabase& db) {
|
||||
db.SetContrabandItem({ 14128, "Atlantis Squid Helm", IContraband::eContrabandAction::REMOVE, "admin", 1700000000 });
|
||||
db.SetContrabandItem({ 6655, "Stig's Helmet", IContraband::eContrabandAction::FLAG, "admin", 1700000001 });
|
||||
db.SetContrabandItem({ 6655, "changed", IContraband::eContrabandAction::REMOVE, "mod", 1700000002 });
|
||||
return db.GetContrabandItems();
|
||||
});
|
||||
Both("DeleteContrabandItem", [](GameDatabase& db) { return json{ db.DeleteContrabandItem(14128), db.DeleteContrabandItem(14128), db.GetContrabandItems() }; });
|
||||
Both("Contraband economy flag", [](GameDatabase& db) {
|
||||
const bool first = db.InsertEconomyFlag({ 0, IDashboardAdmin::eFlagKind::CONTRABAND, CHAR_BOB, 6655, 1152921510000300001LL, 1, 1, "Removed at login" });
|
||||
const bool again = db.InsertEconomyFlag({ 0, IDashboardAdmin::eFlagKind::CONTRABAND, CHAR_BOB, 6655, 1152921510000300001LL, 1, 1, "Removed at login" });
|
||||
return json{ first, again, db.GetEconomyFlagsFor(CHAR_BOB, 5).size() };
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(ParitySeeded, MessageCaptures) {
|
||||
using Query = IMessageCaptures::SessionQuery;
|
||||
using eOrder = IMessageCaptures::eSessionOrder;
|
||||
|
||||
@@ -6,6 +6,7 @@ set(DGAMETEST_SOURCES
|
||||
"PlayerReportsLimitTests.cpp"
|
||||
"SlashCommandPermissionTests.cpp"
|
||||
"StaleSaveGuardTests.cpp"
|
||||
"ContrabandTests.cpp"
|
||||
)
|
||||
|
||||
add_subdirectory(dComponentsTests)
|
||||
|
||||
38
tests/dGameTests/ContrabandTests.cpp
Normal file
38
tests/dGameTests/ContrabandTests.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "Contraband.h"
|
||||
#include "eGameMasterLevel.h"
|
||||
|
||||
using Contraband::HeldItem;
|
||||
using eAction = IContraband::eContrabandAction;
|
||||
|
||||
TEST(ContrabandTests, FindsListedItemsOnly) {
|
||||
Contraband::List list{ { 14128, { "Atlantis Squid Helm", eAction::REMOVE } }, { 6655, { "Stig's Helmet", eAction::FLAG } } };
|
||||
const std::vector<HeldItem> items{
|
||||
{ 1, 6086, 1, eInventoryType::ITEMS },
|
||||
{ 2, 14128, 1, eInventoryType::VAULT_ITEMS },
|
||||
{ 3, 6655, 2, eInventoryType::ITEMS },
|
||||
{ 4, 6655, 0, eInventoryType::ITEMS }, // an empty stack is nothing
|
||||
};
|
||||
const auto found = Contraband::Find(items, list);
|
||||
ASSERT_EQ(found.size(), 2u);
|
||||
EXPECT_EQ(found[0].item.id, 2);
|
||||
EXPECT_EQ(found[0].entry.action, eAction::REMOVE);
|
||||
EXPECT_EQ(found[1].item.id, 3);
|
||||
EXPECT_EQ(found[1].entry.reason, "Stig's Helmet");
|
||||
EXPECT_TRUE(Contraband::Find(items, {}).empty());
|
||||
}
|
||||
|
||||
TEST(ContrabandTests, StaffAreSkippedUnlessConfigured) {
|
||||
EXPECT_TRUE(Contraband::Applies(eGameMasterLevel::CIVILIAN, true));
|
||||
EXPECT_FALSE(Contraband::Applies(eGameMasterLevel::MODERATOR, true));
|
||||
EXPECT_TRUE(Contraband::Applies(eGameMasterLevel::MODERATOR, false));
|
||||
}
|
||||
|
||||
TEST(ContrabandTests, OwnInventoryMovesAreNotNewItems) {
|
||||
EXPECT_TRUE(Contraband::CountsAsAdded(eLootSourceType::TRADE, eInventoryType::INVALID));
|
||||
EXPECT_TRUE(Contraband::CountsAsAdded(eLootSourceType::NONE, eInventoryType::INVALID));
|
||||
EXPECT_FALSE(Contraband::CountsAsAdded(eLootSourceType::NONE, eInventoryType::VAULT_ITEMS));
|
||||
EXPECT_FALSE(Contraband::CountsAsAdded(eLootSourceType::RELOCATE, eInventoryType::INVALID));
|
||||
EXPECT_FALSE(Contraband::CountsAsAdded(eLootSourceType::INVENTORY, eInventoryType::INVALID));
|
||||
}
|
||||
Reference in New Issue
Block a user