Advertisement
Guest User

Untitled

a guest
Aug 19th, 2017
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 24.87 KB | None | 0 0
  1. // Copyright © 2011 J.M. Linden
  2. // This program is free software; you can redistribute it and/or
  3. // modify it under the terms of the GNU General Public License
  4. // as published by the Free Software Foundation; either version 2
  5. // of the License, or (at your option) any later version.
  6. //
  7. // This program is distributed in the hope that it will be useful,
  8. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  10. // GNU General Public License for more details.
  11. //
  12. // You should have received a copy of the GNU General Public License
  13. // along with this program; if not, write to the Free Software
  14. // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  15.  
  16. package org.mike.gielinor.game.service.task;
  17.  
  18. import static org.mike.gielinor.game.model.World.getWorld;
  19. import static org.mike.gielinor.game.model.container.Equipment.SLOT_BOOTS;
  20. import static org.mike.gielinor.game.model.container.Equipment.SLOT_CHEST;
  21. import static org.mike.gielinor.game.model.container.Equipment.SLOT_GLOVES;
  22. import static org.mike.gielinor.game.model.container.Equipment.SLOT_HELM;
  23. import static org.mike.gielinor.game.model.container.Equipment.SLOT_SHIELD;
  24. import static org.mike.gielinor.game.model.container.Equipment.isType;
  25. import static org.mike.gielinor.game.model.update.UpdateFlags.UpdateFlag.ANIMATION;
  26. import static org.mike.gielinor.game.model.update.UpdateFlags.UpdateFlag.APPEARANCE;
  27. import static org.mike.gielinor.game.model.update.UpdateFlags.UpdateFlag.CHAT;
  28. import static org.mike.gielinor.game.model.update.UpdateFlags.UpdateFlag.FACE_COORDINATE;
  29. import static org.mike.gielinor.game.model.update.UpdateFlags.UpdateFlag.FACE_ENTITY;
  30. import static org.mike.gielinor.game.model.update.UpdateFlags.UpdateFlag.FORCED_CHAT;
  31. import static org.mike.gielinor.game.model.update.UpdateFlags.UpdateFlag.FORCED_MOVEMENT;
  32. import static org.mike.gielinor.game.model.update.UpdateFlags.UpdateFlag.GRAPHICS;
  33. import static org.mike.gielinor.game.model.update.UpdateFlags.UpdateFlag.HIT;
  34. import static org.mike.gielinor.game.model.update.UpdateFlags.UpdateFlag.HIT_2;
  35. import static org.mike.gielinor.game.model.util.Skills.HITPOINTS;
  36. import static org.mike.gielinor.game.net.logic.GamePacket.PacketType.VARIABLE_SHORT;
  37.  
  38. import java.util.Iterator;
  39. import java.util.List;
  40.  
  41. import org.mike.core.service.task.Task;
  42. import org.mike.gielinor.game.model.Entity;
  43. import org.mike.gielinor.game.model.Item;
  44. import org.mike.gielinor.game.model.Player;
  45. import org.mike.gielinor.game.model.container.Container;
  46. import org.mike.gielinor.game.model.container.Equipment.EquipmentType;
  47. import org.mike.gielinor.game.model.update.UpdateAttributes;
  48. import org.mike.gielinor.game.model.update.UpdateFlags;
  49. import org.mike.gielinor.game.model.util.Animation;
  50. import org.mike.gielinor.game.model.util.Appearance;
  51. import org.mike.gielinor.game.model.util.ChatMessage;
  52. import org.mike.gielinor.game.model.util.Damage;
  53. import org.mike.gielinor.game.model.util.Graphic;
  54. import org.mike.gielinor.game.model.util.Location;
  55. import org.mike.gielinor.game.model.util.Skills;
  56. import org.mike.gielinor.game.net.logic.GamePacket;
  57. import org.mike.gielinor.game.net.logic.dispatch.GamePacketBuilder;
  58. import org.mike.gielinor.game.net.logic.dispatch.impl.MapRegionPacket;
  59.  
  60. /**
  61.  * A {@link Task} which deals with the updating of a specific {@link Player}.
  62.  *
  63.  * @author J.M. Linden
  64.  *
  65.  */
  66. public final class PlayerUpdateTask implements Task {
  67.  
  68.     /**
  69.      * The {@link Player} to update.
  70.      */
  71.     private final Player player;
  72.  
  73.     /**
  74.      * Creates a new {@link PlayerUpdateTask} for the specified {@link Player}.
  75.      *
  76.      * @param player
  77.      *            The {@link Player} to update.
  78.      */
  79.     public PlayerUpdateTask(final Player player) {
  80.         this.player = player;
  81.     }
  82.  
  83.     @Override
  84.     public void execute() {
  85.         System.out.println("Updating player...");
  86.         // TODO player updating
  87.         /*
  88.          * If the map region changed send the new one. We do this immediately as
  89.          * the client can begin loading it before the actual packet is received.
  90.          */
  91.         if (player.isMapRegionChanging()) {
  92.             final Location loc = player.getLocation();
  93.             player.setLastKnownRegion(loc);
  94.             player.send(new MapRegionPacket(loc));
  95.         }
  96.  
  97.         /*
  98.          * The update block packet holds update blocks and is send after the
  99.          * main packet.
  100.          */
  101.         final GamePacketBuilder updateBlock = new GamePacketBuilder();
  102.  
  103.         /*
  104.          * The main packet is written in bits instead of bytes and holds
  105.          * information about the local list, players to add and remove, movement
  106.          * and which updates are required.
  107.          */
  108.         final GamePacketBuilder packet = new GamePacketBuilder(81,
  109.                 VARIABLE_SHORT);
  110.         packet.startBitAccess();
  111.  
  112.         /*
  113.          * Update this player.
  114.          */
  115.         updateThisPlayerMovement(packet);
  116.         updatePlayer(updateBlock, player, false, true);
  117.  
  118.         final List<Player> localPlayers = player.getLocalPlayers();
  119.         /*
  120.          * Write the current size of the player list.
  121.          */
  122.         packet.writeBits(8, localPlayers.size());
  123.  
  124.         /*
  125.          * Iterate through the world's player list.
  126.          */
  127.         for (Iterator<Player> it$ = localPlayers.iterator(); it$.hasNext();) {
  128.             /*
  129.              * Get the next player.
  130.              */
  131.             final Player otherPlayer = it$.next();
  132.  
  133.             /*
  134.              * If the player should still be in our list.
  135.              */
  136.             if (getWorld().getPlayers().contains(otherPlayer)
  137.                     && !otherPlayer.isTeleporting()
  138.                     && otherPlayer.getLocation().isWithinDistance(
  139.                             player.getLocation())) {
  140.                 /*
  141.                  * Update the movement.
  142.                  */
  143.                 updatePlayerMovement(packet, otherPlayer);
  144.  
  145.                 /*
  146.                  * Check if an update is required, and if so, send it.
  147.                  */
  148.                 if (otherPlayer.getUpdateAttributes().getFlags()
  149.                         .isUpdateRequired()) {
  150.                     updatePlayer(updateBlock, otherPlayer, false, false);
  151.                 }
  152.             } else {
  153.                 /*
  154.                  * Otherwise, remove the player from the list.
  155.                  */
  156.                 it$.remove();
  157.  
  158.                 /*
  159.                  * Tell the client to remove the player from the list.
  160.                  */
  161.                 packet.writeBits(1, 1);
  162.                 packet.writeBits(2, 3);
  163.             }
  164.         }
  165.  
  166.         /*
  167.          * Loop through every player in the same region.
  168.          */
  169.         for (Player otherPlayer : getWorld().getRegionManager()
  170.                 .getLocalPlayers(player)) {
  171.             /*
  172.              * Check if there is room left in the local list.
  173.              */
  174.             if (localPlayers.size() >= 255) {
  175.                 /*
  176.                  * There is no more room left in the local list. We cannot add
  177.                  * more players, so we just ignore the extra ones. They will be
  178.                  * added as other players get removed.
  179.                  */
  180.                 break;
  181.             }
  182.  
  183.             /*
  184.              * If they should not be added ignore them.
  185.              */
  186.             if (otherPlayer == player || localPlayers.contains(otherPlayer)) {
  187.                 continue;
  188.             }
  189.  
  190.             /*
  191.              * Add the player to the local list if it is within distance.
  192.              */
  193.             localPlayers.add(otherPlayer);
  194.  
  195.             /*
  196.              * Add the player in the packet.
  197.              */
  198.             addNewPlayer(packet, otherPlayer);
  199.  
  200.             /*
  201.              * Update the player, forcing the appearance flag.
  202.              */
  203.             updatePlayer(updateBlock, otherPlayer, true, false);
  204.         }
  205.  
  206.         /*
  207.          * Check if the update block is not empty.
  208.          */
  209.         if (!updateBlock.isEmpty()) {
  210.             /*
  211.              * Write a magic id indicating an update block follows.
  212.              */
  213.             packet.writeBits(11, 2047);
  214.             packet.finishBitAccess();
  215.  
  216.             /*
  217.              * Add the update block at the end of this packet.
  218.              */
  219.             packet.writeBytes(updateBlock.toPacket().getPayload());
  220.         } else {
  221.             /*
  222.              * Terminate the packet normally.
  223.              */
  224.             packet.finishBitAccess();
  225.         }
  226.  
  227.         /*
  228.          * Write the packet.
  229.          */
  230.         player.write(packet.toPacket());
  231.     }
  232.  
  233.     /**
  234.      * Updates the movement of a non-this {@link Player}.
  235.      *
  236.      * @param packet
  237.      *            The {@link GamePacketBuilder} to append the update to.
  238.      * @param otherPlayer
  239.      *            The {@link Player} to get the update data from.
  240.      */
  241.     private void updatePlayerMovement(final GamePacketBuilder packet,
  242.             final Player otherPlayer) {
  243.         final UpdateAttributes otherAttributes = otherPlayer
  244.                 .getUpdateAttributes();
  245.         /*
  246.          * Check which type of movement took place.
  247.          */
  248.         if (otherAttributes.getPrimarySprite() == -1) {
  249.             /*
  250.              * If no movement did, check if an update is required.
  251.              */
  252.             if (otherAttributes.getFlags().isUpdateRequired()) {
  253.                 /*
  254.                  * Signify that an update happened.
  255.                  */
  256.                 packet.writeBits(1, 1);
  257.  
  258.                 /*
  259.                  * Signify that there was no movement.
  260.                  */
  261.                 packet.writeBits(2, 0);
  262.             } else {
  263.                 /*
  264.                  * Signify that nothing changed.
  265.                  */
  266.                 packet.writeBits(1, 0);
  267.             }
  268.         } else if (otherAttributes.getSecondarySprite() == -1) {
  269.             /*
  270.              * The player moved but didn't run. Signify that an update is
  271.              * required.
  272.              */
  273.             packet.writeBits(1, 1);
  274.  
  275.             /*
  276.              * Signify we moved one tile.
  277.              */
  278.             packet.writeBits(2, 1);
  279.  
  280.             /*
  281.              * Write the primary sprite (i.e. walk direction).
  282.              */
  283.             packet.writeBits(3, otherAttributes.getPrimarySprite());
  284.  
  285.             /*
  286.              * Write a flag indicating if a block update happened.
  287.              */
  288.             packet.writeBits(1,
  289.                     otherAttributes.getFlags().isUpdateRequired() ? 1 : 0);
  290.         } else {
  291.             /*
  292.              * The player ran. Signify that an update happened.
  293.              */
  294.             packet.writeBits(1, 1);
  295.  
  296.             /*
  297.              * Signify that we moved two tiles.
  298.              */
  299.             packet.writeBits(2, 2);
  300.  
  301.             /*
  302.              * Write the primary sprite (i.e. walk direction).
  303.              */
  304.             packet.writeBits(3, otherAttributes.getPrimarySprite());
  305.  
  306.             /*
  307.              * Write the secondary sprite (i.e. run direction).
  308.              */
  309.             packet.writeBits(3, otherAttributes.getSecondarySprite());
  310.  
  311.             /*
  312.              * Write a flag indicating if a block update happened.
  313.              */
  314.             packet.writeBits(1,
  315.                     otherAttributes.getFlags().isUpdateRequired() ? 1 : 0);
  316.         }
  317.  
  318.     }
  319.  
  320.     /**
  321.      * Updates the movement of the {@link #player}.
  322.      *
  323.      * @param packet
  324.      *            The {@link GamePacketBuilder} to write the update data to.
  325.      */
  326.     private void updateThisPlayerMovement(final GamePacketBuilder packet) {
  327.         /*
  328.          * Check if the player is teleporting or their map region is changing.
  329.          */
  330.         if (player.isTeleporting() || player.isMapRegionChanging()) {
  331.             /*
  332.              * They are, so an update is required.
  333.              */
  334.             packet.writeBits(1, 1);
  335.  
  336.             /*
  337.              * This value indicates the player teleported.
  338.              */
  339.             packet.writeBits(2, 3);
  340.  
  341.             final Location loc = player.getLocation();
  342.             /*
  343.              * This is the new player height.
  344.              */
  345.             packet.writeBits(2, loc.getZ());
  346.  
  347.             /*
  348.              * This indicates that the client should discard the walking queue.
  349.              */
  350.             packet.writeBits(1, player.isTeleporting() ? 1 : 0);
  351.  
  352.             /*
  353.              * This flag indicates if an update block is appended.
  354.              */
  355.             packet.writeBits(1, player.getUpdateAttributes().getFlags()
  356.                     .isUpdateRequired() ? 1 : 0);
  357.  
  358.             /*
  359.              * These are the positions.
  360.              */
  361.             final Location lkr = player.getLastKnownRegion();
  362.             packet.writeBits(7, loc.getLocalY(lkr));
  363.             packet.writeBits(7, loc.getLocalX(lkr));
  364.         } else {
  365.             final UpdateAttributes attributes = player.getUpdateAttributes();
  366.             /*
  367.              * Otherwise, check if the player moved.
  368.              */
  369.             if (attributes.getPrimarySprite() == -1) {
  370.                 /*
  371.                  * The player didn't move. Check if an update is required.
  372.                  */
  373.                 if (attributes.getFlags().isUpdateRequired()) {
  374.                     /*
  375.                      * Signifies an update is required.
  376.                      */
  377.                     packet.writeBits(1, 1);
  378.  
  379.                     /*
  380.                      * But signifies that we didn't move.
  381.                      */
  382.                     packet.writeBits(2, 0);
  383.                 } else {
  384.                     /*
  385.                      * Signifies that nothing changed.
  386.                      */
  387.                     packet.writeBits(1, 0);
  388.                 }
  389.             } else {
  390.                 /*
  391.                  * Check if the player was running.
  392.                  */
  393.                 if (attributes.getSecondarySprite() == -1) {
  394.                     /*
  395.                      * The player walked, an update is required.
  396.                      */
  397.                     packet.writeBits(1, 1);
  398.  
  399.                     /*
  400.                      * This indicates the player only walked.
  401.                      */
  402.                     packet.writeBits(2, 1);
  403.  
  404.                     /*
  405.                      * This is the player's walking direction.
  406.                      */
  407.                     packet.writeBits(3, attributes.getPrimarySprite());
  408.  
  409.                     /*
  410.                      * This flag indicates an update block is appended.
  411.                      */
  412.                     packet.writeBits(1, attributes.getFlags()
  413.                             .isUpdateRequired() ? 1 : 0);
  414.                 } else {
  415.                     /*
  416.                      * The player ran, so an update is required.
  417.                      */
  418.                     packet.writeBits(1, 1);
  419.  
  420.                     /*
  421.                      * This indicates the player ran.
  422.                      */
  423.                     packet.writeBits(2, 2);
  424.  
  425.                     /*
  426.                      * This is the walking direction.
  427.                      */
  428.                     packet.writeBits(3, attributes.getPrimarySprite());
  429.  
  430.                     /*
  431.                      * And this is the running direction.
  432.                      */
  433.                     packet.writeBits(3, attributes.getSecondarySprite());
  434.  
  435.                     /*
  436.                      * And this flag indicates an update block is appended.
  437.                      */
  438.                     packet.writeBits(1, attributes.getFlags()
  439.                             .isUpdateRequired() ? 1 : 0);
  440.                 }
  441.             }
  442.         }
  443.     }
  444.  
  445.     /**
  446.      * Appends the update of a newly added {@link Player}.
  447.      *
  448.      * @param packet
  449.      *            The {@link GamePacketBuilder} to write the update to.
  450.      * @param otherPlayer
  451.      *            The {@link Player} to add.
  452.      */
  453.     private void addNewPlayer(final GamePacketBuilder packet,
  454.             final Player otherPlayer) {
  455.         /*
  456.          * Write the player index.
  457.          */
  458.         packet.writeBits(11, otherPlayer.getIndex());
  459.  
  460.         /*
  461.          * Write two flags here: the first indicates an update is required (this
  462.          * is always true as we add the appearance after adding a player) and
  463.          * the second to indicate we should discard client-side walk queues.
  464.          */
  465.         packet.writeBits(1, 1);
  466.         packet.writeBits(1, 1);
  467.  
  468.         /*
  469.          * Fetch the x and y coordinates.
  470.          */
  471.         final Location loc = player.getLocation(), otherLoc = otherPlayer
  472.                 .getLocation();
  473.  
  474.         /*
  475.          * Write the x and y offsets.
  476.          */
  477.         packet.writeBits(5, otherLoc.getY() - loc.getY());
  478.         packet.writeBits(5, otherLoc.getX() - loc.getX());
  479.     }
  480.  
  481.     /**
  482.      * Writes an update of the specified {@link Player} into the specified
  483.      * {@link GamePacketBuilder}.
  484.      *
  485.      * @param packet
  486.      *            The {@link GamePacketBuilder} to write the update to.
  487.      * @param otherPlayer
  488.      *            The {@link Player} to obtain the update data from.
  489.      * @param forceAppearance
  490.      *            The force appearance flag.
  491.      * @param noChat
  492.      *            Indicates chat should not be relayed to this player.
  493.      */
  494.     private void updatePlayer(final GamePacketBuilder packet,
  495.             final Player otherPlayer, final boolean forceAppearance,
  496.             final boolean noChat) {
  497.         final UpdateAttributes otherAttributes = otherPlayer
  498.                 .getUpdateAttributes();
  499.         /*
  500.          * If no update is required and we don't have to force an appearance
  501.          * update, don't write anything.
  502.          */
  503.         if (!otherAttributes.getFlags().isUpdateRequired() && !forceAppearance) {
  504.             return;
  505.         }
  506.  
  507.         /*
  508.          * We can used the cached update block!
  509.          */
  510.         synchronized (otherPlayer) {
  511.             if (otherPlayer.hasCachedUpdateBlock() && otherPlayer != player
  512.                     && !forceAppearance && !noChat) {
  513.                 packet.writeBytes(otherPlayer.getCachedUpdateBlock()
  514.                         .getPayload());
  515.                 return;
  516.             }
  517.  
  518.             /*
  519.              * We have to construct and cache our own block.
  520.              */
  521.             final GamePacketBuilder block = new GamePacketBuilder();
  522.  
  523.             /*
  524.              * Calculate the bitmask.
  525.              */
  526.             int mask = 0;
  527.             final UpdateFlags flags = otherAttributes.getFlags();
  528.             final boolean forcedMovement = flags.get(FORCED_MOVEMENT);
  529.             if (forcedMovement) {
  530.                 // TODO forced movement (mask 0x400)
  531.             }
  532.             final boolean graphics = flags.get(GRAPHICS);
  533.             if (graphics) {
  534.                 mask |= 0x100;
  535.             }
  536.             final boolean animation = flags.get(ANIMATION);
  537.             if (animation) {
  538.                 mask |= 0x8;
  539.             }
  540.             final boolean forcedChat = flags.get(FORCED_CHAT);
  541.             if (forcedChat) {
  542.                 // TODO forced chat (mask 0x4)
  543.             }
  544.             final boolean chat = flags.get(CHAT);
  545.             if (chat && !noChat) {
  546.                 mask |= 0x80;
  547.             }
  548.             final boolean faceEntity = flags.get(FACE_ENTITY);
  549.             if (faceEntity) {
  550.                 mask |= 0x1;
  551.             }
  552.             final boolean appearance = flags.get(APPEARANCE);
  553.             if (appearance) {
  554.                 mask |= 0x10;
  555.             }
  556.             final boolean faceCoordinate = flags.get(FACE_COORDINATE);
  557.             if (faceCoordinate) {
  558.                 mask |= 0x2;
  559.             }
  560.             final boolean hit = flags.get(HIT);
  561.             if (hit) {
  562.                 mask |= 0x20;
  563.             }
  564.             final boolean hit2 = flags.get(HIT_2);
  565.             if (hit2) {
  566.                 mask |= 0x200;
  567.             }
  568.  
  569.             /*
  570.              * Check if the bitmask would overflow a byte.
  571.              */
  572.             if (mask >= 0x100) {
  573.                 /*
  574.                  * Write it as a short and indicate we have done so.
  575.                  */
  576.                 mask |= 0x40;
  577.                 block.writeByte(mask & 0xFF);
  578.                 block.writeByte(mask >> 8);
  579.             } else {
  580.                 /*
  581.                  * Write it as a byte.
  582.                  */
  583.                 block.writeByte(mask);
  584.             }
  585.  
  586.             /*
  587.              * Append the appropriate updates.
  588.              */
  589.             if (forcedMovement) {
  590.  
  591.             }
  592.             if (graphics) {
  593.                 appendGraphicsUpdate(block, otherPlayer);
  594.             }
  595.             if (animation) {
  596.                 appendAnimationUpdate(block, otherPlayer);
  597.             }
  598.             if (forcedChat) {
  599.  
  600.             }
  601.             if (chat && !noChat) {
  602.                 appendChatUpdate(block, otherPlayer);
  603.             }
  604.             if (faceEntity) {
  605.                 final Entity entity = otherPlayer.getInteractingEntity();
  606.                 block.writeLittleEndianShort(entity == null ? -1 : entity
  607.                         .getClientIndex());
  608.             }
  609.             if (appearance) {
  610.                 appendPlayerAppearanceUpdate(block, otherPlayer);
  611.             }
  612.             if (faceCoordinate) {
  613.                 appendPlayerFacingCoordinateUpdate(block, otherPlayer);
  614.             }
  615.             if (hit) {
  616.                 appendPlayerHitUpdate(block, otherPlayer);
  617.             }
  618.             if (hit2) {
  619.                 appendPlayerHit2Update(block, otherPlayer);
  620.             }
  621.  
  622.             /*
  623.              * Convert the block builder to a packet.
  624.              */
  625.             final GamePacket blockPacket = block.toPacket();
  626.  
  627.             /*
  628.              * Now it is over, cache the block if we can.
  629.              */
  630.             if (otherPlayer != player && !forceAppearance && !noChat) {
  631.                 otherPlayer.setCachedUpdateBlock(blockPacket);
  632.             }
  633.  
  634.             /*
  635.              * And finally append the block at the end.
  636.              */
  637.             packet.writeBytes(blockPacket.getPayload());
  638.         }
  639.     }
  640.  
  641.     /**
  642.      * Appends an update for a specific {@link Player}'s current {@link Graphic}
  643.      * appearance.
  644.      *
  645.      * @param block
  646.      *            The {@link GamePacketBuilder block builder} to append the
  647.      *            update to.
  648.      * @param otherPlayer
  649.      *            The {@link Player} that is playing the {@link Graphic}.
  650.      */
  651.     private void appendGraphicsUpdate(final GamePacketBuilder block,
  652.             final Player otherPlayer) {
  653.         final Graphic g = otherPlayer.getCurrentGraphic();
  654.         block.writeLittleEndianShort(g.getId());
  655.         block.writeInt((g.getHeight() << 16) | g.getDelay());
  656.     }
  657.  
  658.     /**
  659.      * Appends an update for a specific {@link Player}'s current
  660.      * {@link Animation} appearance.
  661.      *
  662.      * @param block
  663.      *            The {@link GamePacketBuilder block builder} to append the
  664.      *            update to.
  665.      * @param otherPlayer
  666.      *            The {@link Player} that is performing the {@link Animation}.
  667.      */
  668.     private void appendAnimationUpdate(final GamePacketBuilder block,
  669.             final Player otherPlayer) {
  670.         final Animation a = otherPlayer.getCurrentAnimation();
  671.         block.writeLittleEndianShort(a.getId());
  672.         block.writeByteNegated(a.getDelay());
  673.     }
  674.  
  675.     /**
  676.      * Appends an update for a specific {@link Player}'s current
  677.      * {@link ChatMessage}.
  678.      *
  679.      * @param block
  680.      *            The {@link GamePacketBuilder block builder} to append the
  681.      *            update to.
  682.      * @param otherPlayer
  683.      *            The {@link Player} that has said the {@link ChatMessage}.
  684.      */
  685.     private void appendChatUpdate(final GamePacketBuilder block,
  686.             final Player otherPlayer) {
  687.         final ChatMessage cm = otherPlayer.getCurrentChatMessage();
  688.         final byte[] bytes = cm.getText();
  689.  
  690.         block.writeLittleEndianShort(((cm.getColor() & 0xFF) << 8)
  691.                 | (cm.getEffects() & 0xFF));
  692.         block.writeByte(otherPlayer.getRights().toInteger());
  693.  
  694.         final int length = bytes.length;
  695.         block.writeByteNegated(length);
  696.         for (int ptr = length - 1; ptr >= 0; ptr--) {
  697.             block.writeByte(bytes[ptr]);
  698.         }
  699.     }
  700.  
  701.     /**
  702.      * Appends an update for a specific {@link Player}'s general appearance.
  703.      *
  704.      * @param block
  705.      *            The {@link GamePacketBuilder block builder} to append the
  706.      *            update to.
  707.      * @param otherPlayer
  708.      *            The {@link Player} of which the appearance should be updated.
  709.      */
  710.     private void appendPlayerAppearanceUpdate(final GamePacketBuilder block,
  711.             final Player otherPlayer) {
  712.         final Appearance app = otherPlayer.getAppearance();
  713.         final Container eq = otherPlayer.getEquipment();
  714.  
  715.         final GamePacketBuilder playerProps = new GamePacketBuilder();
  716.         playerProps.writeByte(app.getGender()); // Gender
  717.         playerProps.writeByte(0); // Skull icon
  718.  
  719.         for (int i = 0; i < 4; i++) {
  720.             if (eq.isSlotUsed(i)) {
  721.                 playerProps.writeShort(0x200 + eq.get(i).getId());
  722.             } else {
  723.                 playerProps.writeByte(0);
  724.             }
  725.         }
  726.         playerProps.writeShort(eq.isSlotUsed(SLOT_CHEST) ? 0x200 + eq.get(
  727.                 SLOT_CHEST).getId() : 0x100 + app.getChest());
  728.  
  729.         if (eq.isSlotUsed(SLOT_SHIELD)) {
  730.             playerProps.writeShort(0x200 + eq.get(SLOT_SHIELD).getId());
  731.         } else {
  732.             playerProps.writeByte(0);
  733.         }
  734.  
  735.         final Item chest = eq.get(SLOT_CHEST);
  736.         if (chest != null && isType(EquipmentType.PLATEBODY, chest)) {
  737.             playerProps.writeShort(0x200 + chest.getId());
  738.         } else {
  739.             playerProps.writeShort(0x100 + app.getArms());
  740.         }
  741.  
  742.         final Item helm = eq.get(SLOT_HELM);
  743.         if (helm != null) {
  744.             if (!isType(EquipmentType.FULL_HELM, helm)
  745.                     && !isType(EquipmentType.FULL_MASK, helm)) {
  746.                 playerProps.writeShort(0x100 + app.getHead());
  747.             } else {
  748.                 playerProps.writeByte(0);
  749.             }
  750.         } else {
  751.             playerProps.writeShort(0x100 + app.getHead());
  752.         }
  753.  
  754.         playerProps.writeShort(eq.isSlotUsed(SLOT_GLOVES) ? 0x200 + eq.get(
  755.                 SLOT_GLOVES).getId() : 0x100 + app.getHands());
  756.         playerProps.writeShort(eq.isSlotUsed(SLOT_BOOTS) ? 0x200 + eq.get(
  757.                 SLOT_BOOTS).getId() : 0x100 + app.getFeet());
  758.  
  759.         boolean fullHelm = false, hat = false;
  760.         if (helm != null) {
  761.             hat = isType(EquipmentType.HAT, helm);
  762.             fullHelm = !isType(EquipmentType.FULL_HELM, helm);
  763.         }
  764.         if ((!hat && fullHelm) || app.getGender() == 1) {
  765.             playerProps.writeByte(0);
  766.         } else {
  767.             playerProps.writeShort(0x100 + app.getBeard());
  768.         }
  769.  
  770.         playerProps.writeByte(app.getHairColour())
  771.                 .writeByte(app.getTorsoColour()).writeByte(app.getLegColour())
  772.                 .writeByte(app.getFeetColour()).writeByte(app.getSkinColour());
  773.  
  774.         playerProps.writeShort(0x328); // stand
  775.         playerProps.writeShort(0x337); // stand turn
  776.         playerProps.writeShort(0x333); // walk
  777.         playerProps.writeShort(0x334); // turn 180°
  778.         playerProps.writeShort(0x335); // turn 90° cw
  779.         playerProps.writeShort(0x336); // turn 90° ccw
  780.         playerProps.writeShort(0x338); // run
  781.  
  782.         playerProps.writeLong(otherPlayer.getNameAsLong());
  783.         playerProps.writeByte(otherPlayer.getSkills().getCombatLevel());
  784.         playerProps.writeShort(0); // total level
  785.  
  786.         final GamePacket propsPacket = playerProps.toPacket();
  787.         block.writeByteNegated(propsPacket.getLength());
  788.         block.writeBytes(propsPacket.getPayload());
  789.     }
  790.  
  791.     /**
  792.      * Appends an update of the specified {@link Player}'s facing coordinate, to
  793.      * the specified {@link GamePacketBuilder block builder}.
  794.      *
  795.      * @param block
  796.      *            The {@link GamePacketBuilder block builder} to append the
  797.      *            update to.
  798.      * @param otherPlayer
  799.      *            The {@link Player} of which the facing coordinate should be
  800.      *            updated.
  801.      */
  802.     private void appendPlayerFacingCoordinateUpdate(
  803.             final GamePacketBuilder block, final Player otherPlayer) {
  804.         final Location loc = otherPlayer.getFaceLocation();
  805.         if (loc == null) {
  806.             block.writeLittleEndianShortAdded(0);
  807.             block.writeLittleEndianShort(0);
  808.         } else {
  809.             block.writeLittleEndianShortAdded(loc.getX() * 2 + 1);
  810.             block.writeLittleEndianShort(loc.getY() * 2 + 1);
  811.         }
  812.     }
  813.  
  814.     /**
  815.      * Appends a first-hit update dealt to the specified {@link Player}, to the
  816.      * specified {@link GamePacketBuilder block builder}.
  817.      *
  818.      * @param block
  819.      *            The {@link GamePacketBuilder block builder} to append the
  820.      *            update to.
  821.      * @param otherPlayer
  822.      *            The {@link Player} that took the {@link Damage}.
  823.      */
  824.     private void appendPlayerHitUpdate(final GamePacketBuilder block,
  825.             final Player otherPlayer) {
  826.         final Damage dmg = otherPlayer.getDamage();
  827.         block.writeByte(dmg.getHitDamage1()).writeByteAdded(dmg.getHitType1());
  828.         final Skills s = otherPlayer.getSkills();
  829.         block.writeByteNegated(s.getLevel(HITPOINTS)).writeByte(
  830.                 s.getLevelForExperience(HITPOINTS));
  831.     }
  832.  
  833.     /**
  834.      * Appends a second-hit update dealt to the specified {@link Player}, to the
  835.      * specified {@link GamePacketBuilder block builder}.
  836.      *
  837.      * @param block
  838.      *            The {@link GamePacketBuilder block builder} to append the
  839.      *            update to.
  840.      * @param otherPlayer
  841.      *            The {@link Player} that took the {@link Damage}.
  842.      */
  843.     private void appendPlayerHit2Update(final GamePacketBuilder block,
  844.             final Player otherPlayer) {
  845.         final Damage dmg = otherPlayer.getDamage();
  846.         block.writeByte(dmg.getHitDamage2()).writeByteSubtracted(
  847.                 dmg.getHitDamage2());
  848.         final Skills s = otherPlayer.getSkills();
  849.         block.writeByte(s.getLevel(HITPOINTS)).writeByteNegated(
  850.                 s.getLevelForExperience(HITPOINTS));
  851.     }
  852.  
  853. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement