Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add audit trail to Destroy, TryRemoveFromInventory, TryDequipObject #3888

Draft
wants to merge 39 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
18b7576
Add audit trail to Destroy, TryRemoveFromInventory, TryDequipObject
LtRipley36706 Aug 10, 2022
9aba635
Update Container.cs
LtRipley36706 Aug 10, 2022
d36f56d
Update Creature_Equipment.cs
LtRipley36706 Aug 10, 2022
dc4ae6a
Update WorldObject.cs
LtRipley36706 Aug 10, 2022
b6b876a
Update WorldObject.cs
LtRipley36706 Aug 10, 2022
60554fb
Update WorldObject.cs
LtRipley36706 Aug 11, 2022
a43092e
Update WorldObject.cs
LtRipley36706 Aug 11, 2022
6428b7f
Update WorldObject.cs
LtRipley36706 Aug 11, 2022
55316c2
Update WorldObject.cs
LtRipley36706 Aug 11, 2022
c997697
Update WorldObject.cs
LtRipley36706 Aug 11, 2022
3a74be7
Update WorldObject.cs
LtRipley36706 Aug 11, 2022
a1fe96a
Update WorldObject.cs
LtRipley36706 Aug 12, 2022
9363ead
Update WorldObject.cs
LtRipley36706 Aug 12, 2022
dec6237
lots o' changes
LtRipley36706 Aug 19, 2022
a1aae16
.
LtRipley36706 Aug 19, 2022
07a8143
add option to destroy failed spawns
LtRipley36706 Aug 21, 2022
6aa5b86
Merge branch 'master' into itemaudit
LtRipley36706 Aug 22, 2022
94fa841
Update ShardDatabaseOfflineTools.cs
LtRipley36706 Aug 29, 2022
2223f6f
Update DeveloperFixCommands.cs
LtRipley36706 Aug 29, 2022
509ce73
Update PropertyManager.cs
LtRipley36706 Aug 29, 2022
cfb2368
Update Program.cs
LtRipley36706 Aug 29, 2022
f8ad27f
Update WorldObject.cs
LtRipley36706 Aug 29, 2022
5332e52
Merge branch 'master' into itemaudit
LtRipley36706 Aug 29, 2022
04fc0d8
Merge branch 'master' into itemaudit
LtRipley36706 Aug 31, 2022
a957cc2
Update ShardDatabaseOfflineTools.cs
LtRipley36706 Aug 31, 2022
cc3d8de
Update WorldObject.cs
LtRipley36706 Aug 31, 2022
4321d9e
Merge branch 'master' into itemaudit
LtRipley36706 Sep 24, 2022
33e6055
Update ShardDatabaseOfflineTools.cs
LtRipley36706 Sep 24, 2022
7ef4b57
Merge branch 'master' into itemaudit
LtRipley36706 Oct 19, 2022
7413a17
Merge branch 'master' into itemaudit
LtRipley36706 Nov 29, 2022
00e579f
Merge branch 'master' into itemaudit
LtRipley36706 Dec 14, 2022
54c400e
Merge branch 'master' into itemaudit
LtRipley36706 Dec 28, 2022
5558795
Merge branch 'master' into itemaudit
LtRipley36706 Dec 29, 2022
751cd15
Merge branch 'master' into itemaudit
LtRipley36706 Mar 30, 2023
7d9e9d7
Merge branch 'master' into itemaudit
LtRipley36706 Apr 21, 2023
ed5a471
Merge branch 'master' into itemaudit
LtRipley36706 Jun 10, 2023
44a18d2
Merge branch 'master' into itemaudit
LtRipley36706 Feb 5, 2024
3cf2357
Update OfflineConfiguration.cs
LtRipley36706 Feb 5, 2024
9fa3437
Update OfflineConfiguration.cs
LtRipley36706 Feb 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions Source/ACE.Common/OfflineConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ namespace ACE.Common
public class OfflineConfiguration
{
/// <summary>
/// Purge characters that have been deleted longer than PruneDeletedCharactersDays
/// These characters, and their associated biotas, will be deleted permanantly!
/// Purge characters that have been deleted longer than PurgeDeletedCharactersDays
/// These characters, and their associated biotas, will be deleted permanently!
/// </summary>
public bool PurgeDeletedCharacters { get; set; } = false;

Expand All @@ -25,6 +25,17 @@ public class OfflineConfiguration
/// </summary>
public bool PurgeOrphanedBiotas { get; set; } = false;

/// <summary>
/// Purge biota that have been deleted longer than PurgeReleasedBiotasDays
/// These biota will be deleted permanently!
/// </summary>
public bool PurgeReleasedBiotas { get; set; } = false;

/// <summary>
/// Number of days a biota must have been deleted for before eligible for purging
/// </summary>
public int PurgeReleasedBiotasDays { get; set; } = 30;

/// <summary>
/// Prune deleted characters from all friend lists
/// </summary>
Expand Down
7 changes: 5 additions & 2 deletions Source/ACE.Database/ShardDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,11 @@ public uint GetMaxGuidFoundInRange(uint min, uint max)
" JOIN biota" + Environment.NewLine +
" WHERE id > " + min + Environment.NewLine +
" ORDER BY id" + Environment.NewLine +
" ) AS z" + Environment.NewLine +
"WHERE z.gap_ends_at_not_inclusive!=0 AND @available_ids<" + limitAvailableIDsReturned + "; ";
" ) AS z" + Environment.NewLine;
if (limitAvailableIDsReturned != uint.MaxValue)
sql += "WHERE z.gap_ends_at_not_inclusive!=0 AND @available_ids<" + limitAvailableIDsReturned + "; ";
else
sql += "WHERE z.gap_ends_at_not_inclusive!=0;";

using (var context = new ShardDbContext())
{
Expand Down
61 changes: 59 additions & 2 deletions Source/ACE.Database/ShardDatabaseOfflineTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ public static void PurgeOrphanedBiotasInParallel(ShardDbContext context, out int

HashSet<uint> playerBiotaIds = null;
HashSet<uint> characterIds = null;
HashSet<uint> releasedIds = null;

Dictionary<uint, WeenieType> biotas = null;
Dictionary<uint, BiotaPropertiesIID> containerPointers = null;
Expand Down Expand Up @@ -428,6 +429,9 @@ from c in combined.DefaultIfEmpty()
});
}

context.Database.SetCommandTimeout(900);
releasedIds = context.BiotaPropertiesFloat.AsNoTracking().Where(r => r.Type == (ushort)PropertyFloat.ReleasedTimestamp).Select(r => r.ObjectId).ToHashSet();

// Purge contained items that belong to a parent container that no longer exists
{
// select * from biota_properties_i_i_d iid left join biota on biota.id=iid.`value` where iid.`type`=2 and biota.id is null;
Expand Down Expand Up @@ -460,7 +464,7 @@ from b in combined.DefaultIfEmpty()

Parallel.ForEach(results, ConfigManager.Config.Server.Threading.DatabaseParallelOptions, result =>
{
if (PurgeBiota(result.ObjectId, "Parent container not found"))
if (!releasedIds.Contains(result.ObjectId) && PurgeBiota(result.ObjectId, "Parent container not found"))
Interlocked.Increment(ref totalNumberOfBiotasPurged);
});

Expand Down Expand Up @@ -498,7 +502,7 @@ from b in combined.DefaultIfEmpty()

Parallel.ForEach(results, ConfigManager.Config.Server.Threading.DatabaseParallelOptions, result =>
{
if (PurgeBiota(result.ObjectId, "Parent wielder not found"))
if (!releasedIds.Contains(result.ObjectId) && PurgeBiota(result.ObjectId, "Parent wielder not found"))
Interlocked.Increment(ref totalNumberOfBiotasPurged);
});

Expand All @@ -512,6 +516,10 @@ from b in combined.DefaultIfEmpty()

foreach (var kvp in biotas)
{
// exclude released objects
if (releasedIds.Contains(kvp.Key))
continue;

// exclude allegiances
if (kvp.Value == WeenieType.Allegiance)
continue;
Expand Down Expand Up @@ -919,6 +927,55 @@ public static void PurgeOrphanedBiotasInParallel(out int numberOfBiotasPurged)
PurgeOrphanedBiotasInParallel(context, out numberOfBiotasPurged);
}

public static void PurgeReleasedBiotasInParallel(ShardDbContext context, int daysLimiter, out int numberOfBiotasPurged)
{
var deleteLimit = Time.GetUnixTime(DateTime.UtcNow.AddDays(-daysLimiter));

context.Database.SetCommandTimeout(900);

var releasedIds = context.BiotaPropertiesFloat.AsNoTracking().Where(r => r.Type == (ushort)PropertyFloat.ReleasedTimestamp && r.Value <= deleteLimit).Select(r => new { r.ObjectId, r.Value }).AsEnumerable().Select(r => (Id: r.ObjectId, ReleasedTimestamp: r.Value)).ToHashSet();

int biotaPurgedTotal = 0;

Parallel.ForEach(releasedIds, ConfigManager.Config.Server.Threading.DatabaseParallelOptions, result =>
{
if (PurgeBiota(result.Id, $"Released on {Time.GetDateTimeFromTimestamp(result.ReleasedTimestamp).ToLocalTime()} which is older than {daysLimiter} days"))
Interlocked.Increment(ref biotaPurgedTotal);
});

numberOfBiotasPurged = biotaPurgedTotal;
}

public static void PurgeDoDBiotasInParallel(out int numberOfBiotasPurged)
{
using (var context = new ShardDbContext())
{
context.Database.SetCommandTimeout(900);
PurgeDoDBiotasInParallel(context, out numberOfBiotasPurged);
}
}

public static void PurgeDoDBiotasInParallel(ShardDbContext context, out int numberOfBiotasPurged)
{
var destroyedIds = context.BiotaPropertiesInt.AsNoTracking().Where(r => r.Type == (ushort)PropertyInt.Bonded && r.Value == (int)BondedStatus.Destroy).Select(r => r.ObjectId).ToHashSet();

int biotaPurgedTotal = 0;

Parallel.ForEach(destroyedIds, ConfigManager.Config.Server.Threading.DatabaseParallelOptions, result =>
{
if (PurgeBiota(result, $"Biota has BondedStatus.Destroy"))
Interlocked.Increment(ref biotaPurgedTotal);
});

numberOfBiotasPurged = biotaPurgedTotal;
}

public static void PurgeReleasedBiotasInParallel(int daysLimiter, out int numberOfBiotasPurged)
{
using (var context = new ShardDbContext())
PurgeReleasedBiotasInParallel(context, daysLimiter, out numberOfBiotasPurged);
}

/// <summary>
/// This is temporary and can be removed in the near future, 2020-04-05 Mag-nus
/// </summary>
Expand Down
5 changes: 4 additions & 1 deletion Source/ACE.Entity/Enum/Properties/PositionType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,9 @@ public enum PositionType : ushort
TeleportedCharacter = 27,

[ServerOnly]
PCAPRecordedLocation = 8040
PCAPRecordedLocation = 8040,

[ServerOnly]
PreDestroyLocation = 9000
}
}
10 changes: 10 additions & 0 deletions Source/ACE.Entity/Enum/Properties/PropertyString.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,16 @@ public enum PropertyString : ushort
GodState = 9006,
[ServerOnly]
TinkerLog = 9007,
[ServerOnly]
DestroyStackLog = 9008,
[ServerOnly]
PreviousOwners = 9009,
[ServerOnly]
PreviousWielders = 9010,
[ServerOnly]
PreviousOwnerStackLog = 9011,
[ServerOnly]
PreviousWielderStackLog = 9012,
}

public static class PropertyStringExtensions
Expand Down
13 changes: 10 additions & 3 deletions Source/ACE.Server/Config.js.docker
Original file line number Diff line number Diff line change
Expand Up @@ -179,14 +179,21 @@
// This section can trigger events that may happen before the world starts up, or after it shuts down
// The shard should be in a disconnected state from any running ACE world
"Offline": {
// Purge characters that have been deleted longer than PruneDeletedCharactersDays
// These characters, and their associated biotas, will be deleted permanantly!
// Purge characters that have been deleted longer than PurgeDeletedCharactersDays
// These characters, and their associated biotas, will be deleted permanently!
"PurgeDeletedCharacters": false,

// Number of days a character must have been deleted for before eligible for purging
"PurgeDeletedCharactersDays": 30,

// This will purge biotas that are completely disconnected from the world
// Purge biotas that have been released longer than PurgeReleasedBiotasDays
// These biotas (World Objects) will be deleted permanently!
"PurgeReleasedBiotas": false,

// Number of days a biota must have been released for before eligible for purging
"PurgeReleasedBiotasDays": 30,

// This will purge biotas that are completely disconnected from the world, excluding biotas marked as released
// These may have been items that were never deleted properly, items that were given to the town crier before delete was implemented, etc...
// This can be time consuming so it's not something you would have set to true for every server startup. You might run this once every few months
"PurgeOrphanedBiotas": false,
Expand Down
13 changes: 10 additions & 3 deletions Source/ACE.Server/Config.js.example
Original file line number Diff line number Diff line change
Expand Up @@ -177,14 +177,21 @@
// This section can trigger events that may happen before the world starts up, or after it shuts down
// The shard should be in a disconnected state from any running ACE world
"Offline": {
// Purge characters that have been deleted longer than PruneDeletedCharactersDays
// These characters, and their associated biotas, will be deleted permanantly!
// Purge characters that have been deleted longer than PurgeDeletedCharactersDays
// These characters, and their associated biotas, will be deleted permanently!
"PurgeDeletedCharacters": false,

// Number of days a character must have been deleted for before eligible for purging
"PurgeDeletedCharactersDays": 30,

// This will purge biotas that are completely disconnected from the world
// Purge biotas that have been released longer than PurgeReleasedBiotasDays
// These biotas (World Objects) will be deleted permanently!
"PurgeReleasedBiotas": false,

// Number of days a biota must have been released for before eligible for purging
"PurgeReleasedBiotasDays": 30,

// This will purge biotas that are completely disconnected from the world, excluding biotas marked as released
// These may have been items that were never deleted properly, items that were given to the town crier before delete was implemented, etc...
// This can be time consuming so it's not something you would have set to true for every server startup. You might run this once every few months
"PurgeOrphanedBiotas": false,
Expand Down
5 changes: 5 additions & 0 deletions Source/ACE.Server/Entity/Landblock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -874,6 +874,11 @@ private bool AddWorldObjectInternal(WorldObject wo)
else if (wo.ProjectileTarget == null && !(wo is SpellProjectile))
log.Warn($"AddWorldObjectInternal: couldn't spawn 0x{wo.Guid}:{wo.Name} [{wo.WeenieClassId} - {wo.WeenieType}] at {wo.Location.ToLOCString()}");

if (PropertyManager.GetBool("landblock_destroys_failed_unstuck_spawns").Item && wo is not Creature && !wo.Stuck && wo.Generator is null)
{
wo.Destroy();
}

return false;
}
}
Expand Down
6 changes: 3 additions & 3 deletions Source/ACE.Server/Managers/GuidManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ private class DynamicGuidAllocator
private bool useSequenceGapExhaustedMessageDisplayed;
private LinkedList<(uint start, uint end)> availableIDs = new LinkedList<(uint start, uint end)>();

public DynamicGuidAllocator(uint min, uint max, string name)
public DynamicGuidAllocator(uint min, uint max, string name, bool unlimitedGaps)
{
this.max = max;

Expand Down Expand Up @@ -164,7 +164,7 @@ public DynamicGuidAllocator(uint min, uint max, string name)
lock (this)
{
bool done = false;
Database.DatabaseManager.Shard.GetSequenceGaps(ObjectGuid.DynamicMin, limitAvailableIDsReturnedInGetSequenceGaps, gaps =>
Database.DatabaseManager.Shard.GetSequenceGaps(ObjectGuid.DynamicMin, unlimitedGaps ? uint.MaxValue : limitAvailableIDsReturnedInGetSequenceGaps, gaps =>
{
lock (this)
{
Expand Down Expand Up @@ -294,7 +294,7 @@ public override string ToString()
public static void Initialize()
{
playerAlloc = new PlayerGuidAllocator(ObjectGuid.PlayerMin, ObjectGuid.PlayerMax, "player");
dynamicAlloc = new DynamicGuidAllocator(ObjectGuid.DynamicMin, ObjectGuid.DynamicMax, "dynamic");
dynamicAlloc = new DynamicGuidAllocator(ObjectGuid.DynamicMin, ObjectGuid.DynamicMax, "dynamic", PropertyManager.GetBool("unlimited_sequence_gaps").Item);
}

/// <summary>
Expand Down
8 changes: 8 additions & 0 deletions Source/ACE.Server/Managers/PropertyManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,7 @@ public static void LoadDefaultProperties()
("craft_exact_msg", new Property<bool>(false, "If TRUE, and player has crafting chance of success dialog enabled, shows them an additional message in their chat window with exact %")),
("creature_name_check", new Property<bool>(true, "if enabled, creature names in world database restricts player names during character creation")),
("creatures_drop_createlist_wield", new Property<bool>(false, "If FALSE then Wielded items in CreateList will not drop. Retail defaulted to TRUE but there are currently data errors")),
("destroy_deletes_from_database", new Property<bool>(true, "when an item is destroyed, if it was stored in database it will be immediately deleted")),
("equipmentsetid_enabled", new Property<bool>(true, "enable this to allow adding EquipmentSetIDs to loot armor")),
("equipmentsetid_name_decoration", new Property<bool>(false, "enable this to add the EquipmentSet name to loot armor name")),
("fastbuff", new Property<bool>(true, "If TRUE, enables the fast buffing trick from retail.")),
Expand All @@ -567,6 +568,7 @@ public static void LoadDefaultProperties()
("house_rent_enabled", new Property<bool>(true, "If FALSE then rent is not required")),
("iou_trades", new Property<bool>(false, "(non-retail function) If enabled, IOUs can be traded for objects that are missing in DB but added/restored later on")),
("item_dispel", new Property<bool>(false, "if enabled, allows players to dispel items. defaults to end of retail, where item dispels could only target creatures")),
("landblock_destroys_failed_unstuck_spawns", new Property<bool>(false, "if enabled, any unmanaged/uncontrolled unstuck object that fails to spawn on a landblock will be destroyed")),
("legacy_loot_system", new Property<bool>(false, "use the previous iteration of the ace lootgen system")),
("lifestone_broadcast_death", new Property<bool>(true, "if true, player deaths are additionally broadcast to other players standing near the destination lifestone")),
("loot_quality_mod", new Property<bool>(true, "if FALSE then the loot quality modifier of a Death Treasure profile does not affect loot generation")),
Expand All @@ -586,6 +588,10 @@ public static void LoadDefaultProperties()
("rares_real_time", new Property<bool>(true, "allow for second chance roll based on an rng seeded timestamp for a rare on rare eligible kills that do not generate a rare, rares_max_seconds_between defines maximum seconds before second chance kicks in")),
("rares_real_time_v2", new Property<bool>(false, "chances for a rare to be generated on rare eligible kills are modified by the last time one was found per each player, rares_max_days_between defines maximum days before guaranteed rare generation")),
("runrate_add_hooks", new Property<bool>(false, "if TRUE, adds some runrate hooks that were missing from retail (exhaustion done, raise skill/attribute")),
("record_destroy_stacktrace", new Property<bool>(false, "logs stack trace when object is destroyed")),
("record_dequip_stacktrace", new Property<bool>(false, "logs stack trace when object is dequiped")),
("record_remove_stacktrace", new Property<bool>(false, "logs stack trace when object is removed")),
("recycle_guids", new Property<bool>(true, "allows dynamic objects guids to be recycled")),
("reportbug_enabled", new Property<bool>(false, "toggles the /reportbug player command")),
("require_spell_comps", new Property<bool>(true, "if FALSE, spell components are no longer required to be in inventory to cast spells. defaults to enabled, as in retail")),
("safe_spell_comps", new Property<bool>(false, "if TRUE, disables spell component burning for everyone")),
Expand All @@ -605,6 +611,7 @@ public static void LoadDefaultProperties()
("trajectory_alt_solver", new Property<bool>(false, "use the alternate trajectory solver for missiles and spell projectiles")),
("universal_masteries", new Property<bool>(true, "if TRUE, matches end of retail masteries - players wielding almost any weapon get +5 DR, except if the weapon \"seems tough to master\". " +
"if FALSE, players start with mastery of 1 melee and 1 ranged weapon type based on heritage, and can later re-select these 2 masteries")),
("unlimited_sequence_gaps", new Property<bool>(false, "upon startup, allows server to find all unused guids in a range instead of a set hard limit")),
("use_generator_rotation_offset", new Property<bool>(true, "enables or disables using the generator's current rotation when offseting relative positions")),
("use_turbine_chat", new Property<bool>(true, "enables or disables global chat channels (General, LFG, Roleplay, Trade, Olthoi, Society, Allegience)")),
("use_wield_requirements", new Property<bool>(true, "disable this to bypass wield requirements. mostly for dev debugging")),
Expand All @@ -621,6 +628,7 @@ public static void LoadDefaultProperties()
("chat_requires_player_level", new Property<long>(0, "the level a player is required to have for global chat privileges")),
("corpse_spam_limit", new Property<long>(15, "the number of corpses a player is allowed to leave on a landblock at one time")),
("default_subscription_level", new Property<long>(1, "retail defaults to 1, 1 = standard subscription (same as 2 and 3), 4 grants ToD pre-order bonus item Asheron's Benediction")),
("destroy_saves_older_than_seconds", new Property<long>(86400, "the amount of time in seconds a destroyed object, which is not Stuck, must have existed for before it is worth saving from immediate destruction. Object can then later be purged via startup database maintanence")),
("fellowship_even_share_level", new Property<long>(50, "level when fellowship XP sharing is no longer restricted")),
("mansion_min_rank", new Property<long>(6, "overrides the default allegiance rank required to own a mansion")),
("max_chars_per_account", new Property<long>(11, "retail defaults to 11, client supports up to 20")),
Expand Down
Loading