SaptaZapta Wrote:That's exactly it. Their server and database were apparently built quite incompetently. Hence, the bugs are currently built-in. It can be fixed, or more accurately rewritten/restructured, but it's not something they can do in hours while MTS is "temporarily" down.
Are you sure they have individual item ids? If that's so and they are not using that info to take care of duplication, what is it even there for?
Also, what about valuable non-equips that can be duped? Surely a stack of 100 whitescrolls doesn't have an id attached to each scroll?
Honey I'm a professional DBA, we can fix their database structure in virtually no time, even while the game is online and running, by adding in columns that to the game don't exist/matter but to the DB do. A few constraints, a trigger here and there, or even a job that runs nightly or gets run during maintenance and most of what they experience would be addressed.
As for IDs, each unique instance in memory can have an ID at the time it's created. It's very simple to do this. Stacked items are merged - One ID survives, the others don't and the quantities increase. Here's a very basic two minute dupe-check I wrote & released for SMAUG for in-memory testing back in '99-'01. Today's modern programming and this being a database-saved game makes it even easier because you can just add an identity column to do all the work without even touching the actual source code.
Spoiler
Code:
/*
Object duplication prevention system.
*/
prototypes to put in mud.h:
long make_obj_guid(void);
OBJ_DATA *dupecheck( long id );
char dupelist[MSL];
after
CREATE( obj, OBJ_DATA, 1 );
obj->count = 1;
add
obj->guid = 0;
Then add
case 'G':
if ( !strcmp( word, "GUID" ) )
{
OBJ_DATA *dupe=NULL;
fMatch = TRUE;
long guid;
guid = fread_number(fp); // change GUID
if (guid)
obj->guid = guid;
else
break; // New.
if ( (dupe = dupecheck( obj->guid )) != NULL) // Critical!
{
sprintf( dupelist, "%s%d ", dupelist, vnum );
fVnum = FALSE; // treat as an Illegal vnum, remove from character when done.
}
break;
}
break;
in clans.c
in load_clan_file
between:
found = TRUE;
for ( ; ; )
add:
*dupelist = 0;
between:
}
fclose( fp );
Add:
bug( "Duping detected: %s, had the following in their hall: %s, stripping", clan->name, dupelist );
If you're using Erwins board system you can replace the bug messages with:
if (*dupelist != 0)
{
logs( "Duping detected: %s, duped: %s, stripping", ch ? ch->name : "Unknown", dupelist );
}
with:
if (*dupelist != 0)
{
char buf[MAX_INPUT_LENGTH];
sprintf( buf, "Duping detected: %s, duped: %s, stripping", ch ? ch->name : "Unknown", dupelist );
make_note ( "Immortals", "The MUD", "imm", "Duping Report", 60, wordwrap( buf, 78 ) );
if (ch && !IS_STAFF(ch) && !IS_NPC(ch))
{
char to[MAX_INPUT_LENGTH];
sprintf( buf, "You have been caught duplicating items by the MUD. These duplicate items have been removed from your possession and will not be refunded. Signs of this having been deliberate may incur further punishment. You are encouraged to report how this happened if you know what you did to cause it.");
sprintf( to, "%s imm", ch->name );
make_note ( "Personal", "The MUD", to, "Your Warning", 60, wordwrap( buf, 78 ) );
}
}
or similar
You'll need to add to mud.h :
char *wordwrap( char *txt, sh_int wrap );
void make_note (const char* board_name, char *sender, char *to, char *subject, const int expire_days, char *text);
If you're using lockers or a similar system you'll want to put similar dupecheck initializations and reportings immediately before/after the loads.
It's not having what you want - It's wanting what you've got.