예제 #1
0
        /// <summary>
        /// Process a zone proto message and scan for relevant data.
        /// </summary>
        /// <param name="message">The message bytes.</param>
        /// <returns>True if an upload succeeded.</returns>
        private MarketBoardItemRequest GetRequestData(MatchaOpcode opcode, byte[] message)
        {
            if (opcode == MatchaOpcode.PlayerSetup)
            {
                LocalContentId = BitConverter.ToUInt64(message, 0x20);
                LocalContentId = LocalContentId & 0xffffffff00000000 | (uint)Config.Instance.UUIDHash; // mask the lower 32 bit for privacy concern
                Log?.Invoke(this, $"New CID: {LocalContentId.ToString("X")}");
                LocalContentIdUpdated?.Invoke(this, LocalContentId);
                return(null);
            }

            if (opcode == MatchaOpcode.MarketBoardItemListingCount)
            {
                var catalogId = (uint)BitConverter.ToInt32(message, 0x20);
                var amount    = message[0x2B];

                var request = _marketBoardRequests.LastOrDefault(r => r.CatalogId == catalogId);
                if (request == null)
                {
                    _marketBoardRequests.Add(new MarketBoardItemRequest
                    {
                        CatalogId      = catalogId,
                        AmountToArrive = amount,
                        Listings       = new List <MarketBoardCurrentOfferings.MarketBoardItemListing>(),
                        History        = new List <MarketBoardHistory.MarketBoardHistoryListing>()
                    });
                }
                else
                {
                    request.AmountToArrive = amount;
                    request.Listings.Clear();
                }

                Log?.Invoke(this, $"NEW MB REQUEST START: item#{catalogId} amount#{amount}");
                return(null);
            }

            if (opcode == MatchaOpcode.MarketBoardItemListing)
            {
                var listing = MarketBoardCurrentOfferings.Read(message.Skip(0x20).ToArray());

                var request =
                    _marketBoardRequests.LastOrDefault(
                        r => r.CatalogId == listing.ItemListings[0].CatalogId && !r.IsDone);

                if (request == null)
                {
                    Log?.Invoke(this,
                                $"[ERROR] Market Board data arrived without a corresponding request: item#{listing.ItemListings[0].CatalogId}");
                    return(null);
                }

                if (request.Listings.Count + listing.ItemListings.Count > request.AmountToArrive)
                {
                    Log?.Invoke(this,
                                $"[ERROR] Too many Market Board listings received for request: {request.Listings.Count + listing.ItemListings.Count} > {request.AmountToArrive} item#{listing.ItemListings[0].CatalogId}");
                    _marketBoardRequests.Remove(request);
                    return(null);
                }

                if (request.ListingsRequestId != -1 && request.ListingsRequestId != listing.RequestId)
                {
                    Log?.Invoke(this,
                                $"[ERROR] Non-matching RequestIds for Market Board data request: {request.ListingsRequestId}, {listing.RequestId}");
                    _marketBoardRequests.Remove(request);
                    return(null);
                }

                if (request.ListingsRequestId == -1 && request.Listings.Count > 0)
                {
                    Log?.Invoke(this,
                                $"[ERROR] Market Board data request sequence break: {request.ListingsRequestId}, {request.Listings.Count}");
                    _marketBoardRequests.Remove(request);
                    return(null);
                }

                if (request.ListingsRequestId == -1)
                {
                    request.ListingsRequestId = listing.RequestId;
                    Log?.Invoke(this, $"First Market Board packet in sequence: {listing.RequestId}");
                }

                request.Listings.AddRange(listing.ItemListings);

                Log?.Invoke(this,
                            $"Added {listing.ItemListings.Count} ItemListings to request#{request.ListingsRequestId}, now {request.Listings.Count}/{request.AmountToArrive}, item#{request.CatalogId}");

                if (request.IsDone)
                {
                    if (CurrentWorldId == 0)
                    {
                        Log?.Invoke(this, "[ERROR] Not sure about your current world. Please move your character between zones once to start uploading.");
                        _marketBoardRequests.Remove(request);
                        return(null);
                    }

                    RequestContentIdUpdate?.Invoke(this, null);

                    if (LocalContentId == 0)
                    {
                        Log?.Invoke(this, "Not sure about your character information. Please log in once with your character while having the program open to verify it.");
                    }

                    LocalContentIdUpdated?.Invoke(this, LocalContentId);

                    Log?.Invoke(this,
                                $"Market Board request finished, starting upload: request#{request.ListingsRequestId} item#{request.CatalogId} amount#{request.AmountToArrive}");
                    return(request);
                }

                return(null);
            }

            if (opcode == MatchaOpcode.MarketBoardItemListingHistory)
            {
                var listing = MarketBoardHistory.Read(message.Skip(0x20).ToArray());

                var request = _marketBoardRequests.LastOrDefault(r => r.CatalogId == listing.CatalogId);

                if (request == null)
                {
                    request = new MarketBoardItemRequest
                    {
                        CatalogId      = listing.CatalogId,
                        AmountToArrive = 0,
                        Listings       = new List <MarketBoardCurrentOfferings.MarketBoardItemListing>(),
                        History        = new List <MarketBoardHistory.MarketBoardHistoryListing>()
                    };
                    _marketBoardRequests.Add(request);
                }

                request.History.AddRange(listing.HistoryListings);

                if (request.IsDone)
                {
                    if (CurrentWorldId == 0)
                    {
                        Log?.Invoke(this, "[ERROR] Not sure about your current world. Please move your character between zones once to start uploading.");
                        _marketBoardRequests.Remove(request);
                        return(null);
                    }

                    RequestContentIdUpdate?.Invoke(this, null);

                    if (LocalContentId == 0)
                    {
                        Log?.Invoke(this, "Not sure about your character information. Please log in once with your character while having the program open to verify it.");
                    }

                    LocalContentIdUpdated?.Invoke(this, LocalContentId);

                    Log?.Invoke(this,
                                $"Market Board request finished, starting upload: request#{request.ListingsRequestId} item#{request.CatalogId} amount#{request.AmountToArrive}");
                    return(request);
                }

                Log?.Invoke(this, $"Added history for item#{listing.CatalogId}");
                return(null);
            }

            return(null);
        }
예제 #2
0
파일: Api.cs 프로젝트: yimo0908/matcha
        public async void Upload(ushort worldId, MarketBoardItemRequest request)
        {
            using (var client = new WebClient())
            {
                _packetProcessor.Log?.Invoke(this, "Starting Universalis upload.");
                var uploader = _packetProcessor.LocalContentId;

                var listingsRequestObject = new UniversalisItemListingsUploadRequest();
                listingsRequestObject.WorldId    = worldId;
                listingsRequestObject.UploaderId = uploader;
                listingsRequestObject.ItemId     = request.CatalogId;

                listingsRequestObject.Listings = new List <UniversalisItemListingsEntry>();
                foreach (var marketBoardItemListing in request.Listings)
                {
                    var universalisListing = new UniversalisItemListingsEntry
                    {
                        Hq             = marketBoardItemListing.IsHq,
                        SellerId       = marketBoardItemListing.RetainerOwnerId,
                        RetainerName   = marketBoardItemListing.RetainerName,
                        RetainerId     = marketBoardItemListing.RetainerId,
                        CreatorId      = marketBoardItemListing.ArtisanId,
                        CreatorName    = marketBoardItemListing.PlayerName,
                        OnMannequin    = marketBoardItemListing.OnMannequin,
                        LastReviewTime = ((DateTimeOffset)marketBoardItemListing.LastReviewTime).ToUnixTimeSeconds(),
                        PricePerUnit   = marketBoardItemListing.PricePerUnit,
                        Quantity       = marketBoardItemListing.ItemQuantity,
                        RetainerCity   = marketBoardItemListing.RetainerCityId
                    };

                    universalisListing.Materia = new List <UniversalisItemMateria>();
                    foreach (var itemMateria in marketBoardItemListing.Materia)
                    {
                        universalisListing.Materia.Add(new UniversalisItemMateria
                        {
                            MateriaId = itemMateria.MateriaId,
                            SlotId    = itemMateria.Index
                        });
                    }

                    listingsRequestObject.Listings.Add(universalisListing);
                }

                await Request.SendAsJson($"{ApiBase}/upload/{_apiKey}", "", listingsRequestObject);

                var historyRequestObject = new UniversalisHistoryUploadRequest();
                historyRequestObject.WorldId    = worldId;
                historyRequestObject.UploaderId = uploader;
                historyRequestObject.ItemId     = request.CatalogId;

                historyRequestObject.Entries = new List <UniversalisHistoryEntry>();
                foreach (var marketBoardHistoryListing in request.History)
                {
                    historyRequestObject.Entries.Add(new UniversalisHistoryEntry
                    {
                        BuyerName    = marketBoardHistoryListing.BuyerName,
                        Hq           = marketBoardHistoryListing.IsHq,
                        OnMannequin  = marketBoardHistoryListing.OnMannequin,
                        PricePerUnit = marketBoardHistoryListing.SalePrice,
                        Quantity     = marketBoardHistoryListing.Quantity,
                        Timestamp    = ((DateTimeOffset)marketBoardHistoryListing.PurchaseTime).ToUnixTimeSeconds()
                    });
                }

                await Request.SendAsJson($"{ApiBase}/upload/{_apiKey}", "", historyRequestObject);

                _packetProcessor.Log?.Invoke(this,
                                             $"Universalis data upload for item#{request.CatalogId} to world#{historyRequestObject.WorldId} completed.");
            }
        }