一起做网游吧【7】:服务器端注册和登录处理

C:登录

登录登录登录!!!我听到有人非常不耐烦的声音。

    
%% @copyright GPL
%% @author  --==rix==-- <zeze0556@gmail.com>
%% @doc
%% 主要处理用户的注册和登录.
-module( login ) .

%% API
-export( [login / 3, logout / 1, test / 0,creat/2 ] ) .
-include( "proto.hrl" ) .
-include( "test.hrl" ) .
-include( "schema.hrl" ) .

%% @doc 检查数据库中检索到的记录和用户登录的记录是否一致.
login( { atomic, [] }, _ ) ->
    io:format("login: login error~n"),
    { error, ?ERR_BAD_LOGIN };
login({ atomic, [Player] }, [_Nick, Pass,Pid] = Args) when is_record( Player, player ) ->
    Player1 = Player#player {
		socket = fix_pid( Player#player.socket ),
		pid = fix_pid( Player#player.pid ),
                login_errors = 0,
                online = false,
                ingame = false,
                now_play = 0
		},
    Condition = check_player( Player1, [Pass], [ fun is_account_disabled / 2,
						 fun is_bad_password / 2,
						 fun is_player_busy / 2,
						 fun is_player_online / 2,
						 fun is_client_down / 2,
						 fun is_offline / 2
						 ] ),
    { ok, Player2 } = login( Player1, Condition, Args ),
%%    Player2 = Player3#player{pid = Pid},
    io:format("Player2=~w~n",[Player2]),
    F = fun()->
		mnesia:write( Player2 ) end,
    case mnesia:transaction( F ) of
	{ atomic, ok } ->
	    {ok, Player2};
	_  ->
	    { error, "unknow error, pleaseconnect administrator!" }
    end .

%% @doc 尝试登录用户
login( Nick, Pass, Socket ) when is_list( Nick ), is_list( Pass ), is_pid( Socket ) ->
    login( db:find( player, nick, Nick ), [Nick, Pass, Socket] );
login(Player, bad_password, _) ->
    N = Player#player.login_errors + 1,
    { atomic, MaxLoginErrors } = 
	db:get( cluster_config, 0, max_login_errors ),
    if
	N > MaxLoginErrors ->
	    Player1 = Player#player {
			disabled = true
			},
	    { Player1, { error, "your count have been locked, please connect administrator!" } };
	true ->
	    Player1 = Player#player {
			login_errors = N
			},
	    { Player1, { error, "login failed, try again" } }
    end;
login(Player, accound_disabled, _ ) ->
    { Player, { error, "your count have been locked or the the count does not existed, try again" } };
login(Player, player_online, Args) ->
    logout( Player#player.id ),
    login( Player, player_offline, Args );
login(Player, client_down, [_, _, Socket] ) ->
    router:logout( Player#player.pid),
    { ok, Player };
login(Player, player_busy, Args ) ->
    Temp = login( Player, client_down, Args ),
    router:logout(Player),
    Temp;
login(Player, player_offline, [Nick, _, Socket] ) ->
   io:format( "login check offline ~w    ~w~n", [ ?MODULE, ?LINE] ),
    Player1 = Player#player{online = true, socket=Socket},
    { ok, Player1 }.

%% @doc 检查登录
check_player( Player, Args, [Guard|Rest] ) ->
    case Guard( Player, Args ) of
	{ true, Condition } ->
	    Condition;
	_ ->
	    check_player( Player, Args, Rest )
    end;
check_player(_Player, _Args, [] ) ->
%    io:format( "~w    ~w~n", [ ?MODULE, ?LINE] ),
    unknow_error .

%% @doc 密码错误?
is_bad_password( Player, [Pass] ) ->
    Hash = erlang:phash2( Pass, 1 bsl 32 ),
    Match = Player#player.password == Hash,
    { not Match, bad_password } .

%% @doc 帐号被禁掉? 倒霉蛋
is_account_disabled( Player, _ ) ->
    { Player#player.disabled, account_disabled } .

%% @doc 用户已经在游戏中? 
is_player_busy( Player, _ ) ->
    { Online, _ } = is_player_online( Player, [] ) ,
    Playing = Player#player.ingame /= none,
    { Online and Playing, player_busy } .

%% @doc 用户已在线? 
is_player_online( Player, _ ) ->
    SocketAlive = Player#player.socket /= none,
    PlayerAlive = Player#player.pid /= none,
    { SocketAlive and PlayerAlive, player_online } .

%% @doc 用户已下线? 
is_client_down( Player, _ ) ->
    SocketDown = Player#player.socket == none,
    PlayerAlive = Player#player.pid /= none,
    { SocketDown and PlayerAlive, player_offline } .

%% @doc 用户已下线? 
is_offline( Player, _ ) ->
    SocketDown = Player#player.socket == none,
    PlayerDown = Player#player.pid == none,
    { SocketDown and PlayerDown, player_offline } .

%% @doc 纠正用户进程
fix_pid( Pid ) when is_pid( Pid ) ->
    case erlang:is_process_alive( Pid ) of
	true ->
	    Pid;
	_ ->
	    none
    end;
fix_pid(Pid) ->
    Pid .

%% @doc 用户登出 
logout( OID ) ->
    case db:find( player, OID ) of
	{ atomic, [Player] } ->
	    player:stop( Player#player.pid ),
	    { atomic, ok } = db:set( player, OID, [{pid, none}, { socket, none } ] );
	_ ->
	    oops
    end .

%% @doc test函数 
test() ->
    ok.

%% @doc 添加新用户 
creat( Nick, Pass ) ->
    case db:find (player, nick, Nick) of
        {atomic, []} ->
            Player = #player{
              id = counter:bump( player ),
              nick = Nick,
              password = erlang:phash2( Pass, 1 bsl 32 )
             },
            mnesia:transaction( fun()->mnesia:write( Player ), Player#player.id end ) ,
            {ok, {Nick, Pass}};
        _ ->
            {error, "exist"}
    end.
    </zeze0556@gmail.com>

上面就是登录和创建新用户的所有处理了。大部分的代码都是在检查,检查,检查。相对来说,我反而没有什么要说的了。

因为添加了很多的代码,因此文件现在变成了这样的

    bloggame
|-- ReadMe
`-- server
    |-- doc
    |-- ebin
    |-- makefile
    |-- src
    |   |-- login.erl
    |   |-- Makefile
    |   |-- netgame.app
    |   |-- netgame_app.erl
    |   |-- netgame_deps.erl
    |   |-- netgame.erl
    |   |-- netgame_sup.erl
    |   |-- proto.erl
    |   |-- proto.hrl
    |   |-- reloader.erl
    |   |-- router.erl
    |   |-- schema.erl
    |   |-- schema.hrl
    |   |-- server.erl
    |   |-- tcp_server.erl
    |   `-- test.hrl
    |-- start-dev.sh
    |-- start.sh
    `-- support
        `-- include.mk

5 directories, 21 files

基本上这就是这次所有的更新内容了。每个人看到这里都非常的不耐烦了,为了回应你们的耐心,我将代码的git管理的仓库使用Dropbox共享了,我放在我的Dropbox共享的Public目录下的bloggame.git中,我的Dropbox帐号是zeze0556@gmail.com,我现在还没看Dropbox如何查看获得别人共享的内容,但我知道总有办法的。

发表评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据