/** * Substitute placeholders in a command string. Placeholders consist of two characters, * the first being a %. Use %% to output a plain % character. * * - <code>%i</code>: id member of the event * - <code>%p</code>: (symbolic events only) local player number * * @param command Original command string with the placeholders. * @param event Event data. * @param eb Binding data. * @param out String with placeholders replaced. */ static void B_SubstituteInCommand(char const *command, ddevent_t const *event, evbinding_t *eb, ddstring_t *out) { const char* ptr = command; for(; *ptr; ptr++) { if(*ptr == '%') { // Escape. ptr++; // Must have another character in the placeholder. if(!*ptr) break; if(*ptr == 'i') { int id = 0; switch(event->type) { case E_TOGGLE: id = event->toggle.id; break; case E_AXIS: id = event->axis.id; break; case E_ANGLE: id = event->angle.id; break; case E_SYMBOLIC: id = event->symbolic.id; break; default: break; } Str_Appendf(out, "%i", id); } else if(*ptr == 'p') { int id = 0; if(event->type == E_SYMBOLIC) { id = P_ConsoleToLocal(event->symbolic.id); } Str_Appendf(out, "%i", id); } else if(*ptr == '%') { Str_AppendChar(out, *ptr); } continue; } Str_AppendChar(out, *ptr); } }
void B_AppendAxisPositionToString(ebstate_t state, float pos, ddstring_t* str) { if(state == EBAXIS_WITHIN) Str_Appendf(str, "-within%g", pos); else if(state == EBAXIS_BEYOND) Str_Appendf(str, "-beyond%g", pos); else if(state == EBAXIS_BEYOND_POSITIVE) Str_Appendf(str, "-pos%g", pos); else Str_Appendf(str, "-neg%g", -pos); }
void B_AppendDeviceDescToString(uint device, ddeventtype_t type, int id, ddstring_t* str) { inputdev_t* dev = I_GetDevice(device, false); const char* name; if(type != E_SYMBOLIC) { // Name of the device. Str_Append(str, dev->name); Str_Append(str, "-"); } switch(type) { case E_TOGGLE: if(dev->keys[id].name) { Str_Append(str, dev->keys[id].name); } else if(device == IDEV_KEYBOARD) { name = B_ShortNameForKey(id); if(name) Str_Append(str, name); else Str_Appendf(str, "code%03i", id); } else Str_Appendf(str, "button%i",id + 1); break; case E_AXIS: Str_Append(str, dev->axes[id].name); break; case E_ANGLE: Str_Appendf(str, "hat%i", id + 1); break; case E_SYMBOLIC: Str_Append(str, "sym"); break; default: Con_Error("B_AppendDeviceDescToString: Invalid value, type = %i.", (int) type); break; } }
/** * @param ev Event. * @param str The event in textual format is appended here. */ void B_AppendEventToString(const ddevent_t* ev, ddstring_t* str) { B_AppendDeviceDescToString(ev->device, ev->type, ev->type == E_TOGGLE? ev->toggle.id : ev->type == E_AXIS? ev->axis.id : ev->type == E_ANGLE? ev->angle.id : ev->type == E_SYMBOLIC? ev->symbolic.id : 0, str); switch(ev->type) { case E_TOGGLE: B_AppendToggleStateToString(ev->toggle.state == ETOG_DOWN? EBTOG_DOWN : ev->toggle.state == ETOG_UP? EBTOG_UP : EBTOG_REPEAT, str); break; case E_AXIS: B_AppendAxisPositionToString(ev->axis.pos >= 0? EBAXIS_BEYOND_POSITIVE : EBAXIS_BEYOND_NEGATIVE, ev->axis.pos, str); break; case E_ANGLE: B_AppendAnglePositionToString(ev->angle.pos, str); break; case E_SYMBOLIC: Str_Appendf(str, "-%s", ev->symbolic.name); break; case E_FOCUS: break; } }
void B_AppendAnglePositionToString(float pos, ddstring_t* str) { if(pos < 0) Str_Append(str, "-center"); else Str_Appendf(str, "-angle%g", pos); }
/** * Does the opposite of the B_Parse* methods for event descriptor, including the * state conditions. */ void B_EventBindingToString(const evbinding_t* eb, ddstring_t* str) { int i; Str_Clear(str); B_AppendDeviceDescToString(eb->device, eb->type, eb->id, str); if(eb->type == E_TOGGLE) { B_AppendToggleStateToString(eb->state, str); } else if(eb->type == E_AXIS) { B_AppendAxisPositionToString(eb->state, eb->pos, str); } else if(eb->type == E_ANGLE) { B_AppendAnglePositionToString(eb->pos, str); } else if(eb->type == E_SYMBOLIC) { Str_Appendf(str, "-%s", eb->symbolicName); } // Append any state conditions. for(i = 0; i < eb->numConds; ++i) { Str_Append(str, " + "); B_AppendConditionToString(&eb->conds[i], str); } }
void P_SetYellowMessage(player_t* pl, int flags, const char* msg) { #define YELLOW_FMT "{r=1;g=0.7;b=0.3;}" #define YELLOW_FMT_LEN 18 size_t len; AutoStr* buf; if(!msg || !msg[0]) return; len = strlen(msg); buf = AutoStr_NewStd(); Str_Reserve(buf, YELLOW_FMT_LEN + len+1); Str_Set(buf, YELLOW_FMT); Str_Appendf(buf, "%s", msg); ST_LogPost(pl - players, flags, Str_Text(buf)); if(pl == &players[CONSOLEPLAYER] && cfg.echoMsg) Con_FPrintf(CPF_CYAN, "%s\n", msg); // Servers are responsible for sending these messages to the clients. /// @todo We shouldn't need to send the format string along with every /// important game message. Instead flag a bit in the packet and then /// reconstruct on the other end. NetSv_SendMessage(pl - players, Str_Text(buf)); #undef YELLOW_FMT }
/** * Open a demo file and begin recording. * Returns false if the recording can't be begun. */ boolean Demo_BeginRecording(const char* fileName, int plrNum) { DENG_UNUSED(fileName); DENG_UNUSED(plrNum); return false; #if 0 client_t* cl = &clients[plrNum]; player_t* plr = &ddPlayers[plrNum]; ddstring_t buf; // Is a demo already being recorded for this client? if(cl->recording || playback || (isDedicated && !plrNum) || !plr->shared.inGame) return false; // Compose the real file name. Str_InitStd(&buf); Str_Appendf(&buf, "%s%s", demoPath, fileName); F_ExpandBasePath(&buf, &buf); F_ToNativeSlashes(&buf, &buf); // Open the demo file. cl->demo = lzOpen(Str_Text(&buf), "wp"); Str_Free(&buf); if(!cl->demo) { return false; // Couldn't open it! } cl->recording = true; cl->recordPaused = false; writeInfo[plrNum].first = true; writeInfo[plrNum].canwrite = false; writeInfo[plrNum].cameratimer = 0; writeInfo[plrNum].fov = -1; // Must be written in the first packet. if(isServer) { // Playing demos alters gametic. This'll make sure we're going to // get updates. clients[0].lastTransmit = -1; // Servers need to send a handshake packet. // It only needs to recorded in the demo file, though. allowSending = false; Sv_Handshake(plrNum, false); // Enable sending to network. allowSending = true; } else { // Clients need a Handshake packet. // Request a new one from the server. Cl_SendHello(); } // The operation is a success. return true; #endif }
void B_AppendConditionToString(const statecondition_t* cond, ddstring_t* str) { if(cond->type == SCT_STATE) { if(cond->flags.multiplayer) { Str_Append(str, "multiplayer"); } } else if(cond->type == SCT_MODIFIER_STATE) { Str_Appendf(str, "modifier-%i", cond->id - CTL_MODIFIER_1 + 1); } else { B_AppendDeviceDescToString(cond->device, cond->type == SCT_TOGGLE_STATE? E_TOGGLE : cond->type == SCT_AXIS_BEYOND? E_AXIS : E_ANGLE, cond->id, str); } if(cond->type == SCT_TOGGLE_STATE || cond->type == SCT_MODIFIER_STATE) { B_AppendToggleStateToString(cond->state, str); } else if(cond->type == SCT_AXIS_BEYOND) { B_AppendAxisPositionToString(cond->state, cond->pos, str); } else if(cond->type == SCT_ANGLE_AT) { B_AppendAnglePositionToString(cond->pos, str); } // Flags. if(cond->flags.negate) { Str_Append(str, "-not"); } }
static Uri *readTextureUrn(Reader *reader, char const *schemeName) { DENG_ASSERT(reader && schemeName); return Uri_NewWithPath2(Str_Text(Str_Appendf(AutoStr_NewStd(), "urn:%s:%i", schemeName, Reader_ReadInt16(svReader))), RC_NULL); }
/// @note Derived from Qt's QByteArray q_toPercentEncoding ddstring_t *Str_PercentEncode2(ddstring_t *str, char const *excludeChars, char const *includeChars) { dd_bool didEncode = false; int i, span, begin, len; ddstring_t buf; DENG_ASSERT(str); if(!str) return 0; if(Str_IsEmpty(str)) return str; len = Str_Length(str); begin = span = 0; for(i = 0; i < len; ++i) { char ch = str->str[i]; // Are we encoding this? if(((ch >= 0x61 && ch <= 0x7A) // ALPHA || (ch >= 0x41 && ch <= 0x5A) // ALPHA || (ch >= 0x30 && ch <= 0x39) // DIGIT || ch == 0x2D // - || ch == 0x2E // . || ch == 0x5F // _ || ch == 0x7E // ~ || (excludeChars && strchr(excludeChars, ch))) && !(includeChars && strchr(includeChars, ch))) { // Not an encodeable. Span grows. span++; } else { // Found an encodeable. if(!didEncode) { Str_InitStd(&buf); Str_Reserve(&buf, len*3); // Worst case. didEncode = true; } Str_PartAppend(&buf, str->str, begin, span); Str_Appendf(&buf, "%%%X", (uint)ch); // Start a new span. begin += span + 1; span = 0; } } if(didEncode) { // Copy anything remaining. if(span) { Str_PartAppend(&buf, str->str, begin, span); } Str_Set(str, Str_Text(&buf)); Str_Free(&buf); } return str; }
void FI_StackExecuteWithId(const char* scriptSrc, int flags, finale_mode_t mode, const char* defId) { fi_state_t* s, *prevTopScript; gamestate_t prevGamestate; ddstring_t setupCmds; finaleid_t finaleId; int i, fontIdx; if(!finaleStackInited) Con_Error("FI_StackExecute: Not initialized yet!"); // Should we ignore this? if(defId && stackHasDefId(defId)) { Con_Message("There already is a finale running with ID \"%s\"; won't execute again.", defId); return; } prevGamestate = G_GameState(); prevTopScript = stackTop(); // Configure the predefined fonts. Str_Init(&setupCmds); fontIdx = 1; Str_Appendf(&setupCmds, "prefont %i %s", fontIdx++, "a"); Str_Appendf(&setupCmds, "\nprefont %i %s", fontIdx++, "b"); Str_Appendf(&setupCmds, "\nprefont %i %s", fontIdx++, "status"); #if __JDOOM__ Str_Appendf(&setupCmds, "\nprefont %i %s", fontIdx++, "index"); #endif #if __JDOOM__ || __JDOOM64__ Str_Appendf(&setupCmds, "\nprefont %i %s", fontIdx++, "small"); #endif #if __JHERETIC__ || __JHEXEN__ Str_Appendf(&setupCmds, "\nprefont %i %s", fontIdx++, "smallin"); #endif // Configure the predefined colors. #if __JDOOM__ Str_Appendf(&setupCmds, "\nprecolor 2 %f %f %f\n", defFontRGB[CR], defFontRGB[CG], defFontRGB[CB]); Str_Appendf(&setupCmds, "\nprecolor 1 %f %f %f\n", defFontRGB2[CR], defFontRGB2[CG], defFontRGB2[CB]); Str_Appendf(&setupCmds, "\nprecolor 3 %f %f %f\n", defFontRGB3[CR], defFontRGB3[CG], defFontRGB3[CB]); i = 4; #elif __JHERETIC__ Str_Appendf(&setupCmds, "\nprecolor 3 %f %f %f\n", defFontRGB[CR], defFontRGB[CG], defFontRGB[CB]); Str_Appendf(&setupCmds, "\nprecolor 2 %f %f %f\n", defFontRGB2[CR], defFontRGB2[CG], defFontRGB2[CB]); Str_Appendf(&setupCmds, "\nprecolor 1 %f %f %f\n", defFontRGB3[CR], defFontRGB3[CG], defFontRGB3[CB]); i = 4; #elif __JHEXEN__ Str_Appendf(&setupCmds, "\nprecolor 3 %f %f %f\n", defFontRGB[CR], defFontRGB[CG], defFontRGB[CB]); Str_Appendf(&setupCmds, "\nprecolor 2 %f %f %f\n", defFontRGB2[CR], defFontRGB2[CG], defFontRGB2[CB]); Str_Appendf(&setupCmds, "\nprecolor 1 %f %f %f\n", defFontRGB3[CR], defFontRGB3[CG], defFontRGB3[CB]); i = 4; #elif __JDOOM64__ Str_Appendf(&setupCmds, "\nprecolor 2 %f %f %f\n", defFontRGB[CR], defFontRGB[CG], defFontRGB[CB]); Str_Appendf(&setupCmds, "\nprecolor 1 %f %f %f\n", defFontRGB2[CR], defFontRGB2[CG], defFontRGB2[CB]); i = 3; #else i = 0; #endif // Set the rest to white. for(; i <= FIPAGE_NUM_PREDEFINED_COLORS; ++i) { Str_Appendf(&setupCmds, "\nprecolor %i 1 1 1\n", i); } finaleId = FI_Execute2(scriptSrc, flags, Str_Text(&setupCmds)); Str_Free(&setupCmds); if(finaleId == 0) return; if(mode != FIMODE_OVERLAY) { G_ChangeGameState(GS_INFINE); } // Only the top-most script can be "active". if(prevTopScript) { FI_ScriptSuspend(prevTopScript->finaleId); } s = stackPush(finaleId, mode, prevGamestate, defId); // Do we need to transmit the state conditions to clients? if(IS_SERVER && !(flags & FF_LOCAL)) { NetSv_SendFinaleState(s); } }