CharServer.pm
上传用户:market2
上传日期:2018-11-18
资源大小:18786k
文件大小:5k
源码类别:

外挂编程

开发平台:

Windows_Unix

  1. package Base::Ragnarok::CharServer;
  2. use strict;
  3. use Time::HiRes qw(time);
  4. use Socket qw(inet_aton);
  5. use Modules 'register';
  6. use Base::RagnarokServer;
  7. use base qw(Base::RagnarokServer);
  8. use Misc;
  9. use Globals qw(%config);
  10. use constant SESSION_TIMEOUT => 120;
  11. use constant DUMMY_CHARACTER => {
  12. charID => pack("V", 1234),
  13. lv_job => 50,
  14. hp => 1,
  15. hp_max => 1,
  16. sp => 1,
  17. sp_max => 1,
  18. walk_speed => 1,
  19. jobID => 8, # Priest
  20. hair_style => 2,
  21. lv => 1,
  22. hair_color => 5,
  23. clothes_color => 1,
  24. name => 'Character',
  25. str => 1,
  26. agi => 1,
  27. vit => 1,
  28. dex => 1,
  29. luk => 1,
  30. look => {
  31. head => 3,
  32. body => 3
  33. }
  34. };
  35. sub new {
  36. my $class = shift;
  37. my %options = @_;
  38. my $self = $class->SUPER::new(
  39. $options{host},
  40. $options{port},
  41. $options{serverType},
  42. $options{rpackets}
  43. );
  44. $self->{sessionStore} = $options{sessionStore};
  45. $self->{mapServer} = $options{mapServer};
  46. $self->{name} = $options{name} || 'Ragnarok Online';
  47. $self->{charBlockSize} = $options{charBlockSize} || 106;
  48. return $self;
  49. }
  50. sub getName {
  51. return $_[0]->{name};
  52. }
  53. sub getPlayersCount {
  54. return 0;
  55. }
  56. sub getCharacters {
  57. die "This is an abstract method and has not been implemented.";
  58. }
  59. sub charBlockSize {
  60. return $_[0]->{charBlockSize};
  61. }
  62. sub process_0065 {
  63. # Character server login.
  64. my ($self, $client, $message) = @_;
  65. my ($accountID, $sessionID, $sessionID2, $gender) = unpack('x2 a4 V V x2 C', $message);
  66. my $session = $self->{sessionStore}->get($sessionID);
  67. if (!$session || $session->{accountID} ne $accountID || $session->{sessionID} != $sessionID
  68.   || $session->{sex} != $gender || $session->{state} ne 'About to select character') {
  69. $client->close();
  70. } else {
  71. no encoding 'utf8';
  72. use bytes;
  73. # Show list of characters.
  74. my $output = '';
  75. my $index = -1;
  76. foreach my $char ($self->getCharacters($session)) {
  77. $index++;
  78. next if (!$char);
  79. my $charStructure = pack('x' . $self->charBlockSize());
  80. substr($charStructure, 0, 18) = pack('a4 V3 v',
  81. $char->{charID}, # character ID
  82. $char->{exp}, # base experience
  83. $char->{zenny}, # zeny
  84. $char->{exp_job}, # job experience
  85. $char->{lv_job} # job level
  86. );
  87. substr($charStructure, 42, 64) = pack('v7 x2 v x2 v x2 v4 Z24 C6 v',
  88. $char->{hp},
  89. $char->{hp_max},
  90. $char->{sp},
  91. $char->{sp_max},
  92. $char->{walk_speed} * 1000,
  93. $char->{jobID},
  94. $char->{hair_style},
  95. $char->{lv},
  96. $char->{headgear}{low},
  97. $char->{headgear}{top},
  98. $char->{headgear}{mid},
  99. $char->{hair_color},
  100. $char->{clothes_color},
  101. $char->{name},
  102. $char->{str},
  103. $char->{agi},
  104. $char->{vit},
  105. $char->{int},
  106. $char->{dex},
  107. $char->{luk},
  108. $index
  109. );
  110. $output .= $charStructure;
  111. }
  112.          if ($self->{serverType} == 8){
  113. $output = pack('C20') . $output;
  114. }
  115. # SECURITY NOTE: the session should be marked as belonging to this
  116. # character server only. Right now there is the possibility that
  117. # someone can login to another character server with a session
  118. # that was already handled by this one.
  119. $self->{sessionStore}->mark($session);
  120. $client->{session} = $session;
  121. $session->{time} = time;
  122. $client->send($accountID);
  123. if ($config{XKore_altCharServer} == 1){
  124. $client->send(pack('C2 v', 0x72, 0x00, length($output) + 4) . $output);
  125. }else{
  126. $client->send(pack('C2 v', 0x6B, 0x00, length($output) + 4) . $output);
  127. }
  128. }
  129. }
  130. sub process_0066 {
  131. # Select character.
  132. my ($self, $client, $message) = @_;
  133. my $session = $client->{session};
  134. if ($session) {
  135. $self->{sessionStore}->mark($session);
  136. my ($charIndex) = unpack('x2 C', $message);
  137. my @characters = $self->getCharacters();
  138. if (!$characters[$charIndex]) {
  139. # Invalid character selected.
  140. $client->send(pack('C*', 0x6C, 0x00, 0));
  141. } else {
  142. my $char = $characters[$charIndex];
  143. my $charInfo = $self->{mapServer}->getCharInfo($session);
  144. if (!$charInfo) {
  145. # We can't get the character information for some reason.
  146. $client->send(pack('C*', 0x6C, 0x00, 0));
  147. } else {
  148. my $output = pack('C2 a4 Z16 a4 v',
  149. 0x71, 0x00,
  150. $char->{charID},
  151. $charInfo->{map},
  152. inet_aton($self->{mapServer}->getHost()),
  153. $self->{mapServer}->getPort()
  154. );
  155. $session->{charID} = $char->{charID};
  156. $session->{state} = 'About to load map';
  157. $client->send($output);
  158. }
  159. }
  160. }
  161. $client->close();
  162. }
  163. sub process_0187 {
  164. # Ban check.
  165. # Doing nothing seems to work.
  166. }
  167. sub process_0067 {
  168. # Character creation.
  169. my ($self, $client) = @_;
  170. # Deny it.
  171. $client->send(pack('C*', 0x6E, 0x00, 2));
  172. }
  173. sub process_0067 {
  174. # Character deletion.
  175. my ($self, $client) = @_;
  176. # Deny it.
  177. $client->send(pack('C*', 0x70, 0x00, 1));
  178. }
  179. sub unhandledMessage {
  180. my ($self, $client) = @_;
  181. $client->close();
  182. }
  183. 1;