Use the username and password entered to separate the save data into accounts.

This commit is contained in:
Loïc Hoguin 2010-05-13 20:45:17 +02:00
parent 894a6b1d9c
commit 9b315de02e
4 changed files with 31 additions and 13 deletions

View File

@ -18,4 +18,4 @@
%% EGS database schema.
-record(users, {gid, pid, socket, auth, charnumber, charname}).
-record(users, {gid, pid, socket, auth, folder, charnumber, charname}).

View File

@ -74,7 +74,7 @@ process_handle(16#020d, CSocket, Version, Packet) ->
case User#users.auth of
Auth ->
log(GID, "good auth, proceed"),
egs_db:users_insert(#users{gid=GID, pid=self(), socket=CSocket, auth= << 0:32 >>}),
egs_db:users_insert(#users{gid=GID, pid=self(), socket=CSocket, auth= << 0:32 >>, folder=User#users.folder}),
egs_proto:send_flags(CSocket, GID),
?MODULE:char_select(CSocket, GID, Version);
_ ->
@ -123,16 +123,23 @@ char_select_handle(16#020b, CSocket, GID, Version, Packet) ->
char_select_handle(16#0d02, CSocket, GID, Version, Packet) ->
log(GID, "character creation"),
User = egs_db:users_select(GID),
[{number, Number}, {char, Char}] = egs_proto:parse_character_create(Packet),
file:write_file(io_lib:format("save/~b-character", [Number]), Char),
file:write_file(io_lib:format("save/~b-character.options", [Number]), << 0:192 >>),
_ = file:make_dir(io_lib:format("save/~s", [User#users.folder])),
file:write_file(io_lib:format("save/~s/~b-character", [User#users.folder, Number]), Char),
file:write_file(io_lib:format("save/~s/~b-character.options", [User#users.folder, Number]), << 0:192 >>),
char_select_load(CSocket, GID, Version, Number);
%% @doc Character selection screen request.
char_select_handle(16#0d06, CSocket, GID, Version, _) ->
log(GID, "send character selection screen"),
egs_proto:send_character_list(CSocket, GID, char_load(0), char_load(1), char_load(2), char_load(3)),
User = egs_db:users_select(GID),
egs_proto:send_character_list(CSocket, GID,
char_load(User#users.folder, 0),
char_load(User#users.folder, 1),
char_load(User#users.folder, 2),
char_load(User#users.folder, 3)),
?MODULE:char_select(CSocket, GID, Version);
%% @doc Unknown command handler. Do nothing.
@ -143,8 +150,8 @@ char_select_handle(Command, CSocket, GID, Version, _) ->
%% @doc Load the given character's data.
char_load(Number) ->
Filename = io_lib:format("save/~b-character", [Number]),
char_load(Folder, Number) ->
Filename = io_lib:format("save/~s/~b-character", [Folder, Number]),
case file:read_file(Filename) of
{ok, Char} ->
{ok, Options} = file:read_file(io_lib:format("~s.options", [Filename])),
@ -156,8 +163,8 @@ char_load(Number) ->
%% @doc Load the selected character and start the main game's loop.
char_select_load(CSocket, GID, Version, Number) ->
[{status, _}, {char, << Name:512/bits, _/bits >>}|_] = char_load(Number),
User = egs_db:users_select(GID),
[{status, _}, {char, << Name:512/bits, _/bits >>}|_] = char_load(User#users.folder, Number),
NewRow = User#users{charnumber=Number, charname=Name},
egs_db:users_insert(NewRow),
?MODULE:lobby_load(CSocket, GID, 16#0100, 16#0100),
@ -168,7 +175,7 @@ char_select_load(CSocket, GID, Version, Number) ->
lobby_load(CSocket, GID, Map, Entry) ->
User = egs_db:users_select(GID),
[{status, 1}, {char, Char}, {options, Options}] = char_load(User#users.charnumber),
[{status, 1}, {char, Char}, {options, Options}] = char_load(User#users.folder, User#users.charnumber),
[{quest, Quest}, {zone, Zone}] = proplists:get_value(Map, ?MAPS, [{quest, "p/quest.gc1.nbl"}, {zone, "p/zone.gc1.nbl"}]),
try
egs_proto:send_character_selected(CSocket, GID, Char, Options),
@ -297,7 +304,7 @@ handle(Command, _, GID, _, Packet) when Command =:= 16#0d07 ->
log(GID, "options changes"),
[{options, Options}] = egs_proto:parse_options_change(Packet),
User = egs_db:users_select(GID),
file:write_file(io_lib:format("save/~b-character.options", [User#users.charnumber]), Options);
file:write_file(io_lib:format("save/~s/~b-character.options", [User#users.folder, User#users.charnumber]), Options);
%% @doc Unknown command handler. Do nothing.

View File

@ -90,12 +90,16 @@ handle(16#0217, CSocket, SessionID, _) ->
%% @doc Authentication request handler. Currently always succeed.
%% Use the temporary session ID as the GID for now.
%% Use username and password as a folder name for saving character data.
%% @todo Handle real GIDs whenever there's real authentication.
handle(16#0219, CSocket, SessionID, _) ->
log(SessionID, "auth success"),
handle(16#0219, CSocket, SessionID, Packet) ->
[{username, Username}, {password, Password}] = egs_proto:parse_auth_request(Packet),
log(SessionID, io_lib:format("auth success for ~s ~s", [Username, Password])),
Auth = crypto:rand_bytes(4),
egs_db:users_insert(#users{gid=SessionID, pid=self(), socket=CSocket, auth=Auth}),
Folder = << Username/binary, "-", Password/binary >>,
log(SessionID, Folder),
egs_db:users_insert(#users{gid=SessionID, pid=self(), socket=CSocket, auth=Auth, folder=Folder}),
egs_proto:send_auth_success(CSocket, SessionID, SessionID, Auth);
%% @doc MOTD request handler. Handles both forms of MOTD requests, US and JP.

View File

@ -111,6 +111,13 @@ packet_split(Packet) ->
[ Split | packet_split(Rest) ]
end.
%% @doc Parse a login authentication command. Return the username and password.
parse_auth_request(Packet) ->
<< _:352, Username:192/bits, Password:192/bits, _/bits >> = Packet,
[{username, re:replace(Username, "\\0+", "", [global, {return, binary}])},
{password, re:replace(Password, "\\0+", "", [global, {return, binary}])}].
%% @doc Parse a character creation command. Return the character number and data.
parse_character_create(Packet) ->