Welcome to the Builder Academy

Question Zone Instancing

More
13 Apr 2020 02:24 #8626 by Gahan
Zone Instancing was created by Gahan
Hey folks, due to lock-down I have decided to get back into the grit, and add some new features to a mud. Currently, I am looking for folks who have either added zone instancing already into their mud or people with ideas on how to do it efficiently within the tbaMUD realm.

I have been able to create a new zone with the old zone's information and have been able to create new rooms, but I feel like this process is duplicating a lot of existing code, as the existing code doesn't really seem to support mass creation of content in-game. One of the things I've been able to manage doing it the long way, is not to have the data stored to disk. That way after a certain period of time the zone gets free'd or if the mud is rebooted so instanced zones don't "pile up".

Would like to start a discussion on it if anyone is interested!

Please Log in or Create an account to join the conversation.

More
13 Apr 2020 19:20 #8628 by thomas
Replied by thomas on topic Zone Instancing
I have some thoughts about this.

But first, some requirements gathering:

- When you say "zone instancing" are you thinking of randomized zones (like the mission zones in Anarchy Online) or more traditional "raid" instances?
- Do you want the option of having a group instance (so members of a group get back to the same instance if they reenter after a death).
- How do you want to handle deaths? I mean, if I drop all my items in the zone, and it despawns, do I lose all my stuff?
- What is the purpose? Avoiding kill-stealing? Scaling the mobs/rewards to fit the group?
- those zones - will they have zone reset events? Ie. are mobs going to respawn here?`

I'm sure this list isn't complete, but it's a start. A thing I've been working on lately at work is "user stories" as a way of requirements specification. These have the format
As a <role or person> I would like <thing to happen> so that <value proposition>.
The most important being the value proposition. With the questions above I'm trying to determine the value these instances will provide to the players or you as an implementor. My first guess is

As a player i would like instanced zones so that other players don't steal my loot.

I'm not entirely sure that's the real value - please help me out here.
The following user(s) said Thank You: Gahan

Please Log in or Create an account to join the conversation.

More
13 Apr 2020 19:52 #8629 by Gahan
Replied by Gahan on topic Zone Instancing
When I say zone instancing i'm thinking about having a "source" zone and making an identical copy of it to my "instanced" zone, and adding an identifier to it so that it can be accessed by those who created it (without their knowledge). For sanity purposes I suppose I'd start by creating a new zone with a new zone number, different room vnums (incremented identically from the source zone) and then copy in all of the zone reset commands, leaving original mob vnums/obj vnums/shops/triggers to load properly.

I, ideally would start by adding a new groupID value to the group or player structure when a group is created so that I could identify those who were able to access the zone.

For deaths, our corpses don't populate with gear. However, that's a good point. If you "drop" items in the zone and it despawns then of course you would lose your stuff. The same way you would lose your stuff if you dropped stuff on the group and the mud was rebooted. My original plan would to have the zone reset despawn an instance after it was empty for a certain period of time. Say, 30 - 60 minutes. Which would probably solve the corpse issue, as they would decompose long before the zone despawns.

For the purpose of this, yes avoid kill-stealing, or interfering with special quests, the ability to scale mobs for large groups would definitely be one of top 5 reasons. My MUD has some player killing elements as well and this would allow for a period of time on certain missions in which they'd not have to worry about it. Also, I know "gear runners" in some muds are always the first to a zone to get the gear... for special quest related gear items this would allow everyone to have a fair crack and not be limited specifically to max_load or percent load. Which in my opinion is more interesting than a quest keeper just giving you the special dragon slayer sword that you would have gotten as loot for killing the epic dragon slayer himself. I could list other value propositions, but i think these are the main ones.

Yes, these zones would have zone reset events.

I'm not looking for anyone to do the work for me, in fact, I've kind of looked forward to this challenge for a while, but I am not anywhere near your league for knowledge in programming, so I thought I'd pop in here first and get everyone's 2 cents.

Appreciate the reply Thomas!

Please Log in or Create an account to join the conversation.

More
13 Apr 2020 23:14 #8631 by thomas
Replied by thomas on topic Zone Instancing
Now we know what you're trying to achieve, we can ask even deeper:

Would it be acceptable to have some kind of instance marker you could share? For instance, the questgiver (or whatever means we are using to distribute the quest) give a "token" of a sort that has an internal code?
Think of something like this:
Code:
The questmaster gives you a key to the dungeons. > examine key This is a key to the dungeons, given to playername. You can use it to enter your own dungeon. If you need help, you can give a copy of the key to another player. They can then enter the same dungeon. To do this, use the command: copy key to playername The key has an ephemeral feeling. The key seems to be fading from existence. It will be completely gone in 105 hours.
Here, the "ephemeral" would mean it persisted after death and that it disappears in a cloud of smoke if it is ever intentionally dropped or attempted rented. Attempts to give it away/steal it should fail.

I'm introducing some new concepts here - persistence across death, timed objects, a "copy" (and corresponding "accept") command.

All this to avoid assigning a specific id to a group and preventing changes to a group (or joining a group half-way through) from causing trouble. For instance, say I'm part of one group when I accept the quest, but join another before going into the instance - who should have access?

Also, having objects with a set timeout will help us in deciding whether a zone can be safely unloaded - no more access keys == no more zone. It could even go as far as when the zone has been "defeated", the key is removed from everyone, so the zone is no longer accessible. And once everyone has left, it is removed.

About the actual implementation: There are some limits that need to be addressed for this to work.
github.com/tbamud/tbamud/blob/master/src/structs.h#L24 :
Code:
/* preamble */ /** As of bpl20, it should be safe to use unsigned data types for the various * virtual and real number data types. There really isn't a reason to use * signed anymore so use the unsigned types and get 65,535 objects instead of * 32,768. NOTE: This will likely be unconditionally unsigned later. * 0 = use signed indexes; 1 = use unsigned indexes */ #define CIRCLE_UNSIGNED_INDEX 1 #if CIRCLE_UNSIGNED_INDEX # define IDXTYPE ush_int /**< Index types are unsigned short ints */ # define IDXTYPE_MAX USHRT_MAX /**< Used for compatibility checks. */ # define IDXTYPE_MIN 0 /**< Used for compatibility checks. */ # define NOWHERE ((IDXTYPE)~0) /**< Sets to ush_int_MAX, or 65,535 */ # define NOTHING ((IDXTYPE)~0) /**< Sets to ush_int_MAX, or 65,535 */ # define NOBODY ((IDXTYPE)~0) /**< Sets to ush_int_MAX, or 65,535 */ # define NOFLAG ((IDXTYPE)~0) /**< Sets to ush_int_MAX, or 65,535 */ #else # define IDXTYPE sh_int /**< Index types are unsigned short ints */ # define IDXTYPE_MAX SHRT_MAX /**< Used for compatibility checks. */ # define IDXTYPE_MIN SHRT_MIN /**< Used for compatibility checks. */ # define NOWHERE ((IDXTYPE)-1) /**< nil reference for rooms */ # define NOTHING ((IDXTYPE)-1) /**< nil reference for objects */ # define NOBODY ((IDXTYPE)-1) /**< nil reference for mobiles */ # define NOFLAG ((IDXTYPE)-1) /**< nil reference for flags */ #endif
The limit is currently 65535 rooms in the world. In all zones, regardless of whether they're loaded dynamically. This makes it slightly more trouble to do this. For us to actually do this, we'll need a somewhat larger addressable scope, at least an uint32. i haven't tested tbamud with this, but it might be simple: os.mbed.com/handbook/C-Data-Types
Upping it to an uint32_t would let us use 4 million room, though this would potentially have an impact on the performance of other aspects of the mud. I think we can safely say that we need to look into this before just changing the limit (we're looping over "all rooms" and "all items" quite often).

Please Log in or Create an account to join the conversation.

More
14 Apr 2020 01:10 #8632 by Gahan
Replied by Gahan on topic Zone Instancing
The key idea is definitely a feasible concept, however my original plan was to streamline it a bit more and have the actual zone linked lets say you're in room 199 and exit 200 is north but is flagged ZONE_INSTANCE or some such thing. A call would be made to create the duplicate zone in instance "space". (An allotted amount of potential vnums that haven't been loaded yet via #defined macros). Some integration of the #define MIN_INSTANCE / MAX_INSTANCE could take some of the looping pressure off the cpu couldn't it?

I have actually gone through the work of changing the IDXTYPE to u_int (my linux distro is 64-bit and thus has a size_of u_int of over 4 billion). It does create other obvious issues such as saving zon/wld/obj/mob/trg/shp data, because all of the routines use %d instead of %u (or in your 32 bit uint32 case %ul) to parse the vnums. Similarly the display issues arise with displaying original short int vnums with %d. After changing all of them (and btw there are a bunch the compiler doesn't pick up for whatever reason), I am able to create zones up to 40 million (change max_zone) and vnums up to 4 billion (nr>4000000 instead of 65535).

That said, my test tbaMUD has been stripped of all zones and i'm playing with limbo and zone 1, so I really cannot comment on how this has impacted performance, like, at all and likely can't until I've gone too far with this, lol!

As far as the development has gone on my end so far, I've been able to have a player walk into a normal zone with my new "INSTANCED" flag (or through a door, or entering a special door) the MUD identifies it and takes the "source" zone from the room the player is in, and loops from #MIN_INSTANCED_ZONE to where a zone doesn't exist, creates an empty zone, recreates the top_of_zone list, and then populates the struct zone_data with the the source zone. I have gone one step further to create a new room in that zone to test the seamless passage by removing them from their existing room and putting them into the new room in the new zone but this is where I am stuck, and re-thinking my implementation.

The code I started writing from cycling through each room in the source zone and the creation of the new zone is almost identical to existing code, but with fewer "features" IE: i dont want the zone to be saved to disk, etc.

Please Log in or Create an account to join the conversation.

More
16 Apr 2020 17:27 #8634 by thomas
Replied by thomas on topic Zone Instancing
Of course, 4 billion, don't know what I was thinking.

Given the requirements, I'd go ahead and "tag" each created zone with the player ID, and then when a player tries to enter, check if they're the same ID or if they're currently grouped with that player as the group leader.

This will make sure only people the original player want to see are coming along (or he'd kick them from the group) and also makes it quite easy to get back, without the need for specific objects persisting through death.
Also, it makes it easy to send a message when entering: "This instance is owned by Spiffer, your group leader", in case you want to send some message when it happens.

So, the next step - when you enter, you need to tag with the current players id.

Whenever any movement occurs, I'd check if the zone for the two rooms is the same - this is where I'd track if the zone is empty (so, you're the last player, and you've been killed? Ok, the zone is now empty). I think I'd also track "last command issued" here, in case I'd want to force remove the instance even if there's a player idling there.

The mechanism to actually copy the rooms is the same you see other places, in the OLC. To avoid having too many functions with the same purpose, they could probably be refactored a bit, but I don't think it's really that difficult, though care must be taken to free the memory correctly.

Please Log in or Create an account to join the conversation.

Time to create page: 0.192 seconds