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!

Ultima Live - In Game Map Editing Framework

Praxiiz

Sorceror
I'm mostly interested in the additional maps. Seems you've got a proof of concept going, to prove to yourself that it could work. But I have a few questions pertaining to this. Will the additional maps also support having their own separate statics? Will there be a way of making the additional maps client side and not have to send every bit of the map over the network. Do you plan on providing easy methods of...maybe copying/cloning a map?

If you have tested the additional maps...did you only test it with the client? Won't we still need to update the RunUO server core to work with the new maps?

Here is what I've done so far on the maps. My proof of concept has been all client side. Without the client working with it, there's zero chance of implementing it. I can successfully find where the client stores its memory pointer to a map/statics, and point it to a location I choose. This means I can allocate memory and point the client to that memory, and the client will use it as the map. This works with both the maps and statics.

To implement it, I plan on intercepting the MapChange packet and parse it for the map number. If it corresponds to an existing map file, then I will let it pass through. If it doesn't correspond to a normal map, then I'll check to see if that mapXX.mul file exists on the disk client side. If it doesn't exist, I'll create it as a blank file. The server won't stream the entire map to the client when they change maps. It only streams the current block the player is standing in and the 24 blocks around it. This means that as the player moves, portions of the map which aren't built will have the same CRC check as the client side (both will be essentially blank), which means no network bandwidth would be used on unfinished portions of the map. For finished portions, the server would stream blocks to the client as the client encounters them in its 25 block area. So running at full speed you'd probably expect to send a client 5 blocks per second. I'd be surprised if this was more than a few kilobytes of data.

Now I am fully expecting some complications server side. I haven't read through all the server side code dealing with maps, so I am speculating at this point. I am hoping that I will be able to register maps and give them a fileindex that is higher than the normal range. (Client is upto index 5 now?)

Just glancing through the MapDefinitions.cs file, I see

Code:
/* Example of registering a custom map:
 * RegisterMap( 32, 0, 0, 6144, 4096, 3, "Iceland", MapRules.FeluccaRules );
 *
 * Defined:
 * RegisterMap( <index>, <mapID>, <fileIndex>, <width>, <height>, <season>, <name>, <rules> );
 *  - <index> : An unreserved unique index for this map
 *  - <mapID> : An identification number used in client communications. For any visible maps, this value must be from 0-3
 *  - <fileIndex> : A file identification number. For any visible maps, this value must be 0, 2, 3, or 4
 *  - <width>, <height> : Size of the map (in tiles)
 *  - <name> : Reference name for the map, used in props gump, get/set commands, region loading, etc
 *  - <rules> : Rules and restrictions associated with the map. See documentation for details
 */

And glancing at the server core Map.cs file

Code:
public sealed class Map : IComparable, IComparable<Map>
    {
        public const int SectorSize = 16;
        public const int SectorShift = 4;
        public static int SectorActiveRange = 2;

        private static Map[] m_Maps = new Map[0x100];

        public static Map[] Maps { get { return m_Maps; } }

Initially, it looks like they've given the array for maps a capacity of 255. They reserve the first 32 for core use, and they also reserve 0x7F and 0xFF. This leaves space for 221 maps (some of which are likely being used with the same map index on custom shards already). As I said before I haven't read through it yet, I'm just speculating. I will dig into it further after I finish reducing the save times. I fully expect to be able to implement maps with their own sets of statics, and with their own map files.
 

Pure Insanity

Sorceror
Here's a bit of my registered maps.

[syntax]
RegisterMap( 0, 1, 1, 7168, 4096, 0, "Felucca",MapRules.FeluccaRules );
RegisterMap( 1, 1, 1, 7168, 4096, 0, "Trammel",MapRules.TrammelRules );
RegisterMap( 2, 2, 2, 2304, 1600, 1, "Ilshenar",MapRules.TrammelRules );
RegisterMap( 3, 3, 3, 2560, 2048, 1, "Malas",MapRules.TrammelRules );
RegisterMap( 4, 4, 4, 1448, 1448, 1, "Tokuno",MapRules.TrammelRules );
RegisterMap( 5, 5, 5, 1280, 4096, 1, "TerMur", MapRules.TrammelRules);
RegisterMap(33, 0, 0, 7168, 4096, 0, "BloodRock", MapRules.FeluccaRules);
RegisterMap(34, 0, 0, 7168, 4096, 0, "Savage", MapRules.FeluccaRules);
RegisterMap(35, 0, 0, 7168, 4096, 0, "Moonlake", MapRules.TrammelRules);
RegisterMap(36, 0, 0, 7168, 4096, 0, "ImmortalsPlayground", MapRules.FeluccaRules);
RegisterMap( 40, 0, 0, 7168, 4096, 1, "Sosaria",MapRules.TrammelRules );
[/syntax]

And I believe the core is set for 255 maps by default, not sure what changing it could cause as I've never needed more than that.
 

Praxiiz

Sorceror
Hey Prax, I tried this out and it's really nice, such a great concept. I was wondering though and forgive me for saying so, but building is kind of clunky. Would it be possible to hook this into Pandora's Box?

I take no offense that you find it clunky to build stuff at this point. I think many people would agree with you.

The project has two main directions. Map editor, and map/static streaming client for players. Much of the functionality that is built in so far has been done in the streaming part of the project. I hope that when its finished, players will run it and continue to play normally without ever noticing that it is there. The more transparent it is for the player, the better. It should just update their map and interact with the server on their behalf.

I think the best thing to do for the Map Editor portion of the project is to allow several options. I would like to have a set of in game gumps and commands that can be used with the appropriate access level. This would let the project continue to truly be an in-game map editor. I built one area command that lets you increase the altitude of a circular area of the map. This type of command really needs to be extended to increase the altitude of statics in its area as well. Another area command could be used to flatten areas (or make them jagged in altitude). There are a lot of possibilities for commands that can be made, and they can all be implemented server side. Because they can be done server side and anyone can work on them, I haven't focused on them.

I also plan on developing a set of protocols for receiving updates from a client (pending access level checks of course). I have left a portion of the code stubbed for now that will later handle this. If you look at the screenshot that I posted of the early overlay grid system (the one with the ugly white window on the side of the game window), I can add editing buttons to that portion that would be similar to Pandora. You can toggle that overlay on and off, so it wouldn't be there unless you needed it. That overlay would send the server commands directly. The server would receive them and check your access level, then either implement them or drop them. I'd like to make it so you could drag the map vertices with your map using the overlay. It would be nice to add some other features for making the map more interactive.

I know many people use Pandora's box for decorating their maps. To be honest, I hadn't even thought of Pandora. I like the idea of hooking into Pandora. I will investigate it further and see what it would require.

Btw, there is one crash bug that I found related to the existing server side commands. If two people try to remove a static at the same time, or edit the terrain. It will cause a crash, but it's an easy enough fix.

I will take a look at this.

Do you plan on sticking with the current setup for commands? Plan on changing it any? Would be nice if it played nicely with the [m [area and other commands. Even with distro edits to files to make it play nicely with the modifiers would be worth it, like have it pass the command over to your command methods when it encounters a LandTile or StaticTile or something. A mod like this would make this system far easier to use and more fluid. I believe once this system is a bit more rock solid, the UO community will start seeing some pretty awesome custom maps, as I believe this would allow one to create a map far faster and easier than using something like Dragon or something else to make the map.

There are some tweaks I'd like to do to the command system. Some of the arguments are geared toward targets, which need to be cleaned up. The MapOperationSeries needs to be tweaked a little so you don't have to pass a null to it when you're starting a chain. I tried to make that class so a series could contain another series etc. I planned on making it play nicely with the [m and [area commands, but I just haven't taken the time to do so. I need to look at how they are handled to see what it would require. If you already have it working, that would save me a lot of time :)
 

Praxiiz

Sorceror
Code:
*  - <fileIndex> : A file identification number. For any visible maps, this value must be 0, 2, 3, or 4

Your custom maps (33,34,35,36, 40) are all using file index 0, which is felucca. I am hoping that my system would simply allow more than the 6 default file indexes. (0-5)

So you would register a new map, but for the file index, you'd pass it 10 for example. The server would try to find or create map10.mul, statics10.mul, and staidx10.mul. The client end would intercept the file number and create those files client end as well.

Using it in this way would make it so your players would have to use Ultima Live with razor or they wouldn't be able to get to the additional maps.
 

Pure Insanity

Sorceror
Yes, I know what you mean. That would be lovely. I have 1 custom map, then tons of clones.

I don't see an issue with requiring users to install an addon to Razor. Just keep in mind that Razor is mostly directed at PLAYERS, so I believe it would be rather silly to add the Land/Static stuff to your tab that you created on Razor. It's fine as it is, but ignore the people that want you to add buttons and stuff on there to do the land stuff. They can just wait till the command system is improved.
 

Praxiiz

Sorceror
The way I planned on adding the other stuff to the razor tab is to include it in a DLL. If the DLL exists in your razor folder, then you see the buttons and have the functionality. So when you package it up for your players, just simply leave the DLL out and they won't know it exists. (Unless they come get it from here and install it, but even then they won't have the access levels to use it)
 

Praxiiz

Sorceror
Right now, the DLL for the overlay and commands is not a priority. The save system and the capability to have more maps is my biggest concern. I am hoping that people will want to contribute commands/gumps which will allow me to continue to work on stability on both the client and server end.
 

Pure Insanity

Sorceror
Eh, if you can finish the main features you're wanting to focus on. I'm sure me or someone else can focus on making a better command system/gump to handle everything. With that part of it being server side, there's nothing really for you to worry about. We can make what we want with it now.

I would absolutely love the ability to load in extra maps. I'd love to test it out for you too, I have a bunch of custom maps that I could use to test it with.

The easiest way to fix the saves is to move the map files outside of the save folder. And only save them when enough edits have been done or something similar. Could easily make it so you could type something like [LiveUltima in game and it open a Props gump that lets you configure how many edits need to be pushed to the stack before it saves the actual map files. Or an optional extra time variable to save the map files every so many hours or something.

As for editing Land and Statics, I believe to best way to do it would be to either make a gump. Or modify distro files to make it play nicely with the command modifiers. Or are you trying to stay away from distro edits?
 

Praxiiz

Sorceror
I've been trying to stay away from distro edits, but I'm not entirely against them.

I've now completed the main portion of the new save system. I'm testing it now. The way it works is every time the world saves, any changes that have been made to maps/statics are saved out to the folder under a separate file. Shard owners can still revert to old saves and the world will match if they remove the change files that occurred after the desired save. Over time, these files will accumulate and slow down loading time of a server. This can be fixed by issueing an export command. The export command will save out all the mul files with all the changes on them to an export folder. They can then be copied to the folder that the server uses for its client files, and the change files can be removed.

This greatly improves save time. My blank world has gone from 10+ seconds saving under the old system to saving in under .04 seconds as one would expect of a blank world.

Eventually it will be nice to have some configuration gumps. I think while the system is so volatile, however, it will be best to leave them for later. A lot of time can get sunk into the GUI of a project, and at this point I think I would be altering the configuration GUI with almost every new feature / change I make.

This save system is all implemented server side of course. I suppose that really is the good thing about this project. If someone doesn't like a server side feature, they are free to change it. After I finish up the export command, I will post another release.

Next I will focus on adding new map capability.
 

Pure Insanity

Sorceror
Awesome, good to hear.

Quick question. Using your method, you believe it would be possible to inject new gumps or replace existing ones durring run time. Or something else like Skills (I know you can change the order, and even the name of skills...but I believe adding more skills than what the client is made to believe exists causes problems. Haven't tested to confirm.)

Something like this could easily allow for versioning of files and stuff, perhaps a custom shard have their player download 5 new gumps that was added to the gumps, animations, skills, w/e. Instead of the entire file, plus with your method it may be possible to exceed limits imposed by doing it other ways. Just some ideas, not suggesting you start working on this or anything. I'm still having fun with this system and can't wait for you to finish the map features. =D
 

Praxiiz

Sorceror
I can edit any of the files that the client maps while it is running, or replace them with alternate versions in memory. If the client caches the particular file, then I have to find a way for the client to refresh its cache of that file for it to be effective. I haven't tested to see if any of the other files are cached besides the map files.
 

Pakko

Traveler
Is any body using this on a live server yet? i think this is awsome and insane :) Been wondering when CUO was gonna come back and thought well maybe this is an idea.

And does this only freeze the changes made to the ground, lets say i made changes near a players house and froze a bounding box containing the house would the house then become static without needing to be patched to see it. ?

Great work though man really smart.
 

Praxiiz

Sorceror
v0.44a released.

The livefreeze command works like the regular freeze command, but you see changes instantly.
 

Praxiiz

Sorceror
Its still in alpha phase, I don't think there has been enough testing to reliably use it on a production server yet. The recently added CRC system and Saving systems haven't been tested by anyone but me as far as I am aware.
 

Pakko

Traveler
Ok. well ill wait for it to be out of alpha, before i go and implement this to my live shard but i really like it man and cant wait for the updaes.
If i knew any more about anything important "LOL" i would be on board to help you bro but im only good at PHP & HTML
 

Praxiiz

Sorceror
Does anyone have any experience in customizing the size of a map? I've successfully implemented the hooks for the memory addresses I need to swap out maps, but right now I'm constrained to the standard sizes. I'm trying to figure out a good way to handle this.

Does anyone have any experience with modifying the standard map constraints including wraparound?

Some basic memory searching gives me this, but changing the values doesn't seem to have any effect on the wrap-around.

I'm assuming that the second set of constraints in the image below (7168 4096 5120 4096 )
is the wrap-around for the map.

memory.jpg

Code:
RegisterMap( 0, 0, 0, 7168, 4096, 4, "Felucca",        MapRules.FeluccaRules );
RegisterMap( 1, 1, 1, 7168, 4096, 0, "Trammel",        MapRules.TrammelRules );
RegisterMap( 2, 2, 2, 2304, 1600, 1, "Ilshenar",    MapRules.TrammelRules );
RegisterMap( 3, 3, 3, 2560, 2048, 1, "Malas",        MapRules.TrammelRules );
RegisterMap( 4, 4, 4, 1448, 1448, 1, "Tokuno",        MapRules.TrammelRules );
RegisterMap( 5, 5, 5, 1280, 4096, 1, "TerMur",        MapRules.TrammelRules );
 
Top