Black market tabs: Buy / Sell / Orders; Ponero swap moved into the Web3 trade page

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ZHU MINCHAOandClaude Sonnet 5.5 committed 2026-11-03 22:04:31 +08:00
1 parent 776f66fd2c
commit 5b7013f240
4 files changed
+121 -102

No files matched your search

+103 -91
View File
@@ -271,11 +271,12 @@ namespace Decentralized
r.AddHeader(L.T("trade.h"));
AmountRow(r);
TradeRows(r, Venue.Dex);
if (Unlock.BlackUnlocked && BlackMarket.DeskOpen(StoreReputation.GetBMReputation())) PoneroBlock(r);
});
}
private enum BlackTab { Shop, Orders, Sell, Mine, Desk }
private static BlackTab _blackTab = BlackTab.Shop;
private enum BlackTab { Buy, Sell, Orders }
private static BlackTab _blackTab = BlackTab.Buy;
private static PayMode _mode = PayMode.Escrow;
private static string _deskAsset = Assets.PSC;
private static bool _deskIn = true;
@@ -306,11 +307,9 @@ namespace Decentralized
var d = Session.Data;
if (Night.ActiveEvents().Contains(MarketEvent.Crackdown)) { b.AddLabel(L.T("black.offline")); return; }
if (!BlackMarket.Open(rep)) { b.AddLabel(L.T("black.closed", Tuning.BmOpenRep, rep)); return; }
bool desk = BlackMarket.DeskOpen(rep);
b.BeginRow();
foreach (BlackTab t in Enum.GetValues(typeof(BlackTab)))
{
if (t == BlackTab.Desk && !desk) continue;
var tab = t;
string name = L.T("black.sub." + t.ToString().ToLowerInvariant());
b.AddButton(tab == _blackTab ? $"[{name}]" : name, () => { _blackTab = tab; _message = null; _pay = null; _edit = null; Open(); });
@@ -318,11 +317,18 @@ namespace Decentralized
b.End();
if (d.Black.Closed(day)) { b.AddLabel(L.T("black.rugged", d.Black.ClosedUntil - day + 1)); return; }
if (_edit != null) { EditPage(b); return; }
if (_blackTab == BlackTab.Desk && desk) { DeskPage(b, rep, day); return; }
if (_blackTab == BlackTab.Mine) { MinePage(b, day); return; }
if (_blackTab == BlackTab.Orders) { OrdersPage(b, day); return; }
if (_blackTab == BlackTab.Sell) { SellPage(b, day); return; }
bool orders = _blackTab == BlackTab.Orders;
BuyPage(b, d, rep);
}
/// <summary>买货:选一家卖家(第一个是平台现货,立即到货但贵,其余是商家,便宜但要等),选件数,下单。论坛情报在最下面。</summary>
private static void BuyPage(CustomUIBuilder b, SaveData d, int rep)
{
var w = d.Hot;
var sellers = d.Black.Sellers;
if (_merchant >= sellers.Count) _merchant = -1;
bool platform = _merchant < 0;
b.AddLabel(L.T("black.rep", rep, BlackMarket.MaxLevel(rep)) + " " + L.T("mixer.balance", _payAsset, Fmt.Num(w.Avail(_payAsset))) + (w.Taint > 0.5 ? " " + L.T("wallet.taint", Fmt.Credits(w.Taint)) : ""));
b.BeginRow();
foreach (var a in new[] { Assets.PSC, Assets.CRT, Assets.CRA, Assets.Ponero })
@@ -330,7 +336,7 @@ namespace Decentralized
var asset = a;
b.AddButton(asset == _payAsset ? $"[{asset}]" : asset, () => { _payAsset = asset; Open(); });
}
if (orders)
if (!platform)
foreach (PayMode m in Enum.GetValues(typeof(PayMode)))
{
var mode = m;
@@ -338,20 +344,48 @@ namespace Decentralized
b.AddButton(mode == _mode ? $"[{n}]" : n, () => { _mode = mode; Open(); });
}
b.End();
b.AddSeparator();
if (!orders)
b.BeginRow();
foreach (var m in Qtys)
{
if (d.Black.Offers.Count == 0) b.AddLabel(L.T("black.empty"));
Shelf(b, d.Black.Offers.Cast<BmGood>().ToList(), (c, g) =>
{
var offer = (BmOffer)g;
GoodHead(c, g, L.T("black.stock", offer.Qty));
c.AddLabel(L.T("black.price", offer.Price));
c.AddFlexibleSpace();
c.AddButton(L.T("black.buy"), () => BeginPay(d.Address("platform"), ItemName(offer.Item), offer.Price, () => BuyOffer(offer)));
});
int q = m;
b.AddButton(q == _qty ? $"[×{q}]" : "×" + q, () => { _qty = q; Open(); });
}
b.End();
var all = new System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<int, string>> { new System.Collections.Generic.KeyValuePair<int, string>(-1, "[" + L.T("merchant.Platform") + "] " + d.Address("platform")) };
for (int k = 0; k < sellers.Count; k++) all.Add(new System.Collections.Generic.KeyValuePair<int, string>(k, MerchantLabel(sellers[k])));
for (int i = 0; i < all.Count; i += 3)
{
b.BeginRow();
for (int k = i; k < Math.Min(all.Count, i + 3); k++)
{
int idx = all[k].Key; string n = all[k].Value;
b.AddButton(idx == _merchant ? "> " + n : n, () => { _merchant = idx; Open(); });
}
b.End();
}
b.AddSeparator();
if (platform) PlatformShelf(b, d);
else MerchantShelf(b, d);
b.AddSeparator();
b.AddHeader(L.T("black.forum.h"));
if (d.Black.Forum.Count == 0) b.AddLabel(L.T("black.forum.quiet"));
foreach (var f in d.Black.Forum)
b.AddLabel(f.StartsWith("scam:") ? L.T("black.forum.scam", BlackDelivery.DisplayName(f.Substring(5))) : f.StartsWith("busted:") ? L.T("black.forum.busted", f.Substring(7)) : L.T("black.forum." + f));
}
private static void PlatformShelf(CustomUIBuilder b, SaveData d)
{
b.AddLabel(L.T("black.platform.line", d.Address("platform")));
if (d.Black.Offers.Count == 0) { b.AddLabel(L.T("black.empty")); return; }
Shelf(b, d.Black.Offers.Cast<BmGood>().ToList(), (c, g) =>
{
var offer = (BmOffer)g;
int count = Math.Min(_qty, offer.Qty);
GoodHead(c, g, L.T("black.stock", offer.Qty));
c.AddLabel(L.T("black.price", offer.Price * count) + (count > 1 ? " ×" + count : ""));
c.AddFlexibleSpace();
c.AddButton(L.T("black.buy"), () => BeginPay(d.Address("platform"), ItemName(offer.Item) + (count > 1 ? " ×" + count : ""), offer.Price * count, () => BuyOffer(offer, count)));
});
}
private static double _sellMult = 1.0;
@@ -429,7 +463,7 @@ namespace Decentralized
private static string MerchantLabel(BmSeller s) => "[" + L.T("merchant." + s.Type) + "] " + s.Name;
private static int _merchant;
private static int _merchant = -1;
private static int _qty = 1;
private static readonly int[] Qtys = { 1, 5, 10 };
@@ -437,26 +471,6 @@ namespace Decentralized
private static void MerchantShelf(CustomUIBuilder b, SaveData d)
{
var sellers = d.Black.Sellers;
if (sellers.Count == 0) { b.AddLabel(L.T("black.empty")); return; }
if (_merchant >= sellers.Count) _merchant = 0;
b.BeginRow();
foreach (var m in Qtys)
{
int q = m;
b.AddButton(q == _qty ? $"[×{q}]" : "×" + q, () => { _qty = q; Open(); });
}
b.End();
for (int i = 0; i < sellers.Count; i += 3)
{
b.BeginRow();
for (int k = i; k < Math.Min(sellers.Count, i + 3); k++)
{
int idx = k;
string n = MerchantLabel(sellers[k]);
b.AddButton(idx == _merchant ? "> " + n : n, () => { _merchant = idx; Open(); });
}
b.End();
}
var seller = sellers[_merchant];
b.AddLabel(L.T("black.seller", MerchantLabel(seller), seller.Trades, seller.Rating) + " " + L.T("black.days", seller.Days));
var goods = d.Black.Catalog.Where(l => l.Seller == _merchant).Cast<BmGood>().ToList();
@@ -533,14 +547,20 @@ namespace Decentralized
b.End();
}
private static void BuyOffer(BmOffer o)
private static void BuyOffer(BmOffer o, int count)
{
var d = Session.Data;
string item = o.Item, model = o.Model, fake = o.FakeOf;
double health = o.Health;
if (!d.Black.Buy(o, d.Hot, _payAsset, Session.Price)) { _message = L.T("msg.balance"); Open(); return; }
Items.Give(BlackDelivery.Make(item, model, fake, health));
_message = L.T("black.bought", ItemName(item));
int bought = 0;
for (int i = 0; i < count; i++)
{
if (!d.Black.Buy(o, d.Hot, _payAsset, Session.Price)) break;
Items.Give(BlackDelivery.Make(item, model, fake, health));
bought++;
}
if (bought == 0) { _message = L.T("msg.balance"); Open(); return; }
_message = L.T("black.bought", ItemName(item) + (bought > 1 ? " ×" + bought : ""));
Session.Save();
Open();
}
@@ -619,65 +639,57 @@ namespace Decentralized
}
/// <summary>我的订单与论坛情报。</summary>
private static void MinePage(CustomUIBuilder b, int day)
private static void OrdersPage(CustomUIBuilder b, int day)
{
var d = Session.Data;
Columns(b, l =>
b.AddHeader(L.T("black.orders.in"));
if (d.Black.Orders.Count == 0) b.AddLabel(L.T("black.mine.none"));
foreach (var o in d.Black.Orders.OrderByDescending(x => x.PlacedDay))
b.AddLabel(L.T("black.mine.line", ItemName(o.Item) + (o.Count > 1 ? " ×" + o.Count : ""), BlackDelivery.DisplayName(o.Seller), L.T("black.mode." + o.Mode), L.T("black.state." + o.State + (o.Why != null && o.State != OrderState.Done ? "." + o.Why : "")), o.DueDay));
b.AddSeparator();
b.AddHeader(L.T("black.orders.out"));
if (d.Black.Sales.Count == 0) b.AddLabel(L.T("black.mine.none"));
foreach (var sl in d.Black.Sales.Where(x => x.State != SaleState.Delisted || x.Why == "fake").OrderByDescending(x => x.ListedDay))
{
l.AddHeader(L.T("black.mine.h"));
if (d.Black.Orders.Count == 0 && d.Black.Sales.Count == 0) l.AddLabel(L.T("black.mine.none"));
foreach (var sl in d.Black.Sales.Where(x => x.State != SaleState.Delisted || x.Why == "fake").OrderByDescending(x => x.ListedDay))
var sale = sl;
string st = sale.State == SaleState.Sold ? L.T("black.sale.Sold", sale.PayDay) : L.T("black.sale." + sale.State + (sale.State == SaleState.Delisted && sale.Why != null ? "." + sale.Why : ""));
b.AddLabel(L.T("black.mine.sale", ItemName(sale.Item), sale.Ref, sale.ListPrice, sale.Mult.ToString("0.00", CultureInfo.InvariantCulture), st));
if (sale.State == SaleState.Listed)
{
var sale = sl;
string st = sale.State == SaleState.Sold ? L.T("black.sale.Sold", sale.PayDay) : L.T("black.sale." + sale.State + (sale.State == SaleState.Delisted && sale.Why != null ? "." + sale.Why : ""));
l.AddLabel(L.T("black.mine.sale", ItemName(sale.Item), sale.Ref, sale.ListPrice, sale.Mult.ToString("0.00", CultureInfo.InvariantCulture), st));
if (sale.State == SaleState.Listed)
{
l.BeginRow();
l.AddButton(L.T("black.sell.reprice"), () => BeginEdit(new EditPrice { Sale = sale, Id = sale.Item, Ref = sale.Ref }, sale.ListPrice));
l.AddButton(L.T("black.sell.delist"), () => Delist(sale));
l.End();
}
b.BeginRow();
b.AddButton(L.T("black.sell.reprice"), () => BeginEdit(new EditPrice { Sale = sale, Id = sale.Item, Ref = sale.Ref }, sale.ListPrice));
b.AddButton(L.T("black.sell.delist"), () => Delist(sale));
b.End();
}
foreach (var o in d.Black.Orders.OrderByDescending(x => x.PlacedDay))
l.AddLabel(L.T("black.mine.line", ItemName(o.Item) + (o.Count > 1 ? " ×" + o.Count : ""), BlackDelivery.DisplayName(o.Seller), L.T("black.mode." + o.Mode), L.T("black.state." + o.State + (o.Why != null && o.State != OrderState.Done ? "." + o.Why : "")), o.DueDay));
}, r =>
{
r.AddHeader(L.T("black.forum.h"));
if (d.Black.Forum.Count == 0) r.AddLabel(L.T("black.forum.quiet"));
foreach (var f in d.Black.Forum)
r.AddLabel(f.StartsWith("scam:") ? L.T("black.forum.scam", BlackDelivery.DisplayName(f.Substring(5))) : f.StartsWith("busted:") ? L.T("black.forum.busted", f.Substring(7)) : L.T("black.forum." + f));
});
}
}
private static void DeskPage(CustomUIBuilder b, int rep, int day)
/// <summary>匿名币兑换:Web3 交易页里的一个通用兑换块,带"匿名币"标签。要黑市声望,有每日额度;兑入时这部分价值的污点被清除。</summary>
private static void PoneroBlock(CustomUIBuilder r)
{
var d = Session.Data;
var w = d.Hot;
Columns(b, l =>
int day = StoreStation.GetDayCounter();
r.AddSeparator();
r.AddLabel(L.T("black.desk.pair", Fmt.Num(Session.Price(Assets.Ponero))));
r.AddLabel(L.T("black.desk.left", Fmt.Credits(d.Black.DeskLeft(day)), Fmt.Credits(Tuning.PoneroDailyCap)));
r.BeginRow();
foreach (var a in new[] { Assets.PSC, Assets.CRT, Assets.CRA })
{
l.AddHeader(L.T("black.desk.h"));
l.AddLabel(L.T("black.desk.left", Fmt.Credits(d.Black.DeskLeft(day)), Fmt.Credits(Tuning.PoneroDailyCap)));
l.AddLabel(L.T("black.desk.price", Fmt.Num(Session.Price(Assets.Ponero))));
Holdings(l, w, a => a == Assets.Ponero || a == _deskAsset);
}, r =>
var asset = a;
r.AddButton(asset == _deskAsset ? $"[{asset}]" : asset, () => { _deskAsset = asset; Open(); });
}
r.End();
r.BeginRow();
r.AddButton(L.T("black.desk.in"), () => { _deskIn = true; Swap(); });
r.AddButton(L.T("black.desk.out"), () => { _deskIn = false; Swap(); });
r.End();
void Swap()
{
r.AddHeader(L.T("black.desk.swap"));
r.BeginRow();
r.AddButton(_deskIn ? $"[{L.T("black.desk.in")}]" : L.T("black.desk.in"), () => { _deskIn = true; Open(); });
r.AddButton(_deskIn ? L.T("black.desk.out") : $"[{L.T("black.desk.out")}]", () => { _deskIn = false; Open(); });
r.End();
r.BeginRow();
foreach (var a in new[] { Assets.PSC, Assets.CRT, Assets.CRA })
{
var asset = a;
r.AddButton(asset == _deskAsset ? $"[{asset}]" : asset, () => { _deskAsset = asset; Open(); });
}
r.End();
r.AddLabel(_deskIn ? L.T("mixer.balance", _deskAsset, Fmt.Num(w.Avail(_deskAsset))) : L.T("mixer.balance", Assets.Ponero, Fmt.Num(w.Avail(Assets.Ponero))));
AmountRow(r);
r.AddButton(L.T("black.desk.go"), () => { if (!ReadAmount(out double dv)) return; BeginPay(d.Address("desk"), L.T("pay.swap", Fmt.Num(dv), _deskIn ? _deskAsset : Assets.Ponero), (int)Math.Round(dv * Session.Price(_deskIn ? _deskAsset : Assets.Ponero)), DeskSwap); });
});
if (!ReadAmount(out double dv)) return;
string asset = _deskIn ? _deskAsset : Assets.Ponero;
BeginPay(d.Address("desk"), L.T("pay.swap", Fmt.Num(dv), asset), (int)Math.Round(dv * Session.Price(asset)), DeskSwap);
}
}
private static void DeskSwap()