Skip to content

Commit

Permalink
fix: Fixes duping containers and removes copying private setter prope…
Browse files Browse the repository at this point in the history
…rties (#1816)

### Summary
- Removes copying private setters
- Fixes duping containers
- Adds public `Dupe.DoDupe` functions for external scripts to hook into the existing logic.
  • Loading branch information
kamronbatman authored Jun 3, 2024
1 parent c69d16a commit 0b802db
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 65 deletions.
8 changes: 7 additions & 1 deletion Projects/Server/Items/Item.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3381,9 +3381,15 @@ public static void CopyProperties(Item src, Item dest)
continue;
}

var setMethod = p.GetSetMethod(false);

try
{
p.SetValue(dest, p.GetValue(src, null), null);
// Do not copy private properties
if (setMethod != null)
{
p.SetValue(dest, p.GetValue(src, null), null);
}
}
catch
{
Expand Down
2 changes: 2 additions & 0 deletions Projects/Server/Mobiles/Mobile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -865,10 +865,12 @@ public ContextMenu ContextMenu
}
}

[IgnoreDupe]
public bool Pushing { get; set; }

public virtual bool IsDeadBondedPet => false;

[IgnoreDupe]
public ISpell Spell
{
get => m_Spell;
Expand Down
4 changes: 2 additions & 2 deletions Projects/Server/Utilities/ActivatorExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ public static T CreateInstance<T>(
{
var argLength = args?.Length ?? 0;

var types = argLength > 0 ? new Type[argLength] : Array.Empty<Type>();
var types = argLength > 0 ? new Type[argLength] : [];
for (int i = 0; i < types.Length; i++)
{
types[i] = args![i]?.GetType();
Expand All @@ -139,7 +139,7 @@ public static T CreateInstance<T>(
object[] paramArgs;
if (paramCount == 0)
{
paramArgs = Array.Empty<object>();
paramArgs = [];
}
else if (argLength == paramCount)
{
Expand Down
162 changes: 104 additions & 58 deletions Projects/UOContent/Commands/Dupe.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Reflection;
using Server.Items;
using Server.Targeting;

Expand Down Expand Up @@ -40,21 +41,110 @@ private static void DupeInBag_OnCommand(CommandEventArgs e)
e.Mobile.SendMessage("What do you wish to dupe?");
}

public static bool DoDupe(Item src, int amount, Mobile from = null, Container pack = null)
{
from?.SendMessage($"Duping {amount}...");
var c = src.GetType().GetConstructor(out var paramCount);
if (c == null)
{
from?.SendMessage("Unable to dupe. Item must have a constructor with zero required parameters.");
return false;
}

var args = paramCount == 0 ? null : new object[paramCount];
if (args != null)
{
Array.Fill(args, Type.Missing);
}

try
{

for (var i = 0; i < amount; i++)
{
var newItem = DoDupe(src, c, args, from);
if (newItem != null)
{
if (pack != null)
{
pack.DropItem(newItem);
}
else if (from != null)
{
newItem.MoveToWorld(from.Location, from.Map);
}
}
}

return true;
}
catch
{
return false;
}
}

public static Item DoDupe(Item src, ConstructorInfo c, object[] args, Mobile from = null)
{
try
{
if (c.Invoke(args) is not Item newItem)
{
return null;
}

src.Dupe(newItem);

newItem.UpdateTotals();
newItem.InvalidateProperties();
newItem.Delta(ItemDelta.Update);

if (from != null)
{
CommandLogging.WriteLine(
from,
$"{from.AccessLevel} {CommandLogging.Format(from)} duped {CommandLogging.Format(src)} creating {CommandLogging.Format(newItem)}"
);
}

// Recurse for items that have items
if (newItem.Items.Count > 0)
{
for (var j = newItem.Items.Count - 1; j >= 0; j--)
{
var itemToDelete = newItem.Items[j];
newItem.RemoveItem(itemToDelete);
itemToDelete.Delete();
}
}

for (var j = 0; j < src.Items.Count; j++)
{
var subItem = DoDupe(src.Items[j], c, args, from);
newItem.AddItem(subItem);
}

return newItem;
}
catch
{
return null;
}
}

private class DupeTarget : Target
{
private readonly int m_Amount;
private readonly bool m_InBag;
private readonly int _amount;
private readonly bool _inBag;

public DupeTarget(bool inbag, int amount)
: base(15, false, TargetFlags.None)
public DupeTarget(bool inbag, int amount) : base(15, false, TargetFlags.None)
{
m_InBag = inbag;
m_Amount = amount;
_inBag = inbag;
_amount = amount;
}

protected override void OnTarget(Mobile from, object targ)
{
var done = false;
if (targ is not Item copy)
{
from.SendMessage("You can only dupe items.");
Expand All @@ -63,12 +153,12 @@ protected override void OnTarget(Mobile from, object targ)

CommandLogging.WriteLine(
from,
$"{from.AccessLevel} {CommandLogging.Format(from)} duping {CommandLogging.Format(copy)} (inBag={m_InBag}; amount={m_Amount})"
$"{from.AccessLevel} {CommandLogging.Format(from)} duping {CommandLogging.Format(copy)} (inBag={_inBag}; amount={_amount})"
);

Container pack = null;
Container pack;

if (m_InBag)
if (_inBag)
{
pack = copy.Parent switch
{
Expand All @@ -82,57 +172,13 @@ protected override void OnTarget(Mobile from, object targ)
pack = from.Backpack;
}

var c = copy.GetType().GetConstructor(out var paramCount);
if (c != null)
if (DoDupe(copy, _amount, from, pack))
{
var args = paramCount == 0 ? null : new object[paramCount];
if (args != null)
{
Array.Fill(args, Type.Missing);
}

try
{
from.SendMessage($"Duping {m_Amount}...");
for (var i = 0; i < m_Amount; i++)
{
if (c.Invoke(args) is Item newItem)
{
copy.Dupe(newItem);

if (pack != null)
{
pack.DropItem(newItem);
}
else
{
newItem.MoveToWorld(from.Location, from.Map);
}

newItem.UpdateTotals();
newItem.InvalidateProperties();
newItem.Delta(ItemDelta.Update);

CommandLogging.WriteLine(
from,
$"{from.AccessLevel} {CommandLogging.Format(from)} duped {CommandLogging.Format(copy)} creating {CommandLogging.Format(newItem)}"
);
}
}

from.SendMessage("Done");
done = true;
}
catch
{
from.SendMessage("Error!");
return;
}
from.SendMessage("Duping done.");
}

if (!done)
else
{
from.SendMessage("Unable to dupe. Item must have a constructor with zero required parameters.");
from.SendMessage("Duping Error!");
}
}
}
Expand Down
5 changes: 1 addition & 4 deletions Projects/UOContent/Items/Aquarium/Aquarium.cs
Original file line number Diff line number Diff line change
Expand Up @@ -492,10 +492,7 @@ public override void OnAfterDuped(Item newItem)
aquarium.Water.Maintain = Water.Maintain;
aquarium.Water.State = Water.State;

for (var i = 0; i < _events.Count; i++)
{
aquarium.AddToEvents(_events[i]);
}
aquarium.Events = [..Events];
}

private void Deserialize(IGenericReader reader, int version)
Expand Down

0 comments on commit 0b802db

Please sign in to comment.