Make spaceport work as expected. Add Neudaiz main lobby.

This commit is contained in:
Loïc Hoguin 2010-05-22 22:50:44 +02:00
parent c0fdfd7a26
commit 48ba723e8c
5 changed files with 84 additions and 42 deletions

View File

@ -19,18 +19,23 @@
%% EGS maps settings. %% EGS maps settings.
-define(MAPS, [ -define(MAPS, [
{ 1, [{name, "GC Floor 1"}, {quest, "p/quest.gc1.nbl"}, {zone, "p/zone.gc1.nbl"}] }, { [1100000,0,1], [{name, "GC Floor 1"}, {quest, "p/quest.gc1.nbl"}, {zone, "p/zone.gc1.nbl"}] },
{ 2, [{name, "GC Floor 2"}, {quest, "p/quest.gc1.nbl"}, {zone, "p/zone.gc1.nbl"}] }, { [1100000,0,2], [{name, "GC Floor 2"}, {quest, "p/quest.gc1.nbl"}, {zone, "p/zone.gc1.nbl"}] },
{ 3, [{name, "GC Floor 3"}, {quest, "p/quest.gc1.nbl"}, {zone, "p/zone.gc1.nbl"}] }, { [1100000,0,3], [{name, "GC Floor 3"}, {quest, "p/quest.gc1.nbl"}, {zone, "p/zone.gc1.nbl"}] },
{ 4, [{name, "GC Floor 4"}, {quest, "p/quest.gc1.nbl"}, {zone, "p/zone.gc1.nbl"}] }, { [1100000,0,4], [{name, "GC Floor 4"}, {quest, "p/quest.gc1.nbl"}, {zone, "p/zone.gc1.nbl"}] },
{ 5, [{name, "GC Floor 5"}, {quest, "p/quest.gc1.nbl"}, {zone, "p/zone.club.nbl"}] }, { [1100000,0,5], [{name, "GC Floor 5"}, {quest, "p/quest.gc1.nbl"}, {zone, "p/zone.club.nbl"}] },
{ [1100000,0,103], [{name, "GC Club Commune"}, {quest, "p/quest.gc1.nbl"}, {zone, "p/zone.club.nbl"}] }, % entries 0 1
{ [1102000,0,1], [{name, "Neudaiz City"}, {quest, "p/quest.8a23294b.bin"}, {zone, "p/zone-2.nbl"}] },
% { [1102000,11,100], [{name, "Neudaiz City"}, {quest, "p/quest.8a23294b.bin"}, {zone, "p/zone-2.nbl"}] },
{ [1104000,0,900], [{name, "Space Port"}, {quest, "p/quest.spaceport.nbl"}, {zone, "p/zone.spaceport.nbl"}] }
]).
% { 100, [{name, "GC Floor 2 Shops R"}, {quest, "p/quest.gc1.nbl"}, {zone, "p/TODO"}] }, % entries 0 1 2 % { 100, [{name, "GC Floor 2 Shops R"}, {quest, "p/quest.gc1.nbl"}, {zone, "p/TODO"}] }, % entries 0 1 2
% { 101, [{name, "GC Floor 2 Shops L"}, {quest, "p/quest.gc1.nbl"}, {zone, "p/TODO"}] }, % entries 0 1 2 % { 101, [{name, "GC Floor 2 Shops L"}, {quest, "p/quest.gc1.nbl"}, {zone, "p/TODO"}] }, % entries 0 1 2
% { 102, [{name, "GC Floor 3 Shops R"}, {quest, "p/quest.gc1.nbl"}, {zone, "p/TODO"}] }, % entries 0 1 2 % { 102, [{name, "GC Floor 3 Shops R"}, {quest, "p/quest.gc1.nbl"}, {zone, "p/TODO"}] }, % entries 0 1 2
{ 103, [{name, "GC Club Commune"}, {quest, "p/quest.gc1.nbl"}, {zone, "p/zone.club.nbl"}] }, % entries 0 1
{ 900, [{name, "GC Space Port"}, {quest, "p/quest.spaceport.nbl"}, {zone, "p/zone.spaceport.nbl"}] }
% { 16#a701, [{quest, "p/quest.myroom.nbl"}, {zone, "p/zone.myroom.nbl"}] } % TODO: 6400 too? on US through a door? % { 16#a701, [{quest, "p/quest.myroom.nbl"}, {zone, "p/zone.myroom.nbl"}] } % TODO: 6400 too? on US through a door?
]).
% TODO: % TODO:
% 100 101 102 103 104 105 106 107 108 109 111 112 113 117 119 120 121 122 123 124 130 131 140 % 100 101 102 103 104 105 106 107 108 109 111 112 113 117 119 120 121 122 123 124 130 131 140

View File

@ -19,4 +19,4 @@
%% EGS database schema. %% EGS database schema.
-record(ids, {type, id}). -record(ids, {type, id}).
-record(users, {gid, pid, socket, auth, time, folder, charnumber, charname, lid, maptype, mapnumber, mapentry, coords}). -record(users, {gid, pid, socket, auth, time, folder, charnumber, charname, lid, quest, maptype, mapnumber, mapentry, coords}).

View File

@ -17,7 +17,7 @@
% along with EGS. If not, see <http://www.gnu.org/licenses/>. % along with EGS. If not, see <http://www.gnu.org/licenses/>.
-module(egs). -module(egs).
-export([start/0, reload/0, global/2, warp/3, warp/4]). -compile(export_all).
-include("include/records.hrl"). -include("include/records.hrl").
@ -49,11 +49,11 @@ global(Type, Message) ->
%% @doc Warp all players to a new map. %% @doc Warp all players to a new map.
warp(MapType, MapNumber, MapEntry) -> warp(Quest, MapType, MapNumber, MapEntry) ->
lists:foreach(fun(User) -> egs_game:lobby_load(User#users.socket, User#users.gid, MapType, MapNumber, MapEntry) end, egs_db:users_select_all()). lists:foreach(fun(User) -> egs_game:lobby_load(User#users.socket, User#users.gid, Quest, MapType, MapNumber, MapEntry) end, egs_db:users_select_all()).
%% @doc Warp one player to a new map. %% @doc Warp one player to a new map.
warp(GID, MapType, MapNumber, MapEntry) -> warp(GID, Quest, MapType, MapNumber, MapEntry) ->
User = egs_db:users_select(GID), User = egs_db:users_select(GID),
egs_game:lobby_load(User#users.socket, User#users.gid, MapType, MapNumber, MapEntry). egs_game:lobby_load(User#users.socket, User#users.gid, Quest, MapType, MapNumber, MapEntry).

View File

@ -18,7 +18,7 @@
-module(egs_game). -module(egs_game).
-export([start/0]). % external -export([start/0]). % external
-export([listen/0, accept/1, process/2, char_select/3, lobby_load/5, loop/3, loop/4]). % internal -export([listen/0, accept/1, process/2, char_select/3, lobby_load/6, loop/3, loop/4]). % internal
-include("include/records.hrl"). -include("include/records.hrl").
-include("include/network.hrl"). -include("include/network.hrl").
@ -180,18 +180,18 @@ char_select_load(CSocket, GID, Version, Number) ->
[{status, _}, {char, << Name:512/bits, _/bits >>}|_] = char_load(User#users.folder, Number), [{status, _}, {char, << Name:512/bits, _/bits >>}|_] = char_load(User#users.folder, Number),
NewRow = User#users{charnumber=Number, charname=Name}, NewRow = User#users{charnumber=Number, charname=Name},
egs_db:users_insert(NewRow), egs_db:users_insert(NewRow),
?MODULE:lobby_load(CSocket, GID, 0, 1, 1), lobby_load(CSocket, GID, 1100000, 0, 1, 1),
ssl:setopts(CSocket, [{active, true}]), ssl:setopts(CSocket, [{active, true}]),
?MODULE:loop(CSocket, GID, Version). ?MODULE:loop(CSocket, GID, Version).
%% @doc Load the given map as a standard lobby. %% @doc Load the given map as a standard lobby.
lobby_load(CSocket, GID, MapType, MapNumber, MapEntry) -> lobby_load(CSocket, GID, Quest, MapType, MapNumber, MapEntry) ->
OldUser = egs_db:users_select(GID), OldUser = egs_db:users_select(GID),
User = OldUser#users{maptype=MapType, mapnumber=MapNumber, mapentry=MapEntry}, User = OldUser#users{quest=Quest, maptype=MapType, mapnumber=MapNumber, mapentry=MapEntry},
egs_db:users_insert(User), egs_db:users_insert(User),
[{status, 1}, {char, Char}, {options, Options}] = char_load(User#users.folder, User#users.charnumber), [{status, 1}, {char, Char}, {options, Options}] = char_load(User#users.folder, User#users.charnumber),
[{name, _}, {quest, Quest}, {zone, Zone}] = proplists:get_value(MapNumber, ?MAPS, [{name, "Unknown"}, {quest, "p/quest.gc1.nbl"}, {zone, "p/zone.gc1.nbl"}]), [{name, _}, {quest, QuestFile}, {zone, ZoneFile}] = proplists:get_value([Quest, MapType, MapNumber], ?MAPS, [{name, "Unknown"}, {quest, "p/quest.gc1.nbl"}, {zone, "p/zone.gc1.nbl"}]),
try try
% broadcast spawn to other people % broadcast spawn to other people
lists:foreach(fun(Other) -> Other#users.pid ! {psu_player_spawn, User} end, egs_db:users_select_others(GID)), lists:foreach(fun(Other) -> Other#users.pid ! {psu_player_spawn, User} end, egs_db:users_select_others(GID)),
@ -205,11 +205,11 @@ lobby_load(CSocket, GID, MapType, MapNumber, MapEntry) ->
% 1501 1512 0303 % 1501 1512 0303
egs_proto:send_npc_info(CSocket, GID), egs_proto:send_npc_info(CSocket, GID),
% 0c00 % 0c00
egs_proto:send_quest(CSocket, Quest), egs_proto:send_quest(CSocket, QuestFile),
% 0a05 0111 010d % 0a05 0111 010d
send_packet_200(CSocket, GID), send_packet_200(CSocket, GID),
egs_proto:send_zone(CSocket, Zone), egs_proto:send_zone(CSocket, ZoneFile),
egs_proto:send_map(CSocket, MapType, MapNumber, MapEntry), egs_proto:send_map(CSocket, Quest, MapType, MapNumber, MapEntry),
% 100e 020c % 100e 020c
egs_proto:send_load_quest(CSocket, GID), egs_proto:send_load_quest(CSocket, GID),
send_packet_201(CSocket, GID, User, Char), send_packet_201(CSocket, GID, User, Char),
@ -224,6 +224,32 @@ lobby_load(CSocket, GID, MapType, MapNumber, MapEntry) ->
log(GID, "send error, closing") log(GID, "send error, closing")
end. end.
%% @doc Load the given map as a spaceport.
spaceport_load(CSocket, GID, Quest, MapType, MapNumber, MapEntry) ->
OldUser = egs_db:users_select(GID),
User = OldUser#users{quest=Quest, maptype=MapType, mapnumber=MapNumber, mapentry=MapEntry},
egs_db:users_insert(User),
[{status, 1}, {char, Char}, {options, _}] = char_load(User#users.folder, User#users.charnumber),
[{name, _}, {quest, QuestFile}, {zone, ZoneFile}] = proplists:get_value([Quest, MapType, MapNumber], ?MAPS, [{name, "Unknown"}, {quest, "p/quest.gc1.nbl"}, {zone, "p/zone.gc1.nbl"}]),
try
% 0c00
egs_proto:send_quest(CSocket, QuestFile),
% 0a05
send_packet_200(CSocket, GID),
egs_proto:send_zone(CSocket, ZoneFile),
egs_proto:send_map(CSocket, Quest, MapType, MapNumber, MapEntry),
% 100e 020c
send_packet_201(CSocket, GID, User, Char),
% 0a06
egs_proto:send_loading_end(CSocket, GID),
egs_proto:send_camera_center(CSocket, GID)
catch
_ ->
ssl:close(CSocket),
log(GID, "send error, closing")
end.
%% @doc Alias for the game main's loop when the buffer is empty. %% @doc Alias for the game main's loop when the buffer is empty.
loop(CSocket, GID, Version) -> loop(CSocket, GID, Version) ->
@ -283,10 +309,10 @@ dispatch(CSocket, GID, Version, Packet) ->
%% @doc Position change broadcast handler. Save the position and then dispatch it. %% @doc Position change broadcast handler. Save the position and then dispatch it.
broadcast(16#0503, _, GID, _, Packet) -> broadcast(16#0503, _, GID, _, Packet) ->
<< _:448, Coords:96/bits, _:128, MapType:32/little-unsigned-integer, MapNumber:32/little-unsigned-integer, << _:448, Coords:96/bits, _:96, Quest:32/little-unsigned-integer, MapType:32/little-unsigned-integer,
MapEntry:32/little-unsigned-integer, _/bits >> = Packet, MapNumber:32/little-unsigned-integer, MapEntry:32/little-unsigned-integer, _/bits >> = Packet,
User = egs_db:users_select(GID), User = egs_db:users_select(GID),
NewUser = User#users{coords=Coords, maptype=MapType, mapnumber=MapNumber, mapentry=MapEntry}, NewUser = User#users{coords=Coords, quest=Quest, maptype=MapType, mapnumber=MapNumber, mapentry=MapEntry},
egs_db:users_insert(NewUser), egs_db:users_insert(NewUser),
broadcast(default, ignore, GID, ignore, Packet); broadcast(default, ignore, GID, ignore, Packet);
@ -335,11 +361,11 @@ handle(16#021f, CSocket, GID, _, Packet) ->
log(GID, "uni selection (my room)"), log(GID, "uni selection (my room)"),
% 0230 0220 % 0230 0220
% myroom_load(CSocket, GID, Version, 16#a701, 16#0100); % myroom_load(CSocket, GID, Version, 16#a701, 16#0100);
lobby_load(CSocket, GID, 11, 103, 1); lobby_load(CSocket, GID, 1100000, 11, 103, 1);
_ -> _ ->
log(GID, "uni selection (reload)"), log(GID, "uni selection (reload)"),
% 0230 0220 % 0230 0220
lobby_load(CSocket, GID, 0, 1, 1) lobby_load(CSocket, GID, 1100000, 0, 1, 1)
end; end;
%% @doc Shortcut changes handler. Do nothing. %% @doc Shortcut changes handler. Do nothing.
@ -368,14 +394,21 @@ handle(16#0304, _, GID, Version, Packet) ->
end, end,
lists:foreach(fun(User) -> User#users.pid ! {psu_chat, GID, ActualName, ChatModifiers, ChatMessage} end, egs_db:users_select_all()); lists:foreach(fun(User) -> User#users.pid ! {psu_chat, GID, ActualName, ChatModifiers, ChatMessage} end, egs_db:users_select_all());
%% @doc Lobby change handler. %% @doc Map change handler.
%% Spaceports are handled differently than normal lobbies.
handle(16#0807, CSocket, GID, _, Packet) -> handle(16#0807, CSocket, GID, _, Packet) ->
[{maptype, MapType}, {mapnumber, MapNumber}, {mapentry, MapEntry}] = egs_proto:parse_lobby_change(Packet), [{quest, Quest}, {maptype, MapType}, {mapnumber, MapNumber}, {mapentry, MapEntry}] = egs_proto:parse_lobby_change(Packet),
log(GID, io_lib:format("lobby change (~b,~b,~b)", [MapType, MapNumber, MapEntry])), log(GID, io_lib:format("lobby change (~b,~b,~b,~b)", [Quest,MapType, MapNumber, MapEntry])),
lobby_load(CSocket, GID, MapType, MapNumber, MapEntry); case {Quest, MapType, MapNumber, MapEntry} of
{1104000, 0, 900, 0} ->
spaceport_load(CSocket, GID, Quest, MapType, MapNumber, MapEntry);
_ ->
lobby_load(CSocket, GID, Quest, MapType, MapNumber, MapEntry)
end;
%% @doc Unknown flags-related command handler. %% @doc Unknown flags-related command handler.
%% Probably a new flag to save (entered a new lobby and stuff).
%% Just reply with a success value. %% Just reply with a success value.
%% @todo Find what it really does and handle it correctly. %% @todo Find what it really does and handle it correctly.
@ -419,16 +452,17 @@ send_packet_200(CSocket, GID) ->
%% @todo Figure out what the other things are. %% @todo Figure out what the other things are.
send_packet_201(CSocket, GID, User, Char) -> send_packet_201(CSocket, GID, User, Char) ->
Quest = User#users.quest,
MapType = User#users.maptype, MapType = User#users.maptype,
MapNumber = User#users.mapnumber, MapNumber = User#users.mapnumber,
MapEntry = User#users.mapentry, MapEntry = User#users.mapentry,
CharGID = User#users.gid, CharGID = User#users.gid,
CharLID = User#users.lid, CharLID = User#users.lid,
{ok, File} = file:read_file("p/packet0201.bin"), {ok, File} = file:read_file("p/packet0201.bin"),
<< _:96, A:32/bits, _:96, B:32/bits, _:256, D:64/bits, _:2624, After/bits >> = File, << _:96, A:32/bits, _:96, B:32/bits, _:256, D:32/bits, _:2656, After/bits >> = File,
Packet = << 16#0201:16, 0:48, A/binary, CharGID:32/little-unsigned-integer, 0:64, B/binary, GID:32/little-unsigned-integer, Packet = << 16#0201:16, 0:48, A/binary, CharGID:32/little-unsigned-integer, 0:64, B/binary, GID:32/little-unsigned-integer,
0:64, CharLID:32/little-unsigned-integer, CharGID:32/little-unsigned-integer, 0:96, D/binary, MapType:32/little-unsigned-integer, 0:64, CharLID:32/little-unsigned-integer, CharGID:32/little-unsigned-integer, 0:96, D/binary, Quest:32/little-unsigned-integer,
MapNumber:32/little-unsigned-integer, MapEntry:32/little-unsigned-integer, 0:320, Char/binary, After/binary >>, MapType:32/little-unsigned-integer, MapNumber:32/little-unsigned-integer, MapEntry:32/little-unsigned-integer, 0:320, Char/binary, After/binary >>,
egs_proto:packet_send(CSocket, Packet). egs_proto:packet_send(CSocket, Packet).
%% @todo Figure out what the other things are. %% @todo Figure out what the other things are.
@ -451,25 +485,28 @@ build_packet_233_contents([]) ->
build_packet_233_contents(Users) -> build_packet_233_contents(Users) ->
[User|Rest] = Users, [User|Rest] = Users,
{ok, File} = file:read_file("p/player.bin"), {ok, File} = file:read_file("p/player.bin"),
<< A:32/bits, _:32, B:64/bits, _:32, C:64/bits, _:96, D:32/bits, _:96, E:96/bits, _:2304, F/bits >> = File, << A:32/bits, _:32, B:64/bits, _:32, C:32/bits, _:128, D:32/bits, _:96, E:64/bits, _:2336, F/bits >> = File,
{ok, CharFile} = file:read_file(io_lib:format("save/~s/~b-character", [User#users.folder, User#users.charnumber])), {ok, CharFile} = file:read_file(io_lib:format("save/~s/~b-character", [User#users.folder, User#users.charnumber])),
CharGID = User#users.gid, CharGID = User#users.gid,
LID = User#users.lid, LID = User#users.lid,
case User#users.coords of % TODO: temporary? undefined handling case User#users.coords of % TODO: temporary? undefined handling
undefined -> undefined ->
Coords = << 0:96 >>, Coords = << 0:96 >>,
Quest = 1100000,
MapType = 0, MapType = 0,
MapNumber = 1, MapNumber = 1,
MapEntry = 0; MapEntry = 0;
_ -> _ ->
Coords = User#users.coords, Coords = User#users.coords,
Quest = User#users.quest,
MapType = User#users.maptype, MapType = User#users.maptype,
MapNumber = User#users.mapnumber, MapNumber = User#users.mapnumber,
MapEntry = User#users.mapentry MapEntry = User#users.mapentry
end, end,
Chunk = << A/binary, CharGID:32/little-unsigned-integer, B/binary, LID:16/little-unsigned-integer, 16#0100:16, C/binary, Chunk = << A/binary, CharGID:32/little-unsigned-integer, B/binary, LID:16/little-unsigned-integer, 16#0100:16, C/binary,
MapType:32/little-unsigned-integer, MapNumber:32/little-unsigned-integer, MapEntry:32/little-unsigned-integer, D:32/bits, Coords:96/bits, E/binary, Quest:32/little-unsigned-integer, MapType:32/little-unsigned-integer, MapNumber:32/little-unsigned-integer, MapEntry:32/little-unsigned-integer,
MapType:32/little-unsigned-integer, MapNumber:32/little-unsigned-integer, MapEntry:32/little-unsigned-integer, CharFile/binary, F/binary >>, D:32/bits, Coords:96/bits, E/binary, Quest:32/little-unsigned-integer, MapType:32/little-unsigned-integer, MapNumber:32/little-unsigned-integer,
MapEntry:32/little-unsigned-integer, CharFile/binary, F/binary >>,
Next = build_packet_233_contents(Rest), Next = build_packet_233_contents(Rest),
<< Chunk/binary, Next/binary >>. << Chunk/binary, Next/binary >>.

View File

@ -159,9 +159,9 @@ parse_game_auth(Packet) ->
%% @doc Parse a lobby change command. %% @doc Parse a lobby change command.
parse_lobby_change(Packet) -> parse_lobby_change(Packet) ->
<< _:384, MapType:16/little-unsigned-integer, MapNumber:16/little-unsigned-integer, << _:352, Quest:32/little-unsigned-integer, MapType:16/little-unsigned-integer,
MapEntry:16/little-unsigned-integer, _/bits >> = Packet, MapNumber:16/little-unsigned-integer, MapEntry:16/little-unsigned-integer, _/bits >> = Packet,
[{maptype, MapType}, {mapnumber, MapNumber}, {mapentry, MapEntry}]. [{quest, Quest}, {maptype, MapType}, {mapnumber, MapNumber}, {mapentry, MapEntry}].
%% @doc Parse the MOTD request command. %% @doc Parse the MOTD request command.
@ -306,8 +306,8 @@ send_loading_end(CSocket, GID) ->
%% @doc Send the map ID to be loaded by the client. %% @doc Send the map ID to be loaded by the client.
send_map(CSocket, MapType, MapNumber, MapEntry) -> send_map(CSocket, Quest, MapType, MapNumber, MapEntry) ->
Packet = << 16#0205:16, 0:336, MapType:32/little-unsigned-integer, Packet = << 16#0205:16, 0:304, Quest:32/little-unsigned-integer, MapType:32/little-unsigned-integer,
MapNumber:32/little-unsigned-integer, MapEntry:32/little-unsigned-integer, 0:64 >>, MapNumber:32/little-unsigned-integer, MapEntry:32/little-unsigned-integer, 0:64 >>,
packet_send(CSocket, Packet). packet_send(CSocket, Packet).