My goal was to make the library as simple to use as possible. The SwapMaps library provides this same feature, but I've been told it's not very easy to use (I've never used it myself, though). With my library, here's all you have to do to copy a map:
// create a new copy of the second z level
var/Map/map = maps.copy(2)
// move the mob to 5,3 on the new map
mob.loc = locate(5, 3, map.z)
The Map object contains some information and procs you can use to work with the new map copy. As you can see from the example, it has a z var which you can use to move players to that map. When the map is copied, the copy is placed on a different z level - you don't need to tell the library what z level to use, it finds an available one (it'll create a new one if it needs to).
The Map object also has some procs you can use. You can call map.repop() to repopulate the map. This will create new instances of objects that were initially on the map but have since been deleted - for example, if you kill an enemy it gets deleted, calling map.repop() will make that mob respawn at its original location. This is similar to BYOND's world.Repop() proc, except that it applies only to that copy of a map. This way you can repop a single instance at a time.
The map.free() proc tells the library that the map is no longer needed. This means that the library will re-use that map's z level. The library maintains a list of available z levels. When you create a map it uses an available z level, or, if none are available, it'll create a new one. Calling the map.free() proc will add the map's z level to the list of available ones. It's up to you to make sure that the map is not in use - you wouldn't want to free the map if players are still inside.
The MapBase Object
Before the library makes a copy of a map it first makes a MapBase object. This object stores all of the information needed to create a copy of the map. This way you don't need to keep an untouched, original copy of the map. You can create the MapBase object when the game starts up and then write over the original map - all of the information needed to create a map is stored in the MapBase object.
When you call maps.copy() the library automatically creates the MapBase object (if it doesn't already have one for the z level you're copying), but you can create these manually if you wish:
// create a MapBase for the second z level
var/MapBase/base = new(2)
// tell the library it can re-use the second z level
maps.clear(2)
// make a copy of the third z level
maps.copy(3)
// make an instance of the base
base.make()
This code makes a MapBase of the second z level then tells the library that it can re-use that z level. The third command copies the third z level - this copy will be placed on the second z level because we told the library it could use it. The last command makes an instance of the base. Even though we wrote over the second z level we have the MapBase object, which is all we need to make a copy of the map.
Future Work
When dealing with instanced maps, being able to create copies of a map is only part of the problem. The bigger problem is designing your game in such a way that everything works even when there are multiple instances of a map. You wouldn't want to do something like this:
obj
switch_03
proc/use()
for(var/obj/door_03/d in world)
d.open()
door_03
proc/open()
density = 0
When you have multiple instances of a map that has switch_03 on it, using the switch will open all instances of door_03 - even the doors in different map instances!
I'd like for the library to include additional demos and features that help you create maps that function effectively whether there's one instance or 10. I'm not sure what this means - I don't know what features you'd need. It really depends on how you use the library, so if you find a need for some feature, let me know and I'll see if I can add it.