anchor.diff:  
   -module(egs_game).
   -export([start/0]). % external
  --export([supervisor_init/0, supervisor/0, listen/1, accept/2, process/2, char_select/3, area_load/6, loop/3, loop/4]). % internal
  +-export([supervisor_init/0, supervisor/0, listen/1, accept/2, process_init/1, process/0, char_select/0, area_load/4, loop/1]). % internal
   
   -include("include/records.hrl").
   -include("include/network.hrl").
  
positive.code: 	if	QuestChange =:= true ->
  			% reload the character if entering or leaving the room quest
  			if	OldUser#users.questid =:= 1120000; User#users.questid =:= 1120000 ->
  					char_load(CSocket, GID, Char, Options, User#users.charnumber);
  				true -> ignore
  			end,
  			% load new quest
  			send_0c00(CSocket, GID, User#users.questid),
  			send_020e(CSocket, QuestFile);
  		true -> ignore
  	end,
  	if	IsStart =:= true ->
  			send_0215(CSocket, GID, 16#ffffffff);
  		true -> ignore
  	end,
  	if	ZoneChange =:= true ->
  			% load new zone
  			send_0a05(CSocket, GID),
  			if AreaType =:= lobby ->
  					send_0111(CSocket, GID);
  				true -> ignore
  			end,
  			% 010d
  			send_0200(CSocket, GID, AreaType),
  			Layout = if IsStart =:= true -> crypto:rand_uniform(0, 4);
  				true -> 0
  			end,
  			send_020f(CSocket, ZoneFile, Layout, Season);
  		true -> ignore
  	end,
  	send_0205(CSocket, User#users.zoneid, User#users.mapid, User#users.entryid, IsSeasonal),
  	send_100e(CSocket, GID, User#users.questid, User#users.zoneid, User#users.mapid, AreaName, 16#ffffffff),
  	if	AreaType =:= mission ->
  			send_0215(CSocket, GID, 0),
  			if	IsStart =:= true ->
  					send_0215(CSocket, GID, 0),
  					send_0c09(CSocket, GID);
  				true -> ignore
  			end;
  		true ->
  			send_020c(CSocket)
  	end,
  	case AreaType of
  		myroom ->
  			myroom_send_packet(CSocket, "p/packet1332.bin"),
  			send_1202(CSocket, GID),
  			send_1204(CSocket, GID),
  			send_1206(CSocket, GID);
  		mission ->
  			send_1202(CSocket, GID),
  			send_1204(CSocket, GID),
  			send_1206(CSocket, GID),
  			send_1207(CSocket, GID);
  		_ -> ignore
  	end,
  	if	AreaType /= spaceport ->
  			send_1212(CSocket, GID);
  		true -> ignore
  	end,
  	if	AreaType =:= myroom ->
  			myroom_send_packet(CSocket, "p/packet1309.bin");
  		true -> ignore
  	end,
  	send_0201(CSocket, GID, User, Char),
  	if	ZoneChange =:= true ->
  			send_0a06(CSocket, GID);
  		true -> ignore
  	end,
  	send_0233(CSocket, GID, egs_db:users_select_others_in_area(User)),
  	send_0208(CSocket, GID),
  	send_0236(CSocket, GID).
  
  myroom_send_packet(CSocket, Filename) ->
  	{ok, << _:32, File/bits >>} = file:read_file(Filename),
  	egs_proto:packet_send(CSocket, File).
  
  %% @doc Alias for the game main's loop when the buffer is empty.
  
  loop(CSocket, GID, Version) ->
  	loop(CSocket, GID, Version, << >>).
  
  %% @doc Game's main loop.
  
  loop(CSocket, GID, Version, SoFar) ->
  	receive
  		{psu_broadcast, Orig} ->
  			<< A:64/bits, _:32, B:96/bits, _:64, C/bits >> = Orig,
  			Packet = << A/binary, 16#00011300:32, B/binary, 16#00011300:32, GID:32/little-unsigned-integer, C/binary >>,
  			egs_proto:packet_send(CSocket, Packet),
  			?MODULE:loop(CSocket, GID, Version, SoFar);
  		{psu_chat, ChatGID, ChatName, ChatModifiers, ChatMessage} ->
  			send_0304(CSocket, Version, ChatGID, ChatName, ChatModifiers, ChatMessage),
  			?MODULE:loop(CSocket, GID, Version, SoFar);
  		{psu_keepalive} ->
  			egs_proto:send_keepalive(CSocket),
  			?MODULE:loop(CSocket, GID, Version, SoFar);
  		{psu_player_spawn, Spawn} ->
  			send_spawn(CSocket, GID, Spawn),
  			?MODULE:loop(CSocket, GID, Version, SoFar);
  		{psu_player_unspawn, Spawn} ->
  			send_0204(CSocket, GID, Spawn#users.gid, Spawn#users.lid, 5),
  			?MODULE:loop(CSocket, GID, Version, SoFar);
  		{ssl, _, Data} ->
  			{Packets, Rest} = egs_proto:packet_split(<< SoFar/bits, Data/bits >>),
  			[dispatch(CSocket, GID, Version, Orig) || Orig <- Packets],
  			?MODULE:loop(CSocket, GID, Version, Rest);
  		{ssl_closed, _} ->
  			exit(ssl_closed);
  		{ssl_error, _, _} ->
  			exit(ssl_error);
  		_ ->
  			?MODULE:loop(CSocket, GID, Version, SoFar)
  	after 1000 ->
  		reload,
  		?MODULE:loop(CSocket, GID, Version, SoFar)
  	end.
  
  %% @doc Dispatch the command to the right handler.
  
  dispatch(CSocket, GID, Version, Orig) ->
  	{command, Command, Channel, Data} = egs_proto:packet_parse(Orig),
  	case Channel of
  		ignore -> ignore;
  		1 -> broadcast(Command, GID, Orig);
  		_ -> handle(Command, CSocket, GID, Version, Data)
  	end.
  
  %% @doc Position change broadcast handler. Save the position and then dispatch it.
  
  broadcast(16#0503, GID, Orig) ->
  	<< 100:32/little-unsigned-integer, 16#050301:24/unsigned-integer, _:360, Direction:32/bits, Coords:96/bits, _:96,
  		QuestID:32/little-unsigned-integer, ZoneID:32/little-unsigned-integer, MapID:32/little-unsigned-integer,
  		EntryID:32/little-unsigned-integer, _:32 >> = Orig,
  	User = egs_db:users_select(GID),
  	NewUser = User#users{direction=Direction, coords=Coords, questid=QuestID, zoneid=ZoneID, mapid=MapID, entryid=EntryID},
  	egs_db:users_insert(NewUser),
  	broadcast(default, GID, Orig);
  
  %% @doc Stand still broadcast handler. Save the position and then dispatch it.
  
  broadcast(16#0514, GID, Orig) ->
  	<< _:320, _:96, Direction:32/bits, Coords:96/bits, QuestID:32/little-unsigned-integer, ZoneID:32/little-unsigned-integer,
  		MapID:32/little-unsigned-integer, EntryID:32/little-unsigned-integer, _/bits >> = Orig,
  	User = egs_db:users_select(GID),
  	NewUser = User#users{direction=Direction, coords=Coords, questid=QuestID, zoneid=ZoneID, mapid=MapID, entryid=EntryID},
  	egs_db:users_insert(NewUser),
  	broadcast(default, GID, Orig);
  
  %% @doc Default broadcast handler. Dispatch the command to everyone.
  %%      We clean up the command and use the real GID and LID of the user, disregarding what was sent and possibly tampered with.
  %%      Only a handful of commands are allowed to broadcast. An user tampering with it would get disconnected instantly.
  %% @todo Don't query the user data everytime! Keep an User instead of a GID probably.
  
  broadcast(Command, GID, Orig)
  	when	Command =:= 16#0101;
  			Command =:= 16#0102;
  			Command =:= 16#0104;
  
negative.code: 		_ ->
  			Footer = << CounterID:32/little-unsigned-integer, 1:32/little-unsigned-integer >>
  	end,
  	send(<< Packet/binary, 0:PaddingSize, Footer/binary >>).
  
  %% @doc Send the mission's quest file when starting a new mission.
  %% @todo Handle correctly. 0:32 is actually a missing value. Value before that is unknown too.
  
  send_1015(QuestID) ->
  	[{type, _}, {file, QuestFile}|_] = proplists:get_value(QuestID, ?QUESTS),
  	{ok, File} = file:read_file(QuestFile),
  	Size = byte_size(File),
  	GID = get(gid),
  	send(<< 16#10150300:32, 0:160, 16#00011300:32, GID:32/little-unsigned-integer, 0:64,
  		QuestID:32/little-unsigned-integer, 16#01010000:32, 0:32, Size:32/little-unsigned-integer, File/binary >>).
  
  %% @todo Totally unknown.
  
  send_1020() ->
  	GID = get(gid),
  	send(<< 16#10200300:32, 0:160, 16#00011300:32, GID:32/little-unsigned-integer, 0:64 >>).
  
  %% @todo Figure out what this packet does. Sane values for counter and missions for now.
  
  send_1202() ->
  	GID = get(gid),
  	send(<< 16#12020300:32, 0:160, 16#00011300:32, GID:32/little-unsigned-integer, 0:96, 16#10000000:32, 0:64, 16#14000000:32, 0:32 >>).
  
  %% @todo Figure out what this packet does. Seems it's the same values all the time.
  
  send_1204() ->
  	GID = get(gid),
  	send(<< 16#12040300:32, 0:160, 16#00011300:32, GID:32/little-unsigned-integer, 0:96, 16#20000000:32, 0:256 >>).
  
  %% @doc Object events response?
  %% @todo Figure things out.
  
  send_1205(A, B) ->
  	GID = get(gid),
  	send(<< 16#12050300:32, 0:160, 16#00011300:32, GID:32/little-unsigned-integer, 0:64, A:32/little-unsigned-integer, B:32/little-unsigned-integer >>).
  
  %% @todo Figure out what this packet does. Sane values for counter and missions for now.
  
  send_1206() ->
  	GID = get(gid),
  	send(<< 16#12060300:32, 0:160, 16#00011300:32, GID:32/little-unsigned-integer, 0:96, 16#80020000:32, 0:5120 >>).
  
  %% @todo Figure out what this packet does. Sane values for counter and missions for now.
  
  send_1207() ->
  	GID = get(gid),
  	Chunk = << 16#ffffffff:32, 16#ffffffff:32, 16#ffffffff:32, 16#ffffffff:32, 16#ffffffff:32, 0:224, 16#0000ffff:32, 16#ff000000:32, 16#64000a00:32 >>,
  	send(<< 16#12070300:32, 0:160, 16#00011300:32, GID:32/little-unsigned-integer, 0:64,
  		Chunk/binary, Chunk/binary, Chunk/binary, Chunk/binary, Chunk/binary, Chunk/binary >>).
  
  %% @todo Object interaction? Figure out. C probably the interaction type.
  
  send_1211(A, B, C, D) ->
  	GID = get(gid),
  	send(<< 16#12110300:32, 0:160, 16#00011300:32, GID:32/little-unsigned-integer, 0:64, A:32/little-unsigned-integer, B:32/little-unsigned-integer, C:32/little-unsigned-integer, D:32/little-unsigned-integer >>).
  
  %% @doc Make the client load the quest previously sent.
  
  send_1212() ->
  	GID = get(gid),
  	send(<< 16#12120300:32, 0:160, 16#00011300:32, GID:32/little-unsigned-integer, 0:19264 >>).
  
  %% @todo Not sure. Related to keys.
  
  send_1213(A, B) ->
  	GID = get(gid),
  	send(<< 16#12120300:32, 0:160, 16#00011300:32, GID:32/little-unsigned-integer, A:32/little-unsigned-integer, B:32/little-unsigned-integer >>).
  
  %% @doc Send the player's partner card.
  
  send_1500(Char, Number) ->
  	<< CharInfo:576/bits, _/bits >> = Char,
  	GID = get(gid),
  	send(<< 16#15000300:32, 0:160, 16#00011300:32, GID:32/little-unsigned-integer, 0:64, CharInfo/binary, 0:3072, 16#010401:24, Number:8, 0:64 >>).
  
  %% @todo Send an empty partner card list.
  
  send_1501() ->
  	GID = get(gid),
  	send(<< 16#15010300:32, 0:160, 16#00011300:32, GID:32/little-unsigned-integer, 0:96 >>).
  
  %% @todo Send an empty blacklist.
  
  send_1512() ->
  	GID = get(gid),
  	send(<< 16#15120300:32, 0:160, 16#00011300:32, GID:32/little-unsigned-integer, 0:46144 >>).
  
  %% @doc Send the player's NPC and PM information.
  
  send_1602() ->
  	{ok, File} = file:read_file("p/npc.bin"),
  	GID = get(gid),
  	send(<< 16#16020300:32, 0:160, 16#00011300:32, GID:32/little-unsigned-integer, 0:96, File/binary >>).
  
  %% @doc Party information.
  %% @todo Handle existing parties.
  
  send_1706(CharName) ->
  	GID = get(gid),
  	send(<< 16#17060300:32, 0:160, 16#00011300:32, GID:32/little-unsigned-integer, 0:64,
  		16#00000300:32, 16#d5c0faff:32, 0:64, CharName/binary, 16#78000000:32, 16#01010000:32,
  		0:1536, 16#0100c800:32, 16#0601010a:32, 16#ffffffff:32, 0:32 >>).
  
  %% @doc Party settings. Item distribution is random for now.
  %% @todo Handle correctly.
  
  send_170a() ->
  	GID = get(gid),
  	send(<< 16#170a0300:32, 0:160, 16#00011300:32, GID:32/little-unsigned-integer, 0:64, 16#01010c08:32 >>).
  
  %% @todo Find what the heck this packet is.
  
  send_170c() ->
  	{ok, File} = file:read_file("p/packet170c.bin"),
  	GID = get(gid),
  	send(<< 16#170c0300:32, 0:160, 16#00011300:32, GID:32/little-unsigned-integer, 0:64, File/binary >>).
  
  %% @doc Send the background to use for the counter.
  %% @todo Background has more info past the first byte.
  
  send_1711(Background) ->
  	GID = get(gid),
  	send(<< 16#17110300:32, 0:160, 16#00011300:32, GID:32/little-unsigned-integer, 0:64, Background:32/little-unsigned-integer >>).
  
  %% @doc Unknown dialog-related handler.
  %% @todo Everything!
  
  send_1a02(A, B, C, D, E) ->
  	GID = get(gid),
  	send(<< 16#1a020300:32, 0:160, 16#00011300:32, GID:32/little-unsigned-integer, 0:64, A:32/little-unsigned-integer,
  		B:16/little-unsigned-integer, C:16/little-unsigned-integer, D:16/little-unsigned-integer, E:16/little-unsigned-integer >>).
  
  %% @doc Lumilass handler. Possibly more.
  %% @todo Figure out how Lumilass work exactly. The 4 bytes before the file may vary.
  
  send_1a03() ->
  	{ok, File} = file:read_file("p/lumilassA.bin"),
  	GID = get(gid),
  	send(<< 16#1a030300:32, 0:160, 16#00011300:32, GID:32/little-unsigned-integer, 0:96, File/binary >>).
  
  %% @doc PP cube handler. 
  %% @todo The 4 bytes before the file may vary. Everything past that is the same. Figure things out.
  
  send_1a04() ->
  	{ok, File} = file:read_file("p/ppcube.bin"),
  	GID = get(gid),
  	send(<< 16#1a040300:32, 0:160, 16#00011300:32, GID:32/little-unsigned-integer, 0:96, File/binary >>).
  
  %% @doc Types menu handler.
  %% @todo Handle correctly.
  
  send_1a07() ->
  	GID = get(gid),
  	send(<< 16#1a070300:32, 0:160, 16#00011300:32, GID:32/little-unsigned-integer, 0:64, 16#085b5d0a:32, 16#3a200000:32, 0:32,
  		16#01010101:32, 16#01010101:32, 16#01010101:32, 16#01010101:32 >>).
  
  %% @todo Figure out what the other things are and do it right.
  %% @todo Temporarily send 233 until the correct process is figured out.
  %%       Should be something along the lines of 203 201 204.
  
  send_spawn(_) ->
  	send_0233(egs_db:users_select_others_in_area(egs_db:users_select(get(gid)))).
  
  %% @doc Log message to the console.
  
  log(Message) ->
  	io:format("game (~p): ~s~n", [get(gid), Message]).
  
  log(Message, Format) ->
  	FormattedMessage = io_lib:format(Message, Format),
  	log(FormattedMessage).
  