LPMuds.net
July 30, 2010, 06:08:00 AM *
Welcome, Guest. Please login or register.

Login with username, password and session length
News: This is the forum page. For the main LPMuds page, visit http://lpmuds.net
 
   Home   SITE FAQ INTERMUD DOWNLOADS LINKS Help Search Login Register  
Pages: [1]   Go Down
  Print  
Author Topic: Instanceable Rooms?  (Read 1512 times)
Sluggy
Friend
**
Offline Offline

Posts: 59



View Profile
« on: August 12, 2008, 05:00:44 AM »

One of the specs I've been given is a short tutorial section at the very beginning where new players may learn the basic rules of the game while in an isolated and controlled environment. After creating their character they are placed within this tutorial zone and instructed how some of the basic interactions within the game world work. I personally feel this is somewhat important because several parts of DS have been modded or extended.

As far as I know, there is no out-of-box support to spawn 'instanced room' objects. Rooms, that are copied from a master version and then loaded into memory and supplied for individual players. This also seems a little time consuming and out of my league to try to implement so I'm rather thinking along the lines of simply providing several copies of the same domain and simply assigning each new player to one. Of course this has the natural limit that only as many players can create new characters as there are copies available. So before I go and do that I figured I would just ask if there was any way to create instanced rooms.

Logged
cratylus
Your favorite and best
Administrator
***
Offline Offline

Posts: 904


Cratylus@Dead Souls <ds> np


View Profile WWW
« Reply #1 on: August 12, 2008, 05:19:27 AM »

Quote
As far as I know, there is no out-of-box support to spawn 'instanced room' objects.

That is correct. The lib does not expect cloned rooms to exist, and indeed
there are various systems that would react with some hostility to such
a room.

However, it's certainly doable. I haven't tried it...let me check...
Quote
cd /domains/examples/room
/domains/examples/room:
Dead Souls Zayin /domains/examples/room >
ls
/domains/examples/room:
 1   README        002 exroom2.c     006 exroom4.c     1   start.c     
 004 entrance.c    002 exroom2a.c    004 exroom5.c                     
 1   ex.h          1   exroom2b.c    001 exroom6.c                     
 003 exroom1.c     001 exroom3.c     002 exroom7.c                     


Dead Souls Zayin /domains/examples/room >
eval return this_player()->eventMoveLiving(new("/domains/examples/room/entrance"))
/domains/examples/room/entrance#806
Entrance to Hall Of Rooms
|-----------------------------------------------------------------------------|

  You are in a large, empty room.  There are few things to examine -- only the
floor, ceiling and wall at this time.  An opening to your north leads to the
incredible Hall of Examples.  The line at the top of this description was put
in as a VERY useful tool for keeping a standard width to all descriptions
 and messages.

  The Hall of Examples has many rooms to look through.  Each room is limited
to one or two different types of things.  For example, showing how to do a
pre-exit function.  Naturally, you will probably combine many of these
functions into one single room.  Room files can get long and involved, but
when you understand the individual parts, you have no trouble understanding
the whole.  Don't forget to 'more here' in each room.  Most of the rooms have
expla nations written out in comments.

  As a final aside, most of the functions are simplistic.  These are
very basic examples.
Obvious exits: north, south
Result = 1

Dead Souls Zayin /domains/examples/room >

Lol, win.

So yeah, you can do it. The trick is handling stuff like the fact that
the reaper daemon is liable to try to dest that room as a cloned
object without an environment, that sort of thing.

Play around with it and post the problems you find.

-Crat
Logged
Sluggy
Friend
**
Offline Offline

Posts: 59



View Profile
« Reply #2 on: August 12, 2008, 05:55:03 AM »

Sweet! Thank you sir! I'll post what i find but it may take some time as their are other things higher on the TODO list.
Logged
wodan
BFF
***
Offline Offline

Posts: 268

Drink and code, you know you want to!


View Profile
« Reply #3 on: August 12, 2008, 12:03:35 PM »

aww, the first baby steps to a terrains system Smiley
Logged
Nulvect
Friend
**
Offline Offline

Posts: 73


View Profile
« Reply #4 on: August 18, 2008, 05:37:13 AM »

This is funny, because a week or so ago a new coder I brought on to my mud actually created an instancing system from scratch. Before that I had never even considered instances on a mud. It's probably not ready for general use yet, and as Cratylus said would require changes to how your mud thinks of rooms, but I'll definitely be encouraging him to release the code for general use.
Logged
Sluggy
Friend
**
Offline Offline

Posts: 59



View Profile
« Reply #5 on: August 08, 2009, 10:45:11 PM »

I finally got around to making a proof-of-concept for instance rooms. It wasn't nearly as hard as I thought it would be. However, there are still a lot of quirks so any ideas are welcome. It was specifically designed with my goals in mind so it may be a tad biased to certain situations. It is mostly designed for small areas with few concurrent instanced rooms. This may be distributed freely and used any way you like. No warranties though, so don't come crying to me if your house blows up Wink


WHAT IT DOES:
It allows certain rooms to be 'instanced' whereby each person entering can go to their own unique copy of a room. Parties can all enter the same copy if they group up in advance. Best of all, most any basic room can easily be converted to an instanceable version by simply changing one line of code!


WHAT IT COMPRISES:
Instance Server Daemon:
-The object responsible for tracking who belongs to what instances, cleanup of empty instances, and doling out new instances and instance rooms.

Instance:
-A object used to identify a player or group of players and all of the rooms they have allocted to themselves.

Instance Room:
-An individual room that exists as a clone of the original and belongs to an instance.

HOW TO USE:
1)Place the files 'instance.c', 'instance_room.c', 'living_instance.c', and 'instance_server.c' where you want them. Put 'instancerooms.h' in /lib/include.
2)Add the instance_server.c to the preload list.
3)Adjust the file names and directories within 'instancerooms.h' to match whatever you need.
3)Add LIB_LIVINGINSTANCE to the inherit list of 'living.c'
4)Within 'living.c->eventMoveLiving()' you'll need to add the folowing:
Code:
//This function calls eventMoveLiving with an instance if passed a master copy.
//However, it will simply return 0 if passed a cloned room.
if(instResult = this_object()->eventRegisterInstance(dest,omsg,imsg,dir))
{
return instResult;
}
I suggest right after the GUARD_D check but before anything else.

5)For any room that you want to be instanced, inherit LIB_INSTANCEROOM instead of LIB_ROOM
6)Come here and yell at me when I forget a step.
7)Reboot and you're set!


HOW IT WORKS:
Basically, when a player enters a room though 'living.c->eventMoveLiving()' a few lines of code check to see if that room is derived from LIB_INSTANCEROOM. If so, it goes though a checklist of things to do. The two main ones are as follows:

-Does the player already belong to an instance? If not, create one and register it with the daemon. Also the player with the new instance. Registrations is determined by party name first and user name if there is no party. In this way multiple people in the same party can be registered with a single instance once any one of them enters.

-Does the room already exist for this instance? Is so, obtain it and send the player their, otherwise we have to clone a new one.

If the player enters and regular room, they will automgaically be unregistered from their instance. If all players attached to that instance are gone the instance will self destruct.

The instance server daemon will occasionally trigger a few instance objects to go through their rooms. If the instance finds there are no players present in any of its rooms it will be destroyed.

Take note: Instances and the instance server daemon have no knowledge or concern for domains. All instance rooms that are loaded by a single person or group are loaded within the same instance.



This post is getting long so I'm going to make another with the files as well as a list of known issues.
Logged
Sluggy
Friend
**
Offline Offline

Posts: 59



View Profile
« Reply #6 on: August 08, 2009, 10:53:11 PM »

Part two of the above post.

ISSUES:
-I haven't tested any room code that references itself using this_object() yet.

-Warmboots will destroy instance objects and send anyone in an instanced room to the furnace. Ouch.

-Any teleporting abilities should use 'living.c->eventMoveLiving()' if they want instances to work properly with them.
 
-Not sure what kind of effect 'reclaim_objects()' will have on instance objects and instanced rooms.

-Only interactive living objects are allowed to enter instance rooms. This was done as a simple way of diabling NPCs from accidentally generating instances if they wandered into one. This means pets and non-player followers won't be able to follow without some additional modifications to 'instance_server.c->CreateInstance()'.

-Originally the player would simply be sent to an instance based on their InstanceID string. However this left a vulnerability for malicious players to use. They could repeatedly change their party name and enter new instanced room in order to build up a large number of instances. To stop this, I added the 'InstanceObject', a simple reference to the last instance the player entered. As long as they are moving within an instance room this will be left untouched. The system checks this object first to see if a currently existing instance exists and defaults to the InstanceID string only when that fails. This reference is reset when they enter a non-instance room. In this way the player can only create and enter a new instance after they have left an old one.
 
-Instances are cleaned up as soon as all players leave by entering a non-instanced room. None of the rooms are cleaned up until then.
 
-Haven't tested to see if the reaper will cleanup the rooms while players are in them. I tried to fend off the reaper by simply making instances a container and placing the room instances within it (the eventMove functoin has been overriden to allow instanced rooms to be moved). Perhaps I could have just made the rooms daemons. I don't really know. Any advice?

-The instance server destroys an instance when all memebers leave it. The only way for it to know is the players' 'eventMoveLiving' function is called. This function will inform the instance when a member leaves it by entering a non-instanced room. If the player(s) were to be teleported out in some fashion that does not call this, the instance would never know and could continue to exist. This could be exploited by malicious players.
 
 To a degree this has been combated in the server daemon. It occasionally checks some of the instances and passes through all of the belonging memebers. If they are no longer active, existant, or in an instanced room. The instance will be destroyed. With some modification this feature may be helpful for fixing the issue of a large build up of empty instance rooms.
 
-Malicious player may be able to quit while in an instance (thus stopping it from auto-destructing it), log back into a non-instanced room, change their party name, and re-enter a new instance. Doing this repeatedly will build up a large bumber of instances.

-All instanced rooms are stored within the same instance regardless of where they are or how the player entered. Because no rooms are deleted until all members of the instance leave, it may be possible to build up a rather large collection of rooms before anything gets cleaned up if the number of concurrent instanced rooms is high.

-All instances are registered and created when a player enters an instance room and the server has no record of their party or name. It is possible for malicious players to contantly change their party status and move into different instance rooms in order to build up a large number of instances.

-The 'master copy' of the room to be instanced is never stored anywhere so it is likely to be destrcuted by the reaper at one point or another. All of the referencing in the instances is dones with the filename however so this isn;t an issue most of the time. However, if you want that room to stick around for some additional features like a global room registery in the server you'll need to rework the 'eventMove' override in  instance_room.c and allow non-instanced rooms to be moved. From there, you should be able to setup some kind of inventory within the


instance_server.c
Code:
/*
By: SLUGGY
Distributed under WTFPL. No warranties.
2009

Daemon that allocates and manages instanced areas.
*/

#include <lib.h>
#include <daemons.h>
#include <rooms.h>
#include <instancerooms.h>


inherit LIB_DAEMON;



static mixed AddPlayer(object player);
void SetDomain(string name);
void CleanInstances();


//'Players' tracks all players that are in an instance and to what instance they currently belong
//private mapping Players = ([]);

//'Instances' tracks all instances running and references them by hash IDs. These ids are generated
//for each idividual that enters and instance room as well as for the first member of a party. In the
//case of an individual, their name is the key, for a party, the party name plus the domainname is the key.
//In this way, party members can all enter the same instance if they are at the same domain.
private mapping Instances = ([]);

//'Owners' keeps another list of each instance id like above, but this one simply stores a reference
//to all players currently within that instance.
//private mapping Owners = ([]);


private int CalloutHandle;
private int StartRange = 0;


static void create()
{
::create();

//TODO: setup a callout here to periodically check for empty instances and clean them up when need be
CalloutHandle = call_out("CleanInstances",CLEANUP_FREQU);
}

void init()
{
}

void CleanInstances()
{
int count = StartRange;
int max = sizeof(values(Instances));
string* cleanList = ({});

//TODO: There could probably be quite a few optimiztions made here

//build a list of rooms to clean
foreach(string key in keys(Instances))
{
object inst = Instances[key];

//NOTE: This instance may self destruct after this point,
if(inst->InstanceClean())
{
cleanList += ({key});
}

StartRange++;
if(StartRange > max)
{
StartRange = 0;
}
count++;
if(count > INSTANCE_CLEAN_CHUNK)
{
break;
}
}

//now cleanup the list
foreach(string key2 in cleanList)
{
//this will call RemoveInstance() for us.
Instances[key2]->eventDestruct();
}

remove_call_out(CalloutHandle);
CalloutHandle = call_out("CleanInstances",CLEANUP_FREQU);
}


int RemoveInstance(string name)
{
map_delete(Instances,name);
return 1;
}


/*
Create a new clone of a given master copy room (it's filename). Register it under the instance given.
This function assumes a copy doesn't already exist for this instance object.
*/
object CreateInstanceRoom(string masterRoom,object instance)
{
object room;
if(!masterRoom || !stringp(masterRoom)) return 0;
if(!instance || !objectp(instance)) return 0;
if( (room = new(masterRoom)) )
{
room->Register(masterRoom,instance);
}
else{
error("Failed to create room instance object for " + masterRoom + ". instance_server->CreateInstanceRoom().");
}
return room;
}



/*
If a particular clone of a room belonging to the instance exists return it, otherwise
create a new one, register it with the instance and return that.
*/
object GetInstanceRoom(string masterRoom,object instance)
{
mapping roomMap;

if(!masterRoom || !stringp(masterRoom)) return 0;
if(!instance || !objectp(instance)) return 0;

roomMap = instance->GetRoomsMap();
if(roomMap && mapp(roomMap) )
{
foreach(string str in keys(roomMap))
{
if(str == masterRoom)
{
return roomMap[str];
}
}
}
return CreateInstanceRoom(masterRoom,instance);
}



/*
Return an instance object if the player belongs to one. Othwerwise, zero.
*/
object PlayerBelongsToInstance(object player)
{
object instance;
if(!player || !objectp(player)) return 0;

if( (instance = player->GetInstanceObject()) ) return instance;
else{
string id = player->GetInstanceID(1);
if(member_array(id,keys(Instances)) == -1)
{
return 0;
}
return Instances[id];
}
return 0;
}



/*
Create a new instance and register it under the player's party name or actual name.
This function assumes that it has already been confirmed that the instance doesn't exist.
*/
object CreateInstance(object player)
{
string id;
object instance;
if(!player || !objectp(player) || !interactive(player)) return 0;

if(sizeof(keys(Instances)) > MAX_INSTANCE_ALLOCATION)
{
//TODO: print the date here
string temp = "Instance allocation limit was hit by " + player->GetName() + "(" + player->GetInstanceID() + ").";
tc(temp);
tell_object(player,INSTANCE_UNAVAILABLE_MSG);
return 0;
}

if(! (instance = new(OBJ_INSTANCE)) )
{
error("Failed to create instance object. Player: " + player->GetName() + ", Party: " + player->GetParty() + ", InstanceID: " + player->GetInstanceID(1) + ".");
return 0;
}

id = player->GetInstanceID(1);
instance->SetInstanceID(id);
player->Register(instance);
Instances[id] = instance;
return instance;
}



/*
If an instance to which the player is registered exists return it, otherwise
create a new one and return that.
*/
object GetInstance(object player)
{
object instance;
if( (instance = PlayerBelongsToInstance(player)) ) return instance;

return CreateInstance(player);
}


instance.c
Code:
/*
By: SLUGGY
Distributed under WTFPL. No warranties.
2009

Manages all of the rooms and players within a single instance.
*/

#include <lib.h>
#include <rooms.h>
#include <instancerooms.h>

inherit LIB_DAEMON;
inherit LIB_CONTAINER;

//this will either be set to the party name of the first person to enter
//or the name of a single person that was in no party
private string RegisteredName = 0;

//[master room's filename : cloned object]
private mapping Rooms = ([]);

//references to all players that are part of this instance
private object* Owners = ({});


static void create()
{
::create();

//just in case this is derived by something that might be cleaned :O
SetNoClean(1);
}

void init()
{
}

int SetInstanceID(string name)
{
if(name && stringp(name) && name != "")
{
RegisteredName = name;
return 1;
}
return 0;
}

int eventDestruct()
{
/*
if(checkFlag)
{
foreach(object room in values(Rooms))
{
if(room && objectp(room))
{
//TODO: make absolutely sure that all players are gone from the room
//      if not, then we need to cancel the destruct and re-add these
// players to the 'Owners' list.
//return 0;
}
}
}
*/

INSTANCE_SERVER_D->RemoveInstance(RegisteredName);
return ::eventDestruct();
//destruct(this_object());
}

int AddPlayer(object player)
{
if(player && objectp(player))
{
if(member_array(player,Owners) == -1) Owners += ({ player });
return 1;
}
return 0;
}

int RemovePlayer(object player)
{
if(player && objectp(player))
{
if(member_array(player,Owners) != -1)
{
Owners -= ({ player });
}

if(sizeof(Owners) < 1)
{
eventDestruct();
}
return 1;
}
return 0;
}

object* GetOwners()
{
return Owners;
}

int AddRoom(string masterName,object room)
{
if(!masterName || !stringp(masterName) || !sizeof(masterName)) return 0;
if(room && objectp(room) && room->IsInstanceableRoom() && room->IsInstanced())
{
if(member_array(masterName,keys(Rooms)) != -1)
{
//entry already exists
return 1;
}
Rooms[masterName] = room;
//room->eventMove(this_object()); //put the instanced-room in the instance's inventory
return 1;
}
return 0;
}

int RemoveRoom(string masterName)
{
if(!masterName || !stringp(masterName) || !sizeof(masterName)) return 0;
if(member_array(masterName,keys(Rooms)) == -1) return 0;
//TODO: make absolutely sure that all players are gone from the room
//      if not, then we need to cancel the destruct and re-add these
// players to the 'Owners' list.
map_delete(Rooms,masterName);
//room->eventDestruct();
return 1;
}

mapping GetRoomsMap()
{
return Rooms;
}

int IsInstance()
{
return 1;
}

int InstanceClean()
{
if(!sizeof(Owners))
{
return 1;
}

foreach(object room in values(Rooms))
{
foreach(object dude in livings(room))
{
//if there are any players in any rooms then we shouldn't allow cleanup
if(interactive(dude)) {return 0;}
}
}
return 1;
}

instance_room.c
Code:
/*
By: SLUGGY
Distributed under WTFPL. No warranties.
2009

Instanced room. This room is set to not be cleaned by the GC, stores a reference to it's instance master
and registers itself with that master. All exits generate additional rooms within the instance.
*/

#include <lib.h>
#include <rooms.h>

inherit LIB_ROOM;

private object InstanceObject;
private int InstanceActive = 0;
private int PartyAllowed = 1;

static void create()
{
::create();

SetNoClean(1);
SetNoReplace(1);
}

static void init()
{
::init();
}

int eventDestruct()
{
if(this_object())
{move_object(ROOM_FURNACE);}
::eventDestruct();
}

int SetPartyAllowed(int flag)
{
return (PartyAllowed = flag);
}

int GetPartyAllowed()
{
return PartyAllowed;
}

int Register(string masterRoom,object instance)
{
if(!instance || !objectp(instance))
{
error("Invalid instance master passed to " + this_object()->GetSHort() + ". instance_room.c->Register().");
return 0;
}

move_object(instance);
InstanceObject = instance;
InstanceActive = 1;
InstanceObject->AddRoom(masterRoom,this_object());

return 1;
}

int Unregister()
{
if(!InstanceObject || !objectp(InstanceObject))
{
error("Master InstanceObject reference in " + this_object()->GetShort() + " is invalid. instance_room.c->Unregister().");
return 0;
}

//NOTE: After this point, the instance may have self-destructed so do not try to access it again.
InstanceObject->RemoveRoom(this_object());
InstanceActive = 0;
eventDestruct();
return 1;
}


int IsInstanced()
{
return InstanceActive;
}

int IsInstanceableRoom()
{
return 1;
}
/*
int eventMove(object dest)
{
if(dest && objectp(dest) && dest->IsInstance())
{
if(IsInstanced())
{
move_object(dest);
return 1;
}
}

return 0;
}
*/

living_instance.c
Code:
/*
By: SLUGGY
Distributed under WTFPL. No warranties.
2009

Provides a few utility functions used by the stock 'living.c' file for checking
if a creature is entering an instancable room as well as storing instance data.
*/

#include <lib.h>
#include <instancerooms.h>

private object InstanceObject = 0;

void SetInstanceObject(object inst)
{
InstanceObject = inst;
}

object GetInstanceObject()
{
return InstanceObject;
}

string GetInstanceID(int partyAllowed)
{
if(partyAllowed)
{
string party = this_object()->GetParty();
if(party && stringp(party) && sizeof(party) > 0)
{
return party;
}
}

return this_object()->GetName();
}

int Register(object instance)
{
if(!instance || !objectp(instance))
{
error("Invalid instance master passed to " + this_object()->GetName() + ". livinginstance.c->Register().");
return 0;
}
InstanceObject = instance;
InstanceObject->AddPlayer(this_object());
return 1;
}

int Unregister()
{
if(InstanceObject && objectp(InstanceObject))
{
//NOTE: After this point, the instance may have self-destructed so do not try to access it again.
InstanceObject->RemovePlayer(this_object());
InstanceObject = 0;
return 1;
}
return 0;
}

/*
Called by living.c->eventMoveLiving(). This function should return true if the player
is moved to a cloned instance room and false if not. And value of false signifies to that
caller that it can continue as normal and move the player into a non-instanced room. Otherwise
it will just return this function's return value.
*/
varargs int eventRegisterInstance(mixed dest, string omsg, string imsg, mixed dir)
{
object player = this_object();
object inst;
object room;
string instID;

//if this destination isn't an instance-room we can unregister any previous instance master
//and return false to let the player move into the room normally
if(!dest->IsInstanceableRoom())
{
Unregister();
return 0;
}

//Make sure this isn't a recursive call due to the below call to 'eventMoveLiving'. if that is
//the case, then this destination will be a clone rather than the master copy and as such we simply
//want the player to enter the destination provided to the function that called this one.
if(dest->IsInstanced())
{
return 0;
}


//TODO: Should check the room's flag to see if parties are allowed to instance together

if( (inst = INSTANCE_SERVER_D->GetInstance(player)) )
{
room = INSTANCE_SERVER_D->GetInstanceRoom((string)dest,inst);
if(!room || !objectp(room))
{
error("Failed to create or obtain instance of a room. livinginstance->eventEnterInstance().");
tell_object(player,INSTANCE_FAILED_MSG);
return 1;
}
if(!player->GetInstanceObject())
{
player->Register(inst);
}
return player->eventMoveLiving(room,omsg,imsg,dir);
}
else{
error("Could not obtain instance.");
tell_object(player,INSTANCE_FAILED_MSG);
return 1; //we still return 1 so player still can't enter master copy of room
}
//this lets the calling function, living->eventMoveLiving(), know that it can should not
//proceed as normal so that the player isn't moved into the master copy of the room by mistake.
return 1;
}

instancerooms.h
NOTE: Don't forget to change the directories to where you want them. Also remember that single empty line you need at the end of the file after the #endif Wink  That one always gets me.
Code:
/*
By: SLUGGY
Distributed under WTFPL. No warranties.
2009
*/
#ifndef __INSTANCEROOMS_H
#define __INSTANCEROOMS_H

#define INSTANCE_SERVER_D "/lib/instances/instance_server.c"
#define OBJ_INSTANCE "/lib/instances/instance"
#define LIB_INSTANCEROOM "/lib/instances/instance_room"

#define MAX_INSTANCE_ALLOCATION 50
#define INSTANCE_CLEAN_CHUNK 5
//attempt cleanup approx every fifteen minutes
#define CLEANUP_FREQU 900

#define INSTANCE_UNAVAILABLE_MSG "%^BLACK%^The server is too busy to provide an instance right now. Please wait a bit before trying to enter again. Thank you.%^RESET%^"
#define INSTANCE_FAILED_MSG "%^BLACK%^There was a problem creating an instance for you. Please inform mud staff (ERROR: instance #1). Thank you. %^RESET%^"
#define INSTANCEROOM_FAILED_MSG "%^BLACK%^There was a problem creating a room instance for you. Please inform mud staff (ERROR: instance #2). Thank you. %^RESET%^"



#endif



If I forgot anything lemme know. I sometimes do dumb things like that.
Logged
daelaskai
BFF
***
Offline Offline

Posts: 168


View Profile
« Reply #7 on: August 09, 2009, 03:08:46 AM »

Sluggy,

This is interesting.  I think you could have done this without any modification to the player's
eventMoveLiving() function.  For instance, DS has CanReceive() and CanRelease() functions
that, in my opinion, would work just as well.  I applaud the work you have done.  It looks
fairly neat and straightforward.  We appreciate the contribution to the community.  I think
it would be interesting to see how this compares to the instancing system that Nulvect
mentioned earlier.  I look forward to testing this soon.

Daelas
Logged
Sluggy
Friend
**
Offline Offline

Posts: 59



View Profile
« Reply #8 on: August 09, 2009, 05:51:50 AM »

Thanks and you're welcome.

I think at one point I had planned to use CanReceive() but decided that it wouldn't work out. At the time though, I hadn't planned on having the central server. When I realized that I needed to change a few things, I ended keeping whatever code I could that still worked, namely the change to living.c. I had briefly considered trying to stick it somewhere in the 'exits.c' object but that didn't even make it past the drawing board. Maybe if I get time I'll go back and try it the way you suggest.
Logged
quixadhal
BFF
***
Offline Offline

Posts: 218



View Profile
« Reply #9 on: August 09, 2009, 08:07:24 AM »

Very nice Sluggy!

-All instances are registered and created when a player enters an instance room and the server has no record of their party or name. It is possible for malicious players to contantly change their party status and move into different instance rooms in order to build up a large number of instances.

Hmmmm.... thinking. Smiley

Currently, the instance daemon doesn't have any concept of what rooms belong to what instances, right?  That is, you get a new instance when you enter ANY instanced room (and aren't already in one), and you stay in that instance until you hit a non-instance room.

If you allowed rooms to specify a global instance ID, you could then allow non-contiguous instances.  It would also give you a handle to use for solving the above problem.  If your instance ID (temporary) were generated as a combination of the global ID + the player's name (or the party leader's name), exiting and re-entering would always land them in the same one.  Changing party names or other such wouldn't matter, since the only way to be in a different one is to change parties... and being solo means you are your own party leader, so that can't change.

It would also allow you to lock people out of instances if they're already part of a different instance.  For example, I setup an instance dungeon called "FooMines" and my party ventures into them.  I wander out to get supplies and stumble upon another instance called "BarMines".  I would guess that most game admins would want me to not be allowed into this instance while I'm still "doing" the other one.

I could quit the party and lose access to the first instance to enter the second.  Doing that would also require (silently) renaming the original instance to be the NEW party leader's name + ID, as well as the variables in each player still there, IF I was the original party leader.

It could also be used to check if the instance is indeed empty, since players listed as being "in" the instance could be checked to see if their current environment is an instance room with the same ID tag.

I dunno... I'm rambling a bit I suppose.  I think something up there might have been useful, but maybe not.  Nice job though!
Logged

Sluggy
Friend
**
Offline Offline

Posts: 59



View Profile
« Reply #10 on: August 09, 2009, 06:17:47 PM »

Quote
Quote from: Sluggy on August 08, 2009, 10:53:11 PM
-All instances are registered and created when a player enters an instance room and the server has no record of their party or name. It is possible for malicious players to contantly change their party status and move into different instance rooms in order to build up a large number of instances.

Hmmmm.... thinking. Smiley


Heh whoops. Sorry. That actually isn't a problem anymore. It was a note I left to myself and forgot to remove (based on all the spelling mistakes it must have been pretty late when I wrote all of this Wink ).

In one of the previous bullet points I mentioned how the player now has a InstanceObject that references the current instance to which they belong. The room won't check the party name/user name until after it has checked this instance. In effect it does exactly what you described but in a slightly different manner. The instance is aware of what copies of what rooms it has and they are all stored in a map that is reference by the master copy's filename. So you can never spawn two copies of the same room in the same instance. It also has a list of all players currently within that instance. The server has a list of all instances and the player has an object to any instance in which they currently exist. In theory this should be enough that any object can identify any other object in the system. However, if something gets out of sync that's when it all falls down.

For example, if the player logs out and the room specifies a different login location, it may be possible for them to log back in, create a new party and re-enter and create a new instance. Rinse, repeat. This could be avoided by doing something in the logout code to see if the instance is empty I suppose.


BTW: Is anyone aware of a bug with the party system in DS 2.9a31? Apparently when I create a party if I warmboot or reset the server without disbanding it first, that name can never be used for a party again.
« Last Edit: August 09, 2009, 06:19:28 PM by Sluggy » Logged
Pages: [1]   Go Up
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.11 | SMF © 2006-2009, Simple Machines LLC Valid XHTML 1.0! Valid CSS!