Add feature queries, dungeon information and event calendar UI

This commit is contained in:
shen
2026-10-15 02:28:01 -07:00
parent 9d9993b007
commit 4e2d39b612
17 changed files with 1248 additions and 11 deletions
+43
View File
@@ -15,6 +15,7 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
using namespace mtnet::classic;
@@ -911,6 +912,48 @@ bool FakeLoginServer::ServeGame(Connection& c, int index)
if (!c.Send(chat) || !c.Send(cmd.c_str(), cmd.size() + 1)) return Fail(name + ": biolog reply");
}
}
else if (text.rfind("/mt_features ",0)==0) {
std::istringstream in(text);std::string command,kind;unsigned version=0,request=0,subject=0,offset=0;
in>>command>>version>>request>>kind>>subject>>offset;
auto reply=[&](const std::string& cmd) {
GCChatHead chat={HDR_GC_CHAT,static_cast<std::uint16_t>(sizeof(GCChatHead)+cmd.size()+1),5,0,1};
return c.Send(chat)&&c.Send(cmd.c_str(),cmd.size()+1);
};
const std::string r=std::to_string(request);
if(kind=="cap") {if(!reply("MTF1 cap "+r+" 1 63 1700000000"))return Fail(name+": feature cap");}
else if(kind=="calendar") {
if(!reply("MTF1 begin "+r+" calendar 1 0 2 0 1700000000") ||
!reply("MTF1 event "+r+" 0 1 1 1700000000 1700003600 0 0 1") ||
!reply("MTF1 event "+r+" 1 2 2 1700086400 1700090000 2 0 0") ||
!reply("MTF1 end "+r+" 2"))return Fail(name+": calendar");
}
else if(kind=="dungeons") {
const std::pair<const char*,long long> values[]={
{"lair_end",1700003600},{"lair_join_end",1700000300},{"lair_phase",1},
{"lair_ticket",30179},{"lair_tickets",3},{"lair_boss",2430},{"lair_owned",7},
{"lair_alive",1},{"lair_npc",30121},{"lair_map",208},
{"weekly_end",1700561600},{"weekly_hunt_end",1700007200},{"weekly_active",1},
{"weekly_npc",30122},{"weekly_map",73}};
if(!reply("MTF1 begin "+r+" dungeons 0 0 15 0 1700000000"))return Fail(name+": dungeon begin");
for(unsigned i=0;i<15;++i)
if(!reply("MTF1 stat "+r+" "+std::to_string(i)+" "+values[i].first+" "+std::to_string(values[i].second)))return Fail(name+": dungeon stat");
if(!reply("MTF1 end "+r+" 15"))return Fail(name+": dungeon end");
}
else if(kind=="stats") {
if(!reply("MTF1 begin "+r+" stats 0 0 3 0 1700000000") ||
!reply("MTF1 stat "+r+" 0 maxhp 1500") || !reply("MTF1 stat "+r+" 1 stone 10") ||
!reply("MTF1 stat "+r+" 2 resist_human 4") || !reply("MTF1 end "+r+" 3"))return Fail(name+": feature stats");
} else {
unsigned total=kind=="mob"?10:kind=="chest"?2:1;
if(!reply("MTF1 begin "+r+" "+kind+" "+std::to_string(subject)+" "+std::to_string(offset)+" "+std::to_string(total)+" "+(kind=="chest"?"10":"0")+" 1700000000"))return Fail(name+": feature begin");
unsigned sent=0;
for(unsigned i=offset;i<total && sent<8;++i,++sent) {
std::string row=kind=="mob"?"30006 1 1 0 0 100 0 0":kind=="sources"?"101 1 0 1 30 100 0 0":i==0?"19 1 10 0 0 80 100 0":"1 500 10 0 0 20 100 0";
if(!reply("MTF1 row "+r+" "+std::to_string(i)+" "+row))return Fail(name+": feature row");
}
if(!reply("MTF1 end "+r+" "+std::to_string(sent)))return Fail(name+": feature end");
}
}
else if (text == "/server_bonuses") {
const std::string cmd = "ServerBonuses 200 200 200 200 200 0 200 0";
GCChatHead chat = {HDR_GC_CHAT, static_cast<std::uint16_t>(sizeof(GCChatHead) + cmd.size() + 1), 5, 0, 1};