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 }
virtual void invoke(int player, EventSequenceArg* args, int numArgs) { if(!strchr(Str_Text(&commandTemplate), '%')) { DD_Execute(true/*silent*/, Str_Text(&commandTemplate)); return; } // Compose the command from the template, inserting values for named arguments. /// @todo This logic should be extracted and made into an Str method. AutoStr* cmd = AutoStr_NewStd(); // Reserve an estimate of the composed command length. Str_Reserve(cmd, Str_Length(&commandTemplate) + numArgs + 1); int len = Str_Length(&commandTemplate); const char* start = Str_Text(&commandTemplate); const char* ch = start, *substart = start; while(ch + 1 < start + len) { if(ch[0] == '%' && ch[1] && ch[1] != '%') { Str_PartAppend(cmd, substart, 0, ch - substart); if(ch[1] == 'p') { Str_AppendChar(cmd, '0' + player); } else { int arg = ch[1] - '0' - 1; DENG_ASSERT(arg >= 0 && arg < 9); Str_AppendChar(cmd, char(args[arg])); } ch += 2; substart = ch; } else { ch++; } } // Add anything remaining. Str_Append(cmd, substart); DD_Execute(true/*silent*/, Str_Text(cmd)); }
/// @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; }
de::Action *EventBinding_ActionForEvent(evbinding_t *eb, ddevent_t const *event, struct bcontext_s *eventClass, bool respectHigherAssociatedContexts) { int i; inputdev_t* dev = 0; ddstring_t command; if(eb->device != event->device || eb->type != event->type) return 0; if(event->type != E_SYMBOLIC) { dev = I_GetDevice(eb->device, true); if(!dev) { // The device is not active, there is no way this could get executed. return 0; } } switch(event->type) { case E_TOGGLE: if(eb->id != event->toggle.id) return 0; if(respectHigherAssociatedContexts) { if(eventClass && dev->keys[eb->id].assoc.bContext != eventClass) return 0; // Shadowed by a more important active class. } // We're checking it, so clear the triggered flag. dev->keys[eb->id].assoc.flags &= ~IDAF_TRIGGERED; // Is the state as required? switch(eb->state) { case EBTOG_UNDEFINED: // Passes no matter what. break; case EBTOG_DOWN: if(event->toggle.state != ETOG_DOWN) return 0; break; case EBTOG_UP: if(event->toggle.state != ETOG_UP) return 0; break; case EBTOG_REPEAT: if(event->toggle.state != ETOG_REPEAT) return 0; break; case EBTOG_PRESS: if(event->toggle.state == ETOG_UP) return 0; break; default: return 0; } break; case E_AXIS: if(eb->id != event->axis.id) return 0; if(eventClass && dev->axes[eb->id].assoc.bContext != eventClass) return 0; // Shadowed by a more important active class. // Is the position as required? if(!B_CheckAxisPos(eb->state, eb->pos, I_TransformAxis(I_GetDevice(event->device, false), event->axis.id, event->axis.pos))) return 0; break; case E_ANGLE: if(eb->id != event->angle.id) return 0; if(eventClass && dev->hats[eb->id].assoc.bContext != eventClass) return 0; // Shadowed by a more important active class. // Is the position as required? if(event->angle.pos != eb->pos) return 0; break; case E_SYMBOLIC: if(strcmp(event->symbolic.name, eb->symbolicName)) return 0; break; default: return 0; } // Any conditions on the current state of the input devices? for(i = 0; i < eb->numConds; ++i) { if(!B_CheckCondition(&eb->conds[i], 0, NULL)) return 0; } // Substitute parameters in the command. Str_Init(&command); Str_Reserve(&command, strlen(eb->command)); B_SubstituteInCommand(eb->command, event, eb, &command); de::Action *act = new CommandAction(Str_Text(&command), CMDS_BIND); Str_Free(&command); return act; }