Phase 2: CRT freeze during crackdowns (frozen balance, thaw, news, test entry)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ZHU MINCHAOandClaude Sonnet 5.5 committed 2026-11-03 16:51:12 +08:00
1 parent be18078f69
commit c295e72a48
10 files changed
+91 -5

No files matched your search

+7
View File
@@ -15,6 +15,13 @@ namespace Decentralized
public static void Subscribe()
{
ModHook.OnGenerateCustomerLate += OnGenerate;
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Frozen CRT (test)", () => Log.Guard("冻结 CRT(测试)", () =>
{
var w = Session.Data.Hot;
w.Add(Assets.CRT, 1000);
double f = w.Freeze(Assets.CRT, Tuning.CrtFreezeShare, StoreStation.GetDayCounter() + Tuning.CrtUnfreezeAfter);
Log.Info($"CRT {w.Get(Assets.CRT):0},冻结 {f:0},可动用 {w.Avail(Assets.CRT):0}");
}));
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Tainted wallet (test)", () => Log.Guard("带污点的钱包(测试)", () =>
{
var w = Session.Data.Hot;
@@ -200,3 +200,9 @@ nightlog.mixer_flag, (withdrawn during sanctions; address flagged)
nightlog.mixer_rug,The mixer's operator ran off with it: {0} {1} never came back.
web3.sub.trade,Trade
web3.sub.mixer,Mixer
msg.frozen,Those coins are frozen until they thaw.
wallet.frozen,"{0}: {1} frozen, thaws on day {2}"
nightlog.crt_freeze,The black market handed over addresses during the crackdown: {0} of your CRT is frozen until day {1}.
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."
1 # Probably Decentralized localization table: English (en)
200 nightlog.mixer_rug
201 web3.sub.trade
202 web3.sub.mixer
203 msg.frozen
204 wallet.frozen
205 nightlog.crt_freeze
206 nightlog.thaw
207 news.crtfreeze.title
208 news.crtfreeze.desc
@@ -199,3 +199,9 @@ nightlog.mixer_flag,(制裁期间提出,地址被标记)
nightlog.mixer_rug,混币器的运营者卷款跑路了:{0} {1} 没有提回。
web3.sub.trade,交易
web3.sub.mixer,混币器
msg.frozen,这部分币被冻结了,到期前不能动用。
wallet.frozen,"{0} 冻结 {1},第 {2} 天解冻"
nightlog.crt_freeze,镇压期间黑市交出了一批地址:你的 {0} CRT 被冻结,第 {1} 天解冻。
nightlog.thaw,冻结的 {0} {1} 已解冻。
news.crtfreeze.title,黑市配合镇压冻结部分 CRT 地址
news.crtfreeze.desc,"传闻黑市为换取放行,向安保交出了一批 CRT 地址。声望低的持有者更容易被冻结。"
1 # Probably Decentralized 本地化表:简体中文(zh)
199 nightlog.mixer_rug
200 web3.sub.trade
201 web3.sub.mixer
202 msg.frozen
203 wallet.frozen
204 nightlog.crt_freeze
205 nightlog.thaw
206 news.crtfreeze.title
207 news.crtfreeze.desc
+15 -1
View File
@@ -83,7 +83,21 @@ namespace Decentralized
int day = StoreStation.GetDayCounter();
var events = ActiveEvents();
bool wasSanctioned = d.Mixer.Sanctioned(day);
foreach (var ev in events.Where(e => !d.ActiveEvents.Contains(e))) { d.Stable.OnEventStart(ev, day, d.Rng); d.Mixer.OnEvent(ev, day, d.Rng); }
foreach (var ev in events.Where(e => !d.ActiveEvents.Contains(e)))
{
d.Stable.OnEventStart(ev, day, d.Rng); d.Mixer.OnEvent(ev, day, d.Rng);
// 镇压开始:黑市为换取放行,按声望出卖一批 CRT 地址
if (ev == MarketEvent.Crackdown && Stablecoins.CrtFrozenByCrackdown(StoreReputation.GetBMReputation(), d.Rng))
{
double frozen = d.Hot.Freeze(Assets.CRT, Tuning.CrtFreezeShare, day + Tuning.CrtUnfreezeAfter);
if (frozen > 0)
{
PlayerStore.Instance.AddNightLog(L.T("nightlog.crt_freeze", Fmt.Num(frozen), day + Tuning.CrtUnfreezeAfter), "cc7755");
News.Show("pd_news_crtfreeze_" + day, L.T("news.crtfreeze.title"), L.T("news.crtfreeze.desc"), 3);
}
}
}
foreach (var t in d.Hot.Thaw(day)) PlayerStore.Instance.AddNightLog(L.T("nightlog.thaw", Fmt.Num(t.Value), t.Key));
if (!wasSanctioned && d.Mixer.Sanctioned(day) && Unlock.MixerUnlocked) News.Show("pd_news_sanction_" + day, L.T("news.sanction.title"), L.T("news.sanction.desc"), 3);
d.ActiveEvents = events;
d.Network.Availability = (events.Contains(MarketEvent.Blackout) ? 0.8 : 1) * (events.Contains(MarketEvent.LowerUnrest) ? 0.9 : 1);
+7 -3
View File
@@ -212,6 +212,8 @@ namespace Decentralized
TableRow(b, HoldW, kv.Key, Fmt.Num(kv.Value), Fmt.Credits(kv.Value * Session.Price(kv.Key)), AvgText(w, kv.Key));
}
if (!any) b.AddLabel(L.T("wallet.empty"));
foreach (var kv in w.Frozen.OrderBy(k => k.Key).Where(k => show(k.Key)))
b.AddLabel(L.T("wallet.frozen", kv.Key, Fmt.Num(kv.Value), w.FrozenUntil.TryGetValue(kv.Key, out var u) ? u : 0));
}
/// <summary>Poinbase:合规交易所。左边账户持仓,右边交易;信用点的存取在银行。</summary>
@@ -296,7 +298,7 @@ namespace Decentralized
r.AddButton(asset == _mixAsset ? $"[{asset}]" : asset, () => { _mixAsset = asset; Open(); });
}
r.End();
r.AddLabel(L.T("mixer.balance", _mixAsset, Fmt.Num(w.Get(_mixAsset))));
r.AddLabel(L.T("mixer.balance", _mixAsset, Fmt.Num(w.Avail(_mixAsset))));
AmountRow(r);
r.AddLabel(L.T("mixer.rounds"));
r.BeginRow();
@@ -320,13 +322,15 @@ namespace Decentralized
if (!ReadAmount(out double v)) return;
var d = Session.Data;
int day = StoreStation.GetDayCounter();
if (d.Hot.Get(_mixAsset) + 1e-9 < v) { _message = L.T("msg.balance"); Open(); return; }
if (d.Hot.Avail(_mixAsset) + 1e-9 < v) { _message = L.T("msg.balance"); Open(); return; }
var dep = d.Mixer.Deposit(d.Hot, _mixAsset, v, _mixRounds, day, Session.Price);
_message = dep == null ? L.T("mixer.min", Tuning.MixerMin) : L.T("mixer.done", Fmt.Num(v), _mixAsset, dep.ReadyDay);
Session.Save();
Open();
}
private static bool frozenPay(Wallet w, string asset) => w.Frozen.ContainsKey(asset);
private static string AvgText(Wallet w, string asset) => w.AvgBuy(asset) is double a ? Fmt.Num(a) : L.T("avg.none");
private static void ReportPage(CustomUIBuilder b)
@@ -393,7 +397,7 @@ namespace Decentralized
if (!ReadAmount(out double v)) return;
var w = Session.Data.Hot;
string pay = buy ? p.Quote : p.Base, get = buy ? p.Base : p.Quote;
if (w.Get(pay) + 1e-9 < v) { _message = L.T("msg.balance"); Open(); return; }
if (w.Avail(pay) + 1e-9 < v) { _message = L.T(frozenPay(w, pay) ? "msg.frozen" : "msg.balance"); Open(); return; }
double got = buy ? p.BuyBase(v) : p.SellBase(v);
double spent = v * Session.Price(pay);
w.Add(pay, -v);