Atrinik Server 2.5
server/region.c
Go to the documentation of this file.
00001 /************************************************************************
00002 *            Atrinik, a Multiplayer Online Role Playing Game            *
00003 *                                                                       *
00004 *    Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team    *
00005 *                                                                       *
00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game)     *
00007 * and Crossfire (Multiplayer game for X-windows).                       *
00008 *                                                                       *
00009 * This program is free software; you can redistribute it and/or modify  *
00010 * it under the terms of the GNU General Public License as published by  *
00011 * the Free Software Foundation; either version 2 of the License, or     *
00012 * (at your option) any later version.                                   *
00013 *                                                                       *
00014 * This program is distributed in the hope that it will be useful,       *
00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00017 * GNU General Public License for more details.                          *
00018 *                                                                       *
00019 * You should have received a copy of the GNU General Public License     *
00020 * along with this program; if not, write to the Free Software           *
00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.             *
00022 *                                                                       *
00023 * The author can be reached at admin@atrinik.org                        *
00024 ************************************************************************/
00025 
00032 #include <global.h>
00033 
00035 region *first_region = NULL;
00036 
00037 static region *get_region_struct();
00038 static void assign_region_parents();
00039 
00049 region *get_region_by_name(const char *region_name)
00050 {
00051     region *reg;
00052 
00053     for (reg = first_region; reg; reg = reg->next)
00054     {
00055         if (!strcmp(reg->name, region_name))
00056         {
00057             return reg;
00058         }
00059     }
00060 
00061     LOG(llevDebug, "Got no region for region %s.\n", region_name);
00062     return NULL;
00063 }
00064 
00073 char *get_region_longname(const region *r)
00074 {
00075     if (r->longname)
00076     {
00077         return r->longname;
00078     }
00079     else if (r->parent)
00080     {
00081         return get_region_longname(r->parent);
00082     }
00083 
00084     LOG(llevDebug, "Region %s has no parent and no longname.\n", r->name);
00085     return "no region name";
00086 }
00087 
00093 char *get_region_msg(const region *r)
00094 {
00095     if (r->msg)
00096     {
00097         return r->msg;
00098     }
00099     else if (r->parent)
00100     {
00101         return get_region_msg(r->parent);
00102     }
00103 
00104     LOG(llevDebug, "Region %s has no parent and no msg.\n", r->name);
00105     return "no region message";
00106 }
00107 
00114 object *get_jail_exit(object *op)
00115 {
00116     region *reg;
00117     object *exit_ob;
00118 
00119     if (op->type != PLAYER)
00120     {
00121         LOG(llevBug, "get_jail_exit() called for non-player object.\n");
00122         return NULL;
00123     }
00124 
00125     if (!op->map->region)
00126     {
00127         return NULL;
00128     }
00129 
00130     reg = op->map->region;
00131 
00132     while (reg)
00133     {
00134         if (reg->jailmap)
00135         {
00136             exit_ob = get_object();
00137             FREE_AND_COPY_HASH(EXIT_PATH(exit_ob), reg->jailmap);
00138             /* Damned exits reset savebed and remove teleports, so the prisoner can't escape */
00139             SET_FLAG(exit_ob, FLAG_DAMNED);
00140             EXIT_X(exit_ob) = reg->jailx;
00141             EXIT_Y(exit_ob) = reg->jaily;
00142             return exit_ob;
00143         }
00144         else
00145         {
00146             reg = reg->parent;
00147         }
00148     }
00149 
00150     LOG(llevDebug, "No suitable jailmap for region %s was found.\n", reg->name);
00151     return NULL;
00152 }
00153 
00156 void init_regions()
00157 {
00158     FILE *fp;
00159     char filename[MAX_BUF];
00160     int comp;
00161     region *new = NULL, *reg;
00162     char buf[HUGE_BUF * 4], msgbuf[HUGE_BUF], *key = NULL, *value, *end;
00163     int msgpos = 0;
00164 
00165     /* Only do this once */
00166     if (first_region)
00167     {
00168         return;
00169     }
00170 
00171     snprintf(filename, sizeof(filename), "%s/regions.reg", settings.mapdir);
00172     LOG(llevDebug, "Reading regions from %s...\n", filename);
00173 
00174     if ((fp = open_and_uncompress(filename, 0, &comp)) == NULL)
00175     {
00176         LOG(llevError, "init_regions(): Can't open regions file: %s.\n", filename);
00177         return;
00178     }
00179 
00180     while (fgets(buf, sizeof(buf) - 1, fp))
00181     {
00182         buf[sizeof(buf) - 1] = '\0';
00183         key = buf;
00184 
00185         while (isspace(*key))
00186         {
00187             key++;
00188         }
00189 
00190         /* Empty line or a comment */
00191         if (*key == '\0' || *key == '#')
00192         {
00193             continue;
00194         }
00195 
00196         value = strchr(key, ' ');
00197 
00198         if (!value)
00199         {
00200             end = strchr(key, '\n');
00201             *end = '\0';
00202         }
00203         else
00204         {
00205             *value = '\0';
00206             value++;
00207 
00208             while (isspace(*value))
00209             {
00210                 value++;
00211             }
00212 
00213             end = strchr(value, '\n');
00214         }
00215 
00216         if (!strcmp(key, "region"))
00217         {
00218             *end = '\0';
00219             new = get_region_struct();
00220             new->name = strdup_local(value);
00221         }
00222         else if (!strcmp(key, "parent"))
00223         {
00224             *end = '\0';
00225             new->parent_name = strdup_local(value);
00226         }
00227         else if (!strcmp(key, "longname"))
00228         {
00229             *end = '\0';
00230             new->longname = strdup_local(value);
00231         }
00232         else if (!strcmp(key, "map_first"))
00233         {
00234             *end = '\0';
00235             new->map_first = strdup_local(value);
00236         }
00237         else if (!strcmp(key, "map_bg"))
00238         {
00239             *end = '\0';
00240             new->map_bg = strdup_local(value);
00241         }
00242         /* Jail entries are of the form: /path/to/map x y */
00243         else if (!strcmp(key, "jail"))
00244         {
00245             char path[MAX_BUF];
00246             int x, y;
00247 
00248             if (sscanf(value, "%[^ ] %d %d\n", path, &x, &y) != 3)
00249             {
00250                 LOG(llevError, "init_regions(): Malformed regions entry: jail %s\n", value);
00251                 continue;
00252             }
00253 
00254             new->jailmap = strdup_local(path);
00255             new->jailx = x;
00256             new->jaily = y;
00257         }
00258         else if (!strcmp(key, "msg"))
00259         {
00260             while (fgets(buf, sizeof(buf) - 1, fp))
00261             {
00262                 if (!strcmp(buf, "endmsg\n"))
00263                 {
00264                     break;
00265                 }
00266 
00267                 strcpy(msgbuf + msgpos, buf);
00268                 msgpos += strlen(buf);
00269             }
00270 
00271             if (msgpos != 0)
00272             {
00273                 new->msg = strdup_local(msgbuf);
00274             }
00275 
00276             /* we have to reset msgpos, or the next region will store both msg blocks. */
00277             msgpos = 0;
00278         }
00279         else if (!strcmp(key, "end"))
00280         {
00281             /* Place this new region last on the list, if the list is empty put it first */
00282             for (reg = first_region; reg != NULL && reg->next != NULL; reg = reg->next)
00283             {
00284             }
00285 
00286             if (reg == NULL)
00287             {
00288                 first_region = new;
00289             }
00290             else
00291             {
00292                 reg->next = new;
00293             }
00294 
00295             new = NULL;
00296         }
00297         else
00298         {
00299             /* We should never get here, if we have, then something is wrong */
00300             LOG(llevError, "Got unknown value in region file: %s %s\n", key, value);
00301         }
00302     }
00303 
00304     assign_region_parents();
00305     LOG(llevDebug, " done\n");
00306 
00307     close_and_delete(fp, comp);
00308 }
00309 
00313 static region *get_region_struct()
00314 {
00315     region *new = (region *) CALLOC(1, sizeof(region));
00316 
00317     if (new == NULL)
00318     {
00319         LOG(llevError, "get_region_struct(): Out of memory.");
00320     }
00321 
00322     memset(new, 0, sizeof(region));
00323     return new;
00324 }
00325 
00328 static void assign_region_parents()
00329 {
00330     region *reg;
00331     uint32 parent_count = 0, region_count = 0;
00332 
00333     for (reg = first_region; reg; reg = reg->next)
00334     {
00335         if (reg->parent_name)
00336         {
00337             reg->parent = get_region_by_name(reg->parent_name);
00338             parent_count++;
00339         }
00340 
00341         region_count++;
00342     }
00343 
00344     LOG(llevDebug, "Assigned %u regions with %u parents.\n", region_count, parent_count);
00345 }
00346 
00349 void free_regions()
00350 {
00351     region *reg, *next;
00352 
00353     LOG(llevDebug, "Freeing regions.\n");
00354 
00355     for (reg = first_region; reg; reg = next)
00356     {
00357         next = reg->next;
00358 
00359         FREE_AND_NULL_PTR(reg->name);
00360         FREE_AND_NULL_PTR(reg->parent_name);
00361         FREE_AND_NULL_PTR(reg->longname);
00362         FREE_AND_NULL_PTR(reg->msg);
00363         FREE_AND_NULL_PTR(reg->jailmap);
00364         CFREE(reg);
00365     }
00366 }