cstring *ser_wallet(const struct wallet *wlt) { struct bp_key *key; cstring *rs = cstr_new_sz(20 * 1024); /* * ser "root" record */ { cstring *s_root = ser_wallet_root(wlt); cstring *recdata = message_str(wlt->chain->netmagic, "root", s_root->str, s_root->len); cstr_append_buf(rs, recdata->str, recdata->len); cstr_free(recdata, true); cstr_free(s_root, true); } /* ser "privkey" records */ wallet_for_each_key(wlt, key) { void *privkey = NULL; size_t pk_len = 0; bp_privkey_get(key, &privkey, &pk_len); cstring *recdata = message_str(wlt->chain->netmagic, "privkey", privkey, pk_len); free(privkey); cstr_append_buf(rs, recdata->str, recdata->len); cstr_free(recdata, true); }
QSharedPointer<MsgBase> LinkLayerIcarus::getNextMessage() { QSharedPointer<MsgBase> message; int index_start = 0; // The token ":" must be the second in a message, so if the colon // appears at first position, the message type may be lost while((index_start = this->buffer->indexOf(":"), index_start)<1) { if(index_start == -1) // Not found { return message; //Empty } } // Now, we search for the end of the message. If the method indexOf // returns -1, the buffer has no token ";", so the message is incomplete int index_end = this->buffer->indexOf(";", index_start); if(index_end == -1) // Not found { return message; //Empty } // If we found a message in the buffer, we extract it and pop it from the buffer QString message_str(this->buffer->mid(index_start -1, index_end - index_start + 1)); this->buffer->remove(0, index_end); message = QSharedPointer<MsgBase>(new MsgBase(message_str)); return message; }
/* * Recall the most recent message */ void do_cmd_message_one(void) { cptr msg = format("> %s", message_str(0)); /* Recall one message XXX XXX XXX */ display_message(0, 0, strlen(msg), message_color(0), msg); }
static cstring *blkdb_ser_rec(struct blkdb *db, const struct blkinfo *bi) { cstring *data = ser_blkinfo(bi); cstring *rs = message_str(db->netmagic, "rec", data->str, data->len); cstr_free(data, true); return rs; }
static bool ser_peerman(struct peer_manager *peers, int fd) { /* write "magic number" (constant first file record) */ GString *rec = message_str(chain->netmagic, "magic.peers", NULL, 0); unsigned int rec_len = rec->len; ssize_t wrc = write(fd, rec->str, rec_len); g_string_free(rec, TRUE); if (wrc != rec_len) return false; if (debugging) fprintf(stderr, "peerman: %u peers to write\n", g_list_length(peers->addrlist)); /* write peer list */ GList *tmp = peers->addrlist; while (tmp) { struct peer *peer; peer = tmp->data; tmp = tmp->next; GString *msg_data = g_string_sized_new(sizeof(struct peer)); ser_peer(msg_data, CADDR_TIME_VERSION, peer); rec = message_str(chain->netmagic, "peer", msg_data->str, msg_data->len); rec_len = rec->len; wrc = write(fd, rec->str, rec_len); g_string_free(rec, TRUE); g_string_free(msg_data, TRUE); if (wrc != rec_len) return false; } return true; }
static bool ser_peerman(struct peer_manager *peers, int fd, const struct chain_info *chain) { /* write "magic number" (constant first file record) */ cstring *rec = message_str(chain->netmagic, "magic.peers", NULL, 0); unsigned int rec_len = rec->len; ssize_t wrc = write(fd, rec->str, rec_len); cstr_free(rec, true); if (wrc != rec_len) return false; log_debug("peerman: %zu peers to write", clist_length(peers->addrlist)); /* write peer list */ clist *tmp = peers->addrlist; while (tmp) { struct peer *peer; peer = tmp->data; tmp = tmp->next; cstring *msg_data = cstr_new_sz(sizeof(struct peer)); ser_peer(msg_data, CADDR_TIME_VERSION, peer); rec = message_str(chain->netmagic, "peer", msg_data->str, msg_data->len); rec_len = rec->len; wrc = write(fd, rec->str, rec_len); cstr_free(rec, true); cstr_free(msg_data, true); if (wrc != rec_len) return false; } return true; }
static bool nc_conn_send(struct nc_conn *conn, const char *command, const void *data, size_t data_len) { LOG("attempting to send:[%s] to %s", command, conn->addr_str); /* build wire message */ cstring *msg = message_str(chain->netmagic, command, data, data_len); if (!msg) return false; /* buffer now owns message data */ struct buffer *buf = calloc(1, sizeof(struct buffer)); buf->p = msg->str; buf->len = msg->len; cstr_free(msg, false); /* if write q exists, write_evt will handle output */ if (conn->write_q) { conn->write_q = clist_append(conn->write_q, buf); return true; } /* attempt optimistic write */ ssize_t wrc = write(conn->fd, buf->p, buf->len); if (wrc < 0) { if (errno != EAGAIN && errno != EWOULDBLOCK) { free(buf->p); free(buf); return false; } conn->write_q = clist_append(conn->write_q, buf); goto out_wrstart; } /* message fully sent */ if (wrc == buf->len) { free(buf->p); free(buf); return true; } /* message partially sent; pause read; poll for writable */ conn->write_q = clist_append(conn->write_q, buf); conn->write_partial = wrc; out_wrstart: nc_conn_read_disable(conn); nc_conn_write_enable(conn); return true; }
void chordService::detectNodesResponse() { DEBUG_PRINT("chord service starts detect nodes response process."); struct sockaddr_in addr; int fd; socklen_t addrlen; struct ip_mreq mreq; char message[100]; char prefix[20]; std::string prefix_str; sprintf(prefix, "type:%d", chordMessager::chordMessageType::messageDetectNode); prefix_str = std::string(prefix); fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { throw ERRORS::chordServiceSocketCreateFail(); } bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(SERVICE_DETECT_PORT_BIND); addrlen = sizeof(addr); if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { throw ERRORS::chordServiceSocketBindFail(); } mreq.imr_multiaddr.s_addr = inet_addr(GROUP_IP); mreq.imr_interface.s_addr = htonl(INADDR_ANY); if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { throw ERRORS::chordServiceSetSocketOptFail(); } while (true) { ssize_t cnt = recvfrom(fd, message, sizeof(message), 0, (struct sockaddr*)&addr, &addrlen); if (cnt < 0) { throw ERRORS::chordServiceRecvfromFail(); }else if (cnt > 0) { std::string message_str(message); if (message_str.find(prefix_str) == 0) { //this is a detectNode message //return this node info back to the source chordMessager::chordMessageBase* inmsg = nullptr; chordMessager::chordMessager::deserializeMessage(message_str, inmsg); chordMessager::chordMessageDetectNodeResponse* outmsg = new chordMessager::chordMessageDetectNodeResponse(serviceChordNode->thisNode, inmsg->getNodeParam()[0], serviceChordNode->thisNode); delete inmsg; inmsg = nullptr; serviceChordNode->makeRequest(outmsg, inmsg); delete inmsg; } } std::this_thread::sleep_for(std::chrono::seconds(5)); } }
void wr_messages(void) { s16b i; u16b num; num = messages_num(); if (num > 80) num = 80; wr_u16b(num); /* Dump the messages (oldest first!) */ for (i = num - 1; i >= 0; i--) { wr_string(message_str(i)); wr_u16b(message_type(i)); } }
wallet_for_each_mkey(wlt, hdkey) { struct hd_extended_key_serialized hdraw; bool rc = write_ek_ser_prv(&hdraw, hdkey); assert(rc == true); cstring *recdata = message_str(wlt->chain->netmagic, "hdmaster", hdraw.data, sizeof(hdraw.data) - 1); assert(recdata != NULL); cstr_append_buf(rs, recdata->str, recdata->len); cstr_free(recdata, true); }
/* * Hack -- display recent messages in sub-windows * * XXX XXX XXX Adjust for width and split messages */ void fix_message(void) { s32b j, i; s32b w, h; s32b x, y; /* Scan windows */ for (j = 0; j < 8; j++) { term *old = Term; /* No window */ if (!angband_term[j]) continue; /* No relevant flags */ if (!flag_exists(&window_flag[j], FLAG_PW_MESSAGE)) continue; /* Activate */ Term_activate(angband_term[j]); /* Get size */ Term_get_size(&w, &h); /* Dump messages */ for (i = 0; i < h; i++) { /* Dump the message on the appropriate line */ display_message(0, (h - 1) - i, strlen(message_str((s16b)i)), message_color((s16b)i), message_str((s16b)i)); /* Cursor */ Term_locate(&x, &y); /* Clear to end of line */ Term_erase(x, y, 255); } /* Fresh */ Term_fresh(); /* Restore */ Term_activate(old); } }
static void init_block0(void) { const char *genesis_hex = NULL; switch (chain->chain_id) { case CHAIN_BITCOIN: genesis_hex = genesis_bitcoin; break; case CHAIN_TESTNET3: genesis_hex = genesis_testnet; break; default: fprintf(plog, "unsupported chain. add genesis block here!\n"); exit(1); break; } size_t olen = 0; size_t genesis_rawlen = strlen(genesis_hex) / 2; char genesis_raw[genesis_rawlen]; if (!decode_hex(genesis_raw, sizeof(genesis_raw), genesis_hex, &olen)) { fprintf(plog, "chain hex decode fail\n"); exit(1); } cstring *msg0 = message_str(chain->netmagic, "block", genesis_raw, genesis_rawlen); ssize_t bwritten = write(blocks_fd, msg0->str, msg0->len); if (bwritten != msg0->len) { fprintf(plog, "blocks write0 failed: %s\n", strerror(errno)); exit(1); } cstr_free(msg0, true); off64_t fpos64 = lseek64(blocks_fd, 0, SEEK_SET); if (fpos64 == (off64_t)-1) { fprintf(plog, "blocks lseek0 failed: %s\n", strerror(errno)); exit(1); } fprintf(plog, "blocks: genesis block written\n"); }
void TSaslServerTransport::handleSaslStartMessage() { uint32_t resLength; NegotiationStatus status; uint8_t* message = receiveSaslMessage(&status, &resLength); // Message is a non-null terminated string; to use it like a // C-string we have to copy it into a null-terminated buffer. string message_str(reinterpret_cast<char*>(message), resLength); if (status != TSASL_START) { stringstream ss; ss << "Expecting START status, received " << status; sendSaslMessage(TSASL_ERROR, reinterpret_cast<const uint8_t*>(ss.str().c_str()), ss.str().size()); throw TTransportException(ss.str()); } map<string, TSaslServerDefinition*>::iterator defn = TSaslServerTransport::serverDefinitionMap_.find(message_str); if (defn == TSaslServerTransport::serverDefinitionMap_.end()) { stringstream ss; ss << "Unsupported mechanism type " << message_str; sendSaslMessage(TSASL_BAD, reinterpret_cast<const uint8_t*>(ss.str().c_str()), ss.str().size()); throw TTransportException(TTransportException::BAD_ARGS, ss.str()); } // TODO: when should realm be used? string realm; TSaslServerDefinition* serverDefinition = defn->second; sasl_.reset(new TSaslServer(serverDefinition->protocol_, serverDefinition->serverName_, realm, serverDefinition->flags_, &serverDefinition->callbacks_[0])); // First argument is interpreted as C-string sasl_->evaluateChallengeOrResponse( reinterpret_cast<const uint8_t*>(message_str.c_str()), resLength, &resLength); }
/** * Write a character dump */ void write_character_dump(ang_file *fff) { int i, x, y; int a; wchar_t c; struct store *home = &stores[STORE_HOME]; struct object **home_list = mem_zalloc(sizeof(struct object *) * z_info->store_inven_max); char o_name[80]; char buf[1024]; char *p; /* Begin dump */ file_putf(fff, " [%s Character Dump]\n\n", buildid); /* Display player */ display_player(0); /* Dump part of the screen */ for (y = 1; y < 23; y++) { p = buf; /* Dump each row */ for (x = 0; x < 79; x++) { /* Get the attr/char */ (void)(Term_what(x, y, &a, &c)); /* Dump it */ p += wctomb(p, c); } /* Back up over spaces */ while ((p > buf) && (p[-1] == ' ')) --p; /* Terminate */ *p = '\0'; /* End the row */ file_putf(fff, "%s\n", buf); } /* Skip a line */ file_putf(fff, "\n"); /* Display player */ display_player(1); /* Dump part of the screen */ for (y = 11; y < 20; y++) { p = buf; /* Dump each row */ for (x = 0; x < 39; x++) { /* Get the attr/char */ (void)(Term_what(x, y, &a, &c)); /* Dump it */ p += wctomb(p, c); } /* Back up over spaces */ while ((p > buf) && (p[-1] == ' ')) --p; /* Terminate */ *p = '\0'; /* End the row */ file_putf(fff, "%s\n", buf); } /* Skip a line */ file_putf(fff, "\n"); /* Dump part of the screen */ for (y = 11; y < 20; y++) { p = buf; /* Dump each row */ for (x = 0; x < 39; x++) { /* Get the attr/char */ (void)(Term_what(x + 40, y, &a, &c)); /* Dump it */ p += wctomb(p, c); } /* Back up over spaces */ while ((p > buf) && (p[-1] == ' ')) --p; /* Terminate */ *p = '\0'; /* End the row */ file_putf(fff, "%s\n", buf); } /* Skip some lines */ file_putf(fff, "\n\n"); /* If dead, dump last messages -- Prfnoff */ if (player->is_dead) { i = messages_num(); if (i > 15) i = 15; file_putf(fff, " [Last Messages]\n\n"); while (i-- > 0) { file_putf(fff, "> %s\n", message_str((s16b)i)); } file_putf(fff, "\nKilled by %s.\n\n", player->died_from); } /* Dump the equipment */ file_putf(fff, " [Character Equipment]\n\n"); for (i = 0; i < player->body.count; i++) { struct object *obj = slot_object(player, i); if (!obj) continue; object_desc(o_name, sizeof(o_name), obj, ODESC_PREFIX | ODESC_FULL); file_putf(fff, "%c) %s\n", gear_to_label(obj), o_name); object_info_chardump(fff, obj, 5, 72); } file_putf(fff, "\n\n"); /* Dump the inventory */ file_putf(fff, "\n\n [Character Inventory]\n\n"); for (i = 0; i < z_info->pack_size; i++) { struct object *obj = player->upkeep->inven[i]; if (!obj) break; object_desc(o_name, sizeof(o_name), obj, ODESC_PREFIX | ODESC_FULL); file_putf(fff, "%c) %s\n", gear_to_label(obj), o_name); object_info_chardump(fff, obj, 5, 72); } file_putf(fff, "\n\n"); /* Dump the quiver */ file_putf(fff, "\n\n [Character Quiver]\n\n"); for (i = 0; i < z_info->quiver_size; i++) { struct object *obj = player->upkeep->quiver[i]; if (!obj) continue; object_desc(o_name, sizeof(o_name), obj, ODESC_PREFIX | ODESC_FULL); file_putf(fff, "%c) %s\n", gear_to_label(obj), o_name); object_info_chardump(fff, obj, 5, 72); } file_putf(fff, "\n\n"); /* Dump the Home -- if anything there */ store_stock_list(home, home_list, z_info->store_inven_max); if (home->stock_num) { /* Header */ file_putf(fff, " [Home Inventory]\n\n"); /* Dump all available items */ for (i = 0; i < z_info->store_inven_max; i++) { struct object *obj = home_list[i]; if (!obj) break; object_desc(o_name, sizeof(o_name), obj, ODESC_PREFIX | ODESC_FULL); file_putf(fff, "%c) %s\n", I2A(i), o_name); object_info_chardump(fff, obj, 5, 72); } /* Add an empty line */ file_putf(fff, "\n\n"); } /* Dump character history */ dump_history(fff); file_putf(fff, "\n\n"); /* Dump options */ file_putf(fff, " [Options]\n\n"); /* Dump options */ for (i = 0; i < OP_MAX; i++) { int opt; const char *title = ""; switch (i) { case OP_INTERFACE: title = "User interface"; break; case OP_BIRTH: title = "Birth"; break; default: continue; } file_putf(fff, " [%s]\n\n", title); for (opt = 0; opt < OPT_MAX; opt++) { if (option_type(opt) != i) continue; file_putf(fff, "%-45s: %s (%s)\n", option_desc(opt), player->opts.opt[opt] ? "yes" : "no ", option_name(opt)); } /* Skip some lines */ file_putf(fff, "\n"); } mem_free(home_list); }
/* * Show previous messages to the user -BEN- * * The screen format uses line 0 and (Term->hgt - 1) for headers and prompts, * skips line 1 and (Term->hgt - 2), and uses line 2 thru (Term->hgt - 3) for * old messages. * * This command shows you which commands you are viewing, and allows * you to "search" for strings in the recall. * * Note that messages may be longer than 80 characters, but they are * displayed using "infinite" length, with a special sub-command to * "slide" the virtual display to the left or right. * * Attempt to only hilite the matching portions of the string. * * Now taking advantages of big-screen. -pav- */ void do_cmd_messages(void) { s32b i, j, k, n, q; s32b wid, hgt; char shower[80]; char finder[80]; /* Wipe finder */ strcpy(finder, ""); /* Wipe shower */ strcpy(shower, ""); /* Total messages */ n = message_num(); /* Start on first message */ i = 0; /* Start at leftmost edge */ q = 0; /* Enter "icky" mode */ character_icky++; /* Save the screen */ Term_save(); /* Process requests until done */ while (1) { /* Clear screen */ Term_clear(); /* Retrieve current screen size */ Term_get_size(&wid, &hgt); /* Dump up to 20 (or more in bigscreen) lines of messages */ for (j = 0; (j < (hgt - 4)) && (i + j < n); j++) { cptr msg = message_str(i + j); byte color = message_color(i + j); /* Apply horizontal scroll */ msg = (strlen(msg) >= q) ? (msg + q) : ""; /* Dump the messages, bottom to top */ display_message(0, (hgt - 3) - j, strlen(msg), color, msg); /* Hilite "shower" */ if (shower[0]) { cptr str = msg; /* Display matches */ while ((str = strstr(str, shower)) != NULL) { s32b len = strlen(shower); /* Display the match */ Term_putstr(str - msg, (hgt - 3) - j, len, TERM_YELLOW, shower); /* Advance */ str += len; } } } /* Display header XXX XXX XXX */ prt(format("Message Recall (%d-%d of %d), Offset %d", i, i + j - 1, n, q), 0, 0); /* Display prompt (not very informative) */ prt("[Press 'p' for older, 'n' for newer, ..., or ESCAPE]", hgt - 1, 0); /* Get a command */ k = inkey(); /* Exit on Escape */ if (k == ESCAPE) break; /* Hack -- Save the old index */ j = i; /* Horizontal scroll */ if (k == '4') { /* Scroll left */ q = (q >= wid / 2) ? (q - wid / 2) : 0; /* Success */ continue; } /* Horizontal scroll */ if (k == '6') { /* Scroll right */ q = q + wid / 2; /* Success */ continue; } /* Hack -- handle show */ if (k == '=') { /* Prompt */ prt("Show: ", hgt - 1, 0); /* Get a "shower" string, or continue */ if (!askfor_aux(shower, 80)) continue; /* Okay */ continue; } /* Hack -- handle find */ if (k == '/') { s16b z; /* Prompt */ prt("Find: ", hgt - 1, 0); /* Get a "finder" string, or continue */ if (!askfor_aux(finder, 80)) continue; /* Show it */ strcpy(shower, finder); /* Scan messages */ for (z = i + 1; z < n; z++) { cptr msg = message_str(z); /* Search for it */ if (strstr(msg, finder)) { /* New location */ i = z; /* Done */ break; } } } /* Recall 1 older message */ if ((k == '8') || (k == '\n') || (k == '\r')) { /* Go newer if legal */ if (i + 1 < n) i += 1; } /* Recall 10 older messages */ if (k == '+') { /* Go older if legal */ if (i + 10 < n) i += 10; } /* Recall one screen of older messages */ if ((k == 'p') || (k == KTRL('P')) || (k == ' ')) { /* Go older if legal */ if (i + (hgt - 4) < n) i += (hgt - 4); } /* Recall one screen of newer messages */ if ((k == 'n') || (k == KTRL('N'))) { /* Go newer (if able) */ i = (i >= (hgt - 4)) ? (i - (hgt - 4)) : 0; } /* Recall 10 newer messages */ if (k == '-') { /* Go newer (if able) */ i = (i >= 10) ? (i - 10) : 0; } /* Recall 1 newer messages */ if (k == '2') { /* Go newer (if able) */ i = (i >= 1) ? (i - 1) : 0; } /* Hack -- Error of some kind */ if (i == j) bell(); } /* Restore the screen */ Term_load(); /* Leave "icky" mode */ character_icky--; }
/* * Hack -- Dump a character description file * * XXX XXX XXX Allow the "full" flag to dump additional info, * and trigger its usage from various places in the code. */ errr file_character(const char *path, bool full) { int i, x, y; byte a; char c; ang_file *fp; struct store *st_ptr = &stores[STORE_HOME]; char o_name[80]; byte (*old_xchar_hook)(byte c) = Term.xchar_hook; char buf[1024]; /* We use either ascii or system-specific encoding */ int encoding = OPT(xchars_to_file) ? SYSTEM_SPECIFIC : ASCII; /* Unused parameter */ (void)full; /* Open the file for writing */ fp = file_open(path, MODE_WRITE, FTYPE_TEXT); if (!fp) return (-1); /* Display the requested encoding -- ASCII or system-specific */ if (!OPT(xchars_to_file)) Term.xchar_hook = null; /* Begin dump */ file_putf(fp, " [%s Character Dump]\n\n", buildid); /* Display player */ display_player(0); /* Dump part of the screen */ for (y = 1; y < 23; y++) { /* Dump each row */ for (x = 0; x < 79; x++) { /* Get the attr/char */ (void)(Term_what(x, y, &a, &c)); /* Dump it */ buf[x] = c; } /* Back up over spaces */ while ((x > 0) && (buf[x-1] == ' ')) --x; /* Terminate */ buf[x] = '\0'; /* End the row */ x_file_putf(fp, encoding, "%s\n", buf); } /* Skip a line */ file_putf(fp, "\n"); /* Display player */ display_player(1); /* Dump part of the screen */ for (y = 11; y < 20; y++) { /* Dump each row */ for (x = 0; x < 39; x++) { /* Get the attr/char */ (void)(Term_what(x, y, &a, &c)); /* Dump it */ buf[x] = c; } /* Back up over spaces */ while ((x > 0) && (buf[x-1] == ' ')) --x; /* Terminate */ buf[x] = '\0'; /* End the row */ x_file_putf(fp, encoding, "%s\n", buf); } /* Skip a line */ file_putf(fp, "\n"); /* Dump part of the screen */ for (y = 11; y < 20; y++) { /* Dump each row */ for (x = 0; x < 39; x++) { /* Get the attr/char */ (void)(Term_what(x + 40, y, &a, &c)); /* Dump it */ buf[x] = c; } /* Back up over spaces */ while ((x > 0) && (buf[x-1] == ' ')) --x; /* Terminate */ buf[x] = '\0'; /* End the row */ x_file_putf(fp, encoding, "%s\n", buf); } /* Skip some lines */ file_putf(fp, "\n\n"); /* If dead, dump last messages -- Prfnoff */ if (p_ptr.is_dead) { i = messages_num(); if (i > 15) i = 15; file_putf(fp, " [Last Messages]\n\n"); while (i-- > 0) { x_file_putf(fp, encoding, "> %s\n", message_str((s16b)i)); } x_file_putf(fp, encoding, "\nKilled by %s.\n\n", p_ptr.died_from); } /* Dump the equipment */ file_putf(fp, " [Character Equipment]\n\n"); for (i = INVEN_WIELD; i < ALL_INVEN_TOTAL; i++) { if (i == INVEN_TOTAL) { file_putf(fp, "\n\n [Character Quiver]\n\n"); continue; } object_desc(o_name, sizeof(o_name), &p_ptr.inventory[i], ODESC_PREFIX | ODESC_FULL); x_file_putf(fp, encoding, "%c) %s\n", index_to_label(i), o_name); if (p_ptr.inventory[i].kind) object_info_chardump(fp, &p_ptr.inventory[i], 5, 72); } /* Dump the inventory */ file_putf(fp, "\n\n [Character Inventory]\n\n"); for (i = 0; i < INVEN_PACK; i++) { if (!p_ptr.inventory[i].kind) break; object_desc(o_name, sizeof(o_name), &p_ptr.inventory[i], ODESC_PREFIX | ODESC_FULL); x_file_putf(fp, encoding, "%c) %s\n", index_to_label(i), o_name); object_info_chardump(fp, &p_ptr.inventory[i], 5, 72); } file_putf(fp, "\n\n"); /* Dump the Home -- if anything there */ if (st_ptr.stock_num) { /* Header */ file_putf(fp, " [Home Inventory]\n\n"); /* Dump all available items */ for (i = 0; i < st_ptr.stock_num; i++) { object_desc(o_name, sizeof(o_name), &st_ptr.stock[i], ODESC_PREFIX | ODESC_FULL); x_file_putf(fp, encoding, "%c) %s\n", I2A(i), o_name); object_info_chardump(fp, &st_ptr.stock[i], 5, 72); } /* Add an empty line */ file_putf(fp, "\n\n"); } /* Dump character history */ dump_history(fp); file_putf(fp, "\n\n"); /* Dump options */ file_putf(fp, " [Options]\n\n"); /* Dump options */ for (i = OPT_BIRTH; i < OPT_BIRTH + N_OPTS_BIRTH; i++) { if (option_name(i)) { file_putf(fp, "%-45s: %s (%s)\n", option_desc(i), op_ptr.opt[i] ? "yes" : "no ", option_name(i)); } } /* Skip some lines */ file_putf(fp, "\n\n"); /* Return to standard display */ Term.xchar_hook = old_xchar_hook; file_close(fp); /* Success */ return (0); }
/** * Show previous messages to the user * * The screen format uses line 0 and 23 for headers and prompts, * skips line 1 and 22, and uses line 2 thru 21 for old messages. * * This command shows you which commands you are viewing, and allows * you to "search" for strings in the recall. * * Note that messages may be longer than 80 characters, but they are * displayed using "infinite" length, with a special sub-command to * "slide" the virtual display to the left or right. * * Attempt to only hilight the matching portions of the string. */ void do_cmd_messages(void) { ui_event ke; int i, j, n, q; int wid, hgt; char shower[80]; char finder[80]; char p[80]; /* Wipe finder */ my_strcpy(finder, "", sizeof(shower)); /* Wipe shower */ my_strcpy(shower, "", sizeof(finder)); /* Total messages */ n = messages_num(); /* Start on first message */ i = 0; /* Start at leftmost edge */ q = 0; /* Get size */ Term_get_size(&wid, &hgt); /* Prompt */ strncpy(p, "[Press 'p' for older, 'n' for newer, ..., or ESCAPE]", 80); /* Save screen */ screen_save(); /* Adjust the buttons */ button_backup_all(); button_kill_all(); button_add("ESC", ESCAPE); button_add("-", '-'); button_add("=", '='); button_add("/", '/'); button_add("p", 'p'); button_add("n", 'n'); button_add("+", '+'); button_add("->", '6'); button_add("<-", '4'); p_ptr->redraw |= (PR_BUTTONS); /* Process requests until done */ while (1) { /* Clear screen */ Term_clear(); /* Dump messages */ for (j = 0; (j < hgt - 4) && (i + j < n); j++) { const char *msg = message_str((s16b)(i+j)); byte attr = message_color((s16b)(i+j)); /* Apply horizontal scroll */ msg = ((int)strlen(msg) >= q) ? (msg + q) : ""; /* Dump the messages, bottom to top */ Term_putstr(0, hgt - 3 - j, -1, attr, msg); /* Hilight "shower" */ if (shower[0]) { const char *str = msg; /* Display matches */ while ((str = strstr(str, shower)) != NULL) { int len = strlen(shower); /* Display the match */ Term_putstr(str-msg, hgt - 3 - j, len, TERM_YELLOW, shower); /* Advance */ str += len; } } } /* Display header XXX XXX XXX */ prt(format("Message Recall (%d-%d of %d), Offset %d", i, i + j - 1, n, q), 0, 0); /* Display prompt (not very informative) */ prt(p, hgt - 1, 0); redraw_stuff(p_ptr); /* Get a command */ ke = inkey_ex(); /* Exit on Escape */ if (ke.key.code == ESCAPE) break; /* Hack -- Save the old index */ j = i; /* Horizontal scroll */ if (ke.key.code == '4') { /* Scroll left */ q = (q >= wid / 2) ? (q - wid / 2) : 0; /* Success */ continue; } /* Horizontal scroll */ if (ke.key.code == '6') { /* Scroll right */ q = q + wid / 2; /* Success */ continue; } /* Hack -- handle show */ if (ke.key.code == '=') { /* Prompt */ prt("Show: ", hgt - 1, 0); /* Get a "shower" string, or continue */ if (!askfor_aux(shower, sizeof shower, NULL)) continue; /* Okay */ continue; } /* Hack -- handle find */ if (ke.key.code == '/') { s16b z; /* Prompt */ prt("Find: ", hgt - 1, 0); /* Get a "finder" string, or continue */ if (!askfor_aux(finder, sizeof finder, NULL)) continue; /* Show it */ my_strcpy(shower, finder, sizeof(shower)); /* Scan messages */ for (z = i + 1; z < n; z++) { const char *msg = message_str(z); /* Search for it */ if (strstr(msg, finder)) { /* New location */ i = z; /* Done */ break; } } } /* Recall 20 older messages */ if ((ke.key.code == 'p') || (ke.key.code == KTRL('P')) || (ke.key.code == ' ')) { /* Go older if legal */ if (i + 20 < n) i += 20; } /* Recall 10 older messages */ if (ke.key.code == '+') { /* Go older if legal */ if (i + 10 < n) i += 10; } /* Recall 1 older message */ if ((ke.key.code == '8') || (ke.key.code == '\n') || (ke.key.code == '\r')) { /* Go older if legal */ if (i + 1 < n) i += 1; } /* Recall 20 newer messages */ if ((ke.key.code == 'n') || (ke.key.code == KTRL('N'))) { /* Go newer (if able) */ i = (i >= 20) ? (i - 20) : 0; } /* Recall 10 newer messages */ if (ke.key.code == '-') { /* Go newer (if able) */ i = (i >= 10) ? (i - 10) : 0; } /* Recall 1 newer messages */ if (ke.key.code == '2') { /* Go newer (if able) */ i = (i >= 1) ? (i - 1) : 0; } /* Scroll forwards or backwards using mouse clicks */ if (ke.mouse.button) { if (ke.mouse.y <= hgt / 2) { /* Go older if legal */ if (i + 20 < n) i += 20; } else { /* Go newer (if able) */ i = (i >= 20) ? (i - 20) : 0; } } /* Hack -- Error of some kind */ if (i == j) bell(NULL); } /* Adjust the buttons */ button_restore(); /* Load screen */ screen_load(); }
/* * Actually write a save-file */ static bool wr_savefile(void) { int i; u32b now; u16b tmp16u; /* Guess at the current time */ now = time((time_t *)0); /* Note the operating system */ sf_xtra = 0L; /* Note when the file was saved */ sf_when = now; /* Note the number of saves */ sf_saves++; /*** Actually write the file ***/ /* Dump the file header */ xor_byte = 0; wr_byte(VERSION_MAJOR); xor_byte = 0; wr_byte(VERSION_MINOR); xor_byte = 0; wr_byte(VERSION_PATCH); xor_byte = 0; wr_byte(VERSION_EXTRA); /* Reset the checksum */ v_stamp = 0L; x_stamp = 0L; /* Operating system */ wr_u32b(sf_xtra); /* Time file last saved */ wr_u32b(sf_when); /* Number of past lives */ wr_u16b(sf_lives); /* Number of times saved */ wr_u16b(sf_saves); // 8 spare bytes wr_u32b(0L); wr_u32b(0L); /* Write the RNG state */ wr_randomizer(); /* Write the boolean "options" */ wr_options(); /* Dump the number of "messages" */ tmp16u = message_num(); wr_u16b(tmp16u); /* Dump the messages (oldest first!) */ for (i = tmp16u - 1; i >= 0; i--) { wr_string(message_str((s16b)i)); wr_u16b(message_type((s16b)i)); } /* Dump the monster lore */ tmp16u = z_info->r_max; wr_u16b(tmp16u); for (i = 0; i < tmp16u; i++) wr_lore(i); /* Dump the object memory */ tmp16u = z_info->k_max; wr_u16b(tmp16u); for (i = 0; i < tmp16u; i++) wr_xtra(i); /* Hack -- Dump the artefacts */ tmp16u = z_info->art_max; wr_u16b(tmp16u); for (i = 0; i < tmp16u; i++) { artefact_type *a_ptr = &a_info[i]; wr_byte(a_ptr->cur_num); wr_byte(a_ptr->found_num); } /* Write the "extra" information */ wr_extra(); /*Write the randarts*/ wr_randarts(); /*Copy the notes file into the savefile*/ wr_notes(); // Write the smithing item wr_item(smith_o_ptr); /* Write the inventory */ for (i = 0; i < INVEN_TOTAL; i++) { object_type *o_ptr = &inventory[i]; /* Skip non-objects */ if (!o_ptr->k_idx) continue; /* Dump index */ wr_u16b((u16b)i); /* Dump object */ wr_item(o_ptr); } /* Add a sentinel */ wr_u16b(0xFFFF); /* Player is not dead, write the dungeon */ if (!p_ptr->is_dead) { /* Dump the dungeon */ wr_dungeon(); } /* Write the "value check-sum" */ wr_u32b(v_stamp); /* Write the "encoded checksum" */ wr_u32b(x_stamp); /* Error in save */ if (ferror(fff) || (fflush(fff) == EOF)) return FALSE; /* Successful save */ return TRUE; }
/* * Show previous messages to the user -BEN- * * The screen format uses line 0 and 23 for headers and prompts, * skips line 1 and 22, and uses line 2 thru 21 for old messages. * * This command shows you which commands you are viewing, and allows * you to "search" for strings in the recall. * * Note that messages may be longer than 80 characters, but they are * displayed using "infinite" length, with a special sub-command to * "slide" the virtual display to the left or right. * * Attempt to only hilite the matching portions of the string. */ void do_cmd_messages(void) { int i, j, k, n, q; char shower[80] = ""; char finder[80] = ""; /* Total messages */ n = message_num(); /* Start on first message */ i = 0; /* Start at leftmost edge */ q = 0; /* Enter "icky" mode */ screen_icky = topline_icky = TRUE; /* Save the screen */ Term_save(); /* Process requests until done */ while (1) { /* Clear screen */ Term_clear(); /* Dump up to 20 lines of messages */ for (j = 0; (j < 20) && (i + j < n); j++) { byte a = TERM_WHITE; cptr str = message_str(i+j); /* Determine color */ message_color(str, &a); /* Apply horizontal scroll */ str = (strlen(str) >= q) ? (str + q) : ""; /* Handle "shower" */ if (shower[0] && strstr(str, shower)) a = TERM_YELLOW; /* Dump the messages, bottom to top */ Term_putstr(0, 21-j, -1, a, str); } /* Display header XXX XXX XXX */ prt(format("Message Recall (%d-%d of %d), Offset %d", i, i+j-1, n, q), 0, 0); /* Display prompt (not very informative) */ prt("[Press 'p' for older, 'n' for newer, ..., or ESCAPE]", 23, 0); /* Get a command */ k = inkey(); /* Exit on Escape */ if (k == ESCAPE) break; /* Hack -- Save the old index */ j = i; /* Horizontal scroll */ if (k == '4') { /* Scroll left */ q = (q >= 40) ? (q - 40) : 0; /* Success */ continue; } /* Horizontal scroll */ if (k == '6') { /* Scroll right */ q = q + 40; /* Success */ continue; } /* Hack -- handle show */ if (k == '=') { /* Prompt */ prt("Show: ", 23, 0); /* Get a "shower" string, or continue */ if (!askfor_aux(shower, 80, 0)) continue; /* Okay */ continue; } /* Hack -- handle find */ if (k == '/') { int z; /* Prompt */ prt("Find: ", 23, 0); /* Get a "finder" string, or continue */ if (!askfor_aux(finder, 80, 0)) continue; /* Scan messages */ for (z = i + 1; z < n; z++) { cptr str = message_str(z); /* Handle "shower" */ if (strstr(str, finder)) { /* New location */ i = z; /* Done */ break; } } } /* Recall 1 older message */ if ((k == '8') || (k == '\n') || (k == '\r')) { /* Go newer if legal */ if (i + 1 < n) i += 1; } /* Recall 10 older messages */ if (k == '+') { /* Go older if legal */ if (i + 10 < n) i += 10; } /* Recall 20 older messages */ if ((k == 'p') || (k == KTRL('P')) || (k == ' ')) { /* Go older if legal */ if (i + 20 < n) i += 20; } /* Recall 20 newer messages */ if ((k == 'n') || (k == KTRL('N'))) { /* Go newer (if able) */ i = (i >= 20) ? (i - 20) : 0; } /* Recall 10 newer messages */ if (k == '-') { /* Go newer (if able) */ i = (i >= 10) ? (i - 10) : 0; } /* Recall 1 newer messages */ if (k == '2') { /* Go newer (if able) */ i = (i >= 1) ? (i - 1) : 0; } /* Hack -- Error of some kind */ if (i == j) bell(); } /* Restore the screen */ Term_load(); /* Leave "icky" mode */ screen_icky = topline_icky = FALSE; /* Flush any queued events */ Flush_queue(); }
/* * Show previous messages to the user * * The screen format uses line 0 and 23 for headers and prompts, * skips line 1 and 22, and uses line 2 thru 21 for old messages. * * This command shows you which commands you are viewing, and allows * you to "search" for strings in the recall. * * Note that messages may be longer than 80 characters, but they are * displayed using "infinite" length, with a special sub-command to * "slide" the virtual display to the left or right. * * Attempt to only highlight the matching portions of the string. */ void do_cmd_messages(void) { ui_event ke; bool more = TRUE; int i, j, n, q; int wid, hgt; char shower[80] = ""; /* Total messages */ n = messages_num(); /* Start on first message */ i = 0; /* Start at leftmost edge */ q = 0; /* Get size */ Term_get_size(&wid, &hgt); /* Save screen */ screen_save(); /* Process requests until done */ while (more) { /* Clear screen */ Term_clear(); /* Dump messages */ for (j = 0; (j < hgt - 4) && (i + j < n); j++) { const char *msg; const char *str = message_str(i + j); byte attr = message_color(i + j); u16b count = message_count(i + j); if (count == 1) msg = str; else msg = format("%s <%dx>", str, count); /* Apply horizontal scroll */ msg = ((int)strlen(msg) >= q) ? (msg + q) : ""; /* Dump the messages, bottom to top */ Term_putstr(0, hgt - 3 - j, -1, attr, msg); /* Highlight "shower" */ if (shower[0]) { str = msg; /* Display matches */ while ((str = my_stristr(str, shower)) != NULL) { int len = strlen(shower); /* Display the match */ Term_putstr(str-msg, hgt - 3 - j, len, TERM_YELLOW, str); /* Advance */ str += len; } } } /* Display header */ prt(format("Message recall (%d-%d of %d), offset %d", i, i + j - 1, n, q), 0, 0); /* Display prompt (not very informative) */ if (shower[0]) prt("[Movement keys to navigate, '-' for next, '=' to find]", hgt - 1, 0); else prt("[Movement keys to navigate, '=' to find, or ESCAPE to exit]", hgt - 1, 0); /* Get a command */ ke = inkey_ex(); /* Scroll forwards or backwards using mouse clicks */ if (ke.type == EVT_MOUSE) { if (ke.mouse.y <= hgt / 2) { /* Go older if legal */ if (i + 20 < n) i += 20; } else { /* Go newer */ i = (i >= 20) ? (i - 20) : 0; } } else if (ke.type == EVT_KBRD) { switch (ke.key.code) { case ESCAPE: { more = FALSE; break; } case '=': { /* Get the string to find */ prt("Find: ", hgt - 1, 0); if (!askfor_aux(shower, sizeof shower, NULL)) continue; /* Set to find */ ke.key.code = '-'; break; } case ARROW_LEFT: case '4': q = (q >= wid / 2) ? (q - wid / 2) : 0; break; case ARROW_RIGHT: case '6': q = q + wid / 2; break; case ARROW_UP: case '8': if (i + 1 < n) i += 1; break; case ARROW_DOWN: case '2': case '\r': case '\n': i = (i >= 1) ? (i - 1) : 0; break; case KC_PGUP: case 'p': case ' ': if (i + 20 < n) i += 20; break; case KC_PGDOWN: case 'n': i = (i >= 20) ? (i - 20) : 0; break; } } /* Find the next item */ if (ke.key.code == '-' && shower[0]) { s16b z; /* Scan messages */ for (z = i + 1; z < n; z++) { /* Search for it */ if (my_stristr(message_str(z), shower)) { /* New location */ i = z; /* Done */ break; } } } } /* Load screen */ screen_load(); }
/* * Recall the most recent message */ void do_cmd_message_one(void) { /* Recall one message XXX XXX XXX */ c_prt(message_color(0), format( "> %s", message_str(0)), 0, 0); }
/*! * @brief セーブデータの書き込み / * Actually write a save-file * @return 成功すればtrue */ static bool wr_savefile_new(void) { int i, j; u32b now; byte tmp8u; u16b tmp16u; /* Compact the objects */ compact_objects(0); /* Compact the monsters */ compact_monsters(0); /* Guess at the current time */ now = time((time_t *)0); /* Note the operating system */ sf_system = 0L; /* Note when the file was saved */ sf_when = now; /* Note the number of saves */ sf_saves++; /*** Actually write the file ***/ /* Dump the file header */ xor_byte = 0; wr_byte(FAKE_VER_MAJOR); xor_byte = 0; wr_byte(FAKE_VER_MINOR); xor_byte = 0; wr_byte(FAKE_VER_PATCH); xor_byte = 0; /* Initial value of xor_byte */ tmp8u = (byte)Rand_external(256); wr_byte(tmp8u); /* Reset the checksum */ v_stamp = 0L; x_stamp = 0L; /* Write the savefile version for Hengband 1.1.1 and later */ wr_byte(H_VER_EXTRA); wr_byte(H_VER_PATCH); wr_byte(H_VER_MINOR); wr_byte(H_VER_MAJOR); /* Operating system */ wr_u32b(sf_system); /* Time file last saved */ wr_u32b(sf_when); /* Number of past lives */ wr_u16b(sf_lives); /* Number of times saved */ wr_u16b(sf_saves); /* Space */ wr_u32b(0L); wr_u16b(0); wr_byte(0); #ifdef JP # ifdef EUC /* EUC kanji code */ wr_byte(2); # endif # ifdef SJIS /* SJIS kanji code */ wr_byte(3); # endif #else /* ASCII */ wr_byte(1); #endif /* Write the RNG state */ wr_randomizer(); /* Write the boolean "options" */ wr_options(); /* Dump the number of "messages" */ tmp16u = message_num(); if (compress_savefile && (tmp16u > 40)) tmp16u = 40; wr_u16b(tmp16u); /* Dump the messages (oldest first!) */ for (i = tmp16u - 1; i >= 0; i--) { wr_string(message_str((s16b)i)); } /* Dump the monster lore */ tmp16u = max_r_idx; wr_u16b(tmp16u); for (i = 0; i < tmp16u; i++) wr_lore(i); /* Dump the object memory */ tmp16u = max_k_idx; wr_u16b(tmp16u); for (i = 0; i < tmp16u; i++) wr_xtra(i); /* Dump the towns */ tmp16u = max_towns; wr_u16b(tmp16u); /* Dump the quests */ tmp16u = max_quests; wr_u16b(tmp16u); /* Dump the quests */ tmp8u = MAX_RANDOM_QUEST-MIN_RANDOM_QUEST; wr_byte(tmp8u); for (i = 0; i < max_quests; i++) { quest_type* const q_ptr = &quest[i]; /* Save status for every quest */ wr_s16b(q_ptr->status); /* And the dungeon level too */ /* (prevents problems with multi-level quests) */ wr_s16b(q_ptr->level); wr_byte(q_ptr->complev); wr_u32b(q_ptr->comptime); /* Save quest status if quest is running */ if (q_ptr->status == QUEST_STATUS_TAKEN || q_ptr->status == QUEST_STATUS_COMPLETED || !is_fixed_quest_idx(i)) { wr_s16b(q_ptr->cur_num); wr_s16b(q_ptr->max_num); wr_s16b(q_ptr->type); wr_s16b(q_ptr->r_idx); wr_s16b(q_ptr->k_idx); wr_byte(q_ptr->flags); wr_byte(q_ptr->dungeon); } } /* Dump the position in the wilderness */ wr_s32b(p_ptr->wilderness_x); wr_s32b(p_ptr->wilderness_y); wr_byte(p_ptr->wild_mode); wr_byte(ambush_flag); wr_s32b(max_wild_x); wr_s32b(max_wild_y); /* Dump the wilderness seeds */ for (i = 0; i < max_wild_x; i++) { for (j = 0; j < max_wild_y; j++) { wr_u32b(wilderness[j][i].seed); } } /* Hack -- Dump the artifacts */ tmp16u = max_a_idx; wr_u16b(tmp16u); for (i = 0; i < tmp16u; i++) { artifact_type *a_ptr = &a_info[i]; wr_byte(a_ptr->cur_num); wr_s16b(a_ptr->floor_id); } /* Write the "extra" information */ wr_extra(); /* Dump the "player hp" entries */ tmp16u = PY_MAX_LEVEL; wr_u16b(tmp16u); for (i = 0; i < tmp16u; i++) { wr_s16b(p_ptr->player_hp[i]); } /* Write spell data */ wr_u32b(p_ptr->spell_learned1); wr_u32b(p_ptr->spell_learned2); wr_u32b(p_ptr->spell_worked1); wr_u32b(p_ptr->spell_worked2); wr_u32b(p_ptr->spell_forgotten1); wr_u32b(p_ptr->spell_forgotten2); wr_s16b(p_ptr->learned_spells); wr_s16b(p_ptr->add_spells); /* Dump the ordered spells */ for (i = 0; i < 64; i++) { wr_byte(p_ptr->spell_order[i]); } /* Write the inventory */ for (i = 0; i < INVEN_TOTAL; i++) { object_type *o_ptr = &inventory[i]; /* Skip non-objects */ if (!o_ptr->k_idx) continue; /* Dump index */ wr_u16b((u16b)i); /* Dump object */ wr_item(o_ptr); } /* Add a sentinel */ wr_u16b(0xFFFF); /* Note the towns */ tmp16u = max_towns; wr_u16b(tmp16u); /* Note the stores */ tmp16u = MAX_STORES; wr_u16b(tmp16u); /* Dump the stores of all towns */ for (i = 1; i < max_towns; i++) { for (j = 0; j < MAX_STORES; j++) { wr_store(&town[i].store[j]); } } /* Write the pet command settings */ wr_s16b(p_ptr->pet_follow_distance); wr_s16b(p_ptr->pet_extra_flags); /* Write screen dump for sending score */ if (screen_dump && (p_ptr->wait_report_score || !p_ptr->is_dead)) { wr_string(screen_dump); } else { wr_string(""); } /* Player is not dead, write the dungeon */ if (!p_ptr->is_dead) { /* Dump the dungeon */ if (!wr_dungeon()) return FALSE; /* Dump the ghost */ wr_ghost(); /* No scripts */ wr_s32b(0); } /* Write the "value check-sum" */ wr_u32b(v_stamp); /* Write the "encoded checksum" */ wr_u32b(x_stamp); /* Error in save */ if (ferror(fff) || (fflush(fff) == EOF)) return FALSE; /* Successful save */ return TRUE; }
/* * Hack -- Dump a character description file * * XXX XXX XXX Allow the "full" flag to dump additional info, * and trigger its usage from various places in the code. */ errr file_character(const char *path, bool full) { int i, x, y; int a; wchar_t c; ang_file *fp; struct store *st_ptr = &stores[STORE_HOME]; char o_name[80]; char buf[1024]; char *p; /* Unused parameter */ (void)full; /* Open the file for writing */ fp = file_open(path, MODE_WRITE, FTYPE_TEXT); if (!fp) return (-1); /* Begin dump */ file_putf(fp, " [%s Character Dump]\n\n", buildid); /* Display player */ display_player(0); /* Dump part of the screen */ for (y = 1; y < 23; y++) { p = buf; /* Dump each row */ for (x = 0; x < 79; x++) { /* Get the attr/char */ (void)(Term_what(x, y, &a, &c)); /* Dump it */ p += wctomb(p, c); } /* Back up over spaces */ while ((p > buf) && (p[-1] == ' ')) --p; /* Terminate */ *p = '\0'; /* End the row */ x_file_putf(fp, "%s\n", buf); } /* Skip a line */ file_putf(fp, "\n"); /* Display player */ display_player(1); /* Dump part of the screen */ for (y = 11; y < 20; y++) { p = buf; /* Dump each row */ for (x = 0; x < 39; x++) { /* Get the attr/char */ (void)(Term_what(x, y, &a, &c)); /* Dump it */ p += wctomb(p, c); } /* Back up over spaces */ while ((p > buf) && (p[-1] == ' ')) --p; /* Terminate */ *p = '\0'; /* End the row */ x_file_putf(fp, "%s\n", buf); } /* Skip a line */ file_putf(fp, "\n"); /* Dump part of the screen */ for (y = 11; y < 20; y++) { p = buf; /* Dump each row */ for (x = 0; x < 39; x++) { /* Get the attr/char */ (void)(Term_what(x + 40, y, &a, &c)); /* Dump it */ p += wctomb(p, c); } /* Back up over spaces */ while ((p > buf) && (p[-1] == ' ')) --p; /* Terminate */ *p = '\0'; /* End the row */ x_file_putf(fp, "%s\n", buf); } /* Skip some lines */ file_putf(fp, "\n\n"); /* If dead, dump last messages -- Prfnoff */ if (p_ptr->is_dead) { i = messages_num(); if (i > 15) i = 15; file_putf(fp, " [Last Messages]\n\n"); while (i-- > 0) { x_file_putf(fp, "> %s\n", message_str((s16b)i)); } x_file_putf(fp, "\nKilled by %s.\n\n", p_ptr->died_from); } /* Dump the equipment */ file_putf(fp, " [Character Equipment]\n\n"); for (i = INVEN_WIELD; i < ALL_INVEN_TOTAL; i++) { if (i == INVEN_TOTAL) { file_putf(fp, "\n\n [Character Quiver]\n\n"); continue; } object_desc(o_name, sizeof(o_name), &p_ptr->inventory[i], ODESC_PREFIX | ODESC_FULL); x_file_putf(fp, "%c) %s\n", index_to_label(i), o_name); if (p_ptr->inventory[i].kind) object_info_chardump(fp, &p_ptr->inventory[i], 5, 72); } /* Dump the inventory */ file_putf(fp, "\n\n [Character Inventory]\n\n"); for (i = 0; i < INVEN_PACK; i++) { if (!p_ptr->inventory[i].kind) break; object_desc(o_name, sizeof(o_name), &p_ptr->inventory[i], ODESC_PREFIX | ODESC_FULL); x_file_putf(fp, "%c) %s\n", index_to_label(i), o_name); object_info_chardump(fp, &p_ptr->inventory[i], 5, 72); } file_putf(fp, "\n\n"); /* Dump the Home -- if anything there */ if (st_ptr->stock_num) { /* Header */ file_putf(fp, " [Home Inventory]\n\n"); /* Dump all available items */ for (i = 0; i < st_ptr->stock_num; i++) { object_desc(o_name, sizeof(o_name), &st_ptr->stock[i], ODESC_PREFIX | ODESC_FULL); x_file_putf(fp, "%c) %s\n", I2A(i), o_name); object_info_chardump(fp, &st_ptr->stock[i], 5, 72); } /* Add an empty line */ file_putf(fp, "\n\n"); } /* Dump character history */ dump_history(fp); file_putf(fp, "\n\n"); /* Dump options */ file_putf(fp, " [Options]\n\n"); /* Dump options */ for (i = 0; i < OPT_PAGE_MAX - 1; i++) { int j; const char *title = ""; switch (i) { case 0: title = "Interface"; break; case 1: title = "Warning"; break; case 2: title = "Birth"; break; } file_putf(fp, " [%s]\n\n", title); for (j = 0; j < OPT_PAGE_PER; j++) { int opt = option_page[i][j]; if (!option_name(opt)) continue; file_putf(fp, "%-45s: %s (%s)\n", option_desc(opt), op_ptr->opt[opt] ? "yes" : "no ", option_name(opt)); } /* Skip some lines */ file_putf(fp, "\n"); } file_close(fp); /* Success */ return (0); }
int main() { std::string name = "BrickyBot"; std::string source = ":BrickyBot!~BrickyBot@BrickHouse"; std::string server = "irc.p2p-network.net"; std::string port = "6667"; std::string channel = "#MyLittleAlcoholic"; bool auto_reconnect = false; // Load and parse the options file for configurability std::vector<std::pair<std::string, std::string> > options = get_pairs_from_file("data/options"); for (std::vector<std::pair<std::string, std::string> >::iterator options_it = options.begin(); options_it != options.end(); options_it++) { if ((*options_it).first == "name") name = (*options_it).second; else if ((*options_it).first == "source") source = (*options_it).second; else if ((*options_it).first == "server") server = (*options_it).second; else if ((*options_it).first == "port") port = (*options_it).second; else if ((*options_it).first == "channel") channel = (*options_it).second; else if ((*options_it).first == "auto_reconnect" && (*options_it).second == "true") auto_reconnect = true; else if ((*options_it).first == "debug" && (*options_it).second == "true") debug = true; } // initialize vectors std::vector<std::string> operators = get_vector_from_file("data/operators"); std::vector<std::string> episodes = get_vector_from_file("data/pony_episodes"); std::vector<boost::tuple<std::string, uint16_t, time_t> > drinks = get_counts_from_tuples(get_tuples_from_file("data/drinkcount")); std::vector<std::pair<std::string, std::string> > responses = get_pairs_from_file("data/responses"); std::vector<boost::tuple<std::string, uint16_t, time_t> > hits = get_counts_from_tuples(get_tuples_from_file("data/hitcount")); // set up signal handlers signal(SIGABRT, handleSignal); signal(SIGINT, handleSignal); signal(SIGTERM, handleSignal); try { // networking shit boost::asio::io_service io_service; boost::asio::ip::tcp::resolver resolver(io_service); boost::asio::ip::tcp::resolver::query query(server, port); boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); boost::asio::ip::tcp::socket socket(io_service); boost::asio::connect(socket, endpoint_iterator); boost::system::error_code ignored_error; uint64_t num_in = 0; bool first_ping = false; bool in_channel = false; while (running) { // Get a message from the server boost::array<char, 1024> buf; boost::system::error_code error; size_t len = socket.read_some(boost::asio::buffer(buf), error); // Check for an error or a closed connection if (error == boost::asio::error::eof) { // Connection closed cleanly by peer running = false; } else if (error) { // Some other dipshit error throw boost::system::system_error(error); } else { // No error. Parse the message. // First form a string from the char array std::string message_str(buf.begin(), buf.begin() + len); // Tokenize the string for multiple messages boost::char_separator<char> msg_sep("\r\n"); boost::tokenizer<boost::char_separator<char> > msg_tok(message_str, msg_sep); // Place all the tokens into a vector std::vector<std::string> message_strings; for (boost::tokenizer<boost::char_separator<char> >::iterator it = msg_tok.begin(); it != msg_tok.end(); ++it) message_strings.push_back(*it); // Process each message for (uint16_t i = 0; i < message_strings.size(); ++i) { dbgPrint("incoming: %s\n", message_strings[i].c_str()); // Tokenize the message boost::char_separator<char> sep(" "); boost::tokenizer<boost::char_separator<char> > tok(message_strings[i], sep); std::vector<std::string> tokens; for (boost::tokenizer<boost::char_separator<char> >::iterator it = tok.begin(); it != tok.end(); ++it) tokens.push_back(*it); // Now process the message. if (tokens[0] == "PING") { // Build a new string consisting of PONG followed by everything else std::string send_str = "PONG"; for (uint16_t j = 1; j < tokens.size(); ++j) send_str += " " + tokens[j]; // Add the carriage return and newline, as per IRC protocol send_str += "\r\n"; // Send it to the server boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error); first_ping = true; } num_in++; // Stupid IRC bullshit. Send some info after getting three messages. if (num_in == 3) { // Send the USER/NICK message pair after 3 receives // (What a w***e; receieves three times before telling its name...) std::string nick_msg_str = "NICK " + name + "\r\n"; std::string user_msg_str = "USER " + name + " 0 * :" + name + "\r\n"; boost::asio::write(socket, boost::asio::buffer(nick_msg_str), ignored_error); boost::asio::write(socket, boost::asio::buffer(user_msg_str), ignored_error); } // Join the channel when appropriate if (first_ping && !in_channel) { // Connect after being pinged std::string send_str = source + " JOIN :" + channel + "\r\n"; boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error); // wait a bit... //boost::this_thread::sleep(boost::posix_time::milliseconds(1000)); in_channel = true; } // Bot is in the channel. The interesting shit is here if (in_channel) { // Used to send messages std::string send_str; if (tokens[1] == "PRIVMSG") // gettin a message { // Get the name of the sending user boost::char_separator<char> user_tok_sep(":!"); boost::tokenizer<boost::char_separator<char> > user_tok(tokens[0], user_tok_sep); std::string sending_user = *(user_tok.begin()); // Check whether the sending user is an operator bool user_is_operator = (std::find(operators.begin(), operators.end(), sending_user) != operators.end()); // Find the start of the text uint16_t chat_start_index = 2; while (tokens[chat_start_index][0] != ':') ++chat_start_index; // Add the first token (the start of the message) and remove the leading colon std::string chat_text = tokens[chat_start_index]; chat_text.erase(0, 1); for (uint16_t chat_text_index = chat_start_index + 1; chat_text_index < tokens.size(); ++chat_text_index) { chat_text += " " + tokens[chat_text_index]; } boost::char_separator<char> chat_sep(" "); boost::tokenizer<boost::char_separator<char> > chat_tok(chat_text, chat_sep); std::string chat_command = chat_text; int16_t chat_arg = -1; if (std::distance(chat_tok.begin(), chat_tok.end()) > 0) { chat_command = *(chat_tok.begin()); boost::tokenizer<boost::char_separator<char> >::iterator chat_tok_it = chat_tok.begin(); if (++chat_tok_it != chat_tok.end()) { try { chat_arg = boost::lexical_cast<int16_t>(*chat_tok_it); } catch (boost::bad_lexical_cast &) { BB } } if (chat_arg < -1) chat_arg = -1; } /* * This is where the bot actually does interesting things. * ---AT THIS INDENTATION, MOTHERFUCKERS.--- */ // quit if an operator tells it to if (boost::iequals(chat_text, name + ": quit") && user_is_operator) { send_str = source + " QUIT " + channel + " :quitting\r\n"; boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error); running = false; } // reload operators file when ordered to by an operator if (boost::iequals(chat_text, name + ": reload ops") && user_is_operator) { operators = get_vector_from_file("data/operators"); send_str = source + " PRIVMSG " + channel + " :Reloaded operators.\r\n"; boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error); } // .poni if (boost::iequals(chat_command, ".poni")) { // pick a random episode int episode = rand() % episodes.size(); send_str = source + " PRIVMSG " + channel + " :" + episodes[episode] + "\r\n"; boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error); } // reload mlp episode list when ordered to by an operator if (boost::iequals(chat_text, name + ": reload poni") && user_is_operator) { episodes = get_vector_from_file("data/pony_episodes"); send_str = source + " PRIVMSG " + channel + " :Reloaded poni.\r\n"; boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error); } if (boost::iequals(chat_command, ".shot") || boost::iequals(chat_command, ".drink")) { // Find the user in the vector int32_t user_index = get_user_index_in_counts(sending_user, drinks); uint16_t current_drink_count; // If the user is already in the vector, increment the count and update the time. // Otherwise, add the user and initialize them. if (user_index != -1) { time_t rawtime; time (&rawtime); drinks[user_index].get<1>() += chat_arg == -1? 1: chat_arg; current_drink_count = boost::get<1>(drinks[user_index]); drinks[user_index].get<2>() = rawtime; // drinks[user_index].second += chat_arg == -1? 1: chat_arg; // current_drink_count = drinks[user_index].second; } else { ///////// Found a bug: if the user isn't in the array and adds more than one, it will only count as one, but ///////// it will say that it added however many it said it would. or so I think. I'm pretty drunk right now. time_t rawtime; time (&rawtime); drinks.push_back(boost::make_tuple(sending_user, 1, rawtime)); //drinks.push_back(std::make_pair(sending_user, 1)); current_drink_count = chat_arg == -1? 1 : chat_arg; } // Write the changes to disk write_counts(drinks, "data/drinkcount"); // Convert the number of drinks into a string std::ostringstream num_to_str; num_to_str << current_drink_count; std::string drink_count_str = num_to_str.str(); // send the current number of drinks send_str = source + " PRIVMSG " + channel + " :" + sending_user + ": you are now at " + drink_count_str + " drink(s).\r\n"; boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error); } if (boost::iequals(chat_command, ".weed") || boost::iequals(chat_command, ".hit") || boost::iequals(chat_command, ".toke")) { // Find the user in the vector int32_t user_index = get_user_index_in_counts(sending_user, hits); uint16_t current_hit_count; // If the user is already in the vector, increment the count. // Otherwise, add the user and initialize them with one drink. if (user_index != -1) { time_t rawtime; time (&rawtime); hits[user_index].get<1>() += chat_arg == -1? 1: chat_arg; current_hit_count = boost::get<1>(hits[user_index]); hits[user_index].get<2>() = rawtime; //hits[user_index].second += chat_arg == -1? 1: chat_arg; //current_hit_count = hits[user_index].second; } else { ///////// Found a bug: if the user isn't in the array and adds more than one, it will only count as one, but ///////// it will say that it added however many it said it would. or so I think. I'm pretty drunk right now. time_t rawtime; time (&rawtime); hits.push_back(boost::make_tuple(sending_user, 1, rawtime)); //hits.push_back(std::make_pair(sending_user, 1)); current_hit_count = chat_arg == -1? 1: chat_arg; } // Write the changes to disk write_counts(hits, "data/hitcount"); // Convert the number of drinks into a string std::ostringstream num_to_str; num_to_str << current_hit_count; std::string hit_count_str = num_to_str.str(); // send the current number of drinks send_str = source + " PRIVMSG " + channel + " :" + sending_user + ": you are now at " + hit_count_str + " hit(s).\r\n"; boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error); } if (boost::iequals(chat_command, ".reset")) { ////////////////// Reset Drink Count // Find the user in the vector int32_t user_index = get_user_index_in_counts(sending_user, drinks); // set that user's shot/drink count to zero if (user_index != -1) { //drinks[user_index].second = 0; drinks[user_index].get<1>() = 0; } else { time_t rawtime; time(&rawtime); //drinks.push_back(std::make_pair(sending_user, 0)); drinks.push_back(boost::make_tuple(sending_user, 0, rawtime)); } // write changes to disk write_counts(drinks, "data/drinkcount"); ////////////////// Reset Hit Count // Find the user in the vector user_index = get_user_index_in_counts(sending_user, hits); // set that user's hit count to zero if (user_index != -1) { //hits[user_index].second = 0; hits[user_index].get<1>() = 0; } else { time_t rawtime; time(&rawtime); //hits.push_back(std::make_pair(sending_user, 0)); hits.push_back(boost::make_tuple(sending_user, 0, rawtime)); } // write changes to disk write_counts(hits, "data/hitcount"); // send acknowledgement send_str = source + " PRIVMSG " + channel + " :" + sending_user + ": you are now at 0 drinks and 0 hits.\r\n"; boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error); } // Print user's counts if (boost::iequals(chat_command, ".count")) { // Find the user in the vector int32_t user_index = get_user_index_in_counts(sending_user, drinks); send_str = source + " PRIVMSG " + channel + " :" + sending_user + ": you are now at "; if (user_index != -1) { std::ostringstream num_to_str; //num_to_str << drinks[user_index].second; num_to_str << drinks[user_index].get<1>(); send_str += num_to_str.str(); } else { send_str += "0"; } send_str += " drinks and "; user_index = get_user_index_in_counts(sending_user, hits); if (user_index != -1) { std::ostringstream num_to_str; //num_to_str << hits[user_index].second; num_to_str << hits[user_index].get<1>(); send_str += num_to_str.str(); } else { send_str += "0"; } send_str += " hits.\r\n"; boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error); } // Print the time of the user's last count update if (boost::iequals(chat_command, ".lastdrink")) { int32_t user_index = get_user_index_in_counts(sending_user, drinks); send_str = source + " PRIVMSG " + channel + " :" + sending_user + ": "; if (user_index != -1) { if (boost::get<1>(drinks[user_index]) > 0) { send_str += "Last counted drink was at " + std::string(ctime(&(boost::get<2>(drinks[user_index])))) + ".\r\n"; } else { send_str += "You have no counted drinks.\r\n"; } } else { send_str += "You have no counted drinks.\r\n"; } boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error); } if (boost::iequals(chat_command, ".lasthit")) { int32_t user_index = get_user_index_in_counts(sending_user, drinks); send_str = source + " PRIVMSG " + channel + " :" + sending_user + ": "; if (user_index != -1) { if (boost::get<1>(hits[user_index]) > 0) { send_str += "Last counted hit was at " + std::string(ctime(&(boost::get<2>(hits[user_index])))) + ".\r\n"; } else { send_str += "You have no counted hits.\r\n"; } } else { send_str += "You have no counted hits.\r\n"; } boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error); } // Print the channel's total number of recorded drinks if (boost::iequals(chat_command, ".chtotal")) { uint32_t total = 0; //for (std::vector<std::pair<std::string, uint16_t> >::iterator drinks_it = drinks.begin(); drinks_it != drinks.end(); drinks_it++) for (std::vector<boost::tuple<std::string, uint16_t, time_t> >::iterator drinks_it = drinks.begin(); drinks_it != drinks.end(); drinks_it++) { //total += (*drinks_it).second; total += boost::get<1>(*drinks_it); } std::ostringstream num_to_str; num_to_str << total; send_str = source + " PRIVMSG " + channel + " :Total drinks: " + num_to_str.str() + "; "; total = 0; //for (std::vector<std::pair<std::string, uint16_t> >::iterator hits_it = hits.begin(); hits_it != hits.end(); hits_it++) for (std::vector<boost::tuple<std::string, uint16_t, time_t> >::iterator hits_it = hits.begin(); hits_it != hits.end(); hits_it++) { //total += (*hits_it).second; total += boost::get<1>(*hits_it); } std::ostringstream num_to_str2; num_to_str2 << total; send_str += "Total hits: " + num_to_str2.str() + "\r\n"; boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error); } // Send all the drink info if (boost::iequals(chat_command, ".chdrinks")) { send_str = source + " PRIVMSG " + channel + " :Channel Drinks: "; for (uint16_t i = 0; i < drinks.size(); i++) { //if (drinks[i].second > 0) if (drinks[i].get<1>() > 0) { std::ostringstream num_to_str; //num_to_str << drinks[i].second; num_to_str << boost::get<1>(drinks[i]); //send_str += drinks[i].first + ": " + num_to_str.str() + ". "; send_str += boost::get<0>(drinks[i]) + ": " + num_to_str.str() + ". "; } } send_str += "\r\n"; boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error); } // Send all the hits info if (boost::iequals(chat_command, ".chhits")) { send_str = source + " PRIVMSG " + channel + " :Channel Hits: "; for (uint16_t i = 0; i < hits.size(); i++) { //if (hits[i].second > 0) if (hits[i].get<1>() > 0) { std::ostringstream num_to_str; //num_to_str << hits[i].second; num_to_str << boost::get<1>(drinks[i]); //send_str += hits[i].first + ": " + num_to_str.str() + ". "; send_str += boost::get<0>(drinks[i]) + ": " + num_to_str.str() + ". "; } } send_str += "\r\n"; boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error); } // Operator command to reset all drinks if (boost::iequals(chat_text, name + ": reset all drinks") && user_is_operator) { for (uint16_t i = 0; i < drinks.size(); i++) { drinks[i].get<1>() = 0; // drinks[i].second = 0; } write_counts(drinks, "data/drinkcount"); send_str = source + " PRIVMSG " + channel + " :All drinks were reset.\r\n"; boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error); } // Operator command to reset all hits if (boost::iequals(chat_text, name + ": reset all hits") && user_is_operator) { for (uint16_t i = 0; i < hits.size(); i++) { //hits[i].second = 0; hits[i].get<1>() = 0; } write_counts(hits, "data/hitcount"); send_str = source + " PRIVMSG " + channel + " :All hits were reset.\r\n"; boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error); } // Operator command to reset both counters if (boost::iequals(chat_text, name + ": reset all") && user_is_operator) { for (uint16_t i = 0; i < drinks.size(); i++) { //drinks[i].second = 0; drinks[i].get<1>() = 0; } write_counts(drinks, "data/drinkcount"); for (uint16_t i = 0; i < hits.size(); i++) { //hits[i].second = 0; hits[i].get<1>() = 0; } write_counts(hits, "data/hitcount"); send_str = source + " PRIVMSG " + channel + " :All drinks and hits were reset.\r\n"; boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error); } // modifying responses while running if (boost::iequals(chat_text, name + ": reload responses") && user_is_operator) { responses = get_pairs_from_file("data/responses"); send_str = source + " PRIVMSG " + channel + " :Reloaded responses.\r\n"; boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error); } // simple response commands for (std::vector<std::pair<std::string, std::string> >::iterator resp_it = responses.begin(); resp_it != responses.end(); resp_it++) { if (boost::iequals(chat_command, (*resp_it).first)) { send_str = source + " PRIVMSG " + channel + " :" + (*resp_it).second + "\r\n"; boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error); } } } else if (tokens[1] == "KICK" && tokens[3] == name) // The bot was kicked { boost::char_separator<char> user_tok_sep(":!"); boost::tokenizer<boost::char_separator<char> > user_tok(tokens[0], user_tok_sep); std::string sending_user = *(user_tok.begin()); bool user_is_operator = (std::find(operators.begin(), operators.end(), sending_user) != operators.end()); if (auto_reconnect && !user_is_operator) { // rejoin the channel std::string send_str = source + " JOIN :" + channel + "\r\n"; boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error); } else { // don't rejoin; just quit send_str = source + " QUIT " + channel + " :quitting\r\n"; boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error); running = false; } } } } }