RunUO Community

This is a sample guest message. Register a free account today to become a member! Once signed in, you'll be able to participate on this site by adding your own topics and posts, as well as connect with other members through your own private inbox!

[SVN] Dupe command 3.0

Lichtblitz

Sorceror
[SVN] Dupe command 3.0

After all the leeching and advices I gave I kind of feel the urge now to give something back to the community. Since I'm using a modified RunUO 1.0 server compiled under .NET 2.0 there is little to no chance at all that my scripts can be used on other shards. So this time I took the effort in converting one of my scripts to RunUO 2.0 SVN.

This command may or may not run with other releases but it is very simple to port it. I have just ported it from RunUO 1.0 and it wasn't too hard.



What does this script do?
This script adds a new improved [dupe command that utilizes the Serialize() and Deserialize() methods to create a perfect duplicate of any item and mobile. This will be done recursively so that duplicated mobiles will come along with their duplicated backpacks and their duplicated loot.

How do I install this script?
  1. Remove the distribution dupe command (e.g. rename "Scripts\Commands\Dupe.cs" to "Scripts\Commands\Dupe.old"
  2. place this script anywhere inside your Scripts folder (e.g. "Scripts\Custom\Commands\SerializeDuper.cs")
  3. done :)

Help, I'm getting an error message ingame!
The text of the error message should speak for itself. If you wish to increase the maximum number of recursions or the maximum item count, change the constants around line 50 in the script (beginning of class DupeCommand)




Questions and suggestions are more than welcome. This script is in use on my shard for over one year and has caused no errors. However I may have introduced errors in porting it from RunUO 1.0. Please report them.
 

Attachments

  • SerializeDuper.cs
    35.1 KB · Views: 170

krazeykow

Sorceror
Wow, the process behind this is impressive. Having created a dupe engine for my previous scripts, I used reflection over the properties to create a mirror image. I never thought of using the serializer/deser. because I probably didn't know how :p. I downloaded this simply to learn some new methods, and I see that you left some comments to help me through. Thanks for the contribution.
 

Kamron

Knight
This is a great dupe method (allbeit very resource intensive for massive dupes).
Please keep in mind that some items are not made to be duped. Specifically any customized items which are cross-linked with other items. And of course objects that have properties which do not serialize (such as SolidHueOverride), will not work inherently with this system either.

Over all, a very good job. I did find a slight problem with properties that GMs could not access (admin only), however may not necessarily serialize, and therefore would affect the duping process.
 

Hawkins

Sorceror
This is truly cool. Thanks very much.

It will be cooler if it's tweaked to allow accessing programmatically ( such that it can be used in my projects ). :D
 

Lichtblitz

Sorceror
Kamron;803549 said:
This is a great dupe method (allbeit very resource intensive for massive dupes).
Please keep in mind that some items are not made to be duped. Specifically any customized items which are cross-linked with other items. And of course objects that have properties which do not serialize (such as SolidHueOverride), will not work inherently with this system either.

Over all, a very good job. I did not find a slight problem with properties that GMs could not access (admin only), however may not necessarily serialize, and therefore would not affect the duping process.

Yes it is (relatively) resource intensive since the methods are recursive. I can't really think of an alternative that would replace the references with duped objects in an iterative process without having the overhead of generic placeholders. This is why I limited the recursions by default to 5 or so to make sure the depth stays low.

My approach was: if an Item or mobile is considered the same after a server restart then objects copied with my dupe methods are the same, too. If it is a problem that specific properties are not copied than it is usually also a problem that they are not saved and thus the serialization should be altered.

The dupe command automatically checks for properties that are not accessible by the caller and stops the dupe, cleans everything up and sends an error notification to the user.

Hawkins;803623 said:
This is truly cool. Thanks very much.

It will be cooler if it's tweaked to allow accessing programmatically ( such that it can be used in my projects ). :D

Yes, I thought about that, too. I will change the implementation as soon as I have the time for it... so I guess within the next two weeks.

Thanks for the feedback :)
 

Kamron

Knight
I am having a problem where if I dupe a container, the new container's Item list contains doubles of all of the items. if I dupe a dupe, it keeps adding an extra list.

I went ahead and fixed the dupe method. I will post the code later once I have time to fully test it. Basically this is the order I did.

List all Mobiles/Items serial numbers (including items that are in containers)
Serialize all Mobiles/Items, in list order.
Go through the Mobiles/Items list and add a new item/mobile with a new serial and add it to the Dictionary<old serial, new serial>.
Then go through the new list of Mobiles/Items and deserialize all of them in the list order, and replace the old serial with the new one.
 

Corpsecrank

Sorceror
You should have made this a new command [SDupe then it would be drop and play and not require the removal of the stock dupe script and command. You would be able to use both [Dupe and [SDupe depending on what you wanted to do.

Still pretty cool and easy enough to change that if I wanted to use it that way.
 

Kamron

Knight
Yeah, I changed it to [serialdupe myself.

Regarding my post above: I modified the command to save a list of all of the old serial numbers for all mobs/items that will be duped. Then when the items were serialized, any references used the list index instead of the old serial number. If the item or mobile is not in the list, it serializes the reference normally.

So for every serial in the list, it adds a new item, assigns a new serial, and adds it to a new list (same order as old one). Then the list index is used to reference new serials during deserialization. Boom boom, it should work.

I also threaded it, so when I test it, I can duplicate thousands of items. To stop any type of enumeration problems because of the threading, the script moves the item/mob to the internal map temporarily. Also if it throws an exception, it deletes all new items from the new serial list.

I will keep everyone up to date on how it goes.
 

Kamron

Knight
nerun;805510 said:
Awesome! Good job! Remember in some way, the possess comand of the old Sphere.

I tried to duplicate the possess command many years ago (back in 2004), but I failed. Mainly because when I changed the netstates around, it disconnected the person. I assume its possible, but to be honest I never tried to recode it. Nerun, is there a working version of it?
 

Lichtblitz

Sorceror
There already is a mapping of old to new serials so that Items won't be duped several times and further references will simply be mapped to already created items

PHP:
Dictionary<int, int> serialMapping

It is created once and all recursions of the Dupe method use references to the same Dictionary.
 

Lichtblitz

Sorceror
Kamron;805499 said:
I am having a problem where if I dupe a container, the new container's Item list contains doubles of all of the items. if I dupe a dupe, it keeps adding an extra list.

Could you please elaborate further? If I dupe a container I'll get a copy with no duplicates.
 

Kamron

Knight
Lichtblitz;805525 said:
Could you please elaborate further? If I dupe a container I'll get a copy with no duplicates.

I added your script, renamed "dupe" to "serialdupe". I placed some items into a container (a bagofreagents, an ethereal, a bankcheck, and a house deed). I type [serialdupe and targeted the bag.

It came up with an interface of the new items and the bag. I single-click the new container that was duped and it says "22 items", not 11. I do [contained get parentitem, and it lists every serial twice. I added ParentItem as a custom property to the core so I can check the parent by serial (great for global checks).

One error I see in the method that you used is that you add the container's serial to the mapping dictionary AFTER you serialize/deserialize the children. Therefore the parent property of all of the children will still reference the old bag. However how this pertains to duplicate serials in the Items list of the container, I dunno.

EDIT: Here is the code I modified. I did basic testing with 10 recursively deep containers, utilizing guild references, player references, mobile references, and item references. I wouldn't call this bug proof just yet though.
I do not include original licenses or headers in code that I release which contain more than 50% of material change to the code. I do however give credit for the origin of this derivation.
 

Attachments

  • SDupe.cs
    28.8 KB · Views: 37

Corpsecrank

Sorceror
Yeah Kamron that is more like what I was thinking. Could go a step further and add in some checks for items that should not be duped to prevent those items from being duped by someone who didn't know they shouldn't be duped. Might help prevent possible problems down the road with supporting this.
 

nerun

Sorceror
Kamron;805512 said:
I tried to duplicate the possess command many years ago (back in 2004), but I failed. Mainly because when I changed the netstates around, it disconnected the person. I assume its possible, but to be honest I never tried to recode it. Nerun, is there a working version of it?

I think that not. But i can imagine a command that dupe the entire apperance of a mobile (body, hair, clothes, items etc), delete that mobile (so not works in players) and place yourself in the same spot that the mobile targeted was. In the other hand, the undupe command will replace the exact mobile and restore yourself to GM appearance.
 

Lichtblitz

Sorceror
Kamron;805542 said:
I added ParentItem as a custom property to the core so I can check the parent by serial (great for global checks).

One error I see in the method that you used is that you add the container's serial to the mapping dictionary AFTER you serialize/deserialize the children.

Oh, I see the problem. Your custom property made it visible. I will provide a new fixed version soon but I will not add threading to my script for the time being since I don't have a complete overview yet what missing synchronization could do to the serialization process of certain classes. Looking at the [XmlFind command of the XmlSpawner gives a good impression on how often Iterators get invalidated in a big world. Also the processing power required by the serialization process is fairly small as long as you're not writing to the hard disk. So even thousands of items could be duped almost seamlessly on decent server hardware.

EDIT: almost forgot: thanks for the heads up and the great contribution :)
 

Lichtblitz

Sorceror
Corpsecrank;805548 said:
Yeah Kamron that is more like what I was thinking. Could go a step further and add in some checks for items that should not be duped to prevent those items from being duped by someone who didn't know they shouldn't be duped. Might help prevent possible problems down the road with supporting this.

Most of the Items I encountered (like controllers for certain systems) either won't allow duplicates to be created in the first place or have Properties only accessible to Administrators. Those Items can in turn only be duplicated by Administrators.
 

Kamron

Knight
Lichtblitz;805556 said:
Oh, I see the problem. Your custom property made it visible. I will provide a new fixed version soon but I will not add threading to my script for the time being since I don't have a complete overview yet what missing synchronization could do to the serialization process of certain classes. Looking at the [XmlFind command of the XmlSpawner gives a good impression on how often Iterators get invalidated in a big world. Also the processing power required by the serialization process is fairly small as long as you're not writing to the hard disk. So even thousands of items could be duped almost seamlessly on decent server hardware.

EDIT: almost forgot: thanks for the heads up and the great contribution :)

You are right about the threading and iterations. I plan to do tests by using a copy of my production world (5.5GB), and duping the whole world to a new facet. That should determine lag time when threaded, and possible crash-points.

Also its very simple to remove threading in that script.
 

Corpsecrank

Sorceror
Lichtblitz;805558 said:
Most of the Items I encountered (like controllers for certain systems) either won't allow duplicates to be created in the first place or have Properties only accessible to Administrators. Those Items can in turn only be duplicated by Administrators.

I see but in the off chance you did run into something weird that had issues I would throw a check into this to eliminate further hassles.

Not exactly easy to determine what things may cause problems without duping the object once.
 
Top