Black market in Web3 page, shelf UI, no dead drop, tech and GPU goods; rules moved to Web3 handbook
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
6bc479f710
commit
e44a4439ed
12 files changed
+296
-245
No files matched your search
@@ -5,20 +5,18 @@ namespace Decentralized
|
||||
{
|
||||
/// <summary>
|
||||
/// Web3 黑市的货物进出:每周刷新现货与订单目录,夜间推进订单并写夜间日志,
|
||||
/// 上门(快递员当顾客上门)和死投(去垃圾场取货)把到货交给玩家。
|
||||
/// 上门(快递员当顾客上门)把到货交给玩家。
|
||||
/// </summary>
|
||||
public static class BlackDelivery
|
||||
{
|
||||
public static void Subscribe()
|
||||
{
|
||||
ModHook.OnGenerateCustomerNormal += OnGenerate;
|
||||
ModHook.OnAfterhourArriveLate += OnArrive;
|
||||
}
|
||||
|
||||
public static void Unsubscribe()
|
||||
{
|
||||
ModHook.OnGenerateCustomerNormal -= OnGenerate;
|
||||
ModHook.OnAfterhourArriveLate -= OnArrive;
|
||||
}
|
||||
|
||||
public static long Value(string id)
|
||||
@@ -30,9 +28,19 @@ namespace Decentralized
|
||||
return v;
|
||||
}
|
||||
|
||||
/// <summary>货架上的货对应的游戏物品 id:显卡是 "gpu:型号",对应本 mod 的显卡物品。</summary>
|
||||
public static string GameId(string id) => id.StartsWith("gpu:") ? Items.GpuId(id.Substring(4)) : id;
|
||||
|
||||
/// <summary>造出这件货:显卡按成色与(可能的)假卡真身造,不带卖家的说法;其余直接造。</summary>
|
||||
public static GameItem Make(string id, string model, string fakeOf, double health)
|
||||
{
|
||||
if (id.StartsWith("gpu:")) return Items.NewCard(model, health, fakeOf, Session.Data.Rng);
|
||||
return ModHelper.SpawnItem(id);
|
||||
}
|
||||
|
||||
public static string ItemName(string id)
|
||||
{
|
||||
var it = ModHelper.SpawnItem(id);
|
||||
var it = ModHelper.SpawnItem(GameId(id));
|
||||
if (it == null) return id;
|
||||
string n = it.name;
|
||||
it.Destroy();
|
||||
@@ -46,7 +54,7 @@ namespace Decentralized
|
||||
if (d.Black.Closed(day)) return false;
|
||||
if (force) d.Black.RefreshedDay = -999;
|
||||
if (!d.Black.Refresh(day, rep, d.Rng, Value)) return false;
|
||||
d.Black.RefreshOrders(rep, d.Rng, Value);
|
||||
d.Black.RefreshOrders(day, rep, d.Rng, Value);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -56,14 +64,13 @@ namespace Decentralized
|
||||
foreach (var e in d.Black.Night(day, crackdown, d.Hot, d.Rng))
|
||||
{
|
||||
string name = e.Order != null ? ItemName(e.Order.Item) : null;
|
||||
Log.Info($"黑市订单事件:{e.Kind} {e.Order?.Item} {e.Order?.Seller} {e.Order?.Mode}/{e.Order?.Delivery} 金额 {e.Amount:0}");
|
||||
Log.Info($"黑市订单事件:{e.Kind} {e.Order?.Item} {e.Order?.Seller} {e.Order?.Mode} 金额 {e.Amount:0}");
|
||||
switch (e.Kind)
|
||||
{
|
||||
case "ready": ps.AddNightLog(L.T("nightlog.bm.ready." + e.Order.Delivery, name), "99bb66"); break;
|
||||
case "ready": ps.AddNightLog(L.T("nightlog.bm.ready", name), "99bb66"); break;
|
||||
case "scam_refund": ps.AddNightLog(L.T("nightlog.bm.scam_refund", e.Order.Seller, name), "cc7755"); break;
|
||||
case "scam_loss": ps.AddNightLog(L.T("nightlog.bm.scam_loss", e.Order.Seller, name, Fmt.Num(e.Amount)), "cc7755"); break;
|
||||
case "intercept": ps.AddNightLog(L.T("nightlog.bm.intercept", name, Fmt.Num(e.Amount)), "cc7755"); break;
|
||||
case "theft": ps.AddNightLog(L.T("nightlog.bm.theft", name, Fmt.Num(e.Amount)), "cc7755"); break;
|
||||
case "rug": ps.AddNightLog(L.T("nightlog.bm.rug", name, Fmt.Num(e.Amount)), "cc7755"); break;
|
||||
case "reopen": ps.AddNightLog(L.T("nightlog.bm.reopen"), "99bb66"); break;
|
||||
}
|
||||
@@ -83,7 +90,7 @@ namespace Decentralized
|
||||
Log.Guard("黑市快递员", () =>
|
||||
{
|
||||
int day = StoreStation.GetDayCounter();
|
||||
if (day == courierDay || !Session.Data.Black.ReadyFor(Delivery.Door).Any()) return;
|
||||
if (day == courierDay || !Session.Data.Black.Ready.Any()) return;
|
||||
courierDay = day;
|
||||
manager.AddClient(CreateCourier());
|
||||
});
|
||||
@@ -110,33 +117,13 @@ namespace Decentralized
|
||||
private static void DeliverDoor()
|
||||
{
|
||||
var d = Session.Data;
|
||||
foreach (var o in d.Black.ReadyFor(Delivery.Door).ToList())
|
||||
foreach (var o in d.Black.Ready.ToList())
|
||||
{
|
||||
Items.Give(ModHelper.SpawnItem(o.Item));
|
||||
Items.Give(Make(o.Item, o.Model, o.FakeOf, o.Health));
|
||||
d.Black.Deliver(o);
|
||||
Log.Info($"黑市快递:{o.Item} 已放进储藏区");
|
||||
Log.Info($"黑市快递:{o.Item}{(o.FakeOf != null ? "(假卡,真身 " + o.FakeOf + ")" : "")} 已放进储藏区");
|
||||
}
|
||||
Session.Save();
|
||||
}
|
||||
|
||||
// ---- 死投:晚上去垃圾场,货在那里 ----
|
||||
private static void OnArrive(string locationId)
|
||||
{
|
||||
if (locationId != "dumping_ground" || Session.Data == null || !Unlock.BlackUnlocked) return;
|
||||
Log.Guard("黑市死投", () =>
|
||||
{
|
||||
var d = Session.Data;
|
||||
var list = d.Black.ReadyFor(Delivery.Drop).ToList();
|
||||
foreach (var o in list)
|
||||
{
|
||||
var item = ModHelper.SpawnItem(o.Item);
|
||||
GeneralHelper.SetItemOwned(item, true);
|
||||
GraphUtils.EmporiumTryAdd(EmporiumEntry.Instance.afterhourInventory, item);
|
||||
d.Black.Deliver(o);
|
||||
Log.Info($"黑市死投:{o.Item} 已放进外出背包");
|
||||
}
|
||||
if (list.Count > 0) { Session.Save(); }
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ namespace Decentralized
|
||||
public const string Terminal = "pd_terminal";
|
||||
public const string Rig = "pd_rig";
|
||||
public const string Guide = "pd_gpu_guide";
|
||||
public const string Web3Guide = "pd_web3_guide";
|
||||
public const string GpuPrefix = "pd_gpu_";
|
||||
|
||||
public const string HealthTag = "PD_HEALTH";
|
||||
@@ -38,6 +39,7 @@ namespace Decentralized
|
||||
dir.Add(Terminal, CreateTerminal);
|
||||
dir.Add(Rig, CreateRig);
|
||||
dir.Add(Guide, CreateGuide);
|
||||
dir.Add(Web3Guide, CreateWeb3Guide);
|
||||
foreach (var spec in Hardware.Specs.Values.Where(s => !s.Asic && !s.Scrap))
|
||||
{
|
||||
var s = spec;
|
||||
@@ -77,6 +79,20 @@ namespace Decentralized
|
||||
return item;
|
||||
}
|
||||
|
||||
/// <summary>Web3 手册:银行、交易、混币器、黑市与 Ponero 的规则。界面上不放说明,规则都在这里。</summary>
|
||||
private static GameItem CreateWeb3Guide()
|
||||
{
|
||||
var item = ItemDirectory.CreateEmptyItem(Web3Guide);
|
||||
item.SetSpriteAndShapeFromMod(ModInfo.Id, "gpu_guide");
|
||||
item.name = L.T("item.web3guide.name");
|
||||
item.shortDescription = L.T("item.web3guide.desc");
|
||||
item.unitValue = 0;
|
||||
item.EnableTag(GeneralHelper.IMPORTANT_TAG);
|
||||
item.EnableTag(TypeHelper.NOT_FOR_RESALE);
|
||||
ModHelper.SetSource(item, ModInfo.Id, ModInfo.Name);
|
||||
return item;
|
||||
}
|
||||
|
||||
// ---------- 显卡 ----------
|
||||
|
||||
/// <summary>RTX70 → "RTX 70",RX800 → "RX 800"。</summary>
|
||||
|
||||
@@ -164,8 +164,6 @@ bank.ops,"Deposit / withdraw"
|
||||
poin.account.h,"Poinbase account"
|
||||
trade.h,"Trade"
|
||||
web3.wallet.h,"On-chain wallet"
|
||||
trade.hint,"Buying pays in the quote coin; |selling sells the traded coin."
|
||||
bank.hint,"Deposit turns credits into CRC; |withdrawing turns CRC back into credits |and passes compliance review."
|
||||
col.peg,"Price"
|
||||
col.status,"Status"
|
||||
stable.ok,"Pegged"
|
||||
@@ -184,7 +182,6 @@ mixer.col.taint,Taint
|
||||
mixer.col.ready,Ready
|
||||
mixer.day,Day {0}
|
||||
mixer.deposit,Deposit
|
||||
mixer.hint,"Pick asset, amount and rounds.|Each round: fee, less taint.|Rounds = days of waiting.|Coins return to this address.|Bigger deposits clean worse."
|
||||
mixer.balance,Balance: {1} {0}
|
||||
mixer.rounds,Rounds
|
||||
mixer.preview,"Expect {0} {1} back, taint down about {2}%, ready on day {3}."
|
||||
@@ -206,23 +203,20 @@ nightlog.crt_freeze,The black market handed over addresses during the crackdown:
|
||||
nightlog.thaw,Frozen {0} {1} thawed.
|
||||
news.crtfreeze.title,Black market freezes some CRT addresses for the crackdown
|
||||
news.crtfreeze.desc,"Word is the black market gave security a list of CRT addresses in exchange for being left alone. Holders with low standing are likelier to be frozen."
|
||||
tab.black,Black market
|
||||
black.upgrade.title,Web3 Black Market
|
||||
black.upgrade.desc,"Unlocks the terminal's black-market page: the black-market faction's on-chain arm. A spot counter restocks weekly with contraband, payable only in coin (PSC, CRT, CRA, Ponero), tainted coin accepted, at a premium; higher standing also opens a Ponero desk. Needs black-market standing; offline during crackdowns."
|
||||
black.upgrade.desc,"Unlocks the black market in the Web3 page: the black-market faction's on-chain arm. Weekly shelves of contraband, occasionally high-tech goods and GPUs (at a markup); buy spot, or order and wait for a courier. Coin only (PSC, CRT, CRA, Ponero), tainted coin accepted. Needs black-market standing; offline during crackdowns."
|
||||
black.offline,The black market's on-chain entrance is offline during the crackdown.
|
||||
black.closed,"You need black-market standing of {0} before anyone lets you in (currently {1})."
|
||||
black.sub.shop,Spot counter
|
||||
black.sub.desk,Ponero desk
|
||||
black.shop.h,Spot counter
|
||||
black.rep,"Black-market standing {0}, goods tier {1}/3 visible. Restocks weekly."
|
||||
black.rep,"Black-market standing {0}"
|
||||
black.empty,Sold out for this week.
|
||||
black.offer,"{0} x{1} {2} credits"
|
||||
black.buy,"Buy with coin ({0})"
|
||||
black.buy,Buy
|
||||
black.bought,"Deal done: {0} is in storage."
|
||||
black.pay.h,Payment
|
||||
black.hint,"Coin only, no CRC.|Prices are 30% above normal channels.|The coin you pay leaves its share of taint with the seller; the goods come without a stolen tag."
|
||||
black.desk.h,Ponero desk
|
||||
black.desk.hint,"Ponero is a privacy coin; it cannot be traced on-chain.|Swapping any coin into Ponero leaves that value's taint behind.|{0}% fee each way, with a daily limit.|Coin swapped out of Ponero has no origin; cash-out screening gets stricter."
|
||||
black.desk.left,"Left today: {0} (limit {1})"
|
||||
black.desk.price,"Ponero price: {0}"
|
||||
black.desk.swap,Swap
|
||||
@@ -233,23 +227,15 @@ black.desk.fail,Swap failed: balance, limit or amount is wrong.
|
||||
black.sub.orders,Orders
|
||||
black.sub.mine,My orders & intel
|
||||
black.rugged,"The platform is down; nobody will reopen for {0} more days."
|
||||
black.seller,"Seller {0} trades {1} rating {2}%"
|
||||
black.seller,"{0}, {1} trades, {2}%"
|
||||
black.orders.h,Order catalog
|
||||
black.listing,"{0} pay {1} credits"
|
||||
black.order,Order
|
||||
black.noadvance,This seller does not take advance release
|
||||
black.orders.hint,"Cheaper than spot, but it takes days|and things can go wrong.|Escrow: {0}% fee, released on delivery;|refunded if the seller runs.|Advance: {1}% off, but a scammer keeps it;|only sellers with >= {2} trades accept.|The platform can rug too; escrow and|advance money both sit with it."
|
||||
black.order,"Order ({0} days)"
|
||||
black.mode.Escrow,Escrow
|
||||
black.mode.Advance,Advance release
|
||||
black.del.Door,Door delivery
|
||||
black.del.Drop,Dead drop
|
||||
black.del.hint.Door,"A courier comes by in {0} days (as a customer when you open); higher interception chance."
|
||||
black.del.hint.Drop,"Left at the dumping ground in {0} days, pick it up at night; low interception chance, but someone may dig it up first."
|
||||
black.ordered,"Ordered: {0}, due day {1}."
|
||||
black.mine.h,My orders
|
||||
black.mine.none,No orders yet.
|
||||
black.mine.line,"{0} ({1}, {2}): {3}, day {4}{5}"
|
||||
black.mine.drop,", pick up at the dumping ground"
|
||||
black.mine.line,"{0} ({1}, {2}): {3}, day {4}"
|
||||
black.state.Pending,in transit
|
||||
black.state.Ready,arrived
|
||||
black.state.Done,picked up
|
||||
@@ -257,17 +243,13 @@ black.state.Refunded.scam,seller ran, refunded
|
||||
black.state.Lost.scam,seller ran, money gone
|
||||
black.state.Lost.rug,platform rugged, money gone
|
||||
black.state.Lost.intercept,intercepted
|
||||
black.state.Lost.theft,dug up by someone else
|
||||
black.forum.h,Forum intel
|
||||
black.forum.quiet,Quiet lately.
|
||||
black.forum.scam,"Someone says {0} takes the money and never ships."
|
||||
black.forum.rug,"Withdrawals have been slow lately, the site is running promos, and a lot of complaint threads got deleted."
|
||||
nightlog.bm.ready.Door,"Black market: {0} arrived; a courier will come by once you open."
|
||||
nightlog.bm.ready.Drop,"Black market: {0} is at the dumping ground, go get it at night."
|
||||
nightlog.bm.scam_refund,"Black market: seller {0} ran; the escrow for {1} was refunded."
|
||||
nightlog.bm.scam_loss,"Black market: seller {0} took the advance and ran; {1} is gone ({2} credits)."
|
||||
nightlog.bm.intercept,"Black market: the parcel with {0} was intercepted; {1} credits of payment lost."
|
||||
nightlog.bm.theft,"Black market: {0} at the dumping ground was dug up by someone else; {1} credits lost."
|
||||
nightlog.bm.rug,"Black market: the platform rugged; the in-transit funds for {0} ({1}) are gone."
|
||||
nightlog.bm.reopen,Black market: someone reopened at the old spot.
|
||||
news.bmrug.title,Black-market platform rugged
|
||||
@@ -277,3 +259,15 @@ courier.line1.1,"Delivery's here."
|
||||
courier.line1.2,"Package for you."
|
||||
courier.line2.1,"Don't tell me what's inside. I don't want to know."
|
||||
courier.line2.2,"Dropped it here. I'm gone."
|
||||
web3.sub.black,Black market
|
||||
black.stock,"{0} left"
|
||||
black.price,"{0} credits"
|
||||
black.noadvance,No advance release
|
||||
black.kind.gpu,"GPU condition {0}%"
|
||||
black.kind.Contraband.1,Contraband (low)
|
||||
black.kind.Contraband.2,Contraband (mid)
|
||||
black.kind.Contraband.3,Contraband (high)
|
||||
black.kind.Tech,High-tech (markup)
|
||||
nightlog.bm.ready,"Black market: {0} arrived; a courier will come by once you open."
|
||||
item.web3guide.name,Web3 Handbook
|
||||
item.web3guide.desc,"Bank: depositing turns credits into CRC; withdrawing turns CRC back into credits and goes through compliance screening. Trading: buys are paid in the quote coin, sells in the traded coin. Mixer: pick a coin, amount and rounds; each round takes a fee and lowers taint, rounds equal days of waiting, and the coins come back to the same address; the more you deposit, the worse the cleaning. Black market: coin only, no CRC, 30% above normal channels, with extra markup on high-tech goods and GPUs; the coin you pay leaves its share of taint with the seller and the goods carry no stolen tag; GPUs may be fake, inspect them yourself. Orders are cheaper than spot but take days and may be intercepted; escrow costs 5%, is released on delivery and refunded if the seller runs; advance release takes another 10% off, but a scammer keeps the money and only sellers with 30+ trades accept; the platform itself can rug. Ponero desk: Ponero is a privacy coin and swapping in wipes the taint on that value; 8% fee each way with a daily limit; coin swapped out of Ponero has no origin and cash-out screening gets stricter."
|
||||
|
@@ -163,8 +163,6 @@ bank.ops,"存取"
|
||||
poin.account.h,"Poinbase 账户"
|
||||
trade.h,"交易"
|
||||
web3.wallet.h,"链上钱包"
|
||||
trade.hint,"买入按计价币的数量支付;|卖出按所交易币的数量卖出。"
|
||||
bank.hint,"存入把信用点换成 CRC;|提取把 CRC 换回信用点,|提取要过合规审查。"
|
||||
col.peg,"价格"
|
||||
col.status,"状态"
|
||||
stable.ok,"锚定正常"
|
||||
@@ -183,7 +181,6 @@ mixer.col.taint,污点
|
||||
mixer.col.ready,到期
|
||||
mixer.day,第 {0} 天
|
||||
mixer.deposit,存入
|
||||
mixer.hint,"选币种、填数量和轮数。|每轮扣手续费并降低污点。|轮数即等待天数。|到期提回同一个地址。|存入越多,清洗越差。"
|
||||
mixer.balance,余额:{1} {0}
|
||||
mixer.rounds,轮数
|
||||
mixer.preview,"预计提回 {0} {1},污点约降低 {2}%,第 {3} 天到期。"
|
||||
@@ -205,23 +202,20 @@ nightlog.crt_freeze,镇压期间黑市交出了一批地址:你的 {0} CRT 被
|
||||
nightlog.thaw,冻结的 {0} {1} 已解冻。
|
||||
news.crtfreeze.title,黑市配合镇压冻结部分 CRT 地址
|
||||
news.crtfreeze.desc,"传闻黑市为换取放行,向安保交出了一批 CRT 地址。声望低的持有者更容易被冻结。"
|
||||
tab.black,黑市
|
||||
black.upgrade.title,Web3 黑市
|
||||
black.upgrade.desc,"解锁终端的黑市页:黑市派系在链上的实体。现货柜台每周上一批违禁品,只收币(PSC、CRT、CRA、Ponero),脏币也收,价格比正常渠道高;声望够高还有 Ponero 兑换处。需要黑市声望,镇压期间下线。"
|
||||
black.upgrade.desc,"解锁 Web3 页里的黑市:黑市派系在链上的实体。货架上每周上一批违禁品,偶尔有高科技物品和显卡(要加价);可以直接买现货,也可以下订单等快递员上门。只收币(PSC、CRT、CRA、Ponero),脏币也收。需要黑市声望,镇压期间下线。"
|
||||
black.offline,镇压期间,黑市的链上入口已经下线。
|
||||
black.closed,"黑市声望达到 {0} 才会有人带你进去(现在 {1})。"
|
||||
black.sub.shop,现货柜台
|
||||
black.sub.desk,Ponero 兑换处
|
||||
black.shop.h,现货柜台
|
||||
black.rep,"黑市声望 {0},可见货物档次 {1}/3。每周刷新。"
|
||||
black.rep,"黑市声望 {0}"
|
||||
black.empty,这周的货卖完了。
|
||||
black.offer,"{0} ×{1} {2} 信用点等值"
|
||||
black.buy,"用币购买({0})"
|
||||
black.buy,购买
|
||||
black.bought,"成交:{0} 已放进储藏区。"
|
||||
black.pay.h,付款
|
||||
black.hint,"只收币,不收 CRC。|价格比正常渠道高 30%。|付出去的币带着按比例的污点一起留在卖家那边,拿到手的货不带赃物标签。"
|
||||
black.desk.h,Ponero 兑换处
|
||||
black.desk.hint,"Ponero 是隐私币,链上无法追踪。|任何币兑入 Ponero 时,这部分价值的污点留在原地。|兑入、兑出各收 {0}% 手续费,每天有额度。|从 Ponero 兑出的币来路不明,出金审查会加重。"
|
||||
black.desk.left,"今天还能兑换 {0}(上限 {1})"
|
||||
black.desk.price,"Ponero 价格:{0}"
|
||||
black.desk.swap,兑换
|
||||
@@ -232,23 +226,15 @@ black.desk.fail,兑换失败:余额、额度或数量不对。
|
||||
black.sub.orders,订单
|
||||
black.sub.mine,我的订单与情报
|
||||
black.rugged,"平台出事了,入口关闭,还要 {0} 天才会有人重新开张。"
|
||||
black.seller,"卖家 {0} 成交 {1} 好评 {2}%"
|
||||
black.seller,"{0},成交 {1},好评 {2}%"
|
||||
black.orders.h,订单目录
|
||||
black.listing,"{0} 实付 {1} 信用点等值"
|
||||
black.order,下单
|
||||
black.noadvance,这个卖家不接受提前放款
|
||||
black.orders.hint,"比现货便宜,但要等几天,|路上可能出事。|托管:多付 {0}% 托管费,|收货后放款,卖家跑路时退款。|提前放款:再打 {1}% 折,|卖家若是骗子钱就没了;|成交 ≥ {2} 的卖家才接受。|平台自己也可能跑路,|托管和提前放款的钱都在它手里。"
|
||||
black.order,"下单({0} 天到)"
|
||||
black.mode.Escrow,托管
|
||||
black.mode.Advance,提前放款
|
||||
black.del.Door,"送货上门"
|
||||
black.del.Drop,死投点
|
||||
black.del.hint.Door,"{0} 天后快递员上门(开店时来个顾客),被截获的概率较高。"
|
||||
black.del.hint.Drop,"{0} 天后货放在垃圾场,晚上去取;被截获的概率低,但可能被别人先挖走。"
|
||||
black.ordered,"已下单:{0},预计第 {1} 天到。"
|
||||
black.mine.h,我的订单
|
||||
black.mine.none,还没有订单。
|
||||
black.mine.line,"{0}({1},{2}):{3},第 {4} 天{5}"
|
||||
black.mine.drop,,去垃圾场取
|
||||
black.mine.line,"{0}({1},{2}):{3},第 {4} 天"
|
||||
black.state.Pending,在途
|
||||
black.state.Ready,到货
|
||||
black.state.Done,已取
|
||||
@@ -256,17 +242,13 @@ black.state.Refunded.scam,卖家跑路,已退款
|
||||
black.state.Lost.scam,卖家跑路,钱没了
|
||||
black.state.Lost.rug,平台跑路,钱没了
|
||||
black.state.Lost.intercept,被截获
|
||||
black.state.Lost.theft,被别人先挖走
|
||||
black.forum.h,论坛情报
|
||||
black.forum.quiet,最近很安静。
|
||||
black.forum.scam,"有人说 {0} 收了钱不发货。"
|
||||
black.forum.rug,"最近提币变慢了,全场还在搞促销,投诉帖被删了不少。"
|
||||
nightlog.bm.ready.Door,"黑市:{0} 到货,开店后会有快递员上门。"
|
||||
nightlog.bm.ready.Drop,"黑市:{0} 已放在垃圾场,晚上去取。"
|
||||
nightlog.bm.scam_refund,"黑市:卖家 {0} 跑路了,{1} 的托管款已退回。"
|
||||
nightlog.bm.scam_loss,"黑市:卖家 {0} 拿了提前放款的钱跑路,{1} 没有了({2} 信用点等值)。"
|
||||
nightlog.bm.intercept,"黑市:{0} 的包裹被截获,{1} 信用点等值的货款没了。"
|
||||
nightlog.bm.theft,"黑市:垃圾场的 {0} 被别人先挖走了,{1} 信用点等值的货款没了。"
|
||||
nightlog.bm.rug,"黑市:平台跑路,{0} 的在途款项({1})归零。"
|
||||
nightlog.bm.reopen,黑市:有人在老地方重新开张了。
|
||||
news.bmrug.title,黑市平台跑路
|
||||
@@ -276,3 +258,15 @@ courier.line1.1,"东西到了。"
|
||||
courier.line1.2,"有你的包裹。"
|
||||
courier.line2.1,"别问我里面是什么,我也不想知道。"
|
||||
courier.line2.2,"货放这儿了,我走了。"
|
||||
web3.sub.black,黑市
|
||||
black.stock,"剩 {0} 件"
|
||||
black.price,"{0} 信用点等值"
|
||||
black.noadvance,不接受提前放款
|
||||
black.kind.gpu,"显卡 成色 {0}%"
|
||||
black.kind.Contraband.1,违禁品(低)
|
||||
black.kind.Contraband.2,违禁品(中)
|
||||
black.kind.Contraband.3,违禁品(高)
|
||||
black.kind.Tech,高科技物品(加价)
|
||||
nightlog.bm.ready,"黑市:{0} 到货,开店后会有快递员上门。"
|
||||
item.web3guide.name,Web3 手册
|
||||
item.web3guide.desc,"银行:存入把信用点换成 CRC;提取把 CRC 换回信用点,提取要过合规审查。交易:买入按计价币的数量支付,卖出按所交易币的数量卖出。混币器:选币种、填数量和轮数,每轮扣手续费并降低污点,轮数即等待天数,到期提回同一个地址;存入越多,清洗越差。黑市:只收币,不收 CRC,价格比正常渠道贵 30%,高科技物品和显卡另有加价;付出去的币带着按比例的污点留在卖家那边,货不带赃物标签;显卡不保证真假,自己鉴定。订单比现货便宜,要等几天,路上可能被截获;托管多付 5% 托管费,收货后放款,卖家跑路时退款;提前放款再打九折,卖家若是骗子钱就没了,只有成交 30 单以上的卖家接受;平台自己也可能跑路。Ponero 兑换处:Ponero 是隐私币,兑入时这部分价值的污点被清除;兑入、兑出各收 8% 手续费,每天有额度;从 Ponero 兑出的币来路不明,出金审查会加重。"
|
||||
|
@@ -13,7 +13,7 @@ namespace Decentralized
|
||||
public static class TerminalWindow
|
||||
{
|
||||
public const string Id = "pd_terminal";
|
||||
private enum Page { Home, Bank, Poinbase, Web3, Black, Report }
|
||||
private enum Page { Home, Bank, Poinbase, Web3, Report }
|
||||
|
||||
private static Page _page = Page.Home;
|
||||
private static string _amount = "";
|
||||
@@ -24,25 +24,23 @@ namespace Decentralized
|
||||
if (Session.Data == null) return;
|
||||
var b = CustomUIManager.Window(Id, L.T("term.title"));
|
||||
if (b == null) return;
|
||||
b.SetSize(780, 580).SetDraggable(true).SetCloseOnEscape(true).UseMachineryStyle();
|
||||
b.SetSize(780, 660).SetDraggable(true).SetCloseOnEscape(true).UseMachineryStyle();
|
||||
b.BeginRow();
|
||||
foreach (Page p in Enum.GetValues(typeof(Page)))
|
||||
{
|
||||
if (p == Page.Black && !Unlock.BlackUnlocked) continue;
|
||||
var page = p;
|
||||
string name = L.T("tab." + p.ToString().ToLowerInvariant());
|
||||
b.AddButton(page == _page ? $"[{name}]" : name, () => { _page = page; _message = null; Open(); });
|
||||
}
|
||||
b.End();
|
||||
b.AddSeparator();
|
||||
b.BeginScroll(450);
|
||||
b.BeginScroll(540);
|
||||
switch (_page)
|
||||
{
|
||||
case Page.Home: HomePage(b); break;
|
||||
case Page.Bank: BankPage(b); break;
|
||||
case Page.Poinbase: ExchangePage(b, Venue.Exchange); break;
|
||||
case Page.Web3: Web3Page(b); break;
|
||||
case Page.Black: BlackPage(b); break;
|
||||
default: ReportPage(b); break;
|
||||
}
|
||||
b.End();
|
||||
@@ -139,7 +137,6 @@ namespace Decentralized
|
||||
}, r =>
|
||||
{
|
||||
r.AddHeader(L.T("bank.ops"));
|
||||
foreach (var line in L.T("bank.hint").Split('|')) r.AddLabel(line);
|
||||
AmountRow(r);
|
||||
AmlPreview(r);
|
||||
r.AddButton(L.T("trade.deposit"), Deposit);
|
||||
@@ -229,7 +226,6 @@ namespace Decentralized
|
||||
}, r =>
|
||||
{
|
||||
r.AddHeader(L.T("trade.h"));
|
||||
foreach (var line in L.T("trade.hint").Split('|')) r.AddLabel(line);
|
||||
AmountRow(r);
|
||||
TradeRows(r, venue);
|
||||
});
|
||||
@@ -239,13 +235,21 @@ namespace Decentralized
|
||||
private static void Web3Page(CustomUIBuilder b)
|
||||
{
|
||||
var w = Session.Data.Hot;
|
||||
if (Unlock.MixerUnlocked)
|
||||
if (Unlock.MixerUnlocked || Unlock.BlackUnlocked)
|
||||
{
|
||||
if (_web3Tab == Web3Tab.Mixer && !Unlock.MixerUnlocked) _web3Tab = Web3Tab.Trade;
|
||||
if (_web3Tab == Web3Tab.Black && !Unlock.BlackUnlocked) _web3Tab = Web3Tab.Trade;
|
||||
b.BeginRow();
|
||||
b.AddButton(_web3Mixer ? L.T("web3.sub.trade") : $"[{L.T("web3.sub.trade")}]", () => { _web3Mixer = false; _message = null; Open(); });
|
||||
b.AddButton(_web3Mixer ? $"[{L.T("web3.sub.mixer")}]" : L.T("web3.sub.mixer"), () => { _web3Mixer = true; _message = null; Open(); });
|
||||
foreach (Web3Tab t in Enum.GetValues(typeof(Web3Tab)))
|
||||
{
|
||||
if ((t == Web3Tab.Mixer && !Unlock.MixerUnlocked) || (t == Web3Tab.Black && !Unlock.BlackUnlocked)) continue;
|
||||
var tab = t;
|
||||
string name = L.T("web3.sub." + t.ToString().ToLowerInvariant());
|
||||
b.AddButton(tab == _web3Tab ? $"[{name}]" : name, () => { _web3Tab = tab; _message = null; Open(); });
|
||||
}
|
||||
b.End();
|
||||
if (_web3Mixer) { MixerPage(b); return; }
|
||||
if (_web3Tab == Web3Tab.Mixer) { MixerPage(b); return; }
|
||||
if (_web3Tab == Web3Tab.Black) { BlackPage(b); return; }
|
||||
}
|
||||
Columns(b, l =>
|
||||
{
|
||||
@@ -258,7 +262,6 @@ namespace Decentralized
|
||||
}, r =>
|
||||
{
|
||||
r.AddHeader(L.T("trade.h"));
|
||||
foreach (var line in L.T("trade.hint").Split('|')) r.AddLabel(line);
|
||||
AmountRow(r);
|
||||
TradeRows(r, Venue.Dex);
|
||||
});
|
||||
@@ -267,12 +270,28 @@ namespace Decentralized
|
||||
private enum BlackTab { Shop, Orders, Mine, Desk }
|
||||
private static BlackTab _blackTab = BlackTab.Shop;
|
||||
private static PayMode _mode = PayMode.Escrow;
|
||||
private static Delivery _delivery = Delivery.Door;
|
||||
private static string _deskAsset = Assets.PSC;
|
||||
private static bool _deskIn = true;
|
||||
private static string _payAsset = Assets.CRT;
|
||||
private static readonly System.Collections.Generic.Dictionary<string, Sprite> IconCache = new System.Collections.Generic.Dictionary<string, Sprite>();
|
||||
|
||||
/// <summary>Web3 黑市:黑市派系的链上实体。现货柜台(只收币)与 Ponero 兑换处。</summary>
|
||||
/// <summary>货架上的商品图:游戏物品自己的贴图(本 mod 的显卡用本 mod 的贴图)。</summary>
|
||||
private static Sprite Icon(string id)
|
||||
{
|
||||
if (IconCache.TryGetValue(id, out var cached)) return cached;
|
||||
Sprite sprite = null;
|
||||
var it = ModHelper.SpawnItem(BlackDelivery.GameId(id));
|
||||
if (it != null)
|
||||
{
|
||||
try { sprite = it.useSpriteFromMod ? Items.ModSprite(it.spritePath) : RenderHandler.LoadFromAtlas(it.spriteAtlasPath, it.spritePath); }
|
||||
catch (Exception ex) { Log.Info($"商品图读取失败 {id}:{ex.Message}"); }
|
||||
it.Destroy();
|
||||
}
|
||||
IconCache[id] = sprite;
|
||||
return sprite;
|
||||
}
|
||||
|
||||
/// <summary>Web3 页里的黑市:黑市派系的链上实体。货架式商城(现货、订单)、我的订单与情报、Ponero 兑换处。</summary>
|
||||
private static void BlackPage(CustomUIBuilder b)
|
||||
{
|
||||
int rep = StoreReputation.GetBMReputation();
|
||||
@@ -292,34 +311,80 @@ namespace Decentralized
|
||||
b.End();
|
||||
if (d.Black.Closed(day)) { b.AddLabel(L.T("black.rugged", d.Black.ClosedUntil - day + 1)); return; }
|
||||
if (_blackTab == BlackTab.Desk && desk) { DeskPage(b, rep, day); return; }
|
||||
if (_blackTab == BlackTab.Orders) { OrdersPage(b, day); return; }
|
||||
if (_blackTab == BlackTab.Mine) { MinePage(b, day); return; }
|
||||
bool orders = _blackTab == BlackTab.Orders;
|
||||
var w = d.Hot;
|
||||
Columns(b, l =>
|
||||
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 })
|
||||
{
|
||||
l.AddHeader(L.T("black.shop.h"));
|
||||
l.AddLabel(L.T("black.rep", rep, BlackMarket.MaxLevel(rep)));
|
||||
if (d.Black.Offers.Count == 0) l.AddLabel(L.T("black.empty"));
|
||||
foreach (var o in d.Black.Offers.ToList())
|
||||
var asset = a;
|
||||
b.AddButton(asset == _payAsset ? $"[{asset}]" : asset, () => { _payAsset = asset; Open(); });
|
||||
}
|
||||
if (orders)
|
||||
foreach (PayMode m in Enum.GetValues(typeof(PayMode)))
|
||||
{
|
||||
var offer = o;
|
||||
l.AddLabel(L.T("black.offer", ItemName(offer.Item), offer.Qty, offer.Price));
|
||||
l.AddButton(L.T("black.buy", offer.Price), () => BuyOffer(offer));
|
||||
var mode = m;
|
||||
string n = L.T("black.mode." + m);
|
||||
b.AddButton(mode == _mode ? $"[{n}]" : n, () => { _mode = mode; Open(); });
|
||||
}
|
||||
}, r =>
|
||||
b.End();
|
||||
b.AddSeparator();
|
||||
if (!orders)
|
||||
{
|
||||
r.AddHeader(L.T("black.pay.h"));
|
||||
foreach (var line in L.T("black.hint").Split('|')) r.AddLabel(line);
|
||||
r.BeginRow();
|
||||
foreach (var a in new[] { Assets.PSC, Assets.CRT, Assets.CRA, Assets.Ponero })
|
||||
if (d.Black.Offers.Count == 0) b.AddLabel(L.T("black.empty"));
|
||||
Shelf(b, d.Black.Offers.Cast<BmGood>().ToList(), (c, g) =>
|
||||
{
|
||||
var asset = a;
|
||||
r.AddButton(asset == _payAsset ? $"[{asset}]" : asset, () => { _payAsset = asset; Open(); });
|
||||
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"), () => BuyOffer(offer));
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
if (d.Black.Catalog.Count == 0) b.AddLabel(L.T("black.empty"));
|
||||
Shelf(b, d.Black.Catalog.Cast<BmGood>().ToList(), (c, g) =>
|
||||
{
|
||||
var listing = (BmListing)g;
|
||||
var seller = d.Black.Sellers[listing.Seller];
|
||||
GoodHead(c, g, L.T("black.seller", seller.Name, seller.Trades, seller.Rating));
|
||||
c.AddLabel(L.T("black.price", BlackMarket.Pay(listing.Price, _mode)));
|
||||
c.AddFlexibleSpace();
|
||||
bool ok = _mode == PayMode.Escrow || seller.Advance;
|
||||
c.AddButton(ok ? L.T("black.order", Tuning.BmDoorDays) : L.T("black.noadvance"), () => { if (ok) PlaceOrder(listing); });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private const int ShelfCols = 4;
|
||||
private const float CardW = 172f, CardH = 268f;
|
||||
|
||||
/// <summary>货架:一行 4 张商品卡。</summary>
|
||||
private static void Shelf(CustomUIBuilder b, System.Collections.Generic.List<BmGood> goods, Action<CustomUIBuilder, BmGood> card)
|
||||
{
|
||||
for (int i = 0; i < goods.Count; i += ShelfCols)
|
||||
{
|
||||
b.BeginRow(6f);
|
||||
for (int k = i; k < Math.Min(goods.Count, i + ShelfCols); k++)
|
||||
{
|
||||
var g = goods[k];
|
||||
b.BeginPanel(CardW, CardH, TextAnchor.UpperCenter, 6f, 3f);
|
||||
card(b, g);
|
||||
b.End();
|
||||
}
|
||||
r.End();
|
||||
r.AddLabel(L.T("mixer.balance", _payAsset, Fmt.Num(w.Avail(_payAsset))));
|
||||
if (w.Taint > 0.5) r.AddLabel(L.T("wallet.taint", Fmt.Credits(w.Taint)));
|
||||
});
|
||||
b.End();
|
||||
}
|
||||
}
|
||||
|
||||
private static void GoodHead(CustomUIBuilder c, BmGood g, string line2)
|
||||
{
|
||||
var sprite = Icon(g.Item);
|
||||
if (sprite != null) c.AddImage(sprite, 64f, 64f); else c.AddSpace(64f);
|
||||
c.AddLabel("<b>" + ItemName(g.Item) + "</b>");
|
||||
c.AddLabel(g.Kind == GoodKind.Gpu ? L.T("black.kind.gpu", (int)Math.Round(g.Health)) : L.T("black.kind." + g.Kind + (g.Kind == GoodKind.Contraband ? "." + g.Level : "")));
|
||||
c.AddLabel(line2);
|
||||
}
|
||||
|
||||
private static string ItemName(string id) => BlackDelivery.ItemName(id);
|
||||
@@ -327,69 +392,19 @@ namespace Decentralized
|
||||
private static void BuyOffer(BmOffer o)
|
||||
{
|
||||
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(ModHelper.SpawnItem(o.Item));
|
||||
_message = L.T("black.bought", ItemName(o.Item));
|
||||
Items.Give(BlackDelivery.Make(item, model, fake, health));
|
||||
_message = L.T("black.bought", ItemName(item));
|
||||
Session.Save();
|
||||
Open();
|
||||
}
|
||||
|
||||
private static string SellerText(BmSeller s) => L.T("black.seller", s.Name, s.Trades, s.Rating);
|
||||
|
||||
/// <summary>订单目录:比现货便宜,要等几天,可能被截获、被骗。</summary>
|
||||
private static void OrdersPage(CustomUIBuilder b, int day)
|
||||
{
|
||||
var d = Session.Data;
|
||||
var w = d.Hot;
|
||||
Columns(b, l =>
|
||||
{
|
||||
l.AddHeader(L.T("black.orders.h"));
|
||||
if (d.Black.Catalog.Count == 0) l.AddLabel(L.T("black.empty"));
|
||||
foreach (var x in d.Black.Catalog.ToList())
|
||||
{
|
||||
var listing = x;
|
||||
var seller = d.Black.Sellers[listing.Seller];
|
||||
l.AddLabel(L.T("black.listing", ItemName(listing.Item), BlackMarket.Pay(listing.Price, _mode)));
|
||||
l.AddLabel(" " + SellerText(seller));
|
||||
bool ok = _mode == PayMode.Escrow || seller.Advance;
|
||||
l.AddButton(ok ? L.T("black.order") : L.T("black.noadvance"), () => { if (ok) PlaceOrder(listing); });
|
||||
}
|
||||
}, r =>
|
||||
{
|
||||
r.AddHeader(L.T("black.pay.h"));
|
||||
foreach (var line in L.T("black.orders.hint", (int)Math.Round(Tuning.BmEscrowFee * 100), (int)Math.Round(Tuning.BmAdvanceDiscount * 100), Tuning.BmAdvanceMinTrades).Split('|')) r.AddLabel(line);
|
||||
r.BeginRow();
|
||||
foreach (PayMode m in Enum.GetValues(typeof(PayMode)))
|
||||
{
|
||||
var mode = m;
|
||||
string n = L.T("black.mode." + m);
|
||||
r.AddButton(mode == _mode ? $"[{n}]" : n, () => { _mode = mode; Open(); });
|
||||
}
|
||||
r.End();
|
||||
r.BeginRow();
|
||||
foreach (Delivery dl in Enum.GetValues(typeof(Delivery)))
|
||||
{
|
||||
var del = dl;
|
||||
string n = L.T("black.del." + dl, Tuning.BmDoorDays);
|
||||
r.AddButton(del == _delivery ? $"[{n}]" : n, () => { _delivery = del; Open(); });
|
||||
}
|
||||
r.End();
|
||||
r.AddLabel(L.T("black.del.hint." + _delivery, BlackMarket.Days(_delivery)));
|
||||
r.BeginRow();
|
||||
foreach (var a in new[] { Assets.PSC, Assets.CRT, Assets.CRA, Assets.Ponero })
|
||||
{
|
||||
var asset = a;
|
||||
r.AddButton(asset == _payAsset ? $"[{asset}]" : asset, () => { _payAsset = asset; Open(); });
|
||||
}
|
||||
r.End();
|
||||
r.AddLabel(L.T("mixer.balance", _payAsset, Fmt.Num(w.Avail(_payAsset))));
|
||||
});
|
||||
}
|
||||
|
||||
private static void PlaceOrder(BmListing l)
|
||||
{
|
||||
var d = Session.Data;
|
||||
var o = d.Black.Place(l, _mode, _delivery, d.Hot, _payAsset, StoreStation.GetDayCounter(), Session.Price);
|
||||
var o = d.Black.Place(l, _mode, d.Hot, _payAsset, StoreStation.GetDayCounter(), Session.Price);
|
||||
if (o == null) { _message = L.T("msg.balance"); Open(); return; }
|
||||
_message = L.T("black.ordered", ItemName(o.Item), o.DueDay);
|
||||
Session.Save();
|
||||
@@ -405,7 +420,7 @@ namespace Decentralized
|
||||
l.AddHeader(L.T("black.mine.h"));
|
||||
if (d.Black.Orders.Count == 0) l.AddLabel(L.T("black.mine.none"));
|
||||
foreach (var o in d.Black.Orders.OrderByDescending(x => x.PlacedDay))
|
||||
l.AddLabel(L.T("black.mine.line", ItemName(o.Item), 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, o.Delivery == Delivery.Drop && o.State == OrderState.Ready ? L.T("black.mine.drop") : ""));
|
||||
l.AddLabel(L.T("black.mine.line", ItemName(o.Item), 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"));
|
||||
@@ -422,7 +437,6 @@ namespace Decentralized
|
||||
Columns(b, l =>
|
||||
{
|
||||
l.AddHeader(L.T("black.desk.h"));
|
||||
foreach (var line in L.T("black.desk.hint", (int)Math.Round(Tuning.PoneroFee * 100)).Split('|')) l.AddLabel(line);
|
||||
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);
|
||||
@@ -460,7 +474,8 @@ namespace Decentralized
|
||||
Open();
|
||||
}
|
||||
|
||||
private static bool _web3Mixer;
|
||||
private enum Web3Tab { Trade, Mixer, Black }
|
||||
private static Web3Tab _web3Tab = Web3Tab.Trade;
|
||||
private static string _mixAsset = Assets.PSC;
|
||||
private static int _mixRounds = 2;
|
||||
private static readonly float[] MixW = { 70f, 100f, 100f, 80f };
|
||||
@@ -488,7 +503,6 @@ namespace Decentralized
|
||||
}, r =>
|
||||
{
|
||||
r.AddHeader(L.T("mixer.deposit"));
|
||||
foreach (var line in L.T("mixer.hint").Split('|')) r.AddLabel(line);
|
||||
r.BeginRow();
|
||||
foreach (var a in new[] { Assets.PSC, Assets.CRC, Assets.CRT, Assets.CRA })
|
||||
{
|
||||
|
||||
@@ -44,6 +44,7 @@ namespace Decentralized
|
||||
Items.Give(ModHelper.SpawnItem(Items.Rig));
|
||||
Items.Give(ModHelper.SpawnItem(Items.GpuId("RTX60")));
|
||||
Items.Give(ModHelper.SpawnItem(Items.Guide));
|
||||
Items.Give(ModHelper.SpawnItem(Items.Web3Guide));
|
||||
Log.Info("已加入 Web3 治理社区");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user