+ for( i = 0; i < numItems; i ++ )
+ {
+ if( items[i].Handler != handler ) continue;
+ if( items[i].ID != num ) continue;
+
+ #if DUMP_ITEMS
+ printf("Redefinition of %s:%i, updated\n", handler->Name, num);
+ #endif
+ items[i].Price = price;
+ free(items[i].Name);
+ items[i].Name = strdup(desc);
+ break;
+ }
+ if( i < numItems ) continue;
+
+ items = realloc( items, (numItems + 1)*sizeof(items[0]) );
+ items[numItems].Handler = handler;
+ items[numItems].ID = num;
+ if( gbNoCostMode )
+ items[numItems].Price = 0;
+ else
+ items[numItems].Price = price;
+ items[numItems].Name = strdup(desc);
+ items[numItems].bHidden = (line[0] == '-');
+ numItems ++;
+ }
+
+ // Clean up old
+ if( giNumItems )
+ {
+ giNumItems = 0;
+ free(gaItems);
+ gaItems = NULL;
+ }
+ fclose(fp);
+
+ // Replace with new
+ giNumItems = numItems;
+ gaItems = items;
+
+ gItems_LastUpdated = time(NULL);
+}
+
+/**
+ * \brief Update the item file from the internal database
+ */
+void Items_UpdateFile(void)
+{
+ FILE *fp;
+ char buffer[BUFSIZ];
+ char *line;
+ int lineNum = 0;
+ int i;
+ regmatch_t matches[5];
+ char **line_comments;
+ int *line_items;
+
+ // Error check
+ fp = fopen(gsItemListFile, "r");
+ if(!fp) {
+ fprintf(stderr, "Unable to open item file '%s'\n", gsItemListFile);
+ perror("Unable to open item file");
+ return ;
+ }
+
+ // Count lines
+ while( fgets(buffer, BUFSIZ, fp) )
+ {
+ lineNum ++;
+ }
+
+ line_comments = malloc(lineNum * sizeof(char*));
+ line_items = malloc(lineNum * sizeof(int));
+
+ // Parse file
+ lineNum = 0;
+ fseek(fp, 0, SEEK_SET);
+ while( fgets(buffer, BUFSIZ, fp) )
+ {
+ char *hashPos, *semiPos;
+ char *type;
+ int num;
+ tHandler *handler;
+
+ trim(buffer);
+
+ lineNum ++;
+ line_items[lineNum-1] = -1;
+ line_comments[lineNum-1] = NULL;
+
+ // Get comments
+ hashPos = strchr(buffer, '#');
+ semiPos = strchr(buffer, ';');
+ if( hashPos && semiPos ) {
+ if( hashPos < semiPos )
+ line_comments[lineNum-1] = strdup(hashPos);
+ }
+ else if( hashPos ) {
+ line_comments[lineNum-1] = strdup(hashPos);
+ }
+ else if( semiPos ) {
+ line_comments[lineNum-1] = strdup(semiPos);
+ }
+ if(hashPos) *hashPos = '\0';
+ if(semiPos) *semiPos = '\0';
+
+ // Trim whitespace
+ line = trim(buffer);
+ if(strlen(line) == 0) continue;
+
+ // Pass regex over line
+ if( RunRegex( &gItemFile_Regex, line, 5, matches, NULL) ) {
+ fprintf(stderr, "Syntax error on line %i of item file '%s'\n", lineNum, gsItemListFile);
+ return ;
+ }
+
+ // Read line data
+ type = line + matches[1].rm_so; line[ matches[1].rm_eo ] = '\0';
+ num = atoi( line + matches[2].rm_so );
+
+ // Find handler
+ handler = NULL;
+ for( i = 0; i < giNumHandlers; i ++ )
+ {
+ if( strcmp(type, gaHandlers[i]->Name) == 0 ) {
+ handler = gaHandlers[i];
+ break;
+ }
+ }
+ if( !handler ) {
+ fprintf(stderr, "Warning: Unknown item type '%s' on line %i\n", type, lineNum);
+ continue ;
+ }
+