summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Longbons <b.r.longbons@gmail.com>2015-01-03 12:11:33 -0800
committerBen Longbons <b.r.longbons@gmail.com>2015-01-03 12:11:33 -0800
commit6f6529a4bbc4dceaaed7e9c56b482e83fb809de9 (patch)
tree27c05065aaa38893ffb5677aebdb7f65286751c4
parent29ec8b3f3910b4b9bb0724953c9628dc039df06b (diff)
downloadtmwa-6f6529a4bbc4dceaaed7e9c56b482e83fb809de9.tar.gz
tmwa-6f6529a4bbc4dceaaed7e9c56b482e83fb809de9.tar.bz2
tmwa-6f6529a4bbc4dceaaed7e9c56b482e83fb809de9.tar.xz
tmwa-6f6529a4bbc4dceaaed7e9c56b482e83fb809de9.zip
Document every network packet's pre, post, and desc
With pretty pictures (not a submodule because large images). Part of this commit was originally made by Rawng.
-rw-r--r--Makefile.in13
-rw-r--r--old-doc/mapserver-logging (renamed from doc/mapserver-logging)0
-rw-r--r--old-doc/old-spell-language (renamed from doc/old-spell-language)0
-rw-r--r--src/admin/ladmin.cpp370
-rw-r--r--src/char/char.cpp86
-rw-r--r--src/login/login.cpp219
-rw-r--r--src/map/battle.cpp11
-rw-r--r--src/map/battle.hpp1
-rw-r--r--src/map/chrif.cpp133
-rw-r--r--src/map/chrif.hpp1
-rw-r--r--src/map/clif.cpp108
-rw-r--r--src/map/clif.hpp5
-rw-r--r--src/map/npc.cpp21
-rw-r--r--src/map/npc.hpp1
-rw-r--r--src/map/pc.cpp180
-rw-r--r--src/map/pc.hpp5
-rw-r--r--src/mmo/skill.t.hpp3
-rwxr-xr-xtools/protocol.py3207
18 files changed, 2843 insertions, 1521 deletions
diff --git a/Makefile.in b/Makefile.in
index 0002153..7cf6080 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -224,6 +224,11 @@ TEST_BINARIES := $(patsubst src/%/test.cpp,bin/tests/test-%,${TEST_SOURCES})
GTEST_BINARIES := $(patsubst src--%_test.cpp,bin/tests/gtest-%,$(subst /,--,${GTEST_SOURCES}))
DTEST_BINARIES := $(patsubst src/debug-debug/%.cpp,bin/tests/dtest-%,${DTEST_SOURCES})
+DOC_DOTS := $(shell cd ${SRC_DIR}; find doc-gen/ -name '*.gv')
+DOC_PNGS := $(patsubst %.gv,${SRC_DIR}/%.png,${DOC_DOTS})
+DOC_OBSOLETE :=
+DOC_OBSOLETE += $(filter-out ${DOC_PNGS},$(wildcard ${SRC_DIR}/doc-gen/*.png))
+
# tricky part
# We can't put comments in a macro so here goes:
@@ -747,6 +752,14 @@ stamp/%.tcc.formatted: src/%.tcc tools/indenter
touch $@
.PHONY: format format-cpp format-hpp
+vpath doc-gen/%.gv ${SRC_DIR}
+${SRC_DIR}/doc-gen/%.png: doc-gen/%.gv
+ dot -Tpng $< -o $@
+doc: ${DOC_PNGS}
+ test -e ${SRC_DIR}/doc-gen/.git
+ rm -f ${DOC_OBSOLETE}
+.PHONY: doc
+
most: $(filter-out bin/${tmwa}-map,${BINARIES})
magic: $(filter obj/map/magic%,${PDC_OBJECTS})
common: $(filter-out %/lib.pdc.o obj/debug-debug/% %_test.pdc.o obj/login/% obj/char/% obj/map/% obj/admin/% obj/monitor/%,${PDC_OBJECTS})
diff --git a/doc/mapserver-logging b/old-doc/mapserver-logging
index 573c61f..573c61f 100644
--- a/doc/mapserver-logging
+++ b/old-doc/mapserver-logging
diff --git a/doc/old-spell-language b/old-doc/old-spell-language
index 5f70f89..5f70f89 100644
--- a/doc/old-spell-language
+++ b/old-doc/old-spell-language
diff --git a/src/admin/ladmin.cpp b/src/admin/ladmin.cpp
index e3557dd..97b570e 100644
--- a/src/admin/ladmin.cpp
+++ b/src/admin/ladmin.cpp
@@ -224,29 +224,6 @@ AString ladmin_log_filename = "log/ladmin.log"_s;
// all other values are 'No MSG', then use state 9 please.
// 'error_message_#7': message of the code error 6 = Your are Prohibited to log in until %s (packet 0x006a)
//
-// timeadd <account_name> <modifier>
-// Adds or substracts time from the validity limit of an account.
-// Modifier is done as follows:
-// Adjustment value (-1, 1, +1, etc...)
-// Modified element:
-// a or y: year
-// m: month
-// j or d: day
-// h: hour
-// mn: minute
-// s: second
-// <example> timeadd testname +1m-2mn1s-6y
-// this example adds 1 month and 1 second, and substracts 2 minutes and 6 years at the same time.
-// NOTE: You can not modify a unlimited validity limit.
-// If you want modify it, you want probably create a limited validity limit.
-// So, at first, you must set the validity limit to a date/time.
-//
-// timeset <account_name> yyyy/mm/dd [hh:mm:ss]
-// Changes the validity limit of an account.
-// Default time [hh:mm:ss]: 23:59:59.
-// timeset <account_name> 0
-// Gives an unlimited validity limit (0 = unlimited).
-//
// unban/unbanish <account name>
// Unban an account.
// Like banset <account name> 0.
@@ -491,13 +468,6 @@ void display_help(ZString param)
PRINTF(" Research by name is not possible with this command.\n"_fmt);
PRINTF(" <example> list 10 9999999\n"_fmt);
}
- else if (command == "itemfrob"_s)
- {
- PRINTF("itemfrob <source-id> <dest-id>\n"_fmt);
- PRINTF(" Translates item IDs for all accounts.\n"_fmt);
- PRINTF(" Any items matching the source item ID will be mapped to the dest-id.\n"_fmt);
- PRINTF(" <example> itemfrob 500 700\n"_fmt);
- }
else if (command == "listban"_s)
{
PRINTF("listban [start_id [end_id]]\n"_fmt);
@@ -569,34 +539,6 @@ void display_help(ZString param)
PRINTF(" 'error_message_#7': message of the code error 6\n"_fmt);
PRINTF(" = Your are Prohibited to log in until... (packet 0x006a)\n"_fmt);
}
- else if (command == "timeadd"_s)
- {
- PRINTF("timeadd <account_name> <modifier>\n"_fmt);
- PRINTF(" Adds or substracts time from the validity limit of an account.\n"_fmt);
- PRINTF(" Modifier is done as follows:\n"_fmt);
- PRINTF(" Adjustment value (-1, 1, +1, etc...)\n"_fmt);
- PRINTF(" Modified element:\n"_fmt);
- PRINTF(" a or y: year\n"_fmt);
- PRINTF(" m: month\n"_fmt);
- PRINTF(" j or d: day\n"_fmt);
- PRINTF(" h: hour\n"_fmt);
- PRINTF(" mn: minute\n"_fmt);
- PRINTF(" s: second\n"_fmt);
- PRINTF(" <example> timeadd testname +1m-2mn1s-6y\n"_fmt);
- PRINTF(" this example adds 1 month and 1 second, and substracts 2 minutes\n"_fmt);
- PRINTF(" and 6 years at the same time.\n"_fmt);
- PRINTF("NOTE: You can not modify a unlimited validity limit.\n"_fmt);
- PRINTF(" If you want modify it, you want probably create a limited validity limit.\n"_fmt);
- PRINTF(" So, at first, you must set the validity limit to a date/time.\n"_fmt);
- }
- else if (command == "timeadd"_s)
- {
- PRINTF("timeset <account_name> yyyy/mm/dd [hh:mm:ss]\n"_fmt);
- PRINTF(" Changes the validity limit of an account.\n"_fmt);
- PRINTF(" Default time [hh:mm:ss]: 23:59:59.\n"_fmt);
- PRINTF("timeset <account_name> 0\n"_fmt);
- PRINTF(" Gives an unlimited validity limit (0 = unlimited).\n"_fmt);
- }
else if (command == "unban"_s)
{
PRINTF("unban/unbanish <account name>\n"_fmt);
@@ -648,7 +590,6 @@ void display_help(ZString param)
PRINTF(" gm <account_name> [GM_level] -- Modify the GM level of an account\n"_fmt);
PRINTF(" id <account name> -- Give the id of an account\n"_fmt);
PRINTF(" info <account_id> -- Display all information of an account\n"_fmt);
- PRINTF(" itemfrob <source-id> <dest-id> -- Map all items from one item ID to another\n"_fmt);
PRINTF(" kami <message> -- Sends a broadcast message (in yellow)\n"_fmt);
PRINTF(" kamib <message> -- Sends a broadcast message (in blue)\n"_fmt);
PRINTF(" list [First_id [Last_id]] -- Display a list of accounts\n"_fmt);
@@ -665,10 +606,6 @@ void display_help(ZString param)
PRINTF(" search <expression> -- Seek accounts\n"_fmt);
PRINTF(" sex <nomcompte> <sexe> -- Modify the sex of an account\n"_fmt);
PRINTF(" state <account_name> <new_state> <error_message_#7> -- Change the state\n"_fmt);
- PRINTF(" timeadd <account_name> <modifier> -- Add or substract time from the\n"_fmt);
- PRINTF(" example: ta apple +1m-2mn1s-2y validity limit of an account\n"_fmt);
- PRINTF(" timeset <account_name> yyyy/mm/dd [hh:mm:ss] -- Change the validify limit\n"_fmt);
- PRINTF(" timeset <account_name> 0 -- Give a unlimited validity limit\n"_fmt);
PRINTF(" unban <account name> -- Remove the banishment of an account\n"_fmt);
PRINTF(" unblock <account name> -- Set state 0 (Account ok) to an account\n"_fmt);
PRINTF(" version -- Gives the version of the login-server\n"_fmt);
@@ -1264,29 +1201,6 @@ void listaccount(ZString param, int type)
list_count = 0;
}
-//--------------------------------------------------------
-// Sub-function: Frobnicate items
-//--------------------------------------------------------
-static
-int itemfrob(ZString param)
-{
- ItemNameId source_id, dest_id;
-
- if (!extract(param, record<' '>(&source_id, &dest_id)))
- {
- PRINTF("You must provide the source and destination item IDs.\n"_fmt);
- return 1;
- }
-
- Packet_Fixed<0x7924> fixed_24;
- fixed_24.source_item_id = source_id;
- fixed_24.dest_item_id = dest_id;
- send_fpacket<0x7924, 10>(login_session, fixed_24);
- bytes_to_read = 1; // all logging is done to the three main servers
-
- return 0;
-}
-
//--------------------------------------------
// Sub-function: Asking to modify a memo field
//--------------------------------------------
@@ -1556,179 +1470,6 @@ void blockaccount(ZString param)
changestatesub(name, 5, "-"_s); // state 5, no error message
}
-//---------------------------------------------------------------------
-// Sub-function: Add/substract time to the validity limit of an account
-//---------------------------------------------------------------------
-static
-void timeaddaccount(ZString param)
-{
- AccountName name;
- HumanTimeDiff modif {};
-
- if (!qsplit(param, &name, &modif))
- {
- PRINTF("Please input an account name and a modifier.\n"_fmt);
- PRINTF(" <example>: timeadd testname +1m-2mn1s-6y\n"_fmt);
- PRINTF(" this example adds 1 month and 1 second, and substracts 2 minutes\n"_fmt);
- PRINTF(" and 6 years at the same time.\n"_fmt);
- LADMIN_LOG("Incomplete parameters to modify a limit time ('timeadd' command).\n"_fmt);
- return;
- }
- if (name.is_print())
- {
- return;
- }
-
- if (!modif)
- {
- PRINTF("Please give an adjustment with this command:\n"_fmt);
- PRINTF(" Adjustment value (-1, 1, +1, etc...)\n"_fmt);
- PRINTF(" Modified element:\n"_fmt);
- PRINTF(" a or y: year\n"_fmt);
- PRINTF(" m: month\n"_fmt);
- PRINTF(" j or d: day\n"_fmt);
- PRINTF(" h: hour\n"_fmt);
- PRINTF(" mn: minute\n"_fmt);
- PRINTF(" s: second\n"_fmt);
- PRINTF(" <example> timeadd testname +1m-2mn1s-6y\n"_fmt);
- PRINTF(" this example adds 1 month and 1 second, and substracts 2 minutes\n"_fmt);
- PRINTF(" and 6 years at the same time.\n"_fmt);
- LADMIN_LOG("No adjustment isn't an adjustment ('timeadd' command).\n"_fmt);
- return;
- }
-
- LADMIN_LOG("Request to login-server to modify a time limit.\n"_fmt);
-
- Packet_Fixed<0x7950> fixed_50;
- fixed_50.account_name = name;
- fixed_50.valid_add = modif;
- send_fpacket<0x7950, 38>(login_session, fixed_50);
- bytes_to_read = 1;
-}
-
-//-------------------------------------------------
-// Sub-function: Set a validity limit of an account
-//-------------------------------------------------
-static
-void timesetaccount(ZString param)
-{
- AccountName name;
- XString date;
- XString time_;
- int year, month, day, hour, minute, second;
-
- year = month = day = hour = minute = second = 0;
-
- // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
- TimeT connect_until_time = TimeT();
- struct tm tmtime = connect_until_time; // initialize
-
- if (!qsplit(param, &name, &date, &time_)
- && !qsplit(param, &name, &date))
- {
- PRINTF("Please input an account name, a date and a hour.\n"_fmt);
- PRINTF("<example>: timeset <account_name> yyyy/mm/dd [hh:mm:ss]\n"_fmt);
- PRINTF(" timeset <account_name> 0 (0 = unlimited)\n"_fmt);
- PRINTF(" Default time [hh:mm:ss]: 23:59:59.\n"_fmt);
- LADMIN_LOG("Incomplete parameters to set a limit time ('timeset' command).\n"_fmt);
- return;
- }
- if (!name.is_print())
- return;
-
- if (!time_)
- time_ = "23:59:59"_s;
-
- if (date != "0"_s
- && ((!extract(date, record<'/'>(&year, &month, &day))
- && !extract(date, record<'-'>(&year, &month, &day))
- && !extract(date, record<'.'>(&year, &month, &day)))
- || !extract(time_, record<':'>(&hour, &minute, &second))))
- {
- PRINTF("Please input 0 or a date and a time (format: 0 or yyyy/mm/dd hh:mm:ss).\n"_fmt);
- LADMIN_LOG("Invalid format for the date/time ('timeset' command).\n"_fmt);
- return;
- }
-
- if (date == "0"_s)
- {
- connect_until_time = TimeT();
- }
- else
- {
- if (year < 70)
- {
- year = year + 100;
- }
- if (year >= 1900)
- {
- year = year - 1900;
- }
- if (month < 1 || month > 12)
- {
- PRINTF("Please give a correct value for the month (from 1 to 12).\n"_fmt);
- LADMIN_LOG("Invalid month for the date ('timeset' command).\n"_fmt);
- return;
- }
- month = month - 1;
- if (day < 1 || day > 31)
- {
- PRINTF("Please give a correct value for the day (from 1 to 31).\n"_fmt);
- LADMIN_LOG("Invalid day for the date ('timeset' command).\n"_fmt);
- return;
- }
- if (((month == 3 || month == 5 || month == 8 || month == 10)
- && day > 30) ||(month == 1 && day > 29))
- {
- PRINTF("Please give a correct value for a day of this month (%d).\n"_fmt,
- month);
- LADMIN_LOG("Invalid day for this month ('timeset' command).\n"_fmt);
- return;
- }
- if (hour < 0 || hour > 23)
- {
- PRINTF("Please give a correct value for the hour (from 0 to 23).\n"_fmt);
- LADMIN_LOG("Invalid hour for the time ('timeset' command).\n"_fmt);
- return;
- }
- if (minute < 0 || minute > 59)
- {
- PRINTF("Please give a correct value for the minutes (from 0 to 59).\n"_fmt);
- LADMIN_LOG("Invalid minute for the time ('timeset' command).\n"_fmt);
- return;
- }
- if (second < 0 || second > 59)
- {
- PRINTF("Please give a correct value for the seconds (from 0 to 59).\n"_fmt);
- LADMIN_LOG("Invalid second for the time ('timeset' command).\n"_fmt);
- return;
- }
- tmtime.tm_year = year;
- tmtime.tm_mon = month;
- tmtime.tm_mday = day;
- tmtime.tm_hour = hour;
- tmtime.tm_min = minute;
- tmtime.tm_sec = second;
- tmtime.tm_isdst = -1; // -1: no winter/summer time modification
- connect_until_time = tmtime;
- if (connect_until_time.error())
- {
- PRINTF("Invalid date.\n"_fmt);
- PRINTF("Please add 0 or a date and a time (format: 0 or yyyy/mm/dd hh:mm:ss).\n"_fmt);
- LADMIN_LOG("Invalid date. ('timeset' command).\n"_fmt);
- return;
- }
- }
-
- LADMIN_LOG("Request to login-server to set a time limit.\n"_fmt);
-
- Packet_Fixed<0x7948> fixed_48;
- fixed_48.account_name = name;
- fixed_48.valid_until = connect_until_time;
- send_fpacket<0x7948, 30>(login_session, fixed_48);
- bytes_to_read = 1;
-}
-
//------------------------------------------------------------------------------
// Sub-function: Asking to displaying information about an account (by its name)
//------------------------------------------------------------------------------
@@ -1878,8 +1619,6 @@ void prompt(void)
infoaccount(wrap<AccountId>(static_cast<uint32_t>(atoi(parameters.c_str()))));
else if (command == "kami"_s)
sendbroadcast(parameters); // flag for normal
- else if (command == "itemfrob"_s)
- itemfrob(parameters); // 0: to list all
else if (command == "list"_s)
listaccount(parameters, 0); // 0: to list all
else if (command == "listban"_s)
@@ -1902,10 +1641,6 @@ void prompt(void)
changesex(parameters);
else if (command == "state"_s)
changestate(parameters);
- else if (command == "timeadd"_s)
- timeaddaccount(parameters);
- else if (command == "timeset"_s)
- timesetaccount(parameters);
else if (command == "unban"_s)
unbanaccount(parameters);
else if (command == "unblock"_s)
@@ -1990,17 +1725,6 @@ void parse_fromlogin(Session *s)
break;
}
- case 0x7925: // Itemfrob-OK
- {
- Packet_Fixed<0x7925> fixed;
- rv = recv_fpacket<0x7925, 2>(s, fixed);
- if (rv != RecvResult::Complete)
- break;
-
- bytes_to_read = 0;
- break;
- }
-
case 0x7921: // Displaying of the list of accounts
{
std::vector<Packet_Repeat<0x7921>> repeat;
@@ -2491,47 +2215,6 @@ void parse_fromlogin(Session *s)
break;
}
- case 0x7949: // answer of an account validity limit set
- {
- Packet_Fixed<0x7949> fixed;
- rv = recv_fpacket<0x7949, 34>(s, fixed);
- if (rv != RecvResult::Complete)
- break;
-
- AccountId account_id = fixed.account_id;
- AccountName name = fixed.account_name;
- if (!account_id)
- {
- PRINTF("Account [%s] validity limit changing failed. Account doesn't exist.\n"_fmt,
- name);
- LADMIN_LOG("Account [%s] validity limit changing failed. Account doesn't exist.\n"_fmt,
- name);
- }
- else
- {
- TimeT timestamp = fixed.valid_until;
- if (!timestamp)
- {
- PRINTF("Validity Limit of the account [%s][id: %d] successfully changed to [unlimited].\n"_fmt,
- name, account_id);
- LADMIN_LOG("Validity Limit of the account [%s][id: %d] successfully changed to [unlimited].\n"_fmt,
- name, account_id);
- }
- else
- {
- timestamp_seconds_buffer tmpstr;
- stamp_time(tmpstr, &timestamp);
- PRINTF("Validity Limit of the account [%s][id: %d] successfully changed to be until %s.\n"_fmt,
- name, account_id, tmpstr);
- LADMIN_LOG("Validity Limit of the account [%s][id: %d] successfully changed to be until %s.\n"_fmt,
- name, account_id,
- tmpstr);
- }
- }
- bytes_to_read = 0;
- break;
- }
-
case 0x794b: // answer of an account ban set
{
Packet_Fixed<0x794b> fixed;
@@ -2636,50 +2319,6 @@ void parse_fromlogin(Session *s)
break;
}
- case 0x7951: // answer of an account validity limit changing
- {
- Packet_Fixed<0x7951> fixed;
- rv = recv_fpacket<0x7951, 34>(s, fixed);
- if (rv != RecvResult::Complete)
- break;
-
- AccountId account_id = fixed.account_id;
- AccountName name = fixed.account_name;
- if (!account_id)
- {
- PRINTF("Account [%s] validity limit changing failed. Account doesn't exist.\n"_fmt,
- name);
- LADMIN_LOG("Account [%s] validity limit changing failed. Account doesn't exist.\n"_fmt,
- name);
- }
- else
- {
- TimeT timestamp = fixed.valid_until;
- if (!timestamp)
- {
- PRINTF("Validity limit of the account [%s][id: %d] unchanged.\n"_fmt,
- name, account_id);
- PRINTF("The account have an unlimited validity limit or\n"_fmt);
- PRINTF("the changing is impossible with the proposed adjustments.\n"_fmt);
- LADMIN_LOG("Validity limit of the account [%s][id: %d] unchanged. The account have an unlimited validity limit or the changing is impossible with the proposed adjustments.\n"_fmt,
- name, account_id);
- }
- else
- {
- timestamp_seconds_buffer tmpstr;
- stamp_time(tmpstr, &timestamp);
- PRINTF("Validity limit of the account [%s][id: %d] successfully changed to be until %s.\n"_fmt,
- name, account_id,
- tmpstr);
- LADMIN_LOG("Validity limit of the account [%s][id: %d] successfully changed to be until %s.\n"_fmt,
- name, account_id,
- tmpstr);
- }
- }
- bytes_to_read = 0;
- break;
- }
-
case 0x7953: // answer of a request about informations of an account (by account name/id)
{
Packet_Head<0x7953> head;
@@ -2700,7 +2339,6 @@ void parse_fromlogin(Session *s)
timestamp_milliseconds_buffer lastlogin = head.last_login_string;
VString<15> last_ip_ = head.ip_string;
AccountEmail email = head.email;
- TimeT connect_until_time = head.connect_until;
TimeT ban_until_time = head.ban_until;
AString& memo = repeat;
if (!account_id)
@@ -2794,17 +2432,9 @@ void parse_fromlogin(Session *s)
connections);
PRINTF(" Last connection at: %s (ip: %s)\n"_fmt,
lastlogin, last_ip_);
- if (!connect_until_time)
{
PRINTF(" Validity limit: unlimited.\n"_fmt);
}
- else
- {
- timestamp_seconds_buffer tmpstr;
- stamp_time(tmpstr, &connect_until_time);
- PRINTF(" Validity limit: until %s.\n"_fmt,
- tmpstr);
- }
PRINTF(" Memo: '%s'\n"_fmt, memo);
}
}
diff --git a/src/char/char.cpp b/src/char/char.cpp
index 0b166c2..8ce2165 100644
--- a/src/char/char.cpp
+++ b/src/char/char.cpp
@@ -145,7 +145,6 @@ struct char_session_data : SessionData
SEX sex;
unsigned short packet_tmw_version;
AccountEmail email;
- TimeT connect_until_time;
};
void SessionDeleter::operator()(SessionData *sd)
@@ -162,7 +161,6 @@ struct AuthFifoEntry
int delflag;
SEX sex;
unsigned short packet_tmw_version;
- TimeT connect_until_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
};
static
std::array<AuthFifoEntry, 256> auth_fifo;
@@ -1287,7 +1285,6 @@ void parse_tologin(Session *ls)
sd->email = stringish<AccountEmail>(fixed.email);
if (!e_mail_check(sd->email))
sd->email = DEFAULT_EMAIL;
- sd->connect_until_time = fixed.connect_until;
// send characters to player
mmo_char_send006b(s2, sd);
}
@@ -1326,7 +1323,6 @@ void parse_tologin(Session *ls)
sd->email = fixed.email;
if (!e_mail_check(sd->email))
sd->email = DEFAULT_EMAIL;
- sd->connect_until_time = fixed.connect_until;
break;
}
}
@@ -1484,64 +1480,6 @@ void parse_tologin(Session *ls)
break;
}
- case 0x7924:
- { // [Fate] Itemfrob package: forwarded from login-server
- Packet_Fixed<0x7924> fixed;
- rv = recv_fpacket<0x7924, 10>(ls, fixed);
- if (rv != RecvResult::Complete)
- break;
-
- ItemNameId source_id = fixed.source_item_id;
- ItemNameId dest_id = fixed.dest_item_id;
-
- Packet_Fixed<0x2afa> fixed_fa;
- fixed_fa.source_item_id = source_id;
- fixed_fa.dest_item_id = dest_id;
-
- // forward package to map servers
- for (Session *ss : iter_map_sessions())
- {
- send_fpacket<0x2afa, 10>(ss, fixed_fa);
- }
-
- for (CharPair& cp : char_keys)
- {
- CharKey *k = &cp.key;
- CharData& cd = *cp.data.get();
- CharData *c = &cd;
- Borrowed<Storage> s = account2storage(k->account_id);
- int changes = 0;
-#define FIX(v) if (v == source_id) {v = dest_id; ++changes; }
- for (IOff0 j : IOff0::iter())
- {
- FIX(c->inventory[j].nameid);
- }
- // used to FIX cart, but it's no longer supported
- // FIX(c->weapon);
- FIX(c->shield);
- FIX(c->head_top);
- FIX(c->head_mid);
- FIX(c->head_bottom);
-
- {
- for (SOff0 j : SOff0::iter())
- {
- FIX(s->storage_[j].nameid);
- }
- }
-#undef FIX
- if (changes)
- CHAR_LOG("itemfrob(%d -> %d): `%s'(%d, account %d): changed %d times\n"_fmt,
- source_id, dest_id, k->name, k->char_id,
- k->account_id, changes);
-
- }
-
- mmo_char_sync();
- inter_storage_save();
- break;
- }
-
// Account deletion notification (from login-server)
case 0x2730:
{
@@ -1739,22 +1677,6 @@ void parse_frommap(Session *ms)
{
switch (packet_id)
{
- // request from map-server to reload GM accounts. Transmission to login-server (by Yor)
- case 0x2af7:
- {
- Packet_Fixed<0x2af7> fixed;
- rv = recv_fpacket<0x2af7, 2>(ms, fixed);
- if (rv != RecvResult::Complete)
- break;
-
- if (login_session)
- { // don't send request if no login-server
- Packet_Fixed<0x2709> fixed_09;
- send_fpacket<0x2709, 2>(login_session, fixed_09);
- }
- break;
- }
-
// Receiving map names list from the map-server
case 0x2afa:
{
@@ -1880,7 +1802,6 @@ void parse_frommap(Session *ms)
Packet_Payload<0x2afd> payload_fd; // not file descriptor
payload_fd.account_id = account_id;
payload_fd.login_id2 = afi.login_id2;
- payload_fd.connect_until = afi.connect_until_time;
cd->sex = afi.sex;
payload_fd.packet_tmw_version = afi.packet_tmw_version;
FPRINTF(stderr,
@@ -1986,7 +1907,6 @@ void parse_frommap(Session *ms)
auth_fifo_iter->login_id1 = fixed.login_id1;
auth_fifo_iter->login_id2 = fixed.login_id2;
auth_fifo_iter->delflag = 2;
- auth_fifo_iter->connect_until_time = TimeT(); // unlimited/unknown time by default (not display in map-server)
auth_fifo_iter->ip = fixed.ip;
auth_fifo_iter++;
@@ -2025,7 +1945,6 @@ void parse_frommap(Session *ms)
auth_fifo_iter->char_id = fixed.char_id;
auth_fifo_iter->delflag = 0;
auth_fifo_iter->sex = fixed.sex;
- auth_fifo_iter->connect_until_time = TimeT(); // unlimited/unknown time by default (not display in map-server)
auth_fifo_iter->ip = fixed.client_ip;
// default, if not found in the loop
@@ -2417,7 +2336,6 @@ void handle_x0066(Session *s, struct char_session_data *sd, uint8_t rfifob_2, IP
auth_fifo_iter->login_id2 = sd->login_id2;
auth_fifo_iter->delflag = 0;
auth_fifo_iter->sex = sd->sex;
- auth_fifo_iter->connect_until_time = sd->connect_until_time;
auth_fifo_iter->ip = s->client_ip;
auth_fifo_iter->packet_tmw_version = sd->packet_tmw_version;
auth_fifo_iter++;
@@ -2486,7 +2404,6 @@ void parse_char(Session *s)
s->session_data = make_unique<char_session_data, SessionDeleter>();
sd = static_cast<char_session_data *>(s->session_data.get());
sd->email = stringish<AccountEmail>("no mail"_s); // put here a mail without '@' to refuse deletion if we don't receive the e-mail
- sd->connect_until_time = TimeT(); // unknow or illimited (not displaying on map-server)
}
sd->account_id = account_id;
sd->login_id1 = fixed.login_id1;
@@ -2665,9 +2582,6 @@ void parse_char(Session *s)
s->set_eof();
return;
}
- AccountEmail email = fixed.email;
- if (!e_mail_check(email))
- email = DEFAULT_EMAIL;
{
{
diff --git a/src/login/login.cpp b/src/login/login.cpp
index fa528ba..526eb5d 100644
--- a/src/login/login.cpp
+++ b/src/login/login.cpp
@@ -177,8 +177,6 @@ GmLevel min_level_to_connect = GmLevel::from(0_u32); // minimum level of player
static
int add_to_unlimited_account = 0; // Give possibility or not to adjust (ladmin command: timeadd) the time of an unlimited account.
static
-int start_limited_time = -1; // Starting additional sec from now for the limited time at creation of accounts (-1: unlimited time, 0 or more: additional sec from now)
-static
int check_ip_flag = 1; // It's to check IP of a player between login-server and char-server (part of anti-hacking system)
DIAG_PUSH();
@@ -216,7 +214,6 @@ struct AuthData
AccountEmail email; // e-mail (by default: a@a.com)
timestamp_seconds_buffer error_message; // Message of error code #6 = Your are Prohibited to log in until %s (packet 0x006a)
TimeT ban_until_time; // # of seconds 1/1/1970 (timestamp): ban time limit of the account (0 = no ban)
- TimeT connect_until_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
IP4Address last_ip; // save of last IP of connection
VString<254> memo; // a memo field
int account_reg2_num;
@@ -482,7 +479,7 @@ AString mmo_auth_tostr(const AuthData *p)
p->state,
p->email,
p->error_message,
- p->connect_until_time,
+ TimeT(),
p->last_ip,
p->memo,
p->ban_until_time);
@@ -499,6 +496,7 @@ AString mmo_auth_tostr(const AuthData *p)
static
bool extract(XString line, AuthData *ad)
{
+ TimeT unused_connect_until_time;
std::vector<GlobalReg> vars;
VString<1> sex;
VString<15> ip;
@@ -513,7 +511,7 @@ bool extract(XString line, AuthData *ad)
&ad->state,
&ad->email,
&ad->error_message,
- &ad->connect_until_time,
+ &unused_connect_until_time,
&ip,
&ad->memo,
&ad->ban_until_time,
@@ -797,17 +795,6 @@ AccountId mmo_auth_new(struct mmo_account *account, SEX sex, AccountEmail email)
ad.error_message = stringish<timestamp_seconds_buffer>("-"_s);
ad.ban_until_time = TimeT();
- if (start_limited_time < 0)
- ad.connect_until_time = TimeT(); // unlimited
- else
- {
- // limited time
- TimeT timestamp = static_cast<time_t>(TimeT::now()) + start_limited_time;
- // there used to be a silly overflow check here, but it wasn't
- // correct, and we don't support time-limited accounts.
- ad.connect_until_time = timestamp;
- }
-
ad.last_ip = IP4Address();
ad.memo = "!"_s;
ad.account_reg2_num = 0;
@@ -901,14 +888,6 @@ int mmo_auth(struct mmo_account *account, Session *s)
}
}
- if (ad->connect_until_time
- && ad->connect_until_time < TimeT::now())
- {
- LOGIN_LOG("Connection refused (account: %s, expired ID, ip: %s)\n"_fmt,
- account->userid, ip);
- return 2; // 2 = This ID is expired
- }
-
LOGIN_LOG("Authentification accepted (account: %s (id: %d), ip: %s)\n"_fmt,
account->userid, ad->account_id, ip);
}
@@ -997,22 +976,6 @@ void parse_fromchar(Session *s)
switch (packet_id)
{
- // request from map-server via char-server to reload GM accounts (by Yor).
- case 0x2709:
- {
- Packet_Fixed<0x2709> fixed;
- rv = recv_fpacket<0x2709, 2>(s, fixed);
- if (rv != RecvResult::Complete)
- break;
-
- LOGIN_LOG("Char-server '%s': Request to re-load GM configuration file (ip: %s).\n"_fmt,
- server[id].name, ip);
- read_gm_account();
- // send GM accounts to all char-servers
- send_GM_accounts();
- break;
- }
-
case 0x2712: // request from char-server to authentify an account
{
Packet_Fixed<0x2712> fixed;
@@ -1059,7 +1022,6 @@ void parse_fromchar(Session *s)
fixed_13.account_id = acc;
fixed_13.invalid = 0;
fixed_13.email = ad.email;
- fixed_13.connect_until = ad.connect_until_time;
send_fpacket<0x2713, 51>(s, fixed_13);
break;
@@ -1118,7 +1080,6 @@ void parse_fromchar(Session *s)
Packet_Fixed<0x2717> fixed_17;
fixed_17.account_id = account_id;
fixed_17.email = ad.email;
- fixed_17.connect_until = ad.connect_until_time;
send_fpacket<0x2717, 50>(s, fixed_17);
if (rv != RecvResult::Complete)
@@ -1720,23 +1681,6 @@ void parse_admin(Session *s)
break;
}
- case 0x7924:
- { // [Fate] Itemfrob package: change item IDs
- Packet_Fixed<0x7924> fixed;
- rv = recv_fpacket<0x7924, 10>(s, fixed);
- if (rv != RecvResult::Complete)
- break;
-
- for (Session *ss : iter_char_sessions())
- {
- send_fpacket<0x7924, 10>(ss, fixed);
- }
-
- Packet_Fixed<0x7925> fixed_25;
- send_fpacket<0x7925, 2>(s, fixed_25);
- break;
- }
-
case 0x7930: // Request for an account creation
{
Packet_Fixed<0x7930> fixed;
@@ -2332,48 +2276,6 @@ void parse_admin(Session *s)
break;
}
- case 0x7948: // Request to change the validity limit (timestamp) (absolute value)
- {
- Packet_Fixed<0x7948> fixed;
- rv = recv_fpacket<0x7948, 30>(s, fixed);
- if (rv != RecvResult::Complete)
- break;
-
- Packet_Fixed<0x7949> fixed_49;
- {
- fixed_49.account_id = AccountId();
- AccountName account_name = stringish<AccountName>(fixed.account_name.to_print());
- TimeT timestamp = fixed.valid_until;
- timestamp_seconds_buffer tmpstr = stringish<timestamp_seconds_buffer>("unlimited"_s);
- if (timestamp)
- stamp_time(tmpstr, &timestamp);
- AuthData *ad = search_account(account_name);
- if (ad)
- {
- fixed_49.account_name = ad->userid;
- LOGIN_LOG("'ladmin': Change of a validity limit (account: %s, new validity: %lld (%s), ip: %s)\n"_fmt,
- ad->userid,
- timestamp,
- tmpstr,
- ip);
- ad->connect_until_time = timestamp;
- fixed_49.account_id = ad->account_id;
- }
- else
- {
- fixed_49.account_name = account_name;
- LOGIN_LOG("'ladmin': Attempt to change the validity limit of an unknown account (account: %s, received validity: %lld (%s), ip: %s)\n"_fmt,
- account_name,
- timestamp,
- tmpstr,
- ip);
- }
- fixed_49.valid_until = timestamp;
- }
- send_fpacket<0x7949, 34>(s, fixed_49);
- break;
- }
-
case 0x794a: // Request to change the final date of a banishment (timestamp) (absolute value)
{
Packet_Fixed<0x794a> fixed;
@@ -2585,99 +2487,6 @@ void parse_admin(Session *s)
break;
}
- case 0x7950: // Request to change the validity limite (timestamp) (relative change)
- {
- Packet_Fixed<0x7950> fixed;
- rv = recv_fpacket<0x7950, 38>(s, fixed);
- if (rv != RecvResult::Complete)
- break;
-
- Packet_Fixed<0x7951> fixed_51;
- {
- fixed_51.account_id = AccountId();
- AccountName account_name = stringish<AccountName>(fixed.account_name.to_print());
- AuthData *ad = search_account(account_name);
- if (ad)
- {
- fixed_51.account_id = ad->account_id;
- fixed_51.account_name = ad->userid;
- if (add_to_unlimited_account == 0 && !ad->connect_until_time)
- {
- LOGIN_LOG("'ladmin': Attempt to adjust the validity limit of an unlimited account (account: %s, ip: %s)\n"_fmt,
- ad->userid, ip);
- fixed_51.valid_until = TimeT();
- }
- else
- {
- TimeT now = TimeT::now();
- TimeT timestamp = ad->connect_until_time;
- if (!timestamp || timestamp < now)
- timestamp = now;
- struct tm tmtime = timestamp;
- HumanTimeDiff v_diff = fixed.valid_add;
- tmtime.tm_year += v_diff.year;
- tmtime.tm_mon += v_diff.month;
- tmtime.tm_mday += v_diff.day;
- tmtime.tm_hour += v_diff.hour;
- tmtime.tm_min += v_diff.minute;
- tmtime.tm_sec += v_diff.second;
- timestamp = tmtime;
- if (timestamp.okay())
- {
- timestamp_seconds_buffer tmpstr = stringish<timestamp_seconds_buffer>("unlimited"_s);
- timestamp_seconds_buffer tmpstr2 = stringish<timestamp_seconds_buffer>("unlimited"_s);
- if (ad->connect_until_time)
- stamp_time(tmpstr, &ad->connect_until_time);
- if (timestamp)
- stamp_time(tmpstr2, &timestamp);
- LOGIN_LOG("'ladmin': Adjustment of a validity limit (account: %s, %lld (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> new validity: %lld (%s), ip: %s)\n"_fmt,
- ad->userid,
- ad->connect_until_time,
- tmpstr,
- v_diff.year,
- v_diff.month,
- v_diff.day,
- v_diff.hour,
- v_diff.minute,
- v_diff.second,
- timestamp,
- tmpstr2,
- ip);
- ad->connect_until_time = timestamp;
- fixed_51.valid_until = timestamp;
- }
- else
- {
- timestamp_seconds_buffer tmpstr = stringish<timestamp_seconds_buffer>("unlimited"_s);
- if (ad->connect_until_time)
- stamp_time(tmpstr, &ad->connect_until_time);
- LOGIN_LOG("'ladmin': Impossible to adjust a validity limit (account: %s, %lld (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> ???, ip: %s)\n"_fmt,
- ad->userid,
- ad->connect_until_time,
- tmpstr,
- v_diff.year,
- v_diff.month,
- v_diff.day,
- v_diff.hour,
- v_diff.minute,
- v_diff.second,
- ip);
- fixed_51.valid_until = TimeT();
- }
- }
- }
- else
- {
- fixed_51.account_name = account_name;
- LOGIN_LOG("'ladmin': Attempt to adjust the validity limit of an unknown account (account: %s, ip: %s)\n"_fmt,
- account_name, ip);
- fixed_51.valid_until = TimeT();
- }
- }
- send_fpacket<0x7951, 34>(s, fixed_51);
- break;
- }
-
case 0x7952: // Request about informations of an account (by account name)
{
Packet_Fixed<0x7952> fixed;
@@ -2701,7 +2510,6 @@ void parse_admin(Session *s)
head_53.last_login_string = ad->lastlogin;
head_53.ip_string = convert_for_printf(ad->last_ip);
head_53.email = ad->email;
- head_53.connect_until = ad->connect_until_time;
head_53.ban_until = ad->ban_until_time;
XString repeat_53 = ad->memo;
@@ -2747,7 +2555,6 @@ void parse_admin(Session *s)
head_53.last_login_string = ad.lastlogin;
head_53.ip_string = convert_for_printf(ad.last_ip);
head_53.email = ad.email;
- head_53.connect_until = ad.connect_until_time;
head_53.ban_until = ad.ban_until_time;
XString repeat_53 = ad.memo;
send_vpacket<0x7953, 150, 1>(s, head_53, repeat_53);
@@ -3401,10 +3208,6 @@ bool login_config(XString w1, ZString w2)
{
add_to_unlimited_account = config_switch(w2);
}
- else if (w1 == "start_limited_time"_s)
- {
- start_limited_time = atoi(w2.c_str());
- }
else if (w1 == "check_ip_flag"_s)
{
check_ip_flag = config_switch(w2);
@@ -3626,14 +3429,6 @@ bool display_conf_warnings(void)
rv = false;
}
- if (start_limited_time < -1)
- { // -1: create unlimited account, 0 or more: additionnal sec from now to create limited time
- PRINTF("***WARNING: Invalid value for start_limited_time parameter\n"_fmt);
- PRINTF(" -> set to -1 (new accounts are created with unlimited time).\n"_fmt);
- start_limited_time = -1;
- rv = false;
- }
-
if (check_ip_flag != 0 && check_ip_flag != 1)
{ // 0: no, 1: yes
PRINTF("***WARNING: Invalid value for check_ip_flag parameter\n"_fmt);
@@ -3775,13 +3570,9 @@ void save_config_in_log(void)
else
LOGIN_LOG("- to refuse adjustment (with timeadd ladmin) on an unlimited account. You must use timeset (ladmin command) before.\n"_fmt);
- if (start_limited_time < 0)
+ {
LOGIN_LOG("- to create new accounts with an unlimited time.\n"_fmt);
- else if (start_limited_time == 0)
- LOGIN_LOG("- to create new accounts with a limited time: time of creation.\n"_fmt);
- else
- LOGIN_LOG("- to create new accounts with a limited time: time of creation + %d second(s).\n"_fmt,
- start_limited_time);
+ }
if (check_ip_flag)
LOGIN_LOG("- with control of players IP between login-server and char-server.\n"_fmt);
diff --git a/src/map/battle.cpp b/src/map/battle.cpp
index f852265..88fcc07 100644
--- a/src/map/battle.cpp
+++ b/src/map/battle.cpp
@@ -985,17 +985,6 @@ int battle_stopattack(dumb_ptr<block_list> bl)
return 0;
}
-// 移動停止
-int battle_stopwalking(dumb_ptr<block_list> bl, int type)
-{
- nullpo_retz(bl);
- if (bl->bl_type == BL::MOB)
- return mob_stop_walking(bl->is_mob(), type);
- else if (bl->bl_type == BL::PC)
- return pc_stop_walking(bl->is_player(), type);
- return 0;
-}
-
/*==========================================
* ダメージ最終計算
*------------------------------------------
diff --git a/src/map/battle.hpp b/src/map/battle.hpp
index aa96a72..7733391 100644
--- a/src/map/battle.hpp
+++ b/src/map/battle.hpp
@@ -58,7 +58,6 @@ int battle_heal(dumb_ptr<block_list> bl, dumb_ptr<block_list> target, int hp,
// 攻撃や移動を止める
int battle_stopattack(dumb_ptr<block_list> bl);
-int battle_stopwalking(dumb_ptr<block_list> bl, int type);
// 通常攻撃処理まとめ
ATK battle_weapon_attack(dumb_ptr<block_list> bl, dumb_ptr<block_list> target,
diff --git a/src/map/chrif.cpp b/src/map/chrif.cpp
index dbdd401..9a36a60 100644
--- a/src/map/chrif.cpp
+++ b/src/map/chrif.cpp
@@ -912,126 +912,6 @@ int chrif_recvgmaccounts(Session *s, const std::vector<Packet_Repeat<0x2b15>>& r
return 0;
}
-/*==========================================
- * Request to reload GM accounts and their levels: send to char-server by [Yor]
- *------------------------------------------
- */
-int chrif_reloadGMdb(void)
-{
- if (!char_session)
- return -1;
-
- Packet_Fixed<0x2af7> fixed_f7;
- send_fpacket<0x2af7, 2>(char_session, fixed_f7);
-
- return 0;
-}
-
-/*========================================
- * Map item IDs
- *----------------------------------------
- */
-
-static
-void ladmin_itemfrob_fix_item(ItemNameId source, ItemNameId dest, Item *item)
-{
- if (item && item->nameid == source)
- {
- item->nameid = dest;
- item->equip = EPOS::ZERO;
- }
-}
-
-static
-void ladmin_itemfrob_c2(dumb_ptr<block_list> bl, ItemNameId source_id, ItemNameId dest_id)
-{
-#define IFIX(v) if (v == source_id) {v = dest_id; }
-#define FIX(item) ladmin_itemfrob_fix_item(source_id, dest_id, &item)
-
- if (!bl)
- return;
-
- switch (bl->bl_type)
- {
- case BL::PC:
- {
- dumb_ptr<map_session_data> pc = bl->is_player();
-
- for (IOff0 j : IOff0::iter())
- IFIX(pc->status.inventory[j].nameid);
- // cart is no longer supported
- // IFIX(pc->status.weapon);
- IFIX(pc->status.shield);
- IFIX(pc->status.head_top);
- IFIX(pc->status.head_mid);
- IFIX(pc->status.head_bottom);
-
- Option<P<Storage>> stor_ = account2storage2(pc->status_key.account_id);
- if OPTION_IS_SOME(stor, stor_)
- {
- for (SOff0 j : SOff0::iter())
- FIX(stor->storage_[j]);
- }
-
- for (IOff0 j : IOff0::iter())
- {
- P<struct item_data> item = TRY_UNWRAP(pc->inventory_data[j], continue);
- if (item->nameid == source_id)
- {
- item->nameid = dest_id;
- if (bool(item->equip))
- pc_unequipitem(pc, j, CalcStatus::NOW);
- item->nameid = dest_id;
- }
- }
-
- break;
- }
-
- case BL::MOB:
- {
- dumb_ptr<mob_data> mob = bl->is_mob();
- for (Item& itm : mob->lootitemv)
- FIX(itm);
- break;
- }
-
- case BL::ITEM:
- {
- dumb_ptr<flooritem_data> item = bl->is_item();
- FIX(item->item_data);
- break;
- }
- }
-#undef FIX
-#undef IFIX
-}
-
-static
-void ladmin_itemfrob_c(dumb_ptr<block_list> bl, ItemNameId source_id, ItemNameId dest_id)
-{
- ladmin_itemfrob_c2(bl, source_id, dest_id);
-}
-
-static
-void ladmin_itemfrob(Session *, const Packet_Fixed<0x2afa>& fixed)
-{
- ItemNameId source_id = fixed.source_item_id;
- ItemNameId dest_id = fixed.dest_item_id;
- dumb_ptr<block_list> bl = map_get_first_session();
-
- // flooritems
- map_foreachobject(std::bind(ladmin_itemfrob_c, ph::_1, source_id, dest_id),
- BL::NUL /* any object */);
-
- // player characters (and, hopefully, mobs)
- while (bl->bl_next)
- {
- ladmin_itemfrob_c2(bl, source_id, dest_id);
- bl = bl->bl_next;
- }
-}
-
static
void chrif_delete(Session *s)
{
@@ -1066,16 +946,6 @@ void chrif_parse(Session *s)
chrif_connectack(s, fixed);
break;
}
- case 0x2afa:
- {
- Packet_Fixed<0x2afa> fixed;
- rv = recv_fpacket<0x2afa, 10>(s, fixed);
- if (rv != RecvResult::Complete)
- break;
-
- ladmin_itemfrob(s, fixed);
- break;
- }
case 0x2afb:
{
Packet_Fixed<0x2afb> fixed;
@@ -1095,12 +965,11 @@ void chrif_parse(Session *s)
AccountId id = payload.account_id;
int login_id2 = payload.login_id2;
- TimeT connect_until_time = payload.connect_until;
short tmw_version = payload.packet_tmw_version;
CharKey st_key = payload.char_key;
CharData st_data = payload.char_data;
pc_authok(id, login_id2,
- connect_until_time, tmw_version,
+ tmw_version,
&st_key, &st_data);
break;
}
diff --git a/src/map/chrif.hpp b/src/map/chrif.hpp
index 4bd00aa..59fb541 100644
--- a/src/map/chrif.hpp
+++ b/src/map/chrif.hpp
@@ -47,7 +47,6 @@ void chrif_changeemail(AccountId id, AccountEmail actual_email, AccountEmail new
void chrif_char_ask_name(AccountId id, CharName character_name, short operation_type,
HumanTimeDiff modif);
int chrif_saveaccountreg2(dumb_ptr<map_session_data> sd);
-int chrif_reloadGMdb(void);
int chrif_send_divorce(CharId char_id);
void do_init_chrif(void);
diff --git a/src/map/clif.cpp b/src/map/clif.cpp
index 430d928..edca352 100644
--- a/src/map/clif.cpp
+++ b/src/map/clif.cpp
@@ -622,37 +622,6 @@ int clif_clearchar(dumb_ptr<block_list> bl, BeingRemoveWhy type)
return 0;
}
-static
-void clif_clearchar_delay_sub(TimerData *, tick_t,
- dumb_ptr<block_list> bl, BeingRemoveWhy type)
-{
- clif_clearchar(bl, type);
- MapBlockLock::freeblock(bl);
-}
-
-int clif_clearchar_delay(tick_t tick,
- dumb_ptr<block_list> bl, BeingRemoveWhy type)
-{
- dumb_ptr<block_list> tmpbl;
- tmpbl.new_();
-
- // yikes!
- tmpbl->bl_next = bl->bl_next;
- tmpbl->bl_prev = bl->bl_prev;
- tmpbl->bl_id = bl->bl_id;
- tmpbl->bl_m = bl->bl_m;
- tmpbl->bl_x = bl->bl_x;
- tmpbl->bl_y = bl->bl_y;
- tmpbl->bl_type = bl->bl_type;
-
- Timer(tick,
- std::bind(clif_clearchar_delay_sub, ph::_1, ph::_2,
- tmpbl, type)
- ).detach();
-
- return 0;
-}
-
/*==========================================
*
*------------------------------------------
@@ -2684,43 +2653,6 @@ void clif_mobinsight(dumb_ptr<block_list> bl, dumb_ptr<mob_data> md)
}
/*==========================================
- *
- *------------------------------------------
- */
-int clif_skillinfo(dumb_ptr<map_session_data> sd, SkillID skillid, int type,
- int range)
-{
- nullpo_retz(sd);
-
- Session *s = sd->sess;
- if (!sd->status.skill[skillid].lv)
- return 0;
- Packet_Fixed<0x0147> fixed_147;
- fixed_147.info.skill_id = skillid;
- if (type < 0)
- fixed_147.info.type_or_inf = skill_get_inf(skillid);
- else
- fixed_147.info.type_or_inf = type;
- fixed_147.info.flags = SkillFlags::ZERO;
- fixed_147.info.level = sd->status.skill[skillid].lv;
- fixed_147.info.sp = skill_get_sp(skillid, sd->status.skill[skillid].lv);
- if (range < 0)
- {
- range = skill_get_range(skillid, sd->status.skill[skillid].lv);
- if (range < 0)
- range = battle_get_range(sd) - (range + 1);
- fixed_147.info.range = range;
- }
- else
- fixed_147.info.range = range;
- fixed_147.info.unused = ""_s;
- fixed_147.info.can_raise = sd->status.skill[skillid].lv < skill_get_max_raise(skillid);
- send_fpacket<0x0147, 39>(s, fixed_147);
-
- return 0;
-}
-
-/*==========================================
* スキルリストを送信する
*------------------------------------------
*/
@@ -3201,21 +3133,6 @@ int clif_movetoattack(dumb_ptr<map_session_data> sd, dumb_ptr<block_list> bl)
}
/*==========================================
- * MVPエフェクト
- *------------------------------------------
- */
-int clif_mvp_effect(dumb_ptr<map_session_data> sd)
-{
- nullpo_retz(sd);
-
- Packet_Fixed<0x010c> fixed_10c;
- fixed_10c.block_id = sd->bl_id;
- Buffer buf = create_fpacket<0x010c, 6>(fixed_10c);
- clif_send(buf, sd, SendWho::AREA);
- return 0;
-}
-
-/*==========================================
* エモーション
*------------------------------------------
*/
@@ -3842,25 +3759,6 @@ RecvResult clif_parse_Emotion(Session *s, dumb_ptr<map_session_data> sd)
*------------------------------------------
*/
static
-RecvResult clif_parse_HowManyConnections(Session *s, dumb_ptr<map_session_data>)
-{
- Packet_Fixed<0x00c1> fixed;
- RecvResult rv = recv_fpacket<0x00c1, 2>(s, fixed);
- if (rv != RecvResult::Complete)
- return rv;
-
- Packet_Fixed<0x00c2> fixed_c2;
- fixed_c2.users = map_getusers();
- send_fpacket<0x00c2, 6>(s, fixed_c2);
-
- return rv;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-static
RecvResult clif_parse_ActionRequest(Session *s, dumb_ptr<map_session_data> sd)
{
Packet_Fixed<0x0089> fixed;
@@ -4755,7 +4653,7 @@ RecvResult clif_parse_RemovePartyMember(Session *s, dumb_ptr<map_session_data> s
*------------------------------------------
*/
static
-RecvResult clif_parse_PartyChangeOpt0(Session *s, dumb_ptr<map_session_data> sd)
+RecvResult clif_parse_PartyChangeOption(Session *s, dumb_ptr<map_session_data> sd)
{
Packet_Fixed<0x0102> fixed;
RecvResult rv = recv_fpacket<0x0102, 6>(s, fixed);
@@ -5000,7 +4898,7 @@ func_table clif_parse_func_table[0x0220] =
{0, 5, nullptr, }, // 0x00be
{1000, 3, clif_parse_Emotion, }, // 0x00bf
{0, 7, nullptr, }, // 0x00c0
- {0, 2, clif_parse_HowManyConnections, }, // 0x00c1
+ {0, 2, nullptr, }, // 0x00c1
{0, 6, nullptr, }, // 0x00c2
{0, 8, nullptr, }, // 0x00c3
{0, 6, nullptr, }, // 0x00c4
@@ -5065,7 +4963,7 @@ func_table clif_parse_func_table[0x0220] =
{0, 10, clif_parse_ReplyPartyInvite, }, // 0x00ff
{0, 2, clif_parse_LeaveParty, }, // 0x0100
{0, 6, nullptr, }, // 0x0101
- {0, 6, clif_parse_PartyChangeOpt0, }, // 0x0102
+ {0, 6, clif_parse_PartyChangeOption, }, // 0x0102
{0, 30, clif_parse_RemovePartyMember, }, // 0x0103
{0, 79, nullptr, }, // 0x0104
{0, 31, nullptr, }, // 0x0105
diff --git a/src/map/clif.hpp b/src/map/clif.hpp
index 24f4b80..2242949 100644
--- a/src/map/clif.hpp
+++ b/src/map/clif.hpp
@@ -52,7 +52,6 @@ int clif_charselectok(BlockId);
int clif_dropflooritem(dumb_ptr<flooritem_data>);
int clif_clearflooritem(dumb_ptr<flooritem_data>, Session *);
int clif_clearchar(dumb_ptr<block_list>, BeingRemoveWhy); // area or fd
-int clif_clearchar_delay(tick_t, dumb_ptr<block_list>, BeingRemoveWhy);
void clif_clearchar_id(BlockId, BeingRemoveWhy, Session *);
int clif_spawnpc(dumb_ptr<map_session_data>); //area
int clif_spawnnpc(dumb_ptr<npc_data>); // area
@@ -131,8 +130,6 @@ void clif_pcoutsight(dumb_ptr<block_list>, dumb_ptr<map_session_data>);
void clif_mobinsight(dumb_ptr<block_list>, dumb_ptr<mob_data>);
void clif_moboutsight(dumb_ptr<block_list>, dumb_ptr<mob_data>);
-int clif_skillinfo(dumb_ptr<map_session_data> sd, SkillID skillid, int type,
- int range);
void clif_skillinfoblock(dumb_ptr<map_session_data> sd);
int clif_skillup(dumb_ptr<map_session_data> sd, SkillID skill_num);
@@ -152,8 +149,6 @@ void clif_wis_end(Session *s, int flag);
void clif_itemlist(dumb_ptr<map_session_data> sd);
void clif_equiplist(dumb_ptr<map_session_data> sd);
-int clif_mvp_effect(dumb_ptr<map_session_data> sd);
-
int clif_movetoattack(dumb_ptr<map_session_data> sd, dumb_ptr<block_list> bl);
// party
diff --git a/src/map/npc.cpp b/src/map/npc.cpp
index 90ac917..cd80cdf 100644
--- a/src/map/npc.cpp
+++ b/src/map/npc.cpp
@@ -199,27 +199,6 @@ int npc_delete(dumb_ptr<npc_data> nd)
return 0;
}
-void npc_timer_event(NpcEvent eventname)
-{
- P<struct event_data> ev = TRY_UNWRAP(ev_db.search(eventname),
- {
- PRINTF("npc_event: event not found [%s]\n"_fmt,
- eventname);
- return;
- });
-
- dumb_ptr<npc_data_script> nd;
-
- if ((nd = ev->nd) == nullptr)
- {
- PRINTF("npc_event: event not found [%s]\n"_fmt,
- eventname);
- return;
- }
-
- run_script(ScriptPointer(borrow(*nd->scr.script), ev->pos), nd->bl_id, nd->bl_id);
-}
-
/*==========================================
* 全てのNPCのOn*イベント実行
*------------------------------------------
diff --git a/src/map/npc.hpp b/src/map/npc.hpp
index cb42dbd..e62faf2 100644
--- a/src/map/npc.hpp
+++ b/src/map/npc.hpp
@@ -44,7 +44,6 @@ constexpr Species INVISIBLE_CLASS = wrap<Species>(32767);
int npc_event_dequeue(dumb_ptr<map_session_data> sd);
int npc_event(dumb_ptr<map_session_data> sd, NpcEvent npcname, int);
-void npc_timer_event(NpcEvent eventname); // Added by RoVeRT
int npc_command(dumb_ptr<map_session_data> sd, NpcName npcname, XString command);
int npc_touch_areanpc(dumb_ptr<map_session_data>, Borrowed<map_local>, int, int);
int npc_click(dumb_ptr<map_session_data>, BlockId);
diff --git a/src/map/pc.cpp b/src/map/pc.cpp
index 95bdb8d..468bc2d 100644
--- a/src/map/pc.cpp
+++ b/src/map/pc.cpp
@@ -606,7 +606,7 @@ int pc_isequip(dumb_ptr<map_session_data> sd, IOff0 n)
* char鯖から送られてきたステータスを設定
*------------------------------------------
*/
-int pc_authok(AccountId id, int login_id2, TimeT connect_until_time,
+int pc_authok(AccountId id, int login_id2,
short tmw_version, const CharKey *st_key, const CharData *st_data)
{
dumb_ptr<map_session_data> sd = nullptr;
@@ -760,15 +760,6 @@ int pc_authok(AccountId id, int login_id2, TimeT connect_until_time,
sd->packet_flood_reset_due = TimeT();
sd->packet_flood_in = 0;
- // message of the limited time of the account
- if (connect_until_time)
- {
- timestamp_seconds_buffer buffer;
- stamp_time(buffer, &connect_until_time);
- AString tmpstr = STRPRINTF("Your account time limit is: %s"_fmt, buffer);
-
- clif_wis_message(sd->sess, wisp_server_name, tmpstr);
- }
pc_calcstatus(sd, 1);
return 0;
@@ -2530,72 +2521,6 @@ void pc_touch_all_relevant_npcs(dumb_ptr<map_session_data> sd)
sd->areanpc_id = BlockId();
}
-/*==========================================
- *
- *------------------------------------------
- */
-int pc_movepos(dumb_ptr<map_session_data> sd, int dst_x, int dst_y)
-{
- int moveblock;
- int dx, dy;
-
- struct walkpath_data wpd;
-
- nullpo_retz(sd);
-
- if (path_search(&wpd, sd->bl_m, sd->bl_x, sd->bl_y, dst_x, dst_y, 0))
- return 1;
-
- sd->dir = sd->head_dir = map_calc_dir(sd, dst_x, dst_y);
-
- dx = dst_x - sd->bl_x;
- dy = dst_y - sd->bl_y;
-
- moveblock = (sd->bl_x / BLOCK_SIZE != dst_x / BLOCK_SIZE
- || sd->bl_y / BLOCK_SIZE != dst_y / BLOCK_SIZE);
-
- map_foreachinmovearea(std::bind(clif_pcoutsight, ph::_1, sd),
- sd->bl_m,
- sd->bl_x - AREA_SIZE, sd->bl_y - AREA_SIZE,
- sd->bl_x + AREA_SIZE, sd->bl_y + AREA_SIZE,
- dx, dy,
- BL::NUL);
-
- if (moveblock)
- map_delblock(sd);
- sd->bl_x = dst_x;
- sd->bl_y = dst_y;
- if (moveblock)
- map_addblock(sd);
-
- map_foreachinmovearea(std::bind(clif_pcinsight, ph::_1, sd),
- sd->bl_m,
- sd->bl_x - AREA_SIZE, sd->bl_y - AREA_SIZE,
- sd->bl_x + AREA_SIZE, sd->bl_y + AREA_SIZE,
- -dx, -dy,
- BL::NUL);
-
- if (sd->status.party_id)
- { // パーティのHP情報通知検査
- Option<PartyPair> p = party_search(sd->status.party_id);
- if (p.is_some())
- {
- int flag = 0;
- map_foreachinmovearea(std::bind(party_send_hp_check, ph::_1, sd->status.party_id, &flag),
- sd->bl_m,
- sd->bl_x - AREA_SIZE, sd->bl_y - AREA_SIZE,
- sd->bl_x + AREA_SIZE, sd->bl_y + AREA_SIZE,
- -dx, -dy,
- BL::PC);
- if (flag)
- sd->party_hp = -1;
- }
- }
-
- pc_touch_all_relevant_npcs(sd);
- return 0;
-}
-
//
// 武器戦闘
//
@@ -3146,94 +3071,6 @@ int pc_skillup(dumb_ptr<map_session_data> sd, SkillID skill_num)
}
/*==========================================
- * /resetlvl
- *------------------------------------------
- */
-int pc_resetlvl(dumb_ptr<map_session_data> sd, int type)
-{
- nullpo_retz(sd);
-
- for (SkillID i : erange(SkillID(1), MAX_SKILL))
- {
- sd->status.skill[i].lv = 0;
- }
-
- if (type == 1)
- {
- sd->status.skill_point = 0;
- sd->status.base_level = 1;
- sd->status.job_level = 1;
- sd->status.base_exp = 0;
- sd->status.job_exp = 0;
- sd->status.option = Opt0::ZERO;
-
- for (ATTR attr : ATTRs)
- sd->status.attrs[attr] = 1;
- }
-
- if (type == 2)
- {
- sd->status.skill_point = 0;
- sd->status.base_level = 1;
- sd->status.job_level = 1;
- sd->status.base_exp = 0;
- sd->status.job_exp = 0;
- }
- if (type == 3)
- {
- sd->status.base_level = 1;
- sd->status.base_exp = 0;
- }
- if (type == 4)
- {
- sd->status.job_level = 1;
- sd->status.job_exp = 0;
- }
-
- clif_updatestatus(sd, SP::STATUSPOINT);
- clif_updatestatus(sd, SP::STR);
- clif_updatestatus(sd, SP::AGI);
- clif_updatestatus(sd, SP::VIT);
- clif_updatestatus(sd, SP::INT);
- clif_updatestatus(sd, SP::DEX);
- clif_updatestatus(sd, SP::LUK);
- clif_updatestatus(sd, SP::BASELEVEL);
- clif_updatestatus(sd, SP::JOBLEVEL);
- clif_updatestatus(sd, SP::STATUSPOINT);
- clif_updatestatus(sd, SP::NEXTBASEEXP);
- clif_updatestatus(sd, SP::NEXTJOBEXP);
- clif_updatestatus(sd, SP::SKILLPOINT);
-
- clif_updatestatus(sd, SP::USTR); // Updates needed stat points - Valaris
- clif_updatestatus(sd, SP::UAGI);
- clif_updatestatus(sd, SP::UVIT);
- clif_updatestatus(sd, SP::UINT);
- clif_updatestatus(sd, SP::UDEX);
- clif_updatestatus(sd, SP::ULUK); // End Addition
-
- for (EQUIP i : EQUIPs)
- {
- // unequip items that can't be equipped by base 1 [Valaris]
- IOff0 *idx = &sd->equip_index_maybe[i];
- if ((*idx).ok())
- {
- if (!pc_isequip(sd, *idx))
- {
- pc_unequipitem(sd, *idx, CalcStatus::LATER);
- *idx = IOff0::from(-1);
- }
- }
- }
-
- clif_skillinfoblock(sd);
- pc_calcstatus(sd, 0);
-
- MAP_LOG_STATS(sd, "STATRESET"_fmt);
-
- return 0;
-}
-
-/*==========================================
* /resetstate
*------------------------------------------
*/
@@ -3943,21 +3780,6 @@ int pc_changelook(dumb_ptr<map_session_data> sd, LOOK type, int val)
}
/*==========================================
- * 付属品(鷹,ペコ,カート)設定
- *------------------------------------------
- */
-int pc_setoption(dumb_ptr<map_session_data> sd, Opt0 type)
-{
- nullpo_retz(sd);
-
- sd->status.option = type;
- clif_changeoption(sd);
- pc_calcstatus(sd, 0);
-
- return 0;
-}
-
-/*==========================================
* script用変数の値を読む
*------------------------------------------
*/
diff --git a/src/map/pc.hpp b/src/map/pc.hpp
index 9795443..c889e44 100644
--- a/src/map/pc.hpp
+++ b/src/map/pc.hpp
@@ -77,7 +77,7 @@ int pc_counttargeted(dumb_ptr<map_session_data> sd, dumb_ptr<block_list> src,
int pc_setrestartvalue(dumb_ptr<map_session_data> sd, int type);
void pc_makesavestatus(dumb_ptr<map_session_data>);
int pc_setnewpc(dumb_ptr<map_session_data>, AccountId, CharId, int, uint32_t /*tick_t*/, SEX);
-int pc_authok(AccountId, int, TimeT, short tmw_version, const CharKey *, const CharData *);
+int pc_authok(AccountId, int, short tmw_version, const CharKey *, const CharData *);
int pc_authfail(AccountId accid);
EPOS pc_equippoint(dumb_ptr<map_session_data> sd, IOff0 n);
@@ -87,7 +87,6 @@ IOff0 pc_checkequip(dumb_ptr<map_session_data> sd, EPOS pos);
int pc_walktoxy(dumb_ptr<map_session_data>, int, int);
int pc_stop_walking(dumb_ptr<map_session_data>, int);
-int pc_movepos(dumb_ptr<map_session_data>, int, int);
int pc_setpos(dumb_ptr<map_session_data>, MapName, int, int, BeingRemoveWhy);
void pc_setsavepoint(dumb_ptr<map_session_data>, MapName, int, int);
int pc_randomwarp(dumb_ptr<map_session_data> sd, BeingRemoveWhy type);
@@ -127,7 +126,6 @@ int pc_need_status_point(dumb_ptr<map_session_data>, SP);
int pc_statusup(dumb_ptr<map_session_data>, SP);
int pc_statusup2(dumb_ptr<map_session_data>, SP, int);
int pc_skillup(dumb_ptr<map_session_data>, SkillID);
-int pc_resetlvl(dumb_ptr<map_session_data>, int type);
int pc_resetstate(dumb_ptr<map_session_data>);
int pc_resetskill(dumb_ptr<map_session_data>);
int pc_equipitem(dumb_ptr<map_session_data>, IOff0, EPOS);
@@ -139,7 +137,6 @@ int pc_damage(dumb_ptr<block_list>, dumb_ptr<map_session_data>, int);
int pc_heal(dumb_ptr<map_session_data>, int, int);
int pc_itemheal(dumb_ptr<map_session_data> sd, int hp, int sp);
int pc_percentheal(dumb_ptr<map_session_data> sd, int, int);
-int pc_setoption(dumb_ptr<map_session_data>, Opt0);
int pc_changelook(dumb_ptr<map_session_data>, LOOK, int);
int pc_readparam(dumb_ptr<map_session_data>, SP);
diff --git a/src/mmo/skill.t.hpp b/src/mmo/skill.t.hpp
index d0e3926..21e4059 100644
--- a/src/mmo/skill.t.hpp
+++ b/src/mmo/skill.t.hpp
@@ -77,6 +77,9 @@ enum class SkillID : uint16_t
// TODO: Remove these!
NEGATIVE = 0xffff,
ZERO = 0x0000,
+ // this is probably the remains of the 'basic' skill,
+ // which has since been partially split into emote, trade, and party,
+ // but the confusion is caused by the fact that it also covered attacks.
ONE = 0x0001,
// Basic skills.
diff --git a/tools/protocol.py b/tools/protocol.py
index 3c33b2c..5a91555 100755
--- a/tools/protocol.py
+++ b/tools/protocol.py
@@ -27,6 +27,33 @@ import itertools
import os
from pipes import quote
from posixpath import relpath
+from weakref import ref as wr
+
+try:
+ unicode
+except NameError:
+ unicode = str
+
+## For various reasons this is all one file, so let's navigate with a
+##
+## Table of Contents
+##
+## TOC_HEAD
+## TOC_TYPES
+## TOC_EVENT
+## TOC_CHAN
+## TOC_DATA
+## TOC_GENTYPE
+## TOC_CLIENT
+## TOC_LOGINCHAR
+## TOC_CHARMAP
+## TOC_INTERMAP
+## TOC_MISC
+## TOC_LOGINADMIN
+## TOC_NEW
+## TOC_DRAWING
+## TOC_MAIN
+##
# The following code should be relatively easy to understand, but please
# keep your sanity fastened and your arms and legs inside at all times.
@@ -34,6 +61,9 @@ from posixpath import relpath
# important note: all numbers in this file will make a lot more sense in
# decimal, but they're written in hex.
+
+# TOC_HEAD
+
generated = '// This is a generated file, edit %s instead\n' % __file__
copyright = '''// {filename} - {description}
@@ -69,9 +99,9 @@ class OpenWrite(object):
if ty is not None:
return
frag = '''
- if cmp {0}.tmp {0}.old
+ if cmp -s {0}.tmp {0}.old
then
- echo Unchanged: {0}
+ : echo Unchanged: {0}
rm {0}.tmp
mv {0}.old {0}
else
@@ -82,6 +112,194 @@ class OpenWrite(object):
'''.format(quote(self.filename))
os.system(frag)
+
+# TOC_
+
+def gvq(s):
+ return u'"%s"' % s.replace(u'"', u'\\"')
+
+def gva(d):
+ if d:
+ return u' [%s]' % u', '.join(u'%s=%s' % (ak, gvq(av)) for (ak, av) in sorted(d.items()))
+ return u''
+
+class Attributes(object):
+ __slots__ = (u'_attributes')
+
+ def __init__(self):
+ self._attributes = {}
+
+ def __getitem__(self, k):
+ assert isinstance(k, unicode)
+ return self._attributes[k]
+
+ def __setitem__(self, k, v):
+ assert isinstance(k, unicode)
+ assert isinstance(v, unicode)
+ self._attributes[k] = v
+
+ def __delitem__(self, k):
+ assert isinstance(k, unicode)
+ del self._attributes[k]
+
+ def merge(self, *others):
+ for other in others:
+ assert self.__class__ == other.__class__
+ # if an attribute is present on multiple inputs, prefer
+ # the last one. This is not necessarily what you want, though.
+ self._attributes.update(other._attributes)
+
+class Graph(Attributes):
+ __slots__ = (u'default_vertex', u'default_edge', u'_vertices', u'_edges', u'_vertex_lookup')
+
+ def __init__(self):
+ Attributes.__init__(self)
+ self.default_vertex = Attributes()
+ self.default_edge = Attributes()
+ self._vertices = set()
+ self._edges = {}
+ self._vertex_lookup = {}
+
+ def vertex(self, name, insert=True):
+ assert isinstance(name, unicode)
+ vert = self._vertex_lookup.get(name)
+ if insert and vert is None:
+ vert = Vertex(name)
+ self._vertex_lookup[name] = vert
+ self._vertices.add(vert)
+ return vert
+
+ def _fix_vertex(self, v, insert=True):
+ if isinstance(v, Vertex):
+ return v
+ return self.vertex(v, insert)
+
+ def edge(self, v1, v2, insert=True):
+ v1 = self._fix_vertex(v1, insert)
+ if v1 is None:
+ return None
+ v2 = self._fix_vertex(v2, insert)
+ if v2 is None:
+ return None
+ ek = (v1, v2)
+ edge = self._edges.get(ek)
+ if insert and edge is None:
+ edge = Edge(v1, v2)
+ v1._post.add(wr(v2))
+ v2._pre.add(wr(v1))
+ self._edges[ek] = edge
+ return edge
+
+ def del_edge(self, v1, v2):
+ edge = self.edge(v1, v2, False)
+ if edge is None:
+ return
+ v1 = edge._from
+ v2 = edge._to
+ ek = (v1, v2)
+ v1._post.remove(wr(v2))
+ v2._pre.remove(wr(v1))
+ del self._edges[ek]
+
+ def del_vertex(self, v):
+ v = self._fix_vertex(v, False)
+ if v is None:
+ return
+ pre = list(v._pre)
+ for vp in pre:
+ vp = vp()
+ self.del_edge(vp, v)
+ post = list(v._post)
+ for vp in post:
+ vp = vp()
+ self.del_edge(v, vp)
+ del self._vertex_lookup[v._key]
+ self._vertices.remove(v)
+
+ def splice_out_vertex(self, v):
+ v = self._fix_vertex(v, False)
+ if v is None:
+ return
+ self.del_edge(v, v)
+ for vp in v._pre:
+ vp = vp()
+ ep = self.edge(vp, v, False)
+ for vn in v._post:
+ vn = vn()
+ en = self.edge(v, vn, False)
+ self.edge(vp, vn).merge(ep, en)
+ self.del_vertex(v)
+
+ def dot(self, out, close):
+ if close:
+ with out:
+ self.dot(out, False)
+ return
+
+ def p(*args):
+ for x in args:
+ out.write(unicode(x))
+ out.write(u'\n')
+ p(u'digraph')
+ p(u'{')
+ for ak, av in sorted(self._attributes.items()):
+ p(u' ', ak, u'=', gvq(av), u';')
+ for ak, av in sorted(self.default_vertex._attributes.items()):
+ p(u' node [', ak, u'=', gvq(av), u'];')
+ for ak, av in sorted(self.default_edge._attributes.items()):
+ p(u' edge [', ak, u'=', gvq(av), u'];')
+ for n in sorted(self._vertices):
+ p(u' ', n)
+ for _, e in sorted(self._edges.items()):
+ p(u' ', e)
+ p(u'}')
+
+ def dot_str(self):
+ from io import StringIO
+ out = StringIO()
+ self.dot(out, False)
+ return out.getvalue()
+
+ def dot_file(self, name):
+ with open(name, u'w') as f:
+ self.dot(f, False)
+
+ def preview(self, block):
+ from subprocess import Popen, PIPE
+ proc = Popen([u'dot', u'-Txlib', u'/dev/stdin'], stdin=PIPE, universal_newlines=True)
+ self.dot(proc.stdin, True)
+ if block:
+ proc.wait()
+
+class Vertex(Attributes):
+ __slots__ = (u'_key', u'_post', u'_pre', u'__weakref__')
+
+ def __init__(self, key):
+ Attributes.__init__(self)
+ self._key = key
+ self._post = set()
+ self._pre = set()
+
+ def __str__(self):
+ return u'%s%s;' % (gvq(self._key), gva(self._attributes))
+
+ def __lt__(self, other):
+ return self._key < other._key
+
+class Edge(Attributes):
+ __slots__ = (u'_from', u'_to')
+
+ def __init__(self, f, t):
+ Attributes.__init__(self)
+ self._from = f
+ self._to = t
+
+ def __str__(self):
+ return u'%s -> %s%s;' % (gvq(self._from._key), gvq(self._to._key), gva(self._attributes))
+
+
+# TOC_TYPES
+
class LowType(object):
__slots__ = ('includes')
@@ -95,6 +313,10 @@ class NativeType(LowType):
self.name = name
self.includes = frozenset({include}) if include else frozenset()
+ def __repr__(self):
+ return 'NativeType(%r)' % (self.name)
+
+
def a_tag(self):
return self.name
@@ -105,6 +327,10 @@ class NetworkType(LowType):
self.name = name
self.includes = frozenset({include}) if include else frozenset()
+ def __repr__(self):
+ return 'NetworkType(%r)' % (self.name)
+
+
def e_tag(self):
return self.name
@@ -129,6 +355,10 @@ class NeutralType(Type):
return 'NeutralType(%r)' % (self.name)
+ def __repr__(self):
+ return 'NeutralType(%r)' % (self.name)
+
+
def native_tag(self):
return self.name
@@ -180,6 +410,10 @@ class StringType(Type):
return 'StringType(%r)' % (self.native)
+ def __repr__(self):
+ return 'StringType(%r)' % self.native
+
+
def native_tag(self):
return self.native.a_tag()
@@ -202,6 +436,10 @@ class ProvidedType(Type):
return 'ProvidedType(%r, %r)' % (self.native, self.network)
+ def __repr__(self):
+ return 'ProvidedType(native=%r, network=%r)' % (self.native, self.network)
+
+
def native_tag(self):
return self.native.a_tag()
@@ -221,6 +459,10 @@ class EnumType(Type):
return 'EnumType(%r, %r)' % (self.native, self.under)
+ def __repr__(self):
+ return 'EnumType(%r, %r)' % (self.native, self.under)
+
+
def native_tag(self):
return self.native.a_tag()
@@ -270,6 +512,10 @@ class WrappedType(Type):
return 'WrappedType(%r, %r)' % (self.native, self.under)
+ def __repr__(self):
+ return 'WrappedType(%r, %r)' % (self.native, self.under)
+
+
def native_tag(self):
return self.native.a_tag()
@@ -351,6 +597,10 @@ class StructType(Type):
return '<StructType(%r) with %d fields>' % (self.name, len(self.fields))
+ def __repr__(self):
+ return '<StructType(id=%r, name=%r, size=%r, ctor=%r) with %d fields>' % (self.id, self.name, self.size, self.ctor, len(self.fields))
+
+
def native_tag(self):
return self.name
@@ -451,6 +701,10 @@ class PartialStructType(Type):
return '<PartialStructType(%r) with %d fields>' % (self.native, len(self.body))
+ def __repr__(self):
+ return '<PartialStructType(native=%r) with %d pieces of a body>' % (self.native, len(self.body))
+
+
def native_tag(self):
return self.native.a_tag()
@@ -554,6 +808,47 @@ class InvArrayType(Type):
return 'NetArray<%s, %s>' % (self.element.network_tag(), self.count)
+# TOC_EVENT
+# special event origins
+class SpecialEventOrigin(object):
+ __slots__ = ('name')
+
+ def __init__(self, name):
+ self.name = name
+
+ def __repr__(self):
+ return self.name
+
+ADMIN = SpecialEventOrigin('ADMIN')
+BOOT = SpecialEventOrigin('BOOT')
+FINISH = SpecialEventOrigin('FINISH')
+GM = SpecialEventOrigin('GM')
+HUMAN = SpecialEventOrigin('HUMAN')
+IDLE = SpecialEventOrigin('IDLE')
+MAGIC = SpecialEventOrigin('MAGIC')
+NOTHING = SpecialEventOrigin('NOTHING')
+OTHER = SpecialEventOrigin('OTHER')
+PRETTY = SpecialEventOrigin('PRETTY')
+SCRIPT = SpecialEventOrigin('SCRIPT')
+TIMER = SpecialEventOrigin('TIMER')
+
+def event_name(p):
+ if isinstance(p, SpecialEventOrigin):
+ return p.name
+ if isinstance(p, int):
+ return 'packet 0x%04x' % p
+ assert False, 'Unknown event: %r' % p
+
+def event_link(p):
+ if isinstance(p, SpecialEventOrigin):
+ return p.name
+ if isinstance(p, int):
+ return '[[Packet 0x%04x]]' % p
+ assert False, 'Unknown event: %r' % p
+
+
+# TOC_CHAN
+
class Include(object):
__slots__ = ('path', '_types')
@@ -565,6 +860,19 @@ class Include(object):
return '<Include(%r) with %d types>' % (self.path, len(self._types))
+ def testcase(self, outdir):
+ basename = os.path.basename(self.path.strip('<">'))
+ root = os.path.splitext(basename)[0]
+ filename = 'include_%s_test.cpp' % root.replace('.', '_')
+ desc = 'testsuite for protocol includes'
+ poison = relpath('src/poison.hpp', outdir)
+ with OpenWrite(os.path.join(outdir, filename)) as f:
+ f.write(self.pp(0))
+ f.write(copyright.format(filename=filename, description=desc))
+ f.write('\n')
+ f.write('#include "%s"\n\nnamespace tmwa\n{\n' % poison)
+
+
def pp(self, n):
return '#%*sinclude %s\n' % (n, '', self.path)
@@ -583,15 +891,103 @@ class Include(object):
self._types.append(ty)
return ty
+class BasePacket(object):
+ __slots__ = ('id', 'name', 'define', 'pre', 'post', 'xpost', 'desc')
+
+ def __init__(self, **kwargs):
+ for s in BasePacket.__slots__:
+ setattr(self, s, kwargs[s])
+ del kwargs[s]
+ assert not kwargs, 'Unknown kwargs: %s' % repr(kwargs)
+
+ def base_repr_fragment(self):
+ return ', '.join('%s=%r' % (s, getattr(self, s)) for s in BasePacket.__slots__)
+
+ def comment_doc(self):
+ id = self.id
+ name = self.name
+ define = self.define
+ desc = self.desc
+ pre = self.pre
+ post = self.post
+
+ comment = 'Packet 0x%04x: "%s"\n' % (id, name)
+ if define:
+ comment += 'define: ' + define + '\n'
+ if True:
+ prestr = ', '.join(event_name(x) for x in pre) or 'none'
+ poststr = ', '.join(event_name(x) for x in post) or 'none'
+ comment += 'pre: ' + prestr + '\n'
+ comment += 'post: ' + poststr + '\n'
+ comment += desc
+ comment = ''.join('// ' + c + '\n' if c else '//\n' for c in comment.split('\n'))
+ return comment
+
+ def wiki_doc(self):
+ # TODO do markdown magic
+ id = self.id
+ name = self.name
+ desc = self.desc
+ pre = self.pre
+ post = self.post
+ xpost = self.xpost
+
+ wiki = 'Packet 0x%04x: "%s"\n\n' % (id, name)
+ if True:
+ prestr = ', '.join(event_link(x) for x in pre) or 'none'
+ poststr = ', '.join(event_link(x) for x in fix_sort(post + xpost)) or 'none'
+ wiki += 'pre: ' + prestr + '\n\n'
+ wiki += 'post: ' + poststr + '\n\n'
+ wiki += desc
+ wiki += '\n\n'
+ wiki += '![](packets-around-0x%04x.png)\n' % id
+ return wiki
+
+ def pre_set(self, d, n=float('inf'), accum=None):
+ if accum is None:
+ accum = set()
+ if self.id in accum:
+ return accum
+ accum.add(self.id)
+ if not n:
+ return accum
+ for p in self.pre:
+ # ignore specials
+ if isinstance(p, SpecialEventOrigin):
+ continue
+ # ignore weak links
+ if self.id not in d[p].post:
+ continue
+ d[p].pre_set(d, n - 1 + (len([z for z in self.pre if isinstance(z, SpecialEventOrigin) or self.id in d[z].post]) == 1), accum)
+ return accum
+
+ def post_set(self, d, n=float('inf'), accum=None):
+ if accum is None:
+ accum = set()
+ if self.id in accum:
+ return accum
+ accum.add(self.id)
+ if not n:
+ return accum
+ for p in self.post:
+ # ignore specials
+ if isinstance(p, SpecialEventOrigin):
+ continue
+ # weak links are in xpost
+
+ d[p].post_set(d, n - 1 + (len(self.post) == 1), accum)
+ return accum
-class FixedPacket(object):
+
+class FixedPacket(BasePacket):
__slots__ = ('fixed_struct')
- def __init__(self, fixed_struct):
+ def __init__(self, fixed_struct, **kwargs):
+ BasePacket.__init__(self, **kwargs)
self.fixed_struct = fixed_struct
def __repr__(self):
- return 'FixedPacket(%r)' % (self.fixed_struct)
+ return 'FixedPacket(%r, %s)' % (self.fixed_struct, self.base_repr_fragment())
def add_headers_to(self, headers):
@@ -602,6 +998,7 @@ class FixedPacket(object):
fwd.write('\n')
def dump_native(self, f):
+ f.write(self.comment_doc())
self.fixed_struct.dump_native(f)
f.write('\n')
@@ -613,15 +1010,16 @@ class FixedPacket(object):
self.fixed_struct.dump_convert(f)
f.write('\n')
-class VarPacket(object):
+class VarPacket(BasePacket):
__slots__ = ('head_struct', 'repeat_struct')
- def __init__(self, head_struct, repeat_struct):
+ def __init__(self, head_struct, repeat_struct, **kwargs):
+ BasePacket.__init__(self, **kwargs)
self.head_struct = head_struct
self.repeat_struct = repeat_struct
def __repr__(self):
- return 'VarPacket(%r, %r)' % (self.head_struct, self.repeat_struct)
+ return 'VarPacket(%r, %r, %s)' % (self.head_struct, self.repeat_struct, self.base_repr_fragment())
def add_headers_to(self, headers):
@@ -634,6 +1032,7 @@ class VarPacket(object):
fwd.write('\n')
def dump_native(self, f):
+ f.write(self.comment_doc())
self.head_struct.dump_native(f)
self.repeat_struct.dump_native(f)
f.write('\n')
@@ -648,40 +1047,76 @@ class VarPacket(object):
self.repeat_struct.dump_convert(f)
f.write('\n')
-def packet(id, name,
+def sanitize_line(line, n):
+ if not line:
+ return line
+ m = len(line) - len(line.lstrip(' '))
+ assert m >= n, 'not %d: %r' % (n, line)
+ return line[n:]
+
+def sanitize_multiline(text):
+ text = text.strip('\n').rstrip(' ')
+ assert '\r' not in text
+ assert '\t' not in text
+ n = len(text) - len(text.lstrip(' '))
+ return '\n'.join(sanitize_line(l, n) for l in text.split('\n'))
+
+def packet(id, name, define=None,
fixed=None, fixed_size=None,
payload=None, payload_size=None,
head=None, head_size=None,
repeat=None, repeat_size=None,
option=None, option_size=None,
+ pre=None, post=None, xpost=None, desc=None,
):
assert (fixed is None) <= (fixed_size is None)
assert (payload is None) <= (payload_size is None)
assert (head is None) <= (head_size is None)
assert (repeat is None) <= (repeat_size is None)
assert (option is None) <= (option_size is None)
+ assert (pre is not None) and (post is not None) and desc.strip()
+ if xpost is None:
+ xpost = []
+
+ desc = sanitize_multiline(desc)
if fixed is not None:
assert not head and not repeat and not option and not payload
return FixedPacket(
- StructType(id, 'Packet_Fixed<0x%04x>' % id, fixed, fixed_size))
+ StructType(id, 'Packet_Fixed<0x%04x>' % id, fixed, fixed_size),
+ id=id, name=name, define=define, pre=pre, post=post, xpost=xpost, desc=desc,
+ )
elif payload is not None:
assert not head and not repeat and not option
return FixedPacket(
- StructType(id, 'Packet_Payload<0x%04x>' % id, payload, payload_size))
+ StructType(id, 'Packet_Payload<0x%04x>' % id, payload, payload_size),
+ id=id, name=name, define=define, pre=pre, post=post, xpost=xpost, desc=desc,
+ )
else:
assert head
if option:
+ assert not repeat
return VarPacket(
StructType(id, 'Packet_Head<0x%04x>' % id, head, head_size),
- StructType(id, 'Packet_Option<0x%04x>' % id, option, option_size))
+ StructType(id, 'Packet_Option<0x%04x>' % id, option, option_size),
+ id=id, name=name, define=define, pre=pre, post=post, xpost=xpost, desc=desc,
+ )
else:
assert repeat
return VarPacket(
StructType(id, 'Packet_Head<0x%04x>' % id, head, head_size),
- StructType(id, 'Packet_Repeat<0x%04x>' % id, repeat, repeat_size))
-
-
+ StructType(id, 'Packet_Repeat<0x%04x>' % id, repeat, repeat_size),
+ id=id, name=name, define=define, pre=pre, post=post, xpost=xpost, desc=desc,
+ )
+
+
+# TODO this whole idea is wrong
+# in particular, 'any'.
+# instead, have just one channel for all packets, but store send/recv/type
+# with each packet.
+# Then during codegen, emit:
+# #if PACKET_LOGIN || PACKET_CHAR || PACKET_MAP || PACKET_ADMIN || PACKET_USER
+# (for an 'all' packet) around the send/recv portions separately
class Channel(object):
__slots__ = ('server', 'client', 'packets')
@@ -691,7 +1126,11 @@ class Channel(object):
self.packets = []
def __repr__(self):
- return '<Channel(%r, %r) with %d packets>' % (self.server, self.client, len(self.packets))
+ return '<Channel(%r, %r) with %d packets>' % (
+ self.server,
+ self.client,
+ len(self.packets),
+ )
def x(self, id, name, **kwargs):
@@ -761,8 +1200,11 @@ class Context(object):
self._types = []
def __repr__(self):
- return '<Context with %d includes, %d channels, %d types>' % (
- len(self._includes), len(self._channels), len(self._types),
+ return '<Context(%r) with %d _includes, %d _channels, %d _types>' % (
+ self.outdir,
+ len(self._includes),
+ len(self._channels),
+ len(self._types),
)
@@ -910,6 +1352,8 @@ class Context(object):
return rv
+# TOC_DATA
+
def build_context():
## setup
@@ -1040,6 +1484,7 @@ def build_context():
interval_t = timer_th.native('interval_t')
## generated types
+ # TOC_GENTYPE
u8 = ctx.provided(uint8_t, Byte)
u16 = ctx.provided(uint16_t, Little16)
@@ -1388,18 +1833,60 @@ def build_context():
# sized if all of its members are fixed sized.
#
# The element type of an array shall not be of implicit size.
- # The element type of an array *may* be of explicit size, in which
+ # The element type of an array *may* be of explicit size, in which case
+ # the layout is like option 1 below (see below for discussion).
#
# A string is just an array of characters, except that it may be padded
# with '\0' bytes even when it is sized.
# A map is just an array of two-element structs (key, value)
# However, strings and maps have custom classes used to represent them
- # on the sender and receiver (earray also has this).
+ # on the sender and receiver (earray also has this (but maybe shouldn't?)).
+ # Ytf is tmwa still using fixed-size arrays for this crap anyways?
+ # It probably should be a map in this case.
#
# It would probably be a good idea if everybody parsed network input as
# padded with '\0's if it is too short, and ignored the extra if it is
# too long. However, there are efficiency concerns with this, since we
- # don't want to branch everywhere.
+ # don't want to branch everywhere. But parsing in reverse might work ...
+
+ # possible array layouts:
+ # 1:
+ # | array1 size | array1 data | array2 size | array2 data |
+ # Advantage: linear writing (except final size?).
+ # Disadvantage: linear reading.
+ # This is what I originally imagined, but ...
+ # 2:
+ # | array1 size/offset | array2 size/offset | array1 data | array2 data |
+ # Advantage: random-access reading.
+ # Disadvantage: slightly larger packets, more complicated writing?.
+ # TODO verify whether you really need offset or not?
+ # TODO think about array-of-array case, it's complicated.
+ # | array0 size | array1 size | array 0.0 size | array 0.1 size | array 1.0 size | array 1.1 size | element 0.0.0 | element 0.0.1 | element 0.1.0 | element 0.1.1 | element 1.0.0 | element 1.0.1 | element 1.1.0 | element 1.1.1 |
+ # data a=(b=[d=[h=0.0.0, i=0.0.1], e=[j=0.1.0, k=0.1.1]], c=[f=[l=1.0.0, m=1.0.1], g=[n=1.1.0, o=1.1.1]])
+ # I'm not sure how this can work. If I wrote:
+ # def write_a():
+ # write_head_b() # size
+ # write_head_c() # size
+ # write_data_b()
+ # write_data_c()
+ # def write_data_b():
+ # write_head_d()
+ # write_head_e()
+ # write_data_d()
+ # write_data_e()
+ # def write_data_c():
+ # write_head_f()
+ # write_head_g()
+ # write_data_f()
+ # write_data_g()
+ # ... that would yield |s0|s1|s0.0|s0.1|d0.0.0|d0.0.1|d0.1.0|d0.1.1|s1.0|s1.1|d1.0.0|d1.0.1|d1.1.0|d1.1.1|
+ # Can't do random-access writes because you don't know the offset yet.
+ # I would have to do a bunch of 'write depth n' functions.
+ # Maybe this was a bad idea.
+ # And what exactly is the use of random-access reads? We're doing full
+ # translation for all data anyway. It's probably a bad idea for any
+ # packet to ever contain information that you don't look at.
+
login_char = ctx.chan('login', 'char')
login_admin = ctx.chan('login', 'admin')
@@ -1420,23 +1907,43 @@ def build_context():
## legacy packets
+ # TOC_CLIENT
# * user
- char_user.r(0x0061, 'change password request',
+ char_user.r(0x0061, 'change password',
+ define='CMSG_CHAR_PASSWORD_CHANGE',
fixed=[
at(0, u16, 'packet id'),
at(2, account_pass, 'old pass'),
at(26, account_pass, 'new pass'),
],
fixed_size=50,
+ pre=[HUMAN],
+ post=[0x2740],
+ desc='''
+ Sent by a client to the character server to request a password change.
+ ''',
)
- char_user.s(0x0062, 'change password response',
+ char_user.s(0x0062, 'change password result',
+ define='SMSG_CHAR_PASSWORD_RESPONSE',
fixed=[
at(0, u16, 'packet id'),
at(2, u8, 'status'),
],
fixed_size=3,
- )
- login_user.r(0x0063, 'update host',
+ pre=[0x2741],
+ post=[PRETTY],
+ desc='''
+ Sent by the character server with the response of a password change request.
+
+ Status:
+ 0: The account was not found.
+ 1: Success.
+ 2: The old password was incorrect.
+ 3: The new password was too short.
+ ''',
+ )
+ login_user.s(0x0063, 'update host notify',
+ define='SMSG_UPDATE_HOST',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -1444,8 +1951,16 @@ def build_context():
head_size=4,
repeat=[at(0, u8, 'c')],
repeat_size=1,
+ pre=[0x0064],
+ post=[IDLE],
+ desc='''
+ This packet gives the client the location of the update server URL, such as http://tmwdata.org/updates/
+
+ It is only sent if an update host is specified for the server (there is one in the default configuration) and the client identifies as accepting an update host (which all supported clients do).
+ ''',
)
- login_user.r(0x0064, 'login request',
+ login_user.r(0x0064, 'account login',
+ define='CMSG_LOGIN_REGISTER',
fixed=[
at(0, u16, 'packet id'),
at(2, u32, 'unknown'),
@@ -1454,8 +1969,16 @@ def build_context():
at(54, version_2, 'version 2 flags'),
],
fixed_size=55,
+ pre=[HUMAN, 0x7531],
+ post=[0x0063, 0x0069, 0x006a, 0x0081],
+ desc='''
+ Authenticate a client by user/password.
+
+ All clients must now set both defined version 2 flags.
+ ''',
)
- char_user.r(0x0065, 'char-server connection request',
+ char_user.r(0x0065, 'connect char',
+ define='CMSG_CHAR_SERVER_CONNECT',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
@@ -1465,15 +1988,28 @@ def build_context():
at(16, sex, 'sex'),
],
fixed_size=17,
+ pre=[0x0069, 0x0092, 0x00b3],
+ post=[0x006b, 0x006c, 0x2712, 0x2716],
+ desc='''
+ Begin connection to the char server, based on keys the login
+ server gave us.
+ ''',
)
- char_user.r(0x0066, 'select character request',
+ char_user.r(0x0066, 'select character',
+ define='CMSG_CHAR_SELECT',
fixed=[
at(0, u16, 'packet id'),
at(2, u8, 'code'),
],
fixed_size=3,
+ pre=[0x006b],
+ post=[FINISH, 0x0071, 0x0081],
+ desc='''
+ Choose a character to enter the map.
+ ''',
)
- char_user.r(0x0067, 'create character request',
+ char_user.r(0x0067, 'create character',
+ define='CMSG_CHAR_CREATE',
fixed=[
at(0, u16, 'packet id'),
at(2, char_name, 'char name'),
@@ -1483,16 +2019,32 @@ def build_context():
at(35, u16, 'hair style'),
],
fixed_size=37,
+ pre=[0x006b],
+ post=[0x006d, 0x006e],
+ desc='''
+ Create a new character.
+ ''',
)
- char_user.r(0x0068, 'delete character request',
+ char_user.r(0x0068, 'delete character',
+ define='CMSG_CHAR_DELETE',
fixed=[
at(0, u16, 'packet id'),
at(2, char_id, 'char id'),
- at(6, account_email, 'email'),
+ at(6, account_email, 'unused email'),
],
fixed_size=46,
- )
- login_user.r(0x0069, 'login data',
+ pre=[0x006b],
+ post=[0x006f, 0x0070, 0x2afe, 0x2b12, 0x3821, 0x3824, 0x3826],
+ desc='''
+ Delete an existing character.
+
+ There is no authentication on the server besides what has
+ already been performed to create the connection. "Are you sure?"
+ is solely the client's job.
+ ''',
+ )
+ login_user.s(0x0069, 'account login success',
+ define='SMSG_LOGIN_DATA',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -1514,16 +2066,44 @@ def build_context():
at(30, u16, 'is new'),
],
repeat_size=32,
+ pre=[0x0064],
+ post=[0x0065],
+ desc='''
+ Big blob of information available once when you authenticate:
+
+ * dumb session keys
+ * sex and last login
+ * list of char server
+ ''',
)
- login_user.s(0x006a, 'login error',
+ login_user.s(0x006a, 'account login error',
+ define='SMSG_LOGIN_ERROR',
fixed=[
at(0, u16, 'packet id'),
at(2, u8, 'error code'),
at(3, seconds, 'error message'),
],
fixed_size=23,
- )
- char_user.s(0x006b, 'update character list',
+ pre=[0x0064],
+ post=[PRETTY],
+ desc='''
+ Failure to log in.
+
+ Error codes:
+ * 0: unregistered id
+ * 1: incorrect password
+ * 2: expired id (unused?)
+ * 3: rejected from server (unused?)
+ * 4: permanently blocked
+ * 5: client too old (unused?)
+ * 6: temporary ban (date in 'error message' field)
+ * 7: server full
+ * 8: no message
+ * 99: id erased
+ ''',
+ )
+ char_user.s(0x006b, 'connect char success',
+ define='SMSG_CHAR_LOGIN',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -1534,42 +2114,83 @@ def build_context():
at(0, char_select, 'char select'),
],
repeat_size=106,
+ pre=[0x0065, 0x2713],
+ post=[PRETTY],
+ xpost=[0x0066, 0x0067, 0x0068],
+ desc='''
+ List account's characters on this server.
+ ''',
)
- char_user.s(0x006c, 'login error',
+ char_user.s(0x006c, 'connect char error',
+ define='SMSG_CHAR_LOGIN_ERROR',
fixed=[
at(0, u16, 'packet id'),
at(2, u8, 'code'),
],
fixed_size=3,
+ pre=[0x0065, 0x2713],
+ post=[PRETTY],
+ desc='''
+ Refuse connection.
+
+ Status:
+ 0: Overpopulated
+ 0x42: Auth failed
+ ''',
)
- char_user.s(0x006d, 'create character succeeded',
+ char_user.s(0x006d, 'create character success',
+ define='SMSG_CHAR_CREATE_SUCCEEDED',
fixed=[
at(0, u16, 'packet id'),
at(2, char_select, 'char select'),
],
fixed_size=108,
+ pre=[0x0067],
+ post=[PRETTY],
+ desc='''
+ Give information about newly-created character.
+ ''',
)
- char_user.s(0x006e, 'create character failed',
+ char_user.s(0x006e, 'create character error',
+ define='SMSG_CHAR_CREATE_FAILED',
fixed=[
at(0, u16, 'packet id'),
at(2, u8, 'code'),
],
fixed_size=3,
+ pre=[0x0067],
+ post=[PRETTY],
+ desc='''
+ Failure to create a new character.
+ ''',
)
- char_user.s(0x006f, 'delete character succeeded',
+ char_user.s(0x006f, 'delete character success',
+ define='SMSG_CHAR_DELETE_SUCCEEDED',
fixed=[
at(0, u16, 'packet id'),
],
fixed_size=2,
+ pre=[0x0068],
+ post=[PRETTY],
+ desc='''
+ Character successfully deleted.
+ ''',
)
- char_user.s(0x0070, 'delete character failed',
+ char_user.s(0x0070, 'delete character error',
+ define='SMSG_CHAR_DELETE_FAILED',
fixed=[
at(0, u16, 'packet id'),
at(2, u8, 'code'),
],
fixed_size=3,
+ pre=[0x0068],
+ post=[PRETTY],
+ desc='''
+ Failure to delete character.
+ ''',
)
- char_user.s(0x0071, 'char-map info',
+ char_user.s(0x0071, 'select character success',
+ define='SMSG_CHAR_MAP_INFO',
fixed=[
at(0, u16, 'packet id'),
at(2, char_id, 'char id'),
@@ -1578,8 +2199,14 @@ def build_context():
at(26, u16, 'port'),
],
fixed_size=28,
+ pre=[0x0066],
+ post=[0x0072],
+ desc='''
+ Return character location and map server IP.
+ ''',
)
- map_user.r(0x0072, 'map server connect',
+ map_user.r(0x0072, 'connect map',
+ define='CMSG_MAP_SERVER_CONNECT',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
@@ -1589,8 +2216,15 @@ def build_context():
at(18, sex, 'sex'),
],
fixed_size=19,
+ pre=[0x0071, 0x0092],
+ post=[0x0081, 0x2afc],
+ desc='''
+ Begin connection to the map server, based on keys the login
+ server gave us.
+ ''',
)
- map_user.s(0x0073, 'map login succeeded',
+ map_user.s(0x0073, 'connect map success',
+ define='SMSG_MAP_LOGIN_SUCCESS',
fixed=[
at(0, u16, 'packet id'),
at(2, tick32, 'tick'),
@@ -1599,8 +2233,14 @@ def build_context():
at(10, u8, 'five2'),
],
fixed_size=11,
+ pre=[0x2afd],
+ post=[PRETTY, 0x007e],
+ desc='''
+ Successfully auth'd to the map server
+ ''',
)
- map_user.s(0x0078, 'being visibility',
+ map_user.s(0x0078, 'being appear notify',
+ define='SMSG_BEING_VISIBLE',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'block id'),
@@ -1632,8 +2272,14 @@ def build_context():
at(52, u16, 'level'),
],
fixed_size=54,
+ pre=[BOOT, FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0085, 0x0089, 0x008c, 0x009f, 0x00b8, 0x00b9, 0x00e6, 0x00f7, 0x0143, 0x0146, 0x01d5],
+ post=[0x0094],
+ desc='''
+ A being is stationary.
+ ''',
)
- map_user.s(0x007b, 'being move',
+ map_user.s(0x007b, 'being move notify',
+ define='SMSG_BEING_MOVE',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'block id'),
@@ -1666,8 +2312,14 @@ def build_context():
at(58, u16, 'level'),
],
fixed_size=60,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0085, 0x0089, 0x008c, 0x009f],
+ post=[0x0094],
+ desc='''
+ A being is moving.
+ ''',
)
- map_user.s(0x007c, 'being spawn',
+ map_user.s(0x007c, 'being spawn notify',
+ define='SMSG_BEING_SPAWN',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'block id'),
@@ -1690,50 +2342,95 @@ def build_context():
at(39, u16, 'unknown 11'),
],
fixed_size=41,
+ pre=[BOOT, FINISH, GM, MAGIC, SCRIPT, TIMER, 0x0089, 0x008c, 0x00b8, 0x00b9, 0x00e6, 0x00f7, 0x0143, 0x0146, 0x01d5],
+ post=[PRETTY],
+ desc='''
+ A being is created.
+ ''',
)
map_user.r(0x007d, 'map loaded',
+ define='CMSG_MAP_LOADED',
fixed=[
at(0, u16, 'packet id'),
],
fixed_size=2,
+ pre=[0x0091],
+ post=[SCRIPT, 0x0078, 0x007b, 0x009d, 0x00a4, 0x00b0, 0x00b1, 0x00bd, 0x00fb, 0x0101, 0x010f, 0x0119, 0x013a, 0x0141, 0x019b, 0x01d7, 0x01d8, 0x01d9, 0x01da, 0x01ee, 0x3025, 0x3028],
+ xpost=[0x0080, 0x0081, 0x0088, 0x0091, 0x00a0, 0x00ac, 0x00be, 0x00c0, 0x00e9, 0x00ee, 0x00fd, 0x0106, 0x013c, 0x0196, 0x01b1, 0x2b01, 0x2b05, 0x3011, 0x3022],
+ desc='''
+ Changed map; need info.
+ ''',
)
- map_user.r(0x007e, 'client ping',
+ map_user.r(0x007e, 'ping',
+ define='CMSG_MAP_PING',
fixed=[
at(0, u16, 'packet id'),
at(2, u32, 'client tick'),
],
fixed_size=6,
+ pre=[TIMER, 0x0073],
+ post=[0x007f],
+ desc='''
+ Request ping.
+ ''',
)
- map_user.s(0x007f, 'server ping',
+ map_user.s(0x007f, 'pong',
+ define='SMSG_SERVER_PING',
fixed=[
at(0, u16, 'packet id'),
at(2, tick32, 'tick'),
],
fixed_size=6,
+ pre=[0x007e],
+ post=[NOTHING],
+ desc='''
+ Provide ping.
+ ''',
)
- map_user.s(0x0080, 'remove being',
+ map_user.s(0x0080, 'remove being notify',
+ define='SMSG_BEING_REMOVE',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'block id'),
at(6, being_remove_why, 'type'),
],
fixed_size=7,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0085, 0x0089, 0x008c, 0x0090, 0x009f, 0x00a2, 0x00a7, 0x00a9, 0x00ab, 0x00b2, 0x00b8, 0x00b9, 0x00bb, 0x00c8, 0x00c9, 0x00e4, 0x00e6, 0x00e8, 0x00eb, 0x00ed, 0x00ef, 0x00f3, 0x00f5, 0x00f7, 0x0112, 0x0143, 0x0146, 0x01d5, 0x2afd, 0x2b0d],
+ post=[PRETTY],
+ desc='''
+ A being disappeared.
+ ''',
)
- any_user.s(0x0081, 'connection problem',
+ any_user.s(0x0081, 'connect foo error',
+ define='SMSG_CONNECTION_PROBLEM',
fixed=[
at(0, u16, 'packet id'),
at(2, u8, 'error code'),
],
fixed_size=3,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x0064, 0x0066, 0x0072, 0x007d, 0x0085, 0x0089, 0x008c, 0x009f, 0x00a2, 0x00a7, 0x00a9, 0x00ab, 0x00b2, 0x00b8, 0x00b9, 0x00bb, 0x00c8, 0x00c9, 0x00e4, 0x00e6, 0x00e8, 0x00eb, 0x00ed, 0x00ef, 0x00f3, 0x00f5, 0x00f7, 0x0112, 0x0143, 0x0146, 0x01d5, 0x2afd, 0x2afe, 0x2b06, 0x2b0d],
+ post=[PRETTY],
+ desc='''
+ Failed to connect to some server (multiple meanings).
+ ''',
)
- map_user.r(0x0085, 'change player destination',
+ map_user.r(0x0085, 'walk',
+ define='CMSG_PLAYER_CHANGE_DEST',
fixed=[
at(0, u16, 'packet id'),
at(2, pos1, 'pos'),
],
fixed_size=5,
+ pre=[HUMAN],
+ post=[0x0080, 0x0087, 0x01d7, 0x01da],
+ xpost=[SCRIPT, 0x0078, 0x007b, 0x0081, 0x0088, 0x0091, 0x009d, 0x00a0, 0x00a1, 0x00ac, 0x00b0, 0x00b1, 0x00b4, 0x00b6, 0x00be, 0x00c0, 0x00c4, 0x00e9, 0x00ee, 0x00fd, 0x0106, 0x010f, 0x0119, 0x013a, 0x0141, 0x0196, 0x01b1, 0x01d8, 0x2b01, 0x2b05, 0x3011, 0x3022],
+ desc='''
+ Start walking somewhere.
+ ''',
)
- map_user.s(0x0087, 'walk response',
+ # 0x0086 define='SMSG_BEING_MOVE2',
+ map_user.s(0x0087, 'walk success',
+ define='SMSG_WALK_RESPONSE',
fixed=[
at(0, u16, 'packet id'),
at(2, tick32, 'tick'),
@@ -1741,8 +2438,16 @@ def build_context():
at(11, u8, 'zero'),
],
fixed_size=12,
+ pre=[0x0085, 0x0089],
+ post=[IDLE],
+ desc='''
+ Confirm that you did walk somewhere.
+
+ No corresponding error!
+ ''',
)
- map_user.s(0x0088, 'player stop',
+ map_user.s(0x0088, 'stop walking notify',
+ define='SMSG_PLAYER_STOP',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'block id'),
@@ -1750,16 +2455,36 @@ def build_context():
at(8, u16, 'y'),
],
fixed_size=10,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0085, 0x0089, 0x008c, 0x009f, 0x00a2, 0x00a7, 0x00a9, 0x00ab, 0x00b2, 0x00b8, 0x00b9, 0x00bb, 0x00c8, 0x00c9, 0x00e4, 0x00e6, 0x00e8, 0x00eb, 0x00ed, 0x00ef, 0x00f3, 0x00f5, 0x00f7, 0x0112, 0x0143, 0x0146, 0x01d5, 0x2afd, 0x2b0d],
+ post=[PRETTY],
+ desc='''
+ Being stopped walking.
+ ''',
)
map_user.r(0x0089, 'player action',
+ define='CMSG_PLAYER_CHANGE_ACT',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'target id'),
at(6, damage_type, 'action'),
],
fixed_size=7,
+ pre=[HUMAN],
+ post=[MAGIC, 0x0080, 0x008a, 0x0110, 0x0139],
+ xpost=[SCRIPT, 0x0078, 0x007b, 0x007c, 0x0081, 0x0087, 0x0088, 0x0091, 0x009e, 0x00a0, 0x00a1, 0x00ac, 0x00af, 0x00b0, 0x00b1, 0x00b4, 0x00b6, 0x00be, 0x00c0, 0x00c4, 0x00e9, 0x00ee, 0x00fb, 0x00fd, 0x0101, 0x0106, 0x010f, 0x0119, 0x013a, 0x013b, 0x0141, 0x0196, 0x019b, 0x01b1, 0x01d7, 0x01d8, 0x01da, 0x01de, 0x2b01, 0x2b05, 0x3011, 0x3022, 0x3025, 0x3028],
+ desc='''
+ Perform an action.
+
+ Action:
+ * single attack
+ * continuous attack
+ * sit
+ * stand
+ * (other actions on return only - special calls)
+ ''',
)
- map_user.s(0x008a, 'being action',
+ map_user.s(0x008a, 'being action notify',
+ define='SMSG_BEING_ACTION',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'src id'),
@@ -1773,8 +2498,14 @@ def build_context():
at(27, u16, 'damage2'),
],
fixed_size=29,
- )
- map_user.r(0x008c, 'character chat',
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x0089, 0x009f],
+ post=[PRETTY],
+ desc='''
+ Somebody performed an action on something/somebody.
+ ''',
+ )
+ map_user.r(0x008c, 'global chat',
+ define='CMSG_CHAT_MESSAGE',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -1784,8 +2515,15 @@ def build_context():
at(0, u8, 'c'),
],
repeat_size=1,
- )
- map_user.s(0x008d, 'being chat',
+ pre=[HUMAN],
+ post=[GM, MAGIC, 0x008d, 0x008e],
+ xpost=[SCRIPT, 0x0078, 0x007b, 0x007c, 0x0080, 0x0081, 0x0088, 0x0091, 0x00a0, 0x00ac, 0x00af, 0x00b0, 0x00b1, 0x00b4, 0x00b6, 0x00be, 0x00c0, 0x00c4, 0x00e9, 0x00ee, 0x00fd, 0x0106, 0x010f, 0x0119, 0x013a, 0x0141, 0x0196, 0x01b1, 0x01d7, 0x01d8, 0x01da, 0x2b01, 0x2b05, 0x2b0e, 0x3003, 0x3011, 0x3022],
+ desc='''
+ Talk to everyone nearby.
+ ''',
+ )
+ map_user.s(0x008d, 'global chat notify',
+ define='SMSG_BEING_CHAT',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -1796,8 +2534,14 @@ def build_context():
at(0, u8, 'c'),
],
repeat_size=1,
- )
- map_user.s(0x008e, 'player chat',
+ pre=[GM, SCRIPT, 0x008c],
+ post=[PRETTY],
+ desc='''
+ Somebody is talking (not just a player).
+ ''',
+ )
+ map_user.s(0x008e, 'global chat result',
+ define='SMSG_PLAYER_CHAT',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -1807,16 +2551,33 @@ def build_context():
at(0, u8, 'c'),
],
repeat_size=1,
+ pre=[OTHER, 0x008c],
+ post=[PRETTY],
+ desc='''
+ You talked.
+ ''',
)
- map_user.r(0x0090, 'chat to npc',
+ map_user.r(0x0090, 'npc click',
+ define='CMSG_NPC_TALK',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'block id'),
at(6, u8, 'unused'),
],
fixed_size=7,
+ pre=[HUMAN],
+ post=[SCRIPT, 0x0080, 0x00b4, 0x00b6, 0x00c4],
+ xpost=[0x00c0],
+ desc='''
+ Click on an NPC, to invoke its script/shop/message.
+
+ Error if already talking to an NPC or too far.
+
+ No error if clicking on a warp.
+ ''',
)
- map_user.s(0x0091, 'warp player',
+ map_user.s(0x0091, 'change map notify',
+ define='SMSG_PLAYER_WARP',
fixed=[
at(0, u16, 'packet id'),
at(2, map_name, 'map name'),
@@ -1824,8 +2585,15 @@ def build_context():
at(20, u16, 'y'),
],
fixed_size=22,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0085, 0x0089, 0x008c, 0x009f, 0x00a2, 0x00a7, 0x00a9, 0x00ab, 0x00b2, 0x00b8, 0x00b9, 0x00bb, 0x00c8, 0x00c9, 0x00e4, 0x00e6, 0x00e8, 0x00eb, 0x00ed, 0x00ef, 0x00f3, 0x00f5, 0x00f7, 0x0112, 0x0143, 0x0146, 0x01d5, 0x2afd, 0x2b0d],
+ post=[0x007d],
+ desc='''
+ You teleported to a new map (possible the same map), but on the
+ same server.
+ ''',
)
- map_user.s(0x0092, 'change map server',
+ map_user.s(0x0092, 'change map server notify',
+ define='SMSG_CHANGE_MAP_SERVER',
fixed=[
at(0, u16, 'packet id'),
at(2, map_name, 'map name'),
@@ -1835,23 +2603,43 @@ def build_context():
at(26, u16, 'port'),
],
fixed_size=28,
+ pre=[0x2b06],
+ post=[0x0065, 0x0072],
+ desc='''
+ You teleported to another server.
+ ''',
)
- map_user.r(0x0094, 'request being name',
+ map_user.r(0x0094, 'get being name',
+ define='CMSG_NAME_REQUEST',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'block id'),
],
fixed_size=6,
+ pre=[TIMER, 0x0078, 0x007b, 0x01d8, 0x01d9, 0x01da],
+ post=[0x0095, 0x0195, 0x020c],
+ desc='''
+ Request a beings name. No reply if wrong type.
+
+ Also send misc other info about players.
+ ''',
)
- map_user.s(0x0095, 'being name response',
+ map_user.s(0x0095, 'get being name result',
+ define='SMSG_BEING_NAME_RESPONSE',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'block id'),
at(6, char_name, 'char name'),
],
fixed_size=30,
- )
- map_user.r(0x0096, 'send whisper',
+ pre=[0x0094],
+ post=[PRETTY],
+ desc='''
+ Somebody has a name.
+ ''',
+ )
+ map_user.r(0x0096, 'whisper',
+ define='CMSG_CHAT_WHISPER',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -1862,8 +2650,15 @@ def build_context():
at(0, u8, 'c'),
],
repeat_size=1,
+ pre=[HUMAN],
+ post=[GM, 0x0097, 0x0098, 0x3001],
+ xpost=[0x2b0e, 0x3003],
+ desc='''
+ Talk to someone privately.
+ ''',
)
map_user.s(0x0097, 'receive whisper',
+ define='SMSG_WHISPER',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -1874,15 +2669,28 @@ def build_context():
at(0, u8, 'c'),
],
repeat_size=1,
+ pre=[0x0096, 0x3801, 0x3803],
+ post=[PRETTY],
+ desc='''
+ Somebody is talking to you privately.
+ '''
)
- map_user.s(0x0098, 'whisper status',
+ map_user.s(0x0098, 'whisper result',
+ define='SMSG_WHISPER_RESPONSE',
fixed=[
at(0, u16, 'packet id'),
at(2, u8, 'flag'),
],
fixed_size=3,
- )
- map_user.s(0x009a, 'gm announcement',
+ pre=[0x0096, 0x3802],
+ post=[PRETTY],
+ desc='''
+ Did you successfully talk to someone?
+ ''',
+ )
+ # 0x0099 define='CMSG_ADMIN_ANNOUNCE',
+ map_user.s(0x009a, 'gm announcement notify',
+ define='SMSG_GM_CHAT',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -1892,16 +2700,28 @@ def build_context():
at(0, u8, 'c'),
],
repeat_size=1,
+ pre=[GM, SCRIPT, 0x3800],
+ post=[PRETTY],
+ desc='''
+ The GMs are shouting in red.
+ ''',
)
- map_user.r(0x009b, 'change player direction',
+ map_user.r(0x009b, 'face direction',
+ define='CMSG_PLAYER_CHANGE_DIR',
fixed=[
at(0, u16, 'packet id'),
at(2, u16, 'unused'),
at(4, u8, 'client dir'),
],
fixed_size=5,
+ pre=[HUMAN],
+ post=[0x009c],
+ desc='''
+ Look in a different direction, without moving.
+ ''',
)
- map_user.s(0x009c, 'being changed direction',
+ map_user.s(0x009c, 'face direction notify',
+ define='SMSG_BEING_CHANGE_DIRECTION',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'block id'),
@@ -1909,8 +2729,14 @@ def build_context():
at(8, u8, 'client dir'),
],
fixed_size=9,
+ pre=[0x009b],
+ post=[PRETTY],
+ desc='''
+ Somebody looked in a different direction, without moving.
+ ''',
)
- map_user.s(0x009d, 'visible item',
+ map_user.s(0x009d, 'item visible notify',
+ define='SMSG_ITEM_VISIBLE',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'block id'),
@@ -1923,8 +2749,14 @@ def build_context():
at(16, u8, 'suby'),
],
fixed_size=17,
+ pre=[0x007d, 0x0085],
+ post=[PRETTY],
+ desc='''
+ An item appeared on the ground.
+ ''',
)
- map_user.s(0x009e, 'dropped item',
+ map_user.s(0x009e, 'item dropped notify',
+ define='SMSG_ITEM_DROPPED',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'block id'),
@@ -1937,15 +2769,28 @@ def build_context():
at(15, u16, 'amount'),
],
fixed_size=17,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x0089, 0x00a2],
+ post=[PRETTY],
+ desc='''
+ An item was dropped on the ground.
+ ''',
)
- map_user.r(0x009f, 'pickup item',
+ map_user.r(0x009f, 'item pickup',
+ define='CMSG_ITEM_PICKUP',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'object id'),
],
fixed_size=6,
+ pre=[HUMAN],
+ post=[SCRIPT, 0x0080, 0x008a, 0x0091, 0x00a0, 0x00a1, 0x00b0],
+ xpost=[0x0078, 0x007b, 0x0081, 0x0088, 0x00ac, 0x00b1, 0x00b4, 0x00b6, 0x00be, 0x00c0, 0x00c4, 0x00e9, 0x00ee, 0x00fd, 0x0106, 0x010f, 0x0119, 0x013a, 0x0141, 0x0196, 0x01b1, 0x01d7, 0x01d8, 0x01da, 0x2b01, 0x2b05, 0x3011, 0x3022],
+ desc='''
+ Hey, it's just lying around on the floor, I want it.
+ ''',
)
- map_user.s(0x00a0, 'add item to inventory',
+ map_user.s(0x00a0, 'inventory add notify',
+ define='SMSG_PLAYER_INVENTORY_ADD',
fixed=[
at(0, u16, 'packet id'),
at(2, ioff2, 'ioff2'),
@@ -1963,23 +2808,44 @@ def build_context():
at(22, pickup_fail, 'pickup fail'),
],
fixed_size=23,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0085, 0x0089, 0x008c, 0x009f, 0x00a2, 0x00a7, 0x00a9, 0x00ab, 0x00b2, 0x00b8, 0x00b9, 0x00bb, 0x00c8, 0x00c9, 0x00e4, 0x00e6, 0x00e8, 0x00eb, 0x00ed, 0x00ef, 0x00f3, 0x00f5, 0x00f7, 0x0112, 0x0143, 0x0146, 0x01d5, 0x2afd, 0x2b0d],
+ post=[PRETTY],
+ desc='''
+ Item appeared in your inventory.
+ ''',
)
- map_user.s(0x00a1, 'item removed',
+ map_user.s(0x00a1, 'flooritem delete notify',
+ define='SMSG_ITEM_REMOVE',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'block id'),
],
fixed_size=6,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x0085, 0x0089, 0x009f, 0x00a2],
+ post=[PRETTY],
+ desc='''
+ Item disappeared from the floor.
+ ''',
)
- map_user.r(0x00a2, 'drop an item',
+ map_user.r(0x00a2, 'drop item',
+ define='CMSG_PLAYER_INVENTORY_DROP',
fixed=[
at(0, u16, 'packet id'),
at(2, ioff2, 'ioff2'),
at(4, u16, 'amount'),
],
fixed_size=6,
+ pre=[HUMAN],
+ post=[0x0080, 0x009e, 0x00ac, 0x00af, 0x01d7],
+ xpost=[SCRIPT, 0x0081, 0x0088, 0x0091, 0x00a0, 0x00a1, 0x00b0, 0x00b1, 0x00be, 0x00c0, 0x00e9, 0x00ee, 0x00fd, 0x0106, 0x010f, 0x0119, 0x013a, 0x0141, 0x0196, 0x01b1, 0x01d8, 0x01da, 0x2b01, 0x2b05, 0x3011, 0x3022],
+ desc='''
+ This is worthless, just leave it lying on the ground.
+
+ Also used by people who don't understand trades.
+ ''',
)
- map_user.s(0x00a4, 'player equipment',
+ map_user.s(0x00a4, 'inventory equipment notify',
+ define='SMSG_PLAYER_EQUIPMENT',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -2000,8 +2866,14 @@ def build_context():
at(18, u16, 'card3'),
],
repeat_size=20,
- )
- map_user.s(0x00a6, 'storage equipment',
+ pre=[0x007d],
+ post=[PRETTY],
+ desc='''
+ Complete list of equipment in inventory.
+ ''',
+ )
+ map_user.s(0x00a6, 'storage equipment notify',
+ define='SMSG_PLAYER_STORAGE_EQUIP',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -2022,16 +2894,29 @@ def build_context():
at(18, u16, 'card3'),
],
repeat_size=20,
+ pre=[GM, SCRIPT, 0x3810],
+ post=[PRETTY],
+ desc='''
+ Complete list of equipment in storage.
+ ''',
)
- map_user.r(0x00a7, 'use inventory item',
+ map_user.r(0x00a7, 'use item',
+ define='CMSG_PLAYER_INVENTORY_USE',
fixed=[
at(0, u16, 'packet id'),
at(2, ioff2, 'ioff2'),
at(4, u32, 'unused id'),
],
fixed_size=8,
+ pre=[HUMAN],
+ post=[SCRIPT, 0x0080, 0x00a8, 0x00ac, 0x00af, 0x00b0, 0x01c8, 0x01d7],
+ xpost=[0x0081, 0x0088, 0x0091, 0x00a0, 0x00b1, 0x00be, 0x00c0, 0x00e9, 0x00ee, 0x00fd, 0x0106, 0x010f, 0x0119, 0x013a, 0x0141, 0x0196, 0x01b1, 0x01d8, 0x01da, 0x2b01, 0x2b05, 0x3011, 0x3022],
+ desc='''
+ Use a consumable item in your inventory.
+ ''',
)
- map_user.s(0x00a8, 'item usage response',
+ map_user.s(0x00a8, 'use item result',
+ define='SMSG_ITEM_USE_RESPONSE',
fixed=[
at(0, u16, 'packet id'),
at(2, ioff2, 'ioff2'),
@@ -2039,16 +2924,31 @@ def build_context():
at(6, u8, 'ok'),
],
fixed_size=7,
+ pre=[0x00a7],
+ post=[PRETTY],
+ desc='''
+ You used (or tried to use) an item in your inventory.
+
+ Currently only used in the failure case.
+ ''',
)
- map_user.r(0x00a9, 'equip an item request',
+ map_user.r(0x00a9, 'equip item',
+ define='CMSG_PLAYER_EQUIP',
fixed=[
at(0, u16, 'packet id'),
at(2, ioff2, 'ioff2'),
at(4, epos, 'epos ignored'),
],
fixed_size=6,
+ pre=[HUMAN],
+ post=[SCRIPT, 0x0080, 0x00aa, 0x00ac, 0x013b, 0x013c, 0x01d7],
+ xpost=[0x0081, 0x0088, 0x0091, 0x00a0, 0x00b0, 0x00b1, 0x00be, 0x00c0, 0x00e9, 0x00ee, 0x00fd, 0x0106, 0x010f, 0x0119, 0x013a, 0x0141, 0x0196, 0x01b1, 0x01d8, 0x01da, 0x2b01, 0x2b05, 0x3011, 0x3022],
+ desc='''
+ Put on armor or something.
+ ''',
)
- map_user.s(0x00aa, 'item equip ack',
+ map_user.s(0x00aa, 'equip item result',
+ define='SMSG_PLAYER_EQUIP',
fixed=[
at(0, u16, 'packet id'),
at(2, ioff2, 'ioff2'),
@@ -2056,15 +2956,28 @@ def build_context():
at(6, u8, 'ok'),
],
fixed_size=7,
+ pre=[0x00a9],
+ post=[PRETTY],
+ desc='''
+ Result of trying to wear something.
+ ''',
)
- map_user.r(0x00ab, 'unequip an item',
+ map_user.r(0x00ab, 'unequip item',
+ define='CMSG_PLAYER_UNEQUIP',
fixed=[
at(0, u16, 'packet id'),
at(2, ioff2, 'ioff2'),
],
fixed_size=4,
+ pre=[HUMAN],
+ post=[SCRIPT, 0x0080, 0x00ac, 0x01d7],
+ xpost=[0x0081, 0x0088, 0x0091, 0x00a0, 0x00b0, 0x00b1, 0x00be, 0x00c0, 0x00e9, 0x00ee, 0x00fd, 0x0106, 0x010f, 0x0119, 0x013a, 0x0141, 0x0196, 0x01b1, 0x01d8, 0x01da, 0x2b01, 0x2b05, 0x3011, 0x3022],
+ desc='''
+ Take off armor or something.
+ ''',
)
- map_user.s(0x00ac, 'unequip item ack',
+ map_user.s(0x00ac, 'unequip item result',
+ define='SMSG_PLAYER_UNEQUIP',
fixed=[
at(0, u16, 'packet id'),
at(2, ioff2, 'ioff2'),
@@ -2072,46 +2985,83 @@ def build_context():
at(6, u8, 'ok'),
],
fixed_size=7,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0085, 0x0089, 0x008c, 0x009f, 0x00a2, 0x00a7, 0x00a9, 0x00ab, 0x00b2, 0x00b8, 0x00b9, 0x00bb, 0x00c8, 0x00c9, 0x00e4, 0x00e6, 0x00e8, 0x00eb, 0x00ed, 0x00ef, 0x00f3, 0x00f5, 0x00f7, 0x0112, 0x0143, 0x0146, 0x01d5, 0x2afd, 0x2b0d],
+ post=[PRETTY],
+ desc='''
+ Result of trying to unwear something.
+ ''',
)
- map_user.s(0x00af, 'remove item from inventory',
+ map_user.s(0x00af, 'inventory delete notify',
+ define='SMSG_PLAYER_INVENTORY_REMOVE',
fixed=[
at(0, u16, 'packet id'),
at(2, ioff2, 'ioff2'),
at(4, u16, 'amount'),
],
fixed_size=6,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x0089, 0x008c, 0x00a2, 0x00a7, 0x00c9, 0x00ef, 0x00f3],
+ post=[PRETTY],
+ desc='''
+ An item has been deleted from your inventory.
+ ''',
)
- map_user.s(0x00b0, 'player stat update 1',
+ map_user.s(0x00b0, 'player stat update 1 notify',
+ define='SMSG_PLAYER_STAT_UPDATE_1',
fixed=[
at(0, u16, 'packet id'),
at(2, sp, 'sp type'),
at(4, u32, 'value'),
],
fixed_size=8,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0085, 0x0089, 0x008c, 0x009f, 0x00a2, 0x00a7, 0x00a9, 0x00ab, 0x00b2, 0x00b8, 0x00b9, 0x00bb, 0x00c8, 0x00c9, 0x00e4, 0x00e6, 0x00e8, 0x00eb, 0x00ed, 0x00ef, 0x00f3, 0x00f5, 0x00f7, 0x0112, 0x0143, 0x0146, 0x01d5, 0x2afd, 0x2b0d],
+ post=[PRETTY],
+ desc='''
+ One of many player stat packets with no real difference.
+ ''',
)
- map_user.s(0x00b1, 'player stat update 2',
+ map_user.s(0x00b1, 'player stat update 2 notify',
+ define='SMSG_PLAYER_STAT_UPDATE_2',
fixed=[
at(0, u16, 'packet id'),
at(2, sp, 'sp type'),
at(4, u32, 'value'),
],
fixed_size=8,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0085, 0x0089, 0x008c, 0x009f, 0x00a2, 0x00a7, 0x00a9, 0x00ab, 0x00b2, 0x00b8, 0x00b9, 0x00bb, 0x00c8, 0x00c9, 0x00e4, 0x00e6, 0x00e8, 0x00eb, 0x00ed, 0x00ef, 0x00f3, 0x00f5, 0x00f7, 0x0112, 0x0143, 0x0146, 0x01d5, 0x2afd, 0x2b0d],
+ post=[PRETTY],
+ desc='''
+ One of many player stat packets with no real difference.
+ ''',
)
- map_user.r(0x00b2, 'switch or respawn the character',
+ map_user.r(0x00b2, 'respawn or switch character',
+ define='CMSG_PLAYER_REBOOT',
fixed=[
at(0, u16, 'packet id'),
at(2, u8, 'flag'),
],
fixed_size=3,
+ pre=[HUMAN, 0x01d8],
+ post=[0x0080, 0x0091, 0x00b0, 0x018b, 0x2b02, 0x2b05],
+ xpost=[SCRIPT, 0x0081, 0x0088, 0x00a0, 0x00ac, 0x00b1, 0x00be, 0x00c0, 0x00e9, 0x00ee, 0x00fd, 0x0106, 0x010f, 0x0119, 0x013a, 0x0141, 0x0196, 0x01b1, 0x01d7, 0x01d8, 0x01da, 0x2b01, 0x3011, 0x3022],
+ desc='''
+ If flag is 0, respawn after dying. If flag is 1, try to switch characters.
+ ''',
)
- map_user.s(0x00b3, 'character switch response',
+ map_user.s(0x00b3, 'character switch success',
+ define='SMSG_CHAR_SWITCH_RESPONSE',
fixed=[
at(0, u16, 'packet id'),
at(2, u8, 'one'),
],
fixed_size=3,
- )
- map_user.s(0x00b4, 'npc message',
+ pre=[0x2b03],
+ post=[0x0065],
+ desc='''
+ Permission granted to switch characters.
+ ''',
+ )
+ map_user.s(0x00b4, 'script message notify',
+ define='SMSG_NPC_MESSAGE',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -2122,22 +3072,40 @@ def build_context():
at(0, u8, 'c'),
],
repeat_size=1,
+ pre=[MAGIC, SCRIPT, 0x0085, 0x0089, 0x008c, 0x0090, 0x009f],
+ post=[PRETTY],
+ desc='''
+ An npc is droning on.
+ ''',
)
- map_user.s(0x00b5, 'npc message continues',
+ map_user.s(0x00b5, '(reverse) script next',
+ define='SMSG_NPC_NEXT',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'block id'),
],
fixed_size=6,
+ pre=[SCRIPT],
+ post=[0x00b9],
+ desc='''
+ An npc paused briefly to catch its breath.
+ ''',
)
- map_user.s(0x00b6, 'npc message ends',
+ map_user.s(0x00b6, '(reverse) script close',
+ define='SMSG_NPC_CLOSE',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'block id'),
],
fixed_size=6,
- )
- map_user.s(0x00b7, 'npc prompts a choice',
+ pre=[GM, MAGIC, SCRIPT, 0x0085, 0x0089, 0x008c, 0x0090, 0x009f, 0x00b8, 0x00b9, 0x00e6, 0x00f7, 0x0143, 0x0146, 0x01d5],
+ post=[0x0146],
+ desc='''
+ An npc finally shut up.
+ ''',
+ )
+ map_user.s(0x00b7, '(reverse) script menu',
+ define='SMSG_NPC_CHOICE',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -2148,31 +3116,58 @@ def build_context():
at(0, u8, 'c'),
],
repeat_size=1,
+ pre=[SCRIPT],
+ post=[0x00b8],
+ desc='''
+ An npc let you choose how it will drone on.
+ ''',
)
- map_user.r(0x00b8, 'send npc response',
+ map_user.r(0x00b8, '(reverse) script menu result',
+ define='CMSG_NPC_LIST_CHOICE',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'npc id'),
at(6, u8, 'menu entry'),
],
fixed_size=7,
+ pre=[0x00b7],
+ post=[MAGIC, SCRIPT],
+ xpost=[0x0078, 0x007c, 0x0080, 0x0081, 0x0088, 0x0091, 0x00a0, 0x00ac, 0x00b0, 0x00b1, 0x00b6, 0x00be, 0x00c0, 0x00e9, 0x00ee, 0x00fd, 0x0106, 0x010f, 0x0119, 0x013a, 0x0141, 0x0196, 0x01b1, 0x01d7, 0x01d8, 0x01da, 0x2b01, 0x2b05, 0x3011, 0x3022],
+ desc='''
+ Choose an entry from the menu (1-based), 0xff to run away.
+ ''',
)
- map_user.r(0x00b9, 'request next npc message',
+ map_user.r(0x00b9, '(reverse) script next result',
+ define='CMSG_NPC_NEXT_REQUEST',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'npc id'),
],
fixed_size=6,
+ pre=[0x00b5],
+ post=[MAGIC, SCRIPT],
+ xpost=[0x0078, 0x007c, 0x0080, 0x0081, 0x0088, 0x0091, 0x00a0, 0x00ac, 0x00b0, 0x00b1, 0x00b6, 0x00be, 0x00c0, 0x00e9, 0x00ee, 0x00fd, 0x0106, 0x010f, 0x0119, 0x013a, 0x0141, 0x0196, 0x01b1, 0x01d7, 0x01d8, 0x01da, 0x2b01, 0x2b05, 0x3011, 0x3022],
+ desc='''
+ Let the npc keep breathing.
+ ''',
)
- map_user.r(0x00bb, 'request a stat update',
+ map_user.r(0x00bb, 'stat increase',
+ define='CMSG_STAT_UPDATE_REQUEST',
fixed=[
at(0, u16, 'packet id'),
at(2, sp, 'asp'),
at(4, u8, 'unused'),
],
fixed_size=5,
+ pre=[HUMAN],
+ post=[0x00b0, 0x00bc, 0x00be, 0x0141],
+ xpost=[SCRIPT, 0x0080, 0x0081, 0x0088, 0x0091, 0x00a0, 0x00ac, 0x00b1, 0x00c0, 0x00e9, 0x00ee, 0x00fd, 0x0106, 0x010f, 0x0119, 0x013a, 0x0196, 0x01b1, 0x01d7, 0x01d8, 0x01da, 0x2b01, 0x2b05, 0x3011, 0x3022],
+ desc='''
+ Spend stat points.
+ ''',
)
- map_user.s(0x00bc, 'player stat update 4',
+ map_user.s(0x00bc, 'stat increase result',
+ define='SMSG_PLAYER_STAT_UPDATE_4',
fixed=[
at(0, u16, 'packet id'),
at(2, sp, 'sp type'),
@@ -2180,8 +3175,14 @@ def build_context():
at(5, u8, 'val'),
],
fixed_size=6,
+ pre=[SCRIPT, 0x00bb],
+ post=[PRETTY],
+ desc='''
+ Spent stat points?
+ ''',
)
- map_user.s(0x00bd, 'player stat update 5',
+ map_user.s(0x00bd, 'player stat update 5 notify',
+ define='SMSG_PLAYER_STAT_UPDATE_5',
fixed=[
at(0, u16, 'packet id'),
at(2, u16, 'status point'),
@@ -2213,59 +3214,89 @@ def build_context():
at(42, u16, 'manner'),
],
fixed_size=44,
+ pre=[0x007d],
+ post=[PRETTY],
+ desc='''
+ Bulk notify of stats.
+ ''',
)
- map_user.s(0x00be, 'player stat update 6',
+ map_user.s(0x00be, 'stat price notify',
+ define='SMSG_PLAYER_STAT_UPDATE_6',
fixed=[
at(0, u16, 'packet id'),
at(2, sp, 'sp type'),
at(4, u8, 'value'),
],
fixed_size=5,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0085, 0x0089, 0x008c, 0x009f, 0x00a2, 0x00a7, 0x00a9, 0x00ab, 0x00b2, 0x00b8, 0x00b9, 0x00bb, 0x00c8, 0x00c9, 0x00e4, 0x00e6, 0x00e8, 0x00eb, 0x00ed, 0x00ef, 0x00f3, 0x00f5, 0x00f7, 0x0112, 0x0143, 0x0146, 0x01d5, 0x2afd, 0x2b0d],
+ post=[PRETTY],
+ desc='''
+ Cost of spending stat points.
+ ''',
)
- map_user.r(0x00bf, 'show an emote',
+ map_user.r(0x00bf, 'emote',
+ define='CMSG_PLAYER_EMOTE',
fixed=[
at(0, u16, 'packet id'),
at(2, u8, 'emote'),
],
fixed_size=3,
+ pre=[HUMAN, TIMER],
+ post=[0x00c0, 0x110],
+ desc='''
+ Don't act like a faceless robot.
+ ''',
)
- map_user.s(0x00c0, 'show the emote of a being',
+ map_user.s(0x00c0, 'emote notify',
+ define='SMSG_BEING_EMOTION',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'block id'),
at(6, u8, 'type'),
],
fixed_size=7,
+ pre=[BOOT, FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0085, 0x0089, 0x008c, 0x0090, 0x009f, 0x00a2, 0x00a7, 0x00a9, 0x00ab, 0x00b2, 0x00b8, 0x00b9, 0x00bb, 0x00bf, 0x00c8, 0x00c9, 0x00e4, 0x00e6, 0x00e8, 0x00eb, 0x00ed, 0x00ef, 0x00f3, 0x00f5, 0x00f7, 0x0112, 0x0143, 0x0146, 0x01d5, 0x2afd, 0x2b0d, 0x3800, 0x3821, 0x3823, 0x3824, 0x3825, 0x3826, 0x3827],
+ post=[PRETTY],
+ desc='''
+ Somebody is claiming to not be a faceless robot.
+ ''',
)
- map_user.r(0x00c1, 'request online users (unused)',
- fixed=[
- at(0, u16, 'packet id'),
- ],
- fixed_size=2,
- )
- map_user.s(0x00c2, 'online users response (unused)',
- fixed=[
- at(0, u16, 'packet id'),
- at(2, u32, 'users'),
- ],
- fixed_size=6,
- )
- map_user.s(0x00c4, 'npc shop choice',
+ # 0x00c1 define='CMSG_CHAT_WHO', (unused by this name)
+ # 0x00c1 define='CMSG_WHO_REQUEST',
+ # 0x00c2 define='SMSG_WHO_ANSWER',
+ # 0x00c3 define='SMSG_BEING_CHANGE_LOOKS',
+ map_user.s(0x00c4, 'npc click result shop',
+ define='SMSG_NPC_BUY_SELL_CHOICE',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'block id'),
],
fixed_size=6,
+ pre=[MAGIC, SCRIPT, 0x0085, 0x0089, 0x008c, 0x0090, 0x009f],
+ post=[0x00c5],
+ desc='''
+ That npc you clicked on was a shop.
+ ''',
)
- map_user.r(0x00c5, 'npc shop request',
+ map_user.r(0x00c5, 'npc shop buy/sell select',
+ define='CMSG_NPC_BUY_SELL_REQUEST',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'block id'),
at(6, u8, 'type'),
],
fixed_size=7,
+ pre=[0x00c4],
+ post=[0x00c6, 0x00c7],
+ desc='''
+ Choose whether to buy or sell in a shop.
+
+ type 0: buy
+ type 1: sell
+ ''',
)
- map_user.s(0x00c6, 'npc buy prompt',
+ map_user.s(0x00c6, 'npc shop buy select result',
+ define='SMSG_NPC_BUY',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -2278,8 +3309,14 @@ def build_context():
at(9, item_name_id, 'name id'),
],
repeat_size=11,
- )
- map_user.s(0x00c7, 'npc sell prompt',
+ pre=[0x00c5],
+ post=[0x00c8],
+ desc='''
+ List of items you can buy from the shop.
+ ''',
+ )
+ map_user.s(0x00c7, 'npc shop sell select result',
+ define='SMSG_NPC_SELL',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -2291,8 +3328,17 @@ def build_context():
at(6, u32, 'actual price'),
],
repeat_size=10,
+ pre=[0x00c5],
+ post=[0x00c9],
+ desc='''
+ List of items you can sell to the shop.
+
+ Currently the server doesn't support customizing this list,
+ but in theory it could.
+ ''',
)
- map_user.r(0x00c8, 'npc buy request',
+ map_user.r(0x00c8, 'npc shop buy',
+ define='CMSG_NPC_BUY_REQUEST',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -2303,8 +3349,15 @@ def build_context():
at(2, item_name_id, 'name id'),
],
repeat_size=4,
- )
- map_user.r(0x00c9, 'npc sell request',
+ pre=[0x00c6],
+ post=[0x00a0, 0x00b0, 0x00b1, 0x00ca],
+ xpost=[SCRIPT, 0x0080, 0x0081, 0x0088, 0x0091, 0x00ac, 0x00be, 0x00c0, 0x00e9, 0x00ee, 0x00fd, 0x0106, 0x010f, 0x0119, 0x013a, 0x0141, 0x0196, 0x01b1, 0x01d7, 0x01d8, 0x01da, 0x2b01, 0x2b05, 0x3011, 0x3022],
+ desc='''
+ Purchase a bunch of items from a shop.
+ ''',
+ )
+ map_user.r(0x00c9, 'npc shop sell',
+ define='CMSG_NPC_SELL_REQUEST',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -2315,65 +3368,127 @@ def build_context():
at(2, u16, 'count'),
],
repeat_size=4,
+ pre=[0x00c7],
+ post=[0x00ac, 0x00af, 0x00b0, 0x00b1, 0x00cb, 0x01d7],
+ xpost=[SCRIPT, 0x0080, 0x0081, 0x0088, 0x0091, 0x00a0, 0x00be, 0x00c0, 0x00e9, 0x00ee, 0x00fd, 0x0106, 0x010f, 0x0119, 0x013a, 0x0141, 0x0196, 0x01b1, 0x01d8, 0x01da, 0x2b01, 0x2b05, 0x3011, 0x3022],
+ desc='''
+ Sell a bunch of items to a shop.
+ ''',
)
- map_user.s(0x00ca, 'npc buy response',
+ map_user.s(0x00ca, 'npc shop buy result',
+ define='SMSG_NPC_BUY_RESPONSE',
fixed=[
at(0, u16, 'packet id'),
at(2, u8, 'fail'),
],
fixed_size=3,
+ pre=[0x00c8],
+ post=[PRETTY],
+ desc='''
+ Result of purchasing items.
+ ''',
)
- map_user.s(0x00cb, 'npc sell response',
+ map_user.s(0x00cb, 'npc shop sell result',
+ define='SMSG_NPC_SELL_RESPONSE',
fixed=[
at(0, u16, 'packet id'),
at(2, u8, 'fail'),
],
fixed_size=3,
+ pre=[0x00c9],
+ post=[PRETTY],
+ desc='''
+ Result of purchasing items.
+ ''',
)
- map_user.s(0x00cd, 'kick status',
+ # 0x00cc define='CMSG_ADMIN_KICK',
+ map_user.s(0x00cd, 'kick result',
+ define='SMSG_ADMIN_KICK_ACK',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
],
fixed_size=6,
+ pre=[GM],
+ post=[PRETTY],
+ desc='''
+ Successfully used @kick.
+ ''',
)
- map_user.r(0x00e4, 'trade request request',
+ # 0x00cf define='CMSG_IGNORE_NICK',
+ # 0x00d0 define='CMSG_IGNORE_ALL',
+ # 0x00d2 define='SMSG_IGNORE_ALL_RESPONSE',
+ map_user.r(0x00e4, 'trade please',
+ define='CMSG_TRADE_REQUEST',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'block id'),
],
fixed_size=6,
+ pre=[HUMAN],
+ post=[0x00e5, 0x00e7, 0x00ee, 0x0110],
+ xpost=[SCRIPT, 0x0080, 0x0081, 0x0088, 0x0091, 0x00a0, 0x00ac, 0x00b0, 0x00b1, 0x00be, 0x00c0, 0x00e9, 0x00fd, 0x0106, 0x010f, 0x0119, 0x013a, 0x0141, 0x0196, 0x01b1, 0x01d7, 0x01d8, 0x01da, 0x2b01, 0x2b05, 0x3011, 0x3022],
+ desc='''
+ Ask someone to trade.
+ ''',
)
map_user.s(0x00e5, 'incoming trade request',
+ define='SMSG_TRADE_REQUEST',
fixed=[
at(0, u16, 'packet id'),
at(2, char_name, 'char name'),
],
fixed_size=26,
+ pre=[GM, 0x00e4],
+ post=[0x00e6],
+ desc='''
+ Somebody wants to trade with you.
+ ''',
)
- map_user.r(0x00e6, 'incoming trade request response',
+ map_user.r(0x00e6, 'incoming trade request result',
+ define='CMSG_TRADE_RESPONSE',
fixed=[
at(0, u16, 'packet id'),
at(2, u8, 'type'),
],
fixed_size=3,
+ pre=[0x00e5],
+ post=[0x00e7],
+ xpost=[MAGIC, SCRIPT, 0x0078, 0x007c, 0x0080, 0x0081, 0x0088, 0x0091, 0x00a0, 0x00ac, 0x00b0, 0x00b1, 0x00b6, 0x00be, 0x00c0, 0x00e9, 0x00ee, 0x00f8, 0x00fd, 0x0106, 0x010f, 0x0119, 0x013a, 0x0141, 0x0196, 0x01b1, 0x01d7, 0x01d8, 0x01da, 0x2b01, 0x2b05, 0x3011, 0x3022],
+ desc='''
+ You agree/disagree to begin a trade with someone.
+ ''',
)
- map_user.s(0x00e7, 'trade request response',
+ map_user.s(0x00e7, 'trade please result',
+ define='SMSG_TRADE_RESPONSE',
fixed=[
at(0, u16, 'packet id'),
at(2, u8, 'type'),
],
fixed_size=3,
+ pre=[GM, 0x00e4, 0x00e6],
+ post=[PRETTY],
+ desc='''
+ The original result of asking for a trade.
+ ''',
)
- map_user.r(0x00e8, 'trade item add request',
+ map_user.r(0x00e8, 'trade add',
+ define='CMSG_TRADE_ITEM_ADD_REQUEST',
fixed=[
at(0, u16, 'packet id'),
at(2, ioff2, 'zeny or ioff2'),
at(4, u32, 'amount'),
],
fixed_size=8,
+ pre=[HUMAN],
+ post=[0x00ac, 0x00e9, 0x01b1, 0x01d7],
+ xpost=[SCRIPT, 0x0080, 0x0081, 0x0088, 0x0091, 0x00a0, 0x00b0, 0x00b1, 0x00be, 0x00c0, 0x00ee, 0x00fd, 0x0106, 0x010f, 0x0119, 0x013a, 0x0141, 0x0196, 0x01d8, 0x01da, 0x2b01, 0x2b05, 0x3011, 0x3022],
+ desc='''
+ Add item/zeny to your trade offer.
+ ''',
)
- map_user.s(0x00e9, 'trade item add',
+ map_user.s(0x00e9, 'trade item added notify',
+ define='SMSG_TRADE_ITEM_ADD',
fixed=[
at(0, u16, 'packet id'),
at(2, u32, 'amount'),
@@ -2387,62 +3502,125 @@ def build_context():
at(17, u16, 'card3'),
],
fixed_size=19,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0085, 0x0089, 0x008c, 0x009f, 0x00a2, 0x00a7, 0x00a9, 0x00ab, 0x00b2, 0x00b8, 0x00b9, 0x00bb, 0x00c8, 0x00c9, 0x00e4, 0x00e6, 0x00e8, 0x00eb, 0x00ed, 0x00ef, 0x00f3, 0x00f5, 0x00f7, 0x0112, 0x0143, 0x0146, 0x01d5, 0x2afd, 0x2b0d],
+ post=[PRETTY],
+ desc='''
+ Item successfully added.
+ ''',
)
- map_user.r(0x00eb, 'trade add complete',
+ map_user.r(0x00eb, 'trade lock',
+ define='CMSG_TRADE_ADD_COMPLETE',
fixed=[
at(0, u16, 'packet id'),
],
fixed_size=2,
+ pre=[HUMAN],
+ post=[0x00ec, 0x1b1],
+ xpost=[SCRIPT, 0x0080, 0x0081, 0x0088, 0x0091, 0x00a0, 0x00ac, 0x00b0, 0x00b1, 0x00be, 0x00c0, 0x00e9, 0x00ee, 0x00fd, 0x0106, 0x010f, 0x0119, 0x013a, 0x0141, 0x0196, 0x01d7, 0x01d8, 0x01da, 0x2b01, 0x2b05, 0x3011, 0x3022],
+ desc='''
+ Indicate readiness to end trade.
+
+ Do this when the other person has added all the items you want.
+ ''',
)
- map_user.s(0x00ec, 'trade ok',
+ map_user.s(0x00ec, 'trade lock notify',
+ define='SMSG_TRADE_OK',
fixed=[
at(0, u16, 'packet id'),
at(2, u8, 'fail'),
],
fixed_size=3,
+ pre=[0x00eb],
+ post=[PRETTY],
+ desc='''
+ Somebody locked their half of the trade (0=self, 1=other).
+ ''',
)
- map_user.r(0x00ed, 'trace cancel request',
+ map_user.r(0x00ed, 'trade cancel',
+ define='CMSG_TRADE_CANCEL_REQUEST',
fixed=[
at(0, u16, 'packet id'),
],
fixed_size=2,
+ pre=[HUMAN],
+ post=[0x00a0, 0x00b0, 0x00ee],
+ xpost=[SCRIPT, 0x0080, 0x0081, 0x0088, 0x0091, 0x00ac, 0x00b1, 0x00be, 0x00c0, 0x00e9, 0x00fd, 0x0106, 0x010f, 0x0119, 0x013a, 0x0141, 0x0196, 0x01b1, 0x01d7, 0x01d8, 0x01da, 0x2b01, 0x2b05, 0x3011, 0x3022],
+ desc='''
+ Cancel an ongoing trade.
+ ''',
)
- map_user.s(0x00ee, 'trade cancel',
+ map_user.s(0x00ee, 'trade cancel notify',
+ define='SMSG_TRADE_CANCEL',
fixed=[
at(0, u16, 'packet id'),
],
fixed_size=2,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0085, 0x0089, 0x008c, 0x009f, 0x00a2, 0x00a7, 0x00a9, 0x00ab, 0x00b2, 0x00b8, 0x00b9, 0x00bb, 0x00c8, 0x00c9, 0x00e4, 0x00e6, 0x00e8, 0x00eb, 0x00ed, 0x00ef, 0x00f3, 0x00f5, 0x00f7, 0x0112, 0x0143, 0x0146, 0x01d5, 0x2afd, 0x2b0d],
+ post=[],
+ desc='''
+ Somebody cancelled your trade.
+ ''',
)
- map_user.r(0x00ef, 'trade ok request',
+ map_user.r(0x00ef, 'trade commit',
+ define='CMSG_TRADE_OK',
fixed=[
at(0, u16, 'packet id'),
],
fixed_size=2,
+ pre=[HUMAN],
+ post=[0x00a0, 0x00af, 0x00b0, 0x00f0],
+ xpost=[SCRIPT, 0x0080, 0x0081, 0x0088, 0x0091, 0x00ac, 0x00b1, 0x00be, 0x00c0, 0x00e9, 0x00ee, 0x00fd, 0x0106, 0x010f, 0x0119, 0x013a, 0x0141, 0x0196, 0x01b1, 0x01d7, 0x01d8, 0x01da, 0x2b01, 0x2b05, 0x3011, 0x3022],
+ desc='''
+ Actually perform the trade. Requires half-lock from both sides.
+ ''',
)
- map_user.s(0x00f0, 'trade complete',
+ map_user.s(0x00f0, 'trade complete notify',
+ define='SMSG_TRADE_COMPLETE',
fixed=[
at(0, u16, 'packet id'),
at(2, u8, 'fail'),
],
fixed_size=3,
+ pre=[0x00ef],
+ post=[PRETTY],
+ desc='''
+ Trade is finally over.
+ ''',
)
- map_user.s(0x00f2, 'storage status',
+ map_user.s(0x00f2, 'storage size notify',
+ define='SMSG_PLAYER_STORAGE_STATUS',
fixed=[
at(0, u16, 'packet id'),
at(2, u16, 'current slots'),
at(4, u16, 'max slots'),
],
fixed_size=6,
+ pre=[GM, SCRIPT, 0x00f3, 0x00f5, 0x3810],
+ post=[PRETTY],
+ desc='''
+ Update the current/max storage size.
+
+ It's easy to change the max storage on any basis, pity about
+ the inventory limit ...
+ ''',
)
- map_user.r(0x00f3, 'move item to storage request',
+ map_user.r(0x00f3, 'storage put',
+ define='CMSG_MOVE_TO_STORAGE',
fixed=[
at(0, u16, 'packet id'),
at(2, ioff2, 'ioff2'),
at(4, u32, 'amount'),
],
fixed_size=8,
+ pre=[HUMAN],
+ post=[0x00ac, 0x00af, 0x00b0, 0x00f2, 0x00f4, 0x01d7],
+ xpost=[SCRIPT, 0x0080, 0x0081, 0x0088, 0x0091, 0x00a0, 0x00b1, 0x00be, 0x00c0, 0x00e9, 0x00ee, 0x00fd, 0x0106, 0x010f, 0x0119, 0x013a, 0x0141, 0x0196, 0x01b1, 0x01d8, 0x01da, 0x2b01, 0x2b05, 0x3011, 0x3022],
+ desc='''
+ Move item from inventory to storage.
+ ''',
)
- map_user.s(0x00f4, 'move item to storage',
+ map_user.s(0x00f4, 'storage added notify',
+ define='SMSG_PLAYER_STORAGE_ADD',
fixed=[
at(0, u16, 'packet id'),
at(2, soff1, 'soff1'),
@@ -2457,50 +3635,98 @@ def build_context():
at(19, u16, 'card3'),
],
fixed_size=21,
+ pre=[GM, 0x00f3],
+ post=[PRETTY],
+ desc='''
+ Item was added to your storage.
+ ''',
)
- map_user.r(0x00f5, 'move item from storage request',
+ map_user.r(0x00f5, 'storage take',
+ define='CSMG_MOVE_FROM_STORAGE',
fixed=[
at(0, u16, 'packet id'),
at(2, soff1, 'soff1'),
at(4, u32, 'amount'),
],
fixed_size=8,
+ pre=[HUMAN],
+ post=[0x00a0, 0x00b0, 0x00f2, 0x00f6],
+ xpost=[SCRIPT, 0x0080, 0x0081, 0x0088, 0x0091, 0x00ac, 0x00b1, 0x00be, 0x00c0, 0x00e9, 0x00ee, 0x00fd, 0x0106, 0x010f, 0x0119, 0x013a, 0x0141, 0x0196, 0x01b1, 0x01d7, 0x01d8, 0x01da, 0x2b01, 0x2b05, 0x3011, 0x3022],
+ desc='''
+ Move item from storage to inventory.
+ ''',
)
- map_user.s(0x00f6, 'remove item from storage',
+ map_user.s(0x00f6, 'storage removed notify',
+ define='SMSG_PLAYER_STORAGE_REMOVE',
fixed=[
at(0, u16, 'packet id'),
at(2, soff1, 'soff1'),
at(4, u32, 'amount'),
],
fixed_size=8,
+ pre=[0x00f5],
+ post=[PRETTY],
+ desc='''
+ Item was removed from your storage.
+ ''',
)
- map_user.r(0x00f7, 'storage close request',
+ map_user.r(0x00f7, 'storage close',
+ define='CMSG_CLOSE_STORAGE',
fixed=[
at(0, u16, 'packet id'),
],
fixed_size=2,
+ pre=[HUMAN],
+ post=[MAGIC, SCRIPT, 0x00f8, 0x2b01, 0x3011],
+ xpost=[0x0078, 0x007c, 0x0080, 0x0081, 0x0088, 0x0091, 0x00a0, 0x00ac, 0x00b0, 0x00b1, 0x00b6, 0x00be, 0x00c0, 0x00e9, 0x00ee, 0x00fd, 0x0106, 0x010f, 0x0119, 0x013a, 0x0141, 0x0196, 0x01b1, 0x01d7, 0x01d8, 0x01da, 0x2b05, 0x3022],
+ desc='''
+ Close your storage.
+ ''',
)
- map_user.s(0x00f8, 'storage closed',
+ map_user.s(0x00f8, 'storage closed notify',
+ define='SMSG_PLAYER_STORAGE_CLOSE',
fixed=[
at(0, u16, 'packet id'),
],
fixed_size=2,
+ pre=[GM, 0x00e6, 0x00f7],
+ post=[PRETTY],
+ desc='''
+ Your storage was closed.
+ ''',
)
- map_user.r(0x00f9, 'create party request',
+ map_user.r(0x00f9, 'party create',
+ define='CMSG_PARTY_CREATE',
fixed=[
at(0, u16, 'packet id'),
at(2, party_name, 'party name'),
],
fixed_size=26,
+ pre=[HUMAN],
+ post=[0x00fa, 0x110, 0x3020],
+ desc='''
+ Create a new party with yourself.
+ ''',
)
- map_user.s(0x00fa, 'create party',
+ map_user.s(0x00fa, 'party create result',
+ define='SMSG_PARTY_CREATE',
fixed=[
at(0, u16, 'packet id'),
at(2, u8, 'flag'),
],
fixed_size=3,
- )
- map_user.s(0x00fb, 'party info',
+ pre=[GM, 0x00f9, 0x3820],
+ post=[PRETTY],
+ desc='''
+ Result of creating a new party.
+
+ flag 0: success
+ flag 1: bad name
+ flag 2: already in party
+ ''',
+ )
+ map_user.s(0x00fb, 'party info notify',
+ define='SMSG_PARTY_INFO',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -2515,69 +3741,130 @@ def build_context():
at(45, u8, 'online'),
],
repeat_size=46,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0089, 0x3821, 0x3825],
+ post=[PRETTY],
+ desc='''
+ Full info about your party.
+ ''',
)
- map_user.r(0x00fc, 'party invite request',
+ map_user.r(0x00fc, 'party invite',
+ define='CMSG_PARTY_INVITE',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
],
fixed_size=6,
+ pre=[HUMAN],
+ post=[0x00fd, 0x00fe],
+ desc='''
+ Invite player to your party.
+ ''',
)
- map_user.s(0x00fd, 'party invite response',
+ map_user.s(0x00fd, 'party invite result',
+ define='SMSG_PARTY_INVITE_RESPONSE',
fixed=[
at(0, u16, 'packet id'),
at(2, char_name, 'char name'),
at(26, u8, 'flag'),
],
fixed_size=27,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0085, 0x0089, 0x008c, 0x009f, 0x00a2, 0x00a7, 0x00a9, 0x00ab, 0x00b2, 0x00b8, 0x00b9, 0x00bb, 0x00c8, 0x00c9, 0x00e4, 0x00e6, 0x00e8, 0x00eb, 0x00ed, 0x00ef, 0x00f3, 0x00f5, 0x00f7, 0x00fc, 0x00ff, 0x0112, 0x0143, 0x0146, 0x01d5, 0x2afd, 0x2b0d, 0x3822],
+ post=[PRETTY],
+ desc='''
+ Party invitation response.
+
+ flag 0: already in party
+ flag 1: reject
+ flag 2: accept
+ flag 3: party full
+ flag 4: same party
+ ''',
)
- map_user.s(0x00fe, 'party invite succeeded',
+ map_user.s(0x00fe, '(reverse) party invitation',
+ define='SMSG_PARTY_INVITED',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
at(6, party_name, 'party name'),
],
fixed_size=30,
+ pre=[0x00fc],
+ post=[0x00ff],
+ desc='''
+ You're invited to join someone's party.
+ ''',
)
- map_user.r(0x00ff, 'party join request',
+ map_user.r(0x00ff, '(reverse) party invitation result',
+ define='CMSG_PARTY_INVITED',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
at(6, u32, 'flag'),
],
fixed_size=10,
+ pre=[0x00fe],
+ post=[0x00fd, 0x0110, 0x3022],
+ desc='''
+ Reply to party invitation.
+ ''',
)
- map_user.r(0x0100, 'party leave request',
+ map_user.r(0x0100, 'party leave',
+ define='CMSG_PARTY_LEAVE',
fixed=[
at(0, u16, 'packet id'),
],
fixed_size=2,
+ pre=[HUMAN],
+ post=[0x3024],
+ desc='''
+ I'm sick of your lame party.
+ ''',
)
- map_user.s(0x0101, 'party settings',
+ map_user.s(0x0101, 'party option notify',
+ define='SMSG_PARTY_SETTINGS',
fixed=[
at(0, u16, 'packet id'),
at(2, u16, 'exp'),
at(4, u16, 'item'),
],
fixed_size=6,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0089, 0x3821, 0x3823],
+ post=[PRETTY],
+ desc='''
+ Party settings changed.
+ ''',
)
- map_user.r(0x0102, 'party settings request',
+ map_user.r(0x0102, 'party option',
+ define='CMSG_PARTY_SETTINGS',
fixed=[
at(0, u16, 'packet id'),
at(2, u16, 'exp'),
at(4, u16, 'item'),
],
fixed_size=6,
+ pre=[HUMAN],
+ post=[0x3023],
+ desc='''
+ Please change party settings.
+ ''',
)
- map_user.r(0x0103, 'party kick request',
+ map_user.r(0x0103, 'party kick',
+ define='CMSG_PARTY_KICK',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
at(6, char_name, 'unused char name'),
],
fixed_size=30,
+ pre=[HUMAN],
+ post=[0x3024],
+ desc='''
+ Forcibly remove party member.
+ ''',
)
- map_user.s(0x0105, 'party leave',
+ # 0x0104 define='SMSG_PARTY_MOVE',
+ map_user.s(0x0105, 'party left notify',
+ define='SMSG_PARTY_LEAVE',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
@@ -2585,8 +3872,14 @@ def build_context():
at(30, u8, 'flag'),
],
fixed_size=31,
+ pre=[0x3824, 0x3826],
+ post=[PRETTY],
+ desc='''
+ Somebody got tired of your party.
+ ''',
)
- map_user.s(0x0106, 'update party member hp',
+ map_user.s(0x0106, 'party hp notify',
+ define='SMSG_PARTY_UPDATE_HP',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
@@ -2594,8 +3887,14 @@ def build_context():
at(8, u16, 'max hp'),
],
fixed_size=10,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0085, 0x0089, 0x008c, 0x009f, 0x00a2, 0x00a7, 0x00a9, 0x00ab, 0x00b2, 0x00b8, 0x00b9, 0x00bb, 0x00c8, 0x00c9, 0x00e4, 0x00e6, 0x00e8, 0x00eb, 0x00ed, 0x00ef, 0x00f3, 0x00f5, 0x00f7, 0x0112, 0x0143, 0x0146, 0x01d5, 0x2afd, 0x2b0d],
+ post=[PRETTY],
+ desc='''
+ Party member hp update.
+ ''',
)
- map_user.s(0x0107, 'update party member coords',
+ map_user.s(0x0107, 'party xy notify',
+ define='SMSG_PARTY_UPDATE_COORDS',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
@@ -2603,8 +3902,14 @@ def build_context():
at(8, u16, 'y'),
],
fixed_size=10,
- )
- map_user.r(0x0108, 'party message request',
+ pre=[TIMER],
+ post=[PRETTY],
+ desc='''
+ Party member location update.
+ ''',
+ )
+ map_user.r(0x0108, 'party message',
+ define='CMSG_PARTY_MESSAGE',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -2614,8 +3919,14 @@ def build_context():
at(0, u8, 'c'),
],
repeat_size=1,
- )
- map_user.s(0x0109, 'party message',
+ pre=[HUMAN],
+ post=[0x2b0e, 0x3003, 0x3027],
+ desc='''
+ Talk privately to your party.
+ ''',
+ )
+ map_user.s(0x0109, 'party message notify',
+ define='SMSG_PARTY_MESSAGE',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -2625,16 +3936,17 @@ def build_context():
repeat=[
at(0, u8, 'c'),
],
- repeat_size=1
- )
- map_user.s(0x010c, 'MVP (unused)',
- fixed=[
- at(0, u16, 'packet id'),
- at(2, block_id, 'block id'),
- ],
- fixed_size=6,
+ repeat_size=1,
+ pre=[0x3827],
+ post=[PRETTY],
+ desc='''
+ Somebody in your party is talking to you.
+ ''',
)
- map_user.s(0x010e, 'raise a skill',
+ # 0x010c define='SMSG_MVP',
+ map_user.s(0x010e, 'skill raise result',
+ # define='SMSG_GUILD_SKILL_UP',
+ define='SMSG_PLAYER_SKILL_UP',
fixed=[
at(0, u16, 'packet id'),
at(2, skill_id, 'skill id'),
@@ -2644,8 +3956,14 @@ def build_context():
at(10, u8, 'can raise'),
],
fixed_size=11,
- )
- map_user.s(0x010f, 'player skills',
+ pre=[0x0112],
+ post=[PRETTY],
+ desc='''
+ Successfully raised a skill.
+ ''',
+ )
+ map_user.s(0x010f, 'skill info notify',
+ define='SMSG_PLAYER_SKILLS',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -2655,8 +3973,14 @@ def build_context():
at(0, skill_info, 'info'),
],
repeat_size=37,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0085, 0x0089, 0x008c, 0x009f, 0x00a2, 0x00a7, 0x00a9, 0x00ab, 0x00b2, 0x00b8, 0x00b9, 0x00bb, 0x00c8, 0x00c9, 0x00e4, 0x00e6, 0x00e8, 0x00eb, 0x00ed, 0x00ef, 0x00f3, 0x00f5, 0x00f7, 0x0112, 0x0143, 0x0146, 0x01d5, 0x2afd, 0x2b0d],
+ post=[PRETTY],
+ desc='''
+ Enumeration of your skills.
+ ''',
)
map_user.s(0x0110, 'skill failed',
+ define='SMSG_SKILL_FAILED',
fixed=[
at(0, u16, 'packet id'),
at(2, skill_id, 'skill id'),
@@ -2666,21 +3990,42 @@ def build_context():
at(9, u8, 'type'),
],
fixed_size=10,
+ pre=[0x0089, 0x00bf, 0x00e4, 0x00f9, 0x00ff],
+ post=[PRETTY],
+ desc='''
+ Failed to perform a skill.
+ ''',
)
- map_user.r(0x0112, 'request a skill lvl up',
+ map_user.r(0x0112, 'skill raise',
+ define='CMSG_SKILL_LEVELUP_REQUEST',
fixed=[
at(0, u16, 'packet id'),
at(2, skill_id, 'skill id'),
],
fixed_size=4,
+ pre=[HUMAN],
+ post=[0x00b0, 0x010e, 0x010f],
+ xpost=[SCRIPT, 0x0080, 0x0081, 0x0088, 0x0091, 0x00a0, 0x00ac, 0x00b1, 0x00be, 0x00c0, 0x00e9, 0x00ee, 0x00fd, 0x0106, 0x0119, 0x013a, 0x0141, 0x0196, 0x01b1, 0x01d7, 0x01d8, 0x01da, 0x2b01, 0x2b05, 0x3011, 0x3022],
+ desc='''
+ Spend skill points to raise your skills.
+ ''',
)
- map_user.r(0x0118, 'stop attack request',
+ # 0x0113 define='CMSG_SKILL_USE_BEING',
+ # 0x0116 define='CMSG_SKILL_USE_POSITION',
+ map_user.r(0x0118, 'attack stop',
+ define='CMSG_PLAYER_STOP_ATTACK',
fixed=[
at(0, u16, 'packet id'),
],
fixed_size=2,
+ pre=[HUMAN],
+ post=[IDLE],
+ desc='''
+ Cancel a continuous attack.
+ ''',
)
- map_user.s(0x0119, 'change player status',
+ map_user.s(0x0119, 'player option notify',
+ define='SMSG_PLAYER_STATUS_CHANGE',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'block id'),
@@ -2690,8 +4035,16 @@ def build_context():
at(12, u8, 'zero'),
],
fixed_size=13,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0085, 0x0089, 0x008c, 0x009f, 0x00a2, 0x00a7, 0x00a9, 0x00ab, 0x00b2, 0x00b8, 0x00b9, 0x00bb, 0x00c8, 0x00c9, 0x00e4, 0x00e6, 0x00e8, 0x00eb, 0x00ed, 0x00ef, 0x00f3, 0x00f5, 0x00f7, 0x0112, 0x0143, 0x0146, 0x01d5, 0x2afd, 0x2b0d],
+ post=[PRETTY],
+ desc='''
+ Update 3/4ths of the option fields.
+ ''',
)
- map_user.s(0x0139, 'move player to within attack range',
+ # 0x011a define='SMSG_SKILL_NO_DAMAGE',
+ # 0x011b define='CMSG_SKILL_USE_MAP',
+ map_user.s(0x0139, 'player move attack range notify',
+ define='SMSG_PLAYER_MOVE_TO_ATTACK',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'block id'),
@@ -2702,29 +4055,54 @@ def build_context():
at(14, u16, 'range'),
],
fixed_size=16,
+ pre=[0x0089],
+ post=[PRETTY],
+ desc='''
+ You are moving to enter attack range.
+ ''',
)
- map_user.s(0x013a, 'player attack range',
+ map_user.s(0x013a, 'player attack range notify',
+ define='SMSG_PLAYER_ATTACK_RANGE',
fixed=[
at(0, u16, 'packet id'),
at(2, u16, 'attack range'),
],
fixed_size=4,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0085, 0x0089, 0x008c, 0x009f, 0x00a2, 0x00a7, 0x00a9, 0x00ab, 0x00b2, 0x00b8, 0x00b9, 0x00bb, 0x00c8, 0x00c9, 0x00e4, 0x00e6, 0x00e8, 0x00eb, 0x00ed, 0x00ef, 0x00f3, 0x00f5, 0x00f7, 0x0112, 0x0143, 0x0146, 0x01d5, 0x2afd, 0x2b0d],
+ post=[PRETTY],
+ desc='''
+ Update attack range field.
+ ''',
)
- map_user.s(0x013b, 'player arrow message',
+ map_user.s(0x013b, 'player arrow fail notify',
+ define='SMSG_PLAYER_ARROW_MESSAGE',
fixed=[
at(0, u16, 'packet id'),
at(2, u16, 'type'),
],
fixed_size=4,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x0089, 0x00a9],
+ post=[PRETTY],
+ desc='''
+ Arrow status: failed (0) or equipped (3, ignored).
+ ''',
)
- map_user.s(0x013c, 'player arrow equip',
+ map_user.s(0x013c, 'player arrow equip notify',
+ define='SMSG_PLAYER_ARROW_EQUIP',
fixed=[
at(0, u16, 'packet id'),
at(2, ioff2, 'ioff2'),
],
fixed_size=4,
+ pre=[0x007d, 0x00a9],
+ post=[PRETTY],
+ desc='''
+ Arrow equip inventory slot.
+ ''',
)
+ # 0x013e define='SMSG_SKILL_CASTING',
map_user.s(0x0141, 'player stat update 3',
+ define='SMSG_PLAYER_STAT_UPDATE_3',
fixed=[
at(0, u16, 'packet id'),
at(2, sp, 'sp type'),
@@ -2733,65 +4111,142 @@ def build_context():
at(10, u32, 'value b e'),
],
fixed_size=14,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0085, 0x0089, 0x008c, 0x009f, 0x00a2, 0x00a7, 0x00a9, 0x00ab, 0x00b2, 0x00b8, 0x00b9, 0x00bb, 0x00c8, 0x00c9, 0x00e4, 0x00e6, 0x00e8, 0x00eb, 0x00ed, 0x00ef, 0x00f3, 0x00f5, 0x00f7, 0x0112, 0x0143, 0x0146, 0x01d5, 0x2afd, 0x2b0d],
+ post=[PRETTY],
+ desc='''
+ Update base and cumulative (?) stat points.
+ ''',
)
- map_user.s(0x0142, 'npc integer input',
+ map_user.s(0x0142, '(reverse) script input integer',
+ define='SMSG_NPC_INT_INPUT',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'block id'),
],
fixed_size=6,
+ pre=[SCRIPT],
+ post=[0x0143],
+ desc='''
+ Npc wants an integer.
+ ''',
)
- map_user.r(0x0143, 'npc integer response',
+ map_user.r(0x0143, '(reverse) script input integer result',
+ define='CMSG_NPC_INT_RESPONSE',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'block id'),
at(6, u32, 'input int value'),
],
fixed_size=10,
+ pre=[0x0142],
+ post=[MAGIC, SCRIPT],
+ xpost=[0x0078, 0x007c, 0x0080, 0x0081, 0x0088, 0x0091, 0x00a0, 0x00ac, 0x00b0, 0x00b1, 0x00b6, 0x00be, 0x00c0, 0x00e9, 0x00ee, 0x00fd, 0x0106, 0x010f, 0x0119, 0x013a, 0x0141, 0x0196, 0x01b1, 0x01d7, 0x01d8, 0x01da, 0x2b01, 0x2b05, 0x3011, 0x3022],
+ desc='''
+ Npc can have an integer.
+ ''',
)
- map_user.r(0x0146, 'npc close request',
+ map_user.r(0x0146, '(reverse) script close response',
+ define='CMSG_NPC_CLOSE',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'block id'),
],
fixed_size=6,
+ pre=[0x00b6],
+ post=[MAGIC, SCRIPT],
+ xpost=[0x0078, 0x007c, 0x0080, 0x0081, 0x0088, 0x0091, 0x00a0, 0x00ac, 0x00b0, 0x00b1, 0x00b6, 0x00be, 0x00c0, 0x00e9, 0x00ee, 0x00fd, 0x0106, 0x010f, 0x0119, 0x013a, 0x0141, 0x0196, 0x01b1, 0x01d7, 0x01d8, 0x01da, 0x2b01, 0x2b05, 0x3011, 0x3022],
+ desc='''
+ Interactive npc chat closed, maybe finish noninteractively now.
+ ''',
)
- map_user.s(0x0147, 'single skill info (unused)',
- fixed=[
- at(0, u16, 'packet id'),
- at(2, skill_info, 'info'),
- ],
- fixed_size=39,
- )
- map_user.s(0x0148, 'being resurrected',
+ map_user.s(0x0148, 'being resurrected notify',
+ define='SMSG_BEING_RESURRECT',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'block id'),
at(6, u16, 'type'),
],
fixed_size=8,
- )
- map_user.r(0x014d, 'guild check master (unused)',
- fixed=[
- at(0, u16, 'packet id'),
- ],
- fixed_size=2,
- )
+ pre=[GM],
+ post=[PRETTY],
+ desc='''
+ It's alive!
+ ''',
+ )
+ # 0x0149 define='CMSG_ADMIN_MUTE',
+ # 0x014c define='SMSG_GUILD_ALIANCE_INFO',
+ # 0x014d define='CMSG_GUILD_CHECK_MASTER',
+ # 0x014e define='SMSG_GUILD_MASTER_OR_MEMBER',
+ # 0x014f define='CMSG_GUILD_REQUEST_INFO',
+ # 0x0151 define='CMSG_GUILD_REQUEST_EMBLEM',
+ # 0x0152 define='SMSG_GUILD_EMBLEM',
+ # 0x0153 define='CMSG_GUILD_CHANGE_EMBLEM',
+ # 0x0154 define='SMSG_GUILD_MEMBER_LIST',
+ # 0x0155 define='CMSG_GUILD_CHANGE_MEMBER_POS',
+ # 0x0156 define='SMSG_GUILD_MEMBER_POS_CHANGE',
+ # 0x0159 define='CMSG_GUILD_LEAVE',
+ # 0x015a define='SMSG_GUILD_LEAVE',
+ # 0x015b define='CMSG_GUILD_EXPULSION',
+ # 0x015c define='SMSG_GUILD_EXPULSION',
+ # 0x015d define='CMSG_GUILD_BREAK',
+ # 0x015e define='SMSG_GUILD_BROKEN',
+ # 0x0160 define='SMSG_GUILD_POS_INFO_LIST',
+ # 0x0161 define='CMSG_GUILD_CHANGE_POS_INFO',
+ # 0x0162 define='SMSG_GUILD_SKILL_INFO',
+ # 0x0163 define='SMSG_GUILD_EXPULSION_LIST',
+ # 0x0165 define='CMSG_GUILD_CREATE',
+ # 0x0166 define='SMSG_GUILD_POS_NAME_LIST',
+ # 0x0167 define='SMSG_GUILD_CREATE_RESPONSE',
+ # 0x0168 define='CMSG_GUILD_INVITE',
+ # 0x0169 define='SMSG_GUILD_INVITE_ACK',
+ # 0x016a define='SMSG_GUILD_INVITE',
+ # 0x016b define='CMSG_GUILD_INVITE_REPLY',
+ # 0x016c define='SMSG_GUILD_POSITION_INFO',
+ # 0x016d define='SMSG_GUILD_MEMBER_LOGIN',
+ # 0x016e define='CMSG_GUILD_CHANGE_NOTICE',
+ # 0x016f define='SMSG_GUILD_NOTICE',
+ # 0x0170 define='CMSG_GUILD_ALLIANCE_REQUEST',
+ # 0x0171 define='SMSG_GUILD_REQ_ALLIANCE',
+ # 0x0172 define='CMSG_GUILD_ALLIANCE_REPLY',
+ # 0x0173 define='SMSG_GUILD_REQ_ALLIANCE_ACK',
+ # 0x0174 define='SMSG_GUILD_POSITION_CHANGED',
+ # 0x017e define='CMSG_GUILD_MESSAGE',
+ # 0x017f define='SMSG_GUILD_MESSAGE',
+ # 0x0180 define='CMSG_GUILD_OPPOSITION',
+ # 0x0181 define='SMSG_GUILD_OPPOSITION_ACK',
+ # 0x0183 define='CMSG_GUILD_ALLIANCE_DELETE',
+ # 0x0184 define='SMSG_GUILD_DEL_ALLIANCE',
map_user.r(0x018a, 'client quit',
+ define='CMSG_CLIENT_QUIT',
fixed=[
at(0, u16, 'packet id'),
at(2, u16, 'unused'),
],
fixed_size=4,
+ pre=[NOTHING],
+ post=[0x018b],
+ desc='''
+ Request explicit end of connection.
+ ''',
)
- map_user.s(0x018b, 'map quit response',
+ map_user.s(0x018b, 'client quit result',
+ define='SMSG_MAP_QUIT_RESPONSE',
fixed=[
at(0, u16, 'packet id'),
at(2, u16, 'okay'),
],
fixed_size=4,
+ pre=[GM, 0x00b2, 0x018a],
+ post=[PRETTY],
+ desc='''
+ Result of explicit end of connection.
+ ''',
)
- map_user.s(0x0195, 'guild party info (unused)',
+ # 0x0190 define='CMSG_SKILL_USE_POSITION_MORE',
+ # 0x0193 define='CMSG_SOLVE_CHAR_NAME',
+ # 0x0194 define='SMSG_SOLVE_CHAR_NAME',
+ map_user.s(0x0195, 'guild party info notify',
+ define='SMSG_PLAYER_GUILD_PARTY_INFO',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'block id'),
@@ -2801,8 +4256,14 @@ def build_context():
at(78, str24, 'guild pos again'),
],
fixed_size=102,
+ pre=[0x0094],
+ post=[PRETTY],
+ desc='''
+ Name of player's party and guild.
+ ''',
)
- map_user.s(0x0196, 'being status change',
+ map_user.s(0x0196, 'being status change notify',
+ define='SMSG_BEING_STATUS_CHANGE',
fixed=[
at(0, u16, 'packet id'),
at(2, status_change, 'sc type'),
@@ -2810,16 +4271,32 @@ def build_context():
at(8, u8, 'flag'),
],
fixed_size=9,
- )
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0085, 0x0089, 0x008c, 0x009f, 0x00a2, 0x00a7, 0x00a9, 0x00ab, 0x00b2, 0x00b8, 0x00b9, 0x00bb, 0x00c8, 0x00c9, 0x00e4, 0x00e6, 0x00e8, 0x00eb, 0x00ed, 0x00ef, 0x00f3, 0x00f5, 0x00f7, 0x0112, 0x0143, 0x0146, 0x01d5, 0x2afd, 0x2b0d],
+ post=[PRETTY],
+ desc='''
+ Being adds/removes a persistent status effect.
+ ''',
+ )
+ # 0x0199 define='SMSG_PVP_MAP_MODE',
+ # 0x019a define='SMSG_PVP_SET',
map_user.s(0x019b, 'being effect',
+ define='SMSG_BEING_SELFEFFECT',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'block id'),
at(6, u32, 'type'),
],
fixed_size=10,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0089],
+ post=[PRETTY],
+ desc='''
+ Being runs a one-shot (?) effect.
+ ''',
)
- map_user.s(0x01b1, 'trade item add response',
+ # 0x019C define='CMSG_ADMIN_LOCAL_ANNOUNCE',
+ # 0x019D define='CMSG_ADMIN_HIDE',
+ map_user.s(0x01b1, 'trade add result',
+ define='SMSG_TRADE_ITEM_ADD_RESPONSE',
fixed=[
at(0, u16, 'packet id'),
at(2, ioff2, 'ioff2'),
@@ -2827,8 +4304,16 @@ def build_context():
at(6, u8, 'fail'),
],
fixed_size=7,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0085, 0x0089, 0x008c, 0x009f, 0x00a2, 0x00a7, 0x00a9, 0x00ab, 0x00b2, 0x00b8, 0x00b9, 0x00bb, 0x00c8, 0x00c9, 0x00e4, 0x00e6, 0x00e8, 0x00eb, 0x00ed, 0x00ef, 0x00f3, 0x00f5, 0x00f7, 0x0112, 0x0143, 0x0146, 0x01d5, 0x2afd, 0x2b0d],
+ post=[PRETTY],
+ desc='''
+ Result of trying to add an item/zeny to your trade offer.
+ ''',
)
- map_user.s(0x01c8, 'use inventory item succeeded',
+ # 0x01b6 define='SMSG_GUILD_BASIC_INFO',
+ # 0x01b9 define='SMSG_SKILL_CAST_CANCEL',
+ map_user.s(0x01c8, 'use item result',
+ define='SMSG_PLAYER_INVENTORY_USE',
fixed=[
at(0, u16, 'packet id'),
at(2, ioff2, 'ioff2'),
@@ -2838,15 +4323,29 @@ def build_context():
at(12, u8, 'ok'),
],
fixed_size=13,
+ pre=[0x00a7],
+ post=[PRETTY],
+ desc='''
+ You used (or tried to use) an item in your inventory.
+
+ Currently used only in the success case.
+ ''',
)
- map_user.s(0x01d4, 'npc string input',
+ map_user.s(0x01d4, '(reverse) script input string',
+ define='SMSG_NPC_STR_INPUT',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'block id'),
],
fixed_size=6,
- )
- map_user.r(0x01d5, 'npc string response',
+ pre=[SCRIPT],
+ post=[0x01d5],
+ desc='''
+ Npc wants a string.
+ ''',
+ )
+ map_user.r(0x01d5, '(reverse) script input string result',
+ define='CMSG_NPC_STR_RESPONSE',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -2857,8 +4356,15 @@ def build_context():
at(0, u8, 'c'),
],
repeat_size=1,
+ pre=[0x01d4],
+ post=[MAGIC, SCRIPT],
+ xpost=[0x0078, 0x007c, 0x0080, 0x0081, 0x0088, 0x0091, 0x00a0, 0x00ac, 0x00b0, 0x00b1, 0x00b6, 0x00be, 0x00c0, 0x00e9, 0x00ee, 0x00fd, 0x0106, 0x010f, 0x0119, 0x013a, 0x0141, 0x0196, 0x01b1, 0x01d7, 0x01d8, 0x01da, 0x2b01, 0x2b05, 0x3011, 0x3022],
+ desc='''
+ Npc can have an integer.
+ ''',
)
- map_user.s(0x01d7, 'change being appearance (unused)',
+ map_user.s(0x01d7, 'being change look',
+ define='SMSG_BEING_CHANGE_LOOKS2',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'block id'),
@@ -2867,9 +4373,18 @@ def build_context():
at(9, item_name_id, 'shield'),
],
fixed_size=11,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0085, 0x0089, 0x008c, 0x009f, 0x00a2, 0x00a7, 0x00a9, 0x00ab, 0x00b2, 0x00b8, 0x00b9, 0x00bb, 0x00c8, 0x00c9, 0x00e4, 0x00e6, 0x00e8, 0x00eb, 0x00ed, 0x00ef, 0x00f3, 0x00f5, 0x00f7, 0x0112, 0x0143, 0x0146, 0x01d5, 0x2afd, 0x2b0d],
+ post=[PRETTY],
+ desc='''
+ Being change appearance.
+
+ This may be a weapon type, an item nameid, or just a value -
+ it all depends on which look type.
+ ''',
)
# very similar to, but not compatible with, 0x01d9 and 0x01da
- map_user.s(0x01d8, 'player update 1',
+ map_user.s(0x01d8, 'player appear notify',
+ define='SMSG_PLAYER_UPDATE_1',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'block id'),
@@ -2900,9 +4415,17 @@ def build_context():
at(52, u16, 'unused'),
],
fixed_size=54,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0085, 0x0089, 0x008c, 0x009f, 0x00a2, 0x00a7, 0x00a9, 0x00ab, 0x00b2, 0x00b8, 0x00b9, 0x00bb, 0x00c8, 0x00c9, 0x00e4, 0x00e6, 0x00e8, 0x00eb, 0x00ed, 0x00ef, 0x00f3, 0x00f5, 0x00f7, 0x0112, 0x0143, 0x0146, 0x01d5, 0x2afd, 0x2b0d],
+ post=[0x0094, 0x00b2],
+ desc='''
+ A player appeared (unmoving).
+
+ Like 0x0078 but for players, and only in the "enter area" case.
+ ''',
)
# very similar to, but not compatible with, 0x01d8 and 0x01da
- map_user.s(0x01d9, 'player update 2',
+ map_user.s(0x01d9, 'player appear notify',
+ define='SMSG_PLAYER_UPDATE_2',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'block id'),
@@ -2932,9 +4455,17 @@ def build_context():
at(51, u16, 'unused'),
],
fixed_size=53,
+ pre=[0x007d],
+ post=[0x0094],
+ desc='''
+ A wild player appeared!
+
+ Like 0x0078 but for players, but only in the "spawn on map" case.
+ ''',
)
# very similar to, but not compatible with, 0x01d8 and 0x01d9
- map_user.s(0x01da, 'player move',
+ map_user.s(0x01da, 'player move notify',
+ define='SMSG_PLAYER_MOVE',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'block id'),
@@ -2966,8 +4497,17 @@ def build_context():
at(58, u16, 'unused'),
],
fixed_size=60,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0085, 0x0089, 0x008c, 0x009f, 0x00a2, 0x00a7, 0x00a9, 0x00ab, 0x00b2, 0x00b8, 0x00b9, 0x00bb, 0x00c8, 0x00c9, 0x00e4, 0x00e6, 0x00e8, 0x00eb, 0x00ed, 0x00ef, 0x00f3, 0x00f5, 0x00f7, 0x0112, 0x0143, 0x0146, 0x01d5, 0x2afd, 0x2b0d],
+ post=[0x0094],
+ desc='''
+ A player appeared, moving.
+
+ Like 0x007b but for players.
+ ''',
)
map_user.s(0x01de, 'deal skill damage',
+ # define='CMSG_LOGIN_REGISTER2', with a different body ...
+ define='SMSG_SKILL_DAMAGE',
fixed=[
at(0, u16, 'packet id'),
at(2, skill_id, 'skill id'),
@@ -2982,8 +4522,14 @@ def build_context():
at(32, u8, 'type or hit'),
],
fixed_size=33,
- )
- map_user.s(0x01ee, 'player inventory',
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x0089],
+ post=[PRETTY],
+ desc='''
+ Took damage from a skill.
+ ''',
+ )
+ map_user.s(0x01ee, 'inventory list notify',
+ define='SMSG_PLAYER_INVENTORY',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -3002,8 +4548,14 @@ def build_context():
at(16, u16, 'card3'),
],
repeat_size=18,
- )
- map_user.s(0x01f0, 'storage item list',
+ pre=[0x007d],
+ post=[PRETTY],
+ desc='''
+ List of all items in inventory.
+ ''',
+ )
+ map_user.s(0x01f0, 'storage list notify',
+ define='SMSG_PLAYER_STORAGE_ITEMS',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -3022,16 +4574,32 @@ def build_context():
at(16, u16, 'card3'),
],
repeat_size=18,
+ pre=[GM, SCRIPT, 0x3810],
+ post=[PRETTY],
+ desc='''
+ List of all items in storage.
+ ''',
)
- map_user.s(0x020c, 'set being ip',
+ map_user.s(0x020c, 'player ip notify',
+ define='SMSG_BEING_IP_RESPONSE',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'block id'),
at(6, ip4, 'ip'),
],
fixed_size=10,
+ pre=[0x0094],
+ post=[PRETTY],
+ desc='''
+ Show a player's (hashed) IP, for detecting alts.
+
+ The hash is rerandomized every restart.
+ ''',
)
+ # 0x0210 define='CMSG_ONLINE_LIST',
+ # 0x0211 define='SMSG_ONLINE_LIST',
map_user.s(0x0212, 'npc command',
+ define='SMSG_NPC_COMMAND',
fixed=[
at(0, u16, 'packet id'),
at(2, block_id, 'npc id'),
@@ -3041,16 +4609,28 @@ def build_context():
at(14, u16, 'y'),
],
fixed_size=16,
- )
-
+ pre=[NOTHING],
+ post=[PRETTY],
+ desc='''
+ Make an npc do fancy things (for Manaplus).
+ ''',
+ )
+ # 0x0213 define='CMSG_SET_STATUS',
+ # 0x0214 define='SMSG_QUEST_SET_VAR',
+ # 0x0215 define='SMSG_QUEST_PLAYER_VARS',
+ # 0x0220 define='SMSG_BEING_NAME_RESPONSE2',
+ # 0x0221 define='SMSG_CHAR_CREATE_SUCCEEDED2',
+ # 0x0222 define='CMSG_CHAT_MESSAGE2',
+ # 0x0223 define='SMSG_BEING_CHAT2',
+ # 0x0224 define='SMSG_PLAYER_CHAT2',
+ # 0x0225 define='SMSG_BEING_MOVE3',
+ # 0x0226 define='SMSG_MAP_MASK',
+ # 0x0227 define='SMSG_MAP_MUSIC',
+ # 0x0228 define='SMSG_NPC_CHANGETITLE',
+
+ # TOC_LOGINCHAR
# login char
- login_char.r(0x2709, 'reload gm accounts request',
- fixed=[
- at(0, u16, 'packet id'),
- ],
- fixed_size=2,
- )
- login_char.r(0x2710, 'add char server request',
+ login_char.r(0x2710, 'server connect char',
fixed=[
at(0, u16, 'packet id'),
at(2, account_name, 'account name'),
@@ -3064,15 +4644,25 @@ def build_context():
at(84, u16, 'is new'),
],
fixed_size=86,
+ pre=[BOOT],
+ post=[0x2711, 0x2732],
+ desc='''
+ Become an authenticated char server.
+ ''',
)
- login_char.s(0x2711, 'add char server result',
+ login_char.s(0x2711, 'server connect char result',
fixed=[
at(0, u16, 'packet id'),
at(2, u8, 'code'),
],
fixed_size=3,
+ pre=[0x2710],
+ post=[FINISH, IDLE],
+ desc='''
+ Result of auth'ing as a char server.
+ ''',
)
- login_char.r(0x2712, 'account auth request',
+ login_char.r(0x2712, 'account auth',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
@@ -3082,6 +4672,11 @@ def build_context():
at(15, ip4, 'ip'),
],
fixed_size=19,
+ pre=[0x0065],
+ post=[0x2713, 0x2729],
+ desc='''
+ Check whether client's cookies are okay.
+ ''',
)
login_char.s(0x2713, 'account auth result',
fixed=[
@@ -3089,35 +4684,60 @@ def build_context():
at(2, account_id, 'account id'),
at(6, u8, 'invalid'),
at(7, account_email, 'email'),
- at(47, time32, 'connect until'),
+ at(47, time32, 'unused connect until'),
],
fixed_size=51,
+ pre=[0x2712],
+ post=[0x006b, 0x006c],
+ desc='''
+ Send account auth status to tmwa-char.
+
+ Status:
+ 0: good
+ 1: bad
+ ''',
)
- login_char.r(0x2714, 'online count',
+ login_char.r(0x2714, 'online count notify',
fixed=[
at(0, u16, 'packet id'),
at(2, u32, 'users'),
],
fixed_size=6,
+ pre=[TIMER],
+ post=[IDLE],
+ desc='''
+ Update count of online users.
+
+ This occurs every few seconds, so is also used for antifreeze if enabled.
+ ''',
)
- login_char.r(0x2716, 'email limit request',
+ login_char.r(0x2716, 'email limit',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
],
fixed_size=6,
+ pre=[0x0065],
+ post=[0x2717],
+ desc='''
+ Fetch current email (and previously, validity limit) for an account.
+ ''',
)
login_char.s(0x2717, 'email limit result',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
at(6, account_email, 'email'),
- at(46, time32, 'connect until'),
+ at(46, time32, 'unused connect until'),
],
fixed_size=50,
+ pre=[0x2716],
+ post=[IDLE],
+ desc='''
+ Yield current email (and previously, validity limit) for an account.
+ ''',
)
- # 0x2b0a
- login_char.r(0x2720, 'become gm request',
+ login_char.r(0x2720, 'become gm account',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -3126,17 +4746,26 @@ def build_context():
head_size=8,
repeat=[at(0, u8, 'c')],
repeat_size=1,
+ pre=[0x2b0a],
+ post=[0x2721, 0x2732],
+ desc='''
+ Grant privileges by password.
+ ''',
)
- login_char.s(0x2721, 'become gm reply',
+ login_char.s(0x2721, 'become gm account reply',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
at(6, gm, 'gm level'),
],
fixed_size=10,
+ pre=[0x2720],
+ post=[0x2b0b],
+ desc='''
+ Maybe granted privileges?
+ ''',
)
- # 0x2b0c
- login_char.r(0x2722, 'account email change request',
+ login_char.r(0x2722, 'account email change',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
@@ -3144,14 +4773,24 @@ def build_context():
at(46, account_email, 'new email'),
],
fixed_size=86,
+ pre=[0x2b0c],
+ post=[IDLE],
+ desc='''
+ Change account email.
+ ''',
)
- login_char.s(0x2723, 'changesex reply',
+ login_char.s(0x2723, 'changesex result/notify',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
at(6, sex, 'sex'),
],
fixed_size=7,
+ pre=[0x2727, 0x793c],
+ post=[0x2b0d],
+ desc='''
+ Set was flipped (if from char server) or set to an absolute value (if set from admin).
+ ''',
)
login_char.r(0x2724, 'block status',
fixed=[
@@ -3160,6 +4799,15 @@ def build_context():
at(6, u32, 'status'),
],
fixed_size=10,
+ pre=[0x2b0e],
+ post=[0x2731],
+ desc='''
+ Set an account's blocked status, see 0x006a but add one.
+
+ The only really useful values here are 0 ("unblock") and
+ 5 ("block"). Don't use this for state 7 ("ban") because it
+ requires a timestamp argument.
+ ''',
)
login_char.r(0x2725, 'ban add',
fixed=[
@@ -3168,6 +4816,12 @@ def build_context():
at(6, human_time_diff, 'ban add'),
],
fixed_size=18,
+ pre=[0x2b0e],
+ post=[0x2731],
+ desc='''
+ Adjust the time of an account's temporary ban. If the account
+ is not already banned, first set the ban to the current time.
+ ''',
)
# evil packet, see also 0x794e
login_admin.s(0x2726, 'broadcast',
@@ -3181,15 +4835,24 @@ def build_context():
at(0, u8, 'c'),
],
repeat_size=1,
+ pre=[0x794e],
+ post=[0x3800],
+ desc='''
+ This packet is evil.
+ ''',
)
- login_char.r(0x2727, 'change sex request',
+ login_char.r(0x2727, 'change sex',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
],
fixed_size=6,
+ pre=[0x2b0e],
+ post=[0x2723],
+ desc='''
+ Flip account's gender.
+ ''',
)
- # 0x2b10, 0x2b11
login_char.r(0x2728, 'update account reg2',
head=[
at(0, u16, 'packet id'),
@@ -3202,8 +4865,19 @@ def build_context():
at(32, u32, 'value'),
],
repeat_size=36,
+ pre=[0x2b10],
+ post=[0x2729],
+ desc='''
+ Update account's login-stored variables.
+
+ These start with ## and are unused because:
+
+ 1. They didn't work at all before I started working on the server.
+ 2. We only run one char-server so we might as well store vars there.
+ 3. The meaning would be weird anyway.
+ ''',
)
- login_char.s(0x2729, 'update account reg2',
+ login_char.s(0x2729, 'update account reg2 notify',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -3215,22 +4889,40 @@ def build_context():
at(32, u32, 'value'),
],
repeat_size=36,
+ pre=[0x2712, 0x2728],
+ post=[0x2b11],
+ desc='''
+ Updated account's ##variables.
+
+ This is sent both in response to 0x2728 and in response to
+ 0x2712 cookie check.
+ '''
)
- login_char.r(0x272a, 'unban request',
+ login_char.r(0x272a, 'unban',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
],
fixed_size=6,
+ pre=[0x2b0e],
+ post=[IDLE],
+ desc='''
+ Clear an account's temporary ban date.
+ ''',
)
- login_char.s(0x2730, 'account deleted',
+ login_char.s(0x2730, 'account deleted notify',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
],
fixed_size=6,
+ pre=[0x7932],
+ post=[0x2afe, 0x2b12, 0x2b13, 0x3821, 0x3824, 0x3826],
+ desc='''
+ Account just doesn't exist anymore.
+ ''',
)
- login_char.s(0x2731, 'status or ban changed',
+ login_char.s(0x2731, 'status or ban changed notify',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
@@ -3238,8 +4930,13 @@ def build_context():
at(7, time32, 'status or ban until'),
],
fixed_size=11,
+ pre=[0x2724, 0x2725, 0x7936, 0x794a, 0x794c],
+ post=[0x2b14],
+ desc='''
+ Account has a new ban date or block status.
+ ''',
)
- login_char.s(0x2732, 'gm account list',
+ login_char.s(0x2732, 'gm account list notify',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -3250,8 +4947,13 @@ def build_context():
at(4, gm1, 'gm level'),
],
repeat_size=5,
+ pre=[TIMER, 0x2710, 0x2720, 0x793e, 0x7955],
+ post=[0x2b15],
+ desc='''
+ Send GM accounts to all character servers.
+ ''',
)
- login_char.r(0x2740, 'change password request',
+ login_char.r(0x2740, 'change password',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
@@ -3259,24 +4961,29 @@ def build_context():
at(30, account_pass, 'new pass'),
],
fixed_size=54,
+ pre=[0x0061],
+ post=[0x2741],
+ desc='''
+ Change password of an account.
+ ''',
)
- login_char.s(0x2741, 'change password reply',
+ login_char.s(0x2741, 'change password result',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
at(6, u8, 'status'),
],
fixed_size=7,
+ pre=[0x2740],
+ post=[0x0062],
+ desc='''
+ Password changed or not.
+ ''',
)
+ # TOC_CHARMAP
# char map
- char_map.r(0x2af7, 'reload gm db',
- fixed=[
- at(0, u16, 'packet id'),
- ],
- fixed_size=2,
- )
- char_map.r(0x2af8, 'add map server request',
+ char_map.r(0x2af8, 'server connect map',
fixed=[
at(0, u16, 'packet id'),
at(2, account_name, 'account name'),
@@ -3286,15 +4993,27 @@ def build_context():
at(58, u16, 'port'),
],
fixed_size=60,
+ pre=[TIMER],
+ post=[0x2af9, 0x2b15],
+ desc='''
+ Become an authenticated map server.
+ ''',
)
- char_map.s(0x2af9, 'add map server result',
+ char_map.s(0x2af9, 'server connect map result',
fixed=[
at(0, u16, 'packet id'),
at(2, u8, 'code'),
],
fixed_size=3,
+ pre=[0x2af8],
+ post=[FINISH, SCRIPT, 0x2afa],
+ desc='''
+ Did I auth?
+ ''',
)
# wtf duplicate v
+ # formerly 0x2afa, now fixed, but now sorted wrong
+ # (should go below, but don't want to break diff)
char_map.r(0x2afa, 'map list',
head=[
at(0, u16, 'packet id'),
@@ -3305,25 +5024,34 @@ def build_context():
at(0, map_name, 'map name'),
],
repeat_size=16,
+ pre=[0x2af9],
+ post=[0x2afb, 0x2b04],
+ desc='''
+ Tell the char server what maps I have.
+ ''',
)
# wtf duplicate ^
- char_map.s(0x2afa, 'itemfrob',
- fixed=[
- at(0, u16, 'packet id'),
- at(2, item_name_id4, 'source item id'),
- at(6, item_name_id4, 'dest item id'),
- ],
- fixed_size=10,
- )
- char_map.s(0x2afb, 'map list ack',
+ # formerly 0x2afa, now fixed, but now sorted wrong
+ # (should go below, but don't want to break diff)
+ #
+ # (now erased)
+
+ char_map.s(0x2afb, 'map list result',
fixed=[
at(0, u16, 'packet id'),
at(2, u8, 'unknown'),
at(3, char_name, 'whisper name'),
],
fixed_size=27,
+ pre=[0x2afa],
+ post=[FINISH, IDLE],
+ desc='''
+ I got your maps.
+
+ (having pronoun consistency problems here)
+ ''',
)
- char_map.r(0x2afc, 'character auth request',
+ char_map.r(0x2afc, 'character auth',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
@@ -3333,19 +5061,30 @@ def build_context():
at(18, ip4, 'ip'),
],
fixed_size=22,
+ pre=[0x0072],
+ post=[0x2afd, 0x2afe],
+ desc='''
+ Check whether client's cookies are okay.
+ ''',
)
- char_map.s(0x2afd, 'character auth and data',
+ char_map.s(0x2afd, 'character auth success',
payload=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
at(4, account_id, 'account id'),
at(8, u32, 'login id2'),
- at(12, time32, 'connect until'),
+ at(12, time32, 'unused connect until'),
at(16, u16, 'packet tmw version'),
at(18, char_key, 'char key'),
at(None, char_data, 'char data'),
],
payload_size=None,
+ pre=[0x2afc],
+ post=[0x0073, 0x0081, 0x0091, 0x3005, 0x3021],
+ xpost=[GM, SCRIPT, 0x0080, 0x0088, 0x00a0, 0x00ac, 0x00b0, 0x00b1, 0x00be, 0x00c0, 0x00e9, 0x00ee, 0x00fd, 0x0106, 0x010f, 0x0119, 0x013a, 0x0141, 0x0196, 0x01b1, 0x01d7, 0x01d8, 0x01da, 0x2b01, 0x2b05, 0x3011, 0x3022],
+ desc='''
+ Account authentication succeeded.
+ ''',
)
char_map.s(0x2afe, 'character auth error',
fixed=[
@@ -3353,6 +5092,11 @@ def build_context():
at(2, account_id, 'account id'),
],
fixed_size=6,
+ pre=[0x0068, 0x2730, 0x2afc],
+ post=[0x0081],
+ desc='''
+ Send account id to tmwa-map for disconnection.
+ ''',
)
char_map.r(0x2aff, 'user list',
head=[
@@ -3365,6 +5109,11 @@ def build_context():
at(0, char_id, 'char id'),
],
repeat_size=4,
+ pre=[TIMER],
+ post=[IDLE],
+ desc='''
+ Where can everybody be found?
+ ''',
)
char_map.s(0x2b00, 'total users',
fixed=[
@@ -3372,6 +5121,11 @@ def build_context():
at(2, u32, 'users'),
],
fixed_size=6,
+ pre=[TIMER],
+ post=[IDLE],
+ desc='''
+ How many people are there in total?
+ ''',
)
char_map.r(0x2b01, 'character save',
payload=[
@@ -3383,8 +5137,13 @@ def build_context():
at(None, char_data, 'char data'),
],
payload_size=None,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0085, 0x0089, 0x008c, 0x009f, 0x00a2, 0x00a7, 0x00a9, 0x00ab, 0x00b2, 0x00b8, 0x00b9, 0x00bb, 0x00c8, 0x00c9, 0x00e4, 0x00e6, 0x00e8, 0x00eb, 0x00ed, 0x00ef, 0x00f3, 0x00f5, 0x00f7, 0x0112, 0x0143, 0x0146, 0x01d5, 0x2afd, 0x2b0d],
+ post=[IDLE],
+ desc='''
+ Full character save.
+ ''',
)
- char_map.r(0x2b02, 'char select req',
+ char_map.r(0x2b02, 'char select',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
@@ -3393,16 +5152,26 @@ def build_context():
at(14, ip4, 'ip'),
],
fixed_size=18,
+ pre=[0x00b2],
+ post=[0x2b03],
+ desc='''
+ Client is going back to select character again.
+ ''',
)
- char_map.s(0x2b03, 'char select res',
+ char_map.s(0x2b03, 'char select result',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
at(6, u8, 'unknown'),
],
fixed_size=7,
+ pre=[0x2b02],
+ post=[0x00b3],
+ desc='''
+ Client can go back to select character again.
+ ''',
)
- char_map.s(0x2b04, 'map list broadcast',
+ char_map.s(0x2b04, 'map list notify',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -3414,8 +5183,13 @@ def build_context():
at(0, map_name, 'map name'),
],
repeat_size=16,
+ pre=[0x2afa],
+ post=[IDLE],
+ desc='''
+ Send remote map information to everyone.
+ ''',
)
- char_map.r(0x2b05, 'change map server request',
+ char_map.r(0x2b05, 'change map server',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
@@ -3431,6 +5205,11 @@ def build_context():
at(45, ip4, 'client ip'),
],
fixed_size=49,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0085, 0x0089, 0x008c, 0x009f, 0x00a2, 0x00a7, 0x00a9, 0x00ab, 0x00b2, 0x00b8, 0x00b9, 0x00bb, 0x00c8, 0x00c9, 0x00e4, 0x00e6, 0x00e8, 0x00eb, 0x00ed, 0x00ef, 0x00f3, 0x00f5, 0x00f7, 0x0112, 0x0143, 0x0146, 0x01d5, 0x2afd, 0x2b0d],
+ post=[0x2b06],
+ desc='''
+ Client wants to use a remote map.
+ ''',
)
char_map.s(0x2b06, 'change map server ack',
fixed=[
@@ -3446,9 +5225,13 @@ def build_context():
at(42, u16, 'map port'),
],
fixed_size=44,
+ pre=[0x2b05],
+ post=[0x0081, 0x0092],
+ desc='''
+ Client can use a remote map.
+ ''',
)
- # 0x2720
- char_map.r(0x2b0a, 'become gm request',
+ char_map.r(0x2b0a, 'become gm',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -3457,6 +5240,11 @@ def build_context():
head_size=8,
repeat=[at(0, u8, 'c')],
repeat_size=1,
+ pre=[GM],
+ post=[0x2720, 0x2b0b],
+ desc='''
+ Get a GM level from a password.
+ ''',
)
char_map.s(0x2b0b, 'become gm result',
fixed=[
@@ -3465,9 +5253,13 @@ def build_context():
at(6, gm, 'gm level'),
],
fixed_size=10,
+ pre=[0x2721, 0x2b0a],
+ post=[IDLE],
+ desc='''
+ Got a GM level from a password, or not.
+ ''',
)
- # 0x2722
- char_map.r(0x2b0c, 'change email request',
+ char_map.r(0x2b0c, 'change email',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
@@ -3475,6 +5267,11 @@ def build_context():
at(46, account_email, 'new email'),
],
fixed_size=86,
+ pre=[GM],
+ post=[0x2722],
+ desc='''
+ Player used @email.
+ ''',
)
char_map.s(0x2b0d, 'sex changed notify',
fixed=[
@@ -3483,8 +5280,14 @@ def build_context():
at(6, sex, 'sex'),
],
fixed_size=7,
+ pre=[0x2723],
+ post=[0x00ac, 0x01d7, 0x2b01, 0x3011],
+ xpost=[SCRIPT, 0x0080, 0x0081, 0x0088, 0x0091, 0x00a0, 0x00b0, 0x00b1, 0x00be, 0x00c0, 0x00e9, 0x00ee, 0x00fd, 0x0106, 0x010f, 0x0119, 0x013a, 0x0141, 0x0196, 0x01b1, 0x01d8, 0x01da, 0x2b05, 0x3022],
+ desc='''
+ Kick someone who had a sex-change operation.
+ ''',
)
- char_map.r(0x2b0e, 'named char operation request',
+ char_map.r(0x2b0e, 'named char operation',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
@@ -3493,8 +5296,13 @@ def build_context():
at(32, human_time_diff, 'ban add'),
],
fixed_size=44,
+ pre=[GM, SCRIPT, 0x008c, 0x0096, 0x0108],
+ post=[0x2724, 0x2725, 0x2727, 0x272a, 0x2b0f],
+ desc='''
+ Perform block/ban/unblock/unban/sexchange by name.
+ ''',
)
- char_map.r(0x2b0f, 'named char operation answer',
+ char_map.r(0x2b0f, 'named char operation result',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
@@ -3503,9 +5311,13 @@ def build_context():
at(32, u16, 'error'),
],
fixed_size=34,
+ pre=[0x2b0e],
+ post=[IDLE],
+ desc='''
+ Maybe performed block/ban/unblock/unban/sexchange by name.
+ ''',
)
- # 0x2728, 0x2729
- char_map.r(0x2b10, 'account reg2 update',
+ char_map.r(0x2b10, 'account reg2',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -3517,8 +5329,13 @@ def build_context():
at(32, u32, 'value'),
],
repeat_size=36,
+ pre=[SCRIPT],
+ post=[0x2728],
+ desc='''
+ Update login-stored ##registers.
+ ''',
)
- char_map.s(0x2b11, 'account reg2 update',
+ char_map.s(0x2b11, 'account reg2 notify',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -3530,6 +5347,11 @@ def build_context():
at(32, u32, 'value'),
],
repeat_size=36,
+ pre=[0x2729],
+ post=[IDLE],
+ desc='''
+ Broadcast login-stored ##registers.
+ ''',
)
char_map.s(0x2b12, 'divorce notify',
fixed=[
@@ -3538,6 +5360,11 @@ def build_context():
at(6, char_id, 'partner id'),
],
fixed_size=10,
+ pre=[0x0068, 0x2730, 0x2b16],
+ post=[IDLE],
+ desc='''
+ Somebody either performed a divorce or had it done to them.
+ ''',
)
char_map.s(0x2b13, 'account delete notify',
fixed=[
@@ -3545,6 +5372,11 @@ def build_context():
at(2, account_id, 'account id'),
],
fixed_size=6,
+ pre=[0x2730],
+ post=[IDLE],
+ desc='''
+ Disconnect player who was deleted.
+ ''',
)
char_map.s(0x2b14, 'status or ban notify',
fixed=[
@@ -3554,6 +5386,11 @@ def build_context():
at(7, time32, 'status or ban until'),
],
fixed_size=11,
+ pre=[0x2731],
+ post=[IDLE],
+ desc='''
+ Somebody was banned or otherwise had their status changed.
+ ''',
)
char_map.s(0x2b15, 'gm account list notify',
head=[
@@ -3566,16 +5403,29 @@ def build_context():
at(4, gm1, 'gm level'),
],
repeat_size=5,
+ pre=[0x2732, 0x2af8],
+ post=[IDLE],
+ desc='''
+ Update full list of GM accounts.
+ ''',
)
- char_map.r(0x2b16, 'divorce request',
+ char_map.r(0x2b16, 'divorce',
fixed=[
at(0, u16, 'packet id'),
at(2, char_id, 'char id'),
],
fixed_size=6,
+ pre=[SCRIPT],
+ post=[0x2b12],
+ desc='''
+ Live the single life again.
+ ''',
)
+ # 2bfa/2bfb are injected above
+
+ # TOC_INTERMAP
- char_map.r(0x3000, 'gm broadcast',
+ char_map.r(0x3000, 'gm broadcast begin',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -3585,8 +5435,13 @@ def build_context():
at(0, u8, 'c'),
],
repeat_size=1,
+ pre=[GM, SCRIPT],
+ post=[0x3800],
+ desc='''
+ Yell at everybody.
+ ''',
)
- char_map.r(0x3001, 'whisper forward',
+ char_map.r(0x3001, 'whisper remote begin',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -3598,17 +5453,26 @@ def build_context():
at(0, u8, 'c'),
],
repeat_size=1,
+ pre=[0x0096],
+ post=[0x3801, 0x3802],
+ desc='''
+ Begin forwarding a private message to a nonlocal map server.
+ ''',
)
- char_map.r(0x3002, 'whisper forward result',
+ char_map.r(0x3002, 'whisper remote forward result',
fixed=[
at(0, u16, 'packet id'),
at(2, char_id, 'char id'),
at(6, u8, 'flag'),
],
fixed_size=7,
+ pre=[0x3801],
+ post=[0x3802],
+ desc='''
+ Intermediate result of forwarding a private message to a nonlocal map server.
+ ''',
)
- # 0x3803
- char_map.r(0x3003, 'wgm forward',
+ char_map.r(0x3003, 'wgm remote begin',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -3620,8 +5484,12 @@ def build_context():
at(0, u8, 'c'),
],
repeat_size=1,
+ pre=[GM, 0x008c, 0x0096, 0x0108],
+ post=[0x3803],
+ desc='''
+ Begin GM whisper to all map servers.
+ ''',
)
- # 0x3804
char_map.r(0x3004, 'save account reg',
head=[
at(0, u16, 'packet id'),
@@ -3634,6 +5502,11 @@ def build_context():
at(32, u32, 'value'),
],
repeat_size=36,
+ pre=[MAGIC, SCRIPT],
+ post=[0x3804],
+ desc='''
+ Save all char-server-stored account registers.
+ ''',
)
char_map.r(0x3005, 'want account reg',
fixed=[
@@ -3641,15 +5514,25 @@ def build_context():
at(2, account_id, 'account id'),
],
fixed_size=6,
+ pre=[0x2afd],
+ post=[0x3804],
+ desc='''
+ Explicitly request values of char-server-stored account registers.
+ ''',
)
- char_map.r(0x3010, 'want storage',
+ char_map.r(0x3010, 'load storage',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
],
fixed_size=6,
+ pre=[GM, SCRIPT],
+ post=[0x3810],
+ desc='''
+ Request access to storage.
+ ''',
)
- char_map.r(0x3011, 'got storage',
+ char_map.r(0x3011, 'save storage',
payload=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -3657,8 +5540,13 @@ def build_context():
at(8, storage, 'storage'),
],
payload_size=None,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0085, 0x0089, 0x008c, 0x009f, 0x00a2, 0x00a7, 0x00a9, 0x00ab, 0x00b2, 0x00b8, 0x00b9, 0x00bb, 0x00c8, 0x00c9, 0x00e4, 0x00e6, 0x00e8, 0x00eb, 0x00ed, 0x00ef, 0x00f3, 0x00f5, 0x00f7, 0x0112, 0x0143, 0x0146, 0x01d5, 0x2afd, 0x2b0d],
+ post=[0x3811],
+ desc='''
+ Transmission of changed storage.
+ ''',
)
- char_map.r(0x3020, 'create party',
+ char_map.r(0x3020, 'party create',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
@@ -3668,13 +5556,23 @@ def build_context():
at(70, u16, 'level'),
],
fixed_size=72,
+ pre=[GM, 0x00f9],
+ post=[0x3820, 0x3821],
+ desc='''
+ Request creation of a party.
+ ''',
)
- char_map.r(0x3021, 'request party info',
+ char_map.r(0x3021, 'party needinfo',
fixed=[
at(0, u16, 'packet id'),
at(2, party_id, 'party id'),
],
fixed_size=6,
+ pre=[0x2afd],
+ post=[0x3821],
+ desc='''
+ Request full info about a party.
+ ''',
)
char_map.r(0x3022, 'party add member',
fixed=[
@@ -3686,6 +5584,11 @@ def build_context():
at(50, u16, 'level'),
],
fixed_size=52,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0085, 0x0089, 0x008c, 0x009f, 0x00a2, 0x00a7, 0x00a9, 0x00ab, 0x00b2, 0x00b8, 0x00b9, 0x00bb, 0x00c8, 0x00c9, 0x00e4, 0x00e6, 0x00e8, 0x00eb, 0x00ed, 0x00ef, 0x00f3, 0x00f5, 0x00f7, 0x00ff, 0x0112, 0x0143, 0x0146, 0x01d5, 0x2afd, 0x2b0d],
+ post=[0x3821, 0x3822, 0x3823],
+ desc='''
+ Request to add a party member in a slot somewhere.
+ ''',
)
char_map.r(0x3023, 'party change option',
fixed=[
@@ -3696,6 +5599,11 @@ def build_context():
at(12, u16, 'item'),
],
fixed_size=14,
+ pre=[0x0102],
+ post=[0x3823],
+ desc='''
+ Explicitly request a change of party settings.
+ ''',
)
char_map.r(0x3024, 'party leave',
fixed=[
@@ -3704,6 +5612,11 @@ def build_context():
at(6, account_id, 'account id'),
],
fixed_size=10,
+ pre=[0x0100, 0x0103, 0x3822],
+ post=[0x3821, 0x3824, 0x3826],
+ desc='''
+ Remove a member from party.
+ ''',
)
char_map.r(0x3025, 'party change map',
fixed=[
@@ -3715,8 +5628,17 @@ def build_context():
at(27, u16, 'level'),
],
fixed_size=29,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0089],
+ post=[0x3823, 0x3825],
+ desc='''
+ A party member has:
+
+ 1. loaded a new map
+ 2. levelled up
+ 3. logged out
+ ''',
)
- char_map.r(0x3027, 'party message',
+ char_map.r(0x3027, 'party message remote begin',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -3728,6 +5650,11 @@ def build_context():
at(0, u8, 'c'),
],
repeat_size=1,
+ pre=[0x0108],
+ post=[0x3827],
+ desc='''
+ Begin to send a party message to other map servers.
+ ''',
)
char_map.r(0x3028, 'party check conflict',
fixed=[
@@ -3737,9 +5664,16 @@ def build_context():
at(10, char_name, 'char name'),
],
fixed_size=34,
+ pre=[FINISH, GM, MAGIC, SCRIPT, TIMER, 0x007d, 0x0089, 0x3822],
+ post=[0x3821, 0x3824, 0x3826],
+ desc='''
+ Explicitly request a conflict check.
+
+ (I am not sure this is actually meaningful).
+ ''',
)
- char_map.s(0x3800, 'gm broadcast',
+ char_map.s(0x3800, 'gm broadcast forward',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -3749,8 +5683,13 @@ def build_context():
at(0, u8, 'c'),
],
repeat_size=1,
+ pre=[0x2726, 0x3000],
+ post=[0x009a, 0x00c0],
+ desc='''
+ Yell, reaching everybody.
+ ''',
)
- char_map.s(0x3801, 'whisper forward',
+ char_map.s(0x3801, 'whisper remote forward',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -3763,17 +5702,26 @@ def build_context():
at(0, u8, 'c'),
],
repeat_size=1,
+ pre=[0x3001],
+ post=[0x0097, 0x3002],
+ desc='''
+ Intermediate forwarding a private message to a nonlocal map server.
+ ''',
)
- char_map.s(0x3802, 'whisper result',
+ char_map.s(0x3802, 'whisper remote begin result',
fixed=[
at(0, u16, 'packet id'),
at(2, char_name, 'sender char name'),
at(26, u8, 'flag'),
],
fixed_size=27,
+ pre=[0x3001, 0x3002],
+ post=[0x0098],
+ desc='''
+ Final result of forwarding a private message to a nonlocal map server.
+ ''',
)
- # 0x3003
- char_map.s(0x3803, 'whisper gm',
+ char_map.s(0x3803, 'wgm remote forward',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -3785,9 +5733,13 @@ def build_context():
at(0, u8, 'c'),
],
repeat_size=1,
+ pre=[0x3003],
+ post=[0x0097],
+ desc='''
+ Forward of GM whisper.
+ ''',
)
- # 0x3004
- char_map.s(0x3804, 'broadcast account reg',
+ char_map.s(0x3804, 'account reg notify',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -3799,8 +5751,15 @@ def build_context():
at(32, u32, 'value'),
],
repeat_size=36,
+ pre=[0x3004, 0x3005],
+ post=[IDLE],
+ desc='''
+ Char-server-stored account regs have changed.
+
+ Also sent on explicit request.
+ ''',
)
- char_map.s(0x3810, 'load storage',
+ char_map.s(0x3810, 'load storage result',
payload=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -3808,16 +5767,26 @@ def build_context():
at(8, storage, 'storage'),
],
payload_size=None,
+ pre=[0x3010],
+ post=[0x00a6, 0x00f2, 0x01f0],
+ desc='''
+ Transmission of requested storage.
+ ''',
)
- char_map.s(0x3811, 'save storage ack',
+ char_map.s(0x3811, 'save storage result',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
at(6, u8, 'unknown'),
],
fixed_size=7,
+ pre=[0x3011],
+ post=[IDLE],
+ desc='''
+ Acknowledgement of saved storage.
+ ''',
)
- char_map.s(0x3820, 'party created',
+ char_map.s(0x3820, 'party create result',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
@@ -3826,8 +5795,13 @@ def build_context():
at(11, party_name, 'party name'),
],
fixed_size=35,
+ pre=[0x3020],
+ post=[0x00fa],
+ desc='''
+ Result of requesting party creation.
+ ''',
)
- char_map.s(0x3821, 'party info maybe',
+ char_map.s(0x3821, 'party needinfo result',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -3838,8 +5812,16 @@ def build_context():
at(0, party_most, 'party most'),
],
option_size=None,
+ pre=[0x0068, 0x2730, 0x3020, 0x3021, 0x3022, 0x3024, 0x3028],
+ post=[0x00c0, 0x00fb, 0x0101],
+ desc='''
+ Full info about a party, it present.
+
+ Payload may be missing if no such party (*should* not
+ happen, but ...).
+ ''',
)
- char_map.s(0x3822, 'party member added',
+ char_map.s(0x3822, 'party add member result',
fixed=[
at(0, u16, 'packet id'),
at(2, party_id, 'party id'),
@@ -3847,8 +5829,15 @@ def build_context():
at(10, u8, 'flag'),
],
fixed_size=11,
+ pre=[0x3022],
+ post=[0x00fd, 0x3024, 0x3028],
+ desc='''
+ Result of trying to add a party member.
+
+ Flag is 1 if party is no slots or something.
+ ''',
)
- char_map.s(0x3823, 'party option changed',
+ char_map.s(0x3823, 'party change option notify',
fixed=[
at(0, u16, 'packet id'),
at(2, party_id, 'party id'),
@@ -3858,8 +5847,15 @@ def build_context():
at(14, u8, 'flag'),
],
fixed_size=15,
+ pre=[0x3022, 0x3023, 0x3025],
+ post=[0x00c0, 0x0101],
+ desc='''
+ Party options were changed.
+
+ Often generated implicitly.
+ ''',
)
- char_map.s(0x3824, 'party member left',
+ char_map.s(0x3824, 'party leave notify',
fixed=[
at(0, u16, 'packet id'),
at(2, party_id, 'party id'),
@@ -3867,8 +5863,13 @@ def build_context():
at(10, char_name, 'char name'),
],
fixed_size=34,
+ pre=[0x0068, 0x2730, 0x3024, 0x3028],
+ post=[0x00c0, 0x0105],
+ desc='''
+ Member is no longer in party.
+ ''',
)
- char_map.s(0x3825, 'party member moved',
+ char_map.s(0x3825, 'party change map notify',
fixed=[
at(0, u16, 'packet id'),
at(2, party_id, 'party id'),
@@ -3878,16 +5879,26 @@ def build_context():
at(27, u16, 'level'),
],
fixed_size=29,
+ pre=[0x3025],
+ post=[0x00c0, 0x00fb],
+ desc='''
+ Party member location/level/online status has changed.
+ ''',
)
- char_map.s(0x3826, 'party broken',
+ char_map.s(0x3826, 'party broken notify',
fixed=[
at(0, u16, 'packet id'),
at(2, party_id, 'party id'),
at(6, u8, 'flag'),
],
fixed_size=7,
+ pre=[BOOT, 0x0068, 0x2730, 0x3024, 0x3028],
+ post=[0x00c0, 0x0105],
+ desc='''
+ A party just isn't there anymore.
+ ''',
)
- char_map.s(0x3827, 'party message',
+ char_map.s(0x3827, 'party message remote forward',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -3899,37 +5910,67 @@ def build_context():
at(0, u8, 'c'),
],
repeat_size=1,
+ pre=[0x3027],
+ post=[0x00c0, 0x0109],
+ desc='''
+ Actually send a party message to other map servers.
+ ''',
)
+ # TOC_MISC
# any client
- any_user.r(0x7530, 'version request',
+ any_user.r(0x7530, 'version',
fixed=[
at(0, u16, 'packet id'),
],
fixed_size=2,
+ pre=[ADMIN, BOOT, 0x7919],
+ post=[0x7531],
+ desc='''
+ Request from client or ladmin for server version.
+ ''',
)
- any_user.s(0x7531, 'version reply',
+ any_user.s(0x7531, 'version result',
fixed=[
at(0, u16, 'packet id'),
at(2, version, 'version'),
],
fixed_size=10,
+ pre=[0x7530],
+ post=[0x0064],
+ desc='''
+ Response to client's request for server version.
+ ''',
)
- any_user.r(0x7532, 'shutdown please',
+ any_user.r(0x7532, 'disconnect',
fixed=[
at(0, u16, 'packet id'),
],
fixed_size=2,
+ pre=[HUMAN],
+ post=[FINISH],
+ desc='''
+ Request from client or ladmin to disconnect.
+ ''',
)
+ # 0x7530 define='CMSG_SERVER_VERSION_REQUEST',
+ # 0x7531 define='SMSG_SERVER_VERSION_RESPONSE',
+ # 0x7532 define='CMSG_CLIENT_DISCONNECT',
+ # TOC_LOGINADMIN
# login admin
- login_admin.r(0x7918, 'admin auth request',
+ login_admin.r(0x7918, 'admin auth',
fixed=[
at(0, u16, 'packet id'),
at(2, u16, 'encryption zero'),
at(4, account_pass, 'account pass'),
],
fixed_size=28,
+ pre=[BOOT],
+ post=[0x7919],
+ desc='''
+ Authenticate as an admin.
+ ''',
)
login_admin.s(0x7919, 'admin auth result',
fixed=[
@@ -3937,16 +5978,26 @@ def build_context():
at(2, u8, 'error'),
],
fixed_size=3,
+ pre=[0x7918],
+ post=[0x7530],
+ desc='''
+ Status of admin authentication.
+ ''',
)
- login_admin.r(0x7920, 'account list request',
+ login_admin.r(0x7920, 'account list',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'start account id'),
at(6, account_id, 'end account id'),
],
fixed_size=10,
+ pre=[ADMIN, 0x7921],
+ post=[0x7921],
+ desc='''
+ Request list of all accounts (between bounds if given).
+ ''',
)
- login_admin.s(0x7921, 'account list reply',
+ login_admin.s(0x7921, 'account list result',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'packet length'),
@@ -3961,22 +6012,13 @@ def build_context():
at(34, u32, 'status'),
],
repeat_size=38,
+ pre=[0x7920],
+ post=[IDLE, 0x7920],
+ desc='''
+ May be truncated, if so should retry with new lower bound.
+ ''',
)
- login_admin.r(0x7924, 'itemfrob',
- fixed=[
- at(0, u16, 'packet id'),
- at(2, item_name_id4, 'source item id'),
- at(6, item_name_id4, 'dest item id'),
- ],
- fixed_size=10,
- )
- login_admin.s(0x7925, 'itemfrob ok',
- fixed=[
- at(0, u16, 'packet id'),
- ],
- fixed_size=2,
- )
- login_admin.r(0x7930, 'account create request',
+ login_admin.r(0x7930, 'account create',
fixed=[
at(0, u16, 'packet id'),
at(2, account_name, 'account name'),
@@ -3985,6 +6027,11 @@ def build_context():
at(51, account_email, 'email'),
],
fixed_size=91,
+ pre=[ADMIN],
+ post=[0x7931],
+ desc='''
+ Account creation request.
+ ''',
)
login_admin.s(0x7931, 'account create result',
fixed=[
@@ -3993,29 +6040,49 @@ def build_context():
at(6, account_name, 'account name'),
],
fixed_size=30,
+ pre=[0x7930],
+ post=[IDLE],
+ desc='''
+ Account creation response.
+ ''',
)
- login_admin.r(0x7932, 'account delete request',
+ login_admin.r(0x7932, 'account delete',
fixed=[
at(0, u16, 'packet id'),
at(2, account_name, 'account name'),
],
fixed_size=26,
+ pre=[ADMIN],
+ post=[0x2730, 0x7933],
+ desc='''
+ Account deletion request.
+ ''',
)
- login_admin.s(0x7933, 'account delete reply',
+ login_admin.s(0x7933, 'account delete result',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
at(6, account_name, 'account name'),
],
fixed_size=30,
+ pre=[0x7932],
+ post=[IDLE],
+ desc='''
+ Account deletion response.
+ ''',
)
- login_admin.r(0x7934, 'password change request',
+ login_admin.r(0x7934, 'password change',
fixed=[
at(0, u16, 'packet id'),
at(2, account_name, 'account name'),
at(26, account_pass, 'password'),
],
fixed_size=50,
+ pre=[ADMIN],
+ post=[0x7935],
+ desc='''
+ Change password request.
+ ''',
)
login_admin.s(0x7935, 'password change result',
fixed=[
@@ -4024,8 +6091,13 @@ def build_context():
at(6, account_name, 'account name'),
],
fixed_size=30,
+ pre=[0x7934],
+ post=[IDLE],
+ desc='''
+ Change password response.
+ ''',
)
- login_admin.r(0x7936, 'account state change request',
+ login_admin.r(0x7936, 'account state change',
fixed=[
at(0, u16, 'packet id'),
at(2, account_name, 'account name'),
@@ -4033,6 +6105,11 @@ def build_context():
at(30, seconds, 'error message'),
],
fixed_size=50,
+ pre=[ADMIN],
+ post=[0x2731, 0x7937],
+ desc='''
+ Account state change request.
+ ''',
)
login_admin.s(0x7937, 'account state change result',
fixed=[
@@ -4042,12 +6119,22 @@ def build_context():
at(30, u32, 'status'),
],
fixed_size=34,
+ pre=[0x7936],
+ post=[IDLE],
+ desc='''
+ Account state change response.
+ ''',
)
- login_admin.r(0x7938, 'server list request',
+ login_admin.r(0x7938, 'server list',
fixed=[
at(0, u16, 'packet id'),
],
fixed_size=2,
+ pre=[ADMIN],
+ post=[0x7939],
+ desc='''
+ Server list and player count request.
+ ''',
)
login_admin.s(0x7939, 'server list result',
head=[
@@ -4064,14 +6151,24 @@ def build_context():
at(30, u16, 'is new'),
],
repeat_size=32,
+ pre=[0x7938],
+ post=[IDLE],
+ desc='''
+ Server list and player count response.
+ ''',
)
- login_admin.r(0x793a, 'password check request',
+ login_admin.r(0x793a, 'password check',
fixed=[
at(0, u16, 'packet id'),
at(2, account_name, 'account name'),
at(26, account_pass, 'password'),
],
fixed_size=50,
+ pre=[ADMIN],
+ post=[0x793b],
+ desc='''
+ Password check request.
+ ''',
)
login_admin.s(0x793b, 'password check result',
fixed=[
@@ -4080,14 +6177,24 @@ def build_context():
at(6, account_name, 'account name'),
],
fixed_size=30,
+ pre=[0x793a],
+ post=[IDLE],
+ desc='''
+ Password check response.
+ ''',
)
- login_admin.r(0x793c, 'change sex request',
+ login_admin.r(0x793c, 'change sex',
fixed=[
at(0, u16, 'packet id'),
at(2, account_name, 'account name'),
at(26, sex_char, 'sex'),
],
fixed_size=27,
+ pre=[ADMIN],
+ post=[0x2723, 0x793d],
+ desc='''
+ Modify sex request.
+ ''',
)
login_admin.s(0x793d, 'change sex result',
fixed=[
@@ -4096,14 +6203,24 @@ def build_context():
at(6, account_name, 'account name'),
],
fixed_size=30,
+ pre=[0x793c],
+ post=[IDLE],
+ desc='''
+ Modify sex response.
+ ''',
)
- login_admin.r(0x793e, 'adjust gm level request',
+ login_admin.r(0x793e, 'adjust gm level',
fixed=[
at(0, u16, 'packet id'),
at(2, account_name, 'account name'),
at(26, gm1, 'gm level'),
],
fixed_size=27,
+ pre=[ADMIN],
+ post=[0x2732, 0x793f],
+ desc='''
+ Modify GM level request.
+ ''',
)
login_admin.s(0x793f, 'adjust gm level result',
fixed=[
@@ -4112,14 +6229,24 @@ def build_context():
at(6, account_name, 'account name'),
],
fixed_size=30,
+ pre=[0x793e],
+ post=[IDLE],
+ desc='''
+ Modify GM level response.
+ ''',
)
- login_admin.r(0x7940, 'change email request',
+ login_admin.r(0x7940, 'change email',
fixed=[
at(0, u16, 'packet id'),
at(2, account_name, 'account name'),
at(26, account_email, 'email'),
],
fixed_size=66,
+ pre=[ADMIN],
+ post=[0x7941],
+ desc='''
+ Modify e-mail request.
+ ''',
)
login_admin.s(0x7941, 'change email result',
fixed=[
@@ -4128,9 +6255,14 @@ def build_context():
at(6, account_name, 'account name'),
],
fixed_size=30,
+ pre=[0x7940],
+ post=[IDLE],
+ desc='''
+ Modify e-mail response.
+ ''',
)
# this packet is insane
- login_admin.r(0x7942, 'change memo request',
+ login_admin.r(0x7942, 'change memo',
head=[
at(0, u16, 'packet id'),
at(2, account_name, 'account name'),
@@ -4141,6 +6273,11 @@ def build_context():
at(0, u8, 'c'),
],
repeat_size=1,
+ pre=[ADMIN],
+ post=[0x7943],
+ desc='''
+ Modify memo request.
+ ''',
)
login_admin.s(0x7943, 'change memo result',
fixed=[
@@ -4149,13 +6286,23 @@ def build_context():
at(6, account_name, 'account name'),
],
fixed_size=30,
+ pre=[0x7942],
+ post=[IDLE],
+ desc='''
+ Modify memo response.
+ ''',
)
- login_admin.r(0x7944, 'account id lookup request',
+ login_admin.r(0x7944, 'account id lookup',
fixed=[
at(0, u16, 'packet id'),
at(2, account_name, 'account name'),
],
fixed_size=26,
+ pre=[ADMIN],
+ post=[0x7945],
+ desc='''
+ Find account id request.
+ ''',
)
login_admin.s(0x7945, 'account id lookup result',
fixed=[
@@ -4164,13 +6311,23 @@ def build_context():
at(6, account_name, 'account name'),
],
fixed_size=30,
+ pre=[0x7944],
+ post=[IDLE],
+ desc='''
+ Find account id response.
+ ''',
)
- login_admin.r(0x7946, 'account name lookup request',
+ login_admin.r(0x7946, 'account name lookup',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
],
fixed_size=6,
+ pre=[ADMIN],
+ post=[0x7947],
+ desc='''
+ Find account name request.
+ ''',
)
login_admin.s(0x7947, 'account name lookup result',
fixed=[
@@ -4179,31 +6336,24 @@ def build_context():
at(6, account_name, 'account name'),
],
fixed_size=30,
+ pre=[0x7946],
+ post=[IDLE],
+ desc='''
+ Find account name response.
+ ''',
)
- login_admin.r(0x7948, 'validity absolute request',
- fixed=[
- at(0, u16, 'packet id'),
- at(2, account_name, 'account name'),
- at(26, time32, 'valid until'),
- ],
- fixed_size=30,
- )
- login_admin.s(0x7949, 'validity absolute result',
- fixed=[
- at(0, u16, 'packet id'),
- at(2, account_id, 'account id'),
- at(6, account_name, 'account name'),
- at(30, time32, 'valid until'),
- ],
- fixed_size=34,
- )
- login_admin.r(0x794a, 'ban absolute request',
+ login_admin.r(0x794a, 'ban absolute',
fixed=[
at(0, u16, 'packet id'),
at(2, account_name, 'account name'),
at(26, time32, 'ban until'),
],
fixed_size=30,
+ pre=[ADMIN],
+ post=[0x2731, 0x794b],
+ desc='''
+ Ban date end change request.
+ ''',
)
login_admin.s(0x794b, 'ban absolute result',
fixed=[
@@ -4213,14 +6363,24 @@ def build_context():
at(30, time32, 'ban until'),
],
fixed_size=34,
+ pre=[0x794a],
+ post=[IDLE],
+ desc='''
+ Ban date end change response.
+ ''',
)
- login_admin.r(0x794c, 'ban relative request',
+ login_admin.r(0x794c, 'ban relative',
fixed=[
at(0, u16, 'packet id'),
at(2, account_name, 'account name'),
at(26, human_time_diff, 'ban add'),
],
fixed_size=38,
+ pre=[ADMIN],
+ post=[0x2731, 0x794d],
+ desc='''
+ Ban date end change request (2).
+ ''',
)
login_admin.s(0x794d, 'ban relative result',
fixed=[
@@ -4230,9 +6390,14 @@ def build_context():
at(30, time32, 'ban until'),
],
fixed_size=34,
+ pre=[0x794c],
+ post=[IDLE],
+ desc='''
+ Ban date end change response (2).
+ ''',
)
# evil packet (see also 0x2726)
- login_admin.r(0x794e, 'broadcast message request',
+ login_admin.r(0x794e, 'broadcast message',
head=[
at(0, u16, 'packet id'),
at(2, u16, 'unused'),
@@ -4243,6 +6408,11 @@ def build_context():
at(0, u8, 'c'),
],
repeat_size=1,
+ pre=[ADMIN],
+ post=[0x2726, 0x794f],
+ desc='''
+ Send broadcast message request.
+ ''',
)
login_admin.s(0x794f, 'broadcast message result',
fixed=[
@@ -4250,30 +6420,23 @@ def build_context():
at(2, u16, 'error'),
],
fixed_size=4,
+ pre=[0x794e],
+ post=[IDLE],
+ desc='''
+ Send broadcast message response.
+ ''',
)
- login_admin.r(0x7950, 'validity relative request',
- fixed=[
- at(0, u16, 'packet id'),
- at(2, account_name, 'account name'),
- at(26, human_time_diff, 'valid add'),
- ],
- fixed_size=38,
- )
- login_admin.s(0x7951, 'validity relative result',
- fixed=[
- at(0, u16, 'packet id'),
- at(2, account_id, 'account id'),
- at(6, account_name, 'account name'),
- at(30, time32, 'valid until'),
- ],
- fixed_size=34,
- )
- login_admin.r(0x7952, 'account name info request',
+ login_admin.r(0x7952, 'account name info',
fixed=[
at(0, u16, 'packet id'),
at(2, account_name, 'account name'),
],
fixed_size=26,
+ pre=[ADMIN],
+ post=[0x7953],
+ desc='''
+ Account information by name request.
+ ''',
)
# this packet is insane
login_admin.s(0x7953, 'account info result',
@@ -4289,7 +6452,7 @@ def build_context():
at(60, millis, 'last login string'),
at(84, str16, 'ip string'),
at(100, account_email, 'email'),
- at(140, time32, 'connect until'),
+ at(140, time32, 'unused connect until'),
at(144, time32, 'ban until'),
at(148, SkewLengthType(u16, 150), 'magic packet length'),
],
@@ -4298,36 +6461,298 @@ def build_context():
at(0, u8, 'c'),
],
repeat_size=1,
+ pre=[0x7952, 0x7954],
+ post=[IDLE],
+ desc='''
+ Account information by name or id response.
+ ''',
)
- login_admin.r(0x7954, 'account id info request',
+ login_admin.r(0x7954, 'account id info',
fixed=[
at(0, u16, 'packet id'),
at(2, account_id, 'account id'),
],
fixed_size=6,
+ pre=[ADMIN],
+ post=[0x7953],
+ desc='''
+ Account information by id request.
+ ''',
)
- login_admin.r(0x7955, 'reload gm signal',
+ login_admin.r(0x7955, 'reload gm',
fixed=[
at(0, u16, 'packet id'),
],
fixed_size=2,
+ pre=[ADMIN],
+ post=[0x2732],
+ desc='''
+ Reload GM file request.
+ ''',
)
+ # TOC_NEW
## new-style packets
- # general packets
- any_user.x(0x8000, 'special hold',
+ # notify packets, standalone, can occur at any time; always 'payload'
+ any_user.s(0x8000, 'special hold notify',
payload=[
at(0, u16, 'packet id'),
# packet 0x8000 is handled specially
at(2, u16, 'packet length'),
],
payload_size=4,
- )
+ pre=[OTHER],
+ post=[OTHER],
+ desc='''
+ A special packet that is handled specially.
+
+ The "is the packet complete" logic will read its given length,
+ but the "skip packet" will only skip 4 bytes, thus allowing
+ transactions. I'm still not entirely convinced that this is a
+ good idea - perhaps explicit 'being transaction buffer' and
+ 'end transaction buffer' packets? Allow nesting?
+ ''',
+ )
+ # invoke/return/error packets, threaded; always 'payload'
+ # invoke: 0x9000
+ # return: 0xA000
+ # error: 0xB000
+ # invoke: 0x9001
+ # return: 0xA001
+ # error: 0xB001
+ # ... or should it be implicit via a wrapper?
+ #
+ # add_call_packet(from=ANY, to=ANY, id='0x?001', name='version info'
+ # invoke_type=struct(), return_type=struct(), error_type=struct())
+ # for that matter, should these things be read from separate files?
+ # still a lot of ambiguous stuff here ...
+ #
+ # no, merging is a bad idea at the low level
+ # ... but for doc it is ...
+
return ctx
+# TOC_DRAWING
+
+def fix_sort(idlst):
+ idlst = set(idlst)
+ return (sorted([i for i in idlst if isinstance(i, SpecialEventOrigin)], key=lambda e: e.name)
+ + sorted([i for i in idlst if not isinstance(i, SpecialEventOrigin)]))
+
+def check(ctx):
+ d = {}
+
+ for ch in ctx._channels:
+ for p in ch.packets:
+ id = p.id
+ if id in d:
+ print('packet 0x%04x duplicated (old=%r, new=%r)' % (id, d[id], p))
+ d[id] = p
+
+ for (id, packet) in sorted(d.items()):
+ if packet.pre != fix_sort(packet.pre):
+ print('packet 0x%04x pre is not sorted' % id)
+ for pre in packet.pre:
+ if isinstance(pre, SpecialEventOrigin):
+ continue
+ if pre not in d:
+ print('packet 0x%04x pre 0x%04x does not exist' % (id, pre))
+ elif id not in d[pre].post and id not in d[pre].xpost:
+ print('packet 0x%04x pre 0x%04x does not have me in post or xpost' % (id, pre))
+ if packet.post != fix_sort(packet.post):
+ print('packet 0x%04x post is not sorted' % id)
+ if packet.xpost != fix_sort(packet.xpost):
+ print('packet 0x%04x xpost is not sorted' % id)
+ if len(set(packet.post) | set(packet.xpost)) != len(packet.post) + len(packet.xpost):
+ print('packet 0x%04x post intersects xpost' % id)
+ for post in packet.post:
+ if isinstance(post, SpecialEventOrigin):
+ continue
+ if post not in d:
+ print('packet 0x%04x post 0x%04x does not exist' % (id, post))
+ elif id not in d[post].pre:
+ print('packet 0x%04x post 0x%04x does not have me in pre' % (id, post))
+
+ return d
+
+def partition(d):
+ ''' given a directed graph in the form
+ {1: [2, 3], 2: [3, 4], 3: [], 4: [], 5: [6], 6: []}
+ return a list of sets of connected keys, in the form
+ [{1, 2, 3, 4}, {5, 6}]
+ '''
+ leaders = {k: k for k in d}
+
+ # this code looks nothing like what I was intending to write
+ changed = True
+ while changed:
+ changed = False
+ for k, vlist in d.items():
+ if vlist:
+ m = min(leaders[v] for v in vlist)
+ if m < leaders[k]:
+ changed = True
+ leaders[k] = m
+ else:
+ m = leaders[k]
+ else:
+ m = leaders[k]
+ for v in vlist:
+ if m < leaders[v]:
+ changed = True
+ leaders[v] = m
+
+ followers = {}
+ for k, v in leaders.items():
+ followers.setdefault(v, []).append(k)
+ return [set(v) for v in followers.values()]
+
+def ids_only(vpost):
+ rv = [e for e in vpost if not isinstance(e, SpecialEventOrigin)]
+ if len(rv) == len(vpost):
+ rv = vpost
+ return rv
+
+def make_dots(ctx):
+ d = check(ctx)
+ # automatically excludes xpost and does not touch pre
+ # disabled because that's still just too many packets for the 0x0063
+ #p = partition({k: ids_only(v.post) for (k, v) in d.items()})
+
+ for g in glob.glob('doc-gen/*.gv'):
+ os.rename(g, g + '.old')
+ for g in glob.glob('doc-gen/Packet-*.md'):
+ os.rename(g, g + '.old')
+
+ for (id, p) in d.items():
+ md = 'doc-gen/Packet-0x%04x.md' % id
+ dot = 'doc-gen/packets-around-0x%04x.gv' % id
+ with OpenWrite(md) as f:
+ f.write(p.wiki_doc())
+ with OpenWrite(dot) as f:
+ # The goal looks sort of like this:
+ #
+ # O O O O
+ # \ / \ /
+ # O O
+ # \ /
+ # \ /
+ # O
+ # / \
+ # / \
+ # O O
+ # / \ / \
+ # O O O O
+ #
+ # except that we also connect any extra connections between those
+ # in particular, this will DTRT for the common skip-case:
+ #
+ # |
+ # O
+ # |\
+ # | O
+ # | |
+ # | O
+ # |/
+ # O
+ # |
+ #
+ # regardless of which node you're drawing from.
+ #
+ # however, note that we do *not* list siblings.
+ #
+ # The above comment is wrong.
+ # Also, remember that none of this would be necessary without
+ # the overbroad dependencies!
+ #
+ # ... except that I got rid of the overbroad dependencies but
+ # had to kept this still. It's arguably nicer anyway, so I
+ # also made it the only way.
+ covered_nodes = sorted(p.pre_set(d, 2) | p.post_set(d, 2))
+ covered_edges = [(a, b) for a in covered_nodes for b in covered_nodes if b in d[a].post]
+ g = Graph()
+ g.default_vertex[u'shape'] = u'box'
+ # g[u'layout'] = u'twopi'
+ # g[u'root'] = u'0x%04x' % id
+ for n in covered_nodes:
+ v = g.vertex(u'0x%04x' % n)
+ v[u'label'] = u'Packet \\N: %s' % d[n].name
+ if n == id:
+ v[u'style'] = u'filled'
+ for (a, b) in covered_edges:
+ g.edge(u'0x%04x' % a, u'0x%04x' % b)
+ for n in covered_nodes:
+ # the center node will be covered specially below
+ if n == id:
+ continue
+ # backward links (both strong and weak)
+ count = 0
+ for p in d[n].pre:
+ # pre specials are always strong links
+ if isinstance(p, SpecialEventOrigin):
+ count += 1
+ elif n in d[p].xpost:
+ # weak backward links
+ pass
+ elif p not in covered_nodes:
+ # don't show mere siblings unless also ancestor/descendent
+ count += 1
+ if count:
+ v = g.vertex(u'0x%04x...pre' % n)
+ v[u'label'] = u'%d more' % count
+ v[u'style'] = u'dashed'
+ g.edge(v, u'0x%04x' % n)
+ # strong forward links
+ count = 0
+ for p in d[n].post:
+ if isinstance(p, SpecialEventOrigin):
+ count += 1
+ elif p not in covered_nodes:
+ count += 1
+ if count:
+ v = g.vertex(u'0x%04x...post' % n)
+ v[u'label'] = u'%d more' % count
+ v[u'style'] = u'dashed'
+ g.edge(u'0x%04x' % n, v)
+ # for the immediate node, also cover specials and weaks
+ for p in d[id].pre:
+ # (there are no weak backward specials)
+ # strong backward specials
+ if isinstance(p, SpecialEventOrigin):
+ g.edge(unicode(p.name), u'0x%04x' % id)
+ # weak backward nodes
+ elif id in d[p].xpost:
+ e = g.edge(u'0x%04x' % p, u'0x%04x' % id)
+ e[u'style']=u'dashed'
+ e[u'weight'] = u'0'
+ for p in d[id].post:
+ # strong forward specials
+ if isinstance(p, SpecialEventOrigin):
+ g.edge(u'0x%04x' % id, unicode(p.name))
+ for p in d[id].xpost:
+ # weak forward specials
+ if isinstance(p, SpecialEventOrigin):
+ e = g.edge(u'0x%04x' % id, unicode(p.name))
+ e[u'style'] = u'dashed'
+ e[u'weight'] = u'0'
+ # weak forward nodes
+ elif p not in covered_nodes:
+ e = g.edge(u'0x%04x' % id, u'0x%04x' % p)
+ e[u'style'] = u'dashed'
+ e[u'weight'] = u'0'
+ g.dot(f, False)
+
+
+ for g in glob.glob('doc-gen/*.old'):
+ print('Obsolete: %s' % g)
+ os.remove(g)
+
+# TOC_MAIN
+
def main():
ctx = build_context()
## teardown
+ make_dots(ctx)
ctx.dump()
if __name__ == '__main__':