Advertisement
Guest User

Untitled

a guest
Dec 22nd, 2014
154
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.17 KB | None | 0 0
  1. package com.rs.game.player;
  2.  
  3. import java.security.MessageDigest;
  4.  
  5. import com.rs.Settings;
  6. import com.rs.game.Hit;
  7. import com.rs.game.World;
  8. import com.rs.networking.packet.OutgoingPacket;
  9. import com.rs.utility.Misc;
  10.  
  11. public final class LocalPlayerUpdate {
  12.  
  13. /**
  14. * The maximum amount of local players being added per tick.
  15. * This is to decrease time it takes to load crowded places (such as home).
  16. */
  17. private static final int MAX_PLAYER_ADD = 15;
  18.  
  19. private Player player;
  20.  
  21. private byte[] slotFlags;
  22.  
  23. private Player[] localPlayers;
  24. private int[] localPlayersIndexes;
  25. private int localPlayersIndexesCount;
  26.  
  27. private int[] outPlayersIndexes;
  28. private int outPlayersIndexesCount;
  29.  
  30. private int[] regionHashes;
  31.  
  32. private byte[][] cachedAppearencesHashes;
  33. private int totalRenderDataSentLength;
  34.  
  35. /**
  36. * The amount of local players added this tick.
  37. */
  38. private int localAddedPlayers;
  39.  
  40. public Player[] getLocalPlayers() {
  41. return localPlayers;
  42. }
  43.  
  44. public boolean needAppearenceUpdate(int index, byte[] hash) {
  45. if (totalRenderDataSentLength > ((Settings.PACKET_SIZE_LIMIT - 500) / 2)
  46. || hash == null)
  47. return false;
  48. return cachedAppearencesHashes[index] == null
  49. || !MessageDigest.isEqual(cachedAppearencesHashes[index], hash);
  50. }
  51.  
  52. public LocalPlayerUpdate(Player player) {
  53. this.player = player;
  54. slotFlags = new byte[2048];
  55. localPlayers = new Player[2048];
  56. localPlayersIndexes = new int[Settings.PLAYERS_LIMIT];
  57. outPlayersIndexes = new int[2048];
  58. regionHashes = new int[2048];
  59. cachedAppearencesHashes = new byte[Settings.PLAYERS_LIMIT][];
  60. }
  61.  
  62. public void init(OutgoingPacket stream) {
  63. stream.initBitAccess();
  64. stream.writeBits(30, player.getTileHash());
  65. localPlayers[player.getIndex()] = player;
  66. localPlayersIndexes[localPlayersIndexesCount++] = player.getIndex();
  67. for (int playerIndex = 1; playerIndex < 2048; playerIndex++) {
  68. if (playerIndex == player.getIndex())
  69. continue;
  70. Player player = World.getPlayers().get(playerIndex);
  71. stream.writeBits(18, regionHashes[playerIndex] = player == null ? 0
  72. : player.getRegionHash());
  73. outPlayersIndexes[outPlayersIndexesCount++] = playerIndex;
  74.  
  75. }
  76. stream.finishBitAccess();
  77. }
  78.  
  79. private boolean needsRemove(Player p) {
  80. return (p.hasFinished() || !player.withinDistance(p, player.hasLargeSceneView() ? 126 : 14)) || (player.multiplayerDisabled && p != player);
  81. }
  82.  
  83. private boolean needsAdd(Player p) {
  84. return p != null && !p.hasFinished() && player.withinDistance(p, player.hasLargeSceneView() ? 126 : 14) && !player.multiplayerDisabled && localAddedPlayers < MAX_PLAYER_ADD;
  85. }
  86.  
  87. private void updateRegionHash(OutgoingPacket stream, int lastRegionHash, int currentRegionHash) {
  88. int lastRegionX = lastRegionHash >> 8;
  89. int lastRegionY = 0xff & lastRegionHash;
  90. int lastPlane = lastRegionHash >> 16;
  91. int currentRegionX = currentRegionHash >> 8;
  92. int currentRegionY = 0xff & currentRegionHash;
  93. int currentPlane = currentRegionHash >> 16;
  94. int planeOffset = currentPlane - lastPlane;
  95. if (lastRegionX == currentRegionX && lastRegionY == currentRegionY) {
  96. stream.writeBits(2, 1);
  97. stream.writeBits(2, planeOffset);
  98. } else if (Math.abs(currentRegionX - lastRegionX) <= 1 && Math.abs(currentRegionY - lastRegionY) <= 1) {
  99. int opcode;
  100. int dx = currentRegionX - lastRegionX;
  101. int dy = currentRegionY - lastRegionY;
  102. if (dx == -1 && dy == -1)
  103. opcode = 0;
  104. else if (dx == 1 && dy == -1)
  105. opcode = 2;
  106. else if (dx == -1 && dy == 1)
  107. opcode = 5;
  108. else if (dx == 1 && dy == 1)
  109. opcode = 7;
  110. else if (dy == -1)
  111. opcode = 1;
  112. else if (dx == -1)
  113. opcode = 3;
  114. else if (dx == 1)
  115. opcode = 4;
  116. else
  117. opcode = 6;
  118. stream.writeBits(2, 2);
  119. stream.writeBits(5, (planeOffset << 3) + (opcode & 0x7));
  120. } else {
  121. int xOffset = currentRegionX - lastRegionX;
  122. int yOffset = currentRegionY - lastRegionY;
  123. stream.writeBits(2, 3);
  124. stream.writeBits(18, (yOffset & 0xff) + ((xOffset & 0xff) << 8) + (planeOffset << 16));
  125. }
  126. }
  127.  
  128. private void processOutsidePlayers(OutgoingPacket stream,
  129. OutgoingPacket updateBlockData, boolean nsn2) {
  130. stream.initBitAccess();
  131. int skip = 0;
  132. localAddedPlayers = 0;
  133. for (int i = 0; i < outPlayersIndexesCount; i++) {
  134. int playerIndex = outPlayersIndexes[i];
  135. if (nsn2 ? (0x1 & slotFlags[playerIndex]) == 0
  136. : (0x1 & slotFlags[playerIndex]) != 0)
  137. continue;
  138. if (skip > 0) {
  139. skip--;
  140. slotFlags[playerIndex] = (byte) (slotFlags[playerIndex] | 2);
  141. continue;
  142. }
  143. Player p = World.getPlayers().get(playerIndex);
  144. if (needsAdd(p)) {
  145. stream.writeBits(1, 1);
  146. stream.writeBits(2, 0); // request add
  147. int hash = p.getRegionHash();
  148. if (hash == regionHashes[playerIndex])
  149. stream.writeBits(1, 0);
  150. else {
  151. stream.writeBits(1, 1);
  152. updateRegionHash(stream, regionHashes[playerIndex], hash);
  153. regionHashes[playerIndex] = hash;
  154. }
  155. stream.writeBits(6, p.getXInRegion());
  156. stream.writeBits(6, p.getYInRegion());
  157. boolean needAppearenceUpdate = needAppearenceUpdate(
  158. p.getIndex(), p.getAppearence()
  159. .getMD5AppeareanceDataHash());
  160. appendUpdateBlock(p, updateBlockData, needAppearenceUpdate,
  161. true);
  162. stream.writeBits(1, 1);
  163. localAddedPlayers++;
  164. localPlayers[p.getIndex()] = p;
  165. slotFlags[playerIndex] = (byte) (slotFlags[playerIndex] | 2);
  166. } else {
  167. int hash = p == null ? regionHashes[playerIndex] : p
  168. .getRegionHash();
  169. if (p != null && hash != regionHashes[playerIndex]) {
  170. stream.writeBits(1, 1);
  171. updateRegionHash(stream, regionHashes[playerIndex], hash);
  172. regionHashes[playerIndex] = hash;
  173. } else {
  174. stream.writeBits(1, 0); // no update needed
  175. for (int i2 = i + 1; i2 < outPlayersIndexesCount; i2++) {
  176. int p2Index = outPlayersIndexes[i2];
  177. if (nsn2 ? (0x1 & slotFlags[p2Index]) == 0
  178. : (0x1 & slotFlags[p2Index]) != 0)
  179. continue;
  180. Player p2 = World.getPlayers().get(p2Index);
  181. if (needsAdd(p2)
  182. || (p2 != null && p2.getRegionHash() != regionHashes[p2Index]))
  183. break;
  184. skip++;
  185. }
  186. skipPlayers(stream, skip);
  187. slotFlags[playerIndex] = (byte) (slotFlags[playerIndex] | 2);
  188. }
  189. }
  190. }
  191. stream.finishBitAccess();
  192. }
  193.  
  194. private void processLocalPlayers(OutgoingPacket stream,
  195. OutgoingPacket updateBlockData, boolean nsn0) {
  196. stream.initBitAccess();
  197. int skip = 0;
  198. for (int i = 0; i < localPlayersIndexesCount; i++) {
  199. int playerIndex = localPlayersIndexes[i];
  200. if (nsn0 ? (0x1 & slotFlags[playerIndex]) != 0
  201. : (0x1 & slotFlags[playerIndex]) == 0)
  202. continue;
  203. if (skip > 0) {
  204. skip--;
  205. slotFlags[playerIndex] = (byte) (slotFlags[playerIndex] | 2);
  206. continue;
  207. }
  208. Player p = localPlayers[playerIndex];
  209. if (needsRemove(p)) {
  210. stream.writeBits(1, 1); // needs update
  211. stream.writeBits(1, 0); // no masks update needeed
  212. stream.writeBits(2, 0); // request remove
  213. regionHashes[playerIndex] = p.getLastWorldTile() == null ? p.getRegionHash() : p.getLastWorldTile().getRegionHash();
  214. int hash = p.getRegionHash();
  215. if (hash == regionHashes[playerIndex])
  216. stream.writeBits(1, 0);
  217. else {
  218. stream.writeBits(1, 1);
  219. updateRegionHash(stream, regionHashes[playerIndex], hash);
  220. regionHashes[playerIndex] = hash;
  221. }
  222. localPlayers[playerIndex] = null;
  223. } else {
  224. boolean needAppearenceUpdate = needAppearenceUpdate(
  225. p.getIndex(), p.getAppearence()
  226. .getMD5AppeareanceDataHash());
  227. boolean needUpdate = p.needMasksUpdate() || needAppearenceUpdate;
  228. if (needUpdate)
  229. appendUpdateBlock(p, updateBlockData, needAppearenceUpdate,
  230. false);
  231. if (p.hasTeleported()) {
  232. stream.writeBits(1, 1); // needs update
  233. stream.writeBits(1, needUpdate ? 1 : 0);
  234. stream.writeBits(2, 3);
  235. int xOffset = p.getX() - p.getLastWorldTile().getX();
  236. int yOffset = p.getY() - p.getLastWorldTile().getY();
  237. int planeOffset = p.getZ()
  238. - p.getLastWorldTile().getZ();
  239. if (Math.abs(p.getX() - p.getLastWorldTile().getX()) <= 14 //14 for safe
  240. && Math.abs(p.getY() - p.getLastWorldTile().getY()) <= 14) { //14 for safe
  241. stream.writeBits(1, 0);
  242. if (xOffset < 0) // viewport used to be 15 now 16
  243. xOffset += 32;
  244. if (yOffset < 0)
  245. yOffset += 32;
  246. stream.writeBits(12, yOffset + (xOffset << 5)
  247. + (planeOffset << 10));
  248. } else {
  249. stream.writeBits(1, 1);
  250. stream.writeBits(30, (yOffset & 0x3fff)
  251. + ((xOffset & 0x3fff) << 14)
  252. + ((planeOffset & 0x3) << 28));
  253. }
  254. } else if (p.getNextWalkDirection() != -1) {
  255. int dx = Misc.DIRECTION_DELTA_X[p.getNextWalkDirection()];
  256. int dy = Misc.DIRECTION_DELTA_Y[p.getNextWalkDirection()];
  257. boolean running;
  258. int opcode;
  259. if (p.getNextRunDirection() != -1) {
  260. dx += Misc.DIRECTION_DELTA_X[p.getNextRunDirection()];
  261. dy += Misc.DIRECTION_DELTA_Y[p.getNextRunDirection()];
  262. opcode = Misc.getPlayerRunningDirection(dx, dy);
  263. if (opcode == -1) {
  264. running = false;
  265. opcode = Misc.getPlayerWalkingDirection(dx, dy);
  266. } else
  267. running = true;
  268. } else {
  269. running = false;
  270. opcode = Misc.getPlayerWalkingDirection(dx, dy);
  271. }
  272. stream.writeBits(1, 1);
  273. if((dx == 0 && dy == 0)) {
  274. stream.writeBits(1, 1); //quick fix
  275. stream.writeBits(2, 0);
  276. if (!needUpdate) //hasnt been sent yet
  277. appendUpdateBlock(p, updateBlockData, needAppearenceUpdate,false);
  278. }else {
  279. stream.writeBits(1, needUpdate ? 1 : 0);
  280. stream.writeBits(2, running ? 2 : 1);
  281. stream.writeBits(running ? 4 : 3, opcode);
  282. }
  283. } else if (needUpdate) {
  284. stream.writeBits(1, 1); // needs update
  285. stream.writeBits(1, 1);
  286. stream.writeBits(2, 0);
  287. } else { // skip
  288. stream.writeBits(1, 0); // no update needed
  289. for (int i2 = i + 1; i2 < localPlayersIndexesCount; i2++) {
  290. int p2Index = localPlayersIndexes[i2];
  291. if (nsn0 ? (0x1 & slotFlags[p2Index]) != 0
  292. : (0x1 & slotFlags[p2Index]) == 0)
  293. continue;
  294. Player p2 = localPlayers[p2Index];
  295. if (needsRemove(p2)
  296. || p2.hasTeleported()
  297. || p2.getNextWalkDirection() != -1
  298. || (p2.needMasksUpdate() || needAppearenceUpdate(
  299. p2.getIndex(), p2.getAppearence()
  300. .getMD5AppeareanceDataHash())))
  301. break;
  302. skip++;
  303. }
  304. skipPlayers(stream, skip);
  305. slotFlags[playerIndex] = (byte) (slotFlags[playerIndex] | 2);
  306. }
  307.  
  308. }
  309. }
  310. stream.finishBitAccess();
  311. }
  312.  
  313. private void skipPlayers(OutgoingPacket stream, int amount) {
  314. stream.writeBits(2, amount == 0 ? 0 : amount > 255 ? 3
  315. : (amount > 31 ? 2 : 1));
  316. if (amount > 0)
  317. stream.writeBits(amount > 255 ? 11 : (amount > 31 ? 8 : 5), amount);
  318. }
  319.  
  320. private void appendUpdateBlock(Player p, OutgoingPacket data,
  321. boolean needAppearenceUpdate, boolean added) {
  322. int maskData = 0;
  323. if (p.getNextGraphics1() != null)
  324. maskData |= 0x4;
  325. if (added
  326. || (p.getNextFaceWorldTile() != null
  327. && p.getNextRunDirection() == -1 && p
  328. .getNextWalkDirection() == -1))
  329. maskData |= 0x40;
  330. if (p.getNextGraphics2() != null)
  331. maskData |= 0x8000;
  332. if (!p.getNextHits().isEmpty())
  333. maskData |= 0x8;
  334. if (p.getNextGraphics3() != null)
  335. maskData |= 0x400000;
  336. if (p.getNextGraphics4() != null)
  337. maskData |= 0x800000;
  338. if (p.getNextFaceEntity() != -2 || (added && p.getLastFaceEntity() != -1))
  339. maskData |= 0x1;
  340. if (needAppearenceUpdate)
  341. maskData |= 0x10;
  342. if (p.getTemporaryMoveType() != -1)
  343. maskData |= 0x800;
  344. if (p.getNextForceMovement() != null)
  345. maskData |= 0x1000;
  346. if (added || p.isUpdateMovementType())
  347. maskData |= 0x80;
  348. if (p.getNextAnimation() != null)
  349. maskData |= 0x20;
  350. if (p.getNextForceTalk() != null)
  351. maskData |= 0x100;
  352.  
  353. if (maskData >= 256)
  354. maskData |= 0x2;
  355. if (maskData >= 65536)
  356. maskData |= 0x400;
  357. data.writeByte(maskData);
  358. if (maskData >= 256)
  359. data.writeByte(maskData >> 8);
  360. if (maskData >= 65536)
  361. data.writeByte(maskData >> 16);
  362. if (p.getNextGraphics1() != null)
  363. applyGraphicsMask1(p, data);
  364. if (added
  365. || (p.getNextFaceWorldTile() != null
  366. && p.getNextRunDirection() == -1 && p
  367. .getNextWalkDirection() == -1))
  368. applyFaceDirectionMask(p, data);
  369. if (p.getNextGraphics2() != null)
  370. applyGraphicsMask2(p, data);
  371. if (!p.getNextHits().isEmpty())
  372. applyHitsMask(p, data);
  373. if (p.getNextGraphics3() != null)
  374. applyGraphicsMask3(p, data);
  375. if (p.getNextGraphics4() != null)
  376. applyGraphicsMask4(p, data);
  377. if (needAppearenceUpdate)
  378. applyAppearanceMask(p, data);
  379. if (p.getNextFaceEntity() != -2 || (added && p.getLastFaceEntity() != -1))
  380. applyFaceEntityMask(p, data);
  381. if (p.getTemporaryMoveType() != -1)
  382. applyTemporaryMoveTypeMask(p, data);
  383. if (p.getNextForceMovement() != null)
  384. applyForceMovementMask(p, data);
  385. if (added || p.isUpdateMovementType())
  386. applyMoveTypeMask(p, data);
  387. if (p.getNextAnimation() != null)
  388. applyAnimationMask(p, data);
  389. if (p.getNextForceTalk() != null)
  390. applyForceTalkMask(p, data);
  391. }
  392.  
  393. private void applyForceTalkMask(Player p, OutgoingPacket data) {
  394. data.writeString(p.getNextForceTalk().getText());
  395. }
  396.  
  397. private void applyHitsMask(Player p, OutgoingPacket data) {
  398. int count = p.getNextHits().size();
  399. data.writeByteC(count);
  400. if (count > 0) {
  401. int hp = p.getHitpoints();
  402. int maxHp = p.getMaxHitpoints();
  403. if (hp > maxHp)
  404. hp = maxHp;
  405. int hpBarPercentage = maxHp == 0 ? 0 : (hp * 255 / maxHp);
  406. for (Hit hit : p.getNextHits()) {
  407. if (hit.getDamage() < 0)
  408. hit.setDamage(0);
  409. boolean interactingWith = hit.interactingWith(player, p);
  410. if (hit.missed() && !interactingWith)
  411. data.writeSmart(32766);
  412. else {
  413. if (hit.getSoaking() != null) {
  414. data.writeSmart(32767);
  415. data.writeSmart(hit.getMark(player, p));
  416. data.writeSmart(hit.getDamage());
  417. data.writeSmart(hit.getSoaking().getMark(player, p));
  418. data.writeSmart(hit.getSoaking().getDamage());
  419. } else {
  420. data.writeSmart(hit.getMark(player, p));
  421. data.writeSmart(hit.getDamage());
  422. }
  423. }
  424. data.writeSmart(hit.getDelay());
  425. data.write128Byte(hpBarPercentage);
  426. }
  427. }
  428. }
  429.  
  430. private void applyFaceEntityMask(Player p, OutgoingPacket data) {
  431. data.writeShort128(p.getNextFaceEntity() == -2 ? p.getLastFaceEntity()
  432. : p.getNextFaceEntity());
  433. }
  434.  
  435. private void applyFaceDirectionMask(Player p, OutgoingPacket data) {
  436. data.writeShort(p.getDirection()); // also works as face tile as dir
  437. // calced on setnextfacetile
  438. }
  439.  
  440. private void applyMoveTypeMask(Player p, OutgoingPacket data) {
  441. data.write128Byte(p.getRun() ? 2 : 1);
  442. }
  443.  
  444. private void applyTemporaryMoveTypeMask(Player p, OutgoingPacket data) {
  445. data.writeByte128(p.getTemporaryMoveType());
  446. }
  447.  
  448. private void applyGraphicsMask1(Player p, OutgoingPacket data) {
  449. data.writeShort(p.getNextGraphics1().getId());
  450. data.writeIntLE(p.getNextGraphics1().getSettingsHash());
  451. data.writeByte128(p.getNextGraphics1().getSettings2Hash());
  452. }
  453.  
  454. private void applyGraphicsMask2(Player p, OutgoingPacket data) {
  455. data.writeShort128(p.getNextGraphics2().getId());
  456. data.writeIntV1(p.getNextGraphics2().getSettingsHash());
  457. data.writeByte128(p.getNextGraphics2().getSettings2Hash());
  458. }
  459.  
  460. private void applyGraphicsMask3(Player p, OutgoingPacket data) {
  461. data.writeShort128(p.getNextGraphics3().getId());
  462. data.writeInt(p.getNextGraphics3().getSettingsHash());
  463. data.writeByte128(p.getNextGraphics3().getSettings2Hash());
  464. }
  465.  
  466. private void applyGraphicsMask4(Player p, OutgoingPacket data) {
  467. data.writeShort128(p.getNextGraphics4().getId());
  468. data.writeIntV1(p.getNextGraphics4().getSettingsHash());
  469. data.writeByte128(p.getNextGraphics4().getSettings2Hash());
  470. }
  471.  
  472. private void applyAnimationMask(Player p, OutgoingPacket data) {
  473. for (int id : p.getNextAnimation().getIds())
  474. data.writeBigSmart(id);
  475. data.writeByte(p.getNextAnimation().getSpeed());
  476. }
  477.  
  478. private void applyAppearanceMask(Player p, OutgoingPacket data) {
  479. byte[] renderData = p.getAppearence().getAppeareanceData();
  480. totalRenderDataSentLength += renderData.length;
  481. cachedAppearencesHashes[p.getIndex()] = p.getAppearence()
  482. .getMD5AppeareanceDataHash();
  483. data.writeByte128(renderData.length);
  484. data.writeBytes(renderData);
  485.  
  486. }
  487.  
  488. private void applyForceMovementMask(Player p, OutgoingPacket data) {
  489. data.writeByteC(p.getNextForceMovement().getToFirstTile().getX()
  490. - p.getX());
  491. data.writeByte(p.getNextForceMovement().getToFirstTile().getY()
  492. - p.getY());
  493. data.writeByte(p.getNextForceMovement().getToSecondTile() == null ? 0
  494. : p.getNextForceMovement().getToSecondTile().getX() - p.getX());
  495. data.writeByte128(p.getNextForceMovement().getToSecondTile() == null ? 0
  496. : p.getNextForceMovement().getToSecondTile().getY() - p.getY());
  497. data.writeShort(p.getNextForceMovement().getFirstTileTicketDelay() * 30);
  498. data.writeShort(p.getNextForceMovement().getToSecondTile() == null ? 0
  499. : p.getNextForceMovement().getSecondTileTicketDelay() * 30);
  500. data.writeShort(p.getNextForceMovement().getDirection());
  501. }
  502.  
  503. public OutgoingPacket createPacketAndProcess() {
  504. OutgoingPacket stream = new OutgoingPacket();
  505. OutgoingPacket updateBlockData = new OutgoingPacket();
  506. stream.writePacketVarShort(player, 96);
  507. processLocalPlayers(stream, updateBlockData, true);
  508. processLocalPlayers(stream, updateBlockData, false);
  509. processOutsidePlayers(stream, updateBlockData, true);
  510. processOutsidePlayers(stream, updateBlockData, false);
  511. stream.writeBytes(updateBlockData.getBuffer(), 0,
  512. updateBlockData.getOffset());
  513. stream.endPacketVarShort();
  514. totalRenderDataSentLength = 0;
  515. localPlayersIndexesCount = 0;
  516. outPlayersIndexesCount = 0;
  517. for (int playerIndex = 1; playerIndex < 2048; playerIndex++) {
  518. slotFlags[playerIndex] >>= 1;
  519. Player player = localPlayers[playerIndex];
  520. if (player == null)
  521. outPlayersIndexes[outPlayersIndexesCount++] = playerIndex;
  522. else
  523. localPlayersIndexes[localPlayersIndexesCount++] = playerIndex;
  524. }
  525. return stream;
  526. }
  527.  
  528. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement