Account management for pfiles: Suggestions?
< Newer Topic
:: Older Topic >
Pages:<< prev 1 next >>
#1 Oct 18, 2011 9:13 am
Magician
GroupMembers
Posts239
JoinedJun 13, 2008
I was wondering if anyone had decent luck with a connection account for swfotefuss?
That was one of the major things I'd like to get accomplished in my conversion rather than having each player log into their character directly. They'd connect to an account and from there log into one of their characters. I know quite a few current games offer such account systems...
I'll admit I am looking for a pretty easy drop in and run solution with a few tweaks here and there.While I'd love to try and whip up something from scratch is likely beyond my limited abilities. I'm just not sure whats going on with descriptors and all that fun jazz. Pretty low level stuff compared to what I'm used to mucking about with.
Thanks,
ayuri
That was one of the major things I'd like to get accomplished in my conversion rather than having each player log into their character directly. They'd connect to an account and from there log into one of their characters. I know quite a few current games offer such account systems...
I'll admit I am looking for a pretty easy drop in and run solution with a few tweaks here and there.While I'd love to try and whip up something from scratch is likely beyond my limited abilities. I'm just not sure whats going on with descriptors and all that fun jazz. Pretty low level stuff compared to what I'm used to mucking about with.
Thanks,
ayuri
#2 Oct 18, 2011 4:34 pm
Conjurer
GroupMembers
Posts398
JoinedMar 8, 2005
I dunno if anyone has plugin code for you, but the idea is simple enough.
Just add a new state to the login sequence, so instead of being a characer name, it gets a login/user name and checks a new file directory where you'll keep user accounts. After successfully logging in or creating a new user, you'd have the old character name state where it gets which character you want to log into.
The difference is, character names not stored in the user file would be rejected. If you want to be fancy, you could print a listing of existing names and let the user pick them by number as well.
Each character would need to have a new field to refer back to the owning user.
Just add a new state to the login sequence, so instead of being a characer name, it gets a login/user name and checks a new file directory where you'll keep user accounts. After successfully logging in or creating a new user, you'd have the old character name state where it gets which character you want to log into.
The difference is, character names not stored in the user file would be rejected. If you want to be fancy, you could print a listing of existing names and let the user pick them by number as well.
Each character would need to have a new field to refer back to the owning user.
#3 Oct 19, 2011 8:02 pm
Magician
GroupMembers
Posts239
JoinedJun 13, 2008
So I've hacked together bits and parts taking the idea's from the account file snippet I found over on mudbytes.Accounts seem to be loading, even have it where I can reward them with RP Points (YAY!). However, I'm having issues with do_quit function of act_comm.c . . . GRRR
What I'm trying to do is once your ready to quit, have you return back to the account screen. I thought it would be as simple as changing your descriptor once your character has quit to point back to CON_ACCOUNT_PENDING. Like whats in the patch file.
However, that isn't working. Anyone willing to offer some insight?
This is the code in question:
Thanks in advance,
ayuri
What I'm trying to do is once your ready to quit, have you return back to the account screen. I thought it would be as simple as changing your descriptor once your character has quit to point back to CON_ACCOUNT_PENDING. Like whats in the patch file.
However, that isn't working. Anyone willing to offer some insight?
This is the code in question:
void do_quit( CHAR_DATA * ch, const char *argument ) { OBJ_DATA *obj; OBJ_DATA *obj_next; int x, y; int level; char qbuf[MAX_INPUT_LENGTH]; CHAR_DATA *fch; if( IS_NPC( ch ) && IS_SET( ch->act, ACT_POLYMORPHED ) ) { send_to_char( "You can't quit while polymorphed.\r\n", ch ); return; } if( IS_NPC( ch ) ) return; if( ch->position == POS_FIGHTING ) { set_char_color( AT_RED, ch ); send_to_char( "No way! You are fighting.\r\n", ch ); return; } if( ch->position < POS_STUNNED ) { set_char_color( AT_BLOOD, ch ); send_to_char( "You're not DEAD yet.\r\n", ch ); return; } if( auction->item != NULL && ( ( ch == auction->buyer ) || ( ch == auction->seller ) ) ) { send_to_char( "Wait until you have bought/sold the item on auction.\r\n", ch ); return; } if( !IS_IMMORTAL( ch ) && ch->in_room && !IS_SET( ch->in_room->room_flags, ROOM_HOTEL ) && !NOT_AUTHED( ch ) ) { send_to_char( "You may not quit here.\r\n", ch ); send_to_char( "You will have to find a safer resting place such as a hotel...\r\n", ch ); send_to_char( "Maybe you could CALL a speeder.\r\n", ch ); return; } set_char_color( AT_WHITE, ch ); send_to_char ( "Your surroundings begin to fade as a mystical swirling vortex of colors\r\nenvelops your body... When you come to, things are not as they were.\r\n\r\n", ch ); set_char_color( AT_SAY, ch ); ch_printf( ch, "A strange voice says, 'We await your return, %s...'", ch->name ); // act( AT_BYE, "$n has left the game.", ch, NULL, NULL, TO_ROOM ); // set_char_color( AT_GREY, ch); if( ch->challenged ) { sprintf( qbuf, "%s has quit! Challenge is void!", ch->name ); ch->challenged = NULL; sportschan( qbuf ); } for( fch = first_char; fch; fch = fch->next ) { if( IS_NPC( fch ) ) continue; if( fch->challenged && fch->challenged == ch ) fch->challenged = NULL; } sprintf( log_buf, "%s has quit.", ch->name ); if(ch->desc) quitting_char = ch; save_char_obj( ch ); save_home( ch ); if( ch->plr_home ) { for( obj = ch->plr_home->first_content; obj; obj = obj_next ) { obj_next = obj->next_content; if( obj->item_type == ITEM_SPACECRAFT ) continue; extract_obj( obj ); } } saving_char = NULL; level = get_trust( ch ); //Account screen return ? if(ch->desc) ch->desc->connected = CON_ACCOUNT_PENDING; /* * After extract_char the ch is no longer valid! */ extract_char( ch, TRUE ); for( x = 0; x < MAX_WEAR; x++ ) for( x = 0; x < MAX_WEAR; x++ ) for( y = 0; y < MAX_LAYERS; y++ ) save_equipment[x][y] = NULL; /* * don't show who's logging off to leaving player */ /* to_channel( log_buf, CHANNEL_MONITOR, "Monitor", level ); */ log_string_plus( log_buf, LOG_COMM, level ); return; }
Thanks in advance,
ayuri
#4 Oct 20, 2011 3:08 am
Magician
GroupMembers
Posts132
JoinedJan 29, 2006
I haven't looked at said account snippet, but maybe you need to modify the extract_char function? As far as I recall there's some code at the bottom that closes the socket. You could do some magic there to ensure you get back to the account menu rather than closing the socket.
#5 Oct 20, 2011 1:26 pm
Magician
GroupMembers
Posts239
JoinedJun 13, 2008
Hmm...See now why didn't I think to look at extract_char. Bah! I'm such a noob, I even missed it in that snippet code.
Well, with that I'm happy to say that it seems like almost all of the support code for accounts is up and running. Now just need to modify rpconvert to take advantage of it (simple I hope).
Thank you,
ayuri
Well, with that I'm happy to say that it seems like almost all of the support code for accounts is up and running. Now just need to modify rpconvert to take advantage of it (simple I hope).
Thank you,
ayuri
#6 Oct 22, 2011 5:19 pm
Last edited Oct 22, 2011 5:20 pm by ayuri
Magician
GroupMembers
Posts239
JoinedJun 13, 2008
Hmm, seems I've not thought about rewarding RPP all the way though. Right now, since its stored as account data, and account data is accessed via ch->desc->account, when one uses 'loadup ' to reward them the game crashes as its looking for a descriptor which naturally isn't there, or any command that's trying to pull account data.
I am drawing a blank on how to add the account junk to loadup so that its valid?
Welcome to ideas, and not afraid to break something,
ayuri
I am drawing a blank on how to add the account junk to loadup so that its valid?
Welcome to ideas, and not afraid to break something,
ayuri
#7 Oct 24, 2011 1:12 am
Sorcerer
GroupMembers
Posts600
JoinedDec 3, 2008
You are going to need to run gdb.
#8 Oct 24, 2011 1:42 am
Last edited Oct 24, 2011 1:44 am by ayuri
Magician
GroupMembers
Posts239
JoinedJun 13, 2008
Naa, I know why the descriptor is invalid because its set to NULL in the code from do_loadup. Nothing is actually open and pointing to 'd'.
I was originally thinking that I wanted to see if I could fake the descriptor to something just so I could write to the account file directly. However, I've come up with a better(?) solution. Since I didn't remove the rppoints from CHAR_DATA, why not use it? It seems so obvious, I don't know why I didn't think of it at first.
Basically tossed in a check to reward to look for ch->desc != NULL. IF its null then we reward to the pfile, if its not null then we reward to the account. As I understand it, the descriptor should be valid as long as there is a connection. If we try to reward a linkdead player, it writes out to their pfile.
When the player loads that character, in the account start-up, after it runs load_char_obj looks for if(d->character->rppoints != 0) and then sums them up to d->account->points. As of right now, it won't do anything if an imm loads them up and they reconnect in the loadup process as they are already playing. I honestly don't see that as a big deal, however if players do start to complain about it, then I'll do something about it.
The downside of this system is that if someone who posts a log gets rewarded on someone who doesn't play very often, well there is a chance they could be missing some rpp. However, if they were expecting some RPP on that character, then it should be up to them to check that they received on it.
I even added a nice little line right before the title/motd print saying 'Some RPP were moved from this Character to your account!'.
I'm still interested in if anyone has a better way of going about it.
ayuri
I was originally thinking that I wanted to see if I could fake the descriptor to something just so I could write to the account file directly. However, I've come up with a better(?) solution. Since I didn't remove the rppoints from CHAR_DATA, why not use it? It seems so obvious, I don't know why I didn't think of it at first.
Basically tossed in a check to reward to look for ch->desc != NULL. IF its null then we reward to the pfile, if its not null then we reward to the account. As I understand it, the descriptor should be valid as long as there is a connection. If we try to reward a linkdead player, it writes out to their pfile.
When the player loads that character, in the account start-up, after it runs load_char_obj looks for if(d->character->rppoints != 0) and then sums them up to d->account->points. As of right now, it won't do anything if an imm loads them up and they reconnect in the loadup process as they are already playing. I honestly don't see that as a big deal, however if players do start to complain about it, then I'll do something about it.
The downside of this system is that if someone who posts a log gets rewarded on someone who doesn't play very often, well there is a chance they could be missing some rpp. However, if they were expecting some RPP on that character, then it should be up to them to check that they received on it.
I even added a nice little line right before the title/motd print saying 'Some RPP were moved from this Character to your account!'.
I'm still interested in if anyone has a better way of going about it.
ayuri
#9 Oct 26, 2011 5:40 pm
Magician
GroupMembers
Posts239
JoinedJun 13, 2008
Ok, well now I'm fully stumped. I'm trying to allow multi-playing though the account system so that each player tied to the account shares RPP. Here's my current situation: Two players connect using the same account 'test', players are called player1 and player2 to help me explain. I reward player1 10 rpp. Player1 types 'account' to display account info and they see 10 rpp listed. Player2 types 'account' and they show 0 rpp. I look at the physical account file, the account file saved to disk shows 10 rpp.
Its my understanding since the data is being written to the file, anyone on that account should be able to see updated data...I have this feeling I'm missing something simple here, but I'm just not seeing it.
Here's some of the relevant code, if you wish to see more let me know.
First up, the reward function so you can see that its saving the account:
Ok, so, lets take a peek at saving the account:
Lastly, lets take a peek at the 'accountstat' command code for in game.
Maybe I'm just not understanding something here. I've looked at setship for an example, you set the ship, the ship saves the data via save_ship and then you stat the ship and the changes show up with out having to reload the ship file, shouldn't I be able to do the same with account files? Granted, descriptor and character names will be different, but they are all pointing back to account->name, so it should then pull the most current info. . . Right?
Thanks in advance,
ayuri
Its my understanding since the data is being written to the file, anyone on that account should be able to see updated data...I have this feeling I'm missing something simple here, but I'm just not seeing it.
Here's some of the relevant code, if you wish to see more let me know.
First up, the reward function so you can see that its saving the account:
void do_reward( CHAR_DATA *ch, const char *argument ) { DESCRIPTOR_DATA *d; ACCOUNT_DATA *account; CHAR_DATA *victim; char arg[MSL]; int value; argument = one_argument( argument, arg ); if( arg[0] == '\0' ) { send_to_char("&wreward\r\n", ch); return; } if( ( victim = get_char_world( ch, arg ) ) == NULL ) { send_to_char( "They aren't here.\r\n", ch ); return; } if( IS_NPC( victim ) ) { send_to_char( "Not on NPC's.\r\n", ch ); return; } if( argument[0] == '\0' ) { send_to_char("&wreward \r\n", ch); return; } value = atoi( argument ); if( value < -500 || value > 1000 ) { send_to_char("&wInvalid range. Try -500 to 1000.\r\n", ch ); return; } if( value == 0 ) { send_to_char("&wWhat is the use in that?\r\n", ch ); return; } if( victim->desc == NULL) { victim->rppoints += value; sprintf (log_buf, "%s rewarded to pfile.", victim->name); log_string( log_buf ); if( value > 0 ) ch_printf(ch, "&GYou've rewarded %s with %d points.\r\n", victim->name, value ); if( value < 0 ) ch_printf(ch, "&GYou've deducted %d points from %s.\r\n", value, victim->name); } if (victim->desc != NULL) { d = victim->desc; account = d->account; account->points += value; save_account(account); if( value > 0 ) { ch_printf(ch, "&GYou've rewarded %s (%s) with %d points.\r\n", victim->name, victim->desc->account->name, value ); ch_printf(victim, "&G%s has rewarded your account with %d points.\r\n", ch->name, value ); } if( value < 0 ) { ch_printf(ch, "&GYou've deducted %d points from %s (%s).\r\n", value, victim->name, victim->desc->account->name ); ch_printf(victim, "&G%s has deducted %d points from your account.\r\n", ch->name, value ); } } return; }
Ok, so, lets take a peek at saving the account:
void save_account(ACCOUNT_DATA *acc) { FILE *fp; ACC_CHAR_DATA *ch; char filename[256]; if(!acc) return; sprintf(filename, "%s%c/%s", ACCOUNT_DIR, tolower(acc->name[0]), capitalize(acc->name)); if( ( fp = fopen( filename, "w" ) ) == NULL ) { bug( "save_account: fopen", 0 ); perror( filename ); } else { fprintf(fp, "Name %s~\n", acc->name); fprintf(fp, "Password %s~\n", acc->password); for(ch = acc->first_acc_char; ch; ch = ch->next) fprintf(fp, "Char %s~\n", ch->name); fprintf(fp, "Host %s~\n", acc->host); fprintf(fp, "Last_played %s~\n", acc->last_played); fprintf(fp, "Multiplay %d\n", acc->multiplay); fprintf(fp, "Points %d\n", acc->points); fprintf(fp, "End\n" ); fclose(fp); fp = NULL; } return; }
Lastly, lets take a peek at the 'accountstat' command code for in game.
void do_accountstat( CHAR_DATA *ch, const char *argument ) { ACCOUNT_DATA *account; CHAR_DATA *victim; ACC_CHAR_DATA *ach; if( !argument || argument[0] == '\0' ) victim = ch; else if( IS_IMMORTAL( ch ) ) { if( ( victim = get_char_world( ch, argument ) ) == NULL || victim->desc == NULL) { send_to_char( "Victim not found.\r\n", ch ); return; } if( IS_SET( victim->act, PLR_WIZINVIS ) ) { send_to_char( "Victim not found.\r\n", ch ); return; } } else victim = ch; account = victim->desc->account; ch_printf(ch, "&c&V[&d&WAccount: %-8s &GFor Player &W%-8s &c|&d&w------&c&V]\r\n", account->name, victim->name ); ch_printf(ch, "&c&V|&d &WPoints: %-15d Immortal: %-5s &c&V|\r\n", account->points, account->immortal ? "Yes" : "No" ); ch_printf(ch, "&c&V|&d &WMultiplay: %-5s &c&V|\r\n", account->multiplay ? "Yes" : "No" ); send_to_char( "&c&V|&d&w--------------&c|&d&WCharacters&c|&d&w-------------------&c&V|\r\n", ch ); for(ach = account->first_acc_char; ach; ach = ach->next) { ch_printf(ch, "&c&V|&d %-15s &c&V|\r\n", ach->name ); } return; }
Maybe I'm just not understanding something here. I've looked at setship for an example, you set the ship, the ship saves the data via save_ship and then you stat the ship and the changes show up with out having to reload the ship file, shouldn't I be able to do the same with account files? Granted, descriptor and character names will be different, but they are all pointing back to account->name, so it should then pull the most current info. . . Right?
Thanks in advance,
ayuri
#10 Oct 27, 2011 2:01 am
Last edited Oct 27, 2011 2:02 am by ayuri
Magician
GroupMembers
Posts239
JoinedJun 13, 2008
Hmmmm,
Ok how about something like this:
And looping though every connected descriptor and setting them all at once. This way every descriptor connected has the same value. Granted this would need to be put in for everything that would read/write the points line, but it *should* work.. . Right?
I know its ugly, but I'm still not seeing why the points value isn't updating across players.
*goes back to beating the code with a sledge hammer, while muttering "I'm in way over my head"*
ayuri
Ok how about something like this:
for ( d = first_descriptor; d; d = d->next ) if (!str_cmp( ch->desc->account->name, d->account->name)) d->account->points += value;
And looping though every connected descriptor and setting them all at once. This way every descriptor connected has the same value. Granted this would need to be put in for everything that would read/write the points line, but it *should* work.. . Right?
I know its ugly, but I'm still not seeing why the points value isn't updating across players.
*goes back to beating the code with a sledge hammer, while muttering "I'm in way over my head"*
ayuri
Pages:<< prev 1 next >>