/** Check if all GRFs in the GRF config from a savegame can be loaded. * @param grfconfig GrfConfig to check * @return will return any of the following 3 values:<br> * <ul> * <li> GLC_ALL_GOOD: No problems occured, all GRF files were found and loaded * <li> GLC_COMPATIBLE: For one or more GRF's no exact match was found, but a * compatible GRF with the same grfid was found and used instead * <li> GLC_NOT_FOUND: For one or more GRF's no match was found at all * </ul> */ GRFListCompatibility IsGoodGRFConfigList(GRFConfig *grfconfig) { GRFListCompatibility res = GLC_ALL_GOOD; for (GRFConfig *c = grfconfig; c != NULL; c = c->next) { const GRFConfig *f = FindGRFConfig(c->ident.grfid, c->ident.md5sum); if (f == NULL) { char buf[256]; /* If we have not found the exactly matching GRF try to find one with the * same grfid, as it most likely is compatible */ f = FindGRFConfig(c->ident.grfid); if (f != NULL) { md5sumToString(buf, lastof(buf), c->ident.md5sum); DEBUG(grf, 1, "NewGRF %08X (%s) not found; checksum %s. Compatibility mode on", BSWAP32(c->ident.grfid), c->filename, buf); if (!HasBit(c->flags, GCF_COMPATIBLE)) { /* Preserve original_md5sum after it has been assigned */ SetBit(c->flags, GCF_COMPATIBLE); memcpy(c->original_md5sum, c->ident.md5sum, sizeof(c->original_md5sum)); } /* Non-found has precedence over compatibility load */ if (res != GLC_NOT_FOUND) res = GLC_COMPATIBLE; goto compatible_grf; } /* No compatible grf was found, mark it as disabled */ md5sumToString(buf, lastof(buf), c->ident.md5sum); DEBUG(grf, 0, "NewGRF %08X (%s) not found; checksum %s", BSWAP32(c->ident.grfid), c->filename, buf); c->status = GCS_NOT_FOUND; res = GLC_NOT_FOUND; } else { compatible_grf: DEBUG(grf, 1, "Loading GRF %08X from %s", BSWAP32(f->ident.grfid), f->filename); /* The filename could be the filename as in the savegame. As we need * to load the GRF here, we need the correct filename, so overwrite that * in any case and set the name and info when it is not set already. * When the GCF_COPY flag is set, it is certain that the filename is * already a local one, so there is no need to replace it. */ if (!HasBit(c->flags, GCF_COPY)) { free(c->filename); c->filename = strdup(f->filename); memcpy(c->ident.md5sum, f->ident.md5sum, sizeof(c->ident.md5sum)); if (c->name == NULL && f->name != NULL) c->name = strdup(f->name); if (c->info == NULL && f->info != NULL) c->info = strdup(f->info); c->error = NULL; } } } return res; }
DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_CHECK_NEWGRFS) { if (this->status != STATUS_JOIN) return NETWORK_RECV_STATUS_MALFORMED_PACKET; uint grf_count = p->Recv_uint8(); NetworkRecvStatus ret = NETWORK_RECV_STATUS_OKAY; /* Check all GRFs */ for (; grf_count > 0; grf_count--) { GRFIdentifier c; this->ReceiveGRFIdentifier(p, &c); /* Check whether we know this GRF */ const GRFConfig *f = FindGRFConfig(c.grfid, FGCM_EXACT, c.md5sum); if (f == NULL) { /* We do not know this GRF, bail out of initialization */ char buf[sizeof(c.md5sum) * 2 + 1]; md5sumToString(buf, lastof(buf), c.md5sum); DEBUG(grf, 0, "NewGRF %08X not found; checksum %s", BSWAP32(c.grfid), buf); ret = NETWORK_RECV_STATUS_NEWGRF_MISMATCH; } } if (ret == NETWORK_RECV_STATUS_OKAY) { /* Start receiving the map */ return SendNewGRFsOk(); } /* NewGRF mismatch, bail out */ _switch_mode_errorstr = STR_NETWORK_ERROR_NEWGRF_MISMATCH; return ret; }
/** * A client has requested the names of some NewGRFs. * * Replying this can be tricky as we have a limit of SEND_MTU bytes * in the reply packet and we can send up to 100 bytes per NewGRF * (GRF ID, MD5sum and NETWORK_GRF_NAME_LENGTH bytes for the name). * As SEND_MTU is _much_ less than 100 * NETWORK_MAX_GRF_COUNT, it * could be that a packet overflows. To stop this we only reply * with the first N NewGRFs so that if the first N + 1 NewGRFs * would be sent, the packet overflows. * in_reply and in_reply_count are used to keep a list of GRFs to * send in the reply. */ DEF_UDP_RECEIVE_COMMAND(Server, PACKET_UDP_CLIENT_GET_NEWGRFS) { uint8 num_grfs; uint i; const GRFConfig *in_reply[NETWORK_MAX_GRF_COUNT]; uint8 in_reply_count = 0; size_t packet_len = 0; DEBUG(net, 6, "[udp] newgrf data request from %s", client_addr->GetAddressAsString()); num_grfs = p->Recv_uint8 (); if (num_grfs > NETWORK_MAX_GRF_COUNT) return; for (i = 0; i < num_grfs; i++) { GRFConfig c; const GRFConfig *f; this->Recv_GRFIdentifier(p, &c); /* Find the matching GRF file */ f = FindGRFConfig(c.grfid, c.md5sum); if (f == NULL) continue; // The GRF is unknown to this server /* If the reply might exceed the size of the packet, only reply * the current list and do not send the other data. * The name could be an empty string, if so take the filename. */ packet_len += sizeof(c.grfid) + sizeof(c.md5sum) + min(strlen((f->name != NULL && !StrEmpty(f->name)) ? f->name : f->filename) + 1, (size_t)NETWORK_GRF_NAME_LENGTH); if (packet_len > SEND_MTU - 4) { // 4 is 3 byte header + grf count in reply break; } in_reply[in_reply_count] = f; in_reply_count++; } if (in_reply_count == 0) return; Packet packet(PACKET_UDP_SERVER_NEWGRFS); packet.Send_uint8(in_reply_count); for (i = 0; i < in_reply_count; i++) { char name[NETWORK_GRF_NAME_LENGTH]; /* The name could be an empty string, if so take the filename */ strecpy(name, (in_reply[i]->name != NULL && !StrEmpty(in_reply[i]->name)) ? in_reply[i]->name : in_reply[i]->filename, lastof(name)); this->Send_GRFIdentifier(&packet, in_reply[i]); packet.Send_string(name); } this->SendPacket(&packet, client_addr); }
void ClientNetworkUDPSocketHandler::HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config) { /* Find the matching GRF file */ const GRFConfig *f = FindGRFConfig(config->grfid, config->md5sum); if (f == NULL) { /* Don't know the GRF, so mark game incompatible and the (possibly) * already resolved name for this GRF (another server has sent the * name of the GRF already */ config->name = FindUnknownGRFName(config->grfid, config->md5sum, true); config->status = GCS_NOT_FOUND; } else { config->filename = f->filename; config->name = f->name; config->info = f->info; } SetBit(config->flags, GCF_COPY); }
/** * Search a textfile file next to this file in the content list. * @param type The type of the textfile to search for. * @return The filename for the textfile, \c NULL otherwise. */ const char *ContentInfo::GetTextfile(TextfileType type) const { if (this->state == INVALID) return NULL; const char *tmp; switch (this->type) { default: NOT_REACHED(); case CONTENT_TYPE_AI: tmp = AI::GetScannerInfo()->FindMainScript(this, true); break; case CONTENT_TYPE_AI_LIBRARY: tmp = AI::GetScannerLibrary()->FindMainScript(this, true); break; case CONTENT_TYPE_GAME: tmp = Game::GetScannerInfo()->FindMainScript(this, true); break; case CONTENT_TYPE_GAME_LIBRARY: tmp = Game::GetScannerLibrary()->FindMainScript(this, true); break; case CONTENT_TYPE_NEWGRF: { const GRFConfig *gc = FindGRFConfig(BSWAP32(this->unique_id), FGCM_EXACT, this->md5sum); tmp = gc != NULL ? gc->filename : NULL; break; } case CONTENT_TYPE_BASE_GRAPHICS: tmp = TryGetBaseSetFile(this, true, BaseGraphics::GetAvailableSets()); break; case CONTENT_TYPE_BASE_SOUNDS: tmp = TryGetBaseSetFile(this, true, BaseSounds::GetAvailableSets()); break; case CONTENT_TYPE_BASE_MUSIC: tmp = TryGetBaseSetFile(this, true, BaseMusic::GetAvailableSets()); break; case CONTENT_TYPE_SCENARIO: case CONTENT_TYPE_HEIGHTMAP: extern const char *FindScenario(const ContentInfo *ci, bool md5sum); tmp = FindScenario(this, true); break; } if (tmp == NULL) return NULL; return ::GetTextfile(type, GetContentInfoSubDir(this->type), tmp); }
/** * Rebuild the GRFConfig's of the servers in the game list as we did * a rescan and might have found new NewGRFs. */ void NetworkAfterNewGRFScan() { for (NetworkGameList *item = _network_game_list; item != NULL; item = item->next) { /* Reset compatability state */ item->info.compatible = item->info.version_compatible; for (GRFConfig *c = item->info.grfconfig; c != NULL; c = c->next) { assert(HasBit(c->flags, GCF_COPY)); const GRFConfig *f = FindGRFConfig(c->ident.grfid, FGCM_EXACT, c->ident.md5sum); if (f == NULL) { /* Don't know the GRF, so mark game incompatible and the (possibly) * already resolved name for this GRF (another server has sent the * name of the GRF already */ c->name->Release(); c->name = FindUnknownGRFName(c->ident.grfid, c->ident.md5sum, true); c->name->AddRef(); c->status = GCS_NOT_FOUND; /* If we miss a file, we're obviously incompatible */ item->info.compatible = false; } else { c->filename = f->filename; c->name->Release(); c->name = f->name; c->name->AddRef(); c->info->Release(); c->info = f->info; c->info->AddRef(); c->status = GCS_UNKNOWN; } } } InvalidateWindowClassesData(WC_NETWORK_WINDOW); }
/** * Check if all GRFs in the GRF config from a savegame can be loaded. * @param grfconfig GrfConfig to check * @return will return any of the following 3 values:<br> * <ul> * <li> GLC_ALL_GOOD: No problems occurred, all GRF files were found and loaded * <li> GLC_COMPATIBLE: For one or more GRF's no exact match was found, but a * compatible GRF with the same grfid was found and used instead * <li> GLC_NOT_FOUND: For one or more GRF's no match was found at all * </ul> */ GRFListCompatibility IsGoodGRFConfigList(GRFConfig *grfconfig) { GRFListCompatibility res = GLC_ALL_GOOD; for (GRFConfig *c = grfconfig; c != NULL; c = c->next) { const GRFConfig *f = FindGRFConfig(c->ident.grfid, FGCM_EXACT, c->ident.md5sum); if (f == NULL || HasBit(f->flags, GCF_INVALID)) { char buf[256]; /* If we have not found the exactly matching GRF try to find one with the * same grfid, as it most likely is compatible */ f = FindGRFConfig(c->ident.grfid, FGCM_COMPATIBLE, NULL, c->version); if (f != NULL) { md5sumToString(buf, lastof(buf), c->ident.md5sum); DEBUG(grf, 1, "NewGRF %08X (%s) not found; checksum %s. Compatibility mode on", BSWAP32(c->ident.grfid), c->filename, buf); if (!HasBit(c->flags, GCF_COMPATIBLE)) { /* Preserve original_md5sum after it has been assigned */ SetBit(c->flags, GCF_COMPATIBLE); memcpy(c->original_md5sum, c->ident.md5sum, sizeof(c->original_md5sum)); } /* Non-found has precedence over compatibility load */ if (res != GLC_NOT_FOUND) res = GLC_COMPATIBLE; goto compatible_grf; } /* No compatible grf was found, mark it as disabled */ md5sumToString(buf, lastof(buf), c->ident.md5sum); DEBUG(grf, 0, "NewGRF %08X (%s) not found; checksum %s", BSWAP32(c->ident.grfid), c->filename, buf); c->status = GCS_NOT_FOUND; res = GLC_NOT_FOUND; } else { compatible_grf: DEBUG(grf, 1, "Loading GRF %08X from %s", BSWAP32(f->ident.grfid), f->filename); /* The filename could be the filename as in the savegame. As we need * to load the GRF here, we need the correct filename, so overwrite that * in any case and set the name and info when it is not set already. * When the GCF_COPY flag is set, it is certain that the filename is * already a local one, so there is no need to replace it. */ if (!HasBit(c->flags, GCF_COPY)) { free(c->filename); c->filename = stredup(f->filename); memcpy(c->ident.md5sum, f->ident.md5sum, sizeof(c->ident.md5sum)); c->name->Release(); c->name = f->name; c->name->AddRef(); c->info->Release(); c->info = f->name; c->info->AddRef(); c->error = NULL; c->version = f->version; c->min_loadable_version = f->min_loadable_version; c->num_valid_params = f->num_valid_params; c->has_param_defaults = f->has_param_defaults; for (uint i = 0; i < f->param_info.Length(); i++) { if (f->param_info[i] == NULL) { *c->param_info.Append() = NULL; } else { *c->param_info.Append() = new GRFParameterInfo(*f->param_info[i]); } } } } } return res; }
virtual void OnInvalidateData(int data = 0) { switch (data) { default: NOT_REACHED(); case 0: /* Nothing important to do */ break; case 1: /* Search the list for items that are now found and mark them as such. */ for (GRFConfig *c = this->list; c != NULL; c = c->next) { if (c->status != GCS_NOT_FOUND) continue; const GRFConfig *f = FindGRFConfig(c->grfid, c->md5sum); if (f == NULL) continue; free(c->filename); free(c->name); free(c->info); c->filename = f->filename == NULL ? NULL : strdup(f->filename); c->name = f->name == NULL ? NULL : strdup(f->name); c->info = f->info == NULL ? NULL : strdup(f->info); c->status = GCS_UNKNOWN; } break; case 2: this->preset = -1; /* Fall through */ case 3: const GRFConfig *c; int i; for (c = this->list, i = 0; c != NULL; c = c->next, i++) {} this->vscroll.SetCapacityFromWidget(this, SNGRFS_FILE_LIST); this->GetWidget<NWidgetCore>(SNGRFS_FILE_LIST)->widget_data = (this->vscroll.GetCapacity() << MAT_ROW_START) + (1 << MAT_COL_START); this->vscroll.SetCount(i); break; } this->SetWidgetsDisabledState(!this->editable, SNGRFS_PRESET_LIST, SNGRFS_ADD, SNGRFS_APPLY_CHANGES, SNGRFS_TOGGLE_PALETTE, WIDGET_LIST_END ); bool disable_all = this->sel == NULL || !this->editable; this->SetWidgetsDisabledState(disable_all, SNGRFS_REMOVE, SNGRFS_MOVE_UP, SNGRFS_MOVE_DOWN, WIDGET_LIST_END ); this->SetWidgetDisabledState(SNGRFS_SET_PARAMETERS, !this->show_params || disable_all); this->SetWidgetDisabledState(SNGRFS_TOGGLE_PALETTE, disable_all); if (!disable_all) { /* All widgets are now enabled, so disable widgets we can't use */ if (this->sel == this->list) this->DisableWidget(SNGRFS_MOVE_UP); if (this->sel->next == NULL) this->DisableWidget(SNGRFS_MOVE_DOWN); if (this->sel->IsOpenTTDBaseGRF()) this->DisableWidget(SNGRFS_REMOVE); } this->SetWidgetDisabledState(SNGRFS_PRESET_DELETE, this->preset == -1); bool has_missing = false; bool has_compatible = false; for (const GRFConfig *c = this->list; !has_missing && c != NULL; c = c->next) { has_missing |= c->status == GCS_NOT_FOUND; has_compatible |= HasBit(c->flags, GCF_COMPATIBLE); } if (has_missing || has_compatible) { this->GetWidget<NWidgetCore>(SNGRFS_CONTENT_DOWNLOAD)->widget_data = STR_NEWGRF_SETTINGS_FIND_MISSING_CONTENT_BUTTON; this->GetWidget<NWidgetCore>(SNGRFS_CONTENT_DOWNLOAD)->tool_tip = STR_NEWGRF_SETTINGS_FIND_MISSING_CONTENT_TOOLTIP; } else { this->GetWidget<NWidgetCore>(SNGRFS_CONTENT_DOWNLOAD)->widget_data = STR_INTRO_ONLINE_CONTENT; this->GetWidget<NWidgetCore>(SNGRFS_CONTENT_DOWNLOAD)->tool_tip = STR_INTRO_TOOLTIP_ONLINE_CONTENT; } this->SetWidgetDisabledState(SNGRFS_PRESET_SAVE, has_missing); }
/** Wrapper function for the HasProc */ static bool HasGRFConfig(const ContentInfo *ci, bool md5sum) { return FindGRFConfig(BSWAP32(ci->unique_id), md5sum ? ci->md5sum : NULL) != NULL; }