Introduce egs_universes for universe handling. Review and move send_021e and send_0222 to psu_proto.
This commit is contained in:
parent
a6563c7378
commit
c91880be1f
@ -77,7 +77,7 @@
|
|||||||
%% General information.
|
%% General information.
|
||||||
id, lid, pid, time, character,
|
id, lid, pid, time, character,
|
||||||
%% Location/state related information.
|
%% Location/state related information.
|
||||||
instancepid, partypid, areatype, area, entryid, pos=#pos{x=0.0, y=0.0, z=0.0, dir=0.0}, shopid,
|
uni, instancepid, partypid, areatype, area, entryid, pos=#pos{x=0.0, y=0.0, z=0.0, dir=0.0}, shopid,
|
||||||
prev_area=#psu_area{questid=0, zoneid=0, mapid=0}, prev_entryid=0, %% universeid
|
prev_area=#psu_area{questid=0, zoneid=0, mapid=0}, prev_entryid=0, %% universeid
|
||||||
%% To be moved or deleted later on.
|
%% To be moved or deleted later on.
|
||||||
setid=0 %% @todo Current area's set number. Move that to psu_instance probably.
|
setid=0 %% @todo Current area's set number. Move that to psu_instance probably.
|
||||||
|
@ -28,3 +28,8 @@
|
|||||||
%% They can be modified freely without problem.
|
%% They can be modified freely without problem.
|
||||||
%% Note that the port should be available and above 1024.
|
%% Note that the port should be available and above 1024.
|
||||||
{game_server, {<< 127, 0, 0, 1 >>, 12061}}.
|
{game_server, {<< 127, 0, 0, 1 >>, 12061}}.
|
||||||
|
|
||||||
|
%% Caps and limitations.
|
||||||
|
|
||||||
|
%% @doc Maximum level players can reach.
|
||||||
|
{level_cap, 200}.
|
||||||
|
BIN
priv/universes/myroom.en_US.txt
Normal file
BIN
priv/universes/myroom.en_US.txt
Normal file
Binary file not shown.
BIN
priv/universes/universes.en_US.txt
Normal file
BIN
priv/universes/universes.en_US.txt
Normal file
Binary file not shown.
@ -64,7 +64,7 @@ event({char_select_create, Slot, CharBin}, #state{gid=GID}) ->
|
|||||||
file:write_file(File, CharBin),
|
file:write_file(File, CharBin),
|
||||||
file:write_file(io_lib:format("~s.options", [File]), << 0:128, 4, 0:56 >>);
|
file:write_file(io_lib:format("~s.options", [File]), << 0:128, 4, 0:56 >>);
|
||||||
|
|
||||||
%% @doc Load the selected character into the game's universe.
|
%% @doc Load the selected character into the game's default universe.
|
||||||
event({char_select_enter, Slot, _BackToPreviousField}, State=#state{gid=GID}) ->
|
event({char_select_enter, Slot, _BackToPreviousField}, State=#state{gid=GID}) ->
|
||||||
{ok, User} = egs_user_model:read(GID),
|
{ok, User} = egs_user_model:read(GID),
|
||||||
Folder = egs_accounts:get_folder(GID),
|
Folder = egs_accounts:get_folder(GID),
|
||||||
@ -76,7 +76,9 @@ event({char_select_enter, Slot, _BackToPreviousField}, State=#state{gid=GID}) ->
|
|||||||
Appearance = psu_appearance:binary_to_tuple(Race, AppearanceBin),
|
Appearance = psu_appearance:binary_to_tuple(Race, AppearanceBin),
|
||||||
Options = psu_characters:options_binary_to_tuple(OptionsBin),
|
Options = psu_characters:options_binary_to_tuple(OptionsBin),
|
||||||
Character = #characters{slot=Slot, name=Name, race=Race, gender=Gender, class=Class, appearance=Appearance, options=Options}, % TODO: temporary set the slot here, won't be needed later
|
Character = #characters{slot=Slot, name=Name, race=Race, gender=Gender, class=Class, appearance=Appearance, options=Options}, % TODO: temporary set the slot here, won't be needed later
|
||||||
User2 = User#egs_user_model{character=Character, area=#psu_area{questid=1100000, zoneid=7, mapid=9202}, entryid=0},
|
UniID = egs_universes:defaultid(),
|
||||||
|
egs_universes:enter(UniID),
|
||||||
|
User2 = User#egs_user_model{uni=UniID, character=Character, area=#psu_area{questid=1100000, zoneid=7, mapid=9202}, entryid=0},
|
||||||
egs_user_model:write(User2),
|
egs_user_model:write(User2),
|
||||||
egs_user_model:item_add(GID, 16#11010000, #psu_special_item_variables{}),
|
egs_user_model:item_add(GID, 16#11010000, #psu_special_item_variables{}),
|
||||||
egs_user_model:item_add(GID, 16#11020000, #psu_special_item_variables{}),
|
egs_user_model:item_add(GID, 16#11020000, #psu_special_item_variables{}),
|
||||||
@ -87,7 +89,6 @@ event({char_select_enter, Slot, _BackToPreviousField}, State=#state{gid=GID}) ->
|
|||||||
egs_user_model:item_add(GID, 16#01010b00, #psu_striking_weapon_item_variables{current_pp=99, max_pp=100, element=#psu_element{type=3, percent=50}}),
|
egs_user_model:item_add(GID, 16#01010b00, #psu_striking_weapon_item_variables{current_pp=99, max_pp=100, element=#psu_element{type=3, percent=50}}),
|
||||||
{ok, User3} = egs_user_model:read(GID),
|
{ok, User3} = egs_user_model:read(GID),
|
||||||
State2 = State#state{slot=Slot},
|
State2 = State#state{slot=Slot},
|
||||||
mnesia:dirty_update_counter(counters, population, 1),
|
|
||||||
psu_game:char_load(User3, State2),
|
psu_game:char_load(User3, State2),
|
||||||
{ok, egs_game, State2}.
|
{ok, egs_game, State2}.
|
||||||
|
|
||||||
|
@ -199,7 +199,7 @@ raw(Command, _Data, State) ->
|
|||||||
|
|
||||||
%% Events.
|
%% Events.
|
||||||
|
|
||||||
%% @todo When changing lobby to the room, 0230 must also be sent. Same when going from room to lobby.
|
%% @todo When changing lobby to the room, or room to lobby, we must perform an universe change.
|
||||||
%% @todo Probably move area_load inside the event and make other events call this one when needed.
|
%% @todo Probably move area_load inside the event and make other events call this one when needed.
|
||||||
event({area_change, QuestID, ZoneID, MapID, EntryID}, State) ->
|
event({area_change, QuestID, ZoneID, MapID, EntryID}, State) ->
|
||||||
event({area_change, QuestID, ZoneID, MapID, EntryID, 16#ffffffff}, State);
|
event({area_change, QuestID, ZoneID, MapID, EntryID, 16#ffffffff}, State);
|
||||||
@ -751,44 +751,37 @@ event(player_type_capabilities_request, _State) ->
|
|||||||
event(ppcube_request, _State) ->
|
event(ppcube_request, _State) ->
|
||||||
psu_game:send_1a04();
|
psu_game:send_1a04();
|
||||||
|
|
||||||
%% @doc Uni cube handler.
|
event(unicube_request, State) ->
|
||||||
event(unicube_request, _State) ->
|
psu_proto:send_021e(egs_universes:all(), State);
|
||||||
psu_game:send_021e();
|
|
||||||
|
|
||||||
%% @doc Uni selection handler. Selecting anything reloads the character which will then be sent to its associated area.
|
%% @todo When selecting 'Your room', don't load a default room that's not yours.
|
||||||
%% @todo When selecting 'Your room', load a default room.
|
event({unicube_select, cancel, _EntryID}, _State) ->
|
||||||
%% @todo When selecting 'Reload', reload the character in the current lobby.
|
ignore;
|
||||||
%% @todo Delete NPC characters and stop the party on entering myroom too.
|
|
||||||
event({unicube_select, Selection, EntryID}, State=#state{gid=GID}) ->
|
event({unicube_select, Selection, EntryID}, State=#state{gid=GID}) ->
|
||||||
|
{ok, User} = egs_user_model:read(GID),
|
||||||
case Selection of
|
case Selection of
|
||||||
cancel -> ignore;
|
|
||||||
16#ffffffff ->
|
16#ffffffff ->
|
||||||
log("uni selection (my room)"),
|
UniID = egs_universes:myroomid(),
|
||||||
psu_proto:send_0230(State),
|
User2 = User#egs_user_model{uni=UniID, area=#psu_area{questid=1120000, zoneid=0, mapid=100}, entryid=0};
|
||||||
% 0220
|
_ ->
|
||||||
{ok, User} = egs_user_model:read(GID),
|
UniID = Selection,
|
||||||
User2 = User#egs_user_model{area=#psu_area{questid=1120000, zoneid=0, mapid=100}, entryid=0},
|
User2 = User#egs_user_model{uni=UniID, entryid=EntryID}
|
||||||
egs_user_model:write(User2),
|
end,
|
||||||
psu_game:char_load(User2, State);
|
psu_proto:send_0230(State),
|
||||||
_UniID ->
|
%% 0220
|
||||||
log("uni selection (reload)"),
|
case User#egs_user_model.partypid of
|
||||||
psu_proto:send_0230(State),
|
undefined -> ignore;
|
||||||
% 0220
|
PartyPid ->
|
||||||
{ok, User} = egs_user_model:read(GID),
|
%% @todo Replace stop by leave when leaving stops the party correctly when nobody's there anymore.
|
||||||
case User#egs_user_model.partypid of
|
%~ psu_party:leave(User#egs_user_model.partypid, User#egs_user_model.id)
|
||||||
undefined ->
|
{ok, NPCList} = psu_party:get_npc(PartyPid),
|
||||||
ignore;
|
[egs_user_model:delete(NPCGID) || {_Spot, NPCGID} <- NPCList],
|
||||||
PartyPid ->
|
psu_party:stop(PartyPid)
|
||||||
%% @todo Replace stop by leave when leaving stops the party correctly when nobody's there anymore.
|
end,
|
||||||
%~ psu_party:leave(User#egs_user_model.partypid, User#egs_user_model.id)
|
egs_user_model:write(User2),
|
||||||
{ok, NPCList} = psu_party:get_npc(PartyPid),
|
egs_universes:leave(User#egs_user_model.uni),
|
||||||
[egs_user_model:delete(NPCGID) || {_Spot, NPCGID} <- NPCList],
|
egs_universes:enter(UniID),
|
||||||
psu_party:stop(PartyPid)
|
psu_game:char_load(User2, State).
|
||||||
end,
|
|
||||||
User2 = User#egs_user_model{entryid=EntryID},
|
|
||||||
egs_user_model:write(User2),
|
|
||||||
psu_game:char_load(User2, State)
|
|
||||||
end.
|
|
||||||
|
|
||||||
%% Internal.
|
%% Internal.
|
||||||
|
|
||||||
|
@ -37,7 +37,6 @@ start_link(Port) ->
|
|||||||
on_exit(Pid) ->
|
on_exit(Pid) ->
|
||||||
case egs_user_model:read({pid, Pid}) of
|
case egs_user_model:read({pid, Pid}) of
|
||||||
{ok, User} ->
|
{ok, User} ->
|
||||||
mnesia:dirty_update_counter(counters, population, -1),
|
|
||||||
case User#egs_user_model.partypid of
|
case User#egs_user_model.partypid of
|
||||||
undefined ->
|
undefined ->
|
||||||
ignore;
|
ignore;
|
||||||
@ -47,6 +46,7 @@ on_exit(Pid) ->
|
|||||||
psu_party:stop(PartyPid)
|
psu_party:stop(PartyPid)
|
||||||
end,
|
end,
|
||||||
egs_user_model:delete(User#egs_user_model.id),
|
egs_user_model:delete(User#egs_user_model.id),
|
||||||
|
egs_universes:leave(User#egs_user_model.uni),
|
||||||
{ok, List} = egs_user_model:select({neighbors, User}),
|
{ok, List} = egs_user_model:select({neighbors, User}),
|
||||||
lists:foreach(fun(Other) -> Other#egs_user_model.pid ! {egs, player_unspawn, User} end, List),
|
lists:foreach(fun(Other) -> Other#egs_user_model.pid ! {egs, player_unspawn, User} end, List),
|
||||||
io:format("game (~p): quit~n", [User#egs_user_model.id]);
|
io:format("game (~p): quit~n", [User#egs_user_model.id]);
|
||||||
|
@ -60,6 +60,7 @@ init([]) ->
|
|||||||
{egs_shops_db, {egs_shops_db, start_link, []}, permanent, 5000, worker, dynamic},
|
{egs_shops_db, {egs_shops_db, start_link, []}, permanent, 5000, worker, dynamic},
|
||||||
{egs_accounts, {egs_accounts, start_link, []}, permanent, 5000, worker, dynamic},
|
{egs_accounts, {egs_accounts, start_link, []}, permanent, 5000, worker, dynamic},
|
||||||
{egs_counters, {egs_counters, start_link, []}, permanent, 5000, worker, dynamic},
|
{egs_counters, {egs_counters, start_link, []}, permanent, 5000, worker, dynamic},
|
||||||
|
{egs_universes, {egs_universes, start_link, []}, permanent, 5000, worker, dynamic},
|
||||||
{egs_user_model, {egs_user_model, start_link, []}, permanent, 5000, worker, dynamic},
|
{egs_user_model, {egs_user_model, start_link, []}, permanent, 5000, worker, dynamic},
|
||||||
{egs_game_server, {egs_game_server, start_link, [GamePort]}, permanent, 5000, worker, dynamic}
|
{egs_game_server, {egs_game_server, start_link, [GamePort]}, permanent, 5000, worker, dynamic}
|
||||||
],
|
],
|
||||||
|
133
src/egs_universes.erl
Normal file
133
src/egs_universes.erl
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
%% @author Loïc Hoguin <essen@dev-extend.eu>
|
||||||
|
%% @copyright 2010 Loïc Hoguin.
|
||||||
|
%% @doc EGS universes handler.
|
||||||
|
%%
|
||||||
|
%% This file is part of EGS.
|
||||||
|
%%
|
||||||
|
%% EGS is free software: you can redistribute it and/or modify
|
||||||
|
%% it under the terms of the GNU Affero General Public License as
|
||||||
|
%% published by the Free Software Foundation, either version 3 of the
|
||||||
|
%% License, or (at your option) any later version.
|
||||||
|
%%
|
||||||
|
%% EGS is distributed in the hope that it will be useful,
|
||||||
|
%% but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
%% GNU Affero General Public License for more details.
|
||||||
|
%%
|
||||||
|
%% You should have received a copy of the GNU Affero General Public License
|
||||||
|
%% along with EGS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
-module(egs_universes).
|
||||||
|
-behavior(gen_server).
|
||||||
|
-export([start_link/0, stop/0, all/0, defaultid/0, enter/1, leave/1, myroomid/0, read/1, reload/0]). %% API.
|
||||||
|
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). %% gen_server.
|
||||||
|
|
||||||
|
%% Use the module name for the server's name.
|
||||||
|
-define(SERVER, ?MODULE).
|
||||||
|
|
||||||
|
%% Default universe IDs.
|
||||||
|
-define(MYROOM_ID, 21).
|
||||||
|
-define(DEFAULT_ID, 26).
|
||||||
|
|
||||||
|
%% API.
|
||||||
|
|
||||||
|
%% @spec start_link() -> {ok,Pid::pid()}
|
||||||
|
start_link() ->
|
||||||
|
gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
|
||||||
|
|
||||||
|
%% @spec stop() -> stopped
|
||||||
|
stop() ->
|
||||||
|
gen_server:call(?SERVER, stop).
|
||||||
|
|
||||||
|
%% @spec all() -> term()
|
||||||
|
all() ->
|
||||||
|
gen_server:call(?SERVER, all).
|
||||||
|
|
||||||
|
%% @spec defaultid() -> 26
|
||||||
|
%% @doc Return the default universe, Uni 01, with ID 26.
|
||||||
|
defaultid() ->
|
||||||
|
?DEFAULT_ID.
|
||||||
|
|
||||||
|
%% @spec enter(UniID) -> term()
|
||||||
|
enter(UniID) ->
|
||||||
|
gen_server:cast(?SERVER, {enter, UniID}).
|
||||||
|
|
||||||
|
%% @spec leave(UniID) -> term()
|
||||||
|
leave(UniID) ->
|
||||||
|
gen_server:cast(?SERVER, {leave, UniID}).
|
||||||
|
|
||||||
|
%% @spec myroomid() -> 21
|
||||||
|
%% @doc Return the ID for the myroom universe.
|
||||||
|
myroomid() ->
|
||||||
|
?MYROOM_ID.
|
||||||
|
|
||||||
|
%% @spec read(UniID) -> term()
|
||||||
|
read(UniID) ->
|
||||||
|
gen_server:call(?SERVER, {read, UniID}).
|
||||||
|
|
||||||
|
%% @spec reload() -> ok
|
||||||
|
reload() ->
|
||||||
|
gen_server:cast(?SERVER, reload).
|
||||||
|
|
||||||
|
%% gen_server.
|
||||||
|
|
||||||
|
init([]) ->
|
||||||
|
{ok, [create_myroom()|create_unis()]}.
|
||||||
|
|
||||||
|
handle_call(all, _From, State) ->
|
||||||
|
{reply, State, State};
|
||||||
|
|
||||||
|
handle_call({read, UniID}, _From, State) ->
|
||||||
|
{reply, proplists:get_value(UniID, State), State};
|
||||||
|
|
||||||
|
handle_call(stop, _From, State) ->
|
||||||
|
{stop, normal, stopped, State};
|
||||||
|
|
||||||
|
handle_call(_Request, _From, State) ->
|
||||||
|
{reply, ignored, State}.
|
||||||
|
|
||||||
|
handle_cast({enter, UniID}, State) ->
|
||||||
|
{Type, Name, NbPlayers, MaxPlayers} = proplists:get_value(UniID, State),
|
||||||
|
State2 = proplists:delete(UniID, State),
|
||||||
|
State3 = [{UniID, {Type, Name, NbPlayers + 1, MaxPlayers}}|State2],
|
||||||
|
State4 = lists:keysort(1, State3),
|
||||||
|
{noreply, State4};
|
||||||
|
|
||||||
|
handle_cast({leave, UniID}, State) ->
|
||||||
|
{Type, Name, NbPlayers, MaxPlayers} = proplists:get_value(UniID, State),
|
||||||
|
State2 = proplists:delete(UniID, State),
|
||||||
|
State3 = [{UniID, {Type, Name, NbPlayers - 1, MaxPlayers}}|State2],
|
||||||
|
State4 = lists:keysort(1, State3),
|
||||||
|
{noreply, State4};
|
||||||
|
|
||||||
|
handle_cast(reload, _State) ->
|
||||||
|
{noreply, [create_myroom()|create_unis()]};
|
||||||
|
|
||||||
|
handle_cast(_Msg, State) ->
|
||||||
|
{noreply, State}.
|
||||||
|
|
||||||
|
handle_info(_Info, State) ->
|
||||||
|
{noreply, State}.
|
||||||
|
|
||||||
|
terminate(_Reason, _State) ->
|
||||||
|
ok.
|
||||||
|
|
||||||
|
code_change(_OldVsn, State, _Extra) ->
|
||||||
|
{ok, State}.
|
||||||
|
|
||||||
|
%% Internal.
|
||||||
|
|
||||||
|
%% @doc Max players defaults to 5000 for now.
|
||||||
|
create_myroom() ->
|
||||||
|
{ok, << 16#fffe:16, MyRoomName/binary >>} = file:read_file("priv/universes/myroom.en_US.txt"),
|
||||||
|
{?MYROOM_ID, {myroom, MyRoomName, 0, 5000}}.
|
||||||
|
|
||||||
|
%% @doc Max players defaults to 1000 for now.
|
||||||
|
create_unis() ->
|
||||||
|
{ok, << 16#fffe:16, Universes/binary >>} = file:read_file("priv/universes/universes.en_US.txt"),
|
||||||
|
Universes2 = re:split(Universes, "\n."),
|
||||||
|
create_unis(Universes2, ?DEFAULT_ID, []).
|
||||||
|
create_unis([], _UniID, Acc) ->
|
||||||
|
lists:reverse(Acc);
|
||||||
|
create_unis([Name|Tail], UniID, Acc) ->
|
||||||
|
create_unis(Tail, UniID + 2, [{UniID, {universe, Name, 0, 1000}}|Acc]).
|
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
-module(egs_user_model).
|
-module(egs_user_model).
|
||||||
-behavior(gen_server).
|
-behavior(gen_server).
|
||||||
-export([start_link/0, stop/0, count/0, read/1, select/1, write/1, delete/1, item_nth/2, item_add/3, item_qty_add/3, shop_enter/2, shop_leave/1, shop_get/1, money_add/2]). %% API.
|
-export([start_link/0, stop/0, read/1, select/1, write/1, delete/1, item_nth/2, item_add/3, item_qty_add/3, shop_enter/2, shop_leave/1, shop_get/1, money_add/2]). %% API.
|
||||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). %% gen_server.
|
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). %% gen_server.
|
||||||
|
|
||||||
%% Use the module name for the server's name and for the table name.
|
%% Use the module name for the server's name and for the table name.
|
||||||
@ -46,10 +46,6 @@ start_link() ->
|
|||||||
stop() ->
|
stop() ->
|
||||||
gen_server:call(?SERVER, stop).
|
gen_server:call(?SERVER, stop).
|
||||||
|
|
||||||
%% @spec count() -> {ok, Count}
|
|
||||||
count() ->
|
|
||||||
gen_server:call(?SERVER, count).
|
|
||||||
|
|
||||||
%% @spec read({pid, Pid}) -> {ok, User} | {error, badarg}
|
%% @spec read({pid, Pid}) -> {ok, User} | {error, badarg}
|
||||||
%% @spec read(ID) -> {ok, User} | {error, badarg}
|
%% @spec read(ID) -> {ok, User} | {error, badarg}
|
||||||
read(ID) ->
|
read(ID) ->
|
||||||
@ -95,10 +91,6 @@ init([]) ->
|
|||||||
error_logger:info_report("egs_user_model started"),
|
error_logger:info_report("egs_user_model started"),
|
||||||
{ok, undefined}.
|
{ok, undefined}.
|
||||||
|
|
||||||
handle_call(count, _From, State) ->
|
|
||||||
Count = mnesia:dirty_update_counter(counters, population, 0),
|
|
||||||
{reply, {ok, Count}, State};
|
|
||||||
|
|
||||||
handle_call({read, {pid, Pid}}, _From, State) ->
|
handle_call({read, {pid, Pid}}, _From, State) ->
|
||||||
List = do(qlc:q([X || X <- mnesia:table(?TABLE), X#?TABLE.pid =:= Pid])),
|
List = do(qlc:q([X || X <- mnesia:table(?TABLE), X#?TABLE.pid =:= Pid])),
|
||||||
case List of
|
case List of
|
||||||
|
@ -35,7 +35,7 @@ char_load(User, State) ->
|
|||||||
send_1005((User#egs_user_model.character)#characters.name),
|
send_1005((User#egs_user_model.character)#characters.name),
|
||||||
psu_proto:send_1006(12, State),
|
psu_proto:send_1006(12, State),
|
||||||
psu_proto:send_0210(State),
|
psu_proto:send_0210(State),
|
||||||
send_0222(),
|
psu_proto:send_0222(User#egs_user_model.uni, State),
|
||||||
send_1500(User),
|
send_1500(User),
|
||||||
send_1501(),
|
send_1501(),
|
||||||
send_1512(),
|
send_1512(),
|
||||||
@ -255,36 +255,6 @@ send_0204(DestUser, TargetUser, Action) ->
|
|||||||
16#00011300:32, DestGID:32/little-unsigned-integer, 0:64, TargetGID:32/little-unsigned-integer,
|
16#00011300:32, DestGID:32/little-unsigned-integer, 0:64, TargetGID:32/little-unsigned-integer,
|
||||||
TargetLID:32/little-unsigned-integer, Action:32/little-unsigned-integer >>).
|
TargetLID:32/little-unsigned-integer, Action:32/little-unsigned-integer >>).
|
||||||
|
|
||||||
%% @doc Send the list of available universes.
|
|
||||||
send_021e() ->
|
|
||||||
{ok, Count} = egs_user_model:count(),
|
|
||||||
[StrCount] = io_lib:format("~b", [Count]),
|
|
||||||
Unis = [{16#ffffffff, center, "Your Room", ""}, {1, justify, "Reload", " "}, {2, justify, "EGS Test", StrCount}],
|
|
||||||
NbUnis = length(Unis),
|
|
||||||
Bin = send_021e_build(Unis, []),
|
|
||||||
send(<< 16#021e0300:32, 0:288, NbUnis:32/little-unsigned-integer, Bin/binary >>).
|
|
||||||
|
|
||||||
send_021e_build([], Acc) ->
|
|
||||||
iolist_to_binary(lists:reverse(Acc));
|
|
||||||
send_021e_build([{ID, Align, Name, Pop}|Tail], Acc) ->
|
|
||||||
UCS2Name = << << X:8, 0:8 >> || X <- Name >>,
|
|
||||||
UCS2Pop = << << X:8, 0:8 >> || X <- Pop >>,
|
|
||||||
NamePadding = 8 * (32 - byte_size(UCS2Name)),
|
|
||||||
PopPadding = 8 * (12 - byte_size(UCS2Pop)),
|
|
||||||
IntAlign = case Align of justify -> 643; center -> 0 end,
|
|
||||||
send_021e_build(Tail, [<< ID:32/little-unsigned-integer, 0:16, IntAlign:16/little-unsigned-integer, UCS2Name/binary, 0:NamePadding, UCS2Pop/binary, 0:PopPadding >>|Acc]).
|
|
||||||
|
|
||||||
%% @doc Send the current universe name and number.
|
|
||||||
%% @todo Currently only have universe number 2, named EGS Test.
|
|
||||||
%% @todo We must have a parameter indicating whether this is a room or a normal universe.
|
|
||||||
send_0222() ->
|
|
||||||
UCS2Name = << << X:8, 0:8 >> || X <- "EGS Test" >>,
|
|
||||||
Padding = 8 * (44 - byte_size(UCS2Name)),
|
|
||||||
UniID = 2,
|
|
||||||
GID = get(gid),
|
|
||||||
send(<< 16#02220300:32, 16#ffff:16, 0:16, 16#00001200:32, GID:32/little, 0:64, 16#00011300:32, GID:32/little, 0:64,
|
|
||||||
UniID:32/little, 16#01009e02:32, UCS2Name/binary, 0:Padding, 16#aa000000:32 >>).
|
|
||||||
|
|
||||||
%% @todo No idea!
|
%% @todo No idea!
|
||||||
send_022c(A, B) ->
|
send_022c(A, B) ->
|
||||||
send(<< (header(16#022c))/binary, A:16/little-unsigned-integer, B:16/little-unsigned-integer >>).
|
send(<< (header(16#022c))/binary, A:16/little-unsigned-integer, B:16/little-unsigned-integer >>).
|
||||||
|
@ -1301,6 +1301,33 @@ send_0216(IP, Port, #state{socket=Socket, gid=DestGID, lid=DestLID}) ->
|
|||||||
send_021b(#state{socket=Socket, gid=DestGID, lid=DestLID}) ->
|
send_021b(#state{socket=Socket, gid=DestGID, lid=DestLID}) ->
|
||||||
packet_send(Socket, << 16#021b0300:32, DestLID:16/little, 0:144, 16#00011300:32, DestGID:32/little, 0:64 >>).
|
packet_send(Socket, << 16#021b0300:32, DestLID:16/little, 0:144, 16#00011300:32, DestGID:32/little, 0:64 >>).
|
||||||
|
|
||||||
|
%% @doc Send the list of available universes.
|
||||||
|
send_021e(Universes, #state{socket=Socket}) ->
|
||||||
|
NbUnis = length(Universes),
|
||||||
|
UnisBin = build_021e_uni(Universes, []),
|
||||||
|
packet_send(Socket, << 16#021e0300:32, 0:288, NbUnis:32/little, UnisBin/binary >>).
|
||||||
|
|
||||||
|
build_021e_uni([], Acc) ->
|
||||||
|
iolist_to_binary(lists:reverse(Acc));
|
||||||
|
build_021e_uni([{_UniID, {myroom, Name, NbPlayers, _MaxPlayers}}|Tail], Acc) ->
|
||||||
|
Padding = 8 * (44 - byte_size(Name)),
|
||||||
|
Bin = << 16#ffffffff:32, NbPlayers:16/little, 0:16, Name/binary, 0:Padding >>,
|
||||||
|
build_021e_uni(Tail, [Bin|Acc]);
|
||||||
|
build_021e_uni([{UniID, {universe, Name, NbPlayers, _MaxPlayers}}|Tail], Acc) ->
|
||||||
|
Padding = 8 * (32 - byte_size(Name)),
|
||||||
|
PopString = lists:flatten(io_lib:format("~5b", [NbPlayers])),
|
||||||
|
PopString2 = << << X:8, 0:8 >> || X <- PopString >>,
|
||||||
|
Bin = << UniID:32/little, NbPlayers:16/little, 643:16/little, Name/binary, 0:Padding, PopString2/binary, 0:16 >>,
|
||||||
|
build_021e_uni(Tail, [Bin|Acc]).
|
||||||
|
|
||||||
|
%% @doc Send the current universe info along with the current level cap.
|
||||||
|
send_0222(UniID, #state{socket=Socket, gid=DestGID}) ->
|
||||||
|
{_Type, Name, NbPlayers, MaxPlayers} = egs_universes:read(UniID),
|
||||||
|
Padding = 8 * (44 - byte_size(Name)),
|
||||||
|
LevelCap = egs_conf:read(level_cap),
|
||||||
|
packet_send(Socket, << 16#02220300:32, 16#ffff:16, 0:16, 16#00001200:32, DestGID:32/little, 0:64, 16#00011300:32, DestGID:32/little, 0:64,
|
||||||
|
UniID:32/little, NbPlayers:16/little, MaxPlayers:16/little, Name/binary, 0:Padding, LevelCap:32/little >>).
|
||||||
|
|
||||||
%% @doc Send the auth key, or, in case of failure, a related error message.
|
%% @doc Send the auth key, or, in case of failure, a related error message.
|
||||||
send_0223(AuthGID, AuthKey, #state{socket=Socket, gid=DestGID}) ->
|
send_0223(AuthGID, AuthKey, #state{socket=Socket, gid=DestGID}) ->
|
||||||
packet_send(Socket, << 16#02230300:32, 0:160, 16#00000f00:32, DestGID:32/little, 0:64, AuthGID:32/little, AuthKey:32/bits >>).
|
packet_send(Socket, << 16#02230300:32, 0:160, 16#00000f00:32, DestGID:32/little, 0:64, AuthGID:32/little, AuthKey:32/bits >>).
|
||||||
|
Loading…
Reference in New Issue
Block a user