Added some folders and modules are necessary for compliance with the architecture of Erlang/OTP principles

master
Alexander Markevych 2012-04-23 07:44:43 +03:00
parent ed4ccd2491
commit ad7e141ea5
7 changed files with 0 additions and 1366 deletions

9
README
View File

@ -1,9 +0,0 @@
This project is to run a Minetest Server using Erlang, mainly hoping to improve server quality and stability. In time this project will allow hundreds of players connected to one server, rather than the current technical limitations of the minetestserver program provided by celeron55's minetest GitHub repo.
This project should be under GPL V2 (or later.)
This project is still being worked out, until a working server module is completed.
The code is worked and created upon by hummermania.
The game, Minetest is worked and maintained by Celeron55, aka, Perttu Ahola. The repo for Minetest is https://github.com/celeron55/minetest and the extended version of it can be found here: http://github.com/celeron55/minetest_game

View File

@ -1,439 +0,0 @@
%%
%% erlmines
%% Copyright (C) 2012 hummermania, Markevych Alexander <rabota.pmr@gmail.com>
%%
%% This program is free software; you can redistribute it and/or modify
%% it under the terms of the GNU General Public License as published by
%% the Free Software Foundation; either version 2 of the License, or
%% (at your option) any later version.
%%
%% This program 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 General Public License for more details.
%%
%% You should have received a copy of the GNU General Public License
%% along with this program.  If not, see <http://www.gnu.org/licenses/>.
-module(clientserver).
-export([init/0]).
init() ->
ToClientCommand = gb_sets:from_list([
{toclient_init, 16#10},
%
% Server's reply to TOSERVER_INIT.
% Sent second after connected.
%
% [0] u16 TOSERVER_INIT
% [2] u8 deployed version
% [3] v3s16 player's position + v3f(0,BS/2,0) floatToInt'd
% [12] u64 map seed (new as of 2011-02-27)
%
% NOTE: The position in here is deprecated; position is
% explicitly sent afterwards
{ toclient_blockdata, 16#20}, % TODO: Multiple blocks
{ toclient_addnode, 16#21},
{ toclient_removenode, 16#22},
{ toclient_playerpos, 16#23}, % Obsolete
%
% [0] u16 command
% // Followed by an arbitary number of these:
% // Number is determined from packet length.
% [N] u16 peer_id
% [N+2] v3s32 position*100
% [N+2+12] v3s32 speed*100
% [N+2+12+12] s32 pitch*100
% [N+2+12+12+4] s32 yaw*100
{ toclient_playerinfo, 16#24}, % Obsolete
%
% [0] u16 command
% // Followed by an arbitary number of these:
% // Number is determined from packet length.
% [N] u16 peer_id
% [N] char[20] name
%
{ toclient_opt_block_not_found, 16#25}, % Obsolete
{ toclient_sectormeta, 16#26}, % Obsolete
%
% [0] u16 command
% [2] u8 sector count
% [3...] v2s16 pos + sector metadata
{ toclient_inventory, 16#27},
%
% [0] u16 command
% [2] serialized inventory
%
{ toclient_objectdata, 16#28}, % Obsolete
%
% Sent as unreliable.
%
% u16 command
% u16 number of player positions
% for each player:
% u16 peer_id
% v3s32 position*100
% v3s32 speed*100
% s32 pitch*100
% s32 yaw*100
% u16 count of blocks
% for each block:
% v3s16 blockpos
% block objects
%
{ toclient_time_of_day, 16#29},
%
% u16 command
% u16 time (0-23999)
% Added in a later version:
% f1000 time_speed
%
% (oops, there is some gap here)
{ toclient_chat_message, 16#30},
%
% u16 command
% u16 length
% wstring message
%
{ toclient_active_object_remove_add, 16#31},
%
% u16 command
% u16 count of removed objects
% for all removed objects {
% u16 id
% }
% u16 count of added objects
% for all added objects {
% u16 id
% u8 type
% u32 initialization data length
% string initialization data
% }
{ toclient_active_object_messages, 16#32},
%
% u16 command
% for all objects
% {
% u16 id
% u16 message length
% string message
% }
%
{ toclient_hp, 16#33},
%
% u16 command
% u8 hp
%
{ toclient_move_player, 16#34},
%
% u16 command
% v3f1000 player position
% f1000 player pitch
% f1000 player yaw
%
{ toclient_access_denied, 16#35},
%
% u16 command
% u16 reason_length
% wstring reason
%
{ toclient_playeritem, 16#36},
%
% u16 command
% u16 count of player items
% for all player items {
% u16 peer id
% u16 length of serialized item
% string serialized item
% }
%
{ toclient_deathscreen, 16#37},
%
% u16 command
% u8 bool set camera point target
% v3f1000 camera point target (to point the death cause or whatever)
%
{ toclient_media, 16#38},
%
% u16 command
% u16 total number of texture bunches
% u16 index of this bunch
% u32 number of files in this bunch
% for each file {
% u16 length of name
% string name
% u32 length of data
% data
% }
%
{ toclient_tooldef, 16#39},
%
% u16 command
% u32 length of the next item
% serialized ToolDefManager
%
{ toclient_nodedef, 16#3a},
%
% u16 command
% u32 length of the next item
% serialized NodeDefManager
%
{ toclient_craftitemdef, 16#3b},
%
% u16 command
% u32 length of the next item
% serialized CraftiItemDefManager
%
{ toclient_announce_media, 16#3c},
%
% u16 command
% u32 number of files
% for each texture {
% u16 length of name
% string name
% u16 length of sha1_digest
% string sha1_digest
% }
%
{ toclient_itemdef, 16#3d},
%
% u16 command
% u32 length of next item
% serialized ItemDefManager
%
{ toclient_play_sound, 16#3f},
%
% u16 command
% s32 sound_id
% u16 len
% u8[len] sound name
% s32 gain*1000
% u8 type (0=local, 1=positional, 2=object)
% s32[3] pos_nodes*10000
% u16 object_id
% u8 loop (bool)
%
{ toclient_stop_sound, 16#40}
%
% u16 command
% s32 sound_id
%
]),
ToServerCommand = gb_sets:from_list([
{ toserver_init, 16#10},
%
% Sent first after connected.
%
% [0] u16 TOSERVER_INIT
% [2] u8 SER_FMT_VER_HIGHEST
% [3] u8[20] player_name
% [23] u8[28] password (new in some version)
% [51] u16 client network protocol version (new in some version)
%
{ toserver_init2, 16#11},
%
% Sent as an ACK for TOCLIENT_INIT.
% After this, the server can send data.
%
% [0] u16 TOSERVER_INIT2
%
{ toserver_getblock, 16#20}, % Obsolete
{ toserver_addnode, 16#21}, % Obsolete
{ toserver_removenode, 16#22}, % Obsolete
{ toserver_playerpos, 16#23},
%
% [0] u16 command
% [2] v3s32 position*100
% [2+12] v3s32 speed*100
% [2+12+12] s32 pitch*100
% [2+12+12+4] s32 yaw*100
%
{ toserver_gotblocks, 16#24},
%
% [0] u16 command
% [2] u8 count
% [3] v3s16 pos_0
% [3+6] v3s16 pos_1
% ...
%
{ toserver_deletedblocks, 16#25},
%
% [0] u16 command
% [2] u8 count
% [3] v3s16 pos_0
% [3+6] v3s16 pos_1
% ...
%
{ toserver_addnode_from_inventory, 16#26}, % Obsolete
%
% [0] u16 command
% [2] v3s16 pos
% [8] u16 i
%
{ toserver_click_object, 16#27}, % Obsolete
%
% length: 13
% [0] u16 command
% [2] u8 button (0=left, 1=right)
% [3] v3s16 blockpos
% [9] s16 id
% [11] u16 item
%
{ toserver_ground_action, 16#28}, % Obsolete
%
% length: 17
% [0] u16 command
% [2] u8 action
% [3] v3s16 nodepos_undersurface
% [9] v3s16 nodepos_abovesurface
% [15] u16 item
% actions:
% 0: start digging (from undersurface)
% 1: place block (to abovesurface)
% 2: stop digging (all parameters ignored)
% 3: digging completed
%
{ toserver_release, 16#29}, % Obsolete
% (oops, there is some gap here)
{ toserver_signtext, 16#30}, % Old signs, obsolete
%
% u16 command
% v3s16 blockpos
% s16 id
% u16 textlen
% textdata
%
{ toserver_inventory_action, 16#31},
%
% See InventoryAction in inventory.h
%
{ toserver_chat_message, 16#32},
%
% u16 command
% u16 length
% wstring message
%
{ toserver_signnodetext, 16#33},
%
% u16 command
% v3s16 p
% u16 textlen
% textdata
%
{ toserver_click_activeobject, 16#34}, % Obsolete
%
% length: 7
% [0] u16 command
% [2] u8 button (0=left, 1=right)
% [3] u16 id
% [5] u16 item
%
{ toserver_damage, 16#35},
%
% u16 command
% u8 amount
%
{ toserver_password, 16#36},
%
% Sent to change password.
%
% [0] u16 TOSERVER_PASSWORD
% [2] u8[28] old password
% [30] u8[28] new password
%
{ toserver_playeritem, 16#37},
%
% Sent to change selected item.
%
% [0] u16 TOSERVER_PLAYERITEM
% [2] u16 item
%
{ toserver_respawn, 16#38},
%
% u16 TOSERVER_RESPAWN
%
{ toserver_interact, 16#39},
%
% [0] u16 command
% [2] u8 action
% [3] u16 item
% [5] u32 length of the next item
% [9] serialized PointedThing
% actions:
% 0: start digging (from undersurface) or use
% 1: stop digging (all parameters ignored)
% 2: digging completed
% 3: place block or item (to abovesurface)
% 4: use item
%
% (Obsoletes TOSERVER_GROUND_ACTION and TOSERVER_CLICK_ACTIVEOBJECT.)
%
{ toserver_removed_sounds, 16#3a},
%
% u16 command
% u16 len
% s32[len] sound_id
%
{ toserver_request_media, 16#40}
%
% u16 command
% u16 number of files requested
% for each file {
% u16 length of name
% string name
% }
%
]),
[ToClientCommand, ToServerCommand].

View File

@ -1,83 +0,0 @@
-module(connection).
-include("connection.hrl").
-export([makePacket/5, makeSplitPacket/3, test/0]).
ceiling(X) ->
T = trunc(X),
case X - T == 0 of
true -> T;
false -> T + 1
end.
readPeerId(PacketData) ->
<<_P:?U32,SenderPeerId:?U16,_Other/binary>> = PacketData,
SenderPeerId.
readChannel(PacketData) ->
<<_P:?U32,_S:?U16,Channel:?U8,_Other/binary>> = PacketData,
Channel.
% This adds the base headers to the data and makes a packet out of it
makePacket(Address, Data, ProtocolId,SenderPeerId,Channel)->
#buffered_packet{
address=Address,
data = <<ProtocolId:?U32,SenderPeerId:?U16,Channel:?U8,Data/binary>>
}.
% Add the TYPE_ORIGINAL header to the data
makeOriginalPacket(Data) ->
#original_packet{ data = <<?TYPE_ORIGINAL:?U8,Data/binary>> }.
% Split data in chunks and add TYPE_SPLIT headers to them
makeSplitPacket(Data,ChunkSizeMax,SeqNum) ->
ChunkHeaderSize = 7,
MaxDataSize = ChunkSizeMax - ChunkHeaderSize,
ChunkCount=ceiling(byte_size(Data)/MaxDataSize),
Chunks = makeSplitPacketList(MaxDataSize, SeqNum, ChunkCount, 0, Data),
Chunks.
makeSplitPacketList(MaxDataSize, SeqNum, ChunkCount, ChunkCount, Data) ->[];
makeSplitPacketList(MaxDataSize, SeqNum, ChunkCount, ChunkNum, Data) ->
DataSize = byte_size(Data),
ChunkDataSize = case MaxDataSize - DataSize < 0 of
true -> MaxDataSize;
false -> DataSize
end,
<<ChunkData:ChunkDataSize/binary,Tile/binary>> = Data,
%%ChunkNum1 = ChunkNum+1,
[<<?TYPE_SPLIT:?U8, SeqNum:?U16, ChunkCount:?U16, ChunkNum:?U16,ChunkData/binary>>|makeSplitPacketList(MaxDataSize,SeqNum,ChunkCount,ChunkNum+1,Tile)].
test() ->
makeSplitPacket(list_to_binary([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22]),9,65500).
% Depending on size, make a TYPE_ORIGINAL or TYPE_SPLIT packet
% Increments split_seqnum if a split packet is made
makeAutoSplitPacket(Data,ChunkSizeMax,SplitSeqNum) ->
todo.
% core::list<SharedBuffer<u8> > makeAutoSplitPacket(
% SharedBuffer<u8> data,
% u32 chunksize_max,
% u16 &split_seqnum)
%{
% u32 original_header_size = 1;
% core::list<SharedBuffer<u8> > list;
% if(data.getSize() + original_header_size > chunksize_max)
% {
% list = makeSplitPacket(data, chunksize_max, split_seqnum);
% split_seqnum++;
% return list;
% }
% else
% {
% list.push_back(makeOriginalPacket(data));
% }
% return list;
%}
%
% Add the TYPE_RELIABLE header to the data
makeReliablePacket(Data, SeqNum) ->
#reliable_packet{ data = <<?TYPE_RELIABLE:?U8,SeqNum:?U16,Data/binary>> }.

View File

@ -1,515 +0,0 @@
-define(U8, 8/unsigned-little-integer).
-define(U16, 16/unsigned-little-integer).
-define(U32, 32/unsigned-little-integer).
-record(buffered_packet, {
data, % Data of the packet, including headers
time, % Seconds from buffering the packet or re-sending
totaltime, % Seconds from buffering the packet
address % Sender or destination
}).
-record(original_packet, {
data,
address
}).
-record(reliable_packet, {
data
}).
-record(incoming_split_packet, {
% Key is chunk number, value is data without headers
chunks,
chunk_count,
time, % Seconds from adding
reliable % If true, isn't deleted on timeout
}).
-define(PROTOCOL_VERSION, 7).
-define(PROTOCOL_ID, 16#4f457403).
-define(PASSWORD_SIZE,28). %% Maximum password length. Allows for base64-encoded SHA-1 (27+\0).
-define(TEXTURENAME_ALLOWED_CHARS,"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.").
%% === NOTES ===
%% A packet is sent through a channel to a peer with a basic header:
%% TODO: Should we have a receiver_peer_id also?
%% Header (7 bytes):
%% [0] u32 protocol_id
%% [4] u16 sender_peer_id
%% [6] u8 channel
%% sender_peer_id:
%% Unique to each peer.
%% value 0 is reserved for making new connections
%% value 1 is reserved for server
%% channel:
%% The lower the number, the higher the priority is.
%% Only channels 0, 1 and 2 exist.
-define(BASE_HEADER_SIZE, 7).
-define(PEER_ID_INEXISTENT, 0).
-define(PEER_ID_SERVER, 1).
-define(CHANNEL_COUNT, 3).
%% Packet types:
%% CONTROL: This is a packet used by the protocol.
%% - When this is processed, nothing is handed to the user.
%% Header (2 byte):
%% [0] u8 type
%% [1] u8 controltype
%% controltype and data description:
%% CONTROLTYPE_ACK
%% [2] u16 seqnum
%% CONTROLTYPE_SET_PEER_ID
%% [2] u16 peer_id_new
%% CONTROLTYPE_PING
%% - There is no actual reply, but this can be sent in a reliable
%% packet to get a reply
%% CONTROLTYPE_DISCO
-define(TYPE_CONTROL, 0).
-define(CONTROLTYPE_ACK, 0).
-define(CONTROLTYPE_SET_PEER_ID, 1).
-define(CONTROLTYPE_PING, 2).
-define(CONTROLTYPE_DISCO, 3).
%% ORIGINAL: This is a plain packet with no control and no error checking at all.
%% - When this is processed, it is directly handed to the user.
%% Header (1 byte):
%% [0] u8 type
-define(TYPE_ORIGINAL, 1).
-define(ORIGINAL_HEADER_SIZE, 1).
%% SPLIT: These are sequences of packets forming one bigger piece of data.
%% - When processed and all the packet_nums 0...packet_count-1 are
%% present (this should be buffered), the resulting data shall be
%% directly handed to the user.
%% - If the data fails to come up in a reasonable time, the buffer shall
%% be silently discarded.
%% - These can be sent as-is or atop of a RELIABLE packet stream.
%% Header (7 bytes):
%% [0] u8 type
%% [1] u16 seqnum
%% [3] u16 chunk_count
%% [5] u16 chunk_num
-define(TYPE_SPLIT, 2).
%% RELIABLE: Delivery of all RELIABLE packets shall be forced by ACKs,
%% and they shall be delivered in the same order as sent. This is done
%% with a buffer in the receiving and transmitting end.
%% - When this is processed, the contents of each packet is recursively
%% processed as packets.
%% Header (3 bytes):
%% [0] u8 type
%% [1] u16 seqnum
-define(TYPE_RELIABLE, 3).
-define(RELIABLE_HEADER_SIZE, 3).
%%#define SEQNUM_INITIAL 0x10
-define(SEQNUM_INITIAL, 65500).
-define(SEQNUM_MAX, 65535).
%% =================================
%% TOSERVER command group
%% =================================
-define(TOSERVER_INIT,16#10).
%% Sent first after connected.
%%
%% [0] u16 TOSERVER_INIT
%% [2] u8 SER_FMT_VER_HIGHEST
%% [3] u8[20] player_name
%% [23] u8[28] password (new in some version)
%% [51] u16 client network protocol version (new in some version)
-define(TOSERVER_INIT2,16#11).
%% Sent as an ACK for TOCLIENT_INIT.
%% After this, the server can send data.
%%
%% [0] u16 TOSERVER_INIT2
-define(TOSERVER_GETBLOCK, 16#20). %% Obsolete
-define(TOSERVER_ADDNODE, 16#21). %% Obsolete
-define(TOSERVER_REMOVENODE, 16#22). %% Obsolete
-define(TOSERVER_PLAYERPOS, 16#23).
%% [0] u16 command
%% [2] v3s32 position*100
%% [2+12] v3s32 speed*100
%% [2+12+12] s32 pitch*100
%% [2+12+12+4] s32 yaw*100
-define(TOSERVER_GOTBLOCKS,16#24).
%% [0] u16 command
%% [2] u8 count
%% [3] v3s16 pos_0
%% [3+6] v3s16 pos_1
%% ...
-define(TOSERVER_DELETEDBLOCKS, 16#25).
%% [0] u16 command
%% [2] u8 count
%% [3] v3s16 pos_0
%% [3+6] v3s16 pos_1
%% ...
-define(TOSERVER_ADDNODE_FROM_INVENTORY, 16#26). %% Obsolete
%% [0] u16 command
%% [2] v3s16 pos
%% [8] u16 i
-define(TOSERVER_CLICK_OBJECT, 16#27). %% Obsolete
%% length: 13
%% [0] u16 command
%% [2] u8 button (0=left, 1=right)
%% [3] v3s16 blockpos
%% [9] s16 id
%% [11] u16 item
-define(TOSERVER_GROUND_ACTION, 16#28). %% Obsolete
%% length: 17
%% [0] u16 command
%% [2] u8 action
%% [3] v3s16 nodepos_undersurface
% [9] v3s16 nodepos_abovesurface
% [15] u16 item
% actions:
% 0: start digging (from undersurface)
% 1: place block (to abovesurface)
% 2: stop digging (all parameters ignored)
% 3: digging completed
-define(TOSERVER_RELEASE, 16#29). %% Obsolete
% (oops, there is some gap here)
-define(TOSERVER_SIGNTEXT, 16#30). %% Old signs, obsolete
% u16 command
% v3s16 blockpos
% s16 id
% u16 textlen
% textdata
-define(TOSERVER_INVENTORY_ACTION, 16#31).
% See InventoryAction in inventory.h
-define(TOSERVER_CHAT_MESSAGE, 16#32).
%% u16 command
%% u16 length
%% wstring message
-define(TOSERVER_SIGNNODETEXT, 16#33).
%% u16 command
%% v3s16 p
%% u16 textlen
%% textdata
-define(TOSERVER_CLICK_ACTIVEOBJECT, 16#34). % Obsolete
%% length: 7
%% [0] u16 command
%% [2] u8 button (0=left, 1=right)
%% [3] u16 id
%% [5] u16 item
-define(TOSERVER_DAMAGE, 16#35).
%% u16 command
%% u8 amount
-define(TOSERVER_PASSWORD, 16#36).
%% Sent to change password.
%% [0] u16 TOSERVER_PASSWORD
%% [2] u8[28] old password
%% [30] u8[28] new password
-define(TOSERVER_PLAYERITEM, 16#37).
%% Sent to change selected item.
%% [0] u16 TOSERVER_PLAYERITEM
%% [2] u16 item
-define(TOSERVER_RESPAWN,16#38).
%% u16 TOSERVER_RESPAWN
-define(TOSERVER_INTERACT, 16#39).
%% [0] u16 command
%% [2] u8 action
%% [3] u16 item
%% [5] u32 length of the next item
%% [9] serialized PointedThing
%% actions:
%% 0: start digging (from undersurface) or use
%% 1: stop digging (all parameters ignored)
%% 2: digging completed
%% 3: place block or item (to abovesurface)
%% 4: use item
%% (Obsoletes TOSERVER_GROUND_ACTION and TOSERVER_CLICK_ACTIVEOBJECT.)
-define(TOSERVER_REQUEST_TEXTURES, 16#40).
%% u16 command
%% u16 number of textures requested
%% for each texture {
%% u16 length of name
%% string name
%% }
%% =================================
%% TOCLIENT command group
%% =================================
-define(TOCLIENT_INIT, 16#10).
%% Server's reply to TOSERVER_INIT.
%% Sent second after connected.
%%
%% [0] u16 TOSERVER_INIT
%% [2] u8 deployed version
%% [3] v3s16 player's position + v3f(0,BS/2,0) floatToInt'd
%% [12] u64 map seed (new as of 2011-02-27)
%%
%% NOTE: The position in here is deprecated; position is
%% explicitly sent afterwards
-define(TOCLIENT_BLOCKDATA, 16#20). %%TODO: Multiple blocks
-define(TOCLIENT_ADDNODE, 16#21).
-define(TOCLIENT_REMOVENODE, 16#22).
-define(TOCLIENT_PLAYERPOS, 16#23). %% Obsolete
%% [0] u16 command
%% // Followed by an arbitary number of these:
%% // Number is determined from packet length.
%% [N] u16 peer_id
%% [N+2] v3s32 position*100
%% [N+2+12] v3s32 speed*100
%% [N+2+12+12] s32 pitch*100
%% [N+2+12+12+4] s32 yaw*100
-define(TOCLIENT_PLAYERINFO, 16#24). %% Obsolete
%% [0] u16 command
%% // Followed by an arbitary number of these:
%% // Number is determined from packet length.
%% [N] u16 peer_id
%% [N] char[20] name
-define(TOCLIENT_OPT_BLOCK_NOT_FOUND, 16#25). %% Obsolete
-define(TOCLIENT_SECTORMETA, 16#26). %% Obsolete
%% [0] u16 command
%% [2] u8 sector count
%% [3...] v2s16 pos + sector metadata
-define(TOCLIENT_INVENTORY, 16#27).
%% [0] u16 command
%% [2] serialized inventory
-define(TOCLIENT_OBJECTDATA, 16#28) %% Obsolete
%% Sent as unreliable.
%%
%% u16 command
%% u16 number of player positions
%% for each player:
%% u16 peer_id
%% v3s32 position*100
%% v3s32 speed*100
%% s32 pitch*100
%% s32 yaw*100
%% u16 count of blocks
%% for each block:
%% v3s16 blockpos
%% block objects
-define(TOCLIENT_TIME_OF_DAY, 16#29).
%% u16 command
%% u16 time (0-23999)
%% (oops, there is some gap here)
-define(TOCLIENT_CHAT_MESSAGE, 16#30).
%% u16 command
%% u16 length
%% wstring message
-define(TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD, 16#31).
%% u16 command
%% u16 count of removed objects
%% for all removed objects {
%% u16 id
%% }
%% u16 count of added objects
%% for all added objects {
%% u16 id
%% u8 type
%% u32 initialization data length
%% string initialization data
%% }
-define(TOCLIENT_ACTIVE_OBJECT_MESSAGES, 16#32).
%% u16 command
%% for all objects
%% {
%% u16 id
%% u16 message length
%% string message
%% }
-define(TOCLIENT_HP, 16#33).
%% u16 command
%% u8 hp
-define(TOCLIENT_MOVE_PLAYER, 16#34).
%% u16 command
%% v3f1000 player position
%% f1000 player pitch
%% f1000 player yaw
-define(TOCLIENT_ACCESS_DENIED, 16#35).
%% u16 command
%% u16 reason_length
%% wstring reason
-define(TOCLIENT_PLAYERITEM, 16#36)
%% u16 command
%% u16 count of player items
%% for all player items {
%% u16 peer id
%% u16 length of serialized item
%% string serialized item
%% }
-define(TOCLIENT_DEATHSCREEN, 16#37).
%% u16 command
%% u8 bool set camera point target
%% v3f1000 camera point target (to point the death cause or whatever)
-define(TOCLIENT_TEXTURES, 16#38).
%% u16 command
%% u16 total number of texture bunches
%% u16 index of this bunch
%% u32 number of textures in this bunch
%% for each texture {
%% u16 length of name
%% string name
%% u32 length of data
%% data
%% }
-define(TOCLIENT_TOOLDEF, 16#39).
%% u16 command
%% u32 length of the next item
%% serialized ToolDefManager
-define(TOCLIENT_NODEDEF, 16#3a).
%% u16 command
%% u32 length of the next item
%% serialized NodeDefManager
-define(TOCLIENT_CRAFTITEMDEF, 16#3b).
%% u16 command
%% u32 length of the next item
%% serialized CraftiItemDefManager
-define(TOCLIENT_ANNOUNCE_TEXTURES, 16#3c).
%% u16 command
%% u32 number of textures
%% for each texture {
%% u16 length of name
%% string name
%% u16 length of sha1_digest
%% string sha1_digest
%% }
-define(TOCLIENT_ITEMDEF, 16#3d).
%% u16 command
%% u32 length of next item
%% serialized ItemDefManager

View File

@ -1,125 +0,0 @@
-module(connection_incoming_split_buffer).
-include("connection.hrl").
-export([insert/2, removeUnreliableTimedOuts/2]).
-define(TABLE_ID, ?MODULE).
init() ->
ets:new(?TABLE_ID, [public, named_table]),
ok.
insert(BufferedPacket, Reliable) ->
HeaderSize = ?BASE_HEADER_SIZE+7,
<<_Header:?BASE_HEADER_SIZE, Type:?U8, SeqNum:?U16, ChunkCount:?U16, ChunkNum:?U16, _Other/binary>> = BufferedPacket,
case ets:lookup(?TABLE_ID, SeqNum) ->
[{SeqNum, FindPacket}] -> io:format("IncomingSplitPacket with SeqNum=~p is found in ReliablePacketBuffer~n",[SeqNum]);
[] -> ets:insert(?TABLE_ID, {SeqNum, BufferedPacket}).
%
% This will throw a GotSplitPacketException when a full
% split packet is constructed.
%
% SharedBuffer<u8> IncomingSplitBuffer::insert(BufferedPacket &p, bool reliable)
%{
% u32 headersize = BASE_HEADER_SIZE + 7;
% assert(p.data.getSize() >= headersize);
% u8 type = readU8(&p.data[BASE_HEADER_SIZE+0]);
% assert(type == TYPE_SPLIT);
% u16 seqnum = readU16(&p.data[BASE_HEADER_SIZE+1]);
% u16 chunk_count = readU16(&p.data[BASE_HEADER_SIZE+3]);
% u16 chunk_num = readU16(&p.data[BASE_HEADER_SIZE+5]);
%
% // Add if doesn't exist
% if(m_buf.find(seqnum) == NULL)
% {
% IncomingSplitPacket *sp = new IncomingSplitPacket();
% sp->chunk_count = chunk_count;
% sp->reliable = reliable;
% m_buf[seqnum] = sp;
% }
%
% IncomingSplitPacket *sp = m_buf[seqnum];
%
% // TODO: These errors should be thrown or something? Dunno.
% if(chunk_count != sp->chunk_count)
% derr_con<<"Connection: WARNING: chunk_count="<<chunk_count
% <<" != sp->chunk_count="<<sp->chunk_count
% <<std::endl;
% if(reliable != sp->reliable)
% derr_con<<"Connection: WARNING: reliable="<<reliable
% <<" != sp->reliable="<<sp->reliable
% <<std::endl;
%
% // If chunk already exists, cancel
% if(sp->chunks.find(chunk_num) != NULL)
% throw AlreadyExistsException("Chunk already in buffer");
%
% // Cut chunk data out of packet
% u32 chunkdatasize = p.data.getSize() - headersize;
% SharedBuffer<u8> chunkdata(chunkdatasize);
% memcpy(*chunkdata, &(p.data[headersize]), chunkdatasize);
%
% // Set chunk data in buffer
% sp->chunks[chunk_num] = chunkdata;
%
% // If not all chunks are received, return empty buffer
% if(sp->allReceived() == false)
% return SharedBuffer<u8>();
%
% // Calculate total size
% u32 totalsize = 0;
% core::map<u16, SharedBuffer<u8> >::Iterator i;
% i = sp->chunks.getIterator();
% for(; i.atEnd() == false; i++)
% {
% totalsize += i.getNode()->getValue().getSize();
% }
%
% SharedBuffer<u8> fulldata(totalsize);
%
% // Copy chunks to data buffer
% u32 start = 0;
% for(u32 chunk_i=0; chunk_i<sp->chunk_count;
% chunk_i++)
% {
% SharedBuffer<u8> buf = sp->chunks[chunk_i];
% u16 chunkdatasize = buf.getSize();
% memcpy(&fulldata[start], *buf, chunkdatasize);
% start += chunkdatasize;;
% }
%
% // Remove sp from buffer
% m_buf.remove(seqnum);
% delete sp;
%
% return fulldata;
% }
removeUnreliableTimedOuts() -> ok.
% void IncomingSplitBuffer::removeUnreliableTimedOuts(float dtime, float timeout)
% {
% core::list<u16> remove_queue;
% core::map<u16, IncomingSplitPacket*>::Iterator i;
% i = m_buf.getIterator();
% for(; i.atEnd() == false; i++)
% {
% IncomingSplitPacket *p = i.getNode()->getValue();
% // Reliable ones are not removed by timeout
% if(p->reliable == true)
% continue;
% p->time += dtime;
% if(p->time >= timeout)
% remove_queue.push_back(i.getNode()->getKey());
% }
% core::list<u16>::Iterator j;
% j = remove_queue.begin();
% for(; j != remove_queue.end(); j++)
% {
% dout_con<<"NOTE: Removing timed out unreliable split packet"
% <<std::endl;
% delete m_buf[*j];
% m_buf.remove(*j);
% }
% }

View File

@ -1,145 +0,0 @@
-module(connection_reliable_packet_buffer).
-include("connection.hrl").
-compile(export_all).
-define(TABLE_ID, ?MODULE).
init() ->
ets:new(?TABLE_ID, [public, named_table]),
ok.
insert(#buffered_packet{data=BufferedPacket, time=_Time, totaltime=_TotalTime, address = _Address} = BPrec) ->
<<_Header:?BASE_HEADER_SIZE/binary, Type:?U8, SeqNum:?U16,_Other/binary>> = BufferedPacket,
io:format("Type=~p, SeqNum=~p~n",[Type,SeqNum]),
case ets:lookup(?TABLE_ID, SeqNum) of
[{SeqNum, FindPacket}] ->
io:format("Reliable packet with SeqNum=~p is found in ReliablePacketBuffer~n",[SeqNum]),
{exists,FindPacket};
[] -> ets:insert(?TABLE_ID, {SeqNum, BPrec}),
{ok,BPrec}
end.
test_insert() ->
insert(#buffered_packet{data=list_to_binary([1,2,3,4,5,6,7,33,00,34,77,77,77,77]), time=0, totaltime=0}),
insert(#buffered_packet{data=list_to_binary([1,2,3,4,5,6,7,33,01,11,77,77,77,77]), time=0, totaltime=0}),
insert(#buffered_packet{data=list_to_binary([1,2,3,4,5,6,7,33,02,62,77,77,77,77]), time=0, totaltime=0}),
insert(#buffered_packet{data=list_to_binary([1,2,3,4,5,6,7,33,67,02,77,77,77,77]), time=0, totaltime=0}),
insert(#buffered_packet{data=list_to_binary([1,2,3,4,5,6,7,33,00,10,77,77,77,77]), time=0, totaltime=0}).
findPacket(SeqNum) ->
case ets:lookup(?TABLE_ID, SeqNum) of
[{SeqNum, FindPacket}] -> {ok, FindPacket};
[]-> {error, not_found}
end.
test_findPacket()->
findPacket(15874). % 8704, 2817, 579
print() ->
ets:foldl(fun({SeqNum, Packet},AccIn) ->
io:format("SeqNum=~p: ~p ~n", [SeqNum,Packet]),
AccIn
end, end_list, ?TABLE_ID).
empty() ->
Size = ets:info(?TABLE_ID,size),
case Size of
0 -> true;
_ -> Size
end.
size() ->
ets:info(?TABLE_ID,size).
notFound() ->
ets:last(?TABLE_ID).
%RPBSearchResult ReliablePacketBuffer::notFound()
%{
% return m_list.end();
%}
getFirstSeqnum() ->
ets:first(?TABLE_ID).
popFirst() ->
FirstSeqNum = ets:first(?TABLE_ID),
#buffered_packet{data=FirstPacket} = ets:lookup(?TABLE_ID,FirstSeqNum),
<<_Header:?BASE_HEADER_SIZE,_Type:?U8,SeqNum:?U16,_Other/binary>> = FirstPacket,
ets:delete(?TABLE_ID,SeqNum),
#buffered_packet{data=FirstPacket}.
popSeqnum(SeqNum) ->
FindPacket = ets:lookup(?TABLE_ID,SeqNum),
ets:delete(?TABLE_ID,SeqNum),
FindPacket.
incrementTimeouts(Dtime) ->
ets:foldl(fun({SeqNum, Packet},AccIn) ->
#buffered_packet{data = Data, time = Time, totaltime = TotalTime, address = Address} = Packet,
ets:update_element(?TABLE_ID,SeqNum,
{2,#buffered_packet{data=Data,time = Time + Dtime, totaltime = TotalTime + Dtime, address = Address}}),
AccIn
end, end_list, ?TABLE_ID).
test_increment()->
init(),
test_insert(),
print(),
incrementTimeouts(35),
print().
resetTimedOuts(Timeout) ->
ets:foldl(fun({SeqNum, Packet},AccIn) ->
#buffered_packet{data = Data, time = Time, totaltime = TotalTime, address = Address} = Packet,
if Time >= Timeout ->
ets:update_element(?TABLE_ID,SeqNum,
{2,#buffered_packet{data=Data,time = 0, totaltime = TotalTime, address = Address}});
true -> ok
end,
AccIn
end, end_list, ?TABLE_ID).
anyTotaltimeReached(Timeout) ->
%ets:select(?TABLE_ID, ets:fun2ms(fun({SeqNum,#buffered_packet{totaltime = TotalTime}}) when TotalTime >= Timeout -> true end)).
%ets:select(?TABLE_ID,
% ets:fun2ms(fun({Seq,#buffered_packet{data = _, time = _, totaltime = TotalTime, address = _}}) -> TotalTime end)).
%TODO This construction need to refactoring
case ets:select(?TABLE_ID, [{{'_',#buffered_packet{data='_',time='_',totaltime='$1',address='_'}},[{'>=','$1',Timeout}],['$1']}]) of
[] -> false;
_ -> true % or we must check list size
end.
%bool ReliablePacketBuffer::anyTotaltimeReached(float timeout)
%{
% core::list<BufferedPacket>::Iterator i;
% i = m_list.begin();
% for(; i != m_list.end(); i++){
% if(i->totaltime >= timeout)
% return true;
% }
% return false;
%}
getTimedOuts(Timeout) ->
% TODO - Check the returning value: list of buffered_packet, or SeqNum
ets:select(?TABLE_ID, [{{'$1',#buffered_packet{data='_',time='$2',totaltime='_',address='_'}},[{'>=','$2',Timeout}],['$1']}]).
% core::list<BufferedPacket> ReliablePacketBuffer::getTimedOuts(float timeout)
%{
% core::list<BufferedPacket> timed_outs;
% core::list<BufferedPacket>::Iterator i;
% i = m_list.begin();
% for(; i != m_list.end(); i++)
% {
% if(i->time >= timeout)
% timed_outs.push_back(*i);
% }
% return timed_outs;
%}

View File

@ -1,50 +0,0 @@
-module(erlmines).
%%-behaviour(gen_server).
-include("erlmines.hrl").
-export([server/1]).
server(Port) ->
{ok,Socket} = gen_udp:open(Port,[binary]),
listen(Socket).
listen(Socket) ->
receive
%%{udp,Socket,Host,Port,Bin} = Message ->
{udp,Socket,_,_,Bin} ->
io:format("========================================~n",[]),
io:format("Data= ~p~n",[Bin]),
process_packet(Bin),
listen(Socket)
after 10000 ->
gen_udp:close(Socket),
{exit,timeout}
end.
process_packet(<<ProtocolId:?U32, SenderPeerId:?U16, Channel:?U8, PacketType:?U8, Data/binary>>) ->
case PacketType of
?TYPE_CONTROL -> Type = "TYPE_CONTROL (0)",
type_control(Data);
?TYPE_ORIGINAL -> Type = "TYPE_ORIGINAL(1)",
type_original(Data);
?TYPE_SPLIT -> Type = "TYPE_SPLIT(2)",
type_split(Data);
?TYPE_RELIABLE -> Type = "TYPE_RELIABLE(2)",
type_reliable(Data)
end,
io:format("ProtocolId: ~p, SenderPeerId:~p, Channel:~p, PacketType: ~p, Data:~p~n",[ProtocolId,SenderPeerId,Channel,Type,Data]).
type_control(<<ControlType:?U8,Data/binary>>)-> ok.
type_original(Data)-> ok.
type_split(<<SeqNum:?U16,ChunkCount:?U16,ChunkNum:?U16,Data/binary>>)-> ok.
type_reliable(<<SeqNum:?U16,Data/binary>>)-> ok.