public static HousingWardInfo Read(byte[] message, UniversalisPluginControl plugin) { var output = new HousingWardInfo(); using (var stream = new MemoryStream(message)) { using (var reader = new BinaryReader(stream)) { output.LandId = reader.ReadInt16(); output.WardNumber = 1 + reader.ReadInt16(); output.TerritoryTypeId = reader.ReadInt16(); output.WorldId = reader.ReadInt16(); output.HouseListings = new List <HouseInfoEntry>(); for (var i = 0; i < 60; i++) { var listingEntry = new HouseInfoEntry(); listingEntry.HousePrice = reader.ReadUInt32(); listingEntry.fluff = reader.ReadUInt32(); listingEntry.EstateOwnerName = Encoding.UTF8.GetString(reader.ReadBytes(32)).TrimEnd(new[] { '\u0000' }); output.HouseListings.Add(listingEntry); if (listingEntry.EstateOwnerName.Length == 0) { plugin.Log($"House found in ward {output.WardNumber.ToString()}, House {(i + 1).ToString()} Price {listingEntry.HousePrice.ToString()}");; } } } } return(output); }
private void OnHousingWardInfo(IntPtr dataPtr) { HousingWardInfo wardInfo = HousingWardInfo.Read(dataPtr); PluginLog.LogDebug($"Got HousingWardInfo for ward: {wardInfo.LandIdent.WardNumber} territory: {wardInfo.LandIdent.TerritoryTypeId}"); // if the current wardinfo is for a different district than the last swept one, print the header\ // or if the last sweep was > 10m ago if (wardInfo.LandIdent.WorldId != lastSweptDistrictWorldId || wardInfo.LandIdent.TerritoryTypeId != lastSweptDistrictTerritoryTypeId || lastSweepTime < (DateTime.Now - TimeSpan.FromMinutes(10))) { // reset last sweep info to the current sweep lastSweptDistrictWorldId = wardInfo.LandIdent.WorldId; lastSweptDistrictTerritoryTypeId = wardInfo.LandIdent.TerritoryTypeId; lastSweptDistrictSeenWardNumbers.Clear(); lastSweepTime = DateTime.Now; var districtName = this.territories.GetRow((uint)wardInfo.LandIdent.TerritoryTypeId).PlaceName.Value.Name; var worldName = this.worlds.GetRow((uint)wardInfo.LandIdent.WorldId).Name; this.pi.Framework.Gui.Chat.Print($"Began sweep for {districtName} ({worldName})"); } // if we've seen this ward already, ignore it if (lastSweptDistrictSeenWardNumbers.Contains(wardInfo.LandIdent.WardNumber)) { PluginLog.LogDebug($"Skipped processing HousingWardInfo for ward: {wardInfo.LandIdent.WardNumber} because we have seen it already"); return; } // add the ward number to this sweep's seen numbers lastSweptDistrictSeenWardNumbers.Add(wardInfo.LandIdent.WardNumber); // if that's all the wards, give the user a cookie if (lastSweptDistrictSeenWardNumbers.Count == numWardsPerDistrict) { this.pi.Framework.Gui.Chat.Print($"Swept all {numWardsPerDistrict} wards. Thank you!"); } // iterate over houses to find open houses for (int i = 0; i < wardInfo.HouseInfoEntries.Length; i++) { HouseInfoEntry houseInfoEntry = wardInfo.HouseInfoEntries[i]; PluginLog.LogVerbose( $"Got {wardInfo.LandIdent.WardNumber + 1}-{i + 1}: owned by {houseInfoEntry.EstateOwnerName}, flags {houseInfoEntry.InfoFlags}, price {houseInfoEntry.HousePrice}"); if ((houseInfoEntry.InfoFlags & HousingFlags.PlotOwned) == 0) { this.OnFoundOpenHouse(wardInfo, houseInfoEntry, i); } } PluginLog.LogDebug($"Done processing HousingWardInfo for ward: {wardInfo.LandIdent.WardNumber}"); }
private void OnFoundOpenHouse(HousingWardInfo wardInfo, HouseInfoEntry houseInfoEntry, int plotNumber) { var place = this.territories.GetRow((uint)wardInfo.LandIdent.TerritoryTypeId).PlaceName.Value; var districtName = place.NameNoArticle.RawString.Length > 0 ? place.NameNoArticle : place.Name; // languages like German do not use NameNoArticle (#2) var worldName = this.worlds.GetRow((uint)wardInfo.LandIdent.WorldId).Name; // gross way of getting the landset from the territorytype but the game does not send the correct landsetid uint landSetIndex = (uint)wardInfo.LandIdent.TerritoryTypeId - 339; landSetIndex = landSetIndex > 3 ? 3 : landSetIndex; var houseSize = this.housingLandSets.GetRow(landSetIndex).PlotSize[plotNumber]; var districtNameNoSpaces = districtName.ToString().Replace(" ", ""); int wardNum = wardInfo.LandIdent.WardNumber + 1; int plotNum = plotNumber + 1; float housePriceMillions = houseInfoEntry.HousePrice / 1000000f; string houseSizeName = houseSize == 0 ? "Small" : houseSize == 1 ? "Medium" : "Large"; pi.CommandManager.ProcessCommand("/hsplotnotify " + wardNum.ToString()); string output; switch (configuration.OutputFormat) { case OutputFormat.Pings: output = $"@{houseSizeName}{districtNameNoSpaces} {wardNum}-{plotNum} ({housePriceMillions:F3}m)"; break; case OutputFormat.EnoBot: output = $"##forsale {districtNameNoSpaces} w{wardNum} p{plotNum}"; break; case OutputFormat.Custom: output = FormatCustomOutputString(this.configuration.OutputFormatString, districtName.ToString(), districtNameNoSpaces, worldName, wardNum.ToString(), plotNum.ToString(), houseInfoEntry.HousePrice.ToString(), housePriceMillions.ToString("F3"), houseSizeName); break; default: output = $"{districtName} {wardNum}-{plotNum} ({housePriceMillions:F3}m)"; break; } this.pi.Framework.Gui.Chat.Print(output); }