Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Topics - quixadhal

Pages: 1 [2] 3 4
Drivers / Long standing bug in FluffOS
« on: July 27, 2013, 10:07:06 AM »
So, since lots of changes and work are going into FluffOS now, I figured I'd see if I could get someone to take a look at a long-standing bug that still bites people in the arse.

LPC has data types.  Not very many, and a bit strange since the type clings to the value, not the variable... but still, it has types.

In any sane language, when you declare a variable of a specific type, it is initialized to an appropriate value of that same type.  FluffOS's version of LPC does not do this.

If you declare an array or mapping, they are initialized to the value 0, which is an integer.  The runtime error this commonly causes is when you declare a variable and then try to use it the way you'd expect it to work, such as:

Code: [Select]
mapping foo;

foo["hello"] = "blah";

That fails with an illegal index error, because you can't index the value 0, which is what foo is initialized to.  You have to always remember to declare everything and specifically assign it the right value.  Not a big deal if you're working on your MUD consistently, but a royal pain when you just want to code something quickly every now and then, or if you've been using a different driver that does things as you'd expect.

Code Vault / DS mudlist CGI page
« on: July 27, 2013, 02:19:47 AM »
Here's a working mudlist command, which can be placed in the cgi directory of DS's internal web server.
Why?  Because it makes it easy to add I3's muds to my mudlist, since my TMC script already handles web pages.

Code: (lpc) [Select]
#include <lib.h>
#include <privs.h>
#include <daemons.h>

inherit LIB_DAEMON;

varargs string gateway(int strip_html) {
    string output = "";
    mapping mudlist = ([]);
    string mud = "";
    mixed *info = ({});
    string *list = ({});
    string *bg = ({ "#FFFFFF", "#DFFFDF" });
    int bgcolor = 0;
    string *keylist = ({});
    int i = 0;

    foreach( mud, info in INTERMUD_D->GetMudList() ) {
        if(info[0] == -1) {
            mudlist[mud] = info;

    keylist = sort_array(keys(mudlist), 1);

    for(i = 0; i < sizeof(keylist); i++) {
        mud = keylist[i];
        info = mudlist[mud];
        bgcolor = !bgcolor;
        list += ({ sprintf(
                    "<td bgcolor=\"%s\">%s</td>" +
                    "<td bgcolor=\"%s\">%s</td>" +
                    "<td bgcolor=\"%s\">%s</td>" +
                    "<td bgcolor=\"%s\">%s</td>" +
                    "<td bgcolor=\"%s\">%s</td>" +
                    "<td align=\"right\" bgcolor=\"%s\">%d</td>",
                    bg[bgcolor], replace_string(strip_colors(mud), " ", "&nbsp;"),
                    bg[bgcolor], replace_string(info[8], " ", "&nbsp;"),
                    bg[bgcolor], replace_string(info[7], " ", "&nbsp;"),
                    bg[bgcolor], replace_string(info[5], " ", "&nbsp;"),
                    bg[bgcolor], info[1],
                    bg[bgcolor], info[2]) });
    output  = "<div align=\"center\"><table width=\"90%\" border=\"1\" cellspacing=\"0\" padding=\"0\">\n";
    output += "<tr class=\"header\"><td align=\"center\" colspan=\"6\">" + mud_name() + " recognizes " + consolidate(sizeof(mudlist), "a mud")+ ":</td></tr>\n";
    output += "<tr class=\"entry\">" + implode(list, "</tr>\n<tr class=\"entry\">") + "</tr>\n";
    output += "</table></div>\n";
    return output;

Drivers / async IO database example?
« on: May 05, 2013, 02:10:34 PM »
So, in my continuing to slowly poke things into my documentation wiki, I was reminded of something that needs a small quick example, somewhere.

Wodan has stated that Discworld no longer uses the python database helper script, and now uses package_async.  Is there any chance a very small example could be posted in here?

Basically just connect, do a select, do a couple of insert/updates in a transaction block, and disconnect.

At least that way new users wouldn't have to paw through the source code just to figure out how to do basic DB operations. :)

Drivers / Documentation Wiki, part 1.
« on: April 14, 2013, 07:08:52 PM »
Hey guys,

Just to get some feedback, here's the documentation wiki I've been working on.  There's still more to go, but after finishing the gigantic sockets document, I figured perhaps I should let other people see and comment on it.

I started doing it by hand, then wrong a script to try and auto-tag many keywords, and am now cleaning that up by hand, as making a script to do everything right is more work than doing it by hand entirely. :)

So, if you think I should add more whitespace, or not highlight every occurance of words, or whatever, do comment.  Eventually, I'll either open it up to editing and/or figure out how to make the stuff that works in mediawiki work in github's wiki.

Design Lab / Security/Permissions
« on: March 20, 2013, 01:10:10 PM »
So, I'm tinkering with Lil.  The goal is just to make a little I3 chat room thing, but since you have to rebuild it from the ground up, I'm trying to also make it a useful kernel others could build on.

I made a user/account system, and now I figured I should add in user/group security of some sort.

I always hated the typical LpMUD security system, as it tends to rely on fixed pathnames.  I'd rather have something more like VMS or more recent unix systems, where there's not just a concept of owner/group, but also an ACL list that can specify permissions for individual users/groups, not just the one that "owns" them.

So, at blue-sky level, the idea is to create a file daemon that holds permission info on various files and directories.  When you ask if a given user can do something to a file, the daemon can try to look that up directly, and if nothing is found, bubble upwards until it finds a match or a default.

So, groups are easy to define.  You can make "players", "wizards", "admin", and each project domain could have a corresponding group.  Since I plan to have accounts and characters as seperate things, those would also be things you'd have permissions available for.

When thinking about the actual permission entries themselves... each thing needs default permissions, and then one ACL list for allowed, and another for denied.  If the default permission is global read, no write, you could put an ACL to let joe and domain fooland write, and another ACL preventing the wizards group from reading.

For the permissions themselves, the usual read/write of course.  I also liked VMS having a seperate "delete" bit.  I think it also makes sense to have clone/dest permissions.  There may be occasions you want a wizard to be able to read or copy code, but not directly clone an object into the game, or be able to dest an existing object.  Further, being able to control function calls could be useful.

We all know valid_read/valid_write.  I'm thinking valid_object might help with the cloning issue.

So, the question is.. what all simuls would I need to muck with?  clone_object(),  new(), destruct(), call_other(), call_out()?

Feel free to make suggestions.  Right now, it's just an idea.

(Note that this is the permissions system itself, and is just meant to address "can X do Y?".  Determining the correct X is the job of the caller... which would be the simul_efuns that make use of the permissions daemon)

Design Lab / Rooms revisited
« on: February 16, 2013, 06:54:14 PM »
So, I was thinking this morning, about rooms.

The vast majority of MUDs are room based.  Each room exists as a unique object, but most rooms are more-or-less identical in nature.  They have different descriptions, details, inventories, exit links.. but for the most part, they act pretty much like every other room out there.

Some MUDs have the concept of virtual rooms, where the room is generated on the fly, usually drawing data from a graphical map file, or an algorithm.  Sometimes these are fixed, in that if you revisit the same "room" again, it will look the same.  Other times they are more randomized.

As players (and NPCs) wander around the world, each of these rooms acts as an empty container, showing them information about the world around them, but basically not doing anything until the player (or NPC) encounters another player (or NPC).  At that point, they are able to interact.

So, anyways, I was thinking... why not turn the situation around.  Instead of having thousands (or millions) of empty rooms for our entities to wander through, why not let the world move around them?

Simply create a room for each player/NPC and paint it with the details you'd find at the point in the world they're at.  When they "move", just reload the room they're in with the new data.  When a player or NPC walks into the same location as another player/NPC, move them into the same room and let the normal room containment code do its job.  When they move again, if nobody is at that spot, create a new room for them again.

Note that "spot" doesn't have to mean coordinates.  Your world could be a directed graph, just like a room-based MUD is now, you just don't need to actually instantiate all the empty room objects.

What's the advantage?

Well, you could store all the room data in a more compact format that doesn't need to be fully loaded all the time.  Path-finding algorithms don't need to walk all the rooms (forcing them to load), as they could simply use a smaller subset of the data for connectivity.

Just a thought... any comments?

Dead Souls Support / Fix broken pager output for help
« on: February 14, 2013, 01:14:02 PM »
The help system breaks when displaying a large file on a large terminal, because of a string size limit put in place in the 19th century, when 7900 bytes was a LOT of memory.

Code: [Select]
bloodlines@lenin:~/lib/daemon$ git diff ../secure/sefun/strings.c
diff --git a/lib/secure/sefun/strings.c b/lib/secure/sefun/strings.c
index 1975679..65d53c0 100755
--- a/lib/secure/sefun/strings.c
+++ b/lib/secure/sefun/strings.c
@@ -87,6 +87,8 @@ varargs string wrap(string str, int x) {
             else x = 79;
+    return sprintf("%-=" + x + "s\n", str);
+    /*
     if(sizeof(str) < 7900) return sprintf("%-=" + x + "s\n", str);
     else {
         string tmpfile = generate_tmp();
@@ -96,6 +98,7 @@ varargs string wrap(string str, int x) {
         str += "\n*** TRUNCATED ***\n";
         return sprintf("%-=" + x + "s\n", str);
+    */

 varargs mixed convert_string(string str, int flag) {

Discworld Discussion / Adding new I3 channels
« on: February 10, 2013, 09:55:44 AM »
For those running the dist-lib of Discworld, you may find yourself in the situation where
you wish to add MORE I3 channels to the game.  This is foolish, but if you insist,
this is what you need to do.

If you're wanting to make your very own channel, you'll need to call
    exec return "/net/intermud3/services"->AddChannel("channel name", 0);

Now that the channel exists on the I3 server, you have to add it to the hard-coded
list of I3 channels.

    edit /include/creator.h

    Add an entry to the INTERMUD_MAP mapping, where the KEY is your local channel name,
        and the VALUE is the name it has on the I3 system.

Code: [Select]
        #define INTERMUD_MAP ([ "dwchat" : "discworld-chat", "dwcre" : "discworld-cre",
                                "intergossip" : "imud_gossip", "intercre" : "imud_code",
                                "dchat" : "dchat" ])

    Next, you need to either add it to the hard-coded GetLocalChannel() function in
        /net/intermud3/services/channels.c, or replace that function with this:

Code: [Select]
        #include <creator.h>

        string GetLocalChannel(string channel) {
            return allocate_mapping(values(INTERMUD_MAP), keys(INTERMUD_MAP))[channel] || 0;

    Once that's done, you need to reload both systems:

        dupdate /net/intermud3/services.c
        dupdate /global/lord.c

General / tapatalk
« on: December 30, 2012, 08:35:51 AM »
For those of you who use tablets or (I suppose) smartphones to do internet stuff, I recently found a nice little paid app called tapatalk, which is specifically designed to make reading forums easier on the smaller size screens, and also to take advantage of the touch interface where possible... all without the site admin having to do much.

One other advantage, for site admins, is the chance of additional traffic, since your forum would show up in the Giant List O Forums which can be searched and/or browsed from the tapatalk client.  So, for example, if you search for "mud", you get a bunch of results talking about wrestling, snowmobiling, and other stuff.  But if you search for "mud game" or "lpmud", you get NOTHING.

Crat could have an exclusive market to hawk Dead Souls!

So, I figured I'd toss this up here and see if there's any interest in poking Crat with a stick and seeing if he'll download and install the plugin to make it work with these very forums.

The only forum I read which supports it is my gaming guild's site, which has several thousand people on it, and it does seem to work rather well.

Here's a link to the thing you'd need to install:

And, of course, if you just go to the main site, you can read about what it is and see if the sales pitch sounds good.  I would, of course, suggest just doing the free version since I doubt Crat cares about "branding", but hey.. it's an option too.

And yes, my ulterior motive is so I can read this stuff on my tablet without having my eyes bleed. :)

General / 64-bit Java
« on: December 05, 2012, 10:37:21 AM »
Not sure where a good place to post this is, as it isn't LPC, but it's also not quite generic "chat".

Anyways, I know a few of you guys run/play minecraft, and there may even be a few who use CoffeeMUD or some other java codebase out there.  If so, there's a small chance you use Debian or Ubuntu linux, and are annoyed by the fact that there's no official Oracle package for java, and there's also no 64-bit version.

So....  here's how to make Debian use the 64-bit one, and I assume Ubuntu would work the same way.

Code: [Select]
                Go to orcale's web site and download the latest 64-bit jdk, currently:

                mkdir -p /opt/java/64
                cd /opt/java/64
                tar xf jdk-7u7-linux-x64.tar.bz2
                chown -R root.root /opt/java
                chmod ugo+rx -R /opt/java

                update-alternatives --install /usr/bin/java java /opt/java/64/jdk1.7.0_07/bin/java 666
                update-alternatives --install /usr/bin/javac javac /opt/java/64/jdk1.7.0_07/bin/javac 666
                update-alternatives --set java /opt/java/64/jdk1.7.0_07/bin/java
                update-alternatives --set javac /opt/java/64/jdk1.7.0_07/bin/javac

            To verify the right one is being used:

                update-alternatives --config java
                java -version

Code Vault / Keeping track of all those other muds you follow
« on: November 27, 2012, 02:43:16 AM »
So, I'm sure many of you don't JUST tinker with your own code in isolation, but tend to follow other people's stuff to see what they're doing too.  Many of us use a distribution library as a base, and so want to see what changes so we can (maybe) merge new bugfixes into our stuff.

It's a pain to keep track of where everything is, let alone keep it all up to date.

Sooooo, here's a tiny little perl script which I use.  If anyone has any codebases to add, please feel free to do so!

Code: [Select]
#!/usr/bin/perl -w

use strict;

my $repositories = {
    'dgd'       => {
        'dgd'                   => { 'type' => 'git', 'url' => '' },
        'lpc-doc'               => { 'type' => 'git', 'url' => '' },
        'lpc-ext'               => { 'type' => 'git', 'url' => '' },
        'kernellib'             => { 'type' => 'git', 'url' => '' },
        'dgd-httpd'             => { 'type' => 'git', 'url' => '' },
        'gurbalib'              => { 'type' => 'git', 'url' => '' },
        'kernellib-shentino'    => { 'type' => 'git', 'url' => '' },
        'gurbalib-sirdude'      => { 'type' => 'git', 'url' => '' },
        'cloud'                 => { 'type' => 'git', 'url' => '' },
    'fluffos'   => {
        'fluffos'               => { 'type' => 'git', 'url' => '' },
        'ds'                    => { 'type' => 'git', 'url' => '' },
        'lima'                  => { 'type' => 'git', 'url' => '' },
    'diku'      => {
        'quix_smaug'            => { 'type' => 'git', 'url' => '' },
        'smaug'                 => { 'type' => 'git', 'url' => '' },

sub fetch_repository {
    my $style = shift or return 0;
    my $repo = shift or return 0;
    my $data = shift or return 0;
    my $type = $data->{'type'} or return 0;
    my $url = $data->{'url'} or return 0;

    mkdir $style if ! -d $style;
    chdir $style;
    if( $type eq 'git' ) {
        if( -d $repo ) {
            chdir $repo;
            print "==> Updating $style/$repo from $url\n";
            system("git pull");
            chdir '..';
        } else {
            print "==> Fetching $style/$repo from $url\n";
            system("git clone $url $repo");
    } elsif( $type eq 'svn' ) {
        if( -d $repo ) {
            chdir $repo;
            print "==> Updating $style/$repo from $url\n";
            system("svn update");
            chdir '..';
        } else {
            print "==> Fetching $style/$repo from $url\n";
            system("svn checkout $url $repo");
    chdir '..';
    print "\n";
    return 1;

foreach my $style (keys %$repositories) {
    foreach my $repo (keys %{ $repositories->{$style} }) {
        fetch_repository($style, $repo, $repositories->{$style}->{$repo});

NOTE: the subversion code is untested because I don't know of anyone who still uses it. :)

Intermud / channel list update
« on: October 07, 2012, 05:16:08 AM »
Hey, just a quick question...

Is there any way to force the router to update your channel list?  I've been trying to shore up some old I3 code for my DikuMUD, and it had the bad habit of only saving channels which you had locally configured, and so every time it rebooted (which on a Diku is every time you change anything), it forgot the entire list of channels.

The problem is, I can't seem to tell when/if that list ever gets updated.  I know it does, occasionally, when the phase of the moon is right.. but it would be nice if I could send something to the router to say "Hey, please send me the list of channels now".

The mudlist itself updates nice and snappy.

Alternatively, is there a packet I can send to each MUD asking for a list of channels they host?  I could loop through the mudlist a minute or two after reconnecting if that's easier.

Drivers / LDMUD
« on: September 17, 2012, 04:43:54 PM »
Hey, I dunno if you guys have ever poked at ldmud, but it's another LpMUD driver that's been considered the more-or-less direct descendant to the Amylaar LpMUD 3.2, which was also a direct descendant of the original LpMUD 2.4.5.

Anyways, I decided to go see if anything had changed, and found this.

So, while the official site is still up and running, there's now also a github site which has new stuff on it.

Anyone foolish enough to consider coding a new mudlib from scratch, or trying to port some ancient beast from 3.2 or older, might be interested. :)

Discworld Discussion / I3 mudlist fix
« on: September 10, 2012, 09:37:56 PM »
So, for those brave few who might be trying to coax the ancient Discworld into life, with the old distribution that Cratylus has so kindly placed in his respository... here's a fix that's the result of a change to the way mudlist packets are handled on I3.

If I remember correctly, we had gotten to a point somewhere along the line where the mudlist was rather large (many muds, even if most of them had no players).  I believe around the time of the DikuMUD exodus from IMC2, it was discovered that the giant mudlist packets would overflow the fixed-size buffers of some of the Dikurivative codebases.

In an attempt to remedy the situation, the router was made to split the mudlist up into multiple packets, the theory being that if you get multiple packets, you handle each seperatly, and since you're supposed to add new muds onto your local list when you see them, and only remove them when the router says they're gone (or the data gets old enough)... it should work, right?

Well, one line of extra error checking stops that from working in the Discworld distribution.  The idea, if I'm reading this right, is that the router will send out an ID along with the mudlist packet, which tells you if this has changed since the last time you saw it.  If the ID is the same as it was last time, nothing has changed so no need to process it.  Good idea.  Problem is, NOW you get multiple packets in a row with the same ID because the list is sent in chunks.

The router-side solution is to increment the ID for each packet, but keep track of the starting point unless there *IS* a change... so if you break the list into 12 packets, starting from ID 2000, the clients would see ID's 2000 through 2011, and then again 2000 through 2011.  The clients would then change their check from seeing if packet->ID == last_seen_id, to if packet->ID <= largest_seen_id.  So, for 2000, it's new.. process, for 2011, process, now when you see 2000 again, you've seen 2011 so ignore it until 2012.

That fix isn't here... but this is the place you'd put it for Discworld.  The fix here just ignores the ID so you always process it, which solves the problem at the expense of a bit of extra CPU.

Code: [Select]
protected void eventRead(int fd, mixed *packet) {
  case "mudlist":
    if( sizeof(packet) != 8 ) return;
    /* DS has this check commented out, perhaps because of
     * the new fragmented mudlist packets?
    /* if( packet[6] == MudList->ID ) return;  */
    if( packet[2] != Nameservers[0][0] ) return;
    MudList->ID = packet[6];
    foreach(cle, val in packet[7]) {
      if( !val && MudList->List[cle] != 0 )
        map_delete(MudList->List, cle);
      else if( val ) MudList->List[cle] = val;
    unguarded((: save_object, SAVE_INTERMUD, 2 :));

Code Vault / format_desc()
« on: August 20, 2012, 02:25:50 AM »
Here's a little function I threw together to make description formatting a standard API.  Various muds do room descriptions in different ways, some like to indent the first line and leave the rest on the left edge, others do the opposite, and some indent the whole thing.

Here's a bit of code to make that simpler.  Improvements welcome!

Code: [Select]

string format_desc(int terminal_width, int leading_indent_width, int inner_indent_width, string raw) {
    string result = "";

    string *paragraphs = rexplode(raw, "\n");
    string leading_indent = sprintf("%-*.*s", leading_indent_width, leading_indent_width, " ");
    string inner_indent = sprintf("%-*.*s", inner_indent_width, inner_indent_width, " ");

    for(int i = 0; i < sizeof(paragraphs); i++) {
        string p = paragraphs[i];

        result += (i != 0 ? "" : "");
        result += leading_indent + implode(explode(sprintf("%-=*s\n", terminal_width, p), "\n"), "\n" + inner_indent);
        result += "\n";
    return result;

Note that terminal width is the width you want the wrap to occur at, including the largest indent you provide, which should be less than your actual terminal width.  I tend to use 75 with an indent of 4.

Pages: 1 [2] 3 4